Merge pull request #20734 from danielpetri1/pass-breakout-pres

feat: Pass a different presentation to each breakout
This commit is contained in:
Anton Georgiev 2024-07-23 11:52:07 -04:00 committed by GitHub
commit b248143cae
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 89 additions and 9 deletions

View File

@ -18,8 +18,11 @@ object BreakoutModel {
captureSlides: Boolean,
captureNotesFilename: String,
captureSlidesFilename: String,
allPages: Boolean,
presId: String,
): BreakoutRoom2x = {
new BreakoutRoom2x(id, externalId, name, parentId, sequence, shortName, isDefaultName, freeJoin, voiceConf, assignedUsers, Vector(), Vector(), None, false, captureNotes, captureSlides, captureNotesFilename, captureSlidesFilename)
new BreakoutRoom2x(id, externalId, name, parentId, sequence, shortName, isDefaultName, freeJoin, voiceConf, assignedUsers, Vector(), Vector(), None, false,
captureNotes, captureSlides, captureNotesFilename, captureSlidesFilename, allPages, presId)
}
}

View File

@ -40,26 +40,30 @@ trait CreateBreakoutRoomsCmdMsgHdlr extends RightsManagementTrait {
}
def processRequest(msg: CreateBreakoutRoomsCmdMsg, state: MeetingState2x): MeetingState2x = {
val presId = getPresentationId(state)
val presSlide = getPresentationSlide(state)
val presId = getPresentationId(state) // The current presentation
val presSlide = getPresentationSlide(state) // The current slide
val parentId = liveMeeting.props.meetingProp.intId
var rooms = new collection.immutable.HashMap[String, BreakoutRoom2x]
var i = 0
for (room <- msg.body.rooms) {
val roomPresId = if (room.presId.isEmpty) presId else room.presId;
i += 1
val (internalId, externalId) = BreakoutRoomsUtil.createMeetingIds(liveMeeting.props.meetingProp.intId, i)
val voiceConf = BreakoutRoomsUtil.createVoiceConfId(liveMeeting.props.voiceProp.voiceConf, i)
val breakout = BreakoutModel.create(parentId, internalId, externalId, room.name, room.sequence, room.shortName,
room.isDefaultName, room.freeJoin, voiceConf, room.users, msg.body.captureNotes,
msg.body.captureSlides, room.captureNotesFilename, room.captureSlidesFilename)
msg.body.captureSlides, room.captureNotesFilename, room.captureSlidesFilename,
room.allPages, roomPresId)
rooms = rooms + (breakout.id -> breakout)
}
for (breakout <- rooms.values.toVector) {
val roomSlides = if (breakout.allPages) -1 else presSlide;
val roomDetail = new BreakoutRoomDetail(
breakout.id, breakout.name,
liveMeeting.props.meetingProp.intId,
@ -72,7 +76,9 @@ trait CreateBreakoutRoomsCmdMsgHdlr extends RightsManagementTrait {
msg.body.durationInMinutes * 60,
liveMeeting.props.password.moderatorPass,
liveMeeting.props.password.viewerPass,
presId, presSlide, msg.body.record,
breakout.presId,
roomSlides,
msg.body.record,
liveMeeting.props.breakoutProps.privateChatEnabled,
breakout.captureNotes,
breakout.captureSlides,

View File

@ -19,6 +19,8 @@ case class BreakoutRoom2x(
captureSlides: Boolean,
captureNotesFilename: String,
captureSlidesFilename: String,
allPages: Boolean,
presId: String,
) {
}

View File

@ -71,7 +71,7 @@ case class BreakoutRoomDetail(
object CreateBreakoutRoomsCmdMsg { val NAME = "CreateBreakoutRoomsCmdMsg" }
case class CreateBreakoutRoomsCmdMsg(header: BbbClientMsgHeader, body: CreateBreakoutRoomsCmdMsgBody) extends StandardMsg
case class CreateBreakoutRoomsCmdMsgBody(meetingId: String, durationInMinutes: Int, record: Boolean, captureNotes: Boolean, captureSlides: Boolean, rooms: Vector[BreakoutRoomMsgBody], sendInviteToModerators: Boolean)
case class BreakoutRoomMsgBody(name: String, sequence: Int, shortName: String, captureNotesFilename: String, captureSlidesFilename: String, isDefaultName: Boolean, freeJoin: Boolean, users: Vector[String])
case class BreakoutRoomMsgBody(name: String, sequence: Int, shortName: String, captureNotesFilename: String, captureSlidesFilename: String, isDefaultName: Boolean, freeJoin: Boolean, users: Vector[String], allPages: Boolean, presId: String)
// Sent by user to request ending all the breakout rooms
object EndAllBreakoutRoomsMsg { val NAME = "EndAllBreakoutRoomsMsg" }

View File

@ -94,6 +94,7 @@ public class PresentationUrlDownloadService {
}, 5, TimeUnit.SECONDS);
}
// A negative presentationSlide indicates the entire presentation deck should be used.
private void extractPage(final String sourceMeetingId, final String presentationId,
final Integer presentationSlide, final String destinationMeetingId) {
@ -146,7 +147,7 @@ public class PresentationUrlDownloadService {
+ newFilename;
File newPresentation = new File(newFilePath);
if (sourcePresentationFile.getName().toLowerCase().endsWith("pdf")) {
if (sourcePresentationFile.getName().toLowerCase().endsWith("pdf") && presentationSlide >= 0) {
pageExtractor.extractPage(sourcePresentationFile, new File(
newFilePath), presentationSlide);
} else {

View File

@ -181,12 +181,17 @@ const intlMessages = defineMessages({
id: 'app.createBreakoutRoom.sendInvitationToMods',
description: 'label for checkbox send invitation to moderators',
},
currentSlide: {
id: 'app.createBreakoutRoom.currentSlideLabel',
description: 'label for current slide',
},
});
const BREAKOUT_LIM = Meteor.settings.public.app.breakouts.breakoutRoomLimit;
const MIN_BREAKOUT_ROOMS = 2;
const MAX_BREAKOUT_ROOMS = BREAKOUT_LIM > MIN_BREAKOUT_ROOMS ? BREAKOUT_LIM : MIN_BREAKOUT_ROOMS;
const MIN_BREAKOUT_TIME = 5;
const CURRENT_SLIDE_PREFIX = 'current-';
const propTypes = {
intl: PropTypes.shape({
@ -244,6 +249,7 @@ class BreakoutRoom extends PureComponent {
this.removeRoomUsers = this.removeRoomUsers.bind(this);
this.renderErrorMessages = this.renderErrorMessages.bind(this);
this.onUpdateBreakouts = this.onUpdateBreakouts.bind(this);
this.getRoomPresentation = this.getRoomPresentation.bind(this);
this.state = {
numberOfRooms: MIN_BREAKOUT_ROOMS,
@ -266,6 +272,7 @@ class BreakoutRoom extends PureComponent {
durationIsValid: true,
breakoutJoinedUsers: null,
enableUnassingUsers: null,
roomPresentations: [],
};
this.btnLevelId = uniqueId('btn-set-level-');
@ -503,6 +510,8 @@ class BreakoutRoom extends PureComponent {
isDefaultName: !this.hasNameChanged(seq),
freeJoin,
sequence: seq,
allPages: !this.getRoomPresentation(seq).startsWith(CURRENT_SLIDE_PREFIX),
presId: this.getRoomPresentation(seq).replace(CURRENT_SLIDE_PREFIX, ''),
}));
createBreakoutRoom(rooms, durationTime, record, captureNotes, captureSlides, inviteMods);
@ -688,6 +697,15 @@ class BreakoutRoom extends PureComponent {
});
}
getRoomPresentation(position) {
const { roomPresentations } = this.state;
const { presentations } = this.props;
const currentPresentation = presentations.find((presentation) => presentation.current);
return roomPresentations[position] || `${CURRENT_SLIDE_PREFIX}${currentPresentation?.id}`;
}
getFullName(position) {
const { meetingName } = this.props;
@ -909,11 +927,12 @@ class BreakoutRoom extends PureComponent {
}
renderRoomsGrid() {
const { intl, isUpdate } = this.props;
const { intl, isUpdate, presentations } = this.props;
const {
leastOneUserIsValid,
numberOfRooms,
roomNamesChanged,
roomPresentations,
} = this.state;
const rooms = (numberOfRooms > MAX_BREAKOUT_ROOMS
@ -941,6 +960,17 @@ class BreakoutRoom extends PureComponent {
});
};
const changeRoomPresentation = (position) => (ev) => {
const newRoomsPresentations = [...roomPresentations];
newRoomsPresentations[position] = ev.target.value;
this.setState({
roomPresentations: newRoomsPresentations,
});
};
const currentPresentation = presentations.find((presentation) => presentation.current);
return (
<Styled.BoxContainer key="rooms-grid-" ref={(r) => { this.listOfUsers = r; }} data-test="roomGrid">
{
@ -963,6 +993,31 @@ class BreakoutRoom extends PureComponent {
{intl.formatMessage(intlMessages.roomNameInputDesc)}
</div>
</Styled.FreeJoinLabel>
{ presentations.length > 0 ? (
<Styled.BreakoutSlideLabel>
<Styled.InputRooms
value={this.getRoomPresentation(value)}
onChange={changeRoomPresentation(value)}
valid
>
{ currentPresentation?.id ? (
<option key="current-slide" value={`${CURRENT_SLIDE_PREFIX}${currentPresentation.id}`}>
{intl.formatMessage(intlMessages.currentSlide)}
</option>
) : null }
{
presentations.map((presentation) => (
<option
key={presentation.id}
value={presentation.id}
>
{presentation.name}
</option>
))
}
</Styled.InputRooms>
</Styled.BreakoutSlideLabel>
) : null }
<Styled.BreakoutBox id={`breakoutBox-${value}`} onDrop={drop(value)} onDragOver={allowDrop} tabIndex={0}>
{this.renderUserItemByRoom(value)}
</Styled.BreakoutBox>

View File

@ -3,6 +3,7 @@ import { withTracker } from 'meteor/react-meteor-data';
import ActionsBarService from '/imports/ui/components/actions-bar/service';
import BreakoutRoomService from '/imports/ui/components/breakout-room/service';
import CreateBreakoutRoomModal from './component';
import Presentations from '/imports/api/presentations';
import { isImportSharedNotesFromBreakoutRoomsEnabled, isImportPresentationWithAnnotationsFromBreakoutRoomsEnabled } from '/imports/ui/services/features';
const METEOR_SETTINGS_APP = Meteor.settings.public.app;
@ -46,4 +47,5 @@ export default withTracker(() => ({
meetingName: ActionsBarService.meetingName(),
amIModerator: ActionsBarService.amIModerator(),
moveUser: ActionsBarService.moveUser,
presentations: Presentations.find({ 'conversion.done': true }).fetch(),
}))(CreateBreakoutRoomContainer);

View File

@ -68,6 +68,15 @@ const FreeJoinLabel = styled.label`
}
`;
const BreakoutSlideLabel = styled.label`
font-size: ${fontSizeSmall};
font-weight: bolder;
display: flex;
align-items: center;
font-size: ${fontSizeSmall};
margin-bottom: 0.2rem;
`
const BreakoutNameInput = styled.input`
width: 100%;
text-align: center;
@ -377,4 +386,5 @@ export default {
SubTitle,
Content,
ContentContainer,
BreakoutSlideLabel,
};

View File

@ -1249,6 +1249,7 @@
"app.createBreakoutRoom.setTimeHigherThanMeetingTimeError": "The breakout rooms duration can't exceed the meeting remaining time.",
"app.createBreakoutRoom.roomNameInputDesc": "Updates breakout room name",
"app.createBreakoutRoom.movedUserLabel": "Moved {0} to room {1}",
"app.createBreakoutRoom.currentSlideLabel": "Current slide",
"app.updateBreakoutRoom.modalDesc": "To update or invite a user, simply drag them into the desired room.",
"app.updateBreakoutRoom.cancelLabel": "Cancel",
"app.updateBreakoutRoom.title": "Update Breakout Rooms",