From 99e15b20ba24d4988bd57a3a41892b28d1c06c55 Mon Sep 17 00:00:00 2001 From: KDSBrowne <kert.browne85@gmail.com> Date: Mon, 19 Nov 2018 23:29:48 +0000 Subject: [PATCH] add panel manager component --- bigbluebutton-html5/client/main.jsx | 2 + .../actions-dropdown/component.jsx | 5 +- .../imports/ui/components/app/component.jsx | 7 + .../imports/ui/components/app/container.jsx | 2 +- .../ui/components/breakout-room/service.js | 5 +- .../imports/ui/components/chat/component.jsx | 5 +- .../ui/components/nav-bar/component.jsx | 8 +- .../ui/components/panel-manager/component.jsx | 159 ++++++++++++++++++ .../imports/ui/components/poll/component.jsx | 7 +- .../components/poll/live-result/component.jsx | 3 +- .../user-list/chat-list-item/component.jsx | 11 +- .../breakout-room/component.jsx | 10 +- .../user-dropdown/component.jsx | 6 +- .../user-polls/component.jsx | 12 +- 14 files changed, 205 insertions(+), 37 deletions(-) create mode 100644 bigbluebutton-html5/imports/ui/components/panel-manager/component.jsx diff --git a/bigbluebutton-html5/client/main.jsx b/bigbluebutton-html5/client/main.jsx index c7715123a1..b674ebf094 100755 --- a/bigbluebutton-html5/client/main.jsx +++ b/bigbluebutton-html5/client/main.jsx @@ -34,6 +34,8 @@ Meteor.startup(() => { } authenticatedRouteHandler(() => { // set defaults + Session.set('openPanel', ''); + Session.set('isChatOpen', false); Session.set('idChatOpen', ''); Session.set('isMeetingEnded', false); diff --git a/bigbluebutton-html5/imports/ui/components/actions-bar/actions-dropdown/component.jsx b/bigbluebutton-html5/imports/ui/components/actions-bar/actions-dropdown/component.jsx index 0da0a77e1c..5aa94094ba 100755 --- a/bigbluebutton-html5/imports/ui/components/actions-bar/actions-dropdown/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/actions-bar/actions-dropdown/component.jsx @@ -127,7 +127,10 @@ class ActionsDropdown extends Component { label={intl.formatMessage(intlMessages.pollBtnLabel)} description={intl.formatMessage(intlMessages.pollBtnDesc)} key={this.pollId} - onClick={() => togglePollMenu()} + onClick={() => { + Session.set('openPanel', 'poll'); + Session.set('forcePollOpen', true); + }} /> : null), (isUserPresenter ? diff --git a/bigbluebutton-html5/imports/ui/components/app/component.jsx b/bigbluebutton-html5/imports/ui/components/app/component.jsx index 865c027833..868d9c0990 100755 --- a/bigbluebutton-html5/imports/ui/components/app/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/app/component.jsx @@ -17,6 +17,8 @@ import { styles } from './styles'; import UserListContainer from '../user-list/container'; import ChatContainer from '../chat/container'; import PollContainer from '/imports/ui/components/poll/container'; +import PanelManager from '/imports/ui/components/panel-manager/component'; +import { Session } from 'meteor/session'; const MOBILE_MEDIA = 'only screen and (max-width: 40em)'; const USERLIST_COMPACT_WIDTH = 50; @@ -108,6 +110,10 @@ class App extends Component { this.setState({ enableResize: shouldEnableResize }); } + renderPanel() { + return <PanelManager openPanel={Session.get('openPanel')} />; + } + renderPoll() { const { pollIsOpen } = this.props; @@ -346,6 +352,7 @@ class App extends Component { {this.renderPoll()} {this.renderBreakoutRoom()} {this.renderSidebar()} + {this.renderPanel()} </section> <PollingContainer /> <ModalContainer /> diff --git a/bigbluebutton-html5/imports/ui/components/app/container.jsx b/bigbluebutton-html5/imports/ui/components/app/container.jsx index 600aee2578..4bbbbd1781 100755 --- a/bigbluebutton-html5/imports/ui/components/app/container.jsx +++ b/bigbluebutton-html5/imports/ui/components/app/container.jsx @@ -67,7 +67,6 @@ const AppContainer = (props) => { ); }; - export default injectIntl(withModalMounter(withTracker(({ intl, baseControls }) => { const currentUser = Users.findOne({ userId: Auth.userID }); const isMeetingBreakout = meetingIsBreakout(); @@ -117,6 +116,7 @@ export default injectIntl(withModalMounter(withTracker(({ intl, baseControls }) pollIsOpen: Session.get('isPollOpen') && Session.get('isUserListOpen'), customStyle: getFromUserSettings('customStyle', false), customStyleUrl: getFromUserSettings('customStyleUrl', false), + openPanel: Session.get('openPanel'), }; })(AppContainer))); diff --git a/bigbluebutton-html5/imports/ui/components/breakout-room/service.js b/bigbluebutton-html5/imports/ui/components/breakout-room/service.js index 9158ea9d37..025cfb7651 100644 --- a/bigbluebutton-html5/imports/ui/components/breakout-room/service.js +++ b/bigbluebutton-html5/imports/ui/components/breakout-room/service.js @@ -25,9 +25,9 @@ const breakoutRoomUser = (breakoutId) => { return breakoutUser; }; - const endAllBreakouts = () => { makeCall('endAllBreakouts'); + closeBreakoutPanel(); }; const requestJoinURL = (breakoutId) => { @@ -63,8 +63,7 @@ const isModerator = () => { return mappedUser.isModerator; }; - -const closeBreakoutPanel = () => Session.set('breakoutRoomIsOpen', false); +const closeBreakoutPanel = () => Session.set('openPanel', 'userlist'); export default { findBreakouts, diff --git a/bigbluebutton-html5/imports/ui/components/chat/component.jsx b/bigbluebutton-html5/imports/ui/components/chat/component.jsx index 7c6faba8da..2379ed9fb9 100644 --- a/bigbluebutton-html5/imports/ui/components/chat/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/chat/component.jsx @@ -56,7 +56,7 @@ const Chat = (props) => { > <Button onClick={() => { - Session.set('isChatOpen', false); + Session.set('openPanel', 'userlist'); }} aria-label={intl.formatMessage(intlMessages.hideChatLabel, { 0: title })} accessKey={HIDE_CHAT_AK} @@ -74,8 +74,7 @@ const Chat = (props) => { hideLabel onClick={() => { actions.handleClosePrivateChat(chatID); - Session.set('isChatOpen', false); - Session.set('idChatOpen', ''); + Session.set('openPanel', 'userlist'); }} aria-label={intl.formatMessage(intlMessages.closeChatLabel, { 0: title })} label={intl.formatMessage(intlMessages.closeChatLabel, { 0: title })} diff --git a/bigbluebutton-html5/imports/ui/components/nav-bar/component.jsx b/bigbluebutton-html5/imports/ui/components/nav-bar/component.jsx index fb8ae22b3a..bc0bc62eae 100755 --- a/bigbluebutton-html5/imports/ui/components/nav-bar/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/nav-bar/component.jsx @@ -16,6 +16,7 @@ import { styles } from './styles.scss'; import Button from '../button/component'; import RecordingIndicator from './recording-indicator/component'; import SettingsDropdownContainer from './settings-dropdown/container'; +import { Session } from 'meteor/session'; const intlMessages = defineMessages({ toggleUserListLabel: { @@ -109,7 +110,12 @@ class NavBar extends Component { } handleToggleUserList() { - this.props.toggleUserList(); + Session.set( + 'openPanel', + Session.get('openPanel') === 'userlist' + ? '' + : 'userlist', + ); } inviteUserToBreakout(breakout) { diff --git a/bigbluebutton-html5/imports/ui/components/panel-manager/component.jsx b/bigbluebutton-html5/imports/ui/components/panel-manager/component.jsx new file mode 100644 index 0000000000..7dd6c99a1e --- /dev/null +++ b/bigbluebutton-html5/imports/ui/components/panel-manager/component.jsx @@ -0,0 +1,159 @@ +import React, { Component } from 'react'; +import BreakoutRoomContainer from '/imports/ui/components/breakout-room/container'; +import UserListContainer from '/imports/ui/components/user-list/container'; +import ChatContainer from '/imports/ui/components/chat/container'; +import PollContainer from '/imports/ui/components/poll/container'; +import { defineMessages, injectIntl } from 'react-intl'; +import Resizable from 're-resizable'; +import { styles } from '/imports/ui/components/app/styles'; +import cx from 'classnames'; + +const intlMessages = defineMessages({ + chatLabel: { + id: 'app.chat.label', + description: 'Aria-label for Chat Section', + }, + userListLabel: { + id: 'app.userList.label', + description: 'Aria-label for Userlist Nav', + }, +}); + +class PanelManager extends Component { + constructor() { + super(); + } + + renderUserList() { + const { + intl, + } = this.props; + + const userListStyle = {}; + + return ( + <div + className={cx(styles.userList, userListStyle)} + aria-label={intl.formatMessage(intlMessages.userListLabel)} + > + <UserListContainer /> + </div> + ); + } + + renderUserListResizable() { + // Variables for resizing user-list. + const USERLIST_MIN_WIDTH_PX = 150; + const USERLIST_MAX_WIDTH_PX = 240; + const USERLIST_DEFAULT_WIDTH_RELATIVE = 18; + + // decide whether using pixel or percentage unit as a default width for userList + const USERLIST_DEFAULT_WIDTH = (window.innerWidth * (USERLIST_DEFAULT_WIDTH_RELATIVE / 100.0)) < USERLIST_MAX_WIDTH_PX ? `${USERLIST_DEFAULT_WIDTH_RELATIVE}%` : USERLIST_MAX_WIDTH_PX; + + const resizableEnableOptions = { + top: false, + right: true, + bottom: false, + left: false, + topRight: false, + bottomRight: false, + bottomLeft: false, + topLeft: false, + }; + + return ( + <Resizable + defaultSize={{ width: USERLIST_DEFAULT_WIDTH }} + minWidth={USERLIST_MIN_WIDTH_PX} + maxWidth={USERLIST_MAX_WIDTH_PX} + ref={(node) => { this.resizableUserList = node; }} + className={styles.resizableUserList} + enable={resizableEnableOptions} + > + {this.renderUserList()} + </Resizable> + ); + } + + renderChat() { + const { intl } = this.props; + + return ( + <section + className={styles.chat} + aria-label={intl.formatMessage(intlMessages.chatLabel)} + > + <ChatContainer /> + </section> + ); + } + + renderChatResizable() { + // Variables for resizing chat. + const CHAT_MIN_WIDTH = '10%'; + const CHAT_MAX_WIDTH = '25%'; + const CHAT_DEFAULT_WIDTH = '15%'; + + const resizableEnableOptions = { + top: false, + right: true, + bottom: false, + left: false, + topRight: false, + bottomRight: false, + bottomLeft: false, + topLeft: false, + }; + + return ( + <Resizable + defaultSize={{ width: CHAT_DEFAULT_WIDTH }} + minWidth={CHAT_MIN_WIDTH} + maxWidth={CHAT_MAX_WIDTH} + ref={(node) => { this.resizableChat = node; }} + className={styles.resizableChat} + enable={resizableEnableOptions} + > + {this.renderChat()} + </Resizable> + ); + } + + renderPoll() { + return ( + <div className={styles.poll}> + <PollContainer /> + </div> + ); + } + + renderBreakoutRoom() { + return ( + <div className={styles.breakoutRoom}> + <BreakoutRoomContainer /> + </div> + ); + } + + render() { + switch (this.props.openPanel) { + case 'chat': return [ + this.renderUserListResizable(), + this.renderChatResizable(), + ]; + case 'poll': return [ + this.renderUserListResizable(), + this.renderPoll(), + ]; + case 'breakoutroom': return [ + this.renderUserListResizable(), + this.renderBreakoutRoom(), + ]; + case 'userlist': return this.renderUserListResizable(); + default: break; + } + return null; + } +} + +export default injectIntl(PanelManager); diff --git a/bigbluebutton-html5/imports/ui/components/poll/component.jsx b/bigbluebutton-html5/imports/ui/components/poll/component.jsx index e4377ba24c..e28ce86bdf 100644 --- a/bigbluebutton-html5/imports/ui/components/poll/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/poll/component.jsx @@ -248,9 +248,7 @@ class Poll extends Component { aria-label={intl.formatMessage(intlMessages.hidePollDesc)} className={styles.hideBtn} onClick={() => { - Session.set('isPollOpen', false); - Session.set('forcePollOpen', true); - Session.set('isUserListOpen', true); + Session.set('openPanel', 'userlist'); }} /> @@ -260,9 +258,8 @@ class Poll extends Component { if (currentPoll) { stopPoll(); } - Session.set('isPollOpen', false); + Session.set('openPanel', 'userlist'); Session.set('forcePollOpen', false); - Session.set('isUserListOpen', true); }} className={styles.closeBtn} icon="close" diff --git a/bigbluebutton-html5/imports/ui/components/poll/live-result/component.jsx b/bigbluebutton-html5/imports/ui/components/poll/live-result/component.jsx index aa614df8ce..ed5ff11b70 100644 --- a/bigbluebutton-html5/imports/ui/components/poll/live-result/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/poll/live-result/component.jsx @@ -117,8 +117,7 @@ class LiveResult extends Component { onClick={() => { publishPoll(); stopPoll(); - Session.set('isUserListOpen', true); - Session.set('isPollOpen', false); + Session.set('openPanel', 'userlist'); Session.set('forcePollOpen', false); }} label={intl.formatMessage(intlMessages.publishLabel)} diff --git a/bigbluebutton-html5/imports/ui/components/user-list/chat-list-item/component.jsx b/bigbluebutton-html5/imports/ui/components/user-list/chat-list-item/component.jsx index 59231a6409..13faf278e8 100644 --- a/bigbluebutton-html5/imports/ui/components/user-list/chat-list-item/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/user-list/chat-list-item/component.jsx @@ -73,13 +73,12 @@ const ChatListItem = (props) => { tabIndex={tabIndex} accessKey={isPublicChat(chat) ? TOGGLE_CHAT_PUB_AK : null} onClick={() => { - toggleChatOpen(); + Session.set( +'openPanel', + Session.get('openPanel') === 'chat' && Session.get('idChatOpen') === chat.id + ? 'userlist' : 'chat', + ); Session.set('idChatOpen', chat.id); - - if (Session.equals('isPollOpen', true)) { - Session.set('isPollOpen', false); - Session.set('forcePollOpen', true); - } }} id="chat-toggle-button" aria-label={isPublicChat(chat) ? intl.formatMessage(intlMessages.titlePublic) : chat.name} diff --git a/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/breakout-room/component.jsx b/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/breakout-room/component.jsx index b0df572d51..a7784fb50b 100644 --- a/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/breakout-room/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/breakout-room/component.jsx @@ -12,10 +12,12 @@ const intlMessages = defineMessages({ }, }); const toggleBreakoutPanel = () => { - const breakoutPanelState = Session.get('breakoutRoomIsOpen'); - Session.set('breakoutRoomIsOpen', !breakoutPanelState); - Session.set('isChatOpen', false); - Session.set('isPollOpen', false); + Session.set( + 'openPanel', + Session.get('openPanel') === 'breakoutroom' + ? 'userlist' + : 'breakoutroom', + ); }; const BreakoutRoomItem = ({ diff --git a/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/user-participants/user-list-item/user-dropdown/component.jsx b/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/user-participants/user-list-item/user-dropdown/component.jsx index ccb9aa475b..350bcfa3e5 100755 --- a/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/user-participants/user-list-item/user-dropdown/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/user-participants/user-list-item/user-dropdown/component.jsx @@ -236,12 +236,8 @@ class UserDropdown extends Component { intl.formatMessage(messages.ChatLabel), () => { getGroupChatPrivate(currentUser, user); - if (Session.equals('isPollOpen', true)) { - Session.set('isPollOpen', false); - Session.set('forcePollOpen', true); - } + Session.set('openPanel', 'chat'); Session.set('idChatOpen', user.id); - Session.set('isChatOpen', true); }, 'chat', )); diff --git a/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/user-polls/component.jsx b/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/user-polls/component.jsx index 1d9098daea..5c061aac50 100644 --- a/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/user-polls/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/user-polls/component.jsx @@ -41,12 +41,12 @@ class UserPolls extends Component { tabIndex={0} className={styles.pollLink} onClick={() => { - Session.set('isChatOpen', false); - Session.set('breakoutRoomIsOpen', false); - - return Session.equals('isPollOpen', true) - ? Session.set('isPollOpen', false) - : Session.set('isPollOpen', true); + Session.set( +'openPanel', + Session.get('openPanel') === 'poll' + ? 'userlist' + : 'poll', + ); }} > <Icon iconName="polling" className={styles.icon} /> -- GitLab