Merge branch 'master' of github.com:bigbluebutton/bigbluebutton into audio-restructuring

This commit is contained in:
Anton Georgiev 2017-04-19 11:22:48 -04:00
commit 67700f605b
31 changed files with 378 additions and 105 deletions

View File

@ -580,8 +580,8 @@ bbb.shortcutkey.users.joinBreakoutRoom.function = Join selected breakout room
bbb.shortcutkey.chat.focusTabs = 89
bbb.shortcutkey.chat.focusTabs.function = Focus to chat tabs
bbb.shortcutkey.chat.focusBox = 77
bbb.shortcutkey.chat.focusBox.function = Focus to chat box
bbb.shortcutkey.chat.focusBox = 82
bbb.shortcutkey.chat.focusBox.function = Focus to chat message list
bbb.shortcutkey.chat.changeColour = 67
bbb.shortcutkey.chat.changeColour.function = Focus to font color picker.
bbb.shortcutkey.chat.sendMessage = 83

View File

@ -5,25 +5,32 @@ import Modal from '/imports/ui/components/modal/component';
const intlMessages = defineMessages({
title: {
id: 'app.about.title',
description: 'About title label',
},
version: {
id: 'app.about.version',
description: 'Client version label',
},
copyright: {
id: 'app.about.copyright',
defaultMessage: (new Date().getFullYear()),
description: 'Client copyright label',
},
confirmLabel: {
id: 'app.about.confirmLabel',
description: 'Confirmation button label',
},
confirmDesc: {
id: 'app.about.confirmDesc',
description: 'adds descriptive context to confirmLabel',
},
dismissLabel: {
id: 'app.about.dismissLabel',
description: 'Dismiss button label',
},
dismissDesc: {
id: 'app.about.dismissDesc',
description: 'adds descriptive context to dissmissLabel',
},
});

View File

@ -11,30 +11,31 @@ import DropdownListItem from '/imports/ui/components/dropdown/list/item/componen
const intlMessages = defineMessages({
actionsLabel: {
id: 'app.actionsBar.actionsDropdown.actionsLabel',
description: 'Actions button label',
},
presentationLabel: {
id: 'app.actionsBar.actionsDropdown.presentationLabel',
defaultMessage: 'Upload a presentation',
description: 'Upload a presentation option label',
},
initPollLabel: {
id: 'app.actionsBar.actionsDropdown.initPollLabel',
defaultMessage: 'Initiate a poll',
description: 'Initiate a poll option label',
},
desktopShareLabel: {
id: 'app.actionsBar.actionsDropdown.desktopShareLabel',
defaultMessage: 'Share your screen',
description: 'Desktop Share option label',
},
presentationDesc: {
id: 'app.actionsBar.actionsDropdown.presentationDesc',
defaultMessage: 'Upload your presentation',
description: 'adds context to upload presentation option',
},
initPollDesc: {
id: 'app.actionsBar.actionsDropdown.initPollDesc',
defaultMessage: 'Initiate a poll',
description: 'adds context to init Poll option',
},
desktopShareDesc: {
id: 'app.actionsBar.actionsDropdown.desktopShareDesc',
defaultMessage: 'Share your screen with others',
description: 'adds context to desktop share option',
},
});

View File

@ -119,89 +119,91 @@ class EmojiMenu extends Component {
const intlMessages = defineMessages({
statusTriggerLabel: {
id: 'app.actionsBar.emojiMenu.statusTriggerLabel',
description: 'Emoji status button label',
},
// For away status
awayLabel: {
id: 'app.actionsBar.emojiMenu.awayLabel',
description: 'Away emoji label',
},
awayDesc: {
id: 'app.actionsBar.emojiMenu.awayDesc',
description: 'adds context to away option',
},
// For raise hand status
raiseLabel: {
id: 'app.actionsBar.emojiMenu.raiseLabel',
description: 'raise hand emoji label',
},
raiseDesc: {
id: 'app.actionsBar.emojiMenu.raiseDesc',
description: 'adds context to raise hand option',
},
// For undecided status
undecidedLabel: {
id: 'app.actionsBar.emojiMenu.undecidedLabel',
description: 'undecided emoji label',
},
undecidedDesc: {
id: 'app.actionsBar.emojiMenu.undecidedDesc',
description: 'adds context to undecided option',
},
// For confused status
confusedLabel: {
id: 'app.actionsBar.emojiMenu.confusedLabel',
description: 'confused emoji label',
},
confusedDesc: {
id: 'app.actionsBar.emojiMenu.confusedDesc',
description: 'adds context to confused option',
},
// For sad status
sadLabel: {
id: 'app.actionsBar.emojiMenu.sadLabel',
description: 'sad emoji label',
},
sadDesc: {
id: 'app.actionsBar.emojiMenu.sadDesc',
description: 'adds context to sad option',
},
// For happy status
happyLabel: {
id: 'app.actionsBar.emojiMenu.happyLabel',
description: 'happy emoji label',
},
happyDesc: {
id: 'app.actionsBar.emojiMenu.happyDesc',
description: 'adds context to happy option',
},
// For confused status
clearLabel: {
id: 'app.actionsBar.emojiMenu.clearLabel',
description: 'confused emoji label',
},
clearDesc: {
id: 'app.actionsBar.emojiMenu.clearDesc',
description: 'adds context to clear status option',
},
// For applause status
applauseLabel: {
id: 'app.actionsBar.emojiMenu.applauseLabel',
description: 'applause emoji label',
},
applauseDesc: {
id: 'app.actionsBar.emojiMenu.applauseDesc',
description: 'adds context to applause option',
},
// For thumbs up status
thumbsupLabel: {
id: 'app.actionsBar.emojiMenu.thumbsupLabel',
description: 'thumbs up emoji label',
},
thumbsupDesc: {
id: 'app.actionsBar.emojiMenu.thumbsupDesc',
description: 'adds context to thumbs up option',
},
// For thumbs-down status
thumbsdownLabel: {
id: 'app.actionsBar.emojiMenu.thumbsdownLabel',
description: 'thumbs down emoji label',
},
thumbsdownDesc: {
id: 'app.actionsBar.emojiMenu.thumbsdownDesc',
description: 'adds context to thumbs down option',
},
changeStatusLabel: {
id: 'app.actionsBar.changeStatusLabel'
id: 'app.actionsBar.changeStatusLabel',
description: 'Aria-label for emoji status button',
},
});

View File

@ -12,15 +12,19 @@ import cx from 'classnames';
const intlMessages = defineMessages({
userListLabel: {
id: 'app.userlist.Label',
description: 'Aria-label for Userlist Nav',
},
chatLabel: {
id: 'app.chat.Label',
description: 'Aria-label for Chat Section'
},
mediaLabel: {
id: 'app.media.Label',
description: 'Aria-label for Media Section'
},
actionsbarLabel: {
id: 'app.actionsBar.Label',
description: 'Aria-label for ActionsBar Section'
},
});

View File

@ -7,10 +7,11 @@ import { defineMessages, injectIntl } from 'react-intl';
const intlMessages = defineMessages({
joinAudio: {
id: 'app.audio.joinAudio',
description: 'Join audio button label'
},
leaveAudio: {
id: 'app.audio.leaveAudio',
defaultMessage: 'Leave Audio',
description: 'Leave audio button label',
},
});

View File

@ -20,6 +20,7 @@ const defaultProps = {
const intlMessages = defineMessages({
closeLabel: {
id: 'app.audioNotification.closeLabel',
description: 'Audio notification dismiss label',
},
});

View File

@ -1,5 +1,5 @@
import React from 'react';
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
import { defineMessages, injectIntl } from 'react-intl';
import Button from '/imports/ui/components/button/component';
import { clearModal } from '/imports/ui/components/app/service';
import styles from '../audio-modal/styles.scss';
@ -61,9 +61,7 @@ class AudioSettings extends React.Component {
onClick={this.chooseAudio}
/>
<div className={cx(styles.title, styles.chooseAudio)}>
<FormattedMessage
id="app.audio.audioSettings.titleLabel"
/>
{intl.formatMessage(intlMessages.titleLabel)}
</div>
</div>
@ -71,9 +69,7 @@ class AudioSettings extends React.Component {
<div className={styles.row}>
<div className={styles.audioNote}>
<FormattedMessage
id="app.audio.audioSettings.descriptionLabel"
/>
{intl.formatMessage(intlMessages.descriptionLabel)}
</div>
</div>
@ -81,7 +77,7 @@ class AudioSettings extends React.Component {
<div className={styles.col}>
<div className={styles.formElement}>
<label className={cx(styles.label, styles.labelSmall)}>
Microphone source
{intl.formatMessage(intlMessages.micSourceLabel)}
</label>
<DeviceSelector
value={this.state.inputDeviceId}
@ -93,7 +89,7 @@ class AudioSettings extends React.Component {
<div className={styles.col}>
<div className={styles.formElement}>
<label className={cx(styles.label, styles.labelSmall)}>
Speaker source
{intl.formatMessage(intlMessages.speakerSourceLabel)}
</label>
<DeviceSelector
value={this.state.outputDeviceId}
@ -108,7 +104,7 @@ class AudioSettings extends React.Component {
<div className={styles.col}>
<div className={styles.formElement}>
<label className={cx(styles.label, styles.labelSmall)}>
Your audio stream volume
{intl.formatMessage(intlMessages.streamVolumeLabel)}
</label>
<AudioStreamVolume
deviceId={this.state.inputDeviceId}
@ -133,7 +129,28 @@ class AudioSettings extends React.Component {
const intlMessages = defineMessages({
backLabel: {
id: 'app.audio.backLabel',
description: 'audio settings back button label',
},
titleLabel: {
id: 'app.audio.audioSettings.titleLabel',
description: 'audio setting title label',
},
descriptionLabel: {
id: 'app.audio.audioSettings.descriptionLabel',
description: 'audio settings description label',
},
micSourceLabel: {
id: 'app.audio.audioSettings.microphoneSourceLabel',
description: 'Label for mic source',
},
speakerSourceLabel: {
id: 'app.audio.audioSettings.speakerSourceLabel',
description: 'Label for speaker source',
},
streamVolumeLabel: {
id: 'app.audio.audioSettings.microphoneStreamLabel',
description: 'Label for stream volume',
}
});
export default injectIntl(AudioSettings);

View File

@ -28,6 +28,7 @@ class AudioTest extends React.Component {
const intlMessages = defineMessages({
playSoundLabel: {
id: 'app.audio.playSoundLabel',
description: 'Play sound button label',
},
});

View File

@ -28,6 +28,7 @@ class EnterAudio extends React.Component {
const intlMessages = defineMessages({
enterSessionLabel: {
id: 'app.audio.enterSessionLabel',
description: 'enter session button label',
},
});

View File

@ -2,17 +2,24 @@ import React from 'react';
import styles from '../audio-modal/styles.scss';
import Button from '/imports/ui/components/button/component';
import { clearModal } from '/imports/ui/components/app/service';
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
import { defineMessages, injectIntl } from 'react-intl';
const intlMessages = defineMessages({
microphoneLabel: {
id: 'app.audioModal.microphoneLabel',
description: 'Join mic audio button label',
},
listenOnlyLabel: {
id: 'app.audioModal.listenOnlyLabel',
description: 'Join listen only audio button label',
},
closeLabel: {
id: 'app.audioModal.closeLabel',
description: 'close audio modal button label',
},
audioChoiceLabel: {
id: 'app.audioModal.audioChoiceLabel',
description: 'Join audio modal title',
},
});
@ -54,11 +61,7 @@ class JoinAudio extends React.Component {
</div>
<div className={styles.title}>
<FormattedMessage
id="app.audioModal.audioChoiceLabel"
description="app.audioModal.audioChoiceDescription"
defaultMessage="How would you like to join the audio?"
/>
{intl.formatMessage(intlMessages.audioChoiceLabel)}
</div>
<div className={styles.center}>
<Button className={styles.audioBtn}

View File

@ -7,21 +7,27 @@ import Modal from '/imports/ui/components/modal/component';
const intlMessages = defineMessages({
title: {
id: 'app.breakoutJoinConfirmation.title',
description: 'Join breakout room title',
},
message: {
id: 'app.breakoutJoinConfirmation.message',
description: 'Join breakout confim message',
},
confirmLabel: {
id: 'app.breakoutJoinConfirmation.confirmLabel',
description: 'Join confirmation button label',
},
confirmDesc: {
id: 'app.breakoutJoinConfirmation.confirmDesc',
description: 'adds context to confirm option',
},
dismissLabel: {
id: 'app.breakoutJoinConfirmation.dismissLabel',
description: 'Cancel button label',
},
dismissDesc: {
id: 'app.breakoutJoinConfirmation.dismissDesc',
description: 'adds context to dismiss option',
},
});

View File

@ -11,6 +11,11 @@ const ELEMENT_ID = 'chat-messages';
const intlMessages = defineMessages({
closeChatLabel: {
id: 'app.chat.closeChatLabel',
description: 'aria-label for closing chat button',
},
hideChatLabel: {
id: 'app.chat.hideChatLabel',
description: 'aria-label for hiding chat button',
},
});
@ -42,7 +47,7 @@ class Chat extends Component {
<Link
to="/users"
role="button"
aria-label={intl.formatMessage(intlMessages.closeChatLabel, { title: title })}>
aria-label={intl.formatMessage(intlMessages.hideChatLabel, { title: title })}>
<Icon iconName="left_arrow"/> {title}
</Link>
</div>
@ -50,8 +55,11 @@ class Chat extends Component {
{
((this.props.chatID == 'public') ?
null :
<Link to="/users">
<Icon iconName="close" onClick={() => actions.handleClosePrivateChat(chatID)}/>
<Link
to="/users"
role="button"
aria-label={intl.formatMessage(intlMessages.closeChatLabel, { title: title })}>
<Icon iconName="close" onClick={() => actions.handleClosePrivateChat(chatID)}/>
</Link>)
}
</div>

View File

@ -45,7 +45,7 @@ class MessageForm extends Component {
handleMessageKeyDown(e) {
//TODO Prevent send message pressing enter on mobile and/or virtual keyboard
//TODO Prevent send message pressing enter on mobile and/or virtual keyboard
if (e.keyCode === 13 && !e.shiftKey) {
e.preventDefault();

View File

@ -139,7 +139,8 @@ class MessageList extends Component {
<div
tabIndex="0"
role="log"
aria-atomic="true"
aria-atomic="false"
aria-live="polite"
aria-relevant="additions"
ref="scrollArea"
className={styles.messageList}

View File

@ -42,7 +42,7 @@ export default class MessageListItem extends Component {
</div>
<div className={styles.content}>
<div className={styles.meta}>
<div className={user.isOnline ? styles.name : styles.logout}>
<div className={user.isOnline ? styles.name : styles.logout} aria-label={user.name}>
<span>{user.name}</span>
{user.isOnline ? null : <span className={styles.offline}>(offline)</span>}
</div>

View File

@ -12,6 +12,7 @@ const FOCUSABLE_CHILDREN = `[tabindex]:not([tabindex="-1"]), a, input, button`;
const intlMessages = defineMessages({
close: {
id: 'app.dropdown.close',
description: 'Close button label',
},
});

View File

@ -33,7 +33,12 @@ export default class DropdownList extends Component {
}
componentDidUpdate(prevProps, prevState) {
const { activeItemIndex } = this.state;
let { activeItemIndex } = this.state;
if (activeItemIndex === null) {
activeItemIndex = 0;
}
const activeRef = this.childrenRefs[activeItemIndex];
if (activeRef) {

View File

@ -6,15 +6,19 @@ import styles from './styles.scss';
const intlMessages = defineMessages({
500: {
id: 'app.error.500',
defaultMessage: 'Ops, something went wrong',
},
404: {
id: 'app.error.404',
defaultMessage: 'Not found',
},
401: {
id: 'app.about.401',
defaultMessage: 'Unauthorized',
},
403: {
id: 'app.about.403',
defaultMessage: 'Forbidden',
},
});

View File

@ -6,21 +6,27 @@ import Modal from '/imports/ui/components/modal/component';
const intlMessages = defineMessages({
title: {
id: 'app.leaveConfirmation.title',
description: 'Leave session modal title',
},
message: {
id: 'app.leaveConfirmation.message',
description: 'message for leaving session',
},
confirmLabel: {
id: 'app.leaveConfirmation.confirmLabel',
description: 'Confirmation button label',
},
confirmDesc: {
id: 'app.leaveConfirmation.confirmDesc',
description: 'adds context to confim option',
},
dismissLabel: {
id: 'app.leaveConfirmation.dismissLabel',
description: 'Dismiss button label',
},
dismissDesc: {
id: 'app.leaveConfirmation.dismissDesc',
description: 'adds context to dismiss option',
},
});

View File

@ -1,6 +1,5 @@
import React, { Component, PropTypes } from 'react';
import styles from './styles.scss';
import { FormattedMessage, FormattedDate } from 'react-intl';
const propTypes = {
content: PropTypes.element.isRequired,

View File

@ -19,6 +19,11 @@ import { defineMessages, injectIntl } from 'react-intl';
const intlMessages = defineMessages({
toggleUserListLabel: {
id: 'app.navBar.userListToggleBtnLabel',
description: 'Toggle button label',
},
newMessages: {
id: 'app.navbar.toggleUserList.newMessages',
description: 'label for toggleUserList btn when showing red notification'
},
});
@ -72,6 +77,8 @@ class NavBar extends Component {
toggleBtnClasses[styles.btn] = true;
toggleBtnClasses[styles.btnWithNotificationDot] = hasUnreadMessages;
return (
<div className={styles.navbar}>
<div className={styles.left}>
@ -84,7 +91,11 @@ class NavBar extends Component {
icon={'user'}
className={cx(toggleBtnClasses)}
aria-expanded={isExpanded}
aria-describedby="newMessage"
/>
<div
id="newMessage"
aria-label={hasUnreadMessages ? intl.formatMessage(intlMessages.newMessages) : null}/>
</div>
<div className={styles.center} role="banner">
{this.renderPresentationTitle()}

View File

@ -19,36 +19,47 @@ import DropdownListSeparator from '/imports/ui/components/dropdown/list/separato
const intlMessages = defineMessages({
optionsLabel: {
id: 'app.navBar.settingsDropdown.optionsLabel',
description: 'Options button label',
},
fullscreenLabel: {
id: 'app.navBar.settingsDropdown.fullscreenLabel',
description: 'Make fullscreen option label',
},
settingsLabel: {
id: 'app.navBar.settingsDropdown.settingsLabel',
description: 'Open settings option label',
},
aboutLabel: {
id: 'app.navBar.settingsDropdown.aboutLabel',
description: 'About option label',
},
aboutDesc: {
id: 'app.navBar.settingsDropdown.aboutDesc',
description: 'Describes about option',
},
leaveSessionLabel: {
id: 'app.navBar.settingsDropdown.leaveSessionLabel',
description: 'Leave session button label',
},
fullscreenDesc: {
id: 'app.navBar.settingsDropdown.fullscreenDesc',
description: 'Describes fullscreen option',
},
settingsDesc: {
id: 'app.navBar.settingsDropdown.settingsDesc',
description: 'Describes settings option',
},
leaveSessionDesc: {
id: 'app.navBar.settingsDropdown.leaveSessionDesc',
description: 'Describes leave session option',
},
exitFullScreenDesc: {
id: 'app.navBar.settingsDropdown.exitFullScreenDesc',
description: 'Describes exit fullscreen option',
},
exitFullScreenLabel: {
id: 'app.navBar.settingsDropdown.exitFullScreenLabel',
description: 'Exit fullscreen option label',
},
});

View File

@ -7,9 +7,11 @@ import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
const intlMessages = defineMessages({
previousSlideLabel: {
id: 'app.presentation.presentationToolbar.prevSlideLabel',
description: 'Previous slide button label',
},
nextSlideLabel: {
id: 'app.presentation.presentationToolbar.nextSlideLabel',
description: 'Next slide button label'
},
});

View File

@ -1,7 +1,7 @@
import React, { Component } from 'react';
import Modal from '/imports/ui/components/modal/component';
import { Tab, Tabs, TabList, TabPanel } from 'react-tabs';
import { defineMessages, injectIntl } from 'react-intl';
import ClosedCaptions from '/imports/ui/components/settings/submenus/closed-captions/component';
import Application from '/imports/ui/components/settings/submenus/application/container';
import Participants from '/imports/ui/components/settings/submenus/participants/component';
@ -11,10 +11,33 @@ import _ from 'lodash';
import Icon from '../icon/component';
import styles from './styles';
const intlMessages = defineMessages({
appTabLabel: {
id: 'app.settings.applicationTab.label',
description: 'label for application tab',
},
audioTabLabel: {
id: 'app.settings.audioTab.label',
description: 'label for audio tab',
},
videoTabLabel: {
id: 'app.settings.videoTab.label',
description: 'label for video tab',
},
closecaptionTabLabel: {
id: 'app.settings.closedcaptionTab.label',
description: 'label for closed-captions tab',
},
usersTabLabel: {
id: 'app.settings.usersTab.label',
description: 'label for participants tab',
},
});
const propTypes = {
};
export default class Settings extends Component {
class Settings extends Component {
constructor(props) {
super(props);
@ -87,6 +110,7 @@ export default class Settings extends Component {
renderModalContent() {
const {
isModerator,
intl,
} = this.props;
return (
@ -94,24 +118,25 @@ export default class Settings extends Component {
className={styles.tabs}
onSelect={this.handleSelectTab}
selectedIndex={this.state.selectedTab}
role="presentation"
>
<TabList className={styles.tabList}>
<Tab className={styles.tabSelector}>
<Tab className={styles.tabSelector} aria-labelledby="appTab">
<Icon iconName='application' className={styles.icon}/>
Application
<span id="appTab">{intl.formatMessage(intlMessages.appTabLabel)}</span>
</Tab>
<Tab className={styles.tabSelector}>
<Tab className={styles.tabSelector} aria-labelledby="videoTab">
<Icon iconName='video' className={styles.icon}/>
Video
<span id="videoTab">{intl.formatMessage(intlMessages.videoTabLabel)}</span>
</Tab>
<Tab className={styles.tabSelector}>
<Tab className={styles.tabSelector} aria-labelledby="ccTab">
<Icon iconName='user' className={styles.icon}/>
Closed Captions
<span id="ccTab">{intl.formatMessage(intlMessages.closecaptionTabLabel)}</span>
</Tab>
{ isModerator ?
<Tab className={styles.tabSelector}>
<Tab className={styles.tabSelector} aria-labelledby="usersTab">
<Icon iconName='user' className={styles.icon}/>
Participants
<span id="usersTab">{intl.formatMessage(intlMessages.usersTabLabel)}</span>
</Tab>
: null }
</TabList>
@ -146,3 +171,4 @@ export default class Settings extends Component {
}
Settings.propTypes = propTypes;
export default injectIntl(Settings);

View File

@ -7,11 +7,47 @@ import ReactDOM from 'react-dom';
import cx from 'classnames';
import styles from '../styles.scss';
import Toggle from '/imports/ui/components/switch/component';
import { defineMessages, injectIntl } from 'react-intl';
const MIN_FONTSIZE = 0;
const MAX_FONTSIZE = 4;
export default class ApplicationMenu extends BaseMenu {
const intlMessages = defineMessages({
applicationSectionTitle: {
id: 'app.submenu.application.applicationSectionTitle',
description: 'Application section title',
},
audioNotifyLabel: {
id: 'app.submenu.application.audioNotifyLabel',
description: 'audio notification label',
},
pushNotifyLabel: {
id: 'app.submenu.application.pushNotifyLabel',
description: 'push notifiation label',
},
fontSizeControlLabel: {
id: 'app.submenu.application.fontSizeControlLabel',
description: 'label for font size ontrol',
},
increaseFontBtnLabel: {
id: 'app.submenu.application.increaseFontBtnLabel',
description: 'label for button to increase font size',
},
increaseFontBtnDesc: {
id: 'app.submenu.application.increaseFontBtnDesc',
description: 'adds descriptive context to increase font size button',
},
decreaseFontBtnLabel: {
id: 'app.submenu.application.decreaseFontBtnLabel',
description: 'label for button to reduce font size',
},
decreaseFontBtnDesc: {
id: 'app.submenu.application.decreaseFontBtnDesc',
description: 'adds descriptive context to decrease font size button',
},
});
class ApplicationMenu extends BaseMenu {
constructor(props) {
super(props);
@ -57,22 +93,24 @@ export default class ApplicationMenu extends BaseMenu {
};
render() {
const { intl } = this.props;
return (
<div className={styles.tabContent}>
<div className={styles.header}>
<h3 className={styles.title}>Application</h3>
<h3 className={styles.title}>{intl.formatMessage(intlMessages.applicationSectionTitle)}</h3>
</div>
<div className={styles.form}>
<div className={styles.row}>
<div className={styles.col}>
<div className={styles.formElement}>
<label className={styles.label}>
Audio notifications for chat
{intl.formatMessage(intlMessages.audioNotifyLabel)}
</label>
</div>
</div>
<div className={styles.col}>
<div className={cx(styles.formElement, styles.pullContentRight)}>
<div className={cx(styles.formElement, styles.pullContentRight)} aria-label={intl.formatMessage(intlMessages.audioNotifyLabel)}>
<Toggle
icons={false}
defaultChecked={this.state.settings.chatAudioNotifications}
@ -84,7 +122,7 @@ export default class ApplicationMenu extends BaseMenu {
<div className={styles.col}>
<div className={styles.formElement}>
<label className={styles.label}>
Push notifications for chat
{intl.formatMessage(intlMessages.pushNotifyLabel)}
</label>
</div>
</div>
@ -93,7 +131,7 @@ export default class ApplicationMenu extends BaseMenu {
<Toggle
icons={false}
defaultChecked={this.state.settings.chatPushNotifications}
onChange={() => this.handleToggle('chatPushNotifications')} />
onChange={() => this.handleToggle('chatPushNotifications')}/>
</div>
</div>
</div>
@ -102,7 +140,7 @@ export default class ApplicationMenu extends BaseMenu {
<div className={styles.col}>
<div className={styles.formElement}>
<label className={styles.label}>
Font size
{intl.formatMessage(intlMessages.fontSizeControlLabel)}
</label>
</div>
</div>
@ -124,9 +162,8 @@ export default class ApplicationMenu extends BaseMenu {
circle={true}
tabIndex='0'
hideLabel={true}
label={'Increase Font'}
aria-labelledby={'sizeUpLabel'}
aria-describedby={'sizeUpDesc'}
label={intl.formatMessage(intlMessages.increaseFontBtnLabel)}
aria-describedby={""}
/>
<div id='sizeUpLabel' hidden>Font size up</div>
</div>
@ -138,11 +175,9 @@ export default class ApplicationMenu extends BaseMenu {
circle={true}
tabIndex='0'
hideLabel={true}
label={'Decrease Font'}
aria-labelledby={'sizeDownLabel'}
aria-describedby={'sizeDownDesc'}
label={intl.formatMessage(intlMessages.decreaseFontBtnLabel)}
aria-describedby={""}
/>
<div id='sizeUpDesc' hidden>Increases the font size of the application.</div>
</div>
</div>
</div>
@ -153,3 +188,5 @@ export default class ApplicationMenu extends BaseMenu {
);
}
};
export default injectIntl(ApplicationMenu);

View File

@ -6,6 +6,7 @@ import BaseMenu from '../base/component';
import Toggle from '/imports/ui/components/switch/component';
import Checkbox from '/imports/ui/components/checkbox/component';
import { GithubPicker } from 'react-color';
import { defineMessages, injectIntl } from 'react-intl';
//an array of font-families
const FONT_FAMILIES = ['Arial', 'Calibri', 'Time New Roman', 'Sans-serif'];
@ -20,7 +21,54 @@ const COLORS = [
'#8800FF', '#FF00FF',
];
export default class ClosedCaptionsMenu extends BaseMenu {
const intlMessages = defineMessages({
closedCaptionsLabel: {
id: 'app.submenu.closedCaptions.closedCaptionsLabel',
description: 'Closed Captions label',
},
takeOwnershipLabel: {
id: 'app.submenu.closedCaptions.takeOwnershipLabel',
description: 'Take ownership label',
},
languageLabel: {
id: 'app.submenu.closedCaptions.languageLabel',
description: 'Language label',
},
localeOptionLabel: {
id: 'app.submenu.closedCaptions.localeOptionLabel',
description: 'Label for active locales',
},
noLocaleOptionLabel: {
id: 'app.submenu.closedCaptions.noLocaleOptionLabel',
description: 'Label for no active locales',
},
fontFamilyLabel: {
id: 'app.submenu.closedCaptions.fontFamilyLabel',
description: 'Label for type of Font family',
},
fontFamilyOptionLabel: {
id: 'app.submenu.closedCaptions.fontFamilyOptionLabel',
description: 'Font-family default choice option',
},
fontSizeLabel: {
id: 'app.submenu.closedCaptions.fontSizeLabel',
description: 'Font size label',
},
fontSizeOptionLabel: {
id: 'app.submenu.closedCaptions.fontSizeOptionLabel',
description: 'Choose Font size default option label',
},
backgroundColorLabel: {
id: 'app.submenu.closedCaptions.backgroundColorLabel',
description: 'Background color label',
},
fontColorLabel: {
id: 'app.submenu.closedCaptions.fontColorLabel',
description: 'Font color label',
},
});
class ClosedCaptionsMenu extends BaseMenu {
constructor(props) {
super(props);
this.state = {
@ -79,19 +127,20 @@ export default class ClosedCaptionsMenu extends BaseMenu {
render() {
const {
locales,
intl
} = this.props;
return (
<div className={styles.tabContent}>
<div className={styles.header}>
<h3 className={styles.title}>Closed Captions</h3>
<h3 className={styles.title}>{intl.formatMessage(intlMessages.closedCaptionsLabel)}</h3>
</div>
<div className={styles.form}>
<div className={styles.row}>
<div className={styles.col}>
<div className={styles.formElement}>
<label className={styles.label}>
Closed captions
{intl.formatMessage(intlMessages.closedCaptionsLabel)}
</label>
</div>
</div>
@ -108,7 +157,7 @@ export default class ClosedCaptionsMenu extends BaseMenu {
<div className={styles.col}>
<div className={styles.formElement}>
<label className={styles.label}>
Take ownership
{intl.formatMessage(intlMessages.takeOwnershipLabel)}
</label>
</div>
</div>
@ -124,7 +173,7 @@ export default class ClosedCaptionsMenu extends BaseMenu {
<div className={styles.col}>
<div className={styles.formElement}>
<label className={styles.label}>
Language
{intl.formatMessage(intlMessages.languageLabel)}
</label>
</div>
</div>
@ -137,8 +186,8 @@ export default class ClosedCaptionsMenu extends BaseMenu {
<option>
{ this.props.locales &&
this.props.locales.length ?
'Choose language' :
'No active locales' }
intl.formatMessage(intlMessages.localeOptionLabel) :
intl.formatMessage(intlMessages.noLocaleOptionLabel) }
</option>
{this.props.locales ? this.props.locales.map((locale, index) =>
<option key={index} value={index}>
@ -154,7 +203,7 @@ export default class ClosedCaptionsMenu extends BaseMenu {
<div className={styles.col}>
<div className={styles.formElement}>
<label className={styles.label}>
Font family
{intl.formatMessage(intlMessages.fontFamilyLabel)}
</label>
</div>
</div>
@ -164,7 +213,7 @@ export default class ClosedCaptionsMenu extends BaseMenu {
defaultValue={FONT_FAMILIES.indexOf(this.state.settings.fontFamily)}
onChange={this.handleSelectChange.bind(this, 'fontFamily', FONT_FAMILIES)}
className={styles.select}>
<option value='-1' disabled>Choose Font-family</option>
<option value='-1' disabled>{intl.formatMessage(intlMessages.fontFamilyOptionLabel)}</option>
{
FONT_FAMILIES.map((family, index) =>
<option key={index} value={index}>
@ -181,7 +230,7 @@ export default class ClosedCaptionsMenu extends BaseMenu {
<div className={styles.col}>
<div className={styles.formElement}>
<label className={styles.label}>
Font size
{intl.formatMessage(intlMessages.fontSizeLabel)}
</label>
</div>
</div>
@ -191,7 +240,7 @@ export default class ClosedCaptionsMenu extends BaseMenu {
defaultValue={FONT_SIZES.indexOf(this.state.settings.fontSize)}
onChange={this.handleSelectChange.bind(this, 'fontSize', FONT_SIZES)}
className={styles.select}>
<option value='-1' disabled>Choose Font-size</option>
<option value='-1' disabled>{intl.formatMessage(intlMessages.fontSizeOptionLabel)}</option>
{
FONT_SIZES.map((size, index) =>
<option key={index} value={index}>
@ -208,7 +257,7 @@ export default class ClosedCaptionsMenu extends BaseMenu {
<div className={styles.col}>
<div className={styles.formElement}>
<label className={styles.label}>
Background color
{intl.formatMessage(intlMessages.backgroundColorLabel)}
</label>
</div>
</div>
@ -248,7 +297,7 @@ export default class ClosedCaptionsMenu extends BaseMenu {
<div className={styles.col}>
<div className={styles.formElement}>
<label className={styles.label}>
Font color
{intl.formatMessage(intlMessages.fontColorLabel)}
</label>
</div>
</div>
@ -298,3 +347,5 @@ export default class ClosedCaptionsMenu extends BaseMenu {
);
}
};
export default injectIntl(ClosedCaptionsMenu);

View File

@ -1,11 +1,38 @@
import React, { Component } from 'react';
import BaseMenu from '../base/component';
import styles from '../styles.scss';
import { defineMessages, injectIntl } from 'react-intl';
import Toggle from '/imports/ui/components/switch/component';
import cx from 'classnames';
export default class VideoMenu extends BaseMenu {
const intlMessages = defineMessages({
videoSectionTitle: {
id: 'app.submenu.video.title',
description: 'Heading for video submenu section',
},
videoSourceLabel: {
id: 'app.submenu.video.videoSourceLabel',
description: 'Label for video source section',
},
videoOptionLabel: {
id: 'app.submenu.video.videoOptionLabel',
description: 'default video source option label',
},
videoQualityLabel: {
id: 'app.submenu.video.videoQualityLabel',
description: 'Label for video quality section',
},
qualityOptionLabel: {
id: 'app.submenu.video.qualityOptionLabel',
description: 'default quality option label',
},
participantsCamLabel: {
id: 'app.submenu.video.participantsCamLabel',
description: 'Label for participants cam section',
},
});
class VideoMenu extends BaseMenu {
constructor(props) {
super(props);
@ -16,10 +43,12 @@ export default class VideoMenu extends BaseMenu {
}
render() {
const { intl } = this.props;
return (
<div className={styles.tabContent}>
<div className={styles.header}>
<h3 className={styles.title}>Video</h3>
<h3 className={styles.title}>{intl.formatMessage(intlMessages.videoSectionTitle)}</h3>
</div>
<div className={styles.form}>
@ -27,24 +56,24 @@ export default class VideoMenu extends BaseMenu {
<div className={styles.col}>
<div className={styles.formElement}>
<label className={cx(styles.label, styles.labelSmall)}>
View source
{intl.formatMessage(intlMessages.videoSourceLabel)}
</label>
<select
defaultValue='-1'
className={styles.select}>
<option value='-1' disabled>Choose view source</option>
<option value='-1' disabled>{intl.formatMessage(intlMessages.videoOptionLabel)}</option>
</select>
</div>
</div>
<div className={styles.col}>
<div className={styles.formElement}>
<label className={cx(styles.label, styles.labelSmall)}>
Video Quality
{intl.formatMessage(intlMessages.videoQualityLabel)}
</label>
<select
defaultValue='-1'
className={styles.select}>
<option value='-1' disabled>Choose the video quality</option>
<option value='-1' disabled>{intl.formatMessage(intlMessages.qualityOptionLabel)}</option>
</select>
</div>
</div>
@ -53,7 +82,7 @@ export default class VideoMenu extends BaseMenu {
<div className={styles.col}>
<div className={styles.formElement}>
<label className={styles.label}>
Viewing participants webcams
{intl.formatMessage(intlMessages.participantsCamLabel)}
</label>
</div>
</div>
@ -71,3 +100,5 @@ export default class VideoMenu extends BaseMenu {
);
}
};
export default injectIntl(VideoMenu);

View File

@ -32,11 +32,11 @@ export default class UserAvatar extends Component {
};
return (
<div className={user.isOnline ? styles.userAvatar : styles.userLogout}
style={avatarStyles} aria-hidden="true">
<span>
<div className={!user.isLoggedOut ? styles.userAvatar : styles.userLogout}
style={avatarStyles}>
<div>
{this.renderAvatarContent()}
</span>
</div>
{this.renderUserStatus()}
{this.renderUserMediaStatus()}
</div>
@ -46,7 +46,7 @@ export default class UserAvatar extends Component {
renderAvatarContent() {
const user = this.props.user;
let content = user.name.slice(0, 2);
let content = <span aria-hidden="true">{user.name.slice(0, 2)}</span>;
if (user.emoji.status !== 'none') {
let iconEmoji = undefined;
@ -70,7 +70,7 @@ export default class UserAvatar extends Component {
default:
iconEmoji = user.emoji.status;
}
content = <Icon iconName={iconEmoji}/>;
content = <span aria-label={user.emoji.status}><Icon iconName={iconEmoji}/></span>;
}
return content;

View File

@ -10,12 +10,15 @@ import { defineMessages, injectIntl } from 'react-intl';
const intlMessages = defineMessages({
titlePublic: {
id: 'app.chat.titlePublic',
description: 'title for public chat',
},
unreadPlural: {
id: 'app.userlist.chatlistitem.unreadPlural',
description: 'singular aria label for new message'
},
unreadSingular: {
id: 'app.userlist.chatlistitem.unreadSingular',
description: 'plural aria label for new messages'
},
});

View File

@ -13,6 +13,7 @@
"app.chat.titlePrivate": "Private Chat with {name}",
"app.chat.partnerDisconnected": "{name} has left the meeting",
"app.chat.closeChatLabel": "Close {title}",
"app.chat.hideChatLabel": "Hide {title}",
"app.chat.moreMessages": "More messages below",
"app.userlist.chatlistitem.unreadSingular": "{count} New Message",
"app.userlist.chatlistitem.unreadPlural": "{count} New Messages",
@ -45,6 +46,7 @@
"app.navBar.settingsDropdown.exitFullScreenLabel": "Exit fullscreen",
"app.navBar.settingsDropdown.exitFullScreenDesc": "Exit fullscreen mode",
"app.navBar.userListToggleBtnLabel": "User List Toggle",
"app.navbar.toggleUserList.newMessages": "with new message notification",
"app.leaveConfirmation.title": "Leave Session",
"app.leaveConfirmation.message": "Do you want to leave this meeting?",
"app.leaveConfirmation.confirmLabel": "Leave",
@ -63,6 +65,37 @@
"app.actionsBar.camOffLabel": "Cam Off",
"app.actionsBar.raiseLabel": "Raise",
"app.actionsBar.Label": "Actions Bar",
"app.submenu.application.applicationSectionTitle": "Application",
"app.submenu.application.audioNotifyLabel": "Audio notifications for chat",
"app.submenu.application.pushNotifyLabel": "Push notifications for chat",
"app.submenu.application.fontSizeControlLabel": "Font size",
"app.submenu.application.increaseFontBtnLabel": "Increase Font Size",
"app.submenu.application.decreaseFontBtnLabel": "Decrease Font Size",
"app.submenu.audio.micSourceLabel": "Microphone source",
"app.submenu.audio.speakerSourceLabel": "Speaker source",
"app.submenu.audio.streamVolumeLabel": "Your audio stream volume",
"app.submenu.video.title": "Video",
"app.submenu.video.videoSourceLabel": "View source",
"app.submenu.video.videoOptionLabel": "Choose view source",
"app.submenu.video.videoQualityLabel": "Video Quality",
"app.submenu.video.qualityOptionLabel": "Choose the video quality",
"app.submenu.video.participantsCamLabel": "Viewing participants webcams",
"app.submenu.closedCaptions.closedCaptionsLabel": "Closed Captions",
"app.submenu.closedCaptions.takeOwnershipLabel": "Take ownership",
"app.submenu.closedCaptions.languageLabel": "Language",
"app.submenu.closedCaptions.localeOptionLabel": "Choose language",
"app.submenu.closedCaptions.noLocaleOptionLabel": "No active locales",
"app.submenu.closedCaptions.fontFamilyLabel": "Font family",
"app.submenu.closedCaptions.fontFamilyOptionLabel": "Choose Font-family",
"app.submenu.closedCaptions.fontSizeLabel": "Font size",
"app.submenu.closedCaptions.fontSizeOptionLabel": "Choose Font size",
"app.submenu.closedCaptions.backgroundColorLabel": "Background color",
"app.submenu.closedCaptions.fontColorLabel": "Font color",
"app.settings.applicationTab.label": "Application",
"app.settings.audioTab.label": "Audio",
"app.settings.videoTab.label": "Video",
"app.settings.closedcaptionTab.label": "Closed Captions",
"app.settings.usersTab.label": "Participants",
"app.actionsBar.actionsDropdown.actionsLabel": "Actions",
"app.actionsBar.actionsDropdown.presentationLabel": "Upload a presentation",
"app.actionsBar.actionsDropdown.initPollLabel": "Initiate a poll",