SEBSERV-287 finished implementation
This commit is contained in:
parent
e6697dd340
commit
eb46de835a
5 changed files with 108 additions and 26 deletions
|
@ -417,6 +417,16 @@ public enum ActionDefinition {
|
||||||
ImageIcon.DELETE,
|
ImageIcon.DELETE,
|
||||||
PageStateDefinitionImpl.EXAM_TEMPLATE_LIST,
|
PageStateDefinitionImpl.EXAM_TEMPLATE_LIST,
|
||||||
ActionCategory.FORM),
|
ActionCategory.FORM),
|
||||||
|
EXAM_TEMPLATE_PROCTORING_ON(
|
||||||
|
new LocTextKey("sebserver.examtemplate.proctoring.actions.open"),
|
||||||
|
ImageIcon.VISIBILITY,
|
||||||
|
PageStateDefinitionImpl.EXAM_TEMPLATE_VIEW,
|
||||||
|
ActionCategory.FORM),
|
||||||
|
EXAM_TEMPLATE_PROCTORING_OFF(
|
||||||
|
new LocTextKey("sebserver.examtemplate.proctoring.actions.open"),
|
||||||
|
ImageIcon.VISIBILITY_OFF,
|
||||||
|
PageStateDefinitionImpl.EXAM_TEMPLATE_VIEW,
|
||||||
|
ActionCategory.FORM),
|
||||||
|
|
||||||
INDICATOR_TEMPLATE_NEW(
|
INDICATOR_TEMPLATE_NEW(
|
||||||
new LocTextKey("sebserver.examtemplate.indicator.action.list.new"),
|
new LocTextKey("sebserver.examtemplate.indicator.action.list.new"),
|
||||||
|
|
|
@ -23,6 +23,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.ExamTemplate;
|
import ch.ethz.seb.sebserver.gbl.model.exam.ExamTemplate;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.exam.IndicatorTemplate;
|
import ch.ethz.seb.sebserver.gbl.model.exam.IndicatorTemplate;
|
||||||
|
import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringServiceSettings;
|
||||||
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
|
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
|
||||||
import ch.ethz.seb.sebserver.gbl.util.Tuple;
|
import ch.ethz.seb.sebserver.gbl.util.Tuple;
|
||||||
import ch.ethz.seb.sebserver.gui.content.action.ActionDefinition;
|
import ch.ethz.seb.sebserver.gui.content.action.ActionDefinition;
|
||||||
|
@ -39,10 +40,12 @@ import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestService;
|
||||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.DeleteExamTemplate;
|
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.DeleteExamTemplate;
|
||||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.DeleteIndicatorTemplate;
|
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.DeleteIndicatorTemplate;
|
||||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.GetExamTemplate;
|
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.GetExamTemplate;
|
||||||
|
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.GetExamTemplateProctoringSettings;
|
||||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.GetIndicatorTemplatePage;
|
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.GetIndicatorTemplatePage;
|
||||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.NewExamTemplate;
|
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.NewExamTemplate;
|
||||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.SaveExamTemplate;
|
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.SaveExamTemplate;
|
||||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.CurrentUser;
|
import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.CurrentUser;
|
||||||
|
import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.CurrentUser.EntityGrantCheck;
|
||||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.CurrentUser.GrantCheck;
|
import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.CurrentUser.GrantCheck;
|
||||||
import ch.ethz.seb.sebserver.gui.table.ColumnDefinition;
|
import ch.ethz.seb.sebserver.gui.table.ColumnDefinition;
|
||||||
import ch.ethz.seb.sebserver.gui.table.EntityTable;
|
import ch.ethz.seb.sebserver.gui.table.EntityTable;
|
||||||
|
@ -93,13 +96,17 @@ public class ExamTemplateForm implements TemplateComposer {
|
||||||
private final ResourceService resourceService;
|
private final ResourceService resourceService;
|
||||||
private final WidgetFactory widgetFactory;
|
private final WidgetFactory widgetFactory;
|
||||||
private final RestService restService;
|
private final RestService restService;
|
||||||
|
private final ProctoringSettingsPopup proctoringSettingsPopup;
|
||||||
|
|
||||||
public ExamTemplateForm(final PageService pageService) {
|
public ExamTemplateForm(
|
||||||
|
final PageService pageService,
|
||||||
|
final ProctoringSettingsPopup proctoringSettingsPopup) {
|
||||||
|
|
||||||
this.pageService = pageService;
|
this.pageService = pageService;
|
||||||
this.resourceService = pageService.getResourceService();
|
this.resourceService = pageService.getResourceService();
|
||||||
this.widgetFactory = pageService.getWidgetFactory();
|
this.widgetFactory = pageService.getWidgetFactory();
|
||||||
this.restService = pageService.getRestService();
|
this.restService = pageService.getRestService();
|
||||||
|
this.proctoringSettingsPopup = proctoringSettingsPopup;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -185,7 +192,16 @@ public class ExamTemplateForm implements TemplateComposer {
|
||||||
? this.restService.getRestCall(NewExamTemplate.class)
|
? this.restService.getRestCall(NewExamTemplate.class)
|
||||||
: this.restService.getRestCall(SaveExamTemplate.class));
|
: this.restService.getRestCall(SaveExamTemplate.class));
|
||||||
|
|
||||||
|
final boolean proctoringEnabled = this.restService
|
||||||
|
.getBuilder(GetExamTemplateProctoringSettings.class)
|
||||||
|
.withURIVariable(API.PARAM_MODEL_ID, entityKey.modelId)
|
||||||
|
.call()
|
||||||
|
.map(ProctoringServiceSettings::getEnableProctoring)
|
||||||
|
.getOr(false);
|
||||||
|
|
||||||
final GrantCheck userGrant = currentUser.grantCheck(EntityType.EXAM_TEMPLATE);
|
final GrantCheck userGrant = currentUser.grantCheck(EntityType.EXAM_TEMPLATE);
|
||||||
|
final EntityGrantCheck userGrantCheck = currentUser.entityGrantCheck(examTemplate);
|
||||||
|
final boolean modifyGrant = userGrantCheck.m();
|
||||||
// propagate content actions to action-pane
|
// propagate content actions to action-pane
|
||||||
this.pageService.pageActionBuilder(formContext.clearEntityKeys())
|
this.pageService.pageActionBuilder(formContext.clearEntityKeys())
|
||||||
|
|
||||||
|
@ -210,7 +226,17 @@ public class ExamTemplateForm implements TemplateComposer {
|
||||||
.withExec(this::deleteExamTemplate)
|
.withExec(this::deleteExamTemplate)
|
||||||
.publishIf(() -> userGrant.iw() && readonly)
|
.publishIf(() -> userGrant.iw() && readonly)
|
||||||
|
|
||||||
;
|
.newAction(ActionDefinition.EXAM_TEMPLATE_PROCTORING_ON)
|
||||||
|
.withEntityKey(entityKey)
|
||||||
|
.withExec(this.proctoringSettingsPopup.settingsFunction(this.pageService, modifyGrant))
|
||||||
|
.noEventPropagation()
|
||||||
|
.publishIf(() -> proctoringEnabled && readonly)
|
||||||
|
|
||||||
|
.newAction(ActionDefinition.EXAM_TEMPLATE_PROCTORING_OFF)
|
||||||
|
.withEntityKey(entityKey)
|
||||||
|
.withExec(this.proctoringSettingsPopup.settingsFunction(this.pageService, modifyGrant))
|
||||||
|
.noEventPropagation()
|
||||||
|
.publishIf(() -> !proctoringEnabled && readonly);
|
||||||
|
|
||||||
if (readonly) {
|
if (readonly) {
|
||||||
|
|
||||||
|
|
|
@ -193,7 +193,10 @@ public class ProctoringSettingsPopup {
|
||||||
|
|
||||||
if (saveOk) {
|
if (saveOk) {
|
||||||
final PageAction action = pageService.pageActionBuilder(pageContext)
|
final PageAction action = pageService.pageActionBuilder(pageContext)
|
||||||
.newAction(ActionDefinition.EXAM_VIEW_FROM_LIST)
|
.newAction(
|
||||||
|
entityKey.entityType == EntityType.EXAM
|
||||||
|
? ActionDefinition.EXAM_VIEW_FROM_LIST
|
||||||
|
: ActionDefinition.EXAM_TEMPLATE_VIEW_FROM_LIST)
|
||||||
.create();
|
.create();
|
||||||
|
|
||||||
pageService.firePageEvent(
|
pageService.firePageEvent(
|
||||||
|
|
|
@ -28,6 +28,7 @@ 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;
|
||||||
import ch.ethz.seb.sebserver.gbl.api.JSONMapper;
|
import ch.ethz.seb.sebserver.gbl.api.JSONMapper;
|
||||||
|
import ch.ethz.seb.sebserver.gbl.model.Entity;
|
||||||
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.ExamConfigurationMap;
|
import ch.ethz.seb.sebserver.gbl.model.exam.ExamConfigurationMap;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.exam.ExamTemplate;
|
import ch.ethz.seb.sebserver.gbl.model.exam.ExamTemplate;
|
||||||
|
@ -44,6 +45,7 @@ import ch.ethz.seb.sebserver.webservice.servicelayer.dao.AdditionalAttributesDAO
|
||||||
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ConfigurationNodeDAO;
|
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ConfigurationNodeDAO;
|
||||||
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ExamConfigurationMapDAO;
|
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ExamConfigurationMapDAO;
|
||||||
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ExamTemplateDAO;
|
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ExamTemplateDAO;
|
||||||
|
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.FilterMap;
|
||||||
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.IndicatorDAO;
|
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.IndicatorDAO;
|
||||||
import ch.ethz.seb.sebserver.webservice.servicelayer.exam.ExamAdminService;
|
import ch.ethz.seb.sebserver.webservice.servicelayer.exam.ExamAdminService;
|
||||||
import ch.ethz.seb.sebserver.webservice.servicelayer.exam.ExamTemplateService;
|
import ch.ethz.seb.sebserver.webservice.servicelayer.exam.ExamTemplateService;
|
||||||
|
@ -177,28 +179,7 @@ public class ExamTemplateServiceImpl implements ExamTemplateService {
|
||||||
|
|
||||||
if (examTemplate.configTemplateId != null) {
|
if (examTemplate.configTemplateId != null) {
|
||||||
|
|
||||||
// create new exam configuration for the exam
|
final ConfigurationNode examConfig = createOrReuseConfig(exam, examTemplate);
|
||||||
final ConfigurationNode configurationNode = new ConfigurationNode(
|
|
||||||
null,
|
|
||||||
exam.institutionId,
|
|
||||||
examTemplate.configTemplateId,
|
|
||||||
replaceVars(this.defaultExamConfigNameTemplate, exam, examTemplate),
|
|
||||||
replaceVars(this.defaultExamConfigDescTemplate, exam, examTemplate),
|
|
||||||
ConfigurationType.EXAM_CONFIG,
|
|
||||||
exam.owner,
|
|
||||||
ConfigurationStatus.IN_USE);
|
|
||||||
|
|
||||||
final ConfigurationNode examConfig = this.configurationNodeDAO
|
|
||||||
.createNew(configurationNode)
|
|
||||||
.onError(error -> log.error(
|
|
||||||
"Failed to create exam configuration for exam: {} from template: {} examConfig: {}",
|
|
||||||
exam.name,
|
|
||||||
examTemplate.name,
|
|
||||||
configurationNode,
|
|
||||||
error))
|
|
||||||
.getOrThrow(error -> new APIMessageException(
|
|
||||||
ErrorMessage.EXAM_IMPORT_ERROR_AUTO_CONFIG,
|
|
||||||
error));
|
|
||||||
|
|
||||||
// map the exam configuration to the exam
|
// map the exam configuration to the exam
|
||||||
this.examConfigurationMapDAO.createNew(new ExamConfigurationMap(
|
this.examConfigurationMapDAO.createNew(new ExamConfigurationMap(
|
||||||
|
@ -226,6 +207,68 @@ public class ExamTemplateServiceImpl implements ExamTemplateService {
|
||||||
}).onError(error -> log.error("Failed to create exam configuration defined by template for exam: ", error));
|
}).onError(error -> log.error("Failed to create exam configuration defined by template for exam: ", error));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private ConfigurationNode createOrReuseConfig(final Exam exam, final ExamTemplate examTemplate) {
|
||||||
|
final String configName = replaceVars(this.defaultExamConfigNameTemplate, exam, examTemplate);
|
||||||
|
final FilterMap filterMap = new FilterMap();
|
||||||
|
filterMap.putIfAbsent(Entity.FILTER_ATTR_INSTITUTION, exam.institutionId.toString());
|
||||||
|
filterMap.putIfAbsent(Entity.FILTER_ATTR_NAME, configName);
|
||||||
|
|
||||||
|
// get existing config if available
|
||||||
|
final ConfigurationNode examConfig = this.configurationNodeDAO
|
||||||
|
.allMatching(filterMap)
|
||||||
|
.getOrThrow()
|
||||||
|
.stream()
|
||||||
|
.filter(res -> res.name.equals(configName))
|
||||||
|
.findFirst()
|
||||||
|
.orElse(null);
|
||||||
|
|
||||||
|
if (examConfig == null || examConfig.status != ConfigurationStatus.READY_TO_USE) {
|
||||||
|
final ConfigurationNode config = new ConfigurationNode(
|
||||||
|
null,
|
||||||
|
exam.institutionId,
|
||||||
|
examTemplate.configTemplateId,
|
||||||
|
configName,
|
||||||
|
replaceVars(this.defaultExamConfigDescTemplate, exam, examTemplate),
|
||||||
|
ConfigurationType.EXAM_CONFIG,
|
||||||
|
exam.owner,
|
||||||
|
ConfigurationStatus.IN_USE);
|
||||||
|
|
||||||
|
return this.configurationNodeDAO
|
||||||
|
.createNew(config)
|
||||||
|
.onError(error -> log.error(
|
||||||
|
"Failed to create exam configuration for exam: {} from template: {} examConfig: {}",
|
||||||
|
exam.name,
|
||||||
|
examTemplate.name,
|
||||||
|
config,
|
||||||
|
error))
|
||||||
|
.getOrThrow(error -> new APIMessageException(
|
||||||
|
ErrorMessage.EXAM_IMPORT_ERROR_AUTO_CONFIG,
|
||||||
|
error));
|
||||||
|
} else {
|
||||||
|
final ConfigurationNode config = new ConfigurationNode(
|
||||||
|
examConfig.id,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
ConfigurationStatus.IN_USE);
|
||||||
|
|
||||||
|
return this.configurationNodeDAO
|
||||||
|
.save(config)
|
||||||
|
.onError(error -> log.error(
|
||||||
|
"Failed to save exam configuration for exam: {} from template: {} examConfig: {}",
|
||||||
|
exam.name,
|
||||||
|
examTemplate.name,
|
||||||
|
config,
|
||||||
|
error))
|
||||||
|
.getOrThrow(error -> new APIMessageException(
|
||||||
|
ErrorMessage.EXAM_IMPORT_ERROR_AUTO_CONFIG,
|
||||||
|
error));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private Result<Exam> addIndicatorsFromTemplate(final Exam exam) {
|
private Result<Exam> addIndicatorsFromTemplate(final Exam exam) {
|
||||||
return Result.tryCatch(() -> {
|
return Result.tryCatch(() -> {
|
||||||
|
|
||||||
|
|
|
@ -1713,7 +1713,7 @@ sebserver.examtemplate.indicator.action.list.new=Add Indicator
|
||||||
sebserver.examtemplate.indicator.action.list.modify=Edit Indicator
|
sebserver.examtemplate.indicator.action.list.modify=Edit Indicator
|
||||||
sebserver.examtemplate.indicator.action.list.delete=Delete Indicator
|
sebserver.examtemplate.indicator.action.list.delete=Delete Indicator
|
||||||
|
|
||||||
|
sebserver.examtemplate.proctoring.actions.open=Proctoring Settings
|
||||||
|
|
||||||
################################
|
################################
|
||||||
# Certificates
|
# Certificates
|
||||||
|
|
Loading…
Reference in a new issue