record notify modal

This commit is contained in:
Ramón Souza 2022-03-11 20:26:26 +00:00
parent cc54f167f7
commit 35ae2a9e77
12 changed files with 144 additions and 212 deletions

View File

@ -56,6 +56,7 @@ export default function addMeeting(meeting) {
learningDashboardEnabled: Boolean, learningDashboardEnabled: Boolean,
name: String, name: String,
disabledFeatures: Array, disabledFeatures: Array,
remindRecordingIsOn: Boolean,
}, },
usersProp: { usersProp: {
webcamsOnlyForModerator: Boolean, webcamsOnlyForModerator: Boolean,

View File

@ -45,7 +45,6 @@ import Settings from '/imports/ui/services/settings';
import LayoutService from '/imports/ui/components/layout/service'; import LayoutService from '/imports/ui/components/layout/service';
import { registerTitleView } from '/imports/utils/dom-utils'; import { registerTitleView } from '/imports/utils/dom-utils';
import GlobalStyles from '/imports/ui/stylesheets/styled-components/globalStyles'; import GlobalStyles from '/imports/ui/stylesheets/styled-components/globalStyles';
import ModalConsentContainer from '../modal-consent/container';
const MOBILE_MEDIA = 'only screen and (max-width: 40em)'; const MOBILE_MEDIA = 'only screen and (max-width: 40em)';
const APP_CONFIG = Meteor.settings.public.app; const APP_CONFIG = Meteor.settings.public.app;
@ -467,7 +466,6 @@ class App extends Component {
height: '100%', height: '100%',
}} }}
> >
<ModalConsentContainer/>
{this.renderActivityCheck()} {this.renderActivityCheck()}
{this.renderUserInformation()} {this.renderUserInformation()}
<BannerBarContainer /> <BannerBarContainer />

View File

@ -1,76 +0,0 @@
import React from 'react';
import { defineMessages, injectIntl } from 'react-intl';
import style from './style.scss';
import { makeCall } from '/imports/ui/services/api';
import getValueFromKeyObj from './utils/getValueFromKeyObj';
const intlMessages = defineMessages({
title: {
id: 'app.consent.title',
description: 'Title Modal Con sent',
},
desc: {
id: 'app.consent.desc',
description: 'Question for accept or not meeting be recorded',
},
buttonyes: {
id: 'app.consent.buttonyes',
description: 'Button accept',
},
buttonreject: {
id: 'app.consent.buttonreject',
description: 'Button accept',
},
});
const ModalConsent = ({ recMeetingsCollection, intl, meetingsCollection }) => {
const [continueModal, setContinueModal] = React.useState(false);
const allowRecord = getValueFromKeyObj(
'record',
recMeetingsCollection[0],
);
const { isBreakout } = getValueFromKeyObj(
'meetingProp',
meetingsCollection[0],
);
if (
!allowRecord// if meeting is not able to record
|| !Meteor.settings.public.app.requireAdditionalRecordingConsentOnJoin
|| continueModal // if clicked in continue
|| isBreakout // if is breackout (because user already accept before)
) return null;
const LOGOUT_CODE = '680';
function skipButtonHandle() {
makeCall('userLeftMeeting');
Session.set('codeError', LOGOUT_CODE);
setContinueModal(true);
}
return (
<div>
<div className={style.overlay}>
<div className={style.modal}>
<h1>{intl.formatMessage(intlMessages.title)}</h1>
<p>{intl.formatMessage(intlMessages.desc)}</p>
<div className={style.divButtons}>
<button type="button" onClick={() => setContinueModal(true)} className={style.continue}>
{intl.formatMessage(intlMessages.buttonyes)}
</button>
<button type="button" onClick={skipButtonHandle} className={style.skip}>
{intl.formatMessage(intlMessages.buttonreject)}
</button>
</div>
</div>
</div>
</div>
);
};
export default injectIntl(ModalConsent);

View File

@ -1,13 +0,0 @@
import { withTracker } from 'meteor/react-meteor-data';
import ModalConsent from './component';
import { RecordMeetings } from '/imports/api/meetings';
import Meetings from '../../../api/meetings/index';
export default withTracker(() => {
const recMeetingsCollection = RecordMeetings.find().fetch();
const meetingsCollection = Meetings.find().fetch();
return {
recMeetingsCollection,
meetingsCollection,
};
})(ModalConsent);

View File

@ -1,108 +0,0 @@
.overlay{
width: 100%;
height: 100vh;
background-color: rgba(0, 0, 0, 0.322);
z-index: 10000;
overflow: visible;
position: fixed;
display: flex;
justify-content: center;
align-items: center;
}
@keyframes up_modal {
from {
opacity: 0;
transform: translateY(-10px);
}
to {
opacity: 1;
transform: translateY(0px);
}
}
.modal {
padding: 0.625em 3.125em 0.625em 3.125em;
width: 60%;
height: 18.75em;
background-color: rgb(250, 252, 255);
background-color: var( --color-off-white);
border-radius: 0.3125em;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
animation: up_modal 0.3s ease
}
.modal p{
padding: 0em;
margin: 0em;
margin-bottom: 1.25em;
font-size: 1.25em;
}
.continue{
padding: 0.625em 1.875em 0.625em 1.875em;
background-color: var(--color-primary);
border: none;
border-radius: 0.3125em;
color: white;
font-size: 1.1em;
margin-right: 0.7em;
}
.skip{
padding: 0.625em 1.875em 0.625em 1.875em;
background-color: var(--color-blue-lightest);
border: none;
border-radius: 0.3125em;
color: var(--color-gray);
font-size: 1.1em;
}
.divButtons{
width: 100%;
display: flex;
flex-wrap: wrap;
align-items: center;
justify-content: center;
}
.divButtons button{
cursor: pointer;
}
.divButtons button:hover{
transform: scale3d(1.05, 1.05, 1);
}
@media (max-width: 940px)
{
.modal h1
{
font-size: 1.5em;
}
.divButtons{
flex-direction: column;
justify-content: center;
align-items: center;
}
.divButtons button{
width: 100%;
margin: 0.3125em;
padding: 0.625em 1.875em 0.625em 1.875em;
}
.modal{
width: 70%;
height: 90vh;
}
.continue{
margin-right: 03em;
}
}

View File

@ -1,11 +0,0 @@
export default function getValueFromKeyObj(chaveObj, obj){
let existKey = Object.keys(obj).filter(function(key){
return key === chaveObj
})
if(existKey){
return obj[existKey]
} else {
return null
}
}

View File

@ -1,6 +1,6 @@
import React, { Component } from 'react'; import React, { Component } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { withModalMounter } from '/imports/ui/components/common/modal/service'; import { withModalMounter, getModal } from '/imports/ui/components/common/modal/service';
import withShortcutHelper from '/imports/ui/components/shortcut-help/service'; import withShortcutHelper from '/imports/ui/components/shortcut-help/service';
import { defineMessages, injectIntl } from 'react-intl'; import { defineMessages, injectIntl } from 'react-intl';
import Styled from './styles'; import Styled from './styles';
@ -235,6 +235,7 @@ class NavBar extends Component {
</Styled.PresentationTitle> </Styled.PresentationTitle>
<RecordingIndicator <RecordingIndicator
mountModal={mountModal} mountModal={mountModal}
getModal={getModal}
amIModerator={amIModerator} amIModerator={amIModerator}
/> />
</Styled.Center> </Styled.Center>

View File

@ -5,6 +5,7 @@ import Tooltip from '/imports/ui/components/common/tooltip/component';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { defineMessages, injectIntl } from 'react-intl'; import { defineMessages, injectIntl } from 'react-intl';
import Styled from './styles'; import Styled from './styles';
import RecordingNotifyContainer from './notify/container';
const intlMessages = defineMessages({ const intlMessages = defineMessages({
notificationRecordingStart: { notificationRecordingStart: {
@ -67,19 +68,47 @@ class RecordingIndicator extends PureComponent {
super(props); super(props);
this.state = { this.state = {
time: (props.time ? props.time : 0), time: (props.time ? props.time : 0),
shouldNotify: false,
}; };
this.incrementTime = this.incrementTime.bind(this); this.incrementTime = this.incrementTime.bind(this);
this.toggleShouldNotify = this.toggleShouldNotify.bind(this);
} }
componentDidUpdate() { toggleShouldNotify() {
const { shouldNotify } = this.state;
this.setState({shouldNotify: !shouldNotify});
}
componentDidMount() {
const { recording } = this.props; const { recording } = this.props;
if (recording) {
this.toggleShouldNotify();
}
}
componentDidUpdate(prevProps) {
const { recording, mountModal, getModal } = this.props;
const { shouldNotify } = this.state;
if (!recording) { if (!recording) {
clearInterval(this.interval); clearInterval(this.interval);
this.interval = null; this.interval = null;
} else if (this.interval === null) { } else if (this.interval === null) {
this.interval = setInterval(this.incrementTime, 1000); this.interval = setInterval(this.incrementTime, 1000);
} }
if (!prevProps.recording && recording && !shouldNotify) {
return this.setState({shouldNotify: true});
}
const isModalOpen = !!getModal();
// should only display notification modal when other modals are closed
if (shouldNotify && !isModalOpen) {
mountModal(<RecordingNotifyContainer toggleShouldNotify={this.toggleShouldNotify} />);
}
} }
incrementTime() { incrementTime() {

View File

@ -0,0 +1,66 @@
import React from 'react';
import { defineMessages, injectIntl } from 'react-intl';
import { makeCall } from '/imports/ui/services/api';
import Styled from './styles';
const intlMessages = defineMessages({
title: {
id: 'app.recording.notify.title',
description: 'Title Modal Con sent',
},
description: {
id: 'app.recording.notify.description',
description: 'Question for accept or not meeting be recorded',
},
continue: {
id: 'app.recording.notify.continue',
description: 'Button accept',
},
leave: {
id: 'app.recording.notify.leave',
description: 'Button accept',
},
});
const LOGOUT_CODE = '680';
const RecordingNotifyModal = ({ intl, closeModal, toggleShouldNotify }) => {
function skipButtonHandle() {
makeCall('userLeftMeeting');
Session.set('codeError', LOGOUT_CODE);
toggleShouldNotify();
}
return (
<Styled.RecordingNotifyModal
hideBorder
contentLabel={intl.formatMessage(intlMessages.title)}
shouldShowCloseButton={false}
>
<Styled.Container>
<Styled.Header>
<Styled.Title>
{intl.formatMessage(intlMessages.title)}
</Styled.Title>
</Styled.Header>
<Styled.Description>
{intl.formatMessage(intlMessages.description)}
</Styled.Description>
<Styled.Footer>
<Styled.NotifyButton
color="primary"
label={intl.formatMessage(intlMessages.continue)}
onClick={closeModal}
/>
<Styled.NotifyButton
label={intl.formatMessage(intlMessages.leave)}
onClick={skipButtonHandle}
/>
</Styled.Footer>
</Styled.Container>
</Styled.RecordingNotifyModal>
);
};
export default injectIntl(RecordingNotifyModal);

View File

@ -0,0 +1,12 @@
import { withTracker } from 'meteor/react-meteor-data';
import { withModalMounter } from '/imports/ui/components/common/modal/service';
import RecordingNotifyModal from './component';
export default withModalMounter(withTracker(({ mountModal, toggleShouldNotify}) => {
return {
closeModal: () => {
toggleShouldNotify();
mountModal(null);
},
};
})(RecordingNotifyModal));

View File

@ -0,0 +1,29 @@
import styled from 'styled-components';
import Modal from '/imports/ui/components/common/modal/simple/component';
import RecordingModalStyles from '/imports/ui/components/recording/styles';
const RecordingNotifyModal = styled(Modal)``;
const Container = styled(RecordingModalStyles.Container)`
padding: 3.625em 0 3.625em 0;
`;
const Header = styled(RecordingModalStyles.Header)``;
const Title = styled(RecordingModalStyles.Title)``;
const Description = styled(RecordingModalStyles.Description)``;
const Footer = styled(RecordingModalStyles.Footer)``;
const NotifyButton = styled(RecordingModalStyles.RecordingButton)``;
export default {
RecordingNotifyModal,
Container,
Header,
Title,
Description,
Footer,
NotifyButton,
};

View File

@ -726,6 +726,10 @@
"app.recording.resumeTitle": "Resume recording", "app.recording.resumeTitle": "Resume recording",
"app.recording.startDescription": "You can select the record button again later to pause the recording.", "app.recording.startDescription": "You can select the record button again later to pause the recording.",
"app.recording.stopDescription": "Are you sure you want to pause the recording? You can resume by selecting the record button again.", "app.recording.stopDescription": "Are you sure you want to pause the recording? You can resume by selecting the record button again.",
"app.recording.notify.title": "Recording has started",
"app.recording.notify.description": "A recording will be available based on the remainder of this session",
"app.recording.notify.continue": "Continue",
"app.recording.notify.leave": "Leave session",
"app.videoPreview.cameraLabel": "Camera", "app.videoPreview.cameraLabel": "Camera",
"app.videoPreview.profileLabel": "Quality", "app.videoPreview.profileLabel": "Quality",
"app.videoPreview.quality.low": "Low", "app.videoPreview.quality.low": "Low",