fixed proctoring room issues
This commit is contained in:
parent
daebd9b5f7
commit
5b9b336886
9 changed files with 241 additions and 117 deletions
|
@ -11,6 +11,7 @@ package ch.ethz.seb.sebserver.gbl;
|
|||
import java.util.Collection;
|
||||
|
||||
import org.eclipse.swt.graphics.RGB;
|
||||
import org.eclipse.swt.graphics.RGBA;
|
||||
import org.joda.time.format.DateTimeFormat;
|
||||
import org.joda.time.format.DateTimeFormatter;
|
||||
import org.springframework.core.ParameterizedTypeReference;
|
||||
|
@ -124,6 +125,7 @@ public final class Constants {
|
|||
|
||||
public static final RGB WHITE_RGB = new RGB(255, 255, 255);
|
||||
public static final RGB BLACK_RGB = new RGB(0, 0, 0);
|
||||
public static final RGBA GREY_DISABLED = new RGBA(150, 150, 150, 50);
|
||||
|
||||
public static final String IMPORTED_PASSWORD_MARKER = "_IMPORTED_PASSWORD";
|
||||
|
||||
|
|
|
@ -286,28 +286,30 @@ public class MonitoringClientConnection implements TemplateComposer {
|
|||
.publishIf(() -> currentUser.get().hasRole(UserRole.EXAM_SUPPORTER) &&
|
||||
connectionData.clientConnection.status == ConnectionStatus.ACTIVE);
|
||||
|
||||
final ProctoringSettings procotringSettings = restService
|
||||
.getBuilder(GetProctoringSettings.class)
|
||||
.withURIVariable(API.PARAM_MODEL_ID, parentEntityKey.modelId)
|
||||
.call()
|
||||
.onError(error -> log.error("Failed to get ProctoringSettings", error))
|
||||
.getOr(null);
|
||||
// TODO if (connectionData.clientConnection.status == ConnectionStatus.ACTIVE) {
|
||||
if (connectionData.clientConnection.status != ConnectionStatus.DISABLED) {
|
||||
final ProctoringSettings procotringSettings = restService
|
||||
.getBuilder(GetProctoringSettings.class)
|
||||
.withURIVariable(API.PARAM_MODEL_ID, parentEntityKey.modelId)
|
||||
.call()
|
||||
.onError(error -> log.error("Failed to get ProctoringSettings", error))
|
||||
.getOr(null);
|
||||
|
||||
if (procotringSettings != null && procotringSettings.enableProctoring) {
|
||||
actionBuilder
|
||||
.newAction(ActionDefinition.MONITOR_EXAM_CLIENT_CONNECTION_PROCTORING)
|
||||
.withEntityKey(parentEntityKey)
|
||||
.withExec(action -> this.openSingleProctorScreen(action, connectionData))
|
||||
.noEventPropagation()
|
||||
.publish()
|
||||
if (procotringSettings != null && procotringSettings.enableProctoring) {
|
||||
actionBuilder
|
||||
.newAction(ActionDefinition.MONITOR_EXAM_CLIENT_CONNECTION_PROCTORING)
|
||||
.withEntityKey(parentEntityKey)
|
||||
.withExec(action -> this.openSingleProctorScreen(action, connectionData))
|
||||
.noEventPropagation()
|
||||
.publish()
|
||||
|
||||
.newAction(ActionDefinition.MONITOR_EXAM_CLIENT_CONNECTION_EXAM_ROOM_PROCTORING)
|
||||
.withEntityKey(parentEntityKey)
|
||||
.withExec(action -> this.openExamCollectionProctorScreen(action, connectionData))
|
||||
.noEventPropagation()
|
||||
.publish();
|
||||
.newAction(ActionDefinition.MONITOR_EXAM_CLIENT_CONNECTION_EXAM_ROOM_PROCTORING)
|
||||
.withEntityKey(parentEntityKey)
|
||||
.withExec(action -> this.openExamCollectionProctorScreen(action, connectionData))
|
||||
.noEventPropagation()
|
||||
.publish();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private PageAction openExamCollectionProctorScreen(
|
||||
|
|
|
@ -20,9 +20,12 @@ import java.util.function.Function;
|
|||
import org.eclipse.rap.rwt.RWT;
|
||||
import org.eclipse.rap.rwt.client.service.JavaScriptExecutor;
|
||||
import org.eclipse.swt.SWT;
|
||||
import org.eclipse.swt.graphics.Color;
|
||||
import org.eclipse.swt.graphics.Image;
|
||||
import org.eclipse.swt.layout.GridData;
|
||||
import org.eclipse.swt.layout.GridLayout;
|
||||
import org.eclipse.swt.widgets.Composite;
|
||||
import org.eclipse.swt.widgets.Display;
|
||||
import org.eclipse.swt.widgets.Tree;
|
||||
import org.eclipse.swt.widgets.TreeItem;
|
||||
import org.slf4j.Logger;
|
||||
|
@ -31,6 +34,7 @@ import org.springframework.beans.factory.annotation.Value;
|
|||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.Constants;
|
||||
import ch.ethz.seb.sebserver.gbl.api.API;
|
||||
import ch.ethz.seb.sebserver.gbl.api.EntityType;
|
||||
import ch.ethz.seb.sebserver.gbl.model.Domain;
|
||||
|
@ -49,6 +53,7 @@ import ch.ethz.seb.sebserver.gbl.util.Tuple;
|
|||
import ch.ethz.seb.sebserver.gbl.util.Utils;
|
||||
import ch.ethz.seb.sebserver.gui.GuiServiceInfo;
|
||||
import ch.ethz.seb.sebserver.gui.content.action.ActionDefinition;
|
||||
import ch.ethz.seb.sebserver.gui.content.action.ActionPane;
|
||||
import ch.ethz.seb.sebserver.gui.service.ResourceService;
|
||||
import ch.ethz.seb.sebserver.gui.service.i18n.I18nSupport;
|
||||
import ch.ethz.seb.sebserver.gui.service.i18n.LocTextKey;
|
||||
|
@ -361,13 +366,13 @@ public class MonitoringRunningExam implements TemplateComposer {
|
|||
room.subject,
|
||||
room.roomSize,
|
||||
proctoringSettings.collectingRoomSize)));
|
||||
|
||||
processProctorRoomActionActivation(treeItem, room, pageContext);
|
||||
} else {
|
||||
// create new action
|
||||
final PageAction action =
|
||||
actionBuilder.newAction(ActionDefinition.MONITOR_EXAM_VIEW_PROCTOR_ROOM)
|
||||
.withEntityKey(entityKey)
|
||||
.withExec(a -> showExamProctoringRoom(proctoringSettings, room, a))
|
||||
.withExec(a -> showExamProctoringRoom(proctoringSettings, room, rooms, a))
|
||||
.withNameAttributes(
|
||||
room.subject,
|
||||
room.roomSize,
|
||||
|
@ -376,42 +381,89 @@ public class MonitoringRunningExam implements TemplateComposer {
|
|||
.create();
|
||||
|
||||
this.pageService.publishAction(action, treeItem -> rooms.put(room, treeItem));
|
||||
|
||||
// check and add show connections in room action adaptation
|
||||
if (!rooms.isEmpty()) {
|
||||
final TreeItem treeItem = rooms.values().iterator().next();
|
||||
final Tree tree = treeItem.getParent();
|
||||
if (tree.getData(SHOW_CONNECTION_ACTION_APPLIED) == null) {
|
||||
tree.addListener(SWT.Selection, event -> {
|
||||
final TreeItem item = (TreeItem) event.item;
|
||||
treeItem.getParent().deselectAll();
|
||||
if (event.button == 3) {
|
||||
rooms.entrySet()
|
||||
.stream()
|
||||
.filter(e -> e.getValue().equals(item))
|
||||
.findFirst()
|
||||
.ifPresent(e -> {
|
||||
final PageContext pc = pageContext.copy()
|
||||
.clearAttributes()
|
||||
.withEntityKey(new EntityKey(e.getKey().getName(),
|
||||
EntityType.REMOTE_PROCTORING_ROOM))
|
||||
.withParentEntityKey(entityKey);
|
||||
this.proctorRoomConnectionsPopup.show(pc, e.getKey().getSubject());
|
||||
});
|
||||
}
|
||||
});
|
||||
tree.setData(SHOW_CONNECTION_ACTION_APPLIED, true);
|
||||
}
|
||||
}
|
||||
addRoomConnectionsPopupListener(entityKey, pageContext, rooms);
|
||||
rooms.entrySet().stream()
|
||||
.filter(entry -> entry.getKey().equals(room))
|
||||
.findFirst()
|
||||
.ifPresent(entry -> processProctorRoomActionActivation(
|
||||
entry.getValue(),
|
||||
room,
|
||||
pageContext));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void processProctorRoomActionActivation(
|
||||
final TreeItem treeItem,
|
||||
final RemoteProctoringRoom room,
|
||||
final PageContext pageContext) {
|
||||
|
||||
try {
|
||||
final Display display = pageContext.getRoot().getDisplay();
|
||||
final PageAction action = (PageAction) treeItem.getData(ActionPane.ACTION_EVENT_CALL_KEY);
|
||||
final Image image = room.roomSize > 0
|
||||
? action.definition.icon.getImage(display)
|
||||
: action.definition.icon.getGreyedImage(display);
|
||||
treeItem.setImage(image);
|
||||
treeItem.setForeground(room.roomSize > 0 ? null : new Color(display, Constants.GREY_DISABLED));
|
||||
} catch (final Exception e) {
|
||||
log.warn("Failed to set Proctor-Room-Activation: ", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private void addRoomConnectionsPopupListener(
|
||||
final EntityKey entityKey,
|
||||
final PageContext pageContext,
|
||||
final Map<RemoteProctoringRoom, TreeItem> rooms) {
|
||||
|
||||
if (!rooms.isEmpty()) {
|
||||
final TreeItem treeItem = rooms.values().iterator().next();
|
||||
final Tree tree = treeItem.getParent();
|
||||
if (tree.getData(SHOW_CONNECTION_ACTION_APPLIED) == null) {
|
||||
tree.addListener(SWT.Selection, event -> {
|
||||
final TreeItem item = (TreeItem) event.item;
|
||||
item.getParent().deselectAll();
|
||||
if (event.button == 3) {
|
||||
rooms.entrySet()
|
||||
.stream()
|
||||
.filter(e -> e.getValue().equals(item))
|
||||
.findFirst()
|
||||
.ifPresent(e -> {
|
||||
if (e.getKey().roomSize > 0) {
|
||||
final PageContext pc = pageContext.copy()
|
||||
.clearAttributes()
|
||||
.withEntityKey(new EntityKey(e.getKey().getName(),
|
||||
EntityType.REMOTE_PROCTORING_ROOM))
|
||||
.withParentEntityKey(entityKey);
|
||||
this.proctorRoomConnectionsPopup.show(pc, e.getKey().getSubject());
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
tree.setData(SHOW_CONNECTION_ACTION_APPLIED, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int getActualRoomSize(final RemoteProctoringRoom room, final Map<RemoteProctoringRoom, TreeItem> rooms) {
|
||||
return rooms.entrySet().stream()
|
||||
.filter(entry -> entry.getKey().equals(room))
|
||||
.findFirst()
|
||||
.map(entry -> entry.getKey().roomSize)
|
||||
.orElseGet(() -> 1);
|
||||
}
|
||||
|
||||
private PageAction showExamProctoringRoom(
|
||||
final ProctoringSettings proctoringSettings,
|
||||
final RemoteProctoringRoom room,
|
||||
final Map<RemoteProctoringRoom, TreeItem> rooms,
|
||||
final PageAction action) {
|
||||
|
||||
final int actualRoomSize = getActualRoomSize(room, rooms);
|
||||
if (actualRoomSize <= 0) {
|
||||
return action;
|
||||
}
|
||||
|
||||
final SEBProctoringConnectionData proctoringConnectionData = this.pageService
|
||||
.getRestService()
|
||||
.getBuilder(GetProctorRoomConnectionData.class)
|
||||
|
|
|
@ -47,7 +47,7 @@ import ch.ethz.seb.sebserver.gui.widget.WidgetFactory.CustomVariant;
|
|||
@Component
|
||||
public class ActionPane implements TemplateComposer {
|
||||
|
||||
private static final String ACTION_EVENT_CALL_KEY = "ACTION_EVENT_CALL";
|
||||
public static final String ACTION_EVENT_CALL_KEY = "ACTION_EVENT_CALL";
|
||||
private static final LocTextKey TITLE_KEY = new LocTextKey("sebserver.actionpane.title");
|
||||
|
||||
private final PageService pageService;
|
||||
|
@ -226,7 +226,7 @@ public class ActionPane implements TemplateComposer {
|
|||
final Tree actions = this.widgetFactory.treeLocalized(
|
||||
composite,
|
||||
SWT.SINGLE | SWT.FULL_SELECTION | SWT.NO_SCROLL);
|
||||
actions.setData(RWT.CUSTOM_VARIANT, "actions");
|
||||
actions.setData(RWT.CUSTOM_VARIANT, CustomVariant.ACTIONS.key);
|
||||
final GridData gridData = new GridData(SWT.FILL, SWT.TOP, true, false);
|
||||
actions.setLayoutData(gridData);
|
||||
final Template template = new Template();
|
||||
|
|
|
@ -99,7 +99,6 @@ public class JitsiMeetProctoringView implements RemoteProctoringView {
|
|||
final GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
|
||||
browser.setLayoutData(gridData);
|
||||
browser.setUrl(url);
|
||||
//browser.layout();
|
||||
browser.setBackground(new Color(parent.getDisplay(), 100, 100, 100));
|
||||
|
||||
final Composite footer = new Composite(content, SWT.NONE | SWT.NO_SCROLL);
|
||||
|
@ -118,12 +117,14 @@ public class JitsiMeetProctoringView implements RemoteProctoringView {
|
|||
.closeRoom(proctoringWindowData.connectionData.roomName));
|
||||
|
||||
final BroadcastActionState broadcastActionState = new BroadcastActionState();
|
||||
final String connectionTokens = getConnectionTokens(proctoringWindowData);
|
||||
|
||||
final Button broadcastAudioAction = widgetFactory.buttonLocalized(footer, BROADCAST_AUDIO_ON_TEXT_KEY);
|
||||
broadcastAudioAction.setLayoutData(new RowData(150, 30));
|
||||
broadcastAudioAction.addListener(SWT.Selection, event -> toggleBroadcastAudio(
|
||||
proctoringWindowData.examId,
|
||||
proctoringWindowData.connectionData.roomName,
|
||||
connectionTokens,
|
||||
broadcastAudioAction));
|
||||
broadcastAudioAction.setData(BroadcastActionState.KEY_NAME, broadcastActionState);
|
||||
|
||||
|
@ -132,6 +133,7 @@ public class JitsiMeetProctoringView implements RemoteProctoringView {
|
|||
broadcastVideoAction.addListener(SWT.Selection, event -> toggleBroadcastVideo(
|
||||
proctoringWindowData.examId,
|
||||
proctoringWindowData.connectionData.roomName,
|
||||
connectionTokens,
|
||||
broadcastVideoAction,
|
||||
broadcastAudioAction));
|
||||
broadcastVideoAction.setData(BroadcastActionState.KEY_NAME, broadcastActionState);
|
||||
|
@ -141,12 +143,26 @@ public class JitsiMeetProctoringView implements RemoteProctoringView {
|
|||
chatAction.addListener(SWT.Selection, event -> toggleChat(
|
||||
proctoringWindowData.examId,
|
||||
proctoringWindowData.connectionData.roomName,
|
||||
connectionTokens,
|
||||
chatAction));
|
||||
chatAction.setData(BroadcastActionState.KEY_NAME, broadcastActionState);
|
||||
|
||||
}
|
||||
|
||||
private void toggleBroadcastAudio(final String examId, final String roomName, final Button broadcastAction) {
|
||||
private String getConnectionTokens(final ProctoringWindowData proctoringWindowData) {
|
||||
final String connectionTokens = this.pageService
|
||||
.getCurrentUser()
|
||||
.getProctoringGUIService()
|
||||
.getRoomConnectionTokens(proctoringWindowData.connectionData.roomName);
|
||||
return connectionTokens == null ? "" : connectionTokens;
|
||||
}
|
||||
|
||||
private void toggleBroadcastAudio(
|
||||
final String examId,
|
||||
final String roomName,
|
||||
final String connectionTokens,
|
||||
final Button broadcastAction) {
|
||||
|
||||
final BroadcastActionState state =
|
||||
(BroadcastActionState) broadcastAction.getData(BroadcastActionState.KEY_NAME);
|
||||
if (state.audio) {
|
||||
|
@ -154,6 +170,7 @@ public class JitsiMeetProctoringView implements RemoteProctoringView {
|
|||
this.pageService.getRestService().getBuilder(SendProctoringBroadcastOffInstruction.class)
|
||||
.withURIVariable(API.PARAM_MODEL_ID, examId)
|
||||
.withFormParam(Domain.REMOTE_PROCTORING_ROOM.ATTR_ID, roomName)
|
||||
.withFormParam(API.EXAM_API_SEB_CONNECTION_TOKEN, connectionTokens)
|
||||
.withFormParam(
|
||||
ClientInstruction.SEB_INSTRUCTION_ATTRIBUTES.SEB_RECONFIGURE_SETTINGS.JITSI_RECEIVE_AUDIO,
|
||||
Constants.TRUE_STRING)
|
||||
|
@ -164,6 +181,7 @@ public class JitsiMeetProctoringView implements RemoteProctoringView {
|
|||
this.pageService.getRestService().getBuilder(SendProctoringBroadcastOnInstruction.class)
|
||||
.withURIVariable(API.PARAM_MODEL_ID, examId)
|
||||
.withFormParam(Domain.REMOTE_PROCTORING_ROOM.ATTR_ID, roomName)
|
||||
.withFormParam(API.EXAM_API_SEB_CONNECTION_TOKEN, connectionTokens)
|
||||
.withFormParam(
|
||||
ClientInstruction.SEB_INSTRUCTION_ATTRIBUTES.SEB_RECONFIGURE_SETTINGS.JITSI_RECEIVE_AUDIO,
|
||||
Constants.TRUE_STRING)
|
||||
|
@ -176,6 +194,7 @@ public class JitsiMeetProctoringView implements RemoteProctoringView {
|
|||
private void toggleBroadcastVideo(
|
||||
final String examId,
|
||||
final String roomName,
|
||||
final String connectionTokens,
|
||||
final Button videoAction,
|
||||
final Button audioAction) {
|
||||
final BroadcastActionState state =
|
||||
|
@ -187,6 +206,7 @@ public class JitsiMeetProctoringView implements RemoteProctoringView {
|
|||
this.pageService.getRestService().getBuilder(SendProctoringBroadcastOffInstruction.class)
|
||||
.withURIVariable(API.PARAM_MODEL_ID, examId)
|
||||
.withFormParam(Domain.REMOTE_PROCTORING_ROOM.ATTR_ID, roomName)
|
||||
.withFormParam(API.EXAM_API_SEB_CONNECTION_TOKEN, connectionTokens)
|
||||
.withFormParam(
|
||||
ClientInstruction.SEB_INSTRUCTION_ATTRIBUTES.SEB_RECONFIGURE_SETTINGS.JITSI_RECEIVE_AUDIO,
|
||||
Constants.TRUE_STRING)
|
||||
|
@ -201,6 +221,7 @@ public class JitsiMeetProctoringView implements RemoteProctoringView {
|
|||
this.pageService.getRestService().getBuilder(SendProctoringBroadcastOnInstruction.class)
|
||||
.withURIVariable(API.PARAM_MODEL_ID, examId)
|
||||
.withFormParam(Domain.REMOTE_PROCTORING_ROOM.ATTR_ID, roomName)
|
||||
.withFormParam(API.EXAM_API_SEB_CONNECTION_TOKEN, connectionTokens)
|
||||
.withFormParam(
|
||||
ClientInstruction.SEB_INSTRUCTION_ATTRIBUTES.SEB_RECONFIGURE_SETTINGS.JITSI_RECEIVE_AUDIO,
|
||||
Constants.TRUE_STRING)
|
||||
|
@ -214,7 +235,12 @@ public class JitsiMeetProctoringView implements RemoteProctoringView {
|
|||
state.audio = state.video;
|
||||
}
|
||||
|
||||
private void toggleChat(final String examId, final String roomName, final Button broadcastAction) {
|
||||
private void toggleChat(
|
||||
final String examId,
|
||||
final String roomName,
|
||||
final String connectionTokens,
|
||||
final Button broadcastAction) {
|
||||
|
||||
final BroadcastActionState state =
|
||||
(BroadcastActionState) broadcastAction.getData(BroadcastActionState.KEY_NAME);
|
||||
if (state.chat) {
|
||||
|
@ -222,6 +248,7 @@ public class JitsiMeetProctoringView implements RemoteProctoringView {
|
|||
this.pageService.getRestService().getBuilder(SendProctoringBroadcastOffInstruction.class)
|
||||
.withURIVariable(API.PARAM_MODEL_ID, examId)
|
||||
.withFormParam(Domain.REMOTE_PROCTORING_ROOM.ATTR_ID, roomName)
|
||||
.withFormParam(API.EXAM_API_SEB_CONNECTION_TOKEN, connectionTokens)
|
||||
.withFormParam(
|
||||
ClientInstruction.SEB_INSTRUCTION_ATTRIBUTES.SEB_RECONFIGURE_SETTINGS.JITSI_ALLOW_CHAT,
|
||||
Constants.TRUE_STRING)
|
||||
|
@ -232,6 +259,7 @@ public class JitsiMeetProctoringView implements RemoteProctoringView {
|
|||
this.pageService.getRestService().getBuilder(SendProctoringBroadcastOnInstruction.class)
|
||||
.withURIVariable(API.PARAM_MODEL_ID, examId)
|
||||
.withFormParam(Domain.REMOTE_PROCTORING_ROOM.ATTR_ID, roomName)
|
||||
.withFormParam(API.EXAM_API_SEB_CONNECTION_TOKEN, connectionTokens)
|
||||
.withFormParam(
|
||||
ClientInstruction.SEB_INSTRUCTION_ATTRIBUTES.SEB_RECONFIGURE_SETTINGS.JITSI_ALLOW_CHAT,
|
||||
Constants.TRUE_STRING)
|
||||
|
|
|
@ -61,13 +61,24 @@ public class ProctoringGUIService {
|
|||
return this.rooms.keySet();
|
||||
}
|
||||
|
||||
public String getRoomConnectionTokens(final String roomName) {
|
||||
if (this.rooms.containsKey(roomName)) {
|
||||
return StringUtils.join(this.rooms.get(roomName).connections, Constants.COMMA);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static ProctoringWindowData getCurrentProctoringWindowData() {
|
||||
return (ProctoringWindowData) RWT.getUISession()
|
||||
.getHttpSession()
|
||||
.getAttribute(SESSION_ATTR_PROCTORING_DATA);
|
||||
}
|
||||
|
||||
public static void setCurrentProctoringWindowData(final String examId, final SEBProctoringConnectionData data) {
|
||||
public static void setCurrentProctoringWindowData(
|
||||
final String examId,
|
||||
final SEBProctoringConnectionData data) {
|
||||
|
||||
RWT.getUISession().getHttpSession().setAttribute(
|
||||
SESSION_ATTR_PROCTORING_DATA,
|
||||
new ProctoringWindowData(examId, data));
|
||||
|
@ -220,8 +231,9 @@ public class ProctoringGUIService {
|
|||
public final String examId;
|
||||
public final SEBProctoringConnectionData connectionData;
|
||||
|
||||
protected ProctoringWindowData(final String examId, final SEBProctoringConnectionData connectionData) {
|
||||
super();
|
||||
protected ProctoringWindowData(
|
||||
final String examId,
|
||||
final SEBProctoringConnectionData connectionData) {
|
||||
this.examId = examId;
|
||||
this.connectionData = connectionData;
|
||||
}
|
||||
|
|
|
@ -174,6 +174,8 @@ public class WidgetFactory {
|
|||
TEXT_ACTION("action"),
|
||||
TEXT_READONLY("readonlyText"),
|
||||
|
||||
ACTIONS("actions"),
|
||||
|
||||
FORM_CENTER("form-center"),
|
||||
SELECTION("selection"),
|
||||
SELECTED("selected"),
|
||||
|
|
|
@ -72,36 +72,6 @@ public class ExamJITSIProctoringService implements ExamProctoringService {
|
|||
return null;
|
||||
}
|
||||
|
||||
// @Override
|
||||
// public Result<SEBProctoringConnectionData> createProctorPrivateRoomConnection(
|
||||
// final ProctoringSettings proctoringSettings,
|
||||
// final String connectionToken) {
|
||||
//
|
||||
// return Result.tryCatch(() -> {
|
||||
//
|
||||
// final ClientConnectionData clientConnection = this.examSessionService.getConnectionData(connectionToken)
|
||||
// .getOrThrow();
|
||||
//
|
||||
// final long expTime = forExam(proctoringSettings);
|
||||
// final Encoder urlEncoder = Base64.getUrlEncoder().withoutPadding();
|
||||
// final String roomName = urlEncoder.encodeToString(
|
||||
// Utils.toByteArray(clientConnection.clientConnection.connectionToken));
|
||||
//
|
||||
// return createProctoringConnectionData(
|
||||
// proctoringSettings.serverType,
|
||||
// connectionToken,
|
||||
// proctoringSettings.serverURL,
|
||||
// proctoringSettings.appKey,
|
||||
// proctoringSettings.getAppSecret(),
|
||||
// this.authorizationService.getUserService().getCurrentUser().getUsername(),
|
||||
// "seb-server",
|
||||
// roomName,
|
||||
// clientConnection.clientConnection.userSessionId,
|
||||
// expTime)
|
||||
// .getOrThrow();
|
||||
// });
|
||||
// }
|
||||
|
||||
@Override
|
||||
public Result<SEBProctoringConnectionData> createProctorPublicRoomConnection(
|
||||
final ProctoringSettings proctoringSettings,
|
||||
|
|
|
@ -388,7 +388,10 @@ public class ExamMonitoringController {
|
|||
@PathVariable(name = API.PARAM_MODEL_ID) final Long examId,
|
||||
@RequestParam(
|
||||
name = Domain.REMOTE_PROCTORING_ROOM.ATTR_ID,
|
||||
required = true) final String roomName,
|
||||
required = false) final String roomName,
|
||||
@RequestParam(
|
||||
name = API.EXAM_API_SEB_CONNECTION_TOKEN,
|
||||
required = false) final String connectionTokens,
|
||||
@RequestParam(
|
||||
name = ClientInstruction.SEB_INSTRUCTION_ATTRIBUTES.SEB_RECONFIGURE_SETTINGS.JITSI_RECEIVE_AUDIO,
|
||||
required = false) final Boolean sendReceiveAudio,
|
||||
|
@ -429,21 +432,46 @@ public class ExamMonitoringController {
|
|||
return;
|
||||
}
|
||||
|
||||
this.examProcotringRoomService.getRoomConnections(examId, roomName)
|
||||
.getOrThrow()
|
||||
.stream()
|
||||
.forEach(connection -> {
|
||||
this.sebInstructionService.registerInstruction(
|
||||
examId,
|
||||
InstructionType.SEB_RECONFIGURE_SETTINGS,
|
||||
attributes,
|
||||
connection.connectionToken,
|
||||
true)
|
||||
.onError(error -> log.error(
|
||||
"Failed to register reconfiguring instruction for connection: {}",
|
||||
connection.connectionToken,
|
||||
error));
|
||||
});
|
||||
if (StringUtils.isNotBlank(connectionTokens)) {
|
||||
final boolean single = connectionTokens.contains(Constants.LIST_SEPARATOR);
|
||||
(single
|
||||
? Arrays.asList(StringUtils.split(connectionTokens, Constants.LIST_SEPARATOR))
|
||||
: Arrays.asList(connectionTokens))
|
||||
.stream()
|
||||
.forEach(connectionToken -> {
|
||||
this.sebInstructionService.registerInstruction(
|
||||
examId,
|
||||
InstructionType.SEB_RECONFIGURE_SETTINGS,
|
||||
attributes,
|
||||
connectionToken,
|
||||
true)
|
||||
.onError(error -> log.error(
|
||||
"Failed to register reconfiguring instruction for connection: {}",
|
||||
connectionToken,
|
||||
error));
|
||||
|
||||
});
|
||||
} else if (StringUtils.isNotBlank(roomName)) {
|
||||
this.examProcotringRoomService.getRoomConnections(examId, roomName)
|
||||
.getOrThrow()
|
||||
.stream()
|
||||
.forEach(connection -> {
|
||||
this.sebInstructionService.registerInstruction(
|
||||
examId,
|
||||
InstructionType.SEB_RECONFIGURE_SETTINGS,
|
||||
attributes,
|
||||
connection.connectionToken,
|
||||
true)
|
||||
.onError(error -> log.error(
|
||||
"Failed to register reconfiguring instruction for connection: {}",
|
||||
connection.connectionToken,
|
||||
error));
|
||||
});
|
||||
} else {
|
||||
throw new RuntimeException("API attribute validation error: missing "
|
||||
+ Domain.REMOTE_PROCTORING_ROOM.ATTR_ID + " and/or" +
|
||||
API.EXAM_API_SEB_CONNECTION_TOKEN + " attribute");
|
||||
}
|
||||
}
|
||||
|
||||
@RequestMapping(
|
||||
|
@ -461,6 +489,9 @@ public class ExamMonitoringController {
|
|||
@RequestParam(
|
||||
name = Domain.REMOTE_PROCTORING_ROOM.ATTR_ID,
|
||||
required = true) final String roomName,
|
||||
@RequestParam(
|
||||
name = API.EXAM_API_SEB_CONNECTION_TOKEN,
|
||||
required = true) final String connectionTokens,
|
||||
@RequestParam(
|
||||
name = ClientInstruction.SEB_INSTRUCTION_ATTRIBUTES.SEB_RECONFIGURE_SETTINGS.JITSI_RECEIVE_AUDIO,
|
||||
required = false) final Boolean sendReceiveAudio,
|
||||
|
@ -501,21 +532,46 @@ public class ExamMonitoringController {
|
|||
return;
|
||||
}
|
||||
|
||||
this.examProcotringRoomService.getRoomConnections(examId, roomName)
|
||||
.getOrThrow()
|
||||
.stream()
|
||||
.forEach(connection -> {
|
||||
this.sebInstructionService.registerInstruction(
|
||||
examId,
|
||||
InstructionType.SEB_RECONFIGURE_SETTINGS,
|
||||
attributes,
|
||||
connection.connectionToken,
|
||||
true)
|
||||
.onError(error -> log.error(
|
||||
"Failed to register reconfiguring instruction for connection: {}",
|
||||
connection.connectionToken,
|
||||
error));
|
||||
});
|
||||
if (StringUtils.isNotBlank(connectionTokens)) {
|
||||
final boolean single = connectionTokens.contains(Constants.LIST_SEPARATOR);
|
||||
(single
|
||||
? Arrays.asList(StringUtils.split(connectionTokens, Constants.LIST_SEPARATOR))
|
||||
: Arrays.asList(connectionTokens))
|
||||
.stream()
|
||||
.forEach(connectionToken -> {
|
||||
this.sebInstructionService.registerInstruction(
|
||||
examId,
|
||||
InstructionType.SEB_RECONFIGURE_SETTINGS,
|
||||
attributes,
|
||||
connectionToken,
|
||||
true)
|
||||
.onError(error -> log.error(
|
||||
"Failed to register reconfiguring instruction for connection: {}",
|
||||
connectionToken,
|
||||
error));
|
||||
});
|
||||
} else if (StringUtils.isNotBlank(roomName)) {
|
||||
|
||||
this.examProcotringRoomService.getRoomConnections(examId, roomName)
|
||||
.getOrThrow()
|
||||
.stream()
|
||||
.forEach(connection -> {
|
||||
this.sebInstructionService.registerInstruction(
|
||||
examId,
|
||||
InstructionType.SEB_RECONFIGURE_SETTINGS,
|
||||
attributes,
|
||||
connection.connectionToken,
|
||||
true)
|
||||
.onError(error -> log.error(
|
||||
"Failed to register reconfiguring instruction for connection: {}",
|
||||
connection.connectionToken,
|
||||
error));
|
||||
});
|
||||
} else {
|
||||
throw new RuntimeException("API attribute validation error: missing "
|
||||
+ Domain.REMOTE_PROCTORING_ROOM.ATTR_ID + " and/or" +
|
||||
API.EXAM_API_SEB_CONNECTION_TOKEN + " attribute");
|
||||
}
|
||||
}
|
||||
|
||||
@RequestMapping(
|
||||
|
|
Loading…
Reference in a new issue