SEBSERV-96 added also create config action in template view
This commit is contained in:
		
							parent
							
								
									b0ca9dd136
								
							
						
					
					
						commit
						745e0870cb
					
				
					 18 changed files with 326 additions and 1292 deletions
				
			
		|  | @ -16,8 +16,9 @@ import com.fasterxml.jackson.annotation.JsonProperty; | |||
| import ch.ethz.seb.sebserver.gbl.api.EntityType; | ||||
| import ch.ethz.seb.sebserver.gbl.model.Domain.CONFIGURATION_NODE; | ||||
| import ch.ethz.seb.sebserver.gbl.model.Entity; | ||||
| import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode.ConfigurationType; | ||||
| 
 | ||||
| public final class ConfigCopyInfo implements Entity { | ||||
| public final class ConfigCreationInfo implements Entity { | ||||
| 
 | ||||
|     public static final String ATTR_COPY_WITH_HISTORY = "with-history"; | ||||
| 
 | ||||
|  | @ -37,16 +38,23 @@ public final class ConfigCopyInfo implements Entity { | |||
|     @JsonProperty(ATTR_COPY_WITH_HISTORY) | ||||
|     public final Boolean withHistory; | ||||
| 
 | ||||
|     protected ConfigCopyInfo( | ||||
|     @JsonProperty(CONFIGURATION_NODE.ATTR_TYPE) | ||||
|     public final ConfigurationType configurationType; | ||||
| 
 | ||||
|     protected ConfigCreationInfo( | ||||
|             @JsonProperty(CONFIGURATION_NODE.ATTR_ID) final Long configurationNodeId, | ||||
|             @JsonProperty(CONFIGURATION_NODE.ATTR_NAME) final String name, | ||||
|             @JsonProperty(CONFIGURATION_NODE.ATTR_DESCRIPTION) final String description, | ||||
|             @JsonProperty(ATTR_COPY_WITH_HISTORY) final Boolean withHistory) { | ||||
|             @JsonProperty(ATTR_COPY_WITH_HISTORY) final Boolean withHistory, | ||||
|             @JsonProperty(CONFIGURATION_NODE.ATTR_TYPE) final ConfigurationType configurationType) { | ||||
| 
 | ||||
|         this.configurationNodeId = configurationNodeId; | ||||
|         this.name = name; | ||||
|         this.description = description; | ||||
|         this.withHistory = withHistory; | ||||
|         this.configurationType = (configurationType != null) | ||||
|                 ? configurationType | ||||
|                 : ConfigurationType.EXAM_CONFIG; | ||||
|     } | ||||
| 
 | ||||
|     public Long getConfigurationNodeId() { | ||||
|  | @ -66,6 +74,10 @@ public final class ConfigCopyInfo implements Entity { | |||
|         return this.withHistory; | ||||
|     } | ||||
| 
 | ||||
|     public ConfigurationType getConfigurationType() { | ||||
|         return this.configurationType; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public String getModelId() { | ||||
|         return (this.configurationNodeId != null) | ||||
|  | @ -89,6 +101,8 @@ public final class ConfigCopyInfo implements Entity { | |||
|         builder.append(this.description); | ||||
|         builder.append(", withHistory="); | ||||
|         builder.append(this.withHistory); | ||||
|         builder.append(", configurationType="); | ||||
|         builder.append(this.configurationType); | ||||
|         builder.append("]"); | ||||
|         return builder.toString(); | ||||
|     } | ||||
|  | @ -14,6 +14,7 @@ import org.slf4j.LoggerFactory; | |||
| import org.springframework.context.annotation.Lazy; | ||||
| import org.springframework.stereotype.Component; | ||||
| 
 | ||||
| import ch.ethz.seb.sebserver.gbl.Constants; | ||||
| import ch.ethz.seb.sebserver.gbl.api.API; | ||||
| import ch.ethz.seb.sebserver.gbl.model.Domain; | ||||
| import ch.ethz.seb.sebserver.gbl.model.EntityKey; | ||||
|  | @ -275,6 +276,19 @@ public class ConfigTemplateForm implements TemplateComposer { | |||
|                 .withEntityKey(entityKey) | ||||
|                 .publishIf(() -> modifyGrant && isReadonly) | ||||
| 
 | ||||
|                 .newAction(ActionDefinition.SEB_EXAM_CONFIG_TEMPLATE_CREATE_CONFIG) | ||||
|                 .withEntityKey(entityKey) | ||||
|                 .withExec(SebExamConfigCreationUtils.configCreationFunction( | ||||
|                         this.pageService, | ||||
|                         pageContext | ||||
|                                 .withAttribute( | ||||
|                                         PageContext.AttributeKeys.CREATE_FROM_TEMPLATE, | ||||
|                                         Constants.TRUE_STRING) | ||||
|                                 .withAttribute( | ||||
|                                         PageContext.AttributeKeys.COPY_AS_TEMPLATE, | ||||
|                                         Constants.FALSE_STRING))) | ||||
|                 .publishIf(() -> modifyGrant && isReadonly) | ||||
| 
 | ||||
|                 .newAction(ActionDefinition.SEB_EXAM_CONFIG_TEMPLATE_SAVE) | ||||
|                 .withEntityKey(entityKey) | ||||
|                 .withExec(formHandle::processFormSave) | ||||
|  |  | |||
|  | @ -1,128 +0,0 @@ | |||
| /* | ||||
|  * Copyright (c) 2019 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.content; | ||||
| 
 | ||||
| import java.util.function.Function; | ||||
| import java.util.function.Predicate; | ||||
| import java.util.function.Supplier; | ||||
| 
 | ||||
| import org.eclipse.swt.widgets.Composite; | ||||
| 
 | ||||
| import ch.ethz.seb.sebserver.gbl.api.EntityType; | ||||
| import ch.ethz.seb.sebserver.gbl.model.Domain; | ||||
| import ch.ethz.seb.sebserver.gbl.model.EntityKey; | ||||
| import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigCopyInfo; | ||||
| import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode; | ||||
| import ch.ethz.seb.sebserver.gbl.util.Utils; | ||||
| import ch.ethz.seb.sebserver.gui.content.action.ActionDefinition; | ||||
| import ch.ethz.seb.sebserver.gui.form.FormBuilder; | ||||
| import ch.ethz.seb.sebserver.gui.form.FormHandle; | ||||
| import ch.ethz.seb.sebserver.gui.service.page.ModalInputDialogComposer; | ||||
| 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.impl.ModalInputDialog; | ||||
| import ch.ethz.seb.sebserver.gui.service.page.impl.PageAction; | ||||
| import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.CopyConfiguration; | ||||
| 
 | ||||
| public final class SebExamConfigCopy { | ||||
| 
 | ||||
|     static Function<PageAction, PageAction> copyConfigFunction( | ||||
|             final PageService pageService, | ||||
|             final PageContext pageContext) { | ||||
| 
 | ||||
|         return action -> { | ||||
| 
 | ||||
|             final ModalInputDialog<FormHandle<ConfigCopyInfo>> dialog = | ||||
|                     new ModalInputDialog<FormHandle<ConfigCopyInfo>>( | ||||
|                             action.pageContext().getParent().getShell(), | ||||
|                             pageService.getWidgetFactory()) | ||||
|                                     .setDialogWidth(600); | ||||
| 
 | ||||
|             final CopyFormContext formContext = new CopyFormContext( | ||||
|                     pageService, | ||||
|                     action.pageContext()); | ||||
| 
 | ||||
|             final Predicate<FormHandle<ConfigCopyInfo>> doCopy = formHandle -> doCopy( | ||||
|                     pageService, | ||||
|                     pageContext, | ||||
|                     formHandle); | ||||
| 
 | ||||
|             dialog.open( | ||||
|                     SebExamConfigPropForm.FORM_COPY_TEXT_KEY, | ||||
|                     doCopy, | ||||
|                     Utils.EMPTY_EXECUTION, | ||||
|                     formContext); | ||||
| 
 | ||||
|             return action; | ||||
|         }; | ||||
|     } | ||||
| 
 | ||||
|     private static final boolean doCopy( | ||||
|             final PageService pageService, | ||||
|             final PageContext pageContext, | ||||
|             final FormHandle<ConfigCopyInfo> formHandle) { | ||||
| 
 | ||||
|         final ConfigurationNode newConfig = pageService.getRestService().getBuilder(CopyConfiguration.class) | ||||
|                 .withFormBinding(formHandle.getFormBinding()) | ||||
|                 .call() | ||||
|                 .onError(formHandle::handleError) | ||||
|                 .getOr(null); | ||||
| 
 | ||||
|         if (newConfig == null) { | ||||
|             return false; | ||||
|         } | ||||
| 
 | ||||
|         final PageAction viewNewConfig = pageService.pageActionBuilder(pageContext) | ||||
|                 .newAction(ActionDefinition.SEB_EXAM_CONFIG_VIEW_PROP) | ||||
|                 .withEntityKey(new EntityKey(newConfig.id, EntityType.CONFIGURATION_NODE)) | ||||
|                 .create(); | ||||
| 
 | ||||
|         pageService.executePageAction(viewNewConfig); | ||||
| 
 | ||||
|         return true; | ||||
|     } | ||||
| 
 | ||||
|     private static final class CopyFormContext implements ModalInputDialogComposer<FormHandle<ConfigCopyInfo>> { | ||||
| 
 | ||||
|         private final PageService pageService; | ||||
|         private final PageContext pageContext; | ||||
| 
 | ||||
|         protected CopyFormContext(final PageService pageService, final PageContext pageContext) { | ||||
|             this.pageService = pageService; | ||||
|             this.pageContext = pageContext; | ||||
|         } | ||||
| 
 | ||||
|         @Override | ||||
|         public Supplier<FormHandle<ConfigCopyInfo>> compose(final Composite parent) { | ||||
| 
 | ||||
|             final EntityKey entityKey = this.pageContext.getEntityKey(); | ||||
|             final FormHandle<ConfigCopyInfo> formHandle = this.pageService.formBuilder( | ||||
|                     this.pageContext.copyOf(parent), 4) | ||||
|                     .readonly(false) | ||||
|                     .putStaticValue( | ||||
|                             Domain.CONFIGURATION_NODE.ATTR_ID, | ||||
|                             entityKey.getModelId()) | ||||
|                     .addField(FormBuilder.text( | ||||
|                             Domain.CONFIGURATION_NODE.ATTR_NAME, | ||||
|                             SebExamConfigPropForm.FORM_NAME_TEXT_KEY)) | ||||
|                     .addField(FormBuilder.text( | ||||
|                             Domain.CONFIGURATION_NODE.ATTR_DESCRIPTION, | ||||
|                             SebExamConfigPropForm.FORM_DESCRIPTION_TEXT_KEY) | ||||
|                             .asArea()) | ||||
|                     .addField(FormBuilder.checkbox( | ||||
|                             ConfigCopyInfo.ATTR_COPY_WITH_HISTORY, | ||||
|                             SebExamConfigPropForm.FORM_HISTORY_TEXT_KEY)) | ||||
|                     .build(); | ||||
| 
 | ||||
|             return () -> formHandle; | ||||
|         } | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
| } | ||||
|  | @ -0,0 +1,191 @@ | |||
| /* | ||||
|  * Copyright (c) 2019 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.content; | ||||
| 
 | ||||
| import java.util.function.Function; | ||||
| import java.util.function.Predicate; | ||||
| import java.util.function.Supplier; | ||||
| 
 | ||||
| import org.apache.commons.lang3.BooleanUtils; | ||||
| import org.eclipse.swt.widgets.Composite; | ||||
| 
 | ||||
| import ch.ethz.seb.sebserver.gbl.api.EntityType; | ||||
| import ch.ethz.seb.sebserver.gbl.model.Domain; | ||||
| import ch.ethz.seb.sebserver.gbl.model.EntityKey; | ||||
| import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigCreationInfo; | ||||
| import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode; | ||||
| import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode.ConfigurationType; | ||||
| import ch.ethz.seb.sebserver.gbl.util.Utils; | ||||
| import ch.ethz.seb.sebserver.gui.content.action.ActionDefinition; | ||||
| import ch.ethz.seb.sebserver.gui.form.FormBuilder; | ||||
| import ch.ethz.seb.sebserver.gui.form.FormHandle; | ||||
| import ch.ethz.seb.sebserver.gui.service.i18n.LocTextKey; | ||||
| import ch.ethz.seb.sebserver.gui.service.page.ModalInputDialogComposer; | ||||
| 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.impl.ModalInputDialog; | ||||
| import ch.ethz.seb.sebserver.gui.service.page.impl.PageAction; | ||||
| import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCall; | ||||
| import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.CopyConfiguration; | ||||
| import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.NewExamConfig; | ||||
| 
 | ||||
| public final class SebExamConfigCreationUtils { | ||||
| 
 | ||||
|     static final LocTextKey FORM_COPY_TEXT_KEY = | ||||
|             new LocTextKey("sebserver.examconfig.action.copy.dialog"); | ||||
|     static final LocTextKey FORM_COPY_AS_TEMPLATE_TEXT_KEY = | ||||
|             new LocTextKey("sebserver.examconfig.action.copy-as-template.dialog"); | ||||
|     static final LocTextKey FORM_CREATE_FROM_TEMPLATE_TEXT_KEY = | ||||
|             new LocTextKey("sebserver.configtemplate.action.create-config.dialog"); | ||||
| 
 | ||||
|     static Function<PageAction, PageAction> configCreationFunction( | ||||
|             final PageService pageService, | ||||
|             final PageContext pageContext) { | ||||
| 
 | ||||
|         final boolean copyAsTemplate = BooleanUtils.toBoolean( | ||||
|                 pageContext.getAttribute(PageContext.AttributeKeys.COPY_AS_TEMPLATE)); | ||||
|         final boolean createFromTemplate = BooleanUtils.toBoolean( | ||||
|                 pageContext.getAttribute(PageContext.AttributeKeys.CREATE_FROM_TEMPLATE)); | ||||
| 
 | ||||
|         return action -> { | ||||
| 
 | ||||
|             final ModalInputDialog<FormHandle<ConfigCreationInfo>> dialog = | ||||
|                     new ModalInputDialog<FormHandle<ConfigCreationInfo>>( | ||||
|                             action.pageContext().getParent().getShell(), | ||||
|                             pageService.getWidgetFactory()) | ||||
|                                     .setDialogWidth(600); | ||||
| 
 | ||||
|             final CreationFormContext formContext = new CreationFormContext( | ||||
|                     pageService, | ||||
|                     pageContext, | ||||
|                     copyAsTemplate, | ||||
|                     createFromTemplate); | ||||
| 
 | ||||
|             final Predicate<FormHandle<ConfigCreationInfo>> doCopy = formHandle -> doCreate( | ||||
|                     pageService, | ||||
|                     pageContext, | ||||
|                     copyAsTemplate, | ||||
|                     createFromTemplate, | ||||
|                     formHandle); | ||||
| 
 | ||||
|             final LocTextKey title = (copyAsTemplate) | ||||
|                     ? FORM_COPY_AS_TEMPLATE_TEXT_KEY | ||||
|                     : (createFromTemplate) | ||||
|                             ? FORM_CREATE_FROM_TEMPLATE_TEXT_KEY | ||||
|                             : FORM_COPY_TEXT_KEY; | ||||
| 
 | ||||
|             dialog.open( | ||||
|                     title, | ||||
|                     doCopy, | ||||
|                     Utils.EMPTY_EXECUTION, | ||||
|                     formContext); | ||||
| 
 | ||||
|             return action; | ||||
|         }; | ||||
|     } | ||||
| 
 | ||||
|     private static final boolean doCreate( | ||||
|             final PageService pageService, | ||||
|             final PageContext pageContext, | ||||
|             final boolean copyAsTemplate, | ||||
|             final boolean createFromTemplate, | ||||
|             final FormHandle<ConfigCreationInfo> formHandle) { | ||||
| 
 | ||||
|         // create either a new configuration form template or from other configuration | ||||
|         final Class<? extends RestCall<ConfigurationNode>> restCall = (createFromTemplate) | ||||
|                 ? NewExamConfig.class | ||||
|                 : CopyConfiguration.class; | ||||
| 
 | ||||
|         final ConfigurationNode newConfig = pageService | ||||
|                 .getRestService() | ||||
|                 .getBuilder(restCall) | ||||
|                 .withFormBinding(formHandle.getFormBinding()) | ||||
|                 .call() | ||||
|                 .onError(formHandle::handleError) | ||||
|                 .getOr(null); | ||||
| 
 | ||||
|         if (newConfig == null) { | ||||
|             return false; | ||||
|         } | ||||
| 
 | ||||
|         // view either new template or configuration | ||||
|         final PageAction viewCopy = (copyAsTemplate) | ||||
|                 ? pageService.pageActionBuilder(pageContext) | ||||
|                         .newAction(ActionDefinition.SEB_EXAM_CONFIG_TEMPLATE_VIEW) | ||||
|                         .withEntityKey(new EntityKey(newConfig.id, EntityType.CONFIGURATION_NODE)) | ||||
|                         .create() | ||||
|                 : pageService.pageActionBuilder(pageContext) | ||||
|                         .newAction(ActionDefinition.SEB_EXAM_CONFIG_VIEW_PROP) | ||||
|                         .withEntityKey(new EntityKey(newConfig.id, EntityType.CONFIGURATION_NODE)) | ||||
|                         .create(); | ||||
| 
 | ||||
|         pageService.executePageAction(viewCopy); | ||||
| 
 | ||||
|         return true; | ||||
|     } | ||||
| 
 | ||||
|     private static final class CreationFormContext implements ModalInputDialogComposer<FormHandle<ConfigCreationInfo>> { | ||||
| 
 | ||||
|         private final PageService pageService; | ||||
|         private final PageContext pageContext; | ||||
|         private final boolean copyAsTemplate; | ||||
|         private final boolean createFromTemplate; | ||||
| 
 | ||||
|         protected CreationFormContext( | ||||
|                 final PageService pageService, | ||||
|                 final PageContext pageContext, | ||||
|                 final boolean copyAsTemplate, | ||||
|                 final boolean createFromTemplate) { | ||||
| 
 | ||||
|             this.pageService = pageService; | ||||
|             this.pageContext = pageContext; | ||||
|             this.copyAsTemplate = copyAsTemplate; | ||||
|             this.createFromTemplate = createFromTemplate; | ||||
|         } | ||||
| 
 | ||||
|         @Override | ||||
|         public Supplier<FormHandle<ConfigCreationInfo>> compose(final Composite parent) { | ||||
| 
 | ||||
|             final EntityKey entityKey = this.pageContext.getEntityKey(); | ||||
|             final FormHandle<ConfigCreationInfo> formHandle = this.pageService.formBuilder( | ||||
|                     this.pageContext.copyOf(parent), 4) | ||||
|                     .readonly(false) | ||||
|                     .putStaticValueIf( | ||||
|                             () -> !this.createFromTemplate, | ||||
|                             Domain.CONFIGURATION_NODE.ATTR_ID, | ||||
|                             entityKey.getModelId()) | ||||
|                     .putStaticValue( | ||||
|                             Domain.CONFIGURATION_NODE.ATTR_TYPE, | ||||
|                             (this.copyAsTemplate) | ||||
|                                     ? ConfigurationType.TEMPLATE.name() | ||||
|                                     : ConfigurationType.EXAM_CONFIG.name()) | ||||
|                     .putStaticValueIf( | ||||
|                             () -> this.createFromTemplate, | ||||
|                             Domain.CONFIGURATION_NODE.ATTR_TEMPLATE_ID, | ||||
|                             entityKey.getModelId()) | ||||
|                     .addField(FormBuilder.text( | ||||
|                             Domain.CONFIGURATION_NODE.ATTR_NAME, | ||||
|                             SebExamConfigPropForm.FORM_NAME_TEXT_KEY)) | ||||
|                     .addField(FormBuilder.text( | ||||
|                             Domain.CONFIGURATION_NODE.ATTR_DESCRIPTION, | ||||
|                             SebExamConfigPropForm.FORM_DESCRIPTION_TEXT_KEY) | ||||
|                             .asArea()) | ||||
|                     .addFieldIf( | ||||
|                             () -> !this.copyAsTemplate && !this.createFromTemplate, | ||||
|                             () -> FormBuilder.checkbox( | ||||
|                                     ConfigCreationInfo.ATTR_COPY_WITH_HISTORY, | ||||
|                                     SebExamConfigPropForm.FORM_HISTORY_TEXT_KEY)) | ||||
|                     .build(); | ||||
| 
 | ||||
|             return () -> formHandle; | ||||
|         } | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
| } | ||||
|  | @ -45,7 +45,7 @@ import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.Im | |||
| import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.ImportNewExamConfig; | ||||
| import ch.ethz.seb.sebserver.gui.widget.FileUploadSelection; | ||||
| 
 | ||||
| public final class SebExamConfigImport { | ||||
| public final class SebExamConfigImportUtils { | ||||
| 
 | ||||
|     private final static PageMessageException MISSING_PASSWORD = new PageMessageException( | ||||
|             new LocTextKey("sebserver.examconfig.action.import.missing-password")); | ||||
|  | @ -208,7 +208,7 @@ public class SebExamConfigList implements TemplateComposer { | |||
|                 .publishIf(() -> examConfigGrant.im() && configTable.hasAnyContent()) | ||||
| 
 | ||||
|                 .newAction(ActionDefinition.SEB_EXAM_CONFIG_IMPORT_TO_NEW_CONFIG) | ||||
|                 .withExec(SebExamConfigImport.importFunction(this.pageService, true)) | ||||
|                 .withExec(SebExamConfigImportUtils.importFunction(this.pageService, true)) | ||||
|                 .noEventPropagation() | ||||
|                 .publishIf(() -> examConfigGrant.im()) | ||||
| 
 | ||||
|  |  | |||
|  | @ -24,6 +24,7 @@ import org.springframework.beans.factory.annotation.Value; | |||
| import org.springframework.context.annotation.Lazy; | ||||
| import org.springframework.stereotype.Component; | ||||
| 
 | ||||
| import ch.ethz.seb.sebserver.gbl.Constants; | ||||
| import ch.ethz.seb.sebserver.gbl.api.API; | ||||
| import ch.ethz.seb.sebserver.gbl.api.EntityType; | ||||
| import ch.ethz.seb.sebserver.gbl.model.Domain; | ||||
|  | @ -99,8 +100,6 @@ public class SebExamConfigPropForm implements TemplateComposer { | |||
|     static final LocTextKey FORM_ATTACHED_EXAMS_TITLE_TEXT_KEY = | ||||
|             new LocTextKey("sebserver.examconfig.form.attched-to"); | ||||
| 
 | ||||
|     static final LocTextKey FORM_COPY_TEXT_KEY = | ||||
|             new LocTextKey("sebserver.examconfig.action.copy"); | ||||
|     static final LocTextKey SAVE_CONFIRM_STATE_CHANGE_WHILE_ATTACHED = | ||||
|             new LocTextKey("sebserver.examconfig.action.state-change.confirm"); | ||||
| 
 | ||||
|  | @ -253,13 +252,32 @@ public class SebExamConfigPropForm implements TemplateComposer { | |||
| 
 | ||||
|                 .newAction(ActionDefinition.SEB_EXAM_CONFIG_IMPORT_TO_EXISTING_CONFIG) | ||||
|                 .withEntityKey(entityKey) | ||||
|                 .withExec(SebExamConfigImport.importFunction(this.pageService, false)) | ||||
|                 .withExec(SebExamConfigImportUtils.importFunction(this.pageService, false)) | ||||
|                 .noEventPropagation() | ||||
|                 .publishIf(() -> modifyGrant && isReadonly && !isAttachedToExam) | ||||
| 
 | ||||
|                 .newAction(ActionDefinition.SEB_EXAM_CONFIG_COPY_CONFIG) | ||||
|                 .withEntityKey(entityKey) | ||||
|                 .withExec(SebExamConfigCopy.copyConfigFunction(this.pageService, actionContext)) | ||||
|                 .withExec(SebExamConfigCreationUtils.configCreationFunction( | ||||
|                         this.pageService, | ||||
|                         actionContext | ||||
|                                 .withEntityKey(entityKey) | ||||
|                                 .withAttribute( | ||||
|                                         PageContext.AttributeKeys.COPY_AS_TEMPLATE, | ||||
|                                         Constants.FALSE_STRING) | ||||
|                                 .withAttribute( | ||||
|                                         PageContext.AttributeKeys.CREATE_FROM_TEMPLATE, | ||||
|                                         Constants.FALSE_STRING))) | ||||
|                 .noEventPropagation() | ||||
|                 .publishIf(() -> modifyGrant && isReadonly) | ||||
| 
 | ||||
|                 .newAction(ActionDefinition.SEB_EXAM_CONFIG_COPY_CONFIG_AS_TEMPALTE) | ||||
|                 .withEntityKey(entityKey) | ||||
|                 .withExec(SebExamConfigCreationUtils.configCreationFunction( | ||||
|                         this.pageService, | ||||
|                         pageContext.withAttribute( | ||||
|                                 PageContext.AttributeKeys.COPY_AS_TEMPLATE, | ||||
|                                 Constants.TRUE_STRING))) | ||||
|                 .noEventPropagation() | ||||
|                 .publishIf(() -> modifyGrant && isReadonly) | ||||
| 
 | ||||
|  |  | |||
|  | @ -175,6 +175,20 @@ public class SebExamConfigSettingsForm implements TemplateComposer { | |||
|                     .ignoreMoveAwayFromEdit() | ||||
|                     .publishIf(() -> examConfigGrant.iw() && !readonly) | ||||
| 
 | ||||
|                     .newAction(ActionDefinition.SEB_EXAM_CONFIG_COPY_CONFIG_AS_TEMPALTE) | ||||
|                     .withEntityKey(entityKey) | ||||
|                     .withExec(SebExamConfigCreationUtils.configCreationFunction( | ||||
|                             this.pageService, | ||||
|                             pageContext | ||||
|                                     .withAttribute( | ||||
|                                             PageContext.AttributeKeys.COPY_AS_TEMPLATE, | ||||
|                                             Constants.TRUE_STRING) | ||||
|                                     .withAttribute( | ||||
|                                             PageContext.AttributeKeys.CREATE_FROM_TEMPLATE, | ||||
|                                             Constants.FALSE_STRING))) | ||||
|                     .noEventPropagation() | ||||
|                     .publishIf(() -> examConfigGrant.iw()) | ||||
| 
 | ||||
|                     .newAction(ActionDefinition.SEB_EXAM_CONFIG_VIEW_PROP) | ||||
|                     .withEntityKey(entityKey) | ||||
|                     .ignoreMoveAwayFromEdit() | ||||
|  |  | |||
|  | @ -421,6 +421,10 @@ public enum ActionDefinition { | |||
|             new LocTextKey("sebserver.examconfig.action.copy"), | ||||
|             ImageIcon.COPY, | ||||
|             ActionCategory.FORM), | ||||
|     SEB_EXAM_CONFIG_COPY_CONFIG_AS_TEMPALTE( | ||||
|             new LocTextKey("sebserver.examconfig.action.copy-as-template"), | ||||
|             ImageIcon.TEMPLATE, | ||||
|             ActionCategory.FORM), | ||||
| 
 | ||||
|     SEB_EXAM_CONFIG_MODIFY_FROM_LIST( | ||||
|             new LocTextKey("sebserver.examconfig.action.list.modify"), | ||||
|  | @ -464,6 +468,11 @@ public enum ActionDefinition { | |||
|             ImageIcon.EDIT, | ||||
|             PageStateDefinitionImpl.SEB_EXAM_CONFIG_TEMPLATE_EDIT, | ||||
|             ActionCategory.FORM), | ||||
|     SEB_EXAM_CONFIG_TEMPLATE_CREATE_CONFIG( | ||||
|             new LocTextKey("sebserver.configtemplate.action.create-config"), | ||||
|             ImageIcon.NEW, | ||||
|             PageStateDefinitionImpl.SEB_EXAM_CONFIG_TEMPLATE_VIEW, | ||||
|             ActionCategory.FORM), | ||||
|     SEB_EXAM_CONFIG_TEMPLATE_CANCEL_MODIFY( | ||||
|             new LocTextKey("sebserver.overall.action.modify.cancel"), | ||||
|             ImageIcon.CANCEL, | ||||
|  |  | |||
|  | @ -39,6 +39,9 @@ public interface PageContext { | |||
| 
 | ||||
|         public static final String IMPORT_FROM_QUIZ_DATA = "IMPORT_FROM_QUIZ_DATA"; | ||||
| 
 | ||||
|         public static final String COPY_AS_TEMPLATE = "COPY_AS_TEMPLATE"; | ||||
|         public static final String CREATE_FROM_TEMPLATE = "CREATE_FROM_TEMPLATE"; | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     /** Get the I18nSupport service | ||||
|  |  | |||
|  | @ -407,7 +407,9 @@ public class EntityTable<ROW extends Entity> { | |||
|         } | ||||
| 
 | ||||
|         final GridData gridData = (GridData) this.table.getLayoutData(); | ||||
|         gridData.heightHint = (page.content.size() * ROW_HEIGHT) + HEADER_HEIGHT; | ||||
|         gridData.heightHint = (this.pageNumber > 1) | ||||
|                 ? (this.pageSize * ROW_HEIGHT) + HEADER_HEIGHT | ||||
|                 : (page.content.size() * ROW_HEIGHT) + HEADER_HEIGHT; | ||||
| 
 | ||||
|         for (final ROW row : page.content) { | ||||
|             final TableItem item = new TableItem(this.table, SWT.NONE); | ||||
|  |  | |||
|  | @ -22,7 +22,7 @@ import ch.ethz.seb.sebserver.gui.widget.WidgetFactory.CustomVariant; | |||
| 
 | ||||
| public class TableNavigator { | ||||
| 
 | ||||
|     private final static int PAGE_NAV_SIZE = 3; | ||||
|     private final static int PAGE_NAV_SIZE = 10; | ||||
| 
 | ||||
|     private final Composite composite; | ||||
|     private final EntityTable<?> entityTable; | ||||
|  | @ -31,10 +31,6 @@ public class TableNavigator { | |||
|         this.composite = new Composite(entityTable.composite, SWT.NONE); | ||||
|         final GridData gridData = new GridData(SWT.FILL, SWT.TOP, true, false); | ||||
|         this.composite.setLayoutData(gridData); | ||||
| 
 | ||||
| // TODO just for debugging, remove when tested | ||||
| //        this.composite.setBackground(new Color(entityTable.composite.getDisplay(), new RGB(200, 0, 0))); | ||||
| 
 | ||||
|         final GridLayout layout = new GridLayout(3, true); | ||||
|         layout.marginLeft = 20; | ||||
|         this.composite.setLayout(layout); | ||||
|  | @ -75,11 +71,20 @@ public class TableNavigator { | |||
| 
 | ||||
|         if (numberOfPages > 1) { | ||||
|             createBackwardLabel(pageNumber > 1, pageNumber, numNav); | ||||
| 
 | ||||
|             for (int i = pageNumber - PAGE_NAV_SIZE; i < pageNumber + PAGE_NAV_SIZE; i++) { | ||||
|                 if (i >= 1 && i <= numberOfPages) { | ||||
|                     createPageNumberLabel(i, i != pageNumber, numNav); | ||||
|             final int pageNavSize = (numberOfPages > PAGE_NAV_SIZE) ? PAGE_NAV_SIZE : numberOfPages; | ||||
|             final int half = pageNavSize / 2; | ||||
|             int start = pageNumber - half; | ||||
|             if (start < 1) { | ||||
|                 start = 1; | ||||
|             } | ||||
|             int end = start + pageNavSize; | ||||
|             if (end > numberOfPages) { | ||||
|                 end = numberOfPages + 1; | ||||
|                 start = end - pageNavSize; | ||||
|             } | ||||
| 
 | ||||
|             for (int i = start; i < end; i++) { | ||||
|                 createPageNumberLabel(i, i != pageNumber, numNav); | ||||
|             } | ||||
| 
 | ||||
|             createForwardLabel(pageNumber < numberOfPages, pageNumber, numNav); | ||||
|  | @ -94,7 +99,11 @@ public class TableNavigator { | |||
|         pageHeader.setText("Page " + page + "/" + of); | ||||
|     } | ||||
| 
 | ||||
|     private void createPageNumberLabel(final int page, final boolean selectable, final Composite parent) { | ||||
|     private void createPageNumberLabel( | ||||
|             final int page, | ||||
|             final boolean selectable, | ||||
|             final Composite parent) { | ||||
| 
 | ||||
|         final Label pageLabel = new Label(parent, SWT.NONE); | ||||
| 
 | ||||
|         pageLabel.setText(" " + String.valueOf(page) + " "); | ||||
|  |  | |||
|  | @ -8,7 +8,7 @@ | |||
| 
 | ||||
| package ch.ethz.seb.sebserver.webservice.servicelayer.dao; | ||||
| 
 | ||||
| import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigCopyInfo; | ||||
| import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigCreationInfo; | ||||
| import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode; | ||||
| import ch.ethz.seb.sebserver.gbl.util.Result; | ||||
| import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.BulkActionSupportDAO; | ||||
|  | @ -20,6 +20,6 @@ public interface ConfigurationNodeDAO extends | |||
|     Result<ConfigurationNode> createCopy( | ||||
|             Long institutionId, | ||||
|             String newOwner, | ||||
|             ConfigCopyInfo copyInfo); | ||||
|             ConfigCreationInfo copyInfo); | ||||
| 
 | ||||
| } | ||||
|  |  | |||
|  | @ -34,7 +34,7 @@ import org.springframework.stereotype.Component; | |||
| import ch.ethz.seb.sebserver.gbl.api.APIMessage.FieldValidationException; | ||||
| import ch.ethz.seb.sebserver.gbl.api.EntityType; | ||||
| import ch.ethz.seb.sebserver.gbl.model.sebconfig.AttributeType; | ||||
| import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigCopyInfo; | ||||
| import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigCreationInfo; | ||||
| import ch.ethz.seb.sebserver.gbl.model.sebconfig.Configuration; | ||||
| import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationAttribute; | ||||
| import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode; | ||||
|  | @ -347,7 +347,7 @@ class ConfigurationDAOBatchService { | |||
|     Result<ConfigurationNode> createCopy( | ||||
|             final Long institutionId, | ||||
|             final String newOwner, | ||||
|             final ConfigCopyInfo copyInfo) { | ||||
|             final ConfigCreationInfo copyInfo) { | ||||
| 
 | ||||
|         return Result.tryCatch(() -> { | ||||
|             final ConfigurationNodeRecord sourceNode = this.batchConfigurationNodeRecordMapper | ||||
|  | @ -366,7 +366,7 @@ class ConfigurationDAOBatchService { | |||
|     private ConfigurationNodeRecord copyNodeRecord( | ||||
|             final ConfigurationNodeRecord nodeRec, | ||||
|             final String newOwner, | ||||
|             final ConfigCopyInfo copyInfo) { | ||||
|             final ConfigCreationInfo copyInfo) { | ||||
| 
 | ||||
|         final ConfigurationNodeRecord newNodeRec = new ConfigurationNodeRecord( | ||||
|                 null, | ||||
|  | @ -375,8 +375,9 @@ class ConfigurationDAOBatchService { | |||
|                 StringUtils.isNotBlank(newOwner) ? newOwner : nodeRec.getOwner(), | ||||
|                 copyInfo.getName(), | ||||
|                 copyInfo.getDescription(), | ||||
|                 nodeRec.getType(), | ||||
|                 copyInfo.configurationType.name(), | ||||
|                 ConfigurationStatus.CONSTRUCTION.name()); | ||||
| 
 | ||||
|         this.batchConfigurationNodeRecordMapper.insert(newNodeRec); | ||||
|         this.batchSqlSessionTemplate.flushStatements(); | ||||
| 
 | ||||
|  |  | |||
|  | @ -27,7 +27,7 @@ import org.springframework.transaction.annotation.Transactional; | |||
| import ch.ethz.seb.sebserver.gbl.api.APIMessage.FieldValidationException; | ||||
| import ch.ethz.seb.sebserver.gbl.api.EntityType; | ||||
| import ch.ethz.seb.sebserver.gbl.model.EntityKey; | ||||
| import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigCopyInfo; | ||||
| import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigCreationInfo; | ||||
| import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode; | ||||
| import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode.ConfigurationStatus; | ||||
| import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode.ConfigurationType; | ||||
|  | @ -197,9 +197,12 @@ public class ConfigurationNodeDAOImpl implements ConfigurationNodeDAO { | |||
|     public Result<ConfigurationNode> createCopy( | ||||
|             final Long institutionId, | ||||
|             final String newOwner, | ||||
|             final ConfigCopyInfo copyInfo) { | ||||
|             final ConfigCreationInfo copyInfo) { | ||||
| 
 | ||||
|         return this.configurationDAOBatchService.createCopy(institutionId, newOwner, copyInfo); | ||||
|         return this.configurationDAOBatchService.createCopy( | ||||
|                 institutionId, | ||||
|                 newOwner, | ||||
|                 copyInfo); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|  |  | |||
|  | @ -44,7 +44,7 @@ import ch.ethz.seb.sebserver.gbl.model.Domain; | |||
| import ch.ethz.seb.sebserver.gbl.model.Domain.EXAM; | ||||
| import ch.ethz.seb.sebserver.gbl.model.EntityKey; | ||||
| import ch.ethz.seb.sebserver.gbl.model.Page; | ||||
| import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigCopyInfo; | ||||
| import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigCreationInfo; | ||||
| import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigKey; | ||||
| import ch.ethz.seb.sebserver.gbl.model.sebconfig.Configuration; | ||||
| import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode; | ||||
|  | @ -152,7 +152,7 @@ public class ConfigurationNodeController extends EntityController<ConfigurationN | |||
|                     name = API.PARAM_INSTITUTION_ID, | ||||
|                     required = true, | ||||
|                     defaultValue = UserService.USERS_INSTITUTION_AS_DEFAULT) final Long institutionId, | ||||
|             @Valid @RequestBody final ConfigCopyInfo copyInfo) { | ||||
|             @Valid @RequestBody final ConfigCreationInfo copyInfo) { | ||||
| 
 | ||||
|         this.entityDAO.byPK(copyInfo.configurationNodeId) | ||||
|                 .flatMap(this.authorization::checkWrite); | ||||
|  | @ -165,6 +165,13 @@ public class ConfigurationNodeController extends EntityController<ConfigurationN | |||
|                 institutionId, | ||||
|                 currentUser.getUserInfo().uuid, | ||||
|                 copyInfo) | ||||
|                 .map(config -> { | ||||
|                     if (config.type == ConfigurationType.TEMPLATE) { | ||||
|                         return this.createTemplate(config); | ||||
|                     } else { | ||||
|                         return config; | ||||
|                     } | ||||
|                 }) | ||||
|                 .getOrThrow(); | ||||
|     } | ||||
| 
 | ||||
|  |  | |||
|  | @ -456,6 +456,9 @@ sebserver.examconfig.action.saveToHistory.integrity-violation=There is currently | |||
| sebserver.examconfig.action.undo=Undo | ||||
| sebserver.examconfig.action.undo.success=Successfully reverted to last saved state | ||||
| sebserver.examconfig.action.copy=Copy Configuration | ||||
| sebserver.examconfig.action.copy.dialog=Exam Configuration | ||||
| sebserver.examconfig.action.copy-as-template=Save As Template | ||||
| sebserver.examconfig.action.copy-as-template.dialog=Configuration Template | ||||
| sebserver.examconfig.action.export.plainxml=Export Configuration | ||||
| sebserver.examconfig.action.get-config-key=Export Config-Key | ||||
| sebserver.examconfig.action.import-config=Import Exam Configuration | ||||
|  | @ -961,15 +964,17 @@ sebserver.configtemplate.info.pleaseSelect=Please select an exam configuration t | |||
| 
 | ||||
| sebserver.configtemplate.action.list.new=Add Configuration Template | ||||
| sebserver.configtemplate.action.list.view=View Configuration Template | ||||
| sebserver.configtemplate.action.view=View Configuration Template | ||||
| sebserver.configtemplate.action.list.modify=Edit Configuration Template | ||||
| sebserver.configtemplate.action.modify=Edit Configuration Template | ||||
| sebserver.configtemplate.action.view=View Template | ||||
| sebserver.configtemplate.action.list.modify=Edit Template | ||||
| sebserver.configtemplate.action.modify=Edit Template | ||||
| sebserver.configtemplate.action.create-config=Create Configuration | ||||
| sebserver.configtemplate.action.create-config.dialog=Exam Configuration | ||||
| 
 | ||||
| sebserver.configtemplate.form.title.new=Add Configuration Template | ||||
| sebserver.configtemplate.form.title.new=Add Template | ||||
| sebserver.configtemplate.form.title=Configuration Template | ||||
| sebserver.configtemplate.form.name=Name | ||||
| sebserver.configtemplate.form.description=Description | ||||
| sebserver.configtemplate.action.save=Save Configuration Template | ||||
| sebserver.configtemplate.action.save=Save Template | ||||
| 
 | ||||
| sebserver.configtemplate.attr.type.TEXT_FIELD=Text Field | ||||
| sebserver.configtemplate.attr.type.PASSWORD_FIELD=Password Field | ||||
|  |  | |||
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
		Loading…
	
	Add table
		
		Reference in a new issue
	
	 anhefti
						anhefti