SEBSERV-202 implemented
This commit is contained in:
parent
3f6bc5098d
commit
e49d8291d8
10 changed files with 229 additions and 84 deletions
|
@ -8,6 +8,8 @@
|
||||||
|
|
||||||
package ch.ethz.seb.sebserver.gbl.model.exam;
|
package ch.ethz.seb.sebserver.gbl.model.exam;
|
||||||
|
|
||||||
|
import java.util.EnumSet;
|
||||||
|
|
||||||
import org.apache.commons.lang3.BooleanUtils;
|
import org.apache.commons.lang3.BooleanUtils;
|
||||||
import org.hibernate.validator.constraints.URL;
|
import org.hibernate.validator.constraints.URL;
|
||||||
|
|
||||||
|
@ -29,12 +31,20 @@ public class ProctoringServiceSettings implements Entity {
|
||||||
ZOOM
|
ZOOM
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public enum ProctoringFeature {
|
||||||
|
TOWN_HALL,
|
||||||
|
ONE_TO_ONE,
|
||||||
|
BROADCAST,
|
||||||
|
ENABLE_CHAT
|
||||||
|
}
|
||||||
|
|
||||||
public static final String ATTR_ENABLE_PROCTORING = "enableProctoring";
|
public static final String ATTR_ENABLE_PROCTORING = "enableProctoring";
|
||||||
public static final String ATTR_SERVER_TYPE = "serverType";
|
public static final String ATTR_SERVER_TYPE = "serverType";
|
||||||
public static final String ATTR_SERVER_URL = "serverURL";
|
public static final String ATTR_SERVER_URL = "serverURL";
|
||||||
public static final String ATTR_APP_KEY = "appKey";
|
public static final String ATTR_APP_KEY = "appKey";
|
||||||
public static final String ATTR_APP_SECRET = "appSecret";
|
public static final String ATTR_APP_SECRET = "appSecret";
|
||||||
public static final String ATTR_COLLECTING_ROOM_SIZE = "collectingRoomSize";
|
public static final String ATTR_COLLECTING_ROOM_SIZE = "collectingRoomSize";
|
||||||
|
public static final String ATTR_ENABLED_FEATURES = "enabledFeatures";
|
||||||
public static final String ATTR_COLLECT_ALL_ROOM_NAME = "collectAllRoomName";
|
public static final String ATTR_COLLECT_ALL_ROOM_NAME = "collectAllRoomName";
|
||||||
public static final String ATTR_SERVICE_IN_USE = "serviceInUse";
|
public static final String ATTR_SERVICE_IN_USE = "serviceInUse";
|
||||||
|
|
||||||
|
@ -60,6 +70,9 @@ public class ProctoringServiceSettings implements Entity {
|
||||||
@JsonProperty(ATTR_COLLECTING_ROOM_SIZE)
|
@JsonProperty(ATTR_COLLECTING_ROOM_SIZE)
|
||||||
public final Integer collectingRoomSize;
|
public final Integer collectingRoomSize;
|
||||||
|
|
||||||
|
@JsonProperty(ATTR_ENABLED_FEATURES)
|
||||||
|
public final EnumSet<ProctoringFeature> enabledFeatures;
|
||||||
|
|
||||||
@JsonProperty(ATTR_SERVICE_IN_USE)
|
@JsonProperty(ATTR_SERVICE_IN_USE)
|
||||||
public final Boolean serviceInUse;
|
public final Boolean serviceInUse;
|
||||||
|
|
||||||
|
@ -70,6 +83,7 @@ public class ProctoringServiceSettings implements Entity {
|
||||||
@JsonProperty(ATTR_SERVER_TYPE) final ProctoringServerType serverType,
|
@JsonProperty(ATTR_SERVER_TYPE) final ProctoringServerType serverType,
|
||||||
@JsonProperty(ATTR_SERVER_URL) final String serverURL,
|
@JsonProperty(ATTR_SERVER_URL) final String serverURL,
|
||||||
@JsonProperty(ATTR_COLLECTING_ROOM_SIZE) final Integer collectingRoomSize,
|
@JsonProperty(ATTR_COLLECTING_ROOM_SIZE) final Integer collectingRoomSize,
|
||||||
|
@JsonProperty(ATTR_ENABLED_FEATURES) final EnumSet<ProctoringFeature> enabledFeatures,
|
||||||
@JsonProperty(ATTR_SERVICE_IN_USE) final Boolean serviceInUse,
|
@JsonProperty(ATTR_SERVICE_IN_USE) final Boolean serviceInUse,
|
||||||
@JsonProperty(ATTR_APP_KEY) final String appKey,
|
@JsonProperty(ATTR_APP_KEY) final String appKey,
|
||||||
@JsonProperty(ATTR_APP_SECRET) final CharSequence appSecret) {
|
@JsonProperty(ATTR_APP_SECRET) final CharSequence appSecret) {
|
||||||
|
@ -79,9 +93,11 @@ public class ProctoringServiceSettings implements Entity {
|
||||||
this.serverType = (serverType != null) ? serverType : ProctoringServerType.JITSI_MEET;
|
this.serverType = (serverType != null) ? serverType : ProctoringServerType.JITSI_MEET;
|
||||||
this.serverURL = serverURL;
|
this.serverURL = serverURL;
|
||||||
this.collectingRoomSize = (collectingRoomSize != null) ? collectingRoomSize : 20;
|
this.collectingRoomSize = (collectingRoomSize != null) ? collectingRoomSize : 20;
|
||||||
|
this.enabledFeatures = enabledFeatures != null ? enabledFeatures : EnumSet.allOf(ProctoringFeature.class);
|
||||||
this.serviceInUse = serviceInUse;
|
this.serviceInUse = serviceInUse;
|
||||||
this.appKey = appKey;
|
this.appKey = appKey;
|
||||||
this.appSecret = appSecret;
|
this.appSecret = appSecret;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -119,6 +135,10 @@ public class ProctoringServiceSettings implements Entity {
|
||||||
return this.collectingRoomSize;
|
return this.collectingRoomSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public EnumSet<ProctoringFeature> getEnabledFeatures() {
|
||||||
|
return this.enabledFeatures;
|
||||||
|
}
|
||||||
|
|
||||||
public String getAppKey() {
|
public String getAppKey() {
|
||||||
return this.appKey;
|
return this.appKey;
|
||||||
}
|
}
|
||||||
|
@ -162,7 +182,7 @@ public class ProctoringServiceSettings implements Entity {
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
final StringBuilder builder = new StringBuilder();
|
final StringBuilder builder = new StringBuilder();
|
||||||
builder.append("ProctoringSettings [examId=");
|
builder.append("ProctoringServiceSettings [examId=");
|
||||||
builder.append(this.examId);
|
builder.append(this.examId);
|
||||||
builder.append(", enableProctoring=");
|
builder.append(", enableProctoring=");
|
||||||
builder.append(this.enableProctoring);
|
builder.append(this.enableProctoring);
|
||||||
|
@ -170,8 +190,16 @@ public class ProctoringServiceSettings implements Entity {
|
||||||
builder.append(this.serverType);
|
builder.append(this.serverType);
|
||||||
builder.append(", serverURL=");
|
builder.append(", serverURL=");
|
||||||
builder.append(this.serverURL);
|
builder.append(this.serverURL);
|
||||||
|
builder.append(", appKey=");
|
||||||
|
builder.append(this.appKey);
|
||||||
|
builder.append(", appSecret=");
|
||||||
|
builder.append(this.appSecret);
|
||||||
builder.append(", collectingRoomSize=");
|
builder.append(", collectingRoomSize=");
|
||||||
builder.append(this.collectingRoomSize);
|
builder.append(this.collectingRoomSize);
|
||||||
|
builder.append(", enabledFeatures=");
|
||||||
|
builder.append(this.enabledFeatures);
|
||||||
|
builder.append(", serviceInUse=");
|
||||||
|
builder.append(this.serviceInUse);
|
||||||
builder.append("]");
|
builder.append("]");
|
||||||
return builder.toString();
|
return builder.toString();
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,11 +8,15 @@
|
||||||
|
|
||||||
package ch.ethz.seb.sebserver.gui.content;
|
package ch.ethz.seb.sebserver.gui.content;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.EnumSet;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import org.apache.commons.lang3.BooleanUtils;
|
import org.apache.commons.lang3.BooleanUtils;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.eclipse.swt.widgets.Composite;
|
import org.eclipse.swt.widgets.Composite;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
@ -23,6 +27,7 @@ import ch.ethz.seb.sebserver.gbl.Constants;
|
||||||
import ch.ethz.seb.sebserver.gbl.api.API;
|
import ch.ethz.seb.sebserver.gbl.api.API;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
|
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringServiceSettings;
|
import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringServiceSettings;
|
||||||
|
import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringServiceSettings.ProctoringFeature;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringServiceSettings.ProctoringServerType;
|
import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringServiceSettings.ProctoringServerType;
|
||||||
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
|
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
|
||||||
import ch.ethz.seb.sebserver.gbl.util.Utils;
|
import ch.ethz.seb.sebserver.gbl.util.Utils;
|
||||||
|
@ -67,6 +72,8 @@ public class ExamProctoringSettings {
|
||||||
new LocTextKey("sebserver.exam.proctoring.form.appkey");
|
new LocTextKey("sebserver.exam.proctoring.form.appkey");
|
||||||
private final static LocTextKey SEB_PROCTORING_FORM_SECRET =
|
private final static LocTextKey SEB_PROCTORING_FORM_SECRET =
|
||||||
new LocTextKey("sebserver.exam.proctoring.form.secret");
|
new LocTextKey("sebserver.exam.proctoring.form.secret");
|
||||||
|
private final static LocTextKey SEB_PROCTORING_FORM_FEATURES =
|
||||||
|
new LocTextKey("sebserver.exam.proctoring.form.features");
|
||||||
|
|
||||||
Function<PageAction, PageAction> settingsFunction(final PageService pageService, final boolean modifyGrant) {
|
Function<PageAction, PageAction> settingsFunction(final PageService pageService, final boolean modifyGrant) {
|
||||||
|
|
||||||
|
@ -131,12 +138,20 @@ public class ExamProctoringSettings {
|
||||||
final ProctoringServerType serverType = ProctoringServerType
|
final ProctoringServerType serverType = ProctoringServerType
|
||||||
.valueOf(form.getFieldValue(ProctoringServiceSettings.ATTR_SERVER_TYPE));
|
.valueOf(form.getFieldValue(ProctoringServiceSettings.ATTR_SERVER_TYPE));
|
||||||
|
|
||||||
|
final String features = form.getFieldValue(ProctoringServiceSettings.ATTR_ENABLED_FEATURES);
|
||||||
|
final EnumSet<ProctoringFeature> featureFlags =
|
||||||
|
EnumSet.copyOf(Arrays.asList(StringUtils.split(features, Constants.LIST_SEPARATOR))
|
||||||
|
.stream()
|
||||||
|
.map(str -> ProctoringFeature.valueOf(str))
|
||||||
|
.collect(Collectors.toSet()));
|
||||||
|
|
||||||
examProctoring = new ProctoringServiceSettings(
|
examProctoring = new ProctoringServiceSettings(
|
||||||
Long.parseLong(entityKey.modelId),
|
Long.parseLong(entityKey.modelId),
|
||||||
enabled,
|
enabled,
|
||||||
serverType,
|
serverType,
|
||||||
form.getFieldValue(ProctoringServiceSettings.ATTR_SERVER_URL),
|
form.getFieldValue(ProctoringServiceSettings.ATTR_SERVER_URL),
|
||||||
Integer.parseInt(form.getFieldValue(ProctoringServiceSettings.ATTR_COLLECTING_ROOM_SIZE)),
|
Integer.parseInt(form.getFieldValue(ProctoringServiceSettings.ATTR_COLLECTING_ROOM_SIZE)),
|
||||||
|
featureFlags,
|
||||||
false,
|
false,
|
||||||
form.getFieldValue(ProctoringServiceSettings.ATTR_APP_KEY),
|
form.getFieldValue(ProctoringServiceSettings.ATTR_APP_KEY),
|
||||||
form.getFieldValue(ProctoringServiceSettings.ATTR_APP_SECRET));
|
form.getFieldValue(ProctoringServiceSettings.ATTR_APP_SECRET));
|
||||||
|
@ -239,15 +254,6 @@ public class ExamProctoringSettings {
|
||||||
ProctoringServiceSettings.ATTR_SERVER_URL,
|
ProctoringServiceSettings.ATTR_SERVER_URL,
|
||||||
SEB_PROCTORING_FORM_URL,
|
SEB_PROCTORING_FORM_URL,
|
||||||
proctoringSettings.serverURL))
|
proctoringSettings.serverURL))
|
||||||
.withDefaultSpanInput(1)
|
|
||||||
|
|
||||||
.addField(FormBuilder.text(
|
|
||||||
ProctoringServiceSettings.ATTR_COLLECTING_ROOM_SIZE,
|
|
||||||
SEB_PROCTORING_FORM_ROOM_SIZE,
|
|
||||||
String.valueOf(proctoringSettings.getCollectingRoomSize()))
|
|
||||||
.asNumber(numString -> Long.parseLong(numString)))
|
|
||||||
.withDefaultSpanInput(5)
|
|
||||||
.withDefaultSpanEmptyCell(4)
|
|
||||||
|
|
||||||
.addField(FormBuilder.text(
|
.addField(FormBuilder.text(
|
||||||
ProctoringServiceSettings.ATTR_APP_KEY,
|
ProctoringServiceSettings.ATTR_APP_KEY,
|
||||||
|
@ -262,6 +268,22 @@ public class ExamProctoringSettings {
|
||||||
? String.valueOf(proctoringSettings.appSecret)
|
? String.valueOf(proctoringSettings.appSecret)
|
||||||
: null))
|
: null))
|
||||||
|
|
||||||
|
.withDefaultSpanInput(1)
|
||||||
|
.addField(FormBuilder.text(
|
||||||
|
ProctoringServiceSettings.ATTR_COLLECTING_ROOM_SIZE,
|
||||||
|
SEB_PROCTORING_FORM_ROOM_SIZE,
|
||||||
|
String.valueOf(proctoringSettings.getCollectingRoomSize()))
|
||||||
|
.asNumber(numString -> Long.parseLong(numString)))
|
||||||
|
.withEmptyCellSeparation(true)
|
||||||
|
.withDefaultSpanEmptyCell(4)
|
||||||
|
.withDefaultSpanInput(5)
|
||||||
|
|
||||||
|
.addField(FormBuilder.multiCheckboxSelection(
|
||||||
|
ProctoringServiceSettings.ATTR_ENABLED_FEATURES,
|
||||||
|
SEB_PROCTORING_FORM_FEATURES,
|
||||||
|
StringUtils.join(proctoringSettings.enabledFeatures, Constants.LIST_SEPARATOR),
|
||||||
|
resourceService::examProctoringFeaturesResources))
|
||||||
|
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
if (proctoringSettings.serviceInUse) {
|
if (proctoringSettings.serviceInUse) {
|
||||||
|
|
|
@ -27,6 +27,7 @@ import ch.ethz.seb.sebserver.gbl.model.EntityKey;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.exam.Exam;
|
import ch.ethz.seb.sebserver.gbl.model.exam.Exam;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.exam.Indicator;
|
import ch.ethz.seb.sebserver.gbl.model.exam.Indicator;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringServiceSettings;
|
import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringServiceSettings;
|
||||||
|
import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringServiceSettings.ProctoringFeature;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.session.ClientConnection.ConnectionStatus;
|
import ch.ethz.seb.sebserver.gbl.model.session.ClientConnection.ConnectionStatus;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.session.ClientConnectionData;
|
import ch.ethz.seb.sebserver.gbl.model.session.ClientConnectionData;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.session.ClientEvent;
|
import ch.ethz.seb.sebserver.gbl.model.session.ClientEvent;
|
||||||
|
@ -367,27 +368,31 @@ public class MonitoringClientConnection implements TemplateComposer {
|
||||||
connectionData.clientConnection.status.indicatorActiveStatus);
|
connectionData.clientConnection.status.indicatorActiveStatus);
|
||||||
|
|
||||||
if (connectionData.clientConnection.status == ConnectionStatus.ACTIVE) {
|
if (connectionData.clientConnection.status == ConnectionStatus.ACTIVE) {
|
||||||
final ProctoringServiceSettings procotringSettings = restService
|
final ProctoringServiceSettings proctoringSettings = restService
|
||||||
.getBuilder(GetProctoringSettings.class)
|
.getBuilder(GetProctoringSettings.class)
|
||||||
.withURIVariable(API.PARAM_MODEL_ID, parentEntityKey.modelId)
|
.withURIVariable(API.PARAM_MODEL_ID, parentEntityKey.modelId)
|
||||||
.call()
|
.call()
|
||||||
.onError(error -> log.error("Failed to get ProctoringServiceSettings", error))
|
.onError(error -> log.error("Failed to get ProctoringServiceSettings", error))
|
||||||
.getOr(null);
|
.getOr(null);
|
||||||
|
|
||||||
if (procotringSettings != null && procotringSettings.enableProctoring) {
|
if (proctoringSettings != null && proctoringSettings.enableProctoring) {
|
||||||
final ProctoringGUIService proctoringGUIService = this.resourceService
|
final ProctoringGUIService proctoringGUIService = this.resourceService
|
||||||
.getCurrentUser()
|
.getCurrentUser()
|
||||||
.getProctoringGUIService();
|
.getProctoringGUIService();
|
||||||
actionBuilder
|
|
||||||
.newAction(ActionDefinition.MONITOR_EXAM_CLIENT_CONNECTION_PROCTORING)
|
|
||||||
.withEntityKey(parentEntityKey)
|
|
||||||
.withExec(action -> this.monitoringProctoringService.openOneToOneRoom(
|
|
||||||
action,
|
|
||||||
connectionData,
|
|
||||||
proctoringGUIService))
|
|
||||||
.noEventPropagation()
|
|
||||||
.publish()
|
|
||||||
|
|
||||||
|
if (proctoringSettings.enabledFeatures.contains(ProctoringFeature.ONE_TO_ONE)) {
|
||||||
|
actionBuilder
|
||||||
|
.newAction(ActionDefinition.MONITOR_EXAM_CLIENT_CONNECTION_PROCTORING)
|
||||||
|
.withEntityKey(parentEntityKey)
|
||||||
|
.withExec(action -> this.monitoringProctoringService.openOneToOneRoom(
|
||||||
|
action,
|
||||||
|
connectionData,
|
||||||
|
proctoringGUIService))
|
||||||
|
.noEventPropagation()
|
||||||
|
.publish();
|
||||||
|
}
|
||||||
|
|
||||||
|
actionBuilder
|
||||||
.newAction(ActionDefinition.MONITOR_EXAM_CLIENT_CONNECTION_EXAM_ROOM_PROCTORING)
|
.newAction(ActionDefinition.MONITOR_EXAM_CLIENT_CONNECTION_EXAM_ROOM_PROCTORING)
|
||||||
.withEntityKey(parentEntityKey)
|
.withEntityKey(parentEntityKey)
|
||||||
.withExec(action -> this.monitoringProctoringService.openExamCollectionProctorScreen(
|
.withExec(action -> this.monitoringProctoringService.openExamCollectionProctorScreen(
|
||||||
|
|
|
@ -34,6 +34,7 @@ import ch.ethz.seb.sebserver.gbl.model.EntityKey;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.exam.Exam;
|
import ch.ethz.seb.sebserver.gbl.model.exam.Exam;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.exam.Indicator;
|
import ch.ethz.seb.sebserver.gbl.model.exam.Indicator;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringServiceSettings;
|
import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringServiceSettings;
|
||||||
|
import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringServiceSettings.ProctoringFeature;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.session.ClientConnection.ConnectionStatus;
|
import ch.ethz.seb.sebserver.gbl.model.session.ClientConnection.ConnectionStatus;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.session.ClientConnectionData;
|
import ch.ethz.seb.sebserver.gbl.model.session.ClientConnectionData;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.user.UserRole;
|
import ch.ethz.seb.sebserver.gbl.model.user.UserRole;
|
||||||
|
@ -260,22 +261,24 @@ public class MonitoringRunningExam implements TemplateComposer {
|
||||||
.getOr(null);
|
.getOr(null);
|
||||||
|
|
||||||
if (proctoringSettings != null && proctoringSettings.enableProctoring) {
|
if (proctoringSettings != null && proctoringSettings.enableProctoring) {
|
||||||
|
if (proctoringSettings.enabledFeatures.contains(ProctoringFeature.TOWN_HALL)) {
|
||||||
|
|
||||||
actionBuilder.newAction(ActionDefinition.MONITOR_EXAM_OPEN_TOWNHALL_PROCTOR_ROOM)
|
actionBuilder.newAction(ActionDefinition.MONITOR_EXAM_OPEN_TOWNHALL_PROCTOR_ROOM)
|
||||||
.withEntityKey(entityKey)
|
.withEntityKey(entityKey)
|
||||||
.withExec(action -> this.monitoringProctoringService.toggleTownhallRoom(proctoringGUIService,
|
.withExec(action -> this.monitoringProctoringService.toggleTownhallRoom(proctoringGUIService,
|
||||||
action))
|
action))
|
||||||
.noEventPropagation()
|
.noEventPropagation()
|
||||||
.publish();
|
.publish();
|
||||||
|
|
||||||
if (this.monitoringProctoringService.isTownhallRoomActive(entityKey.modelId)) {
|
if (this.monitoringProctoringService.isTownhallRoomActive(entityKey.modelId)) {
|
||||||
this.pageService.firePageEvent(
|
this.pageService.firePageEvent(
|
||||||
new ActionActivationEvent(
|
new ActionActivationEvent(
|
||||||
true,
|
true,
|
||||||
new Tuple<>(
|
new Tuple<>(
|
||||||
ActionDefinition.MONITOR_EXAM_OPEN_TOWNHALL_PROCTOR_ROOM,
|
ActionDefinition.MONITOR_EXAM_OPEN_TOWNHALL_PROCTOR_ROOM,
|
||||||
ActionDefinition.MONITOR_EXAM_CLOSE_TOWNHALL_PROCTOR_ROOM)),
|
ActionDefinition.MONITOR_EXAM_CLOSE_TOWNHALL_PROCTOR_ROOM)),
|
||||||
pageContext);
|
pageContext);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.monitoringProctoringService.initCollectingRoomActions(
|
this.monitoringProctoringService.initCollectingRoomActions(
|
||||||
|
|
|
@ -43,6 +43,7 @@ import ch.ethz.seb.sebserver.gbl.model.exam.ExamConfigurationMap;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.exam.Indicator.IndicatorType;
|
import ch.ethz.seb.sebserver.gbl.model.exam.Indicator.IndicatorType;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.exam.OpenEdxSEBRestriction.PermissionComponent;
|
import ch.ethz.seb.sebserver.gbl.model.exam.OpenEdxSEBRestriction.PermissionComponent;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.exam.OpenEdxSEBRestriction.WhiteListPath;
|
import ch.ethz.seb.sebserver.gbl.model.exam.OpenEdxSEBRestriction.WhiteListPath;
|
||||||
|
import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringServiceSettings.ProctoringFeature;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringServiceSettings.ProctoringServerType;
|
import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringServiceSettings.ProctoringServerType;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetup.LmsType;
|
import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetup.LmsType;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.sebconfig.AttributeType;
|
import ch.ethz.seb.sebserver.gbl.model.sebconfig.AttributeType;
|
||||||
|
@ -122,6 +123,7 @@ public class ResourceService {
|
||||||
public static final String SEB_RESTRICTION_PERMISSIONS_PREFIX = "sebserver.exam.form.sebrestriction.permissions.";
|
public static final String SEB_RESTRICTION_PERMISSIONS_PREFIX = "sebserver.exam.form.sebrestriction.permissions.";
|
||||||
public static final String SEB_CLIENT_CONFIG_PURPOSE_PREFIX = "sebserver.clientconfig.config.purpose.";
|
public static final String SEB_CLIENT_CONFIG_PURPOSE_PREFIX = "sebserver.clientconfig.config.purpose.";
|
||||||
public static final String EXAM_PROCTORING_TYPE_PREFIX = "sebserver.exam.proctoring.type.servertype.";
|
public static final String EXAM_PROCTORING_TYPE_PREFIX = "sebserver.exam.proctoring.type.servertype.";
|
||||||
|
public static final String EXAM_PROCTORING_FEATURES_PREFIX = "sebserver.exam.proctoring.form.features.";
|
||||||
public static final String VDI_TYPE_PREFIX = "sebserver.clientconfig.form.vditype.";
|
public static final String VDI_TYPE_PREFIX = "sebserver.clientconfig.form.vditype.";
|
||||||
|
|
||||||
private static final String DISABLE_LMS_FLAG = "sebserver.gui.webservice.lms.disable.";
|
private static final String DISABLE_LMS_FLAG = "sebserver.gui.webservice.lms.disable.";
|
||||||
|
@ -422,6 +424,18 @@ public class ResourceService {
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<Tuple<String>> examProctoringFeaturesResources() {
|
||||||
|
return Arrays.stream(ProctoringFeature.values())
|
||||||
|
.map(type -> new Tuple3<>(
|
||||||
|
type.name(),
|
||||||
|
this.i18nSupport.getText(EXAM_PROCTORING_FEATURES_PREFIX + type.name()),
|
||||||
|
Utils.formatLineBreaks(this.i18nSupport.getText(
|
||||||
|
EXAM_PROCTORING_FEATURES_PREFIX + type.name() + Constants.TOOLTIP_TEXT_KEY_SUFFIX,
|
||||||
|
StringUtils.EMPTY))))
|
||||||
|
.sorted(RESOURCE_COMPARATOR)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
public List<Tuple<String>> vdiTypeResources() {
|
public List<Tuple<String>> vdiTypeResources() {
|
||||||
return Arrays.stream(VDIType.values())
|
return Arrays.stream(VDIType.values())
|
||||||
.map(type -> new Tuple3<>(
|
.map(type -> new Tuple3<>(
|
||||||
|
|
|
@ -23,11 +23,15 @@ import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import ch.ethz.seb.sebserver.gbl.Constants;
|
import ch.ethz.seb.sebserver.gbl.Constants;
|
||||||
|
import ch.ethz.seb.sebserver.gbl.api.API;
|
||||||
|
import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringServiceSettings;
|
||||||
|
import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringServiceSettings.ProctoringFeature;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringServiceSettings.ProctoringServerType;
|
import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringServiceSettings.ProctoringServerType;
|
||||||
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
|
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
|
||||||
import ch.ethz.seb.sebserver.gui.GuiServiceInfo;
|
import ch.ethz.seb.sebserver.gui.GuiServiceInfo;
|
||||||
import ch.ethz.seb.sebserver.gui.service.page.PageContext;
|
import ch.ethz.seb.sebserver.gui.service.page.PageContext;
|
||||||
import ch.ethz.seb.sebserver.gui.service.page.PageService;
|
import ch.ethz.seb.sebserver.gui.service.page.PageService;
|
||||||
|
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.GetProctoringSettings;
|
||||||
import ch.ethz.seb.sebserver.gui.service.session.proctoring.ProctoringGUIService;
|
import ch.ethz.seb.sebserver.gui.service.session.proctoring.ProctoringGUIService;
|
||||||
import ch.ethz.seb.sebserver.gui.service.session.proctoring.ProctoringGUIService.ProctoringWindowData;
|
import ch.ethz.seb.sebserver.gui.service.session.proctoring.ProctoringGUIService.ProctoringWindowData;
|
||||||
import ch.ethz.seb.sebserver.gui.widget.WidgetFactory;
|
import ch.ethz.seb.sebserver.gui.widget.WidgetFactory;
|
||||||
|
@ -62,6 +66,13 @@ public class JitsiMeetProctoringView extends AbstractProctoringView {
|
||||||
final ProctoringGUIService proctoringGUIService = this.pageService
|
final ProctoringGUIService proctoringGUIService = this.pageService
|
||||||
.getCurrentUser()
|
.getCurrentUser()
|
||||||
.getProctoringGUIService();
|
.getProctoringGUIService();
|
||||||
|
final ProctoringServiceSettings proctoringSettings = this.pageService
|
||||||
|
.getRestService()
|
||||||
|
.getBuilder(GetProctoringSettings.class)
|
||||||
|
.withURIVariable(API.PARAM_MODEL_ID, proctoringWindowData.examId)
|
||||||
|
.call()
|
||||||
|
.onError(error -> log.error("Failed to get ProctoringServiceSettings", error))
|
||||||
|
.getOr(null);
|
||||||
|
|
||||||
content.setLayout(gridLayout);
|
content.setLayout(gridLayout);
|
||||||
final GridData headerCell = new GridData(SWT.FILL, SWT.FILL, true, true);
|
final GridData headerCell = new GridData(SWT.FILL, SWT.FILL, true, true);
|
||||||
|
@ -99,31 +110,34 @@ public class JitsiMeetProctoringView extends AbstractProctoringView {
|
||||||
closeAction.addListener(SWT.Selection, event -> closeRoom(proctoringGUIService, proctoringWindowData));
|
closeAction.addListener(SWT.Selection, event -> closeRoom(proctoringGUIService, proctoringWindowData));
|
||||||
|
|
||||||
final BroadcastActionState broadcastActionState = new BroadcastActionState();
|
final BroadcastActionState broadcastActionState = new BroadcastActionState();
|
||||||
|
if (proctoringSettings.enabledFeatures.contains(ProctoringFeature.BROADCAST)) {
|
||||||
|
final Button broadcastAudioAction = widgetFactory.buttonLocalized(footer, BROADCAST_AUDIO_ON_TEXT_KEY);
|
||||||
|
broadcastAudioAction.setLayoutData(new RowData());
|
||||||
|
broadcastAudioAction.addListener(SWT.Selection, event -> toggleBroadcastAudio(
|
||||||
|
proctoringWindowData.examId,
|
||||||
|
proctoringWindowData.connectionData.roomName,
|
||||||
|
broadcastAudioAction));
|
||||||
|
broadcastAudioAction.setData(BroadcastActionState.KEY_NAME, broadcastActionState);
|
||||||
|
|
||||||
final Button broadcastAudioAction = widgetFactory.buttonLocalized(footer, BROADCAST_AUDIO_ON_TEXT_KEY);
|
final Button broadcastVideoAction = widgetFactory.buttonLocalized(footer, BROADCAST_VIDEO_ON_TEXT_KEY);
|
||||||
broadcastAudioAction.setLayoutData(new RowData());
|
broadcastVideoAction.setLayoutData(new RowData());
|
||||||
broadcastAudioAction.addListener(SWT.Selection, event -> toggleBroadcastAudio(
|
broadcastVideoAction.addListener(SWT.Selection, event -> toggleBroadcastVideo(
|
||||||
proctoringWindowData.examId,
|
proctoringWindowData.examId,
|
||||||
proctoringWindowData.connectionData.roomName,
|
proctoringWindowData.connectionData.roomName,
|
||||||
broadcastAudioAction));
|
broadcastVideoAction,
|
||||||
broadcastAudioAction.setData(BroadcastActionState.KEY_NAME, broadcastActionState);
|
broadcastAudioAction));
|
||||||
|
broadcastVideoAction.setData(BroadcastActionState.KEY_NAME, broadcastActionState);
|
||||||
|
}
|
||||||
|
|
||||||
final Button broadcastVideoAction = widgetFactory.buttonLocalized(footer, BROADCAST_VIDEO_ON_TEXT_KEY);
|
if (proctoringSettings.enabledFeatures.contains(ProctoringFeature.ENABLE_CHAT)) {
|
||||||
broadcastVideoAction.setLayoutData(new RowData());
|
final Button chatAction = widgetFactory.buttonLocalized(footer, CHAT_ON_TEXT_KEY);
|
||||||
broadcastVideoAction.addListener(SWT.Selection, event -> toggleBroadcastVideo(
|
chatAction.setLayoutData(new RowData());
|
||||||
proctoringWindowData.examId,
|
chatAction.addListener(SWT.Selection, event -> toggleChat(
|
||||||
proctoringWindowData.connectionData.roomName,
|
proctoringWindowData.examId,
|
||||||
broadcastVideoAction,
|
proctoringWindowData.connectionData.roomName,
|
||||||
broadcastAudioAction));
|
chatAction));
|
||||||
broadcastVideoAction.setData(BroadcastActionState.KEY_NAME, broadcastActionState);
|
chatAction.setData(BroadcastActionState.KEY_NAME, broadcastActionState);
|
||||||
|
}
|
||||||
final Button chatAction = widgetFactory.buttonLocalized(footer, CHAT_ON_TEXT_KEY);
|
|
||||||
chatAction.setLayoutData(new RowData());
|
|
||||||
chatAction.addListener(SWT.Selection, event -> toggleChat(
|
|
||||||
proctoringWindowData.examId,
|
|
||||||
proctoringWindowData.connectionData.roomName,
|
|
||||||
chatAction));
|
|
||||||
chatAction.setData(BroadcastActionState.KEY_NAME, broadcastActionState);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,11 +23,15 @@ import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import ch.ethz.seb.sebserver.gbl.Constants;
|
import ch.ethz.seb.sebserver.gbl.Constants;
|
||||||
|
import ch.ethz.seb.sebserver.gbl.api.API;
|
||||||
|
import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringServiceSettings;
|
||||||
|
import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringServiceSettings.ProctoringFeature;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringServiceSettings.ProctoringServerType;
|
import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringServiceSettings.ProctoringServerType;
|
||||||
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
|
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
|
||||||
import ch.ethz.seb.sebserver.gui.GuiServiceInfo;
|
import ch.ethz.seb.sebserver.gui.GuiServiceInfo;
|
||||||
import ch.ethz.seb.sebserver.gui.service.page.PageContext;
|
import ch.ethz.seb.sebserver.gui.service.page.PageContext;
|
||||||
import ch.ethz.seb.sebserver.gui.service.page.PageService;
|
import ch.ethz.seb.sebserver.gui.service.page.PageService;
|
||||||
|
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.GetProctoringSettings;
|
||||||
import ch.ethz.seb.sebserver.gui.service.session.proctoring.ProctoringGUIService;
|
import ch.ethz.seb.sebserver.gui.service.session.proctoring.ProctoringGUIService;
|
||||||
import ch.ethz.seb.sebserver.gui.service.session.proctoring.ProctoringGUIService.ProctoringWindowData;
|
import ch.ethz.seb.sebserver.gui.service.session.proctoring.ProctoringGUIService.ProctoringWindowData;
|
||||||
import ch.ethz.seb.sebserver.gui.widget.WidgetFactory;
|
import ch.ethz.seb.sebserver.gui.widget.WidgetFactory;
|
||||||
|
@ -62,6 +66,13 @@ public class ZoomProctoringView extends AbstractProctoringView {
|
||||||
final ProctoringGUIService proctoringGUIService = this.pageService
|
final ProctoringGUIService proctoringGUIService = this.pageService
|
||||||
.getCurrentUser()
|
.getCurrentUser()
|
||||||
.getProctoringGUIService();
|
.getProctoringGUIService();
|
||||||
|
final ProctoringServiceSettings proctoringSettings = this.pageService
|
||||||
|
.getRestService()
|
||||||
|
.getBuilder(GetProctoringSettings.class)
|
||||||
|
.withURIVariable(API.PARAM_MODEL_ID, proctoringWindowData.examId)
|
||||||
|
.call()
|
||||||
|
.onError(error -> log.error("Failed to get ProctoringServiceSettings", error))
|
||||||
|
.getOr(null);
|
||||||
|
|
||||||
content.setLayout(gridLayout);
|
content.setLayout(gridLayout);
|
||||||
final GridData headerCell = new GridData(SWT.FILL, SWT.FILL, true, true);
|
final GridData headerCell = new GridData(SWT.FILL, SWT.FILL, true, true);
|
||||||
|
@ -99,32 +110,33 @@ public class ZoomProctoringView extends AbstractProctoringView {
|
||||||
closeAction.addListener(SWT.Selection, event -> closeRoom(proctoringGUIService, proctoringWindowData));
|
closeAction.addListener(SWT.Selection, event -> closeRoom(proctoringGUIService, proctoringWindowData));
|
||||||
|
|
||||||
final BroadcastActionState broadcastActionState = new BroadcastActionState();
|
final BroadcastActionState broadcastActionState = new BroadcastActionState();
|
||||||
|
if (proctoringSettings.enabledFeatures.contains(ProctoringFeature.BROADCAST)) {
|
||||||
|
final Button broadcastAudioAction = widgetFactory.buttonLocalized(footer, BROADCAST_AUDIO_ON_TEXT_KEY);
|
||||||
|
broadcastAudioAction.setLayoutData(new RowData());
|
||||||
|
broadcastAudioAction.addListener(SWT.Selection, event -> toggleBroadcastAudio(
|
||||||
|
proctoringWindowData.examId,
|
||||||
|
proctoringWindowData.connectionData.roomName,
|
||||||
|
broadcastAudioAction));
|
||||||
|
broadcastAudioAction.setData(BroadcastActionState.KEY_NAME, broadcastActionState);
|
||||||
|
|
||||||
final Button broadcastAudioAction = widgetFactory.buttonLocalized(footer, BROADCAST_AUDIO_ON_TEXT_KEY);
|
final Button broadcastVideoAction = widgetFactory.buttonLocalized(footer, BROADCAST_VIDEO_ON_TEXT_KEY);
|
||||||
broadcastAudioAction.setLayoutData(new RowData());
|
broadcastVideoAction.setLayoutData(new RowData());
|
||||||
broadcastAudioAction.addListener(SWT.Selection, event -> toggleBroadcastAudio(
|
broadcastVideoAction.addListener(SWT.Selection, event -> toggleBroadcastVideo(
|
||||||
proctoringWindowData.examId,
|
proctoringWindowData.examId,
|
||||||
proctoringWindowData.connectionData.roomName,
|
proctoringWindowData.connectionData.roomName,
|
||||||
broadcastAudioAction));
|
broadcastVideoAction,
|
||||||
broadcastAudioAction.setData(BroadcastActionState.KEY_NAME, broadcastActionState);
|
broadcastAudioAction));
|
||||||
|
broadcastVideoAction.setData(BroadcastActionState.KEY_NAME, broadcastActionState);
|
||||||
final Button broadcastVideoAction = widgetFactory.buttonLocalized(footer, BROADCAST_VIDEO_ON_TEXT_KEY);
|
}
|
||||||
broadcastVideoAction.setLayoutData(new RowData());
|
if (proctoringSettings.enabledFeatures.contains(ProctoringFeature.ENABLE_CHAT)) {
|
||||||
broadcastVideoAction.addListener(SWT.Selection, event -> toggleBroadcastVideo(
|
final Button chatAction = widgetFactory.buttonLocalized(footer, CHAT_ON_TEXT_KEY);
|
||||||
proctoringWindowData.examId,
|
chatAction.setLayoutData(new RowData());
|
||||||
proctoringWindowData.connectionData.roomName,
|
chatAction.addListener(SWT.Selection, event -> toggleChat(
|
||||||
broadcastVideoAction,
|
proctoringWindowData.examId,
|
||||||
broadcastAudioAction));
|
proctoringWindowData.connectionData.roomName,
|
||||||
broadcastVideoAction.setData(BroadcastActionState.KEY_NAME, broadcastActionState);
|
chatAction));
|
||||||
|
chatAction.setData(BroadcastActionState.KEY_NAME, broadcastActionState);
|
||||||
final Button chatAction = widgetFactory.buttonLocalized(footer, CHAT_ON_TEXT_KEY);
|
}
|
||||||
chatAction.setLayoutData(new RowData());
|
|
||||||
chatAction.addListener(SWT.Selection, event -> toggleChat(
|
|
||||||
proctoringWindowData.examId,
|
|
||||||
proctoringWindowData.connectionData.roomName,
|
|
||||||
chatAction));
|
|
||||||
chatAction.setData(BroadcastActionState.KEY_NAME, broadcastActionState);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,13 +10,17 @@ package ch.ethz.seb.sebserver.webservice.servicelayer.exam.impl;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.EnumSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import org.apache.commons.lang3.BooleanUtils;
|
import org.apache.commons.lang3.BooleanUtils;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.context.annotation.Lazy;
|
import org.springframework.context.annotation.Lazy;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
@ -32,6 +36,7 @@ import ch.ethz.seb.sebserver.gbl.model.exam.Indicator;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.exam.Indicator.IndicatorType;
|
import ch.ethz.seb.sebserver.gbl.model.exam.Indicator.IndicatorType;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.exam.OpenEdxSEBRestriction;
|
import ch.ethz.seb.sebserver.gbl.model.exam.OpenEdxSEBRestriction;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringServiceSettings;
|
import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringServiceSettings;
|
||||||
|
import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringServiceSettings.ProctoringFeature;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringServiceSettings.ProctoringServerType;
|
import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringServiceSettings.ProctoringServerType;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.exam.QuizData;
|
import ch.ethz.seb.sebserver.gbl.model.exam.QuizData;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetup;
|
import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetup;
|
||||||
|
@ -56,6 +61,9 @@ import ch.ethz.seb.sebserver.webservice.servicelayer.session.impl.proctoring.Exa
|
||||||
@WebServiceProfile
|
@WebServiceProfile
|
||||||
public class ExamAdminServiceImpl implements ExamAdminService {
|
public class ExamAdminServiceImpl implements ExamAdminService {
|
||||||
|
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(ExamAdminServiceImpl.class);
|
||||||
|
|
||||||
|
private static final Object ATTR_ENABLE_PROCTORING = null;
|
||||||
private final ExamDAO examDAO;
|
private final ExamDAO examDAO;
|
||||||
private final IndicatorDAO indicatorDAO;
|
private final IndicatorDAO indicatorDAO;
|
||||||
private final AdditionalAttributesDAO additionalAttributesDAO;
|
private final AdditionalAttributesDAO additionalAttributesDAO;
|
||||||
|
@ -203,6 +211,7 @@ public class ExamAdminServiceImpl implements ExamAdminService {
|
||||||
getServerType(mapping),
|
getServerType(mapping),
|
||||||
getString(mapping, ProctoringServiceSettings.ATTR_SERVER_URL),
|
getString(mapping, ProctoringServiceSettings.ATTR_SERVER_URL),
|
||||||
getCollectingRoomSize(mapping),
|
getCollectingRoomSize(mapping),
|
||||||
|
getEnabledFeatures(mapping),
|
||||||
this.remoteProctoringRoomDAO.isServiceInUse(examId).getOr(true),
|
this.remoteProctoringRoomDAO.isServiceInUse(examId).getOr(true),
|
||||||
getString(mapping, ProctoringServiceSettings.ATTR_APP_KEY),
|
getString(mapping, ProctoringServiceSettings.ATTR_APP_KEY),
|
||||||
getString(mapping, ProctoringServiceSettings.ATTR_APP_SECRET));
|
getString(mapping, ProctoringServiceSettings.ATTR_APP_SECRET));
|
||||||
|
@ -255,6 +264,12 @@ public class ExamAdminServiceImpl implements ExamAdminService {
|
||||||
.getOrThrow()
|
.getOrThrow()
|
||||||
.toString());
|
.toString());
|
||||||
|
|
||||||
|
this.additionalAttributesDAO.saveAdditionalAttribute(
|
||||||
|
EntityType.EXAM,
|
||||||
|
examId,
|
||||||
|
ProctoringServiceSettings.ATTR_ENABLED_FEATURES,
|
||||||
|
StringUtils.join(proctoringServiceSettings.enabledFeatures, Constants.LIST_SEPARATOR));
|
||||||
|
|
||||||
return proctoringServiceSettings;
|
return proctoringServiceSettings;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -310,4 +325,31 @@ public class ExamAdminServiceImpl implements ExamAdminService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private EnumSet<ProctoringFeature> getEnabledFeatures(final Map<String, AdditionalAttributeRecord> mapping) {
|
||||||
|
if (mapping.containsKey(ProctoringServiceSettings.ATTR_ENABLED_FEATURES)) {
|
||||||
|
try {
|
||||||
|
final String value = mapping.get(ProctoringServiceSettings.ATTR_ENABLED_FEATURES).getValue();
|
||||||
|
return EnumSet.copyOf(Arrays.asList(StringUtils.split(value, Constants.LIST_SEPARATOR))
|
||||||
|
.stream()
|
||||||
|
.map(str -> {
|
||||||
|
try {
|
||||||
|
return ProctoringFeature.valueOf(str);
|
||||||
|
} catch (final Exception e) {
|
||||||
|
log.error(
|
||||||
|
"Failed to enabled single features for proctoring settings. Skipping. {}",
|
||||||
|
e.getMessage());
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.filter(Objects::nonNull)
|
||||||
|
.collect(Collectors.toSet()));
|
||||||
|
} catch (final Exception e) {
|
||||||
|
log.error("Failed to get enabled features for proctoring settings. Enable all. {}", e.getMessage());
|
||||||
|
return EnumSet.allOf(ProctoringFeature.class);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return EnumSet.allOf(ProctoringFeature.class);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -661,6 +661,11 @@ sebserver.exam.proctoring.form.appkey=Application Key
|
||||||
sebserver.exam.proctoring.form.appkey.tooltip=The application key of the proctoring service server
|
sebserver.exam.proctoring.form.appkey.tooltip=The application key of the proctoring service server
|
||||||
sebserver.exam.proctoring.form.secret=Secret
|
sebserver.exam.proctoring.form.secret=Secret
|
||||||
sebserver.exam.proctoring.form.secret.tooltip=The secret used to access the proctoring service
|
sebserver.exam.proctoring.form.secret.tooltip=The secret used to access the proctoring service
|
||||||
|
sebserver.exam.proctoring.form.features=Enabled Features
|
||||||
|
sebserver.exam.proctoring.form.features.TOWN_HALL=Town-Hall Room
|
||||||
|
sebserver.exam.proctoring.form.features.ONE_TO_ONE=One to One Room
|
||||||
|
sebserver.exam.proctoring.form.features.BROADCAST=Broadcasting Feature
|
||||||
|
sebserver.exam.proctoring.form.features.ENABLE_CHAT=Chat Feature
|
||||||
|
|
||||||
sebserver.exam.proctoring.type.servertype.JITSI_MEET=Jitsi Meet Server
|
sebserver.exam.proctoring.type.servertype.JITSI_MEET=Jitsi Meet Server
|
||||||
sebserver.exam.proctoring.type.servertype.JITSI_MEET.tooltip=Use a Jitsi Meet server for proctoring
|
sebserver.exam.proctoring.type.servertype.JITSI_MEET.tooltip=Use a Jitsi Meet server for proctoring
|
||||||
|
|
|
@ -62,7 +62,7 @@ public class ExamProctoringRoomServiceTest extends AdministrationAPIIntegrationT
|
||||||
this.examAdminService.saveProctoringServiceSettings(
|
this.examAdminService.saveProctoringServiceSettings(
|
||||||
2L,
|
2L,
|
||||||
new ProctoringServiceSettings(
|
new ProctoringServiceSettings(
|
||||||
2L, true, ProctoringServerType.JITSI_MEET, "http://jitsi.ch", 1, false,
|
2L, true, ProctoringServerType.JITSI_MEET, "http://jitsi.ch", 1, null, false,
|
||||||
"app-key", "app.secret"));
|
"app-key", "app.secret"));
|
||||||
|
|
||||||
assertTrue(this.examAdminService.isProctoringEnabled(2L).get());
|
assertTrue(this.examAdminService.isProctoringEnabled(2L).get());
|
||||||
|
|
Loading…
Reference in a new issue