SEBSERV-192 also improved some error handling for exam import
This commit is contained in:
parent
fad3810ba8
commit
e19e7aeb2a
10 changed files with 107 additions and 53 deletions
|
@ -49,8 +49,6 @@ public class APIMessage implements Serializable {
|
||||||
PASSWORD_MISMATCH("1300", HttpStatus.BAD_REQUEST, "new password do not match confirmed password"),
|
PASSWORD_MISMATCH("1300", HttpStatus.BAD_REQUEST, "new password do not match confirmed password"),
|
||||||
MISSING_PASSWORD("1301", HttpStatus.BAD_REQUEST, "Missing Password"),
|
MISSING_PASSWORD("1301", HttpStatus.BAD_REQUEST, "Missing Password"),
|
||||||
|
|
||||||
BINDING_ERROR("1500", HttpStatus.BAD_REQUEST, "External binding error"),
|
|
||||||
|
|
||||||
EXAM_CONSISTENCY_VALIDATION_SUPPORTER("1400", HttpStatus.OK, "No Exam Supporter defined for the Exam"),
|
EXAM_CONSISTENCY_VALIDATION_SUPPORTER("1400", HttpStatus.OK, "No Exam Supporter defined for the Exam"),
|
||||||
EXAM_CONSISTENCY_VALIDATION_CONFIG("1401", HttpStatus.OK, "No SEB Exam Configuration defined for the Exam"),
|
EXAM_CONSISTENCY_VALIDATION_CONFIG("1401", HttpStatus.OK, "No SEB Exam Configuration defined for the Exam"),
|
||||||
EXAM_CONSISTENCY_VALIDATION_SEB_RESTRICTION("1402", HttpStatus.OK,
|
EXAM_CONSISTENCY_VALIDATION_SEB_RESTRICTION("1402", HttpStatus.OK,
|
||||||
|
@ -60,10 +58,20 @@ public class APIMessage implements Serializable {
|
||||||
EXAM_CONSISTENCY_VALIDATION_INVALID_ID_REFERENCE("1405", HttpStatus.OK,
|
EXAM_CONSISTENCY_VALIDATION_INVALID_ID_REFERENCE("1405", HttpStatus.OK,
|
||||||
"There seems to be an invalid exam - course identifier reference. The course cannot be found"),
|
"There seems to be an invalid exam - course identifier reference. The course cannot be found"),
|
||||||
|
|
||||||
EXAM_IMPORT_ERROR_AUTO_CONFIG("1500", HttpStatus.BAD_REQUEST,
|
EXTERNAL_SERVICE_BINDING_ERROR("1500", HttpStatus.BAD_REQUEST, "External binding error"),
|
||||||
"Failed to automatically create and link exam configuration from exam template"),
|
|
||||||
EXAM_IMPORT_ERROR_AUTO_CONFIG_LINKING("1500", HttpStatus.BAD_REQUEST,
|
EXAM_IMPORT_ERROR_AUTO_SETUP("1600", HttpStatus.PARTIAL_CONTENT,
|
||||||
"Failed to automatically link auto-generated exam configuration");
|
"Exam successfully imported but some additional initialization failed"),
|
||||||
|
EXAM_IMPORT_ERROR_AUTO_INDICATOR("1601", HttpStatus.PARTIAL_CONTENT,
|
||||||
|
"Failed to automatically create pre-defined indicators for the exam"),
|
||||||
|
EXAM_IMPORT_ERROR_AUTO_ATTRIBUTES("1602", HttpStatus.PARTIAL_CONTENT,
|
||||||
|
"Failed to automatically create pre-defined attributes for the exam"),
|
||||||
|
EXAM_IMPORT_ERROR_AUTO_RESTRICTION("1603", HttpStatus.PARTIAL_CONTENT,
|
||||||
|
"Failed to automatically apply SEB restriction for the exam to the involved LMS"),
|
||||||
|
EXAM_IMPORT_ERROR_AUTO_CONFIG("1610", HttpStatus.PARTIAL_CONTENT,
|
||||||
|
"Failed to automatically create and link exam configuration from the exam template to the exam"),
|
||||||
|
EXAM_IMPORT_ERROR_AUTO_CONFIG_LINKING("1611", HttpStatus.PARTIAL_CONTENT,
|
||||||
|
"Failed to automatically link auto-generated exam configuration to the exam");
|
||||||
|
|
||||||
public final String messageCode;
|
public final String messageCode;
|
||||||
public final HttpStatus httpStatus;
|
public final HttpStatus httpStatus;
|
||||||
|
|
|
@ -29,6 +29,7 @@ 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.api.API;
|
||||||
import ch.ethz.seb.sebserver.gbl.api.APIMessage;
|
import ch.ethz.seb.sebserver.gbl.api.APIMessage;
|
||||||
|
import ch.ethz.seb.sebserver.gbl.api.APIMessage.ErrorMessage;
|
||||||
import ch.ethz.seb.sebserver.gbl.api.EntityType;
|
import ch.ethz.seb.sebserver.gbl.api.EntityType;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.Domain;
|
import ch.ethz.seb.sebserver.gbl.model.Domain;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
|
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
|
||||||
|
@ -521,15 +522,20 @@ public class ExamForm implements TemplateComposer {
|
||||||
return processFormSave;
|
return processFormSave;
|
||||||
|
|
||||||
} catch (final Exception e) {
|
} catch (final Exception e) {
|
||||||
// try to geht the created exam id
|
return handleExamImportSetupFailure(action, e);
|
||||||
Throwable error = e;
|
}
|
||||||
if (e instanceof FormPostException) {
|
}
|
||||||
error = ((FormPostException) e).getCause();
|
|
||||||
}
|
private PageAction handleExamImportSetupFailure(final PageAction action, final Exception e) {
|
||||||
if (error instanceof RestCallError) {
|
Throwable error = e;
|
||||||
final List<APIMessage> apiMessages = ((RestCallError) error).getAPIMessages();
|
if (e instanceof FormPostException) {
|
||||||
if (apiMessages != null && !apiMessages.isEmpty()) {
|
error = ((FormPostException) e).getCause();
|
||||||
final APIMessage apiMessage = apiMessages.get(0);
|
}
|
||||||
|
if (error instanceof RestCallError) {
|
||||||
|
final List<APIMessage> apiMessages = ((RestCallError) error).getAPIMessages();
|
||||||
|
if (apiMessages != null && !apiMessages.isEmpty()) {
|
||||||
|
final APIMessage apiMessage = apiMessages.remove(0);
|
||||||
|
if (ErrorMessage.EXAM_IMPORT_ERROR_AUTO_SETUP.isOf(apiMessage)) {
|
||||||
final String examIdAttr = apiMessage.attributes
|
final String examIdAttr = apiMessage.attributes
|
||||||
.stream()
|
.stream()
|
||||||
.filter(attr -> attr.startsWith(API.PARAM_MODEL_ID))
|
.filter(attr -> attr.startsWith(API.PARAM_MODEL_ID))
|
||||||
|
@ -539,16 +545,21 @@ public class ExamForm implements TemplateComposer {
|
||||||
examIdAttr,
|
examIdAttr,
|
||||||
Constants.FORM_URL_ENCODED_NAME_VALUE_SEPARATOR);
|
Constants.FORM_URL_ENCODED_NAME_VALUE_SEPARATOR);
|
||||||
if (API.PARAM_MODEL_ID.equals(split[0])) {
|
if (API.PARAM_MODEL_ID.equals(split[0])) {
|
||||||
|
final String additionlMessages = apiMessages.stream()
|
||||||
|
.reduce(
|
||||||
|
"",
|
||||||
|
(acc, msg) -> acc + "<br/> " + msg.systemMessage,
|
||||||
|
(acc1, acc2) -> acc1 + acc2);
|
||||||
action.pageContext().publishPageMessage(
|
action.pageContext().publishPageMessage(
|
||||||
AUTO_GEN_CONFIG_ERROR_TITLE,
|
AUTO_GEN_CONFIG_ERROR_TITLE,
|
||||||
AUTO_GEN_CONFIG_ERROR_TEXT);
|
new LocTextKey(AUTO_GEN_CONFIG_ERROR_TEXT.name, additionlMessages));
|
||||||
return action.withEntityKey(new EntityKey(split[1], EntityType.EXAM));
|
return action.withEntityKey(new EntityKey(split[1], EntityType.EXAM));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
throw e;
|
|
||||||
}
|
}
|
||||||
|
throw new RuntimeException("Error while handle exam import setup failure:", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean testSEBRestrictionAPI(final Exam exam) {
|
private boolean testSEBRestrictionAPI(final Exam exam) {
|
||||||
|
|
|
@ -136,6 +136,8 @@ public abstract class RestCall<T> {
|
||||||
responseEntity.getBody(),
|
responseEntity.getBody(),
|
||||||
RestCall.this.typeKey.typeRef));
|
RestCall.this.typeKey.typeRef));
|
||||||
|
|
||||||
|
} else if (responseEntity.getStatusCode() == HttpStatus.PARTIAL_CONTENT) {
|
||||||
|
return handleRestCallPartialResponse(responseEntity);
|
||||||
} else {
|
} else {
|
||||||
return handleRestCallError(responseEntity);
|
return handleRestCallError(responseEntity);
|
||||||
}
|
}
|
||||||
|
@ -182,6 +184,11 @@ public abstract class RestCall<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Result<T> handleRestCallPartialResponse(final ResponseEntity<String> responseEntity) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
public RestCallBuilder newBuilder() {
|
public RestCallBuilder newBuilder() {
|
||||||
return new RestCallBuilder(
|
return new RestCallBuilder(
|
||||||
this.restService.getWebserviceAPIRestTemplate(),
|
this.restService.getWebserviceAPIRestTemplate(),
|
||||||
|
|
|
@ -27,7 +27,7 @@ public class ColorData {
|
||||||
|
|
||||||
public ColorData(final Display display) {
|
public ColorData(final Display display) {
|
||||||
this.defaultColor = new Color(display, new RGB(220, 220, 220), 255);
|
this.defaultColor = new Color(display, new RGB(220, 220, 220), 255);
|
||||||
this.color1 = new Color(display, new RGB(34, 177, 76), 255);
|
this.color1 = new Color(display, new RGB(255, 255, 255), 255);
|
||||||
this.color2 = new Color(display, new RGB(255, 194, 14), 255);
|
this.color2 = new Color(display, new RGB(255, 194, 14), 255);
|
||||||
this.color3 = new Color(display, new RGB(237, 28, 36), 255);
|
this.color3 = new Color(display, new RGB(237, 28, 36), 255);
|
||||||
this.darkColor = new Color(display, Constants.BLACK_RGB);
|
this.darkColor = new Color(display, Constants.BLACK_RGB);
|
||||||
|
@ -42,8 +42,6 @@ public class ColorData {
|
||||||
switch (connectionData.clientConnection.status) {
|
switch (connectionData.clientConnection.status) {
|
||||||
case ACTIVE:
|
case ACTIVE:
|
||||||
return (connectionData.missingPing) ? this.color2 : this.color1;
|
return (connectionData.missingPing) ? this.color2 : this.color1;
|
||||||
case DISABLED:
|
|
||||||
return this.color2;
|
|
||||||
default:
|
default:
|
||||||
return this.defaultColor;
|
return this.defaultColor;
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,6 @@ import org.springframework.stereotype.Service;
|
||||||
import com.fasterxml.jackson.core.type.TypeReference;
|
import com.fasterxml.jackson.core.type.TypeReference;
|
||||||
|
|
||||||
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.api.APIMessage.APIMessageException;
|
import ch.ethz.seb.sebserver.gbl.api.APIMessage.APIMessageException;
|
||||||
import ch.ethz.seb.sebserver.gbl.api.APIMessage.ErrorMessage;
|
import ch.ethz.seb.sebserver.gbl.api.APIMessage.ErrorMessage;
|
||||||
import ch.ethz.seb.sebserver.gbl.api.EntityType;
|
import ch.ethz.seb.sebserver.gbl.api.EntityType;
|
||||||
|
@ -149,7 +148,8 @@ public class ExamTemplateServiceImpl implements ExamTemplateService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return _exam;
|
return _exam;
|
||||||
});
|
}).onError(error -> log.error("Failed to create additional attributes defined by template for exam: ",
|
||||||
|
error));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -196,8 +196,7 @@ public class ExamTemplateServiceImpl implements ExamTemplateService {
|
||||||
error))
|
error))
|
||||||
.getOrThrow(error -> new APIMessageException(
|
.getOrThrow(error -> new APIMessageException(
|
||||||
ErrorMessage.EXAM_IMPORT_ERROR_AUTO_CONFIG,
|
ErrorMessage.EXAM_IMPORT_ERROR_AUTO_CONFIG,
|
||||||
error,
|
error));
|
||||||
API.PARAM_MODEL_ID + Constants.FORM_URL_ENCODED_NAME_VALUE_SEPARATOR + exam.id));
|
|
||||||
|
|
||||||
// map the exam configuration to the exam
|
// map the exam configuration to the exam
|
||||||
this.examConfigurationMapDAO.createNew(new ExamConfigurationMap(
|
this.examConfigurationMapDAO.createNew(new ExamConfigurationMap(
|
||||||
|
@ -212,8 +211,7 @@ public class ExamTemplateServiceImpl implements ExamTemplateService {
|
||||||
error))
|
error))
|
||||||
.getOrThrow(error -> new APIMessageException(
|
.getOrThrow(error -> new APIMessageException(
|
||||||
ErrorMessage.EXAM_IMPORT_ERROR_AUTO_CONFIG_LINKING,
|
ErrorMessage.EXAM_IMPORT_ERROR_AUTO_CONFIG_LINKING,
|
||||||
error,
|
error));
|
||||||
API.PARAM_MODEL_ID + Constants.FORM_URL_ENCODED_NAME_VALUE_SEPARATOR + exam.id));
|
|
||||||
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -223,7 +221,7 @@ public class ExamTemplateServiceImpl implements ExamTemplateService {
|
||||||
}
|
}
|
||||||
|
|
||||||
return exam;
|
return exam;
|
||||||
});
|
}).onError(error -> log.error("Failed to create exam configuration defined by template for exam: ", error));
|
||||||
}
|
}
|
||||||
|
|
||||||
private Result<Exam> addIndicatorsFromTemplate(final Exam exam) {
|
private Result<Exam> addIndicatorsFromTemplate(final Exam exam) {
|
||||||
|
@ -248,11 +246,10 @@ public class ExamTemplateServiceImpl implements ExamTemplateService {
|
||||||
|
|
||||||
examTemplate.indicatorTemplates
|
examTemplate.indicatorTemplates
|
||||||
.forEach(it -> createIndicatorFromTemplate(it, exam));
|
.forEach(it -> createIndicatorFromTemplate(it, exam));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return exam;
|
return exam;
|
||||||
});
|
}).onError(error -> log.error("Failed to create indicators defined by template for exam: ", error));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void createIndicatorFromTemplate(final IndicatorTemplate template, final Exam exam) {
|
private void createIndicatorFromTemplate(final IndicatorTemplate template, final Exam exam) {
|
||||||
|
@ -310,7 +307,7 @@ public class ExamTemplateServiceImpl implements ExamTemplateService {
|
||||||
.getOrThrow();
|
.getOrThrow();
|
||||||
|
|
||||||
return exam;
|
return exam;
|
||||||
});
|
}).onError(error -> log.error("Failed to apply default indicators for exam: ", error));
|
||||||
}
|
}
|
||||||
|
|
||||||
private String replaceVars(final String template, final Exam exam, final ExamTemplate examTemplate) {
|
private String replaceVars(final String template, final Exam exam, final ExamTemplate examTemplate) {
|
||||||
|
|
|
@ -150,11 +150,11 @@ public class JitsiProctoringService implements ExamProctoringService {
|
||||||
final ResponseEntity<String> result =
|
final ResponseEntity<String> result =
|
||||||
restTemplate.getForEntity(proctoringSettings.serverURL, String.class);
|
restTemplate.getForEntity(proctoringSettings.serverURL, String.class);
|
||||||
if (result.getStatusCode() != HttpStatus.OK) {
|
if (result.getStatusCode() != HttpStatus.OK) {
|
||||||
throw new APIMessageException(APIMessage.ErrorMessage.BINDING_ERROR);
|
throw new APIMessageException(APIMessage.ErrorMessage.EXTERNAL_SERVICE_BINDING_ERROR);
|
||||||
}
|
}
|
||||||
} catch (final Exception e) {
|
} catch (final Exception e) {
|
||||||
log.error("Failed to access proctoring service: {}", e.getMessage());
|
log.error("Failed to access proctoring service: {}", e.getMessage());
|
||||||
throw new APIMessageException(APIMessage.ErrorMessage.BINDING_ERROR, e.getMessage());
|
throw new APIMessageException(APIMessage.ErrorMessage.EXTERNAL_SERVICE_BINDING_ERROR, e.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -186,13 +186,13 @@ public class ZoomProctoringService implements ExamProctoringService {
|
||||||
|
|
||||||
if (result.getStatusCode() != HttpStatus.OK) {
|
if (result.getStatusCode() != HttpStatus.OK) {
|
||||||
throw new APIMessageException(
|
throw new APIMessageException(
|
||||||
APIMessage.ErrorMessage.BINDING_ERROR,
|
APIMessage.ErrorMessage.EXTERNAL_SERVICE_BINDING_ERROR,
|
||||||
String.valueOf(result.getStatusCode()));
|
String.valueOf(result.getStatusCode()));
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (final Exception e) {
|
} catch (final Exception e) {
|
||||||
log.error("Failed to access Zoom service at: {}", proctoringSettings.serverURL, e);
|
log.error("Failed to access Zoom service at: {}", proctoringSettings.serverURL, e);
|
||||||
throw new APIMessageException(APIMessage.ErrorMessage.BINDING_ERROR, e.getMessage());
|
throw new APIMessageException(APIMessage.ErrorMessage.EXTERNAL_SERVICE_BINDING_ERROR, e.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
|
|
||||||
package ch.ethz.seb.sebserver.webservice.weblayer.api;
|
package ch.ethz.seb.sebserver.webservice.weblayer.api;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
|
@ -35,6 +36,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.api.APIMessage;
|
import ch.ethz.seb.sebserver.gbl.api.APIMessage;
|
||||||
import ch.ethz.seb.sebserver.gbl.api.APIMessage.APIMessageException;
|
import ch.ethz.seb.sebserver.gbl.api.APIMessage.APIMessageException;
|
||||||
|
import ch.ethz.seb.sebserver.gbl.api.APIMessage.ErrorMessage;
|
||||||
import ch.ethz.seb.sebserver.gbl.api.EntityType;
|
import ch.ethz.seb.sebserver.gbl.api.EntityType;
|
||||||
import ch.ethz.seb.sebserver.gbl.api.POSTMapper;
|
import ch.ethz.seb.sebserver.gbl.api.POSTMapper;
|
||||||
import ch.ethz.seb.sebserver.gbl.api.authorization.PrivilegeType;
|
import ch.ethz.seb.sebserver.gbl.api.authorization.PrivilegeType;
|
||||||
|
@ -411,11 +413,42 @@ public class ExamAdministrationController extends EntityController<Exam, Exam> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Result<Exam> notifyCreated(final Exam entity) {
|
protected Result<Exam> notifyCreated(final Exam entity) {
|
||||||
return this.examTemplateService
|
final List<APIMessage> errors = new ArrayList<>();
|
||||||
|
|
||||||
|
this.examTemplateService
|
||||||
.addDefinedIndicators(entity)
|
.addDefinedIndicators(entity)
|
||||||
|
.onErrorDo(error -> {
|
||||||
|
errors.add(ErrorMessage.EXAM_IMPORT_ERROR_AUTO_INDICATOR.of(error));
|
||||||
|
return entity;
|
||||||
|
})
|
||||||
.flatMap(this.examTemplateService::initAdditionalAttributes)
|
.flatMap(this.examTemplateService::initAdditionalAttributes)
|
||||||
|
.onErrorDo(error -> {
|
||||||
|
errors.add(ErrorMessage.EXAM_IMPORT_ERROR_AUTO_ATTRIBUTES.of(error));
|
||||||
|
return entity;
|
||||||
|
})
|
||||||
.flatMap(this.examTemplateService::initExamConfiguration)
|
.flatMap(this.examTemplateService::initExamConfiguration)
|
||||||
.flatMap(this.examAdminService::applyAdditionalSEBRestrictions);
|
.onErrorDo(error -> {
|
||||||
|
if (error instanceof APIMessageException) {
|
||||||
|
errors.addAll(((APIMessageException) error).getAPIMessages());
|
||||||
|
} else {
|
||||||
|
errors.add(ErrorMessage.EXAM_IMPORT_ERROR_AUTO_CONFIG.of(error));
|
||||||
|
}
|
||||||
|
return entity;
|
||||||
|
})
|
||||||
|
.flatMap(this.examAdminService::applyAdditionalSEBRestrictions)
|
||||||
|
.onErrorDo(error -> {
|
||||||
|
errors.add(ErrorMessage.EXAM_IMPORT_ERROR_AUTO_RESTRICTION.of(error));
|
||||||
|
return entity;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!errors.isEmpty()) {
|
||||||
|
errors.add(0, ErrorMessage.EXAM_IMPORT_ERROR_AUTO_SETUP.of(
|
||||||
|
entity.getModelId(),
|
||||||
|
API.PARAM_MODEL_ID + Constants.FORM_URL_ENCODED_NAME_VALUE_SEPARATOR + entity.getModelId()));
|
||||||
|
throw new APIMessageException(errors);
|
||||||
|
} else {
|
||||||
|
return Result.of(entity);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -75,11 +75,11 @@ sebserver.webservice.proctoring.resetBroadcastOnLeav=true
|
||||||
sebserver.webservice.proctoring.zoom.enableWaitingRoom=false
|
sebserver.webservice.proctoring.zoom.enableWaitingRoom=false
|
||||||
sebserver.webservice.proctoring.zoom.sendRejoinForCollectingRoom=true
|
sebserver.webservice.proctoring.zoom.sendRejoinForCollectingRoom=true
|
||||||
|
|
||||||
# Default indicator example:
|
# Default Ping indicator:
|
||||||
#sebserver.webservice.api.exam.indicator.name=Ping
|
sebserver.webservice.api.exam.indicator.name=Ping
|
||||||
#sebserver.webservice.api.exam.indicator.type=LAST_PING
|
sebserver.webservice.api.exam.indicator.type=LAST_PING
|
||||||
#sebserver.webservice.api.exam.indicator.color=b4b4b4
|
sebserver.webservice.api.exam.indicator.color=ffffff
|
||||||
#sebserver.webservice.api.exam.indicator.thresholds=[{'value':5000.0,'color':'22b14c'},{'value':10000.0,'color':'ff7e00'},{'value':15000.0,'color':'ed1c24'}]
|
sebserver.webservice.api.exam.indicator.thresholds=[{"value":5000.0,"color":"22b14c"},{"value":10000.0,"color":"ff7e00"},{"value":15000.0,"color":"ed1c24"}]
|
||||||
|
|
||||||
# Default name and description template for auto-generated exam configuration
|
# Default name and description template for auto-generated exam configuration
|
||||||
sebserver.webservice.configtemplate.examconfig.default.name=__startDate__ __examName__
|
sebserver.webservice.configtemplate.examconfig.default.name=__startDate__ __examName__
|
||||||
|
|
|
@ -446,8 +446,8 @@ sebserver.exam.consistency.missing-seb-restriction= - There is currently no SEB
|
||||||
sebserver.exam.consistency.no-lms-connection= - Failed to connect to the LMS Setup of this exam yet.<br/>Please check the LMS connection within the LMS Setup.
|
sebserver.exam.consistency.no-lms-connection= - Failed to connect to the LMS Setup of this exam yet.<br/>Please check the LMS connection within the LMS Setup.
|
||||||
sebserver.exam.consistency.invalid-lms-id= - The referencing course identifier seems to be invalid.<br/>Please check if the course for this exam still exists on the LMS and the course identifier has not changed.
|
sebserver.exam.consistency.invalid-lms-id= - The referencing course identifier seems to be invalid.<br/>Please check if the course for this exam still exists on the LMS and the course identifier has not changed.
|
||||||
sebserver.exam.confirm.remove-config=This exam is current running. The remove of the attached configuration will led to an invalid state<br/>where connecting SEB clients cannot download the configuration for the exam.<br/><br/>Are you sure to remove the configuration?
|
sebserver.exam.confirm.remove-config=This exam is current running. The remove of the attached configuration will led to an invalid state<br/>where connecting SEB clients cannot download the configuration for the exam.<br/><br/>Are you sure to remove the configuration?
|
||||||
sebserver.exam.autogen.error.config.title=Exam Import with Template
|
sebserver.exam.autogen.error.config.title=Exam Import Setup Failure
|
||||||
sebserver.exam.autogen.error.config.text=There was an unexpected error while auto-create exam configuration.<br/>Please add an exam configuration manually.
|
sebserver.exam.autogen.error.config.text=There was an unexpected error while setting up the imported exam.<br/> Please note that the exam has successfully been imported and can be modified but one or more additional auto-setup(s) failed:<br/>{0}
|
||||||
|
|
||||||
sebserver.exam.action.list=Exam
|
sebserver.exam.action.list=Exam
|
||||||
sebserver.exam.action.list.view=View Exam
|
sebserver.exam.action.list.view=View Exam
|
||||||
|
@ -1797,16 +1797,16 @@ sebserver.monitoring.exam.connection.action.instruction.quit.all.confirm=Are you
|
||||||
sebserver.monitoring.exam.connection.action.instruction.disable.selected.confirm=Are you sure to disable all selected SEB client connections?
|
sebserver.monitoring.exam.connection.action.instruction.disable.selected.confirm=Are you sure to disable all selected SEB client connections?
|
||||||
sebserver.monitoring.exam.connection.action.instruction.disable.all.confirm=Are you sure to disable all active SEB client connections?
|
sebserver.monitoring.exam.connection.action.instruction.disable.all.confirm=Are you sure to disable all active SEB client connections?
|
||||||
sebserver.monitoring.exam.connection.action.disable=Mark As Canceled
|
sebserver.monitoring.exam.connection.action.disable=Mark As Canceled
|
||||||
sebserver.monitoring.exam.connection.action.hide.requested=Hide Requested ({0})
|
sebserver.monitoring.exam.connection.action.hide.requested=Hide Requested ( {0} )
|
||||||
sebserver.monitoring.exam.connection.action.show.requested=Show Requested ({0})
|
sebserver.monitoring.exam.connection.action.show.requested=Show Requested ( {0} )
|
||||||
sebserver.monitoring.exam.connection.action.hide.active=Hide Active ({0})
|
sebserver.monitoring.exam.connection.action.hide.active=Hide Active ( {0} )
|
||||||
sebserver.monitoring.exam.connection.action.show.active=Show Active ({0})
|
sebserver.monitoring.exam.connection.action.show.active=Show Active ( {0} )
|
||||||
sebserver.monitoring.exam.connection.action.hide.closed=Hide Closed ({0})
|
sebserver.monitoring.exam.connection.action.hide.closed=Hide Closed ( {0} )
|
||||||
sebserver.monitoring.exam.connection.action.show.closed=Show Closed ({0})
|
sebserver.monitoring.exam.connection.action.show.closed=Show Closed ( {0} )
|
||||||
sebserver.monitoring.exam.connection.action.hide.disabled=Hide Canceled ({0})
|
sebserver.monitoring.exam.connection.action.hide.disabled=Hide Canceled ( {0} )
|
||||||
sebserver.monitoring.exam.connection.action.show.disabled=Show Canceled ({0})
|
sebserver.monitoring.exam.connection.action.show.disabled=Show Canceled ( {0} )
|
||||||
sebserver.monitoring.exam.connection.action.hide.undefined=Hide Undefined ({0})
|
sebserver.monitoring.exam.connection.action.hide.undefined=Hide Undefined ( {0} )
|
||||||
sebserver.monitoring.exam.connection.action.show.undefined=Show Undefined ({0})
|
sebserver.monitoring.exam.connection.action.show.undefined=Show Undefined ( {0} )
|
||||||
sebserver.monitoring.exam.connection.action.proctoring=Single Room Proctoring
|
sebserver.monitoring.exam.connection.action.proctoring=Single Room Proctoring
|
||||||
sebserver.monitoring.exam.connection.action.proctoring.examroom=Exam Room Proctoring
|
sebserver.monitoring.exam.connection.action.proctoring.examroom=Exam Room Proctoring
|
||||||
sebserver.monitoring.exam.connection.action.openTownhall.confirm=You are about to open the town-hall room and force all SEB clients to join the town-hall room.<br/>Are you sure to open the town-hall?
|
sebserver.monitoring.exam.connection.action.openTownhall.confirm=You are about to open the town-hall room and force all SEB clients to join the town-hall room.<br/>Are you sure to open the town-hall?
|
||||||
|
|
Loading…
Reference in a new issue