Merge pull request #6404 from Tainan404/issue-6261
Add mobile version to sort user on create breakout rooms
This commit is contained in:
commit
85d2e162c5
@ -2,10 +2,13 @@ import React, { Component } from 'react';
|
||||
import { defineMessages, injectIntl } from 'react-intl';
|
||||
import _ from 'lodash';
|
||||
import cx from 'classnames';
|
||||
import browser from 'browser-detect';
|
||||
import Button from '/imports/ui/components/button/component';
|
||||
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 SortList from './sort-user-list/component';
|
||||
import { styles } from './styles';
|
||||
import Icon from '../../icon/component';
|
||||
|
||||
@ -58,6 +61,22 @@ const intlMessages = defineMessages({
|
||||
id: 'app.createBreakoutRoom.notAssigned',
|
||||
description: 'Not assigned label',
|
||||
},
|
||||
breakoutRoomLabel: {
|
||||
id: 'app.createBreakoutRoom.breakoutRoomLabel',
|
||||
description: 'breakout room label',
|
||||
},
|
||||
addParticipantLabel: {
|
||||
id: 'app.createBreakoutRoom.addParticipantLabel',
|
||||
description: 'add Participant label',
|
||||
},
|
||||
nextLabel: {
|
||||
id: 'app.createBreakoutRoom.nextLabel',
|
||||
description: 'Next label',
|
||||
},
|
||||
backLabel: {
|
||||
id: 'app.audio.backLabel',
|
||||
description: 'Back label',
|
||||
},
|
||||
});
|
||||
const MIN_BREAKOUT_ROOMS = 2;
|
||||
const MAX_BREAKOUT_ROOMS = 8;
|
||||
@ -78,6 +97,11 @@ class BreakoutRoom extends Component {
|
||||
this.renderRoomsGrid = this.renderRoomsGrid.bind(this);
|
||||
this.renderBreakoutForm = this.renderBreakoutForm.bind(this);
|
||||
this.renderFreeJoinCheck = this.renderFreeJoinCheck.bind(this);
|
||||
this.renderRoomSortList = this.renderRoomSortList.bind(this);
|
||||
this.renderDesktop = this.renderDesktop.bind(this);
|
||||
this.renderMobile = this.renderMobile.bind(this);
|
||||
this.renderButtonSetLevel = this.renderButtonSetLevel.bind(this);
|
||||
this.renderSelectUserScreen = this.renderSelectUserScreen.bind(this);
|
||||
this.handleDismiss = this.handleDismiss.bind(this);
|
||||
|
||||
this.state = {
|
||||
@ -86,6 +110,8 @@ class BreakoutRoom extends Component {
|
||||
users: [],
|
||||
durationTime: 1,
|
||||
freeJoin: false,
|
||||
formFillLevel: 1,
|
||||
roomSelected: 0,
|
||||
preventClosing: true,
|
||||
valid: true,
|
||||
};
|
||||
@ -108,8 +134,12 @@ class BreakoutRoom extends Component {
|
||||
meetingName,
|
||||
intl,
|
||||
} = this.props;
|
||||
const {
|
||||
users,
|
||||
freeJoin,
|
||||
} = this.state;
|
||||
|
||||
if (this.state.users.length === this.getUserByRoom(0).length) {
|
||||
if (users.length === this.getUserByRoom(0).length) {
|
||||
this.setState({ valid: false });
|
||||
return;
|
||||
}
|
||||
@ -121,11 +151,11 @@ class BreakoutRoom extends Component {
|
||||
0: meetingName,
|
||||
1: value,
|
||||
}),
|
||||
freeJoin: this.state.freeJoin,
|
||||
freeJoin,
|
||||
sequence: value,
|
||||
}));
|
||||
|
||||
createBreakoutRoom(rooms, durationTime, this.state.freeJoin);
|
||||
createBreakoutRoom(rooms, durationTime, freeJoin);
|
||||
Session.set('isUserListOpen', true);
|
||||
}
|
||||
|
||||
@ -147,7 +177,8 @@ class BreakoutRoom extends Component {
|
||||
}
|
||||
|
||||
getUserByRoom(room) {
|
||||
return this.state.users.filter(user => user.room === room);
|
||||
const { users } = this.state;
|
||||
return users.filter(user => user.room === room);
|
||||
}
|
||||
|
||||
handleDismiss() {
|
||||
@ -176,11 +207,13 @@ class BreakoutRoom extends Component {
|
||||
}
|
||||
|
||||
increaseDurationTime() {
|
||||
this.setState({ durationTime: (1 * this.state.durationTime) + 1 });
|
||||
const { durationTime } = this.state;
|
||||
this.setState({ durationTime: (1 * durationTime) + 1 });
|
||||
}
|
||||
|
||||
decreaseDurationTime() {
|
||||
const number = ((1 * this.state.durationTime) - 1);
|
||||
const { durationTime } = this.state;
|
||||
const number = ((1 * durationTime) - 1);
|
||||
this.setState({ durationTime: number < 1 ? 1 : number });
|
||||
}
|
||||
|
||||
@ -194,7 +227,10 @@ class BreakoutRoom extends Component {
|
||||
|
||||
renderRoomsGrid() {
|
||||
const { intl } = this.props;
|
||||
|
||||
const {
|
||||
valid,
|
||||
numberOfRooms,
|
||||
} = this.state;
|
||||
const allowDrop = (ev) => {
|
||||
ev.preventDefault();
|
||||
};
|
||||
@ -208,32 +244,33 @@ class BreakoutRoom extends Component {
|
||||
|
||||
return (
|
||||
<div className={styles.boxContainer}>
|
||||
<label htmlFor="BreakoutRoom" className={!this.state.valid ? styles.changeToWarn : null}>
|
||||
<label htmlFor="BreakoutRoom" className={!valid ? styles.changeToWarn : null}>
|
||||
<p
|
||||
className={styles.freeJoinLabel}
|
||||
>
|
||||
{intl.formatMessage(intlMessages.notAssigned, { 0: this.getUserByRoom(0).length })}
|
||||
</p>
|
||||
<div className={styles.breakoutBox} onDrop={drop(0)} onDragOver={allowDrop} >
|
||||
<div className={styles.breakoutBox} onDrop={drop(0)} onDragOver={allowDrop}>
|
||||
{this.renderUserItemByRoom(0)}
|
||||
</div>
|
||||
<span className={this.state.valid ? styles.dontShow : styles.leastOneWarn} >
|
||||
<span className={valid ? styles.dontShow : styles.leastOneWarn}>
|
||||
{intl.formatMessage(intlMessages.leastOneWarnBreakout)}
|
||||
</span>
|
||||
</label>
|
||||
{
|
||||
_.range(1, this.state.numberOfRooms + 1).map(value =>
|
||||
(
|
||||
<label htmlFor="BreakoutRoom" key={`room-${value}`}>
|
||||
<p
|
||||
className={styles.freeJoinLabel}
|
||||
>
|
||||
{intl.formatMessage(intlMessages.roomLabel, { 0: (value) })}
|
||||
</p>
|
||||
<div className={styles.breakoutBox} onDrop={drop(value)} onDragOver={allowDrop}>
|
||||
{this.renderUserItemByRoom(value)}
|
||||
</div>
|
||||
</label>))
|
||||
_.range(1, numberOfRooms + 1).map(value => (
|
||||
<label htmlFor="BreakoutRoom" key={`room-${value}`}>
|
||||
<p
|
||||
id="BreakoutRoom"
|
||||
className={styles.freeJoinLabel}
|
||||
>
|
||||
{intl.formatMessage(intlMessages.roomLabel, { 0: (value) })}
|
||||
</p>
|
||||
<div className={styles.breakoutBox} onDrop={drop(value)} onDragOver={allowDrop}>
|
||||
{this.renderUserItemByRoom(value)}
|
||||
</div>
|
||||
</label>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
);
|
||||
@ -241,15 +278,19 @@ class BreakoutRoom extends Component {
|
||||
|
||||
renderBreakoutForm() {
|
||||
const { intl } = this.props;
|
||||
|
||||
const {
|
||||
numberOfRooms,
|
||||
durationTime,
|
||||
} = this.state;
|
||||
return (
|
||||
<div className={styles.breakoutSettings}>
|
||||
<label htmlFor="numberOfRooms">
|
||||
<p className={styles.labelText}>{intl.formatMessage(intlMessages.numberOfRooms)}</p>
|
||||
<select
|
||||
id="numberOfRooms"
|
||||
name="numberOfRooms"
|
||||
className={styles.inputRooms}
|
||||
value={this.state.numberOfRooms}
|
||||
value={numberOfRooms}
|
||||
onChange={this.changeNumberOfRooms}
|
||||
>
|
||||
{
|
||||
@ -257,14 +298,14 @@ class BreakoutRoom extends Component {
|
||||
}
|
||||
</select>
|
||||
</label>
|
||||
<label htmlFor="breakoutRoomTime" >
|
||||
<label htmlFor="breakoutRoomTime">
|
||||
<p className={styles.labelText}>{intl.formatMessage(intlMessages.duration)}</p>
|
||||
<div className={styles.durationArea}>
|
||||
<input
|
||||
type="number"
|
||||
className={styles.duration}
|
||||
min={MIN_BREAKOUT_ROOMS}
|
||||
value={this.state.durationTime}
|
||||
value={durationTime}
|
||||
onChange={this.changeDurationTime}
|
||||
/>
|
||||
<span>
|
||||
@ -272,7 +313,7 @@ class BreakoutRoom extends Component {
|
||||
key="decrease-breakout-time"
|
||||
exec={this.decreaseDurationTime}
|
||||
minBound={MIN_BREAKOUT_ROOMS}
|
||||
value={this.state.durationTime}
|
||||
value={durationTime}
|
||||
>
|
||||
<Icon
|
||||
className={styles.iconsColor}
|
||||
@ -297,15 +338,32 @@ class BreakoutRoom extends Component {
|
||||
);
|
||||
}
|
||||
|
||||
renderSelectUserScreen() {
|
||||
const {
|
||||
users,
|
||||
roomSelected,
|
||||
} = this.state;
|
||||
return (
|
||||
<SortList
|
||||
confirm={() => this.setState({ formFillLevel: 2 })}
|
||||
users={users}
|
||||
room={roomSelected}
|
||||
onCheck={this.changeUserRoom}
|
||||
onUncheck={userId => this.changeUserRoom(userId, 0)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
renderFreeJoinCheck() {
|
||||
const { intl } = this.props;
|
||||
const { freeJoin } = this.state;
|
||||
return (
|
||||
<label htmlFor="freeJoinCheckbox" className={styles.freeJoinLabel}>
|
||||
<input
|
||||
type="checkbox"
|
||||
className={styles.freeJoinCheckbox}
|
||||
onChange={this.setFreeJoin}
|
||||
checked={this.state.freeJoin}
|
||||
checked={freeJoin}
|
||||
/>
|
||||
{intl.formatMessage(intlMessages.freeJoinLabel)}
|
||||
</label>
|
||||
@ -313,16 +371,21 @@ class BreakoutRoom extends Component {
|
||||
}
|
||||
|
||||
renderUserItemByRoom(room) {
|
||||
const {
|
||||
valid,
|
||||
seletedId,
|
||||
} = this.state;
|
||||
const dragStart = (ev) => {
|
||||
ev.dataTransfer.setData('text', ev.target.id);
|
||||
this.setState({ seletedId: ev.target.id });
|
||||
|
||||
if (!this.state.valid) {
|
||||
if (!valid) {
|
||||
this.setState({ valid: true });
|
||||
}
|
||||
};
|
||||
|
||||
const dragEnd = (ev) => {
|
||||
|
||||
const dragEnd = () => {
|
||||
this.setState({ seletedId: '' });
|
||||
};
|
||||
|
||||
@ -333,8 +396,8 @@ class BreakoutRoom extends Component {
|
||||
key={user.userId}
|
||||
className={cx(
|
||||
styles.roomUserItem,
|
||||
this.state.seletedId === user.userId ? styles.selectedItem : null,
|
||||
)
|
||||
seletedId === user.userId ? styles.selectedItem : null,
|
||||
)
|
||||
}
|
||||
draggable
|
||||
onDragStart={dragStart}
|
||||
@ -344,8 +407,79 @@ class BreakoutRoom extends Component {
|
||||
</p>));
|
||||
}
|
||||
|
||||
renderRoomSortList() {
|
||||
const { intl } = this.props;
|
||||
const { numberOfRooms } = this.state;
|
||||
const onClick = roomNumber => this.setState({ formFillLevel: 3, roomSelected: roomNumber });
|
||||
return (
|
||||
<div className={styles.listContainer}>
|
||||
<span>
|
||||
{
|
||||
new Array(numberOfRooms).fill(1).map((room, idx) => (
|
||||
<div className={styles.roomItem}>
|
||||
<h2 className={styles.itemTitle}>
|
||||
{intl.formatMessage(intlMessages.breakoutRoomLabel, { 0: idx + 1 })}
|
||||
</h2>
|
||||
<Button
|
||||
className={styles.itemButton}
|
||||
label={intl.formatMessage(intlMessages.addParticipantLabel)}
|
||||
size="lg"
|
||||
ghost
|
||||
color="primary"
|
||||
onClick={() => onClick(idx + 1)}
|
||||
/>
|
||||
</div>
|
||||
))
|
||||
}
|
||||
</span>
|
||||
{this.renderButtonSetLevel(1, intl.formatMessage(intlMessages.backLabel))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
renderDesktop() {
|
||||
return [
|
||||
this.renderBreakoutForm(),
|
||||
this.renderFreeJoinCheck(),
|
||||
this.renderRoomsGrid(),
|
||||
];
|
||||
}
|
||||
|
||||
renderMobile() {
|
||||
const { intl } = this.props;
|
||||
const { formFillLevel } = this.state;
|
||||
if (formFillLevel === 2) {
|
||||
return this.renderRoomSortList();
|
||||
}
|
||||
|
||||
if (formFillLevel === 3) {
|
||||
return this.renderSelectUserScreen();
|
||||
}
|
||||
|
||||
return [
|
||||
this.renderBreakoutForm(),
|
||||
this.renderFreeJoinCheck(),
|
||||
this.renderButtonSetLevel(2, intl.formatMessage(intlMessages.nextLabel)),
|
||||
];
|
||||
}
|
||||
|
||||
renderButtonSetLevel(level, label) {
|
||||
return (
|
||||
<Button
|
||||
color="primary"
|
||||
size="lg"
|
||||
label={label}
|
||||
onClick={() => this.setState({ formFillLevel: level })}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
const { intl } = this.props;
|
||||
const { preventClosing } = this.state;
|
||||
|
||||
const BROWSER_RESULTS = browser();
|
||||
const isMobileBrowser = BROWSER_RESULTS.mobile || BROWSER_RESULTS.os.includes('Android');
|
||||
|
||||
return (
|
||||
<Modal
|
||||
@ -360,17 +494,15 @@ class BreakoutRoom extends Component {
|
||||
callback: this.handleDismiss,
|
||||
label: intl.formatMessage(intlMessages.dismissLabel),
|
||||
}}
|
||||
preventClosing={this.state.preventClosing}
|
||||
preventClosing={preventClosing}
|
||||
>
|
||||
<div className={styles.content}>
|
||||
<p className={styles.subTitle}>
|
||||
{intl.formatMessage(intlMessages.breakoutRoomDesc)}
|
||||
</p>
|
||||
{this.renderBreakoutForm()}
|
||||
{this.renderFreeJoinCheck()}
|
||||
{this.renderRoomsGrid()}
|
||||
{isMobileBrowser ? this.renderMobile() : this.renderDesktop()}
|
||||
</div>
|
||||
</Modal >
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,124 @@
|
||||
import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { defineMessages, injectIntl } from 'react-intl';
|
||||
import Button from '/imports/ui/components/button/component';
|
||||
import { styles } from '../styles';
|
||||
|
||||
const propTypes = {
|
||||
confirm: PropTypes.func.isRequired,
|
||||
users: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||
room: PropTypes.number.isRequired,
|
||||
onCheck: PropTypes.func,
|
||||
onUncheck: PropTypes.func,
|
||||
};
|
||||
|
||||
const defaultProps = {
|
||||
onCheck: () => {},
|
||||
onUncheck: () => {},
|
||||
};
|
||||
|
||||
const intlMessages = defineMessages({
|
||||
breakoutRoomLabel: {
|
||||
id: 'app.createBreakoutRoom.breakoutRoomLabel',
|
||||
description: 'breakout room label',
|
||||
},
|
||||
doneLabel: {
|
||||
id: 'app.createBreakoutRoom.doneLabel',
|
||||
description: 'done label',
|
||||
},
|
||||
});
|
||||
|
||||
class SortUsers extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.setUsers = this.setUsers.bind(this);
|
||||
this.renderUserItem = this.renderUserItem.bind(this);
|
||||
this.onChage = this.onChage.bind(this);
|
||||
|
||||
this.state = {
|
||||
users: [],
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
const { users } = this.props;
|
||||
this.setUsers(users);
|
||||
}
|
||||
|
||||
onChage(userId, room) {
|
||||
const {
|
||||
onCheck,
|
||||
onUncheck,
|
||||
} = this.props;
|
||||
return (ev) => {
|
||||
const check = ev.target.checked;
|
||||
if (check) {
|
||||
return onCheck(userId, room);
|
||||
}
|
||||
return onUncheck(userId, room);
|
||||
};
|
||||
}
|
||||
|
||||
setUsers(users) {
|
||||
this.setState({ users: users.sort((a, b) => a.room - b.room) });
|
||||
}
|
||||
|
||||
renderUserItem() {
|
||||
const { room } = this.props;
|
||||
const { users } = this.state;
|
||||
return users
|
||||
.map((user, idx) => (
|
||||
<div id={user.userId} className={styles.selectUserContainer} key={`breakout-user-${user.userId}`}>
|
||||
<span className={styles.round}>
|
||||
<input
|
||||
type="checkbox"
|
||||
id={`itemId${idx}`}
|
||||
defaultChecked={user.room === room}
|
||||
onChange={this.onChage(user.userId, room)}
|
||||
/>
|
||||
<label htmlFor={`itemId${idx}`}>
|
||||
<input
|
||||
type="checkbox"
|
||||
id={`itemId${idx}`}
|
||||
defaultChecked={user.room === room}
|
||||
onChange={this.onChage(user.userId, room)}
|
||||
/>
|
||||
</label>
|
||||
</span>
|
||||
<span className={styles.textName}>
|
||||
{user.userName}
|
||||
{user.room && !(user.room === room) ? `\t[${user.room}]` : ''}
|
||||
</span>
|
||||
</div>));
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
intl,
|
||||
room,
|
||||
confirm,
|
||||
} = this.props;
|
||||
return (
|
||||
<div className={styles.selectUserScreen}>
|
||||
<header className={styles.header}>
|
||||
<h2 className={styles.title}>
|
||||
{intl.formatMessage(intlMessages.breakoutRoomLabel, { 0: room })}
|
||||
</h2>
|
||||
<Button
|
||||
className={styles.buttonAdd}
|
||||
size="md"
|
||||
label={intl.formatMessage(intlMessages.doneLabel)}
|
||||
color="primary"
|
||||
onClick={confirm}
|
||||
/>
|
||||
</header>
|
||||
{this.renderUserItem()}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
SortUsers.propTypes = propTypes;
|
||||
SortUsers.defaultProps = defaultProps;
|
||||
|
||||
export default injectIntl(SortUsers);
|
@ -154,6 +154,127 @@ input[type="number"]::-webkit-outer-spin-button, input[type="number"]::-webkit-i
|
||||
color: var(--color-white)
|
||||
}
|
||||
|
||||
/* mobile */
|
||||
|
||||
.listContainer {
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.itemTitle {
|
||||
color: var(--color-blue-light);
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.roomItem {
|
||||
margin: 1rem 0 1rem 0;
|
||||
|
||||
}
|
||||
|
||||
.itemButton {
|
||||
padding: 0;
|
||||
outline: none !important;
|
||||
span {
|
||||
color: var(--color-blue-light);
|
||||
}
|
||||
}
|
||||
|
||||
.selectUserScreenContainer {
|
||||
position: fixed;
|
||||
z-index: 1002;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
background-color: rgba(0, 0, 0, .85);
|
||||
}
|
||||
|
||||
.selectUserScreen {
|
||||
position: fixed;
|
||||
display: block;
|
||||
height: 100vh;
|
||||
width: 100%;
|
||||
background-color: var(--color-white);
|
||||
z-index: 1002;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.header {
|
||||
display: flex;
|
||||
padding: var(--line-height-computed) 0;
|
||||
border-bottom: var(--border-size) solid var(--color-gray-lighter);
|
||||
margin: 0 1rem 0 1rem;
|
||||
}
|
||||
|
||||
.title {
|
||||
@extend %text-elipsis;
|
||||
align-content: flex-end;
|
||||
flex: 1;
|
||||
margin: 0;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.buttonAdd {
|
||||
flex: 0 1 35%;
|
||||
}
|
||||
|
||||
.selectUserContainer {
|
||||
margin: 1.5rem 1rem;
|
||||
}
|
||||
|
||||
.textName {
|
||||
@extend %text-elipsis;
|
||||
margin-left: 1.5rem;
|
||||
}
|
||||
|
||||
.round {
|
||||
position: relative;
|
||||
|
||||
& label {
|
||||
margin-top: -10px;
|
||||
background-color: #fff;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 50%;
|
||||
cursor: pointer;
|
||||
height: 28px;
|
||||
left: 0;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
width: 28px;
|
||||
}
|
||||
|
||||
& label:after {
|
||||
border: 2px solid #fff;
|
||||
border-top: none;
|
||||
border-right: none;
|
||||
content: "";
|
||||
height: 6px;
|
||||
left: 7px;
|
||||
opacity: 0;
|
||||
position: absolute;
|
||||
top: 8px;
|
||||
transform: rotate(-45deg);
|
||||
width: 12px;
|
||||
}
|
||||
|
||||
& input[type="checkbox"] {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
& input[type="checkbox"]:checked + label {
|
||||
background-color: #66bb6a;
|
||||
border-color: #66bb6a;
|
||||
}
|
||||
|
||||
& input[type="checkbox"]:checked + label:after {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.dontShow {
|
||||
display: none;
|
||||
}
|
@ -8,6 +8,7 @@
|
||||
outline: none;
|
||||
@include mq($small-only) {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -458,6 +458,7 @@
|
||||
"app.videoDock.webcamUnfocusLabel": "Unfocus",
|
||||
"app.videoDock.webcamUnfocusDesc": "Unfocus the selected webcam",
|
||||
"app.createBreakoutRoom.title": "Breakout Rooms",
|
||||
"app.createBreakoutRoom.breakoutRoomLabel": "Breakout Rooms {0}",
|
||||
"app.createBreakoutRoom.generatingURL": "Generating URL",
|
||||
"app.createBreakoutRoom.generatedURL": "Generated",
|
||||
"app.createBreakoutRoom.duration": "Duration {0}",
|
||||
@ -472,6 +473,9 @@
|
||||
"app.createBreakoutRoom.randomlyAssign": "Randomly Assign",
|
||||
"app.createBreakoutRoom.endAllBreakouts": "End All Breakout Rooms",
|
||||
"app.createBreakoutRoom.roomName": "{0} (Room - {1})",
|
||||
"app.createBreakoutRoom.doneLabel": "Done",
|
||||
"app.createBreakoutRoom.nextLabel": "Next",
|
||||
"app.createBreakoutRoom.addParticipantLabel": "+ Add participant",
|
||||
"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."
|
||||
|
Loading…
Reference in New Issue
Block a user