diff --git a/src/main/java/ch/ethz/seb/sebserver/gbl/api/API.java b/src/main/java/ch/ethz/seb/sebserver/gbl/api/API.java index 100c975e..0f807018 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gbl/api/API.java +++ b/src/main/java/ch/ethz/seb/sebserver/gbl/api/API.java @@ -167,6 +167,7 @@ public final class API { public static final String CONFIGURATION_UNDO_PATH_SEGMENT = "/undo"; public static final String CONFIGURATION_COPY_PATH_SEGMENT = "/copy"; public static final String CONFIGURATION_RESTORE_FROM_HISTORY_PATH_SEGMENT = "/restore"; + public static final String CONFIGURATION_RESET_TO_TEMPLATE_PATH_SEGMENT = "/reset-to-template"; public static final String CONFIGURATION_VALUE_ENDPOINT = "/configuration_value"; public static final String CONFIGURATION_TABLE_VALUE_PATH_SEGMENT = "/table"; public static final String CONFIGURATION_ATTRIBUTE_ENDPOINT = "/configuration_attribute"; diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/content/action/ActionDefinition.java b/src/main/java/ch/ethz/seb/sebserver/gui/content/action/ActionDefinition.java index c6b1efa5..886fb9b8 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/content/action/ActionDefinition.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/content/action/ActionDefinition.java @@ -586,8 +586,12 @@ public enum ActionDefinition { SEB_EXAM_CONFIG_COPY_CONFIG_FROM_LIST( new LocTextKey("sebserver.examconfig.action.copy"), ImageIcon.COPY, - // PageStateDefinitionImpl.SEB_EXAM_CONFIG_PROP_EDIT, ActionCategory.SEB_EXAM_CONFIG_LIST), + + SEB_EXAM_CONFIG_RESET_TO_TEMPLATE_SETTINGS( + new LocTextKey("sebserver.examconfig.action.restore.template.settings"), + ImageIcon.EXPORT, + ActionCategory.FORM), SEB_EXAM_CONFIG_COPY_CONFIG( new LocTextKey("sebserver.examconfig.action.copy"), ImageIcon.COPY, diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/content/configs/SEBExamConfigForm.java b/src/main/java/ch/ethz/seb/sebserver/gui/content/configs/SEBExamConfigForm.java index 6186cc93..1a11d122 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/content/configs/SEBExamConfigForm.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/content/configs/SEBExamConfigForm.java @@ -58,6 +58,7 @@ import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.De import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.ExportConfigKey; import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.GetExamConfigNode; import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.NewExamConfig; +import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.ResetToTemplateSettings; import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.SaveExamConfig; import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.CurrentUser; import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.CurrentUser.EntityGrantCheck; @@ -71,6 +72,8 @@ import ch.ethz.seb.sebserver.gui.widget.WidgetFactory.CustomVariant; @GuiProfile public class SEBExamConfigForm implements TemplateComposer { + private static final LocTextKey MESSAGE_RESET_TO_TEMPL_SUCCESS = + new LocTextKey("sebserver.examconfig.action.restore.template.settings.success"); static final LocTextKey FORM_TITLE_NEW = new LocTextKey("sebserver.examconfig.form.title.new"); static final LocTextKey FORM_TITLE = @@ -101,6 +104,8 @@ public class SEBExamConfigForm implements TemplateComposer { new LocTextKey("sebserver.examconfig.form.attached-to"); static final LocTextKey FORM_ATTACHED_EXAMS_TITLE_TOOLTIP_TEXT_KEY = new LocTextKey("sebserver.examconfig.form.attached-to" + Constants.TOOLTIP_TEXT_KEY_SUFFIX); + static final LocTextKey FORM_RESET_CONFIRM = + new LocTextKey("sebserver.examconfig.action.restore.template.settings.confirm"); static final LocTextKey SAVE_CONFIRM_STATE_CHANGE_WHILE_ATTACHED = new LocTextKey("sebserver.examconfig.action.state-change.confirm"); @@ -248,6 +253,17 @@ public class SEBExamConfigForm implements TemplateComposer { .withAttribute(PageContext.AttributeKeys.READ_ONLY, String.valueOf(!modifyGrant)) .publishIf(() -> isReadonly) + .newAction(ActionDefinition.SEB_EXAM_CONFIG_RESET_TO_TEMPLATE_SETTINGS) + .withConfirm(() -> FORM_RESET_CONFIRM) + .withEntityKey(entityKey) + .withExec(this::restoreToTemplateSettings) + .noEventPropagation() + .publishIf(() -> modifyGrant + && isReadonly + && examConfig.status != ConfigurationStatus.IN_USE + && examConfig.templateId != null + && examConfig.templateId.longValue() > 0) + .newAction(ActionDefinition.SEB_EXAM_CONFIG_COPY_CONFIG) .withEntityKey(entityKey) .withExec(this.sebExamConfigCreationPopup.configCreationFunction( @@ -341,6 +357,18 @@ public class SEBExamConfigForm implements TemplateComposer { } } + private PageAction restoreToTemplateSettings(final PageAction action) { + this.restService.getBuilder(ResetToTemplateSettings.class) + .withURIVariable(API.PARAM_MODEL_ID, action.getEntityKey().modelId) + .call() + .getOrThrow(); + + action.pageContext().publishInfo(MESSAGE_RESET_TO_TEMPL_SUCCESS); + + return action; + + } + private PageAction deleteConfiguration(final PageAction action) { final ConfigurationNode configNode = this.restService .getBuilder(GetExamConfigNode.class) diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/seb/examconfig/ResetToTemplateSettings.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/seb/examconfig/ResetToTemplateSettings.java new file mode 100644 index 00000000..289a1f88 --- /dev/null +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/seb/examconfig/ResetToTemplateSettings.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2022 ETH Zürich, Educational Development and Technology (LET) + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +package ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig; + +import org.springframework.context.annotation.Lazy; +import org.springframework.http.HttpMethod; +import org.springframework.http.MediaType; +import org.springframework.stereotype.Component; + +import com.fasterxml.jackson.core.type.TypeReference; + +import ch.ethz.seb.sebserver.gbl.api.API; +import ch.ethz.seb.sebserver.gbl.api.EntityType; +import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode; +import ch.ethz.seb.sebserver.gbl.profile.GuiProfile; +import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCall; + +@Lazy +@Component +@GuiProfile +public class ResetToTemplateSettings extends RestCall { + + public ResetToTemplateSettings() { + super(new TypeKey<>( + CallType.SAVE, + EntityType.CONFIGURATION_NODE, + new TypeReference() { + }), + HttpMethod.PATCH, + MediaType.APPLICATION_FORM_URLENCODED, + API.CONFIGURATION_NODE_ENDPOINT + + API.MODEL_ID_VAR_PATH_SEGMENT + + API.CONFIGURATION_RESET_TO_TEMPLATE_PATH_SEGMENT); + } + +} diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/ExamConfigService.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/ExamConfigService.java index 9d0e9a43..26209894 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/ExamConfigService.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/ExamConfigService.java @@ -136,6 +136,19 @@ public interface ExamConfigService { * ConfigurationNode */ Result hasUnpublishedChanged(Long institutionId, Long configurationNodeId); + /** Used to reset the settings of a given configuration to the settings of its origin template. + * If the given configuration has no origin template, an error will be reported. + * + * NOTE: This do not publish the changes (applied template settings). + * + * @param configurationNode The ConfigurationNode + * @return Result refer to the configuration with reseted settings or to an error when happened */ + Result resetToTemplateSettings(ConfigurationNode configurationNode); + + /** Checks if given configuration is ready to save. + * + * @param configurationNode the ConfigurationNode instance + * @return Result refer to the given ConfigurationNode or to an error if the check has failed */ Result checkSaveConsistency(ConfigurationNode configurationNode); } diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/impl/ExamConfigServiceImpl.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/impl/ExamConfigServiceImpl.java index f085a302..bccbd4d1 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/impl/ExamConfigServiceImpl.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/impl/ExamConfigServiceImpl.java @@ -431,6 +431,25 @@ public class ExamConfigServiceImpl implements ExamConfigService { }); } + @Override + public Result resetToTemplateSettings(final ConfigurationNode configurationNode) { + return Result.tryCatch(() -> { + if (configurationNode.templateId == null) { + throw new IllegalAccessException( + "Configuration with name: " + configurationNode.name + " has no template!"); + } + if (configurationNode.status == ConfigurationStatus.IN_USE) { + throw new IllegalStateException("Configuration with name: " + configurationNode.name + " is in use!"); + } + + this.configurationDAO + .restoreToDefaultValues(configurationNode.id) + .getOrThrow(); + + return configurationNode; + }); + } + private void exportPlainOnly( final ConfigurationFormat exportFormat, final OutputStream out, diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ConfigurationNodeController.java b/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ConfigurationNodeController.java index 85ddec35..05e58d66 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ConfigurationNodeController.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ConfigurationNodeController.java @@ -72,6 +72,7 @@ import ch.ethz.seb.sebserver.webservice.servicelayer.dao.UserActivityLogDAO; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ViewDAO; import ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.ExamConfigService; import ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.ExamConfigTemplateService; +import ch.ethz.seb.sebserver.webservice.servicelayer.session.ExamConfigUpdateService; import ch.ethz.seb.sebserver.webservice.servicelayer.validation.BeanValidationService; @WebServiceProfile @@ -87,6 +88,7 @@ public class ConfigurationNodeController extends EntityController { + this.examConfigUpdateService + .processExamConfigurationChange(node.id) + .getOrThrow(); + return node; + }) + .getOrThrow(); + } + @RequestMapping( path = API.CONFIGURATION_COPY_PATH_SEGMENT, method = RequestMethod.PUT, @@ -183,7 +207,8 @@ public class ConfigurationNodeController extends EntityControllerPlease remove the exam configuration from running and upcoming exams first. sebserver.examconfig.message.delete.confirm=The exam configuration ({0}) was successfully deleted. sebserver.examconfig.message.delete.partialerror=The exam configuration ({0}) was deleted but there where some dependency errors:

{1} - - - +sebserver.examconfig.action.restore.template.settings=Restore Template Settings +sebserver.examconfig.action.restore.template.settings.success=Configuration settings successfully restored to template defaults +sebserver.examconfig.action.restore.template.settings.confirm=Are you sure to reset this configuration setting to the templates settings? sebserver.examconfig.form.title.new=Add Exam Configuration sebserver.examconfig.form.title=Exam Configuration