SEBSERV-160 added single action to reset to template settings

This commit is contained in:
anhefti 2022-04-11 17:09:09 +02:00
parent 8b856edb70
commit aa2bca9724
8 changed files with 137 additions and 5 deletions

View file

@ -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";

View file

@ -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,

View file

@ -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)

View file

@ -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<ConfigurationNode> {
public ResetToTemplateSettings() {
super(new TypeKey<>(
CallType.SAVE,
EntityType.CONFIGURATION_NODE,
new TypeReference<ConfigurationNode>() {
}),
HttpMethod.PATCH,
MediaType.APPLICATION_FORM_URLENCODED,
API.CONFIGURATION_NODE_ENDPOINT
+ API.MODEL_ID_VAR_PATH_SEGMENT
+ API.CONFIGURATION_RESET_TO_TEMPLATE_PATH_SEGMENT);
}
}

View file

@ -136,6 +136,19 @@ public interface ExamConfigService {
* ConfigurationNode */
Result<Boolean> 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<ConfigurationNode> 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<ConfigurationNode> checkSaveConsistency(ConfigurationNode configurationNode);
}

View file

@ -431,6 +431,25 @@ public class ExamConfigServiceImpl implements ExamConfigService {
});
}
@Override
public Result<ConfigurationNode> 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,

View file

@ -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<ConfigurationN
private final ViewDAO viewDAO;
private final OrientationDAO orientationDAO;
private final ExamConfigService sebExamConfigService;
private final ExamConfigUpdateService examConfigUpdateService;
private final ExamConfigTemplateService sebExamConfigTemplateService;
protected ConfigurationNodeController(
@ -101,6 +103,7 @@ public class ConfigurationNodeController extends EntityController<ConfigurationN
final ViewDAO viewDAO,
final OrientationDAO orientationDAO,
final ExamConfigService sebExamConfigService,
final ExamConfigUpdateService examConfigUpdateService,
final ExamConfigTemplateService sebExamConfigTemplateService) {
super(authorization,
@ -116,6 +119,7 @@ public class ConfigurationNodeController extends EntityController<ConfigurationN
this.viewDAO = viewDAO;
this.orientationDAO = orientationDAO;
this.sebExamConfigService = sebExamConfigService;
this.examConfigUpdateService = examConfigUpdateService;
this.sebExamConfigTemplateService = sebExamConfigTemplateService;
}
@ -171,6 +175,26 @@ public class ConfigurationNodeController extends EntityController<ConfigurationN
.getOrThrow();
}
@RequestMapping(
path = API.MODEL_ID_VAR_PATH_SEGMENT + API.CONFIGURATION_RESET_TO_TEMPLATE_PATH_SEGMENT,
method = RequestMethod.PATCH,
consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE,
produces = MediaType.APPLICATION_JSON_VALUE)
public ConfigurationNode resetToTemplateValues(@PathVariable final String modelId) {
return this.entityDAO
.byModelId(modelId)
.flatMap(this.authorization::checkModify)
.flatMap(this.sebExamConfigService::resetToTemplateSettings)
.flatMap(super::logModify)
.map(node -> {
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 EntityController<ConfigurationN
defaultValue = UserService.USERS_INSTITUTION_AS_DEFAULT) final Long institutionId,
@Valid @RequestBody final ConfigCreationInfo copyInfo) {
this.entityDAO.byPK(copyInfo.configurationNodeId)
this.entityDAO
.byPK(copyInfo.configurationNodeId)
.flatMap(this.authorization::checkWrite);
final SEBServerUser currentUser = this.authorization

View file

@ -856,9 +856,9 @@ sebserver.examconfig.message.confirm.delete=This will completely delete the exam
sebserver.examconfig.message.consistency.error=The exam configuration cannot be deleted since it is used by at least one running or upcoming exam.<br/>Please 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:<br/><br/>{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