diff --git a/bigbluebutton-html5/imports/ui/components/actions-bar/create-breakout-room/component.jsx b/bigbluebutton-html5/imports/ui/components/actions-bar/create-breakout-room/component.jsx index 9fdbac53d2b3b71eb9002fde0fc9bb73e79cd266..240bc3c1f67235c1fca8c1c6d22e83a3ccce134c 100644 --- a/bigbluebutton-html5/imports/ui/components/actions-bar/create-breakout-room/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/actions-bar/create-breakout-room/component.jsx @@ -1,11 +1,13 @@ import React, { Component } from 'react'; -import Modal from '/imports/ui/components/modal/fullscreen/component'; import { defineMessages, injectIntl } from 'react-intl'; import _ from 'lodash'; +import cx from 'classnames'; +import { Session } from 'meteor/session'; +import Modal from '/imports/ui/components/modal/fullscreen/component'; +import { withModalMounter } from '/imports/ui/components/modal/service'; import HoldButton from '/imports/ui/components/presentation/presentation-toolbar/zoom-tool/holdButton/component'; import { styles } from './styles'; import Icon from '../../icon/component'; -import cx from 'classnames'; const intlMessages = defineMessages({ breakoutRoomTitle: { @@ -20,6 +22,10 @@ const intlMessages = defineMessages({ id: 'app.createBreakoutRoom.confirm', description: 'confirm button label', }, + dismissLabel: { + id: 'app.presentationUploder.dismissLabel', + description: 'used in the button that close modal', + }, numberOfRooms: { id: 'app.createBreakoutRoom.numberOfRooms', description: 'number of rooms label', @@ -44,6 +50,10 @@ const intlMessages = defineMessages({ id: 'app.createBreakoutRoom.room', description: 'Room label', }, + leastOneWarnBreakout: { + id: 'app.createBreakoutRoom.leastOneWarnBreakout', + description: 'warn message label', + }, notAssigned: { id: 'app.createBreakoutRoom.notAssigned', description: 'Not assigned label', @@ -68,6 +78,7 @@ class BreakoutRoom extends Component { this.renderRoomsGrid = this.renderRoomsGrid.bind(this); this.renderBreakoutForm = this.renderBreakoutForm.bind(this); this.renderFreeJoinCheck = this.renderFreeJoinCheck.bind(this); + this.handleDismiss = this.handleDismiss.bind(this); this.state = { numberOfRooms: MIN_BREAKOUT_ROOMS, @@ -75,6 +86,8 @@ class BreakoutRoom extends Component { users: [], durationTime: 1, freeJoin: false, + preventClosing: true, + valid: true, }; } @@ -96,6 +109,11 @@ class BreakoutRoom extends Component { intl, } = this.props; + if (this.state.users.length === this.getUserByRoom(0).length) { + this.setState({ valid: false }); + return; + } + this.setState({ preventClosing: false }); const { numberOfRooms, durationTime } = this.state; const rooms = _.range(1, numberOfRooms + 1).map(value => ({ users: this.getUserByRoom(value).map(u => u.userId), @@ -108,6 +126,7 @@ class BreakoutRoom extends Component { })); createBreakoutRoom(rooms, durationTime, this.state.freeJoin); + Session.set('isUserListOpen', true); } setRoomUsers() { @@ -131,6 +150,18 @@ class BreakoutRoom extends Component { return this.state.users.filter(user => user.room === room); } + handleDismiss() { + const { mountModal } = this.props; + + return new Promise((resolve) => { + mountModal(null); + + this.setState({ + preventClosing: false, + }, resolve); + }); + } + resetUserWhenRoomsChange(rooms) { const { users } = this.state; const filtredUsers = users.filter(u => u.room > rooms); @@ -177,7 +208,7 @@ class BreakoutRoom extends Component { return ( <div className={styles.boxContainer}> - <label htmlFor="BreakoutRoom"> + <label htmlFor="BreakoutRoom" className={!this.state.valid ? styles.changeToWarn : null}> <p className={styles.freeJoinLabel} > @@ -186,11 +217,14 @@ class BreakoutRoom extends Component { <div className={styles.breakoutBox} onDrop={drop(0)} onDragOver={allowDrop} > {this.renderUserItemByRoom(0)} </div> + <span className={this.state.valid ? styles.dontShow : styles.leastOneWarn} > + {intl.formatMessage(intlMessages.leastOneWarnBreakout)} + </span> </label> { _.range(1, this.state.numberOfRooms + 1).map(value => ( - <label htmlFor="BreakoutRoom"> + <label htmlFor="BreakoutRoom" key={`room-${value}`}> <p className={styles.freeJoinLabel} > @@ -282,6 +316,10 @@ class BreakoutRoom extends Component { const dragStart = (ev) => { ev.dataTransfer.setData('text', ev.target.id); this.setState({ seletedId: ev.target.id }); + + if (!this.state.valid) { + this.setState({ valid: true }); + } }; const dragEnd = (ev) => { @@ -292,6 +330,7 @@ class BreakoutRoom extends Component { .map(user => ( <p id={user.userId} + key={user.userId} className={cx( styles.roomUserItem, this.state.seletedId === user.userId ? styles.selectedItem : null, @@ -317,6 +356,11 @@ class BreakoutRoom extends Component { callback: this.onCreateBreakouts, } } + dismiss={{ + callback: this.handleDismiss, + label: intl.formatMessage(intlMessages.dismissLabel), + }} + preventClosing={this.state.preventClosing} > <div className={styles.content}> <p className={styles.subTitle}> @@ -331,4 +375,4 @@ class BreakoutRoom extends Component { } } -export default injectIntl(BreakoutRoom); +export default withModalMounter(injectIntl(BreakoutRoom)); diff --git a/bigbluebutton-html5/imports/ui/components/actions-bar/create-breakout-room/styles.scss b/bigbluebutton-html5/imports/ui/components/actions-bar/create-breakout-room/styles.scss index 6aec3714653dacefabf470b18f1765ceab35379f..fded63ce5dc8bd0e16a1398de10a7778872911df 100644 --- a/bigbluebutton-html5/imports/ui/components/actions-bar/create-breakout-room/styles.scss +++ b/bigbluebutton-html5/imports/ui/components/actions-bar/create-breakout-room/styles.scss @@ -98,14 +98,25 @@ input[type="number"]::-webkit-outer-spin-button, input[type="number"]::-webkit-i display: grid; grid-template-columns: 1fr 1fr 1fr; grid-template-rows: 33% 33% 33%; - grid-gap: 1rem; + grid-gap: 1.5rem 1rem; +} + +.changeToWarn { + position: relative; + & > .breakoutBox { + border-color: var(--color-danger) !important; + } + + & > .freeJoinLabel { + color: var(--color-danger); + } } .breakoutBox { @include scrollbox-vertical(); width: 100%; height: 80%; - min-height: 5rem; + min-height: 4rem; max-height: 8rem; border: 1px solid var(--color-gray-lighter); border-radius: var(--border-radius); @@ -116,6 +127,15 @@ input[type="number"]::-webkit-outer-spin-button, input[type="number"]::-webkit-i font-weight: bolder; } +.leastOneWarn { + margin: .25rem; + position: absolute; + font-size: var(--font-size-small); + color: var(--color-danger); + font-weight: 200; + white-space: nowrap; +} + .roomUserItem { width: 11rem; margin: 0; @@ -132,4 +152,8 @@ input[type="number"]::-webkit-outer-spin-button, input[type="number"]::-webkit-i .selectedItem { background-color: var(--color-primary); color: var(--color-white) +} + +.dontShow { + display: none; } \ No newline at end of file diff --git a/bigbluebutton-html5/private/locales/en.json b/bigbluebutton-html5/private/locales/en.json index 08d570800810366faf472d2db05ddb83fcda26f1..93e25afe0f92fb84671dca2d4242e271e6b91559 100755 --- a/bigbluebutton-html5/private/locales/en.json +++ b/bigbluebutton-html5/private/locales/en.json @@ -451,5 +451,6 @@ "app.createBreakoutRoom.endAllBreakouts": "End All Breakout Rooms", "app.createBreakoutRoom.roomName": "{0} (Room - {1})", "app.createBreakoutRoom.freeJoin": "Allow users to choose a breakout room to join", + "app.createBreakoutRoom.leastOneWarnBreakout": "You must place at least one user in a breakout room.", "app.createBreakoutRoom.modalDesc": "Complete the steps below to create rooms in your session, To add participants to a room." }