bigbluebutton-Github/bigbluebutton-html5/imports/ui/components/settings/component.jsx
2016-09-01 13:56:41 +00:00

204 lines
6.8 KiB
JavaScript

import React from 'react';
import Icon from '/imports/ui/components/icon/component';
import Button from '/imports/ui/components/button/component';
import Modal from '/imports/ui/components/modal/component';
import AudioMenu from './submenus/audio/component';
import VideoMenu from './submenus/video/component';
import ApplicationMenu from './submenus/application/component';
import UsersMenu from './submenus/users/component';
import classNames from 'classnames';
import ReactDOM from 'react-dom';
import styles from './styles.scss';
export default class Settings extends React.Component {
constructor(props) {
super(props);
this.submenus = [];
}
componentWillMount() {
/* activeSubmenu represents the submenu in the submenus array to be displayed to the user,
* initialized to 0
*/
this.setState({ activeSubmenu: 0 });
/* focusSubmenu represents the submenu in the submenus array which currently has focus,
* initialized to 0
*/
this.setState({ focusSubmenu: 0 });
this.submenus.push({ componentName: AudioMenu, tabIndex: 3,
props: { title: 'Audio', prependIconName: 'icon-', icon: 'bbb-audio', }, });
this.submenus.push({ componentName: VideoMenu, tabIndex: 4,
props: { title: 'Video', prependIconName: 'icon-', icon: 'bbb-video', }, });
this.submenus.push({ componentName: ApplicationMenu, tabIndex: 5,
props: { title: 'Application', prependIconName: 'icon-', icon: 'bbb-application', }, });
this.submenus.push({ componentName: UsersMenu, tabIndex: 6,
props: { title: 'Participants', prependIconName: 'icon-', icon: 'bbb-user', }, });
}
createMenu() {
const curr = this.state.activeSubmenu === undefined ? 0 : this.state.activeSubmenu;
let props = {
title: this.submenus[curr].props.title,
prependIconName: this.submenus[curr].props.prependIconName,
icon: this.submenus[curr].props.icon,
};
const Submenu = this.submenus[curr].componentName;
return <Submenu {...props}/>;
}
/* When an option in the menu is clicked, set the activeSubmenu and focusSubmenu
* to the value of index. If clicked out of bounds set to 0 or end of submenus array accordingly.
*
* activeSubmenu: the submenu to be displayed to the user
* focusSubmenu: the submenu to set focus to
*/
clickSubmenu(i) {
if (i <= 0) {
this.setState({ activeSubmenu: 0, focusSubmenu: 0, });
return;
}
if (i >= this.submenus.length) {
this.setState({ activeSubmenu: this.submenus.length - 1,
focusSubmenu: this.submenus.length - 1, });
return;
} else {
this.setState({ activeSubmenu: i, focusSubmenu: i, });
}
}
/* calls the focus method on an object in the submenu */
setFocus() {
ReactDOM.findDOMNode(this.refs[`submenu${this.state.focusSubmenu}`]).focus();
}
/* Checks for key presses within the submenu list. Key behaviour varies.
*
* Tab: changes focus to next submenu or element outside of menu
* Shift+Tab: changes focus to previous submenu or element outside of menu
* Up Arrow: changes focus to previous submenu, can cycle through menu
* Down Arrow: changes focus to next submenu, can cycle through menu
* Spacebar: selects submenu in focus and sets as active
* Enter: selects submenu in focus and sets as active
*/
handleKeyDown(event) {
// tab
if (event.keyCode === 9) {
let newIndex = 0;
if (this.state.focusSubmenu >= this.submenus.length - 1) {
newIndex = this.submenus.length - 1;
} else {
newIndex = this.state.focusSubmenu + 1;
}
this.setState({ focusSubmenu: newIndex });
return;
}
// shift+tab
if (event.shiftKey && event.keyCode === 9) {
let newIndex = 0;
if (this.state.focusSubmenu <= 0) {
newIndex = 0;
} else {
newIndex = this.state.focusSubmenu - 1;
}
this.setState({ focusSubmenu: newIndex });
return;
}
// up arrow
if (event.keyCode === 38) {
if (this.state.focusSubmenu <= 0) {
this.setState({ focusSubmenu: this.submenus.length - 1 }, function () {
this.setFocus();
});
} else {
this.setState({ focusSubmenu: this.state.focusSubmenu - 1 }, function () {
this.setFocus();
});
}
return;
}
// down arrow
if (event.keyCode === 40) {
if (this.state.focusSubmenu >= this.submenus.length - 1) {
this.setState({ focusSubmenu: 0 }, function () {
this.setFocus();
});
} else {
this.setState({ focusSubmenu: this.state.focusSubmenu + 1 }, function () {
this.setFocus();
});
}
return;
}
// spacebar or enter
if (event.keyCode === 32 || event.keyCode === 13) {
this.setState({ activeSubmenu: this.state.focusSubmenu });
return;
}
}
/* Keeps the focusSubmenu variable at the correct value when
* tabbing or shift-tabbing out of the submenu array
*/
handleFocus(index) {
this.setState({ focusSubmenu: index });
}
render() {
return (
<Modal
title="Settings"
confirm={{
callback: (() => {
this.setState({ activeSubmenu: 0, focusSubmenu: 0 });
console.log('SHOULD APPLY SETTINGS CHANGES');
}),
label: 'Done',
description: 'Saves the changes and close the settings menu',
}}
dismiss={{
callback: (() => {
this.setState({ activeSubmenu: 0, focusSubmenu: 0 });
console.log('SHOULD DISCART SETTINGS CHANGES');
}),
label: 'Cancel',
description: 'Discart the changes and close the settings menu',
}}>
<div className={styles.full} role='presentation'>
<div className={styles.settingsMenuLeft}>
<ul className={styles.settingsSubmenu} role='menu'>
{this.submenus.map((value, index) => (
<li key={index} ref={'submenu' + index} role='menuitem' tabIndex={value.tabIndex}
onClick={this.clickSubmenu.bind(this, index)}
onKeyDown={this.handleKeyDown.bind(this)}
onFocus={this.handleFocus.bind(this, index)}
className={classNames(styles.settingsSubmenuItem,
index == this.state.activeSubmenu ? styles.settingsSubmenuItemActive : null)}>
<Icon key={index} prependIconName={value.props.prependIconName}
iconName={value.props.icon} title={value.props.title}/>
<span className={styles.settingsSubmenuItemText}>{value.props.title}</span>
</li>
))}
</ul>
</div>
<div className={styles.settingsMenuRight} role='presentation'>
{this.createMenu()}
</div>
</div>
</Modal>
);
}
};
Settings.defaultProps = { title: 'Settings' };