Merge remote-tracking branch 'origin/update-breakout-duration' into update-breakout-duration
This commit is contained in:
commit
6839a424c1
@ -24,14 +24,14 @@ case class MonitorNumberOfUsersInternalMsg(meetingID: String) extends InMessage
|
|||||||
* Audit message sent to meeting to trigger updating clients of meeting time remaining.
|
* Audit message sent to meeting to trigger updating clients of meeting time remaining.
|
||||||
* @param meetingId
|
* @param meetingId
|
||||||
*/
|
*/
|
||||||
case class SendTimeRemainingAuditInternalMsg(meetingId: String) extends InMessage
|
case class SendTimeRemainingAuditInternalMsg(meetingId: String, timeUpdatedInMinutes: Int) extends InMessage
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parent message sent to breakout rooms to trigger updating clients of meeting time remaining.
|
* Parent message sent to breakout rooms to trigger updating clients of meeting time remaining.
|
||||||
* @param meetingId
|
* @param meetingId
|
||||||
* @param timeLeftInSec
|
* @param timeLeftInSec
|
||||||
*/
|
*/
|
||||||
case class SendBreakoutTimeRemainingInternalMsg(meetingId: String, timeLeftInSec: Long) extends InMessage
|
case class SendBreakoutTimeRemainingInternalMsg(meetingId: String, timeLeftInSec: Long, timeUpdatedInMinutes: Int) extends InMessage
|
||||||
|
|
||||||
case class SendRecordingTimerInternalMsg(meetingId: String) extends InMessage
|
case class SendRecordingTimerInternalMsg(meetingId: String) extends InMessage
|
||||||
|
|
||||||
@ -76,12 +76,12 @@ case class BreakoutRoomUsersUpdateInternalMsg(parentId: String, breakoutId: Stri
|
|||||||
case class EndBreakoutRoomInternalMsg(parentId: String, breakoutId: String, reason: String) extends InMessage
|
case class EndBreakoutRoomInternalMsg(parentId: String, breakoutId: String, reason: String) extends InMessage
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sent by parent meeting to breakout room to extend time.
|
* Sent by parent meeting to breakout room to update time.
|
||||||
* @param parentId
|
* @param parentId
|
||||||
* @param breakoutId
|
* @param breakoutId
|
||||||
* @param extendTimeInMinutes
|
* @param durationInSeconds
|
||||||
*/
|
*/
|
||||||
case class ExtendBreakoutRoomTimeInternalMsg(parentId: String, breakoutId: String, extendTimeInMinutes: Int) extends InMessage
|
case class UpdateBreakoutRoomTimeInternalMsg(parentId: String, breakoutId: String, durationInSeconds: Int) extends InMessage
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sent by parent meeting to breakout room to extend time.
|
* Sent by parent meeting to breakout room to extend time.
|
||||||
|
@ -22,7 +22,7 @@ object BreakoutModel {
|
|||||||
|
|
||||||
case class BreakoutModel(
|
case class BreakoutModel(
|
||||||
startedOn: Option[Long],
|
startedOn: Option[Long],
|
||||||
durationInMinutes: Int,
|
durationInSeconds: Int,
|
||||||
rooms: Map[String, BreakoutRoom2x]
|
rooms: Map[String, BreakoutRoom2x]
|
||||||
) {
|
) {
|
||||||
|
|
||||||
@ -78,8 +78,8 @@ case class BreakoutModel(
|
|||||||
copy(rooms = rooms - id)
|
copy(rooms = rooms - id)
|
||||||
}
|
}
|
||||||
|
|
||||||
def extendTime(timeToExtendInMinutes: Int): BreakoutModel = {
|
def setTime(newDurationInSeconds: Int): BreakoutModel = {
|
||||||
copy(durationInMinutes = durationInMinutes + timeToExtendInMinutes)
|
copy(durationInSeconds = newDurationInSeconds)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -10,14 +10,14 @@ trait BreakoutApp2x extends BreakoutRoomCreatedMsgHdlr
|
|||||||
with BreakoutRoomUsersUpdateMsgHdlr
|
with BreakoutRoomUsersUpdateMsgHdlr
|
||||||
with CreateBreakoutRoomsCmdMsgHdlr
|
with CreateBreakoutRoomsCmdMsgHdlr
|
||||||
with EndAllBreakoutRoomsMsgHdlr
|
with EndAllBreakoutRoomsMsgHdlr
|
||||||
with ExtendBreakoutRoomsTimeMsgHdlr
|
with UpdateBreakoutRoomsTimeMsgHdlr
|
||||||
with SendMessageToAllBreakoutRoomsMsgHdlr
|
with SendMessageToAllBreakoutRoomsMsgHdlr
|
||||||
with SendMessageToBreakoutRoomInternalMsgHdlr
|
with SendMessageToBreakoutRoomInternalMsgHdlr
|
||||||
with RequestBreakoutJoinURLReqMsgHdlr
|
with RequestBreakoutJoinURLReqMsgHdlr
|
||||||
with SendBreakoutUsersUpdateMsgHdlr
|
with SendBreakoutUsersUpdateMsgHdlr
|
||||||
with TransferUserToMeetingRequestHdlr
|
with TransferUserToMeetingRequestHdlr
|
||||||
with EndBreakoutRoomInternalMsgHdlr
|
with EndBreakoutRoomInternalMsgHdlr
|
||||||
with ExtendBreakoutRoomTimeInternalMsgHdlr
|
with UpdateBreakoutRoomTimeInternalMsgHdlr
|
||||||
with BreakoutRoomEndedInternalMsgHdlr {
|
with BreakoutRoomEndedInternalMsgHdlr {
|
||||||
|
|
||||||
this: MeetingActor =>
|
this: MeetingActor =>
|
||||||
|
@ -61,7 +61,7 @@ trait CreateBreakoutRoomsCmdMsgHdlr extends RightsManagementTrait {
|
|||||||
breakout.freeJoin,
|
breakout.freeJoin,
|
||||||
liveMeeting.props.voiceProp.dialNumber,
|
liveMeeting.props.voiceProp.dialNumber,
|
||||||
breakout.voiceConf,
|
breakout.voiceConf,
|
||||||
msg.body.durationInMinutes,
|
msg.body.durationInMinutes * 60,
|
||||||
liveMeeting.props.password.moderatorPass,
|
liveMeeting.props.password.moderatorPass,
|
||||||
liveMeeting.props.password.viewerPass,
|
liveMeeting.props.password.viewerPass,
|
||||||
presId, presSlide, msg.body.record,
|
presId, presSlide, msg.body.record,
|
||||||
@ -72,7 +72,7 @@ trait CreateBreakoutRoomsCmdMsgHdlr extends RightsManagementTrait {
|
|||||||
outGW.send(event)
|
outGW.send(event)
|
||||||
}
|
}
|
||||||
|
|
||||||
val breakoutModel = new BreakoutModel(None, msg.body.durationInMinutes, rooms)
|
val breakoutModel = new BreakoutModel(None, msg.body.durationInMinutes * 60, rooms)
|
||||||
state.update(Some(breakoutModel))
|
state.update(Some(breakoutModel))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ trait SendBreakoutTimeRemainingInternalMsgHdlr {
|
|||||||
val outGW: OutMsgRouter
|
val outGW: OutMsgRouter
|
||||||
|
|
||||||
def handleSendBreakoutTimeRemainingInternalMsg(msg: SendBreakoutTimeRemainingInternalMsg): Unit = {
|
def handleSendBreakoutTimeRemainingInternalMsg(msg: SendBreakoutTimeRemainingInternalMsg): Unit = {
|
||||||
val event = MsgBuilder.buildMeetingTimeRemainingUpdateEvtMsg(liveMeeting.props.meetingProp.intId, msg.timeLeftInSec.toInt)
|
val event = MsgBuilder.buildMeetingTimeRemainingUpdateEvtMsg(liveMeeting.props.meetingProp.intId, msg.timeLeftInSec.toInt, msg.timeUpdatedInMinutes)
|
||||||
outGW.send(event)
|
outGW.send(event)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,20 +1,20 @@
|
|||||||
package org.bigbluebutton.core.apps.breakout
|
package org.bigbluebutton.core.apps.breakout
|
||||||
|
|
||||||
import org.bigbluebutton.core.api.{ ExtendBreakoutRoomTimeInternalMsg }
|
import org.bigbluebutton.core.api.{ UpdateBreakoutRoomTimeInternalMsg }
|
||||||
import org.bigbluebutton.core.domain.{ MeetingState2x }
|
import org.bigbluebutton.core.domain.{ MeetingState2x }
|
||||||
import org.bigbluebutton.core.running.{ MeetingActor, OutMsgRouter }
|
import org.bigbluebutton.core.running.{ MeetingActor, OutMsgRouter }
|
||||||
|
|
||||||
trait ExtendBreakoutRoomTimeInternalMsgHdlr {
|
trait UpdateBreakoutRoomTimeInternalMsgHdlr {
|
||||||
this: MeetingActor =>
|
this: MeetingActor =>
|
||||||
|
|
||||||
val outGW: OutMsgRouter
|
val outGW: OutMsgRouter
|
||||||
|
|
||||||
def handleExtendBreakoutRoomTimeInternalMsgHdlr(msg: ExtendBreakoutRoomTimeInternalMsg, state: MeetingState2x): MeetingState2x = {
|
def handleUpdateBreakoutRoomTimeInternalMsgHdlr(msg: UpdateBreakoutRoomTimeInternalMsg, state: MeetingState2x): MeetingState2x = {
|
||||||
|
|
||||||
val breakoutModel = for {
|
val breakoutModel = for {
|
||||||
model <- state.breakout
|
model <- state.breakout
|
||||||
} yield {
|
} yield {
|
||||||
val updatedBreakoutModel = model.extendTime(msg.extendTimeInMinutes)
|
val updatedBreakoutModel = model.setTime(msg.durationInSeconds)
|
||||||
updatedBreakoutModel
|
updatedBreakoutModel
|
||||||
}
|
}
|
||||||
|
|
@ -1,37 +1,38 @@
|
|||||||
package org.bigbluebutton.core.apps.breakout
|
package org.bigbluebutton.core.apps.breakout
|
||||||
|
|
||||||
import org.bigbluebutton.common2.msgs._
|
import org.bigbluebutton.common2.msgs._
|
||||||
import org.bigbluebutton.core.api.{ ExtendBreakoutRoomTimeInternalMsg, SendTimeRemainingAuditInternalMsg }
|
import org.bigbluebutton.core.api.{ UpdateBreakoutRoomTimeInternalMsg, SendTimeRemainingAuditInternalMsg }
|
||||||
import org.bigbluebutton.core.apps.{ PermissionCheck, RightsManagementTrait }
|
import org.bigbluebutton.core.apps.{ PermissionCheck, RightsManagementTrait }
|
||||||
import org.bigbluebutton.core.bus.BigBlueButtonEvent
|
import org.bigbluebutton.core.bus.BigBlueButtonEvent
|
||||||
import org.bigbluebutton.core.domain.MeetingState2x
|
import org.bigbluebutton.core.domain.MeetingState2x
|
||||||
import org.bigbluebutton.core.running.{ MeetingActor, OutMsgRouter }
|
import org.bigbluebutton.core.running.{ MeetingActor, OutMsgRouter }
|
||||||
import org.bigbluebutton.core.util.TimeUtil
|
import org.bigbluebutton.core.util.TimeUtil
|
||||||
|
|
||||||
trait ExtendBreakoutRoomsTimeMsgHdlr extends RightsManagementTrait {
|
trait UpdateBreakoutRoomsTimeMsgHdlr extends RightsManagementTrait {
|
||||||
this: MeetingActor =>
|
this: MeetingActor =>
|
||||||
|
|
||||||
val outGW: OutMsgRouter
|
val outGW: OutMsgRouter
|
||||||
|
|
||||||
def handleExtendBreakoutRoomsTimeMsg(msg: ExtendBreakoutRoomsTimeReqMsg, state: MeetingState2x): MeetingState2x = {
|
def handleUpdateBreakoutRoomsTimeMsg(msg: UpdateBreakoutRoomsTimeReqMsg, state: MeetingState2x): MeetingState2x = {
|
||||||
|
|
||||||
if (permissionFailed(PermissionCheck.MOD_LEVEL, PermissionCheck.VIEWER_LEVEL, liveMeeting.users2x, msg.header.userId)) {
|
if (permissionFailed(PermissionCheck.MOD_LEVEL, PermissionCheck.VIEWER_LEVEL, liveMeeting.users2x, msg.header.userId)) {
|
||||||
val meetingId = liveMeeting.props.meetingProp.intId
|
val meetingId = liveMeeting.props.meetingProp.intId
|
||||||
val reason = "No permission to extend time for breakout rooms for meeting."
|
val reason = "No permission to update time for breakout rooms for meeting."
|
||||||
PermissionCheck.ejectUserForFailedPermission(meetingId, msg.header.userId, reason, outGW, liveMeeting)
|
PermissionCheck.ejectUserForFailedPermission(meetingId, msg.header.userId, reason, outGW, liveMeeting)
|
||||||
state
|
state
|
||||||
} else if (msg.body.extendTimeInMinutes <= 0) {
|
} else if (msg.body.timeInMinutes <= 0) {
|
||||||
log.error("Error while trying to extend {} minutes for breakout rooms time in meeting {}. Only positive values are allowed!", msg.body.extendTimeInMinutes, props.meetingProp.intId)
|
log.error("Error while trying to update {} minutes for breakout rooms time in meeting {}. Only positive values are allowed!", msg.body.timeInMinutes, props.meetingProp.intId)
|
||||||
state
|
state
|
||||||
} else {
|
} else {
|
||||||
val updatedModel = for {
|
val updatedModel = for {
|
||||||
breakoutModel <- state.breakout
|
breakoutModel <- state.breakout
|
||||||
startedOn <- breakoutModel.startedOn
|
startedOn <- breakoutModel.startedOn
|
||||||
} yield {
|
} yield {
|
||||||
val breakoutRoomEndTime = TimeUtil.millisToSeconds(startedOn) + TimeUtil.minutesToSeconds(breakoutModel.durationInMinutes)
|
val newSecsRemaining = msg.body.timeInMinutes * 60
|
||||||
val breakoutRoomSecsRemaining = breakoutRoomEndTime - TimeUtil.millisToSeconds(System.currentTimeMillis())
|
val breakoutRoomSecsElapsed = TimeUtil.millisToSeconds(System.currentTimeMillis()) - TimeUtil.millisToSeconds(startedOn);
|
||||||
|
val newDurationInSeconds = breakoutRoomSecsElapsed.toInt + newSecsRemaining
|
||||||
|
|
||||||
var isExtendTimeHigherThanMeetingRemaining = false
|
var isNewTimeHigherThanMeetingRemaining = false
|
||||||
|
|
||||||
if (state.expiryTracker.durationInMs > 0) {
|
if (state.expiryTracker.durationInMs > 0) {
|
||||||
val mainRoomEndTime = state.expiryTracker.startedOnInMs + state.expiryTracker.durationInMs
|
val mainRoomEndTime = state.expiryTracker.startedOnInMs + state.expiryTracker.durationInMs
|
||||||
@ -40,28 +41,28 @@ trait ExtendBreakoutRoomsTimeMsgHdlr extends RightsManagementTrait {
|
|||||||
|
|
||||||
//Avoid breakout room end later than main room
|
//Avoid breakout room end later than main room
|
||||||
//Keep 5 seconds of margin to finish breakout room and send informations to parent meeting
|
//Keep 5 seconds of margin to finish breakout room and send informations to parent meeting
|
||||||
if (breakoutRoomSecsRemaining + TimeUtil.minutesToSeconds(msg.body.extendTimeInMinutes) > (mainRoomSecsRemaining - 5)) {
|
if (newSecsRemaining > (mainRoomSecsRemaining - 5)) {
|
||||||
log.error("Error while trying to extend {} minutes for breakout rooms time in meeting {}. Parent meeting will end up in {} minutes!", msg.body.extendTimeInMinutes, props.meetingProp.intId, mainRoomTimeRemainingInMinutes)
|
log.error("Error while trying to update {} minutes for breakout rooms time in meeting {}. Parent meeting will end up in {} minutes!", msg.body.timeInMinutes, props.meetingProp.intId, mainRoomTimeRemainingInMinutes)
|
||||||
isExtendTimeHigherThanMeetingRemaining = true
|
isNewTimeHigherThanMeetingRemaining = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isExtendTimeHigherThanMeetingRemaining) {
|
if (isNewTimeHigherThanMeetingRemaining) {
|
||||||
breakoutModel
|
breakoutModel
|
||||||
} else {
|
} else {
|
||||||
breakoutModel.rooms.values.foreach { room =>
|
breakoutModel.rooms.values.foreach { room =>
|
||||||
eventBus.publish(BigBlueButtonEvent(room.id, ExtendBreakoutRoomTimeInternalMsg(props.breakoutProps.parentId, room.id, msg.body.extendTimeInMinutes)))
|
eventBus.publish(BigBlueButtonEvent(room.id, UpdateBreakoutRoomTimeInternalMsg(props.breakoutProps.parentId, room.id, newDurationInSeconds)))
|
||||||
}
|
}
|
||||||
log.debug("Extending {} minutes for breakout rooms time in meeting {}", msg.body.extendTimeInMinutes, props.meetingProp.intId)
|
log.debug("Updating {} minutes for breakout rooms time in meeting {}", msg.body.timeInMinutes, props.meetingProp.intId)
|
||||||
breakoutModel.extendTime(msg.body.extendTimeInMinutes)
|
breakoutModel.setTime(newDurationInSeconds)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val event = buildExtendBreakoutRoomsTimeEvtMsg(msg.body.extendTimeInMinutes)
|
val event = buildUpdateBreakoutRoomsTimeEvtMsg(msg.body.timeInMinutes)
|
||||||
outGW.send(event)
|
outGW.send(event)
|
||||||
|
|
||||||
//Force Update time remaining in the clients
|
//Force Update time remaining in the clients
|
||||||
eventBus.publish(BigBlueButtonEvent(props.meetingProp.intId, SendTimeRemainingAuditInternalMsg(props.meetingProp.intId)))
|
eventBus.publish(BigBlueButtonEvent(props.meetingProp.intId, SendTimeRemainingAuditInternalMsg(props.meetingProp.intId, msg.body.timeInMinutes)))
|
||||||
|
|
||||||
updatedModel match {
|
updatedModel match {
|
||||||
case Some(model) => state.update(Some(model))
|
case Some(model) => state.update(Some(model))
|
||||||
@ -70,13 +71,13 @@ trait ExtendBreakoutRoomsTimeMsgHdlr extends RightsManagementTrait {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
def buildExtendBreakoutRoomsTimeEvtMsg(extendTimeInMinutes: Int): BbbCommonEnvCoreMsg = {
|
def buildUpdateBreakoutRoomsTimeEvtMsg(timeInMinutes: Int): BbbCommonEnvCoreMsg = {
|
||||||
val routing = collection.immutable.HashMap("sender" -> "bbb-apps-akka")
|
val routing = collection.immutable.HashMap("sender" -> "bbb-apps-akka")
|
||||||
val envelope = BbbCoreEnvelope(ExtendBreakoutRoomsTimeEvtMsg.NAME, routing)
|
val envelope = BbbCoreEnvelope(UpdateBreakoutRoomsTimeEvtMsg.NAME, routing)
|
||||||
val header = BbbClientMsgHeader(ExtendBreakoutRoomsTimeEvtMsg.NAME, liveMeeting.props.meetingProp.intId, "not-used")
|
val header = BbbClientMsgHeader(UpdateBreakoutRoomsTimeEvtMsg.NAME, liveMeeting.props.meetingProp.intId, "not-used")
|
||||||
|
|
||||||
val body = ExtendBreakoutRoomsTimeEvtMsgBody(props.meetingProp.intId, extendTimeInMinutes)
|
val body = UpdateBreakoutRoomsTimeEvtMsgBody(props.meetingProp.intId, timeInMinutes)
|
||||||
val event = ExtendBreakoutRoomsTimeEvtMsg(header, body)
|
val event = UpdateBreakoutRoomsTimeEvtMsg(header, body)
|
||||||
BbbCommonEnvCoreMsg(envelope, event)
|
BbbCommonEnvCoreMsg(envelope, event)
|
||||||
}
|
}
|
||||||
|
|
@ -223,8 +223,8 @@ class ReceivedJsonMsgHandlerActor(
|
|||||||
routeGenericMsg[EndAllBreakoutRoomsMsg](envelope, jsonNode)
|
routeGenericMsg[EndAllBreakoutRoomsMsg](envelope, jsonNode)
|
||||||
case TransferUserToMeetingRequestMsg.NAME =>
|
case TransferUserToMeetingRequestMsg.NAME =>
|
||||||
routeGenericMsg[TransferUserToMeetingRequestMsg](envelope, jsonNode)
|
routeGenericMsg[TransferUserToMeetingRequestMsg](envelope, jsonNode)
|
||||||
case ExtendBreakoutRoomsTimeReqMsg.NAME =>
|
case UpdateBreakoutRoomsTimeReqMsg.NAME =>
|
||||||
routeGenericMsg[ExtendBreakoutRoomsTimeReqMsg](envelope, jsonNode)
|
routeGenericMsg[UpdateBreakoutRoomsTimeReqMsg](envelope, jsonNode)
|
||||||
case SendMessageToAllBreakoutRoomsReqMsg.NAME =>
|
case SendMessageToAllBreakoutRoomsReqMsg.NAME =>
|
||||||
routeGenericMsg[SendMessageToAllBreakoutRoomsReqMsg](envelope, jsonNode)
|
routeGenericMsg[SendMessageToAllBreakoutRoomsReqMsg](envelope, jsonNode)
|
||||||
|
|
||||||
|
@ -283,7 +283,7 @@ class MeetingActor(
|
|||||||
case msg: SendBreakoutUsersAuditInternalMsg => handleSendBreakoutUsersUpdateInternalMsg(msg)
|
case msg: SendBreakoutUsersAuditInternalMsg => handleSendBreakoutUsersUpdateInternalMsg(msg)
|
||||||
case msg: BreakoutRoomUsersUpdateInternalMsg => state = handleBreakoutRoomUsersUpdateInternalMsg(msg, state)
|
case msg: BreakoutRoomUsersUpdateInternalMsg => state = handleBreakoutRoomUsersUpdateInternalMsg(msg, state)
|
||||||
case msg: EndBreakoutRoomInternalMsg => handleEndBreakoutRoomInternalMsg(msg)
|
case msg: EndBreakoutRoomInternalMsg => handleEndBreakoutRoomInternalMsg(msg)
|
||||||
case msg: ExtendBreakoutRoomTimeInternalMsg => state = handleExtendBreakoutRoomTimeInternalMsgHdlr(msg, state)
|
case msg: UpdateBreakoutRoomTimeInternalMsg => state = handleUpdateBreakoutRoomTimeInternalMsgHdlr(msg, state)
|
||||||
case msg: BreakoutRoomEndedInternalMsg => state = handleBreakoutRoomEndedInternalMsg(msg, state)
|
case msg: BreakoutRoomEndedInternalMsg => state = handleBreakoutRoomEndedInternalMsg(msg, state)
|
||||||
case msg: SendMessageToBreakoutRoomInternalMsg => state = handleSendMessageToBreakoutRoomInternalMsg(msg, state, liveMeeting, msgBus)
|
case msg: SendMessageToBreakoutRoomInternalMsg => state = handleSendMessageToBreakoutRoomInternalMsg(msg, state, liveMeeting, msgBus)
|
||||||
case msg: SendBreakoutTimeRemainingInternalMsg => handleSendBreakoutTimeRemainingInternalMsg(msg)
|
case msg: SendBreakoutTimeRemainingInternalMsg => handleSendBreakoutTimeRemainingInternalMsg(msg)
|
||||||
@ -454,7 +454,7 @@ class MeetingActor(
|
|||||||
case m: EndAllBreakoutRoomsMsg => state = handleEndAllBreakoutRoomsMsg(m, state)
|
case m: EndAllBreakoutRoomsMsg => state = handleEndAllBreakoutRoomsMsg(m, state)
|
||||||
case m: RequestBreakoutJoinURLReqMsg => state = handleRequestBreakoutJoinURLReqMsg(m, state)
|
case m: RequestBreakoutJoinURLReqMsg => state = handleRequestBreakoutJoinURLReqMsg(m, state)
|
||||||
case m: TransferUserToMeetingRequestMsg => state = handleTransferUserToMeetingRequestMsg(m, state)
|
case m: TransferUserToMeetingRequestMsg => state = handleTransferUserToMeetingRequestMsg(m, state)
|
||||||
case m: ExtendBreakoutRoomsTimeReqMsg => state = handleExtendBreakoutRoomsTimeMsg(m, state)
|
case m: UpdateBreakoutRoomsTimeReqMsg => state = handleUpdateBreakoutRoomsTimeMsg(m, state)
|
||||||
case m: SendMessageToAllBreakoutRoomsReqMsg => state = handleSendMessageToAllBreakoutRoomsMsg(m, state)
|
case m: SendMessageToAllBreakoutRoomsReqMsg => state = handleSendMessageToAllBreakoutRoomsMsg(m, state)
|
||||||
|
|
||||||
// Voice
|
// Voice
|
||||||
|
@ -73,7 +73,7 @@ class MeetingActorAudit(
|
|||||||
eventBus.publish(BigBlueButtonEvent(props.meetingProp.intId, MonitorNumberOfUsersInternalMsg(props.meetingProp.intId)))
|
eventBus.publish(BigBlueButtonEvent(props.meetingProp.intId, MonitorNumberOfUsersInternalMsg(props.meetingProp.intId)))
|
||||||
|
|
||||||
// Trigger updating users of time remaining on meeting.
|
// Trigger updating users of time remaining on meeting.
|
||||||
eventBus.publish(BigBlueButtonEvent(props.meetingProp.intId, SendTimeRemainingAuditInternalMsg(props.meetingProp.intId)))
|
eventBus.publish(BigBlueButtonEvent(props.meetingProp.intId, SendTimeRemainingAuditInternalMsg(props.meetingProp.intId, 0)))
|
||||||
|
|
||||||
if (props.meetingProp.isBreakout) {
|
if (props.meetingProp.isBreakout) {
|
||||||
// This is a breakout room. Update the main meeting with list of users in this breakout room.
|
// This is a breakout room. Update the main meeting with list of users in this breakout room.
|
||||||
|
@ -60,7 +60,7 @@ class AnalyticsActor(val includeChat: Boolean) extends Actor with ActorLogging {
|
|||||||
case m: RequestBreakoutJoinURLReqMsg => logMessage(msg)
|
case m: RequestBreakoutJoinURLReqMsg => logMessage(msg)
|
||||||
case m: EndAllBreakoutRoomsMsg => logMessage(msg)
|
case m: EndAllBreakoutRoomsMsg => logMessage(msg)
|
||||||
case m: TransferUserToMeetingRequestMsg => logMessage(msg)
|
case m: TransferUserToMeetingRequestMsg => logMessage(msg)
|
||||||
case m: ExtendBreakoutRoomsTimeReqMsg => logMessage(msg)
|
case m: UpdateBreakoutRoomsTimeReqMsg => logMessage(msg)
|
||||||
case m: SendMessageToAllBreakoutRoomsReqMsg => logMessage(msg)
|
case m: SendMessageToAllBreakoutRoomsReqMsg => logMessage(msg)
|
||||||
case m: UserLeftVoiceConfToClientEvtMsg => logMessage(msg)
|
case m: UserLeftVoiceConfToClientEvtMsg => logMessage(msg)
|
||||||
case m: UserLeftVoiceConfEvtMsg => logMessage(msg)
|
case m: UserLeftVoiceConfEvtMsg => logMessage(msg)
|
||||||
|
@ -18,19 +18,19 @@ trait SendBreakoutTimeRemainingMsgHdlr {
|
|||||||
model <- state.breakout
|
model <- state.breakout
|
||||||
startedOn <- model.startedOn
|
startedOn <- model.startedOn
|
||||||
} yield {
|
} yield {
|
||||||
val endMeetingTime = TimeUtil.millisToSeconds(startedOn) + TimeUtil.minutesToSeconds(model.durationInMinutes)
|
val endMeetingTime = TimeUtil.millisToSeconds(startedOn) + model.durationInSeconds
|
||||||
val timeRemaining = endMeetingTime - TimeUtil.millisToSeconds(System.currentTimeMillis())
|
val timeRemaining = endMeetingTime - TimeUtil.millisToSeconds(System.currentTimeMillis())
|
||||||
|
|
||||||
if (!liveMeeting.props.meetingProp.isBreakout) {
|
if (!liveMeeting.props.meetingProp.isBreakout) {
|
||||||
// Notify parent meeting users of breakout rooms time remaining
|
// Notify parent meeting users of breakout rooms time remaining
|
||||||
val event = buildBreakoutRoomsTimeRemainingUpdateEvtMsg(liveMeeting.props.meetingProp.intId, timeRemaining.toInt)
|
val event = buildBreakoutRoomsTimeRemainingUpdateEvtMsg(liveMeeting.props.meetingProp.intId, timeRemaining.toInt, 0)
|
||||||
outGW.send(event)
|
outGW.send(event)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tell all breakout rooms of time remaining so they can notify their users.
|
// Tell all breakout rooms of time remaining so they can notify their users.
|
||||||
// This syncs all rooms about time remaining.
|
// This syncs all rooms about time remaining.
|
||||||
model.rooms.values.foreach { room =>
|
model.rooms.values.foreach { room =>
|
||||||
eventBus.publish(BigBlueButtonEvent(room.id, SendBreakoutTimeRemainingInternalMsg(props.breakoutProps.parentId, timeRemaining.toInt)))
|
eventBus.publish(BigBlueButtonEvent(room.id, SendBreakoutTimeRemainingInternalMsg(props.breakoutProps.parentId, timeRemaining.toInt, msg.timeUpdatedInMinutes)))
|
||||||
}
|
}
|
||||||
|
|
||||||
if (timeRemaining < 0) {
|
if (timeRemaining < 0) {
|
||||||
@ -41,7 +41,7 @@ trait SendBreakoutTimeRemainingMsgHdlr {
|
|||||||
state
|
state
|
||||||
}
|
}
|
||||||
|
|
||||||
def buildBreakoutRoomsTimeRemainingUpdateEvtMsg(meetingId: String, timeLeftInSec: Long): BbbCommonEnvCoreMsg = {
|
def buildBreakoutRoomsTimeRemainingUpdateEvtMsg(meetingId: String, timeLeftInSec: Long, timeUpdatedInMinutes: Int = 0): BbbCommonEnvCoreMsg = {
|
||||||
val routing = Routing.addMsgToClientRouting(MessageTypes.BROADCAST_TO_MEETING, meetingId, "not-used")
|
val routing = Routing.addMsgToClientRouting(MessageTypes.BROADCAST_TO_MEETING, meetingId, "not-used")
|
||||||
val envelope = BbbCoreEnvelope(BreakoutRoomsTimeRemainingUpdateEvtMsg.NAME, routing)
|
val envelope = BbbCoreEnvelope(BreakoutRoomsTimeRemainingUpdateEvtMsg.NAME, routing)
|
||||||
val body = BreakoutRoomsTimeRemainingUpdateEvtMsgBody(timeLeftInSec)
|
val body = BreakoutRoomsTimeRemainingUpdateEvtMsgBody(timeLeftInSec)
|
||||||
|
@ -545,10 +545,10 @@ object MsgBuilder {
|
|||||||
BbbCommonEnvCoreMsg(envelope, event)
|
BbbCommonEnvCoreMsg(envelope, event)
|
||||||
}
|
}
|
||||||
|
|
||||||
def buildMeetingTimeRemainingUpdateEvtMsg(meetingId: String, timeLeftInSec: Long): BbbCommonEnvCoreMsg = {
|
def buildMeetingTimeRemainingUpdateEvtMsg(meetingId: String, timeLeftInSec: Long, timeUpdatedInMinutes: Int = 0): BbbCommonEnvCoreMsg = {
|
||||||
val routing = Routing.addMsgToClientRouting(MessageTypes.BROADCAST_TO_MEETING, meetingId, "not-used")
|
val routing = Routing.addMsgToClientRouting(MessageTypes.BROADCAST_TO_MEETING, meetingId, "not-used")
|
||||||
val envelope = BbbCoreEnvelope(MeetingTimeRemainingUpdateEvtMsg.NAME, routing)
|
val envelope = BbbCoreEnvelope(MeetingTimeRemainingUpdateEvtMsg.NAME, routing)
|
||||||
val body = MeetingTimeRemainingUpdateEvtMsgBody(timeLeftInSec)
|
val body = MeetingTimeRemainingUpdateEvtMsgBody(timeLeftInSec, timeUpdatedInMinutes)
|
||||||
val header = BbbClientMsgHeader(MeetingTimeRemainingUpdateEvtMsg.NAME, meetingId, "not-used")
|
val header = BbbClientMsgHeader(MeetingTimeRemainingUpdateEvtMsg.NAME, meetingId, "not-used")
|
||||||
val event = MeetingTimeRemainingUpdateEvtMsg(header, body)
|
val event = MeetingTimeRemainingUpdateEvtMsg(header, body)
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@ case class BreakoutRoomsTimeRemainingUpdateEvtMsg(
|
|||||||
header: BbbClientMsgHeader,
|
header: BbbClientMsgHeader,
|
||||||
body: BreakoutRoomsTimeRemainingUpdateEvtMsgBody
|
body: BreakoutRoomsTimeRemainingUpdateEvtMsgBody
|
||||||
) extends BbbCoreMsg
|
) extends BbbCoreMsg
|
||||||
case class BreakoutRoomsTimeRemainingUpdateEvtMsgBody(timeRemaining: Long)
|
case class BreakoutRoomsTimeRemainingUpdateEvtMsgBody(timeRemaining: Long, timeUpdatedInMinutes: Int)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sent to bbb-web to create breakout rooms.
|
* Sent to bbb-web to create breakout rooms.
|
||||||
@ -94,13 +94,13 @@ object UpdateBreakoutUsersEvtMsg { val NAME = "UpdateBreakoutUsersEvtMsg" }
|
|||||||
case class UpdateBreakoutUsersEvtMsg(header: BbbClientMsgHeader, body: UpdateBreakoutUsersEvtMsgBody) extends BbbCoreMsg
|
case class UpdateBreakoutUsersEvtMsg(header: BbbClientMsgHeader, body: UpdateBreakoutUsersEvtMsgBody) extends BbbCoreMsg
|
||||||
case class UpdateBreakoutUsersEvtMsgBody(parentId: String, breakoutId: String, users: Vector[BreakoutUserVO])
|
case class UpdateBreakoutUsersEvtMsgBody(parentId: String, breakoutId: String, users: Vector[BreakoutUserVO])
|
||||||
|
|
||||||
object ExtendBreakoutRoomsTimeReqMsg { val NAME = "ExtendBreakoutRoomsTimeReqMsg" }
|
object UpdateBreakoutRoomsTimeReqMsg { val NAME = "UpdateBreakoutRoomsTimeReqMsg" }
|
||||||
case class ExtendBreakoutRoomsTimeReqMsg(header: BbbClientMsgHeader, body: ExtendBreakoutRoomsTimeReqMsgBody) extends StandardMsg
|
case class UpdateBreakoutRoomsTimeReqMsg(header: BbbClientMsgHeader, body: UpdateBreakoutRoomsTimeReqMsgBody) extends StandardMsg
|
||||||
case class ExtendBreakoutRoomsTimeReqMsgBody(meetingId: String, extendTimeInMinutes: Int)
|
case class UpdateBreakoutRoomsTimeReqMsgBody(meetingId: String, timeInMinutes: Int)
|
||||||
|
|
||||||
object ExtendBreakoutRoomsTimeEvtMsg { val NAME = "ExtendBreakoutRoomsTimeEvtMsg" }
|
object UpdateBreakoutRoomsTimeEvtMsg { val NAME = "UpdateBreakoutRoomsTimeEvtMsg" }
|
||||||
case class ExtendBreakoutRoomsTimeEvtMsg(header: BbbClientMsgHeader, body: ExtendBreakoutRoomsTimeEvtMsgBody) extends BbbCoreMsg
|
case class UpdateBreakoutRoomsTimeEvtMsg(header: BbbClientMsgHeader, body: UpdateBreakoutRoomsTimeEvtMsgBody) extends BbbCoreMsg
|
||||||
case class ExtendBreakoutRoomsTimeEvtMsgBody(meetingId: String, extendTimeInMinutes: Int)
|
case class UpdateBreakoutRoomsTimeEvtMsgBody(meetingId: String, timeInMinutes: Int)
|
||||||
|
|
||||||
object SendMessageToAllBreakoutRoomsReqMsg { val NAME = "SendMessageToAllBreakoutRoomsReqMsg" }
|
object SendMessageToAllBreakoutRoomsReqMsg { val NAME = "SendMessageToAllBreakoutRoomsReqMsg" }
|
||||||
case class SendMessageToAllBreakoutRoomsReqMsg(header: BbbClientMsgHeader, body: SendMessageToAllBreakoutRoomsReqMsgBody) extends StandardMsg
|
case class SendMessageToAllBreakoutRoomsReqMsg(header: BbbClientMsgHeader, body: SendMessageToAllBreakoutRoomsReqMsgBody) extends StandardMsg
|
||||||
|
@ -2,13 +2,13 @@ import { Meteor } from 'meteor/meteor';
|
|||||||
import createBreakoutRoom from '/imports/api/breakouts/server/methods/createBreakout';
|
import createBreakoutRoom from '/imports/api/breakouts/server/methods/createBreakout';
|
||||||
import requestJoinURL from './methods/requestJoinURL';
|
import requestJoinURL from './methods/requestJoinURL';
|
||||||
import endAllBreakouts from './methods/endAllBreakouts';
|
import endAllBreakouts from './methods/endAllBreakouts';
|
||||||
import extendBreakoutsTime from './methods/extendBreakoutsTime';
|
import setBreakoutsTime from '/imports/api/breakouts/server/methods/setBreakoutsTime';
|
||||||
import sendMessageToAllBreakouts from './methods/sendMessageToAllBreakouts';
|
import sendMessageToAllBreakouts from './methods/sendMessageToAllBreakouts';
|
||||||
|
|
||||||
Meteor.methods({
|
Meteor.methods({
|
||||||
requestJoinURL,
|
requestJoinURL,
|
||||||
createBreakoutRoom,
|
createBreakoutRoom,
|
||||||
endAllBreakouts,
|
endAllBreakouts,
|
||||||
extendBreakoutsTime,
|
setBreakoutsTime,
|
||||||
sendMessageToAllBreakouts,
|
sendMessageToAllBreakouts,
|
||||||
});
|
});
|
||||||
|
@ -4,10 +4,10 @@ import { extractCredentials } from '/imports/api/common/server/helpers';
|
|||||||
import { check } from 'meteor/check';
|
import { check } from 'meteor/check';
|
||||||
import Logger from '/imports/startup/server/logger';
|
import Logger from '/imports/startup/server/logger';
|
||||||
|
|
||||||
export default function extendBreakoutsTime({ extendTimeInMinutes }) {
|
export default function setBreakoutsTime({ timeInMinutes }) {
|
||||||
const REDIS_CONFIG = Meteor.settings.private.redis;
|
const REDIS_CONFIG = Meteor.settings.private.redis;
|
||||||
const CHANNEL = REDIS_CONFIG.channels.toAkkaApps;
|
const CHANNEL = REDIS_CONFIG.channels.toAkkaApps;
|
||||||
const EVENT_NAME = 'ExtendBreakoutRoomsTimeReqMsg';
|
const EVENT_NAME = 'UpdateBreakoutRoomsTimeReqMsg';
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const { meetingId, requesterUserId } = extractCredentials(this.userId);
|
const { meetingId, requesterUserId } = extractCredentials(this.userId);
|
||||||
@ -15,14 +15,14 @@ export default function extendBreakoutsTime({ extendTimeInMinutes }) {
|
|||||||
check(meetingId, String);
|
check(meetingId, String);
|
||||||
check(requesterUserId, String);
|
check(requesterUserId, String);
|
||||||
|
|
||||||
return RedisPubSub.publishUserMessage(
|
RedisPubSub.publishUserMessage(
|
||||||
CHANNEL, EVENT_NAME, meetingId, requesterUserId,
|
CHANNEL, EVENT_NAME, meetingId, requesterUserId,
|
||||||
{
|
{
|
||||||
meetingId,
|
meetingId,
|
||||||
extendTimeInMinutes,
|
timeInMinutes,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
Logger.error(`Exception while invoking method extendBreakoutsTime ${err.stack}`);
|
Logger.error(`Exception while invoking method setBreakoutsTime ${err.stack}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -24,7 +24,8 @@ export default function addSystemMsg(meetingId, chatId, msg) {
|
|||||||
timestamp: Number,
|
timestamp: Number,
|
||||||
sender: Object,
|
sender: Object,
|
||||||
message: String,
|
message: String,
|
||||||
extra: Object,
|
messageValues: Match.Maybe(Object),
|
||||||
|
extra: Match.Maybe(Object),
|
||||||
correlationId: Match.Maybe(String),
|
correlationId: Match.Maybe(String),
|
||||||
});
|
});
|
||||||
const msgDocument = {
|
const msgDocument = {
|
||||||
|
@ -1,14 +1,16 @@
|
|||||||
import { check } from 'meteor/check';
|
import { check } from 'meteor/check';
|
||||||
import { MeetingTimeRemaining } from '/imports/api/meetings';
|
import Meetings, { MeetingTimeRemaining } from '/imports/api/meetings';
|
||||||
import Logger from '/imports/startup/server/logger';
|
import Logger from '/imports/startup/server/logger';
|
||||||
|
import addSystemMsg from '/imports/api/group-chat-msg/server/modifiers/addSystemMsg';
|
||||||
|
|
||||||
export default function handleTimeRemainingUpdate({ body }, meetingId) {
|
export default function handleTimeRemainingUpdate({ body }, meetingId) {
|
||||||
check(meetingId, String);
|
check(meetingId, String);
|
||||||
|
|
||||||
check(body, {
|
check(body, {
|
||||||
timeLeftInSec: Number,
|
timeLeftInSec: Number,
|
||||||
|
timeUpdatedInMinutes: Number,
|
||||||
});
|
});
|
||||||
const { timeLeftInSec } = body;
|
const { timeLeftInSec, timeUpdatedInMinutes } = body;
|
||||||
|
|
||||||
const selector = {
|
const selector = {
|
||||||
meetingId,
|
meetingId,
|
||||||
@ -25,4 +27,34 @@ export default function handleTimeRemainingUpdate({ body }, meetingId) {
|
|||||||
} catch (err) {
|
} catch (err) {
|
||||||
Logger.error(`Changing recording time: ${err}`);
|
Logger.error(`Changing recording time: ${err}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (timeUpdatedInMinutes > 0) {
|
||||||
|
const Meeting = Meetings.findOne({ meetingId });
|
||||||
|
|
||||||
|
if (Meeting.meetingProp.isBreakout) {
|
||||||
|
const CHAT_CONFIG = Meteor.settings.public.chat;
|
||||||
|
const PUBLIC_GROUP_CHAT_ID = CHAT_CONFIG.public_group_id;
|
||||||
|
const PUBLIC_CHAT_SYSTEM_ID = CHAT_CONFIG.system_userid;
|
||||||
|
const PUBLIC_CHAT_INFO = CHAT_CONFIG.system_messages_keys.chat_info;
|
||||||
|
const SYSTEM_CHAT_TYPE = CHAT_CONFIG.type_system;
|
||||||
|
|
||||||
|
const messageValues = {
|
||||||
|
0: timeUpdatedInMinutes,
|
||||||
|
};
|
||||||
|
|
||||||
|
const payload = {
|
||||||
|
id: `${SYSTEM_CHAT_TYPE}-${PUBLIC_CHAT_INFO}`,
|
||||||
|
timestamp: Date.now(),
|
||||||
|
correlationId: `${PUBLIC_CHAT_SYSTEM_ID}-${Date.now()}`,
|
||||||
|
sender: {
|
||||||
|
id: PUBLIC_CHAT_SYSTEM_ID,
|
||||||
|
name: '',
|
||||||
|
},
|
||||||
|
message: 'breakoutDurationUpdated',
|
||||||
|
messageValues,
|
||||||
|
};
|
||||||
|
|
||||||
|
addSystemMsg(meetingId, PUBLIC_GROUP_CHAT_ID, payload);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -63,21 +63,21 @@ const intlMessages = defineMessages({
|
|||||||
id: 'app.createBreakoutRoom.alreadyConnected',
|
id: 'app.createBreakoutRoom.alreadyConnected',
|
||||||
description: 'label for the user that is already connected to breakout room',
|
description: 'label for the user that is already connected to breakout room',
|
||||||
},
|
},
|
||||||
extendTimeInMinutes: {
|
setTimeInMinutes: {
|
||||||
id: 'app.createBreakoutRoom.extendTimeInMinutes',
|
id: 'app.createBreakoutRoom.setTimeInMinutes',
|
||||||
description: 'Label for input to extend time (minutes)',
|
description: 'Label for input to set time (minutes)',
|
||||||
},
|
},
|
||||||
extendTimeLabel: {
|
setTimeLabel: {
|
||||||
id: 'app.createBreakoutRoom.extendTimeLabel',
|
id: 'app.createBreakoutRoom.setTimeLabel',
|
||||||
description: 'Button label to incresce breakout rooms time',
|
description: 'Button label to set breakout rooms time',
|
||||||
},
|
},
|
||||||
extendTimeCancel: {
|
setTimeCancel: {
|
||||||
id: 'app.createBreakoutRoom.extendTimeCancel',
|
id: 'app.createBreakoutRoom.setTimeCancel',
|
||||||
description: 'Button label to cancel extend breakout rooms time',
|
description: 'Button label to cancel set breakout rooms time',
|
||||||
},
|
},
|
||||||
extendTimeHigherThanMeetingTimeError: {
|
setTimeHigherThanMeetingTimeError: {
|
||||||
id: 'app.createBreakoutRoom.extendTimeHigherThanMeetingTimeError',
|
id: 'app.createBreakoutRoom.setTimeHigherThanMeetingTimeError',
|
||||||
description: 'Label for error when extend breakout rooms time would be higher than remaining time in parent meeting',
|
description: 'Label for error when new breakout rooms time would be higher than remaining time in parent meeting',
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -104,9 +104,9 @@ class BreakoutRoom extends PureComponent {
|
|||||||
this.getBreakoutLabel = this.getBreakoutLabel.bind(this);
|
this.getBreakoutLabel = this.getBreakoutLabel.bind(this);
|
||||||
this.renderDuration = this.renderDuration.bind(this);
|
this.renderDuration = this.renderDuration.bind(this);
|
||||||
this.transferUserToBreakoutRoom = this.transferUserToBreakoutRoom.bind(this);
|
this.transferUserToBreakoutRoom = this.transferUserToBreakoutRoom.bind(this);
|
||||||
this.changeExtendTime = this.changeExtendTime.bind(this);
|
this.changeSetTime = this.changeSetTime.bind(this);
|
||||||
this.showExtendTimeForm = this.showExtendTimeForm.bind(this);
|
this.showSetTimeForm = this.showSetTimeForm.bind(this);
|
||||||
this.resetExtendTimeForm = this.resetExtendTimeForm.bind(this);
|
this.resetSetTimeForm = this.resetSetTimeForm.bind(this);
|
||||||
this.renderUserActions = this.renderUserActions.bind(this);
|
this.renderUserActions = this.renderUserActions.bind(this);
|
||||||
this.returnBackToMeeeting = this.returnBackToMeeeting.bind(this);
|
this.returnBackToMeeeting = this.returnBackToMeeeting.bind(this);
|
||||||
this.closePanel = this.closePanel.bind(this);
|
this.closePanel = this.closePanel.bind(this);
|
||||||
@ -116,9 +116,9 @@ class BreakoutRoom extends PureComponent {
|
|||||||
generated: false,
|
generated: false,
|
||||||
joinedAudioOnly: false,
|
joinedAudioOnly: false,
|
||||||
breakoutId: '',
|
breakoutId: '',
|
||||||
visibleExtendTimeForm: false,
|
visibleSetTimeForm: false,
|
||||||
visibleExtendTimeHigherThanMeetingTimeError: false,
|
visibleSetTimeHigherThanMeetingTimeError: false,
|
||||||
extendTime: 5,
|
newTime: 15,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -219,21 +219,21 @@ class BreakoutRoom extends PureComponent {
|
|||||||
this.setState({ joinedAudioOnly: false });
|
this.setState({ joinedAudioOnly: false });
|
||||||
}
|
}
|
||||||
|
|
||||||
changeExtendTime(event) {
|
changeSetTime(event) {
|
||||||
const newExtendTime = Number.parseInt(event.target.value, 10) || 0;
|
const newSetTime = Number.parseInt(event.target.value, 10) || 0;
|
||||||
this.setState({ extendTime: newExtendTime >= 0 ? newExtendTime : 0 });
|
this.setState({ newTime: newSetTime >= 0 ? newSetTime : 0 });
|
||||||
}
|
}
|
||||||
|
|
||||||
showExtendTimeForm() {
|
showSetTimeForm() {
|
||||||
this.setState({ visibleExtendTimeForm: true });
|
this.setState({ visibleSetTimeForm: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
showExtendTimeHigherThanMeetingTimeError(show) {
|
showSetTimeHigherThanMeetingTimeError(show) {
|
||||||
this.setState({ visibleExtendTimeHigherThanMeetingTimeError: show });
|
this.setState({ visibleSetTimeHigherThanMeetingTimeError: show });
|
||||||
}
|
}
|
||||||
|
|
||||||
resetExtendTimeForm() {
|
resetSetTimeForm() {
|
||||||
this.setState({ visibleExtendTimeForm: false, extendTime: 5 });
|
this.setState({ visibleSetTimeForm: false, newTime: 5 });
|
||||||
}
|
}
|
||||||
|
|
||||||
transferUserToBreakoutRoom(breakoutId) {
|
transferUserToBreakoutRoom(breakoutId) {
|
||||||
@ -436,35 +436,35 @@ class BreakoutRoom extends PureComponent {
|
|||||||
breakoutRooms,
|
breakoutRooms,
|
||||||
amIModerator,
|
amIModerator,
|
||||||
isMeteorConnected,
|
isMeteorConnected,
|
||||||
extendBreakoutsTime,
|
setBreakoutsTime,
|
||||||
isExtendTimeHigherThanMeetingRemaining,
|
isNewTimeHigherThanMeetingRemaining,
|
||||||
} = this.props;
|
} = this.props;
|
||||||
const {
|
const {
|
||||||
extendTime,
|
newTime,
|
||||||
visibleExtendTimeForm,
|
visibleSetTimeForm,
|
||||||
visibleExtendTimeHigherThanMeetingTimeError,
|
visibleSetTimeHigherThanMeetingTimeError,
|
||||||
} = this.state;
|
} = this.state;
|
||||||
return (
|
return (
|
||||||
<Styled.DurationContainer>
|
<Styled.DurationContainer>
|
||||||
{amIModerator && visibleExtendTimeForm ? (
|
{amIModerator && visibleSetTimeForm ? (
|
||||||
<Styled.ExtendTimeContainer>
|
<Styled.SetTimeContainer>
|
||||||
<label htmlFor="inputExtendTimeSelector" >
|
<label htmlFor="inputSetTimeSelector" >
|
||||||
{intl.formatMessage(intlMessages.extendTimeInMinutes)}
|
{intl.formatMessage(intlMessages.setTimeInMinutes)}
|
||||||
</label>
|
</label>
|
||||||
<br />
|
<br />
|
||||||
<Styled.ExtendDurationInput
|
<Styled.SetDurationInput
|
||||||
id="inputExtendTimeSelector"
|
id="inputSetTimeSelector"
|
||||||
type="number"
|
type="number"
|
||||||
min="1"
|
min="1"
|
||||||
value={extendTime}
|
value={newTime}
|
||||||
onChange={this.changeExtendTime}
|
onChange={this.changeSetTime}
|
||||||
aria-label={intl.formatMessage(intlMessages.extendTimeInMinutes)}
|
aria-label={intl.formatMessage(intlMessages.setTimeInMinutes)}
|
||||||
/>
|
/>
|
||||||
<br />
|
<br />
|
||||||
<br />
|
<br />
|
||||||
{visibleExtendTimeHigherThanMeetingTimeError ? (
|
{visibleSetTimeHigherThanMeetingTimeError ? (
|
||||||
<Styled.WithError>
|
<Styled.WithError>
|
||||||
{intl.formatMessage(intlMessages.extendTimeHigherThanMeetingTimeError)}
|
{intl.formatMessage(intlMessages.setTimeHigherThanMeetingTimeError)}
|
||||||
<br />
|
<br />
|
||||||
<br />
|
<br />
|
||||||
</Styled.WithError>
|
</Styled.WithError>
|
||||||
@ -473,42 +473,42 @@ class BreakoutRoom extends PureComponent {
|
|||||||
color="default"
|
color="default"
|
||||||
disabled={!isMeteorConnected}
|
disabled={!isMeteorConnected}
|
||||||
size="sm"
|
size="sm"
|
||||||
label={intl.formatMessage(intlMessages.extendTimeCancel)}
|
label={intl.formatMessage(intlMessages.setTimeCancel)}
|
||||||
onClick={this.resetExtendTimeForm}
|
onClick={this.resetSetTimeForm}
|
||||||
/>
|
/>
|
||||||
<Styled.EndButton
|
<Styled.EndButton
|
||||||
color="primary"
|
color="primary"
|
||||||
disabled={!isMeteorConnected}
|
disabled={!isMeteorConnected}
|
||||||
size="sm"
|
size="sm"
|
||||||
label={intl.formatMessage(intlMessages.extendTimeLabel)}
|
label={intl.formatMessage(intlMessages.setTimeLabel)}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
this.showExtendTimeHigherThanMeetingTimeError(false);
|
this.showSetTimeHigherThanMeetingTimeError(false);
|
||||||
|
|
||||||
if (isExtendTimeHigherThanMeetingRemaining(extendTime)) {
|
if (isNewTimeHigherThanMeetingRemaining(newTime)) {
|
||||||
this.showExtendTimeHigherThanMeetingTimeError(true);
|
this.showSetTimeHigherThanMeetingTimeError(true);
|
||||||
} else if (extendBreakoutsTime(extendTime)) {
|
} else if (setBreakoutsTime(newTime)) {
|
||||||
this.resetExtendTimeForm();
|
this.resetSetTimeForm();
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</Styled.ExtendTimeContainer>
|
</Styled.SetTimeContainer>
|
||||||
) : null}
|
) : null}
|
||||||
<Styled.Duration>
|
<Styled.Duration>
|
||||||
<BreakoutRoomContainer
|
<BreakoutRoomContainer
|
||||||
messageDuration={intlMessages.breakoutDuration}
|
messageDuration={intlMessages.breakoutDuration}
|
||||||
breakoutRoom={breakoutRooms[0]}
|
breakoutRoom={breakoutRooms[0]}
|
||||||
/>
|
/>
|
||||||
{amIModerator && !visibleExtendTimeForm
|
{amIModerator && !visibleSetTimeForm
|
||||||
? (
|
? (
|
||||||
<Button
|
<Button
|
||||||
onClick={this.showExtendTimeForm}
|
onClick={this.showSetTimeForm}
|
||||||
color="default"
|
color="default"
|
||||||
icon="add"
|
icon="more"
|
||||||
circle
|
circle
|
||||||
hideLabel
|
hideLabel
|
||||||
size="sm"
|
size="sm"
|
||||||
label={intl.formatMessage(intlMessages.extendTimeLabel)}
|
label={intl.formatMessage(intlMessages.setTimeInMinutes)}
|
||||||
aria-label={intl.formatMessage(intlMessages.extendTimeLabel)}
|
aria-label={intl.formatMessage(intlMessages.setTimeInMinutes)}
|
||||||
disabled={!isMeteorConnected}
|
disabled={!isMeteorConnected}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
|
@ -24,9 +24,9 @@ export default withTracker((props) => {
|
|||||||
const {
|
const {
|
||||||
endAllBreakouts,
|
endAllBreakouts,
|
||||||
requestJoinURL,
|
requestJoinURL,
|
||||||
extendBreakoutsTime,
|
setBreakoutsTime,
|
||||||
sendMessageToAllBreakouts,
|
sendMessageToAllBreakouts,
|
||||||
isExtendTimeHigherThanMeetingRemaining,
|
isNewTimeHigherThanMeetingRemaining,
|
||||||
findBreakouts,
|
findBreakouts,
|
||||||
getBreakoutRoomUrl,
|
getBreakoutRoomUrl,
|
||||||
transferUserToMeeting,
|
transferUserToMeeting,
|
||||||
@ -50,9 +50,9 @@ export default withTracker((props) => {
|
|||||||
breakoutRooms,
|
breakoutRooms,
|
||||||
endAllBreakouts,
|
endAllBreakouts,
|
||||||
requestJoinURL,
|
requestJoinURL,
|
||||||
extendBreakoutsTime,
|
setBreakoutsTime,
|
||||||
sendMessageToAllBreakouts,
|
sendMessageToAllBreakouts,
|
||||||
isExtendTimeHigherThanMeetingRemaining,
|
isNewTimeHigherThanMeetingRemaining,
|
||||||
getBreakoutRoomUrl,
|
getBreakoutRoomUrl,
|
||||||
transferUserToMeeting,
|
transferUserToMeeting,
|
||||||
transferToBreakout,
|
transferToBreakout,
|
||||||
|
@ -47,7 +47,7 @@ const requestJoinURL = (breakoutId) => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const isExtendTimeHigherThanMeetingRemaining = (extendTimeInMinutes) => {
|
const isNewTimeHigherThanMeetingRemaining = (newTimeInMinutes) => {
|
||||||
const meetingId = Auth.meetingID;
|
const meetingId = Auth.meetingID;
|
||||||
const meetingTimeRemaining = MeetingTimeRemaining.findOne({ meetingId });
|
const meetingTimeRemaining = MeetingTimeRemaining.findOne({ meetingId });
|
||||||
|
|
||||||
@ -55,10 +55,7 @@ const isExtendTimeHigherThanMeetingRemaining = (extendTimeInMinutes) => {
|
|||||||
const { timeRemaining } = meetingTimeRemaining;
|
const { timeRemaining } = meetingTimeRemaining;
|
||||||
|
|
||||||
if (timeRemaining) {
|
if (timeRemaining) {
|
||||||
const breakoutRooms = findBreakouts();
|
const newBreakoutRoomsRemainingTime = newTimeInMinutes * 60;
|
||||||
const breakoutRoomsTimeRemaining = breakoutRooms[0].timeRemaining;
|
|
||||||
const newBreakoutRoomsRemainingTime =
|
|
||||||
breakoutRoomsTimeRemaining + extendTimeInMinutes * 60;
|
|
||||||
// Keep margin of 5 seconds for breakout rooms end before parent meeting
|
// Keep margin of 5 seconds for breakout rooms end before parent meeting
|
||||||
const meetingTimeRemainingWithMargin = timeRemaining - 5;
|
const meetingTimeRemainingWithMargin = timeRemaining - 5;
|
||||||
|
|
||||||
@ -71,11 +68,11 @@ const isExtendTimeHigherThanMeetingRemaining = (extendTimeInMinutes) => {
|
|||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
const extendBreakoutsTime = (extendTimeInMinutes) => {
|
const setBreakoutsTime = (timeInMinutes) => {
|
||||||
if (extendTimeInMinutes <= 0) return false;
|
if (timeInMinutes <= 0) return false;
|
||||||
|
|
||||||
makeCall('extendBreakoutsTime', {
|
makeCall('setBreakoutsTime', {
|
||||||
extendTimeInMinutes,
|
timeInMinutes,
|
||||||
});
|
});
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -209,10 +206,10 @@ const isUserInBreakoutRoom = (joinedUsers) => {
|
|||||||
export default {
|
export default {
|
||||||
findBreakouts,
|
findBreakouts,
|
||||||
endAllBreakouts,
|
endAllBreakouts,
|
||||||
extendBreakoutsTime,
|
setBreakoutsTime,
|
||||||
sendMessageToAllBreakouts,
|
sendMessageToAllBreakouts,
|
||||||
getUserMessagesToAllBreakouts,
|
getUserMessagesToAllBreakouts,
|
||||||
isExtendTimeHigherThanMeetingRemaining,
|
isNewTimeHigherThanMeetingRemaining,
|
||||||
requestJoinURL,
|
requestJoinURL,
|
||||||
getBreakoutRoomUrl,
|
getBreakoutRoomUrl,
|
||||||
transferUserToMeeting,
|
transferUserToMeeting,
|
||||||
|
@ -154,13 +154,13 @@ const DurationContainer = styled.div`
|
|||||||
text-align: center;
|
text-align: center;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const ExtendTimeContainer = styled.div`
|
const SetTimeContainer = styled.div`
|
||||||
border-top: 1px solid ${systemMessageBorderColor};
|
border-top: 1px solid ${systemMessageBorderColor};
|
||||||
border-bottom: 1px solid ${systemMessageBorderColor};
|
border-bottom: 1px solid ${systemMessageBorderColor};
|
||||||
padding: 10px 0px;
|
padding: 10px 0px;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const ExtendDurationInput = styled.input`
|
const SetDurationInput = styled.input`
|
||||||
width: 50%;
|
width: 50%;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
padding: .25rem;
|
padding: .25rem;
|
||||||
@ -253,8 +253,8 @@ export default {
|
|||||||
BreakoutColumn,
|
BreakoutColumn,
|
||||||
BreakoutScrollableList,
|
BreakoutScrollableList,
|
||||||
DurationContainer,
|
DurationContainer,
|
||||||
ExtendTimeContainer,
|
SetTimeContainer,
|
||||||
ExtendDurationInput,
|
SetDurationInput,
|
||||||
WithError,
|
WithError,
|
||||||
EndButton,
|
EndButton,
|
||||||
Duration,
|
Duration,
|
||||||
|
@ -50,7 +50,11 @@ const intlMessages = defineMessages({
|
|||||||
[CHAT_CLEAR_MESSAGE]: {
|
[CHAT_CLEAR_MESSAGE]: {
|
||||||
id: 'app.chat.clearPublicChatMessage',
|
id: 'app.chat.clearPublicChatMessage',
|
||||||
description: 'message of when clear the public chat',
|
description: 'message of when clear the public chat',
|
||||||
}
|
},
|
||||||
|
breakoutDurationUpdated: {
|
||||||
|
id: 'app.chat.breakoutDurationUpdated',
|
||||||
|
description: 'used when the breakout duration is updated',
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
class TimeWindowChatItem extends PureComponent {
|
class TimeWindowChatItem extends PureComponent {
|
||||||
@ -89,6 +93,7 @@ class TimeWindowChatItem extends PureComponent {
|
|||||||
renderSystemMessage() {
|
renderSystemMessage() {
|
||||||
const {
|
const {
|
||||||
messages,
|
messages,
|
||||||
|
messageValues,
|
||||||
chatAreaId,
|
chatAreaId,
|
||||||
handleReadMessage,
|
handleReadMessage,
|
||||||
messageKey,
|
messageKey,
|
||||||
@ -104,13 +109,16 @@ class TimeWindowChatItem extends PureComponent {
|
|||||||
key={`time-window-chat-item-${messageKey}`}
|
key={`time-window-chat-item-${messageKey}`}
|
||||||
ref={element => this.itemRef = element} >
|
ref={element => this.itemRef = element} >
|
||||||
<Styled.Messages>
|
<Styled.Messages>
|
||||||
{messages.map(message => (
|
{messages.map((message) => (
|
||||||
message.text !== ''
|
message.text !== ''
|
||||||
? (
|
? (
|
||||||
<Styled.SystemMessageChatItem
|
<Styled.SystemMessageChatItem
|
||||||
border={message.id}
|
border={message.id}
|
||||||
key={message.id ? message.id : _.uniqueId('id-')}
|
key={message.id ? message.id : _.uniqueId('id-')}
|
||||||
text={intlMessages[message.text] ? intl.formatMessage(intlMessages[message.text]) : message.text }
|
text={intlMessages[message.text] ? intl.formatMessage(
|
||||||
|
intlMessages[message.text],
|
||||||
|
messageValues || {},
|
||||||
|
) : message.text}
|
||||||
time={message.time}
|
time={message.time}
|
||||||
isSystemMessage={message.id ? true : false}
|
isSystemMessage={message.id ? true : false}
|
||||||
systemMessageType={message.text === CHAT_CLEAR_MESSAGE ? 'chatClearMessageText' : 'chatWelcomeMessageText'}
|
systemMessageType={message.text === CHAT_CLEAR_MESSAGE ? 'chatClearMessageText' : 'chatWelcomeMessageText'}
|
||||||
|
@ -24,6 +24,7 @@ const TimeWindowChatItemContainer = (props) => {
|
|||||||
timestamp,
|
timestamp,
|
||||||
content,
|
content,
|
||||||
extra,
|
extra,
|
||||||
|
messageValues,
|
||||||
} = message;
|
} = message;
|
||||||
const messages = content;
|
const messages = content;
|
||||||
|
|
||||||
@ -49,6 +50,7 @@ const TimeWindowChatItemContainer = (props) => {
|
|||||||
read: message.read,
|
read: message.read,
|
||||||
messages,
|
messages,
|
||||||
extra,
|
extra,
|
||||||
|
messageValues,
|
||||||
getPollResultString: PollService.getPollResultString,
|
getPollResultString: PollService.getPollResultString,
|
||||||
user,
|
user,
|
||||||
timestamp,
|
timestamp,
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
"app.chat.label": "Chat",
|
"app.chat.label": "Chat",
|
||||||
"app.chat.offline": "Offline",
|
"app.chat.offline": "Offline",
|
||||||
"app.chat.pollResult": "Poll Results",
|
"app.chat.pollResult": "Poll Results",
|
||||||
|
"app.chat.breakoutDurationUpdated": "Breakout time is now {0} minutes",
|
||||||
"app.chat.emptyLogLabel": "Chat log empty",
|
"app.chat.emptyLogLabel": "Chat log empty",
|
||||||
"app.chat.clearPublicChatMessage": "The public chat history was cleared by a moderator",
|
"app.chat.clearPublicChatMessage": "The public chat history was cleared by a moderator",
|
||||||
"app.chat.multi.typing": "Multiple users are typing",
|
"app.chat.multi.typing": "Multiple users are typing",
|
||||||
@ -891,10 +892,10 @@
|
|||||||
"app.createBreakoutRoom.numberOfRoomsError": "The number of rooms is invalid.",
|
"app.createBreakoutRoom.numberOfRoomsError": "The number of rooms is invalid.",
|
||||||
"app.createBreakoutRoom.duplicatedRoomNameError": "Room name can't be duplicated.",
|
"app.createBreakoutRoom.duplicatedRoomNameError": "Room name can't be duplicated.",
|
||||||
"app.createBreakoutRoom.emptyRoomNameError": "Room name can't be empty.",
|
"app.createBreakoutRoom.emptyRoomNameError": "Room name can't be empty.",
|
||||||
"app.createBreakoutRoom.extendTimeInMinutes": "Time to extend (minutes)",
|
"app.createBreakoutRoom.setTimeInMinutes": "Set duration to (minutes)",
|
||||||
"app.createBreakoutRoom.extendTimeLabel": "Extend",
|
"app.createBreakoutRoom.setTimeLabel": "Apply",
|
||||||
"app.createBreakoutRoom.extendTimeCancel": "Cancel",
|
"app.createBreakoutRoom.setTimeCancel": "Cancel",
|
||||||
"app.createBreakoutRoom.extendTimeHigherThanMeetingTimeError": "The breakout rooms duration can't exceed the meeting remaining time.",
|
"app.createBreakoutRoom.setTimeHigherThanMeetingTimeError": "The breakout rooms duration can't exceed the meeting remaining time.",
|
||||||
"app.createBreakoutRoom.roomNameInputDesc": "Updates breakout room name",
|
"app.createBreakoutRoom.roomNameInputDesc": "Updates breakout room name",
|
||||||
"app.externalVideo.start": "Share a new video",
|
"app.externalVideo.start": "Share a new video",
|
||||||
"app.externalVideo.title": "Share an external video",
|
"app.externalVideo.title": "Share an external video",
|
||||||
|
Loading…
Reference in New Issue
Block a user