From 152955f7126b479761da184718a39aa9510301c9 Mon Sep 17 00:00:00 2001 From: anhefti Date: Mon, 6 Sep 2021 15:58:30 +0200 Subject: [PATCH] SEBSERV-153 IndicatorTemplate implementation --- .../gbl/model/exam/ExamTemplate.java | 6 +- .../sebserver/gbl/model/exam/Indicator.java | 8 +- .../gbl/model/exam/IndicatorTemplate.java | 175 ++++++++++++++ .../gui/content/action/ActionCategory.java | 2 +- .../gui/content/action/ActionDefinition.java | 34 ++- .../activity/PageStateDefinitionImpl.java | 4 +- .../gui/content/exam/ExamFormIndicators.java | 19 +- .../gui/content/exam/ExamTemplateForm.java | 38 +-- .../exam/ExamTemplateIndicatorForm.java | 29 --- .../gui/content/exam/IndicatorForm.java | 4 +- .../content/exam/IndicatorTemplateForm.java | 221 ++++++++++++++++++ .../seb/sebserver/gui/form/FormBuilder.java | 6 +- ...ator.java => DeleteIndicatorTemplate.java} | 4 +- ...dicator.java => GetIndicatorTemplate.java} | 8 +- ...age.java => GetIndicatorTemplatePage.java} | 8 +- ...dicator.java => NewIndicatorTemplate.java} | 9 +- ...icator.java => SaveIndicatorTemplate.java} | 12 +- .../dao/impl/ExamTemplateDAOImpl.java | 13 +- .../weblayer/api/ExamTemplateController.java | 50 ++-- .../sql/base/V10__examTemplates_v1_3.sql | 2 +- src/main/resources/messages.properties | 7 +- src/test/resources/schema-test.sql | 2 +- 22 files changed, 524 insertions(+), 137 deletions(-) create mode 100644 src/main/java/ch/ethz/seb/sebserver/gbl/model/exam/IndicatorTemplate.java delete mode 100644 src/main/java/ch/ethz/seb/sebserver/gui/content/exam/ExamTemplateIndicatorForm.java create mode 100644 src/main/java/ch/ethz/seb/sebserver/gui/content/exam/IndicatorTemplateForm.java rename src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/exam/{DeleteExamTemplateIndicator.java => DeleteIndicatorTemplate.java} (89%) rename src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/exam/{GetExamTemplateIndicator.java => GetIndicatorTemplate.java} (82%) rename src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/exam/{GetExamTemplateIndicatorPage.java => GetIndicatorTemplatePage.java} (81%) rename src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/exam/{NewExamTemplateIndicator.java => NewIndicatorTemplate.java} (78%) rename src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/exam/{SaveExamTemplateIndicator.java => SaveIndicatorTemplate.java} (75%) diff --git a/src/main/java/ch/ethz/seb/sebserver/gbl/model/exam/ExamTemplate.java b/src/main/java/ch/ethz/seb/sebserver/gbl/model/exam/ExamTemplate.java index 72836070..d4f72fb3 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gbl/model/exam/ExamTemplate.java +++ b/src/main/java/ch/ethz/seb/sebserver/gbl/model/exam/ExamTemplate.java @@ -59,7 +59,7 @@ public class ExamTemplate implements GrantEntity { public final Long configTemplateId; @JsonProperty(EXAM_TEMPLATE.ATTR_INDICATOR_TEMPLATES) - public final Collection indicatorTemplates; + public final Collection indicatorTemplates; @JsonProperty(ATTR_EXAM_ATTRIBUTES) public final Map examAttributes; @@ -73,7 +73,7 @@ public class ExamTemplate implements GrantEntity { @JsonProperty(EXAM_TEMPLATE.ATTR_EXAM_TYPE) final ExamType examType, @JsonProperty(EXAM_TEMPLATE.ATTR_SUPPORTER) final Collection supporter, @JsonProperty(EXAM_TEMPLATE.ATTR_CONFIGURATION_TEMPLATE_ID) final Long configTemplateId, - @JsonProperty(EXAM_TEMPLATE.ATTR_INDICATOR_TEMPLATES) final Collection indicatorTemplates, + @JsonProperty(EXAM_TEMPLATE.ATTR_INDICATOR_TEMPLATES) final Collection indicatorTemplates, @JsonProperty(ATTR_EXAM_ATTRIBUTES) final Map examAttributes) { this.id = id; @@ -136,7 +136,7 @@ public class ExamTemplate implements GrantEntity { return this.configTemplateId; } - public Collection getIndicatorTemplates() { + public Collection getIndicatorTemplates() { return this.indicatorTemplates; } diff --git a/src/main/java/ch/ethz/seb/sebserver/gbl/model/exam/Indicator.java b/src/main/java/ch/ethz/seb/sebserver/gbl/model/exam/Indicator.java index 3d91331d..4015a67e 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gbl/model/exam/Indicator.java +++ b/src/main/java/ch/ethz/seb/sebserver/gbl/model/exam/Indicator.java @@ -217,8 +217,12 @@ public final class Indicator implements Entity { return builder.toString(); } - public static Indicator createNew(final Exam exam) { - return new Indicator(null, exam.id, null, null, null, null, null, null); + public static Indicator createNew(final String examId) { + try { + return new Indicator(null, Long.parseLong(examId), null, null, null, null, null, null); + } catch (final Exception e) { + return new Indicator(null, null, null, null, null, null, null, null); + } } public static String getDisplayValue(final IndicatorType indicatorType, final Double value) { diff --git a/src/main/java/ch/ethz/seb/sebserver/gbl/model/exam/IndicatorTemplate.java b/src/main/java/ch/ethz/seb/sebserver/gbl/model/exam/IndicatorTemplate.java new file mode 100644 index 00000000..4815adf3 --- /dev/null +++ b/src/main/java/ch/ethz/seb/sebserver/gbl/model/exam/IndicatorTemplate.java @@ -0,0 +1,175 @@ +/* + * Copyright (c) 2021 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.gbl.model.exam; + +import java.util.Collection; +import java.util.List; + +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; + +import org.apache.commons.lang3.StringUtils; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; + +import ch.ethz.seb.sebserver.gbl.api.EntityType; +import ch.ethz.seb.sebserver.gbl.api.POSTMapper; +import ch.ethz.seb.sebserver.gbl.model.Domain; +import ch.ethz.seb.sebserver.gbl.model.Domain.INDICATOR; +import ch.ethz.seb.sebserver.gbl.model.Domain.THRESHOLD; +import ch.ethz.seb.sebserver.gbl.model.Entity; +import ch.ethz.seb.sebserver.gbl.model.exam.Indicator.IndicatorType; +import ch.ethz.seb.sebserver.gbl.model.exam.Indicator.Threshold; +import ch.ethz.seb.sebserver.gbl.util.Utils; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class IndicatorTemplate implements Entity { + + public static final String ATTR_EXAM_TEMPLATE_ID = "examTemplateId"; + + @JsonProperty(INDICATOR.ATTR_ID) + public final Long id; + + @JsonProperty(ATTR_EXAM_TEMPLATE_ID) + public final Long examTemplateId; + + @JsonProperty(INDICATOR.ATTR_NAME) + @NotNull(message = "indicator:name:notNull") + @Size(min = 3, max = 255, message = "indicator:name:size:{min}:{max}:${validatedValue}") + public final String name; + + @JsonProperty(INDICATOR.ATTR_TYPE) + @NotNull(message = "indicator:type:notNull") + public final IndicatorType type; + + @JsonProperty(INDICATOR.ATTR_COLOR) + public final String defaultColor; + + @JsonProperty(INDICATOR.ATTR_ICON) + public final String defaultIcon; + + @JsonProperty(INDICATOR.ATTR_TAGS) + public final String tags; + + @JsonProperty(THRESHOLD.REFERENCE_NAME) + public final List thresholds; + + @JsonCreator + public IndicatorTemplate( + @JsonProperty(INDICATOR.ATTR_ID) final Long id, + @JsonProperty(ATTR_EXAM_TEMPLATE_ID) final Long examTemplateId, + @JsonProperty(INDICATOR.ATTR_NAME) final String name, + @JsonProperty(INDICATOR.ATTR_TYPE) final IndicatorType type, + @JsonProperty(INDICATOR.ATTR_COLOR) final String defaultColor, + @JsonProperty(INDICATOR.ATTR_ICON) final String defaultIcon, + @JsonProperty(INDICATOR.ATTR_TAGS) final String tags, + @JsonProperty(THRESHOLD.REFERENCE_NAME) final Collection thresholds) { + + this.id = id; + this.examTemplateId = examTemplateId; + this.name = name; + this.type = type; + this.defaultColor = defaultColor; + this.defaultIcon = defaultIcon; + this.tags = tags; + this.thresholds = Utils.immutableListOf(thresholds); + } + + /** This initialize an indicator for an exam template */ + public IndicatorTemplate(final Long id, final Long examTemplateId, final POSTMapper postParams) { + this.id = id; + this.examTemplateId = examTemplateId; + this.name = postParams.getString(Domain.INDICATOR.ATTR_NAME); + this.type = postParams.getEnum(Domain.INDICATOR.ATTR_TYPE, IndicatorType.class); + this.defaultColor = postParams.getString(Domain.INDICATOR.ATTR_COLOR); + this.defaultIcon = postParams.getString(Domain.INDICATOR.ATTR_ICON); + this.tags = postParams.getString(Domain.INDICATOR.ATTR_TAGS); + this.thresholds = postParams.getThresholds(); + } + + @Override + public String getModelId() { + return (this.id == null) ? null : String.valueOf(this.id); + } + + @Override + public EntityType entityType() { + return EntityType.INDICATOR; + } + + @Override + public String getName() { + return this.name; + } + + public Long getId() { + return this.id; + } + + public Long getExamTemplateId() { + return this.examTemplateId; + } + + public IndicatorType getType() { + return this.type; + } + + public String getDefaultColor() { + return this.defaultColor; + } + + public String getDefaultIcon() { + return this.defaultIcon; + } + + public String getTags() { + return this.tags; + } + + public Collection getThresholds() { + return this.thresholds; + } + + @Override + public String toString() { + final StringBuilder builder = new StringBuilder(); + builder.append("Indicator [id="); + builder.append(this.id); + builder.append(", examId="); + builder.append(this.examTemplateId); + builder.append(", name="); + builder.append(this.name); + builder.append(", type="); + builder.append(this.type); + builder.append(", defaultColor="); + builder.append(this.defaultColor); + builder.append(", defaultIcon="); + builder.append(this.defaultIcon); + builder.append(", tags="); + builder.append(this.tags); + builder.append(", thresholds="); + builder.append(this.thresholds); + builder.append("]"); + return builder.toString(); + } + + public static String getDisplayValue(final IndicatorType indicatorType, final Double value) { + if (value == null || indicatorType == null) { + return StringUtils.EMPTY; + } + if (indicatorType.integerValue) { + return String.valueOf(value.intValue()); + } else { + return String.valueOf(value.floatValue()); + } + } + +} diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/content/action/ActionCategory.java b/src/main/java/ch/ethz/seb/sebserver/gui/content/action/ActionCategory.java index 297b9d09..ad3a207c 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/content/action/ActionCategory.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/content/action/ActionCategory.java @@ -19,7 +19,7 @@ public enum ActionCategory { QUIZ_LIST(new LocTextKey("sebserver.quizdiscovery.list.actions"), 1), EXAM_LIST(new LocTextKey("sebserver.exam.list.actions"), 1), EXAM_TEMPLATE_LIST(new LocTextKey("sebserver.examtemplate.list.actions"), 1), - EXAM_TEMPLATE_INDICATOR_LIST(new LocTextKey("sebserver.examtemplate.indicator.list.actions"), 2), + INDICATOR_TEMPLATE_LIST(new LocTextKey("sebserver.examtemplate.indicator.list.actions"), 1), EXAM_CONFIG_MAPPING_LIST(new LocTextKey("sebserver.exam.configuration.list.actions"), 1), INDICATOR_LIST(new LocTextKey("sebserver.exam.indicator.list.actions"), 2), SEB_CLIENT_CONFIG_LIST(new LocTextKey("sebserver.clientconfig.list.actions"), 1), 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 89820a4c..d37602ae 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 @@ -398,12 +398,12 @@ public enum ActionDefinition { PageStateDefinitionImpl.EXAM_TEMPLATE_EDIT, ActionCategory.LIST_VARIA), EXAM_TEMPLATE_MODIFY( - new LocTextKey("sebserver.examtemplate.action.list.edit"), - ImageIcon.TEMPLATE, + new LocTextKey("sebserver.examtemplate.form.action.edit"), + ImageIcon.EDIT, PageStateDefinitionImpl.EXAM_TEMPLATE_EDIT, - ActionCategory.LIST_VARIA), + ActionCategory.FORM), EXAM_TEMPLATE_SAVE( - new LocTextKey("sebserver.examtemplate.action.save"), + new LocTextKey("sebserver.examtemplate.form.action.save"), ImageIcon.SAVE, PageStateDefinitionImpl.EXAM_TEMPLATE_VIEW, ActionCategory.FORM), @@ -413,21 +413,31 @@ public enum ActionDefinition { PageStateDefinitionImpl.EXAM_TEMPLATE_VIEW, ActionCategory.FORM), - EXAM_TEMPLATE_INDICATOR_NEW( + INDICATOR_TEMPLATE_NEW( new LocTextKey("sebserver.examtemplate.indicator.action.list.new"), ImageIcon.INDICATOR, - PageStateDefinitionImpl.EXAM_TEMPLATE_INDICATOR_EDIT, - ActionCategory.EXAM_TEMPLATE_INDICATOR_LIST), - EXAM_TEMPLATE_INDICATOR_MODIFY_FROM_LIST( + PageStateDefinitionImpl.INDICATOR_TEMPLATE_EDIT, + ActionCategory.INDICATOR_TEMPLATE_LIST), + INDICATOR_TEMPLATE_MODIFY_FROM_LIST( new LocTextKey("sebserver.examtemplate.indicator.action.list.modify"), ImageIcon.EDIT, - PageStateDefinitionImpl.EXAM_TEMPLATE_INDICATOR_EDIT, - ActionCategory.EXAM_TEMPLATE_INDICATOR_LIST), - EXAM_TEMPLATE_INDICATOR_DELETE_FROM_LIST( + PageStateDefinitionImpl.INDICATOR_TEMPLATE_EDIT, + ActionCategory.INDICATOR_TEMPLATE_LIST), + INDICATOR_TEMPLATE_DELETE_FROM_LIST( new LocTextKey("sebserver.examtemplate.indicator.action.list.delete"), ImageIcon.DELETE, PageStateDefinitionImpl.EXAM_TEMPLATE_VIEW, - ActionCategory.EXAM_TEMPLATE_INDICATOR_LIST), + ActionCategory.INDICATOR_TEMPLATE_LIST), + INDICATOR_TEMPLATE_SAVE( + new LocTextKey("sebserver.examtemplate.indicator.action.save"), + ImageIcon.SAVE, + PageStateDefinitionImpl.EXAM_TEMPLATE_VIEW, + ActionCategory.FORM), + INDICATOR_TEMPLATE_CANCEL_MODIFY( + new LocTextKey("sebserver.overall.action.modify.cancel"), + ImageIcon.CANCEL, + PageStateDefinitionImpl.EXAM_TEMPLATE_VIEW, + ActionCategory.FORM), SEB_CLIENT_CONFIG_LIST( new LocTextKey("sebserver.clientconfig.list.title"), diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/content/activity/PageStateDefinitionImpl.java b/src/main/java/ch/ethz/seb/sebserver/gui/content/activity/PageStateDefinitionImpl.java index 874f5838..54b5d28e 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/content/activity/PageStateDefinitionImpl.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/content/activity/PageStateDefinitionImpl.java @@ -27,9 +27,9 @@ import ch.ethz.seb.sebserver.gui.content.configs.SEBSettingsForm; import ch.ethz.seb.sebserver.gui.content.exam.ExamForm; import ch.ethz.seb.sebserver.gui.content.exam.ExamList; import ch.ethz.seb.sebserver.gui.content.exam.ExamTemplateForm; -import ch.ethz.seb.sebserver.gui.content.exam.ExamTemplateIndicatorForm; import ch.ethz.seb.sebserver.gui.content.exam.ExamTemplateList; import ch.ethz.seb.sebserver.gui.content.exam.IndicatorForm; +import ch.ethz.seb.sebserver.gui.content.exam.IndicatorTemplateForm; import ch.ethz.seb.sebserver.gui.content.exam.LmsSetupForm; import ch.ethz.seb.sebserver.gui.content.exam.LmsSetupList; import ch.ethz.seb.sebserver.gui.content.exam.QuizLookupList; @@ -66,7 +66,7 @@ public enum PageStateDefinitionImpl implements PageStateDefinition { EXAM_TEMPLATE_LIST(Type.LIST_VIEW, ExamTemplateList.class, ActivityDefinition.EXAM_TEMPLATE), EXAM_TEMPLATE_VIEW(Type.LIST_VIEW, ExamTemplateForm.class, ActivityDefinition.EXAM_TEMPLATE), EXAM_TEMPLATE_EDIT(Type.FORM_EDIT, ExamTemplateForm.class, ActivityDefinition.EXAM_TEMPLATE), - EXAM_TEMPLATE_INDICATOR_EDIT(Type.FORM_EDIT, ExamTemplateIndicatorForm.class, ActivityDefinition.EXAM_TEMPLATE), + INDICATOR_TEMPLATE_EDIT(Type.FORM_EDIT, IndicatorTemplateForm.class, ActivityDefinition.EXAM_TEMPLATE), SEB_CLIENT_CONFIG_LIST(Type.LIST_VIEW, SEBClientConfigList.class, ActivityDefinition.SEB_CLIENT_CONFIG), SEB_CLIENT_CONFIG_VIEW(Type.FORM_VIEW, SEBClientConfigForm.class, ActivityDefinition.SEB_CLIENT_CONFIG), diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/content/exam/ExamFormIndicators.java b/src/main/java/ch/ethz/seb/sebserver/gui/content/exam/ExamFormIndicators.java index 2e2c0b90..395fddc8 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/content/exam/ExamFormIndicators.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/content/exam/ExamFormIndicators.java @@ -8,6 +8,8 @@ package ch.ethz.seb.sebserver.gui.content.exam; +import java.util.List; + import org.apache.commons.lang3.BooleanUtils; import org.eclipse.swt.widgets.Composite; import org.springframework.context.annotation.Lazy; @@ -18,6 +20,8 @@ import ch.ethz.seb.sebserver.gbl.api.API; import ch.ethz.seb.sebserver.gbl.model.Domain; import ch.ethz.seb.sebserver.gbl.model.EntityKey; import ch.ethz.seb.sebserver.gbl.model.exam.Indicator; +import ch.ethz.seb.sebserver.gbl.model.exam.Indicator.IndicatorType; +import ch.ethz.seb.sebserver.gbl.model.exam.Indicator.Threshold; import ch.ethz.seb.sebserver.gbl.profile.GuiProfile; import ch.ethz.seb.sebserver.gbl.util.Utils; import ch.ethz.seb.sebserver.gui.content.action.ActionDefinition; @@ -104,10 +108,10 @@ public class ExamFormIndicators implements TemplateComposer { INDICATOR_TYPE_COLUMN_KEY, this::indicatorTypeName) .widthProportion(1)) - .withColumn(new ColumnDefinition<>( + .withColumn(new ColumnDefinition( Domain.THRESHOLD.REFERENCE_NAME, INDICATOR_THRESHOLD_COLUMN_KEY, - ExamFormIndicators::thresholdsValue) + i -> thresholdsValue(i.thresholds, i.type)) .asMarkup() .widthProportion(4)) .withDefaultActionIf( @@ -166,12 +170,15 @@ public class ExamFormIndicators implements TemplateComposer { .getText(ResourceService.EXAM_INDICATOR_TYPE_PREFIX + indicator.type.name()); } - static String thresholdsValue(final Indicator indicator) { - if (indicator.thresholds.isEmpty()) { + static String thresholdsValue( + final List thresholds, + final IndicatorType indicatorType) { + + if (thresholds.isEmpty()) { return Constants.EMPTY_NOTE; } - final StringBuilder builder = indicator.thresholds + final StringBuilder builder = thresholds .stream() .reduce( new StringBuilder(), @@ -183,7 +190,7 @@ public class ExamFormIndicators implements TemplateComposer { ? "color: #4a4a4a; " : "color: #FFFFFF;") .append("'>") - .append(Indicator.getDisplayValue(indicator.type, threshold.value)) + .append(Indicator.getDisplayValue(indicatorType, threshold.value)) .append(" (") .append(threshold.color) .append(")") diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/content/exam/ExamTemplateForm.java b/src/main/java/ch/ethz/seb/sebserver/gui/content/exam/ExamTemplateForm.java index 6f6d00d9..4d9e8b4b 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/content/exam/ExamTemplateForm.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/content/exam/ExamTemplateForm.java @@ -22,7 +22,7 @@ import ch.ethz.seb.sebserver.gbl.model.Domain; 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.ExamTemplate; -import ch.ethz.seb.sebserver.gbl.model.exam.Indicator; +import ch.ethz.seb.sebserver.gbl.model.exam.IndicatorTemplate; import ch.ethz.seb.sebserver.gbl.profile.GuiProfile; import ch.ethz.seb.sebserver.gbl.util.Tuple; import ch.ethz.seb.sebserver.gui.content.action.ActionDefinition; @@ -36,9 +36,9 @@ import ch.ethz.seb.sebserver.gui.service.page.PageService.PageActionBuilder; import ch.ethz.seb.sebserver.gui.service.page.TemplateComposer; import ch.ethz.seb.sebserver.gui.service.page.impl.PageAction; import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestService; -import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.DeleteExamTemplateIndicator; +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.GetExamTemplateIndicatorPage; +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.SaveExamTemplate; import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.CurrentUser; @@ -133,6 +133,9 @@ public class ExamTemplateForm implements TemplateComposer { .putStaticValueIf(() -> !isNew, Domain.EXAM_TEMPLATE.ATTR_ID, examTemplate.getModelId()) + .putStaticValueIf(() -> !isNew, + Domain.EXAM_TEMPLATE.ATTR_INSTITUTION_ID, + String.valueOf(examTemplate.getInstitutionId())) .addField(FormBuilder.text( Domain.EXAM_TEMPLATE.ATTR_NAME, @@ -176,9 +179,6 @@ public class ExamTemplateForm implements TemplateComposer { // propagate content actions to action-pane this.pageService.pageActionBuilder(formContext.clearEntityKeys()) - .newAction(ActionDefinition.EXAM_TEMPLATE_NEW) - .publishIf(() -> userGrant.iw() && readonly) - .newAction(ActionDefinition.EXAM_TEMPLATE_MODIFY) .withEntityKey(entityKey) .publishIf(() -> userGrant.im() && readonly) @@ -207,9 +207,9 @@ public class ExamTemplateForm implements TemplateComposer { final PageActionBuilder actionBuilder = this.pageService .pageActionBuilder(pageContext.clearEntityKeys()); - final EntityTable indicatorTable = + final EntityTable indicatorTable = this.pageService - .entityTableBuilder(this.restService.getRestCall(GetExamTemplateIndicatorPage.class)) + .entityTableBuilder(this.restService.getRestCall(GetIndicatorTemplatePage.class)) .withRestCallAdapter(builder -> builder.withURIVariable( API.PARAM_PARENT_MODEL_ID, entityKey.modelId)) @@ -220,36 +220,36 @@ public class ExamTemplateForm implements TemplateComposer { .withColumn(new ColumnDefinition<>( Domain.INDICATOR.ATTR_NAME, INDICATOR_NAME_COLUMN_KEY, - Indicator::getName) + IndicatorTemplate::getName) .widthProportion(2)) .withColumn(new ColumnDefinition<>( Domain.INDICATOR.ATTR_TYPE, INDICATOR_TYPE_COLUMN_KEY, this::indicatorTypeName) .widthProportion(1)) - .withColumn(new ColumnDefinition<>( + .withColumn(new ColumnDefinition( Domain.THRESHOLD.REFERENCE_NAME, INDICATOR_THRESHOLD_COLUMN_KEY, - ExamFormIndicators::thresholdsValue) + it -> ExamFormIndicators.thresholdsValue(it.thresholds, it.type)) .asMarkup() .widthProportion(4)) .withDefaultActionIf( () -> userGrant.im(), () -> actionBuilder - .newAction(ActionDefinition.EXAM_TEMPLATE_INDICATOR_MODIFY_FROM_LIST) + .newAction(ActionDefinition.INDICATOR_TEMPLATE_MODIFY_FROM_LIST) .withParentEntityKey(entityKey) .create()) .withSelectionListener(this.pageService.getSelectionPublisher( pageContext, - ActionDefinition.EXAM_TEMPLATE_INDICATOR_MODIFY_FROM_LIST, - ActionDefinition.EXAM_TEMPLATE_INDICATOR_DELETE_FROM_LIST)) + ActionDefinition.INDICATOR_TEMPLATE_MODIFY_FROM_LIST, + ActionDefinition.INDICATOR_TEMPLATE_DELETE_FROM_LIST)) .compose(pageContext.copyOf(content)); actionBuilder - .newAction(ActionDefinition.EXAM_TEMPLATE_INDICATOR_MODIFY_FROM_LIST) + .newAction(ActionDefinition.INDICATOR_TEMPLATE_MODIFY_FROM_LIST) .withParentEntityKey(entityKey) .withSelect( indicatorTable::getSelection, @@ -257,7 +257,7 @@ public class ExamTemplateForm implements TemplateComposer { INDICATOR_EMPTY_SELECTION_TEXT_KEY) .publishIf(() -> userGrant.im() && indicatorTable.hasAnyContent(), false) - .newAction(ActionDefinition.EXAM_TEMPLATE_INDICATOR_DELETE_FROM_LIST) + .newAction(ActionDefinition.INDICATOR_TEMPLATE_DELETE_FROM_LIST) .withEntityKey(entityKey) .withSelect( indicatorTable::getSelection, @@ -265,7 +265,7 @@ public class ExamTemplateForm implements TemplateComposer { INDICATOR_EMPTY_SELECTION_TEXT_KEY) .publishIf(() -> userGrant.im() && indicatorTable.hasAnyContent(), false) - .newAction(ActionDefinition.EXAM_TEMPLATE_INDICATOR_NEW) + .newAction(ActionDefinition.INDICATOR_TEMPLATE_NEW) .withParentEntityKey(entityKey) .publishIf(() -> userGrant.im()); } @@ -275,14 +275,14 @@ public class ExamTemplateForm implements TemplateComposer { final EntityKey entityKey = action.getEntityKey(); final EntityKey indicatorKey = action.getSingleSelection(); this.resourceService.getRestService() - .getBuilder(DeleteExamTemplateIndicator.class) + .getBuilder(DeleteIndicatorTemplate.class) .withURIVariable(API.PARAM_PARENT_MODEL_ID, entityKey.modelId) .withURIVariable(API.PARAM_MODEL_ID, indicatorKey.modelId) .call(); return action; } - private String indicatorTypeName(final Indicator indicator) { + private String indicatorTypeName(final IndicatorTemplate indicator) { if (indicator.type == null) { return Constants.EMPTY_NOTE; } diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/content/exam/ExamTemplateIndicatorForm.java b/src/main/java/ch/ethz/seb/sebserver/gui/content/exam/ExamTemplateIndicatorForm.java deleted file mode 100644 index 1450e222..00000000 --- a/src/main/java/ch/ethz/seb/sebserver/gui/content/exam/ExamTemplateIndicatorForm.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (c) 2021 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.exam; - -import org.springframework.context.annotation.Lazy; -import org.springframework.stereotype.Component; - -import ch.ethz.seb.sebserver.gbl.profile.GuiProfile; -import ch.ethz.seb.sebserver.gui.service.page.PageContext; -import ch.ethz.seb.sebserver.gui.service.page.TemplateComposer; - -@Lazy -@Component -@GuiProfile -public class ExamTemplateIndicatorForm implements TemplateComposer { - - @Override - public void compose(final PageContext pageContext) { - // TODO Auto-generated method stub - - } - -} diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/content/exam/IndicatorForm.java b/src/main/java/ch/ethz/seb/sebserver/gui/content/exam/IndicatorForm.java index 88ec8c38..5b12e846 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/content/exam/IndicatorForm.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/content/exam/IndicatorForm.java @@ -99,7 +99,7 @@ public class IndicatorForm implements TemplateComposer { // get data or create new. Handle error if happen final Indicator indicator = (isNew) - ? Indicator.createNew(exam) + ? Indicator.createNew(exam.getModelId()) : restService .getBuilder(GetIndicator.class) .withURIVariable(API.PARAM_MODEL_ID, entityKey.modelId) @@ -176,7 +176,7 @@ public class IndicatorForm implements TemplateComposer { .addField(FormBuilder.thresholdList( Domain.THRESHOLD.REFERENCE_NAME, FORM_THRESHOLDS_TEXT_KEY, - indicator)) + indicator.thresholds)) .buildFor((isNew) ? restService.getRestCall(NewIndicator.class) diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/content/exam/IndicatorTemplateForm.java b/src/main/java/ch/ethz/seb/sebserver/gui/content/exam/IndicatorTemplateForm.java new file mode 100644 index 00000000..cc5bffb2 --- /dev/null +++ b/src/main/java/ch/ethz/seb/sebserver/gui/content/exam/IndicatorTemplateForm.java @@ -0,0 +1,221 @@ +/* + * Copyright (c) 2021 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.exam; + +import org.apache.commons.lang3.StringUtils; +import org.eclipse.swt.widgets.Composite; +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; +import ch.ethz.seb.sebserver.gbl.model.EntityKey; +import ch.ethz.seb.sebserver.gbl.model.exam.ExamTemplate; +import ch.ethz.seb.sebserver.gbl.model.exam.Indicator.IndicatorType; +import ch.ethz.seb.sebserver.gbl.model.exam.IndicatorTemplate; +import ch.ethz.seb.sebserver.gbl.profile.GuiProfile; +import ch.ethz.seb.sebserver.gbl.util.Utils; +import ch.ethz.seb.sebserver.gui.content.action.ActionDefinition; +import ch.ethz.seb.sebserver.gui.form.Form; +import ch.ethz.seb.sebserver.gui.form.FormBuilder; +import ch.ethz.seb.sebserver.gui.form.FormHandle; +import ch.ethz.seb.sebserver.gui.service.ResourceService; +import ch.ethz.seb.sebserver.gui.service.i18n.I18nSupport; +import ch.ethz.seb.sebserver.gui.service.i18n.LocTextKey; +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.TemplateComposer; +import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestService; +import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.GetExamTemplate; +import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.GetIndicatorTemplate; +import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.NewIndicatorTemplate; +import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.SaveIndicatorTemplate; +import ch.ethz.seb.sebserver.gui.widget.WidgetFactory; + +@Lazy +@Component +@GuiProfile +public class IndicatorTemplateForm implements TemplateComposer { + + private static final LocTextKey NEW_INDICATOR_TILE_TEXT_KEY = + new LocTextKey("sebserver.exam.indicator.form.title.new"); + private static final LocTextKey INDICATOR_TILE_TEXT_KEY = + new LocTextKey("sebserver.exam.indicator.form.title"); + private static final LocTextKey FORM_THRESHOLDS_TEXT_KEY = + new LocTextKey("sebserver.exam.indicator.form.thresholds"); + private static final LocTextKey FORM_COLOR_TEXT_KEY = + new LocTextKey("sebserver.exam.indicator.form.color"); + private static final LocTextKey FORM_TYPE_TEXT_KEY = + new LocTextKey("sebserver.exam.indicator.form.type"); + private static final LocTextKey FORM_NAME_TEXT_KEY = + new LocTextKey("sebserver.exam.indicator.form.name"); + private static final LocTextKey FORM_TAGS_TEXT_KEY = + new LocTextKey("sebserver.exam.indicator.form.tags"); + private static final LocTextKey FORM_EXAM_TEXT_KEY = + new LocTextKey("sebserver.exam.indicator.form.exam"); + private static final LocTextKey FORM_DESC_TEXT_KEY = + new LocTextKey("sebserver.exam.indicator.form.description"); + + private static final String INDICATOR_TYPE_DESC_PREFIX = + "sebserver.exam.indicator.type.description."; + private static final String TYPE_DESCRIPTION_FIELD_NAME = + "typeDescription"; + + private final PageService pageService; + private final ResourceService resourceService; + private final I18nSupport i18nSupport; + + protected IndicatorTemplateForm(final PageService pageService) { + + this.pageService = pageService; + this.resourceService = pageService.getResourceService(); + this.i18nSupport = pageService.getI18nSupport(); + } + + @Override + public void compose(final PageContext pageContext) { + final RestService restService = this.resourceService.getRestService(); + final WidgetFactory widgetFactory = this.pageService.getWidgetFactory(); + final EntityKey entityKey = pageContext.getEntityKey(); + final EntityKey parentEntityKey = pageContext.getParentEntityKey(); + final boolean isNew = entityKey == null; + final boolean isReadonly = pageContext.isReadonly(); + + final ExamTemplate examTemplate = restService + .getBuilder(GetExamTemplate.class) + .withURIVariable(API.PARAM_MODEL_ID, parentEntityKey.modelId) + .call() + .onError(error -> pageContext.notifyLoadError(EntityType.EXAM, error)) + .getOrThrow(); + + // get data or create new. Handle error if happen + final IndicatorTemplate indicatorTemplate = (isNew) + ? new IndicatorTemplate(null, Long.parseLong(parentEntityKey.modelId), + null, null, null, null, null, null) + : restService + .getBuilder(GetIndicatorTemplate.class) + .withURIVariable(API.PARAM_PARENT_MODEL_ID, parentEntityKey.modelId) + .withURIVariable(API.PARAM_MODEL_ID, entityKey.modelId) + .call() + .onError(error -> pageContext.notifyLoadError(EntityType.INDICATOR, error)) + .getOrThrow(); + + final boolean typeSet = indicatorTemplate.type != null; + final String typeDescription = (typeSet) + ? Utils.formatLineBreaks( + this.i18nSupport.getText(INDICATOR_TYPE_DESC_PREFIX + indicatorTemplate.type.name)) + : Constants.EMPTY_NOTE; + + // new PageContext with actual EntityKey + final PageContext formContext = pageContext.withEntityKey(indicatorTemplate.getEntityKey()); + + // the default page layout + final LocTextKey titleKey = (isNew) + ? NEW_INDICATOR_TILE_TEXT_KEY + : INDICATOR_TILE_TEXT_KEY; + final Composite content = widgetFactory.defaultPageLayout( + formContext.getParent(), + titleKey); + + final FormHandle formHandle = this.pageService.formBuilder( + formContext.copyOf(content)) + .readonly(isReadonly) + .putStaticValueIf(() -> !isNew, + Domain.INDICATOR.ATTR_ID, + indicatorTemplate.getModelId()) + .putStaticValue( + Domain.EXAM.ATTR_INSTITUTION_ID, + String.valueOf(examTemplate.getInstitutionId())) + .putStaticValue( + Domain.INDICATOR.ATTR_EXAM_ID, + parentEntityKey.getModelId()) + .addField(FormBuilder.text( + Domain.EXAM_TEMPLATE.ATTR_NAME, + FORM_EXAM_TEXT_KEY, + examTemplate.name) + .readonly(true)) + .addField(FormBuilder.text( + Domain.INDICATOR.ATTR_NAME, + FORM_NAME_TEXT_KEY, + indicatorTemplate.name) + .mandatory(!isReadonly)) + + .addField(FormBuilder.singleSelection( + Domain.INDICATOR.ATTR_TYPE, + FORM_TYPE_TEXT_KEY, + (indicatorTemplate.type != null) ? indicatorTemplate.type.name() : null, + this.resourceService::indicatorTypeResources) + .withSelectionListener(this::updateForm) + .mandatory(!isReadonly)) + + .addField(FormBuilder.text( + TYPE_DESCRIPTION_FIELD_NAME, + FORM_DESC_TEXT_KEY, + typeDescription) + .asArea() + //.asHTML(true) + .readonly(true) + .withInputSpan(6)) + + .addField(FormBuilder.colorSelection( + Domain.INDICATOR.ATTR_COLOR, + FORM_COLOR_TEXT_KEY, + indicatorTemplate.defaultColor) + .withEmptyCellSeparation(false)) + .addField(FormBuilder.text( + Domain.INDICATOR.ATTR_TAGS, + FORM_TAGS_TEXT_KEY, + indicatorTemplate.tags) + .visibleIf(indicatorTemplate.type != null && indicatorTemplate.type.tags + && !indicatorTemplate.type.tagsReadonly)) + .addField(FormBuilder.thresholdList( + Domain.THRESHOLD.REFERENCE_NAME, + FORM_THRESHOLDS_TEXT_KEY, + indicatorTemplate.thresholds)) + + .buildFor((isNew) + ? restService.getRestCall(NewIndicatorTemplate.class) + : restService.getRestCall(SaveIndicatorTemplate.class)); + + // propagate content actions to action-pane + this.pageService.pageActionBuilder(formContext.clearEntityKeys()) + + .newAction(ActionDefinition.INDICATOR_TEMPLATE_SAVE) + .withEntityKey(parentEntityKey) + .withExec(formHandle::processFormSave) + .ignoreMoveAwayFromEdit() + .publishIf(() -> !isReadonly) + + .newAction(ActionDefinition.INDICATOR_TEMPLATE_CANCEL_MODIFY) + .withEntityKey(parentEntityKey) + .withExec(this.pageService.backToCurrentFunction()) + .publishIf(() -> !isReadonly); + + } + + private void updateForm(final Form form) { + final String typeValue = form.getFieldValue(Domain.INDICATOR.ATTR_TYPE); + if (StringUtils.isNotBlank(typeValue)) { + final String text = this.i18nSupport.getText(INDICATOR_TYPE_DESC_PREFIX + typeValue); + form.setFieldValue( + TYPE_DESCRIPTION_FIELD_NAME, + Utils.formatLineBreaks(text)); + final IndicatorType type = IndicatorType.valueOf(typeValue); + form.setFieldVisible(type.tags && !type.tagsReadonly, Domain.INDICATOR.ATTR_TAGS); + if (!type.tags || type.tagsReadonly) { + form.setFieldValue(Domain.INDICATOR.ATTR_TAGS, StringUtils.EMPTY); + } + } else { + form.setFieldValue(TYPE_DESCRIPTION_FIELD_NAME, Constants.EMPTY_NOTE); + } + } + +} diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/form/FormBuilder.java b/src/main/java/ch/ethz/seb/sebserver/gui/form/FormBuilder.java index 3eb45487..3b162147 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/form/FormBuilder.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/form/FormBuilder.java @@ -24,7 +24,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import ch.ethz.seb.sebserver.gbl.model.Entity; -import ch.ethz.seb.sebserver.gbl.model.exam.Indicator; +import ch.ethz.seb.sebserver.gbl.model.exam.Indicator.Threshold; import ch.ethz.seb.sebserver.gbl.util.Cryptor; import ch.ethz.seb.sebserver.gbl.util.Tuple; import ch.ethz.seb.sebserver.gui.service.i18n.I18nSupport; @@ -279,12 +279,12 @@ public class FormBuilder { public static ThresholdListBuilder thresholdList( final String name, final LocTextKey label, - final Indicator indicator) { + final List thresholds) { return new ThresholdListBuilder( name, label, - indicator.thresholds); + thresholds); } public static ImageUploadFieldBuilder imageUpload(final String name, final LocTextKey label, final String value) { diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/exam/DeleteExamTemplateIndicator.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/exam/DeleteIndicatorTemplate.java similarity index 89% rename from src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/exam/DeleteExamTemplateIndicator.java rename to src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/exam/DeleteIndicatorTemplate.java index 98cf5fdd..91a14195 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/exam/DeleteExamTemplateIndicator.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/exam/DeleteIndicatorTemplate.java @@ -24,9 +24,9 @@ import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCall; @Lazy @Component @GuiProfile -public class DeleteExamTemplateIndicator extends RestCall { +public class DeleteIndicatorTemplate extends RestCall { - public DeleteExamTemplateIndicator() { + public DeleteIndicatorTemplate() { super(new TypeKey<>( CallType.DELETE, EntityType.INDICATOR, diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/exam/GetExamTemplateIndicator.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/exam/GetIndicatorTemplate.java similarity index 82% rename from src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/exam/GetExamTemplateIndicator.java rename to src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/exam/GetIndicatorTemplate.java index a1fa8f0a..71760038 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/exam/GetExamTemplateIndicator.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/exam/GetIndicatorTemplate.java @@ -17,20 +17,20 @@ 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.exam.Indicator; +import ch.ethz.seb.sebserver.gbl.model.exam.IndicatorTemplate; import ch.ethz.seb.sebserver.gbl.profile.GuiProfile; import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCall; @Lazy @Component @GuiProfile -public class GetExamTemplateIndicator extends RestCall { +public class GetIndicatorTemplate extends RestCall { - public GetExamTemplateIndicator() { + public GetIndicatorTemplate() { super(new TypeKey<>( CallType.GET_SINGLE, EntityType.INDICATOR, - new TypeReference() { + new TypeReference() { }), HttpMethod.GET, MediaType.APPLICATION_FORM_URLENCODED, diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/exam/GetExamTemplateIndicatorPage.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/exam/GetIndicatorTemplatePage.java similarity index 81% rename from src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/exam/GetExamTemplateIndicatorPage.java rename to src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/exam/GetIndicatorTemplatePage.java index a7bc3d1a..1658c141 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/exam/GetExamTemplateIndicatorPage.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/exam/GetIndicatorTemplatePage.java @@ -18,20 +18,20 @@ 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.Page; -import ch.ethz.seb.sebserver.gbl.model.exam.Indicator; +import ch.ethz.seb.sebserver.gbl.model.exam.IndicatorTemplate; import ch.ethz.seb.sebserver.gbl.profile.GuiProfile; import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCall; @Lazy @Component @GuiProfile -public class GetExamTemplateIndicatorPage extends RestCall> { +public class GetIndicatorTemplatePage extends RestCall> { - public GetExamTemplateIndicatorPage() { + public GetIndicatorTemplatePage() { super(new TypeKey<>( CallType.GET_PAGE, EntityType.INDICATOR, - new TypeReference>() { + new TypeReference>() { }), HttpMethod.GET, MediaType.APPLICATION_FORM_URLENCODED, diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/exam/NewExamTemplateIndicator.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/exam/NewIndicatorTemplate.java similarity index 78% rename from src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/exam/NewExamTemplateIndicator.java rename to src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/exam/NewIndicatorTemplate.java index a1dba212..40ad32b4 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/exam/NewExamTemplateIndicator.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/exam/NewIndicatorTemplate.java @@ -17,25 +17,24 @@ 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.exam.Indicator; +import ch.ethz.seb.sebserver.gbl.model.exam.IndicatorTemplate; import ch.ethz.seb.sebserver.gbl.profile.GuiProfile; import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCall; @Lazy @Component @GuiProfile -public class NewExamTemplateIndicator extends RestCall { +public class NewIndicatorTemplate extends RestCall { - public NewExamTemplateIndicator() { + public NewIndicatorTemplate() { super(new TypeKey<>( CallType.NEW, EntityType.INDICATOR, - new TypeReference() { + new TypeReference() { }), HttpMethod.POST, MediaType.APPLICATION_FORM_URLENCODED, API.EXAM_TEMPLATE_ENDPOINT - + API.PARENT_MODEL_ID_VAR_PATH_SEGMENT + API.EXAM_TEMPLATE_INDICATOR_PATH_SEGMENT); } diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/exam/SaveExamTemplateIndicator.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/exam/SaveIndicatorTemplate.java similarity index 75% rename from src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/exam/SaveExamTemplateIndicator.java rename to src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/exam/SaveIndicatorTemplate.java index 04b1e3c8..83694f8c 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/exam/SaveExamTemplateIndicator.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/exam/SaveIndicatorTemplate.java @@ -17,27 +17,25 @@ 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.exam.Indicator; +import ch.ethz.seb.sebserver.gbl.model.exam.IndicatorTemplate; import ch.ethz.seb.sebserver.gbl.profile.GuiProfile; import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCall; @Lazy @Component @GuiProfile -public class SaveExamTemplateIndicator extends RestCall { +public class SaveIndicatorTemplate extends RestCall { - public SaveExamTemplateIndicator() { + public SaveIndicatorTemplate() { super(new TypeKey<>( CallType.SAVE, EntityType.INDICATOR, - new TypeReference() { + new TypeReference() { }), HttpMethod.PUT, MediaType.APPLICATION_JSON, API.EXAM_TEMPLATE_ENDPOINT - + API.PARENT_MODEL_ID_VAR_PATH_SEGMENT - + API.EXAM_TEMPLATE_INDICATOR_PATH_SEGMENT - + API.MODEL_ID_VAR_PATH_SEGMENT); + + API.EXAM_TEMPLATE_INDICATOR_PATH_SEGMENT); } } diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ExamTemplateDAOImpl.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ExamTemplateDAOImpl.java index 8490aba5..5cfd68b3 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ExamTemplateDAOImpl.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ExamTemplateDAOImpl.java @@ -34,7 +34,7 @@ import ch.ethz.seb.sebserver.gbl.api.JSONMapper; import ch.ethz.seb.sebserver.gbl.model.EntityKey; import ch.ethz.seb.sebserver.gbl.model.exam.Exam.ExamType; import ch.ethz.seb.sebserver.gbl.model.exam.ExamTemplate; -import ch.ethz.seb.sebserver.gbl.model.exam.Indicator; +import ch.ethz.seb.sebserver.gbl.model.exam.IndicatorTemplate; import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile; import ch.ethz.seb.sebserver.gbl.util.Result; import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.ExamTemplateRecordDynamicSqlSupport; @@ -125,7 +125,7 @@ public class ExamTemplateDAOImpl implements ExamTemplateDAO { checkUniqueName(data); - final Collection indicatorTemplates = data.getIndicatorTemplates(); + final Collection indicatorTemplates = data.getIndicatorTemplates(); final String indicatorsJSON = (indicatorTemplates != null && !indicatorTemplates.isEmpty()) ? this.jsonMapper.writeValueAsString(indicatorTemplates) : null; @@ -158,7 +158,7 @@ public class ExamTemplateDAOImpl implements ExamTemplateDAO { checkUniqueName(data); - final Collection indicatorTemplates = data.getIndicatorTemplates(); + final Collection indicatorTemplates = data.getIndicatorTemplates(); final String indicatorsJSON = (indicatorTemplates != null && !indicatorTemplates.isEmpty()) ? this.jsonMapper.writeValueAsString(indicatorTemplates) : null; @@ -232,9 +232,10 @@ public class ExamTemplateDAOImpl implements ExamTemplateDAO { return Result.tryCatch(() -> { final String indicatorTemplatesString = record.getIndicatorTemplates(); - final Collection indicators = (StringUtils.isNotBlank(indicatorTemplatesString)) - ? this.jsonMapper.readValue(indicatorTemplatesString, new TypeReference>() { - }) + final Collection indicators = (StringUtils.isNotBlank(indicatorTemplatesString)) + ? this.jsonMapper.readValue(indicatorTemplatesString, + new TypeReference>() { + }) : null; final Map examAttributes = this.additionalAttributesDAO diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ExamTemplateController.java b/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ExamTemplateController.java index e35bc4e6..fc2f3f3a 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ExamTemplateController.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ExamTemplateController.java @@ -41,6 +41,7 @@ import ch.ethz.seb.sebserver.gbl.model.Page; import ch.ethz.seb.sebserver.gbl.model.PageSortOrder; import ch.ethz.seb.sebserver.gbl.model.exam.ExamTemplate; import ch.ethz.seb.sebserver.gbl.model.exam.Indicator; +import ch.ethz.seb.sebserver.gbl.model.exam.IndicatorTemplate; import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile; import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.ExamTemplateRecordDynamicSqlSupport; import ch.ethz.seb.sebserver.webservice.servicelayer.PaginationService; @@ -82,7 +83,7 @@ public class ExamTemplateController extends EntityController getIndicatorPage( + public Page getIndicatorPage( @PathVariable final String modelId, @RequestParam( name = API.PARAM_INSTITUTION_ID, @@ -119,7 +120,7 @@ public class ExamTemplateController extends EntityController allRequestParams, @RequestParam( name = API.PARAM_INSTITUTION_ID, @@ -161,19 +160,21 @@ public class ExamTemplateController extends EntityController indicators = new ArrayList<>(examTemplate.indicatorTemplates); + final ArrayList indicators = new ArrayList<>(examTemplate.indicatorTemplates); indicators.add(newIndicator); final ExamTemplate newExamTemplate = new ExamTemplate( examTemplate.id, @@ -189,29 +190,26 @@ public class ExamTemplateController extends EntityController newIndicators = examTemplate.indicatorTemplates + final String modelId = modifyData.getModelId(); + final List newIndicators = examTemplate.indicatorTemplates .stream() .map(i -> { if (modelId.equals(i.getModelId())) { @@ -241,7 +239,7 @@ public class ExamTemplateController extends EntityController newIndicators = examTemplate.indicatorTemplates + final List newIndicators = examTemplate.indicatorTemplates .stream() .filter(i -> !modelId.equals(i.getModelId())) .collect(Collectors.toList()); @@ -285,11 +283,11 @@ public class ExamTemplateController extends EntityController, List> pageSort(final String sort) { + static Function, List> pageSort(final String sort) { final String sortBy = PageSortOrder.decode(sort); return indicators -> { - final List list = indicators.stream().collect(Collectors.toList()); + final List list = indicators.stream().collect(Collectors.toList()); if (StringUtils.isBlank(sort)) { return list; } diff --git a/src/main/resources/config/sql/base/V10__examTemplates_v1_3.sql b/src/main/resources/config/sql/base/V10__examTemplates_v1_3.sql index 38566475..bd7e4522 100644 --- a/src/main/resources/config/sql/base/V10__examTemplates_v1_3.sql +++ b/src/main/resources/config/sql/base/V10__examTemplates_v1_3.sql @@ -6,7 +6,7 @@ DROP TABLE IF EXISTS `exam_template` ; CREATE TABLE IF NOT EXISTS `exam_template` ( `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, `institution_id` BIGINT UNSIGNED NOT NULL, - `configuration_template_id` BIGINT UNSIGNED NOT NULL, + `configuration_template_id` BIGINT UNSIGNED NULL, `name` VARCHAR(255) NOT NULL, `description` VARCHAR(4000) NULL, `exam_type` VARCHAR(45) NULL, diff --git a/src/main/resources/messages.properties b/src/main/resources/messages.properties index ffb0fd43..7895b43e 100644 --- a/src/main/resources/messages.properties +++ b/src/main/resources/messages.properties @@ -1602,8 +1602,8 @@ sebserver.examtemplate.list.title.subtitle= sebserver.examtemplate.list.empty=There is currently no exam template available. Please create a new one sebserver.examtemplate.list.actions= sebserver.examtemplate.list.action.no.modify.privilege=No Access: An Exam Template from other institution cannot be modified. -sebserver.examtemplate.action.list.view=View -sebserver.examtemplate.action.list.modify=Edit +sebserver.examtemplate.action.list.view=View Exam Template +sebserver.examtemplate.action.list.modify=Edit Exam Template sebserver.examtemplate.action.list.new=Add Exam Template sebserver.examtemplate.list.column.institution=Institution @@ -1629,7 +1629,10 @@ sebserver.examtemplate.form.examConfigTemplate.tooltip=The linked ecam configura sebserver.examtemplate.form.supporter=Exam Supporter sebserver.examtemplate.form.supporter.tooltip=List of all exam supporter user that will automatically be applied to an exam imported with this template. +sebserver.examtemplate.form.action.save=Save +sebserver.examtemplate.form.action.edit=Edit Template Settings +sebserver.examtemplate.indicator.list.actions= sebserver.examtemplate.indicator.list.title=Indicators sebserver.examtemplate.indicator.list.title.tooltip=A list of indicators that will automatically be created when importing a exam with this template sebserver.examtemplate.indicator.list.column.type=Type diff --git a/src/test/resources/schema-test.sql b/src/test/resources/schema-test.sql index 0f654f8a..6fbeffaa 100644 --- a/src/test/resources/schema-test.sql +++ b/src/test/resources/schema-test.sql @@ -611,7 +611,7 @@ DROP TABLE IF EXISTS `exam_template` ; CREATE TABLE IF NOT EXISTS `exam_template` ( `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, `institution_id` BIGINT UNSIGNED NOT NULL, - `configuration_template_id` BIGINT UNSIGNED NOT NULL, + `configuration_template_id` BIGINT UNSIGNED NULL, `name` VARCHAR(255) NOT NULL, `description` VARCHAR(4000) NULL, `exam_type` VARCHAR(45) NULL,