SEBSERV-44 SEBSERV-45 Exam - SEB Configuration mapping implementation

This commit is contained in:
anhefti 2019-05-27 16:29:09 +02:00
parent 322f1c640d
commit a57f937724
36 changed files with 1011 additions and 111 deletions

View file

@ -6,7 +6,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. * file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/ */
package ch.ethz.seb.sebserver.gbl.model.sebconfig; package ch.ethz.seb.sebserver.gbl.model.exam;
import javax.validation.constraints.NotNull; import javax.validation.constraints.NotNull;
@ -16,9 +16,12 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonProperty;
import ch.ethz.seb.sebserver.gbl.api.EntityType; 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.CONFIGURATION_NODE;
import ch.ethz.seb.sebserver.gbl.model.Domain.EXAM_CONFIGURATION_MAP; import ch.ethz.seb.sebserver.gbl.model.Domain.EXAM_CONFIGURATION_MAP;
import ch.ethz.seb.sebserver.gbl.model.Domain.SEB_CLIENT_CONFIGURATION;
import ch.ethz.seb.sebserver.gbl.model.GrantEntity; import ch.ethz.seb.sebserver.gbl.model.GrantEntity;
import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode.ConfigurationStatus;
@JsonIgnoreProperties(ignoreUnknown = true) @JsonIgnoreProperties(ignoreUnknown = true)
public final class ExamConfigurationMap implements GrantEntity { public final class ExamConfigurationMap implements GrantEntity {
@ -35,14 +38,23 @@ public final class ExamConfigurationMap implements GrantEntity {
@JsonProperty(EXAM_CONFIGURATION_MAP.ATTR_INSTITUTION_ID) @JsonProperty(EXAM_CONFIGURATION_MAP.ATTR_INSTITUTION_ID)
public final Long institutionId; public final Long institutionId;
@NotNull @NotNull(message = "examConfigurationMap:examId:notNull")
@JsonProperty(EXAM_CONFIGURATION_MAP.ATTR_EXAM_ID) @JsonProperty(EXAM_CONFIGURATION_MAP.ATTR_EXAM_ID)
public final Long examId; public final Long examId;
@NotNull @NotNull(message = "examConfigurationMap:configurationNodeId:notNull")
@JsonProperty(EXAM_CONFIGURATION_MAP.ATTR_CONFIGURATION_NODE_ID) @JsonProperty(EXAM_CONFIGURATION_MAP.ATTR_CONFIGURATION_NODE_ID)
public final Long configurationNodeId; public final Long configurationNodeId;
@JsonProperty(CONFIGURATION_NODE.ATTR_NAME)
public final String configName;
@JsonProperty(CONFIGURATION_NODE.ATTR_DESCRIPTION)
public final String configDescription;
@JsonProperty(CONFIGURATION_NODE.ATTR_STATUS)
public final ConfigurationStatus configStatus;
@JsonProperty(EXAM_CONFIGURATION_MAP.ATTR_USER_NAMES) @JsonProperty(EXAM_CONFIGURATION_MAP.ATTR_USER_NAMES)
public final String userNames; public final String userNames;
@ -59,8 +71,12 @@ public final class ExamConfigurationMap implements GrantEntity {
@JsonProperty(EXAM_CONFIGURATION_MAP.ATTR_EXAM_ID) final Long examId, @JsonProperty(EXAM_CONFIGURATION_MAP.ATTR_EXAM_ID) final Long examId,
@JsonProperty(EXAM_CONFIGURATION_MAP.ATTR_CONFIGURATION_NODE_ID) final Long configurationNodeId, @JsonProperty(EXAM_CONFIGURATION_MAP.ATTR_CONFIGURATION_NODE_ID) final Long configurationNodeId,
@JsonProperty(EXAM_CONFIGURATION_MAP.ATTR_USER_NAMES) final String userNames, @JsonProperty(EXAM_CONFIGURATION_MAP.ATTR_USER_NAMES) final String userNames,
@JsonProperty(SEB_CLIENT_CONFIGURATION.ATTR_ENCRYPT_SECRET) final CharSequence encryptSecret, @JsonProperty(EXAM_CONFIGURATION_MAP.ATTR_ENCRYPT_SECRET) final CharSequence encryptSecret,
@JsonProperty(ATTR_CONFIRM_ENCRYPT_SECRET) final CharSequence confirmEncryptSecret) { @JsonProperty(ATTR_CONFIRM_ENCRYPT_SECRET) final CharSequence confirmEncryptSecret,
@JsonProperty(CONFIGURATION_NODE.ATTR_NAME) final String configName,
@JsonProperty(CONFIGURATION_NODE.ATTR_DESCRIPTION) final String configDescription,
@JsonProperty(CONFIGURATION_NODE.ATTR_STATUS) final ConfigurationStatus configStatus) {
this.id = id; this.id = id;
this.institutionId = institutionId; this.institutionId = institutionId;
@ -69,6 +85,24 @@ public final class ExamConfigurationMap implements GrantEntity {
this.userNames = userNames; this.userNames = userNames;
this.encryptSecret = encryptSecret; this.encryptSecret = encryptSecret;
this.confirmEncryptSecret = confirmEncryptSecret; this.confirmEncryptSecret = confirmEncryptSecret;
this.configName = configName;
this.configDescription = configDescription;
this.configStatus = configStatus;
}
public ExamConfigurationMap(final Long institutionId, final POSTMapper postParams) {
this.id = null;
this.institutionId = institutionId;
this.examId = postParams.getLong(Domain.EXAM_CONFIGURATION_MAP.ATTR_EXAM_ID);
this.configurationNodeId = postParams.getLong(Domain.EXAM_CONFIGURATION_MAP.ATTR_CONFIGURATION_NODE_ID);
this.userNames = postParams.getString(Domain.EXAM_CONFIGURATION_MAP.ATTR_USER_NAMES);
this.encryptSecret = postParams.getCharSequence(Domain.EXAM_CONFIGURATION_MAP.ATTR_ENCRYPT_SECRET);
this.confirmEncryptSecret = postParams.getCharSequence(ATTR_CONFIRM_ENCRYPT_SECRET);
this.configName = postParams.getString(Domain.CONFIGURATION_NODE.ATTR_NAME);
this.configDescription = postParams.getString(Domain.CONFIGURATION_NODE.ATTR_DESCRIPTION);
this.configStatus = postParams.getEnum(Domain.CONFIGURATION_NODE.ATTR_STATUS, ConfigurationStatus.class);
} }
@Override @Override
@ -122,6 +156,18 @@ public final class ExamConfigurationMap implements GrantEntity {
return this.encryptSecret != null && this.encryptSecret.length() > 0; return this.encryptSecret != null && this.encryptSecret.length() > 0;
} }
public String getConfigName() {
return this.configName;
}
public String getConfigDescription() {
return this.configDescription;
}
public ConfigurationStatus getConfigStatus() {
return this.configStatus;
}
@Override @Override
public String toString() { public String toString() {
final StringBuilder builder = new StringBuilder(); final StringBuilder builder = new StringBuilder();
@ -133,10 +179,20 @@ public final class ExamConfigurationMap implements GrantEntity {
builder.append(this.examId); builder.append(this.examId);
builder.append(", configurationNodeId="); builder.append(", configurationNodeId=");
builder.append(this.configurationNodeId); builder.append(this.configurationNodeId);
builder.append(", configName=");
builder.append(this.configName);
builder.append(", configDescription=");
builder.append(this.configDescription);
builder.append(", configStatus=");
builder.append(this.configStatus);
builder.append(", userNames="); builder.append(", userNames=");
builder.append(this.userNames); builder.append(this.userNames);
builder.append("]"); builder.append("]");
return builder.toString(); return builder.toString();
} }
public static ExamConfigurationMap createNew(final Exam exam) {
return new ExamConfigurationMap(null, exam.institutionId, exam.id, null, null, null, null, null, null, null);
}
} }

View file

@ -29,7 +29,7 @@ import ch.ethz.seb.sebserver.gbl.util.Utils;
@JsonIgnoreProperties(ignoreUnknown = true) @JsonIgnoreProperties(ignoreUnknown = true)
public final class Indicator implements Entity { public final class Indicator implements Entity {
public static final String FILTER_ATTR_EXAM = "exam"; public static final String FILTER_ATTR_EXAM_ID = "examId";
public enum IndicatorType { public enum IndicatorType {
LAST_PING, LAST_PING,

View file

@ -8,6 +8,9 @@
package ch.ethz.seb.sebserver.gui.content; package ch.ethz.seb.sebserver.gui.content;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.function.BooleanSupplier; import java.util.function.BooleanSupplier;
import org.apache.commons.lang3.BooleanUtils; import org.apache.commons.lang3.BooleanUtils;
@ -23,6 +26,7 @@ import ch.ethz.seb.sebserver.gbl.api.API;
import ch.ethz.seb.sebserver.gbl.model.Domain; import ch.ethz.seb.sebserver.gbl.model.Domain;
import ch.ethz.seb.sebserver.gbl.model.EntityKey; import ch.ethz.seb.sebserver.gbl.model.EntityKey;
import ch.ethz.seb.sebserver.gbl.model.exam.Exam; import ch.ethz.seb.sebserver.gbl.model.exam.Exam;
import ch.ethz.seb.sebserver.gbl.model.exam.ExamConfigurationMap;
import ch.ethz.seb.sebserver.gbl.model.exam.Exam.ExamStatus; import ch.ethz.seb.sebserver.gbl.model.exam.Exam.ExamStatus;
import ch.ethz.seb.sebserver.gbl.model.exam.Indicator; import ch.ethz.seb.sebserver.gbl.model.exam.Indicator;
import ch.ethz.seb.sebserver.gbl.model.exam.QuizData; import ch.ethz.seb.sebserver.gbl.model.exam.QuizData;
@ -42,8 +46,10 @@ import ch.ethz.seb.sebserver.gui.service.page.TemplateComposer;
import ch.ethz.seb.sebserver.gui.service.page.event.ActionEvent; import ch.ethz.seb.sebserver.gui.service.page.event.ActionEvent;
import ch.ethz.seb.sebserver.gui.service.page.impl.PageAction; 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.RestService;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.DeleteExamConfigMapping;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.DeleteIndicator; import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.DeleteIndicator;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.GetExam; import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.GetExam;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.GetExamConfigMappingsPage;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.GetIndicators; import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.GetIndicators;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.SaveExam; import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.SaveExam;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.quiz.GetQuizData; import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.quiz.GetQuizData;
@ -62,28 +68,50 @@ public class ExamForm implements TemplateComposer {
private static final Logger log = LoggerFactory.getLogger(ExamForm.class); private static final Logger log = LoggerFactory.getLogger(ExamForm.class);
private static final LocTextKey FORM_SUPPORTER_TEXT_KEY = new LocTextKey("sebserver.exam.form.supporter");
private static final LocTextKey FORM_STATUS_TEXT_KEY = new LocTextKey("sebserver.exam.form.status");
private static final LocTextKey FORM_TYPE_TEXT_KEY = new LocTextKey("sebserver.exam.form.type");
private static final LocTextKey FORM_ENDTIME_TEXT_KEY = new LocTextKey("sebserver.exam.form.endtime");
private static final LocTextKey FORM_STARTTIME_TEXT_KEY = new LocTextKey("sebserver.exam.form.starttime");
private static final LocTextKey FORM_DESCRIPTION_TEXT_KEY = new LocTextKey("sebserver.exam.form.description");
private static final LocTextKey FORM_NAME_TEXT_KEY = new LocTextKey("sebserver.exam.form.name");
private static final LocTextKey FORM_QUIZID_TEXT_KEY = new LocTextKey("sebserver.exam.form.quizid");
private static final LocTextKey FORM_LMSSETUP_TEXT_KEY = new LocTextKey("sebserver.exam.form.lmssetup");
private final PageService pageService; private final PageService pageService;
private final ResourceService resourceService; private final ResourceService resourceService;
private final static LocTextKey listTitleKey = private static final LocTextKey CONFIG_EMPTY_LIST_MESSAGE =
new LocTextKey("sebserver.exam.configuration.list.empty");
private static final LocTextKey INDICATOR_EMPTY_LIST_MESSAGE =
new LocTextKey("sebserver.exam.indicator.list.empty");
private static final LocTextKey FORM_SUPPORTER_TEXT_KEY =
new LocTextKey("sebserver.exam.form.supporter");
private static final LocTextKey FORM_STATUS_TEXT_KEY =
new LocTextKey("sebserver.exam.form.status");
private static final LocTextKey FORM_TYPE_TEXT_KEY =
new LocTextKey("sebserver.exam.form.type");
private static final LocTextKey FORM_ENDTIME_TEXT_KEY =
new LocTextKey("sebserver.exam.form.endtime");
private static final LocTextKey FORM_STARTTIME_TEXT_KEY =
new LocTextKey("sebserver.exam.form.starttime");
private static final LocTextKey FORM_DESCRIPTION_TEXT_KEY =
new LocTextKey("sebserver.exam.form.description");
private static final LocTextKey FORM_NAME_TEXT_KEY =
new LocTextKey("sebserver.exam.form.name");
private static final LocTextKey FORM_QUIZID_TEXT_KEY =
new LocTextKey("sebserver.exam.form.quizid");
private static final LocTextKey FORM_LMSSETUP_TEXT_KEY =
new LocTextKey("sebserver.exam.form.lmssetup");
private final static LocTextKey CONFIG_LIST_TITLE_KEY =
new LocTextKey("sebserver.exam.configuration.list.title");
private final static LocTextKey CONFIG_NAME_COLUMN_KEY =
new LocTextKey("sebserver.exam.configuration.list.column.name");
private final static LocTextKey CONFIG_DESCRIPTION_COLUMN_KEY =
new LocTextKey("sebserver.exam.configuration.list.column.description");
private final static LocTextKey CONFIG_STATUS_COLUMN_KEY =
new LocTextKey("sebserver.exam.configuration.list.column.status");
private final static LocTextKey INDICATOR_LIST_TITLE_KEY =
new LocTextKey("sebserver.exam.indicator.list.title"); new LocTextKey("sebserver.exam.indicator.list.title");
private final static LocTextKey typeColumnKey = private final static LocTextKey INDICATOR_TYPE_COLUMN_KEY =
new LocTextKey("sebserver.exam.indicator.list.column.type"); new LocTextKey("sebserver.exam.indicator.list.column.type");
private final static LocTextKey nameColumnKey = private final static LocTextKey INDICATOR_NAME_COLUMN_KEY =
new LocTextKey("sebserver.exam.indicator.list.column.name"); new LocTextKey("sebserver.exam.indicator.list.column.name");
private final static LocTextKey thresholdColumnKey = private final static LocTextKey INDICATOR_THRESHOLD_COLUMN_KEY =
new LocTextKey("sebserver.exam.indicator.list.column.thresholds"); new LocTextKey("sebserver.exam.indicator.list.column.thresholds");
private final static LocTextKey emptySelectionTextKey = private final static LocTextKey INDICATOR_EMPTY_SELECTION_TEXT_KEY =
new LocTextKey("sebserver.exam.indicator.list.pleaseSelect"); new LocTextKey("sebserver.exam.indicator.list.pleaseSelect");
protected ExamForm( protected ExamForm(
@ -162,7 +190,6 @@ public class ExamForm implements TemplateComposer {
.putStaticValueIf(isNew, .putStaticValueIf(isNew,
QuizData.QUIZ_ATTR_ID, QuizData.QUIZ_ATTR_ID,
exam.externalId) exam.externalId)
.addField(FormBuilder.singleSelection( .addField(FormBuilder.singleSelection(
Domain.EXAM.ATTR_LMS_SETUP_ID, Domain.EXAM.ATTR_LMS_SETUP_ID,
FORM_LMSSETUP_TEXT_KEY, FORM_LMSSETUP_TEXT_KEY,
@ -237,35 +264,102 @@ public class ExamForm implements TemplateComposer {
.publishIf(() -> !readonly); .publishIf(() -> !readonly);
// additional data in read-only view // additional data in read-only view
if (readonly) { if (readonly && !importFromQuizData) {
// List of SEB Configuration
widgetFactory.labelLocalized(
content,
CustomVariant.TEXT_H3,
CONFIG_LIST_TITLE_KEY);
final EntityTable<ExamConfigurationMap> configurationTable =
this.pageService.entityTableBuilder(restService.getRestCall(GetExamConfigMappingsPage.class))
.withRestCallAdapter(builder -> builder.withQueryParam(
ExamConfigurationMap.FILTER_ATTR_EXAM_ID,
entityKey.modelId))
.withEmptyMessage(CONFIG_EMPTY_LIST_MESSAGE)
.withPaging(1)
.hideNavigation()
.withColumn(new ColumnDefinition<>(
Domain.CONFIGURATION_NODE.ATTR_NAME,
CONFIG_NAME_COLUMN_KEY,
ExamConfigurationMap::getConfigName,
false))
.withColumn(new ColumnDefinition<>(
Domain.CONFIGURATION_NODE.ATTR_DESCRIPTION,
CONFIG_DESCRIPTION_COLUMN_KEY,
ExamConfigurationMap::getConfigDescription,
false))
.withColumn(new ColumnDefinition<>(
Domain.CONFIGURATION_NODE.ATTR_STATUS,
CONFIG_STATUS_COLUMN_KEY,
this.resourceService::localizedExamConfigStatusName,
false))
.withDefaultActionIf(
() -> editable,
() -> actionBuilder
.newAction(ActionDefinition.EXAM_CONFIGURATION_MODIFY_FROM_LIST)
.create())
.compose(content);
final EntityKey configMapKey = (configurationTable.hasAnyContent())
? configurationTable.getFirstRowData().getEntityKey()
: null;
actionBuilder
.newAction(ActionDefinition.EXAM_CONFIGURATION_NEW)
.withParentEntityKey(entityKey)
.publishIf(() -> modifyGrant && editable && !configurationTable.hasAnyContent())
.newAction(ActionDefinition.EXAM_CONFIGURATION_MODIFY_FROM_LIST)
.withParentEntityKey(entityKey)
.withEntityKey(configMapKey)
.publishIf(() -> modifyGrant && editable && configurationTable.hasAnyContent())
.newAction(ActionDefinition.EXAM_CONFIGURATION_DELETE_FROM_LIST)
.withEntityKey(entityKey)
.withSelect(
() -> {
final ExamConfigurationMap firstRowData = configurationTable.getFirstRowData();
if (firstRowData == null) {
return Collections.emptySet();
} else {
return new HashSet<>(Arrays.asList(firstRowData.getEntityKey()));
}
},
this::deleteExamConfigMapping,
null)
.publishIf(() -> modifyGrant && configurationTable.hasAnyContent() && editable);
// List of Indicators // List of Indicators
widgetFactory.labelLocalized( widgetFactory.labelLocalized(
content, content,
CustomVariant.TEXT_H3, CustomVariant.TEXT_H3,
listTitleKey); INDICATOR_LIST_TITLE_KEY);
final EntityTable<Indicator> indicatorTable = final EntityTable<Indicator> indicatorTable =
this.pageService.entityTableBuilder(restService.getRestCall(GetIndicators.class)) this.pageService.entityTableBuilder(restService.getRestCall(GetIndicators.class))
.withRestCallAdapter(builder -> builder.withQueryParam( .withRestCallAdapter(builder -> builder.withQueryParam(
Indicator.FILTER_ATTR_EXAM, Indicator.FILTER_ATTR_EXAM_ID,
entityKey.modelId)) entityKey.modelId))
.withEmptyMessage(new LocTextKey("sebserver.exam.indicator.list.empty")) .withEmptyMessage(INDICATOR_EMPTY_LIST_MESSAGE)
.withPaging(5) .withPaging(5)
.hideNavigation() .hideNavigation()
.withColumn(new ColumnDefinition<>( .withColumn(new ColumnDefinition<>(
Domain.INDICATOR.ATTR_NAME, Domain.INDICATOR.ATTR_NAME,
nameColumnKey, INDICATOR_NAME_COLUMN_KEY,
Indicator::getName, Indicator::getName,
false)) false))
.withColumn(new ColumnDefinition<>( .withColumn(new ColumnDefinition<>(
Domain.INDICATOR.ATTR_TYPE, Domain.INDICATOR.ATTR_TYPE,
typeColumnKey, INDICATOR_TYPE_COLUMN_KEY,
this::indicatorTypeName, this::indicatorTypeName,
false)) false))
.withColumn(new ColumnDefinition<>( .withColumn(new ColumnDefinition<>(
Domain.THRESHOLD.REFERENCE_NAME, Domain.THRESHOLD.REFERENCE_NAME,
thresholdColumnKey, INDICATOR_THRESHOLD_COLUMN_KEY,
ExamForm::thresholdsValue, ExamForm::thresholdsValue,
false)) false))
.withDefaultActionIf( .withDefaultActionIf(
@ -285,18 +379,20 @@ public class ExamForm implements TemplateComposer {
.newAction(ActionDefinition.EXAM_INDICATOR_MODIFY_FROM_LIST) .newAction(ActionDefinition.EXAM_INDICATOR_MODIFY_FROM_LIST)
.withParentEntityKey(entityKey) .withParentEntityKey(entityKey)
.withSelect(indicatorTable::getSelection, PageAction::applySingleSelection, emptySelectionTextKey) .withSelect(
indicatorTable::getSelection,
PageAction::applySingleSelection,
INDICATOR_EMPTY_SELECTION_TEXT_KEY)
.publishIf(() -> modifyGrant && indicatorTable.hasAnyContent() && editable) .publishIf(() -> modifyGrant && indicatorTable.hasAnyContent() && editable)
.newAction(ActionDefinition.EXAM_INDICATOR_DELETE_FROM_LIST) .newAction(ActionDefinition.EXAM_INDICATOR_DELETE_FROM_LIST)
.withEntityKey(entityKey) .withEntityKey(entityKey)
.withSelect(indicatorTable::getSelection, this::deleteSelectedIndicator, emptySelectionTextKey) .withSelect(
indicatorTable::getSelection,
this::deleteSelectedIndicator,
INDICATOR_EMPTY_SELECTION_TEXT_KEY)
.publishIf(() -> modifyGrant && indicatorTable.hasAnyContent() && editable); .publishIf(() -> modifyGrant && indicatorTable.hasAnyContent() && editable);
// TODO List of attached SEB Configurations
} }
} }
private PageAction deleteSelectedIndicator(final PageAction action) { private PageAction deleteSelectedIndicator(final PageAction action) {
@ -308,6 +404,15 @@ public class ExamForm implements TemplateComposer {
return action; return action;
} }
private PageAction deleteExamConfigMapping(final PageAction action) {
final EntityKey examConfigMappingKey = action.getSingleSelection();
this.resourceService.getRestService()
.getBuilder(DeleteExamConfigMapping.class)
.withURIVariable(API.PARAM_MODEL_ID, examConfigMappingKey.modelId)
.call();
return action;
}
private Result<Exam> getExistingExam(final EntityKey entityKey, final RestService restService) { private Result<Exam> getExistingExam(final EntityKey entityKey, final RestService restService) {
return restService.getBuilder(GetExam.class) return restService.getBuilder(GetExam.class)
.withURIVariable(API.PARAM_MODEL_ID, entityKey.modelId) .withURIVariable(API.PARAM_MODEL_ID, entityKey.modelId)

View file

@ -0,0 +1,212 @@
/*
* 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 org.apache.commons.lang3.StringUtils;
import org.eclipse.swt.widgets.Composite;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;
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.Exam;
import ch.ethz.seb.sebserver.gbl.model.exam.ExamConfigurationMap;
import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode;
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
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.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.GetExam;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.GetExamConfigMapping;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.NewExamConfigMapping;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.SaveExamConfigMapping;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.GetExamConfigNode;
import ch.ethz.seb.sebserver.gui.widget.WidgetFactory;
@Lazy
@Component
@GuiProfile
public class ExamSebConfigMapForm implements TemplateComposer {
private static final Logger log = LoggerFactory.getLogger(ExamSebConfigMapForm.class);
private static final LocTextKey NEW_CONFIG_MAPPING_TILE_TEXT_KEY =
new LocTextKey("sebserver.exam.configuration.form.title.new");
private static final LocTextKey CONFIG_MAPPING_TILE_TEXT_KEY =
new LocTextKey("sebserver.exam.configuration.form.title");
private static final LocTextKey CONFIG_MAPPING_NAME_TEXT_KEY =
new LocTextKey("sebserver.exam.configuration.form.name");
private static final LocTextKey FORM_DESCRIPTION_TEXT_KEY =
new LocTextKey("sebserver.exam.configuration.form.description");
private static final LocTextKey FORM_STATUS_TEXT_KEY =
new LocTextKey("sebserver.exam.configuration.form.status");
private static final LocTextKey FORM_ENCRYPT_SECRET_TEXT_KEY =
new LocTextKey("sebserver.exam.configuration.form.encryptSecret");
private static final LocTextKey FORM_CONFIRM_ENCRYPT_SECRET_TEXT_KEY =
new LocTextKey("sebserver.exam.configuration.form.encryptSecret.confirm");
private final PageService pageService;
private final ResourceService resourceService;
protected ExamSebConfigMapForm(
final PageService pageService,
final ResourceService resourceService) {
this.pageService = pageService;
this.resourceService = resourceService;
}
@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 Exam exam = (isNew)
? restService
.getBuilder(GetExam.class)
.withURIVariable(API.PARAM_MODEL_ID, parentEntityKey.modelId)
.call()
.get(pageContext::notifyError)
: null;
// get data or create new. Handle error if happen
final ExamConfigurationMap examConfigurationMap = (isNew)
? ExamConfigurationMap.createNew(exam)
: restService
.getBuilder(GetExamConfigMapping.class)
.withURIVariable(API.PARAM_MODEL_ID, entityKey.modelId)
.call()
.get(pageContext::notifyError);
if (examConfigurationMap == null) {
log.error("Failed to get ExamConfigurationMap. "
+ "Error is notified to the User. "
+ "See previous logs for more infomation");
return;
}
// new PageContext with actual EntityKey
final PageContext formContext = pageContext.withEntityKey(examConfigurationMap.getEntityKey());
// the default page layout
final LocTextKey titleKey = (isNew)
? NEW_CONFIG_MAPPING_TILE_TEXT_KEY
: CONFIG_MAPPING_TILE_TEXT_KEY;
final Composite content = widgetFactory.defaultPageLayout(
formContext.getParent(),
titleKey);
final FormHandle<ExamConfigurationMap> formHandle = this.pageService.formBuilder(
formContext.copyOf(content), 4)
.readonly(isReadonly)
.putStaticValueIf(() -> !isNew,
Domain.EXAM_CONFIGURATION_MAP.ATTR_ID,
examConfigurationMap.getModelId())
.putStaticValue(
Domain.EXAM_CONFIGURATION_MAP.ATTR_INSTITUTION_ID,
String.valueOf(examConfigurationMap.getInstitutionId()))
.putStaticValue(
Domain.EXAM_CONFIGURATION_MAP.ATTR_EXAM_ID,
String.valueOf(examConfigurationMap.examId))
.addField(FormBuilder.singleSelection(
Domain.EXAM_CONFIGURATION_MAP.ATTR_CONFIGURATION_NODE_ID,
CONFIG_MAPPING_NAME_TEXT_KEY,
String.valueOf(examConfigurationMap.configurationNodeId),
this.resourceService::examConfigurationSelectionResources)
.withSelectionListener(this::updateFormValuesFromConfigSelection))
.addField(FormBuilder.text(
Domain.CONFIGURATION_NODE.ATTR_DESCRIPTION,
FORM_DESCRIPTION_TEXT_KEY,
examConfigurationMap.configDescription)
.asArea()
.readonly(true))
.addField(FormBuilder.text(
Domain.CONFIGURATION_NODE.ATTR_STATUS,
FORM_STATUS_TEXT_KEY,
this.resourceService.localizedExamConfigStatusName(examConfigurationMap))
.readonly(true))
.addField(FormBuilder.text(
Domain.EXAM_CONFIGURATION_MAP.ATTR_ENCRYPT_SECRET,
FORM_ENCRYPT_SECRET_TEXT_KEY)
.asPasswordField())
.addField(FormBuilder.text(
ExamConfigurationMap.ATTR_CONFIRM_ENCRYPT_SECRET,
FORM_CONFIRM_ENCRYPT_SECRET_TEXT_KEY)
.asPasswordField())
.buildFor((isNew)
? restService.getRestCall(NewExamConfigMapping.class)
: restService.getRestCall(SaveExamConfigMapping.class));
// propagate content actions to action-pane
this.pageService.pageActionBuilder(formContext.clearEntityKeys())
.newAction(ActionDefinition.EXAM_CONFIGURATION_SAVE)
.withEntityKey(parentEntityKey)
.withExec(formHandle::processFormSave)
.ignoreMoveAwayFromEdit()
.publishIf(() -> !isReadonly)
.newAction(ActionDefinition.EXAM_CONFIGURATION_CANCEL_MODIFY)
.withEntityKey(parentEntityKey)
.withExec(action -> this.pageService.onEmptyEntityKeyGoTo(
action,
ActionDefinition.EXAM_VIEW_LIST))
.publishIf(() -> !isReadonly);
}
private void updateFormValuesFromConfigSelection(final Form form) {
final String configId = form.getFieldValue(Domain.EXAM_CONFIGURATION_MAP.ATTR_CONFIGURATION_NODE_ID);
if (StringUtils.isBlank(configId)) {
form.setFieldValue(Domain.CONFIGURATION_NODE.ATTR_DESCRIPTION, null);
form.setFieldValue(Domain.CONFIGURATION_NODE.ATTR_STATUS, null);
} else {
try {
final ConfigurationNode configuration = this.resourceService
.getRestService()
.getBuilder(GetExamConfigNode.class)
.withURIVariable(API.PARAM_MODEL_ID, configId)
.call()
.getOrThrow();
form.setFieldValue(
Domain.CONFIGURATION_NODE.ATTR_DESCRIPTION,
configuration.description);
form.setFieldValue(
Domain.CONFIGURATION_NODE.ATTR_STATUS,
this.resourceService.localizedExamConfigStatusName(configuration));
} catch (final Exception e) {
log.error("Failed to update form values from SEB Configuration selection", e);
form.setFieldValue(Domain.CONFIGURATION_NODE.ATTR_DESCRIPTION, null);
form.setFieldValue(Domain.CONFIGURATION_NODE.ATTR_STATUS, null);
}
}
}
}

View file

@ -43,6 +43,10 @@ public class IndicatorForm implements TemplateComposer {
private static final Logger log = LoggerFactory.getLogger(IndicatorForm.class); private static final Logger log = LoggerFactory.getLogger(IndicatorForm.class);
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 = private static final LocTextKey FORM_THRESHOLDS_TEXT_KEY =
new LocTextKey("sebserver.exam.indicator.form.thresholds"); new LocTextKey("sebserver.exam.indicator.form.thresholds");
private static final LocTextKey FORM_COLOR_TEXT_KEY = private static final LocTextKey FORM_COLOR_TEXT_KEY =
@ -100,10 +104,9 @@ public class IndicatorForm implements TemplateComposer {
final PageContext formContext = pageContext.withEntityKey(indicator.getEntityKey()); final PageContext formContext = pageContext.withEntityKey(indicator.getEntityKey());
// the default page layout // the default page layout
final LocTextKey titleKey = new LocTextKey( final LocTextKey titleKey = (isNew)
(isNew) ? NEW_INDICATOR_TILE_TEXT_KEY
? "sebserver.exam.indicator.form.title.new" : INDICATOR_TILE_TEXT_KEY;
: "sebserver.exam.indicator.form.title");
final Composite content = widgetFactory.defaultPageLayout( final Composite content = widgetFactory.defaultPageLayout(
formContext.getParent(), formContext.getParent(),
titleKey); titleKey);

View file

@ -8,14 +8,11 @@
package ch.ethz.seb.sebserver.gui.content; package ch.ethz.seb.sebserver.gui.content;
import java.util.function.Function;
import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Composite;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Lazy; import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import ch.ethz.seb.sebserver.gbl.Constants;
import ch.ethz.seb.sebserver.gbl.api.EntityType; import ch.ethz.seb.sebserver.gbl.api.EntityType;
import ch.ethz.seb.sebserver.gbl.model.Domain; import ch.ethz.seb.sebserver.gbl.model.Domain;
import ch.ethz.seb.sebserver.gbl.model.Entity; import ch.ethz.seb.sebserver.gbl.model.Entity;
@ -114,7 +111,7 @@ public class SebExamConfigList implements TemplateComposer {
() -> new ColumnDefinition<>( () -> new ColumnDefinition<>(
Domain.LMS_SETUP.ATTR_INSTITUTION_ID, Domain.LMS_SETUP.ATTR_INSTITUTION_ID,
INSTITUTION_TEXT_KEY, INSTITUTION_TEXT_KEY,
examConfigInstitutionNameFunction(this.resourceService), this.resourceService::localizedExamConfigInstitutionName,
this.institutionFilter, this.institutionFilter,
false)) false))
.withColumn(new ColumnDefinition<>( .withColumn(new ColumnDefinition<>(
@ -132,7 +129,7 @@ public class SebExamConfigList implements TemplateComposer {
.withColumn(new ColumnDefinition<>( .withColumn(new ColumnDefinition<>(
Domain.CONFIGURATION_NODE.ATTR_STATUS, Domain.CONFIGURATION_NODE.ATTR_STATUS,
STATUS_TEXT_KEY, STATUS_TEXT_KEY,
this::examConfigStatusName, this.resourceService::localizedExamConfigStatusName,
this.statusFilter, this.statusFilter,
true)) true))
.withDefaultAction(pageActionBuilder .withDefaultAction(pageActionBuilder
@ -141,7 +138,6 @@ public class SebExamConfigList implements TemplateComposer {
.compose(content); .compose(content);
final GrantCheck examConfigGrant = this.currentUser.grantCheck(EntityType.CONFIGURATION_NODE); final GrantCheck examConfigGrant = this.currentUser.grantCheck(EntityType.CONFIGURATION_NODE);
pageActionBuilder pageActionBuilder
.newAction(ActionDefinition.SEB_EXAM_CONFIG_NEW) .newAction(ActionDefinition.SEB_EXAM_CONFIG_NEW)
@ -160,20 +156,4 @@ public class SebExamConfigList implements TemplateComposer {
.publishIf(() -> examConfigGrant.im() && table.hasAnyContent()); .publishIf(() -> examConfigGrant.im() && table.hasAnyContent());
} }
private static Function<ConfigurationNode, String> examConfigInstitutionNameFunction(
final ResourceService resourceService) {
return config -> resourceService.getInstitutionNameFunction()
.apply(String.valueOf(config.institutionId));
}
private String examConfigStatusName(final ConfigurationNode config) {
if (config.status == null) {
return Constants.EMPTY_NOTE;
}
return this.resourceService.getI18nSupport()
.getText(ResourceService.EXAMCONFIG_STATUS_PREFIX + config.status.name());
}
} }

View file

@ -134,7 +134,8 @@ public class SebExamConfigPropForm implements TemplateComposer {
.addField(FormBuilder.text( .addField(FormBuilder.text(
Domain.CONFIGURATION_NODE.ATTR_DESCRIPTION, Domain.CONFIGURATION_NODE.ATTR_DESCRIPTION,
FORM_DESCRIPTION_TEXT_KEY, FORM_DESCRIPTION_TEXT_KEY,
examConfig.description).asArea()) examConfig.description)
.asArea())
.addField(FormBuilder.singleSelection( .addField(FormBuilder.singleSelection(
Domain.CONFIGURATION_NODE.ATTR_STATUS, Domain.CONFIGURATION_NODE.ATTR_STATUS,
FORM_STATUS_TEXT_KEY, FORM_STATUS_TEXT_KEY,

View file

@ -17,7 +17,8 @@ public enum ActionCategory {
LMS_SETUP_LIST(new LocTextKey("sebserver.lmssetup.list.actions"), 1), LMS_SETUP_LIST(new LocTextKey("sebserver.lmssetup.list.actions"), 1),
QUIZ_LIST(new LocTextKey("sebserver.quizdiscovery.list.actions"), 1), QUIZ_LIST(new LocTextKey("sebserver.quizdiscovery.list.actions"), 1),
EXAM_LIST(new LocTextKey("sebserver.exam.list.actions"), 1), EXAM_LIST(new LocTextKey("sebserver.exam.list.actions"), 1),
INDICATOR_LIST(new LocTextKey("sebserver.exam.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), SEB_CLIENT_CONFIG_LIST(new LocTextKey("sebserver.clientconfig.list.actions"), 1),
SEB_EXAM_CONFIG_LIST(new LocTextKey("sebserver.examconfig.list.actions"), 1), SEB_EXAM_CONFIG_LIST(new LocTextKey("sebserver.examconfig.list.actions"), 1),
VARIA(new LocTextKey("sebserver.overall.action.category.varia"), 100), VARIA(new LocTextKey("sebserver.overall.action.category.varia"), 100),

View file

@ -228,10 +228,37 @@ public enum ActionDefinition {
PageStateDefinition.EXAM_VIEW, PageStateDefinition.EXAM_VIEW,
ActionCategory.FORM), ActionCategory.FORM),
EXAM_CONFIGURATION_NEW(
new LocTextKey("sebserver.exam.configuration.action.list.new"),
ImageIcon.NEW,
PageStateDefinition.EXAM_CONFIG_MAP_EDIT,
ActionCategory.EXAM_CONFIG_MAPPING_LIST),
EXAM_CONFIGURATION_MODIFY_FROM_LIST(
new LocTextKey("sebserver.exam.configuration.action.list.modify"),
ImageIcon.EDIT,
PageStateDefinition.EXAM_CONFIG_MAP_EDIT,
ActionCategory.EXAM_CONFIG_MAPPING_LIST),
EXAM_CONFIGURATION_DELETE_FROM_LIST(
new LocTextKey("sebserver.exam.configuration.action.list.delete"),
ImageIcon.DELETE,
PageStateDefinition.EXAM_VIEW,
ActionCategory.EXAM_CONFIG_MAPPING_LIST),
EXAM_CONFIGURATION_SAVE(
new LocTextKey("sebserver.exam.configuration.action.save"),
ImageIcon.SAVE,
PageStateDefinition.EXAM_VIEW,
ActionCategory.FORM),
EXAM_CONFIGURATION_CANCEL_MODIFY(
new LocTextKey("sebserver.overall.action.modify.cancel"),
ImageIcon.CANCEL,
PageStateDefinition.EXAM_VIEW,
ActionCategory.FORM),
EXAM_INDICATOR_NEW( EXAM_INDICATOR_NEW(
new LocTextKey("sebserver.exam.indicator.action.list.new"), new LocTextKey("sebserver.exam.indicator.action.list.new"),
ImageIcon.NEW, ImageIcon.NEW,
PageStateDefinition.INDICATOR_EDIT), PageStateDefinition.INDICATOR_EDIT,
ActionCategory.INDICATOR_LIST),
EXAM_INDICATOR_MODIFY_FROM_LIST( EXAM_INDICATOR_MODIFY_FROM_LIST(
new LocTextKey("sebserver.exam.indicator.action.list.modify"), new LocTextKey("sebserver.exam.indicator.action.list.modify"),
ImageIcon.EDIT, ImageIcon.EDIT,
@ -325,7 +352,7 @@ public enum ActionDefinition {
ActionCategory.FORM), ActionCategory.FORM),
SEB_EXAM_CONFIG_MODIFY( SEB_EXAM_CONFIG_MODIFY(
new LocTextKey("sebserver.examconfig.action.modify"), new LocTextKey("sebserver.examconfig.action.modify"),
ImageIcon.EDIT, ImageIcon.EDIT_SETTINGS,
PageStateDefinition.SEB_EXAM_CONFIG_EDIT, PageStateDefinition.SEB_EXAM_CONFIG_EDIT,
ActionCategory.FORM), ActionCategory.FORM),
SEB_EXAM_CONFIG_CANCEL_MODIFY( SEB_EXAM_CONFIG_CANCEL_MODIFY(
@ -341,7 +368,7 @@ public enum ActionDefinition {
SEB_EXAM_CONFIG_MODIFY_FROM_LIST( SEB_EXAM_CONFIG_MODIFY_FROM_LIST(
new LocTextKey("sebserver.examconfig.action.list.modify"), new LocTextKey("sebserver.examconfig.action.list.modify"),
ImageIcon.EDIT, ImageIcon.EDIT_SETTINGS,
PageStateDefinition.SEB_EXAM_CONFIG_EDIT, PageStateDefinition.SEB_EXAM_CONFIG_EDIT,
ActionCategory.SEB_EXAM_CONFIG_LIST), ActionCategory.SEB_EXAM_CONFIG_LIST),
@ -352,7 +379,7 @@ public enum ActionDefinition {
ActionCategory.SEB_EXAM_CONFIG_LIST), ActionCategory.SEB_EXAM_CONFIG_LIST),
SEB_EXAM_CONFIG_UNDO( SEB_EXAM_CONFIG_UNDO(
new LocTextKey("sebserver.examconfig.action.undo"), new LocTextKey("sebserver.examconfig.action.undo"),
ImageIcon.SAVE, ImageIcon.UNDO,
PageStateDefinition.SEB_EXAM_CONFIG_EDIT, PageStateDefinition.SEB_EXAM_CONFIG_EDIT,
ActionCategory.SEB_EXAM_CONFIG_LIST), ActionCategory.SEB_EXAM_CONFIG_LIST),

View file

@ -119,9 +119,9 @@ public class ActionPane implements TemplateComposer {
} }
} }
final Label labelSeparator = this.widgetFactory.labelSeparator(composite); // final Label labelSeparator = this.widgetFactory.labelSeparator(composite);
final GridData separatorLayout = new GridData(SWT.FILL, SWT.TOP, true, false); // final GridData separatorLayout = new GridData(SWT.FILL, SWT.TOP, true, false);
labelSeparator.setLayoutData(separatorLayout); // labelSeparator.setLayoutData(separatorLayout);
// title // title
if (category.title != null) { if (category.title != null) {
@ -140,7 +140,7 @@ public class ActionPane implements TemplateComposer {
composite, composite,
SWT.SINGLE | SWT.FULL_SELECTION); SWT.SINGLE | SWT.FULL_SELECTION);
actions.setData(RWT.CUSTOM_VARIANT, "actions"); actions.setData(RWT.CUSTOM_VARIANT, "actions");
final GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, true); final GridData gridData = new GridData(SWT.FILL, SWT.TOP, true, false);
actions.setLayoutData(gridData); actions.setLayoutData(gridData);
final Template template = new Template(); final Template template = new Template();
final ImageCell imageCell = new ImageCell(template); final ImageCell imageCell = new ImageCell(template);

View file

@ -10,6 +10,7 @@ package ch.ethz.seb.sebserver.gui.content.activity;
import ch.ethz.seb.sebserver.gui.content.ExamForm; import ch.ethz.seb.sebserver.gui.content.ExamForm;
import ch.ethz.seb.sebserver.gui.content.ExamList; import ch.ethz.seb.sebserver.gui.content.ExamList;
import ch.ethz.seb.sebserver.gui.content.ExamSebConfigMapForm;
import ch.ethz.seb.sebserver.gui.content.IndicatorForm; import ch.ethz.seb.sebserver.gui.content.IndicatorForm;
import ch.ethz.seb.sebserver.gui.content.InstitutionForm; import ch.ethz.seb.sebserver.gui.content.InstitutionForm;
import ch.ethz.seb.sebserver.gui.content.InstitutionList; import ch.ethz.seb.sebserver.gui.content.InstitutionList;
@ -49,6 +50,7 @@ public enum PageStateDefinition implements PageState {
EXAM_LIST(Type.LIST_VIEW, ExamList.class, ActivityDefinition.EXAM), EXAM_LIST(Type.LIST_VIEW, ExamList.class, ActivityDefinition.EXAM),
EXAM_VIEW(Type.FORM_VIEW, ExamForm.class, ActivityDefinition.EXAM), EXAM_VIEW(Type.FORM_VIEW, ExamForm.class, ActivityDefinition.EXAM),
EXAM_EDIT(Type.FORM_EDIT, ExamForm.class, ActivityDefinition.EXAM), EXAM_EDIT(Type.FORM_EDIT, ExamForm.class, ActivityDefinition.EXAM),
EXAM_CONFIG_MAP_EDIT(Type.FORM_EDIT, ExamSebConfigMapForm.class, ActivityDefinition.EXAM),
INDICATOR_EDIT(Type.FORM_EDIT, IndicatorForm.class, ActivityDefinition.EXAM), INDICATOR_EDIT(Type.FORM_EDIT, IndicatorForm.class, ActivityDefinition.EXAM),
SEB_CLIENT_CONFIG_LIST(Type.LIST_VIEW, SebClientConfigList.class, ActivityDefinition.SEB_CLIENT_CONFIG), SEB_CLIENT_CONFIG_LIST(Type.LIST_VIEW, SebClientConfigList.class, ActivityDefinition.SEB_CLIENT_CONFIG),

View file

@ -143,6 +143,24 @@ public final class Form implements FormBinding {
this.formFields.add(name, createAccessor(label, imageUpload)); this.formFields.add(name, createAccessor(label, imageUpload));
} }
public String getFieldValue(final String attributeName) {
final FormFieldAccessor fieldAccessor = this.formFields.getFirst(attributeName);
if (fieldAccessor == null) {
return null;
}
return fieldAccessor.getStringValue();
}
public void setFieldValue(final String attributeName, final String attributeValue) {
final FormFieldAccessor fieldAccessor = this.formFields.getFirst(attributeName);
if (fieldAccessor == null) {
return;
}
fieldAccessor.setStringValue(attributeValue);
}
public void allVisible() { public void allVisible() {
process( process(
name -> true, name -> true,
@ -208,11 +226,13 @@ public final class Form implements FormBinding {
private FormFieldAccessor createAccessor(final Label label, final Label field) { private FormFieldAccessor createAccessor(final Label label, final Label field) {
return new FormFieldAccessor(label, field) { return new FormFieldAccessor(label, field) {
@Override public String getStringValue() { return null; } @Override public String getStringValue() { return null; }
@Override public void setStringValue(final String value) { field.setText( (value == null) ? StringUtils.EMPTY : value); }
}; };
} }
private FormFieldAccessor createAccessor(final Label label, final Text text) { private FormFieldAccessor createAccessor(final Label label, final Text text) {
return new FormFieldAccessor(label, text) { return new FormFieldAccessor(label, text) {
@Override public String getStringValue() { return text.getText(); } @Override public String getStringValue() { return text.getText(); }
@Override public void setStringValue(final String value) { text.setText( (value == null) ? StringUtils.EMPTY : value); }
}; };
} }
private FormFieldAccessor createAccessor(final Label label, final Selection selection) { private FormFieldAccessor createAccessor(final Label label, final Selection selection) {
@ -234,6 +254,7 @@ public final class Form implements FormBinding {
jsonValueAdapter, jsonValueAdapter,
selection.type() != Type.SINGLE) { selection.type() != Type.SINGLE) {
@Override public String getStringValue() { return selection.getSelectionValue(); } @Override public String getStringValue() { return selection.getSelectionValue(); }
@Override public void setStringValue(final String value) { selection.select(value); }
}; };
} }
private FormFieldAccessor createAccessor(final Label label, final ThresholdList thresholdList) { private FormFieldAccessor createAccessor(final Label label, final ThresholdList thresholdList) {
@ -356,6 +377,10 @@ public final class Form implements FormBinding {
public abstract String getStringValue(); public abstract String getStringValue();
public void setStringValue(final String value) {
throw new UnsupportedOperationException();
}
public void setVisible(final boolean visible) { public void setVisible(final boolean visible) {
this.label.setVisible(visible); this.label.setVisible(visible);
this.control.setVisible(visible); this.control.setVisible(visible);

View file

@ -256,7 +256,7 @@ public class FormBuilder {
Label valueLabel(final Composite parent, final String value, final int hspan) { Label valueLabel(final Composite parent, final String value, final int hspan) {
final Label label = new Label(parent, SWT.NONE); final Label label = new Label(parent, SWT.NONE);
label.setText((StringUtils.isNoneBlank(value)) ? value : Constants.EMPTY_NOTE); label.setText((StringUtils.isNoneBlank(value)) ? value : Constants.EMPTY_NOTE);
final GridData gridData = new GridData(SWT.LEFT, SWT.CENTER, true, false, hspan, 1); final GridData gridData = new GridData(SWT.FILL, SWT.CENTER, true, false, hspan, 1);
gridData.verticalIndent = 4; gridData.verticalIndent = 4;
label.setLayoutData(gridData); label.setLayoutData(gridData);
return label; return label;

View file

@ -24,17 +24,23 @@ import org.springframework.stereotype.Service;
import ch.ethz.seb.sebserver.gbl.Constants; import ch.ethz.seb.sebserver.gbl.Constants;
import ch.ethz.seb.sebserver.gbl.model.Entity; import ch.ethz.seb.sebserver.gbl.model.Entity;
import ch.ethz.seb.sebserver.gbl.model.EntityName;
import ch.ethz.seb.sebserver.gbl.model.exam.ExamConfigurationMap;
import ch.ethz.seb.sebserver.gbl.model.exam.Exam.ExamType; import ch.ethz.seb.sebserver.gbl.model.exam.Exam.ExamType;
import ch.ethz.seb.sebserver.gbl.model.exam.Indicator.IndicatorType; import ch.ethz.seb.sebserver.gbl.model.exam.Indicator.IndicatorType;
import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetup.LmsType; import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetup.LmsType;
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.ConfigurationStatus;
import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode.ConfigurationType;
import ch.ethz.seb.sebserver.gbl.model.user.UserInfo; import ch.ethz.seb.sebserver.gbl.model.user.UserInfo;
import ch.ethz.seb.sebserver.gbl.model.user.UserRole; import ch.ethz.seb.sebserver.gbl.model.user.UserRole;
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile; import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
import ch.ethz.seb.sebserver.gbl.util.Result;
import ch.ethz.seb.sebserver.gbl.util.Tuple; import ch.ethz.seb.sebserver.gbl.util.Tuple;
import ch.ethz.seb.sebserver.gui.service.i18n.I18nSupport; 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.i18n.LocTextKey;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestService; import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestService;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.GetExamConfigMappingNames;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.institution.GetInstitutionNames; import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.institution.GetInstitutionNames;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.lmssetup.GetLmsSetupNames; import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.lmssetup.GetLmsSetupNames;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.useraccount.GetUserAccountNames; import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.useraccount.GetUserAccountNames;
@ -105,6 +111,28 @@ public class ResourceService {
.collect(Collectors.toList()); .collect(Collectors.toList());
} }
public List<Tuple<String>> examConfigurationSelectionResources() {
return getExamConfigurationSelection()
.getOr(Collections.emptyList())
.stream()
.map(entityName -> new Tuple<>(entityName.modelId, entityName.name))
.collect(Collectors.toList());
}
// public Function<String, String> getExamConfigurationNameFunction() {
// final Map<String, String> idNameMap = getExamConfigurationSelection()
// .getOr(Collections.emptyList())
// .stream()
// .collect(Collectors.toMap(e -> e.modelId, e -> e.name));
//
// return id -> {
// if (!idNameMap.containsKey(id)) {
// return Constants.EMPTY_NOTE;
// }
// return idNameMap.get(id);
// };
// }
public List<Tuple<String>> userRoleResources() { public List<Tuple<String>> userRoleResources() {
return UserRole.publicRolesForUser(this.currentUser.get()) return UserRole.publicRolesForUser(this.currentUser.get())
.stream() .stream()
@ -125,7 +153,6 @@ public class ResourceService {
} }
public Function<String, String> getInstitutionNameFunction() { public Function<String, String> getInstitutionNameFunction() {
final Map<String, String> idNameMap = this.restService.getBuilder(GetInstitutionNames.class) final Map<String, String> idNameMap = this.restService.getBuilder(GetInstitutionNames.class)
.withQueryParam(Entity.FILTER_ATTR_ACTIVE, Constants.TRUE_STRING) .withQueryParam(Entity.FILTER_ATTR_ACTIVE, Constants.TRUE_STRING)
.call() .call()
@ -248,4 +275,41 @@ public class ResourceService {
: this.i18nSupport.getText(INACTIVE_TEXT_KEY); : this.i18nSupport.getText(INACTIVE_TEXT_KEY);
} }
public String localizedExamConfigInstitutionName(final ConfigurationNode config) {
return getInstitutionNameFunction()
.apply(String.valueOf(config.institutionId));
}
public String localizedExamConfigStatusName(final ConfigurationNode config) {
if (config.status == null) {
return Constants.EMPTY_NOTE;
}
return this.i18nSupport
.getText(ResourceService.EXAMCONFIG_STATUS_PREFIX + config.status.name());
}
public String localizedExamConfigStatusName(final ExamConfigurationMap config) {
if (config.configStatus == null) {
return Constants.EMPTY_NOTE;
}
return this.i18nSupport
.getText(ResourceService.EXAMCONFIG_STATUS_PREFIX + config.configStatus.name());
}
private Result<List<EntityName>> getExamConfigurationSelection() {
return this.restService.getBuilder(GetExamConfigMappingNames.class)
.withQueryParam(
Entity.FILTER_ATTR_INSTITUTION,
String.valueOf(this.currentUser.get().institutionId))
.withQueryParam(
ConfigurationNode.FILTER_ATTR_TYPE,
ConfigurationType.EXAM_CONFIG.name())
.withQueryParam(
ConfigurationNode.FILTER_ATTR_STATUS,
ConfigurationStatus.READY_TO_USE.name())
.call();
}
} }

View file

@ -298,8 +298,8 @@ public class TableFieldBuilder implements InputFieldBuilder {
item.setImage( item.setImage(
cellIndex, cellIndex,
(BooleanUtils.toBoolean((tableValue != null) ? tableValue.value : null)) (BooleanUtils.toBoolean((tableValue != null) ? tableValue.value : null))
? ImageIcon.ACTIVE.getImage(this.control.getDisplay()) ? ImageIcon.YES.getImage(this.control.getDisplay())
: ImageIcon.INACTIVE.getImage(this.control.getDisplay())); : ImageIcon.NO.getImage(this.control.getDisplay()));
} else { } else {
item.setText( item.setText(
cellIndex, cellIndex,

View file

@ -0,0 +1,39 @@
/*
* 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.service.remote.webservice.api.exam;
import org.springframework.context.annotation.Lazy;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import com.fasterxml.jackson.core.type.TypeReference;
import ch.ethz.seb.sebserver.gbl.api.API;
import ch.ethz.seb.sebserver.gbl.api.EntityType;
import ch.ethz.seb.sebserver.gbl.model.EntityProcessingReport;
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCall;
@Lazy
@Component
@GuiProfile
public class DeleteExamConfigMapping extends RestCall<EntityProcessingReport> {
protected DeleteExamConfigMapping() {
super(new TypeKey<>(
CallType.DELETE,
EntityType.EXAM_CONFIGURATION_MAP,
new TypeReference<EntityProcessingReport>() {
}),
HttpMethod.DELETE,
MediaType.APPLICATION_JSON_UTF8,
API.EXAM_CONFIGURATION_MAP_ENDPOINT + API.MODEL_ID_VAR_PATH_SEGMENT);
}
}

View file

@ -0,0 +1,40 @@
/*
* 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.service.remote.webservice.api.exam;
import org.springframework.context.annotation.Lazy;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import com.fasterxml.jackson.core.type.TypeReference;
import ch.ethz.seb.sebserver.gbl.api.API;
import ch.ethz.seb.sebserver.gbl.api.EntityType;
import ch.ethz.seb.sebserver.gbl.model.exam.ExamConfigurationMap;
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCall;
@Lazy
@Component
@GuiProfile
public class GetExamConfigMapping extends RestCall<ExamConfigurationMap> {
protected GetExamConfigMapping() {
super(new TypeKey<>(
CallType.GET_SINGLE,
EntityType.EXAM_CONFIGURATION_MAP,
new TypeReference<ExamConfigurationMap>() {
}),
HttpMethod.GET,
MediaType.APPLICATION_FORM_URLENCODED,
API.EXAM_CONFIGURATION_MAP_ENDPOINT + API.MODEL_ID_VAR_PATH_SEGMENT);
}
}

View file

@ -0,0 +1,42 @@
/*
* 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.service.remote.webservice.api.exam;
import java.util.List;
import org.springframework.context.annotation.Lazy;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import com.fasterxml.jackson.core.type.TypeReference;
import ch.ethz.seb.sebserver.gbl.api.API;
import ch.ethz.seb.sebserver.gbl.api.EntityType;
import ch.ethz.seb.sebserver.gbl.model.EntityName;
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCall;
@Lazy
@Component
@GuiProfile
public class GetExamConfigMappingNames extends RestCall<List<EntityName>> {
protected GetExamConfigMappingNames() {
super(new TypeKey<>(
CallType.GET_NAMES,
EntityType.CONFIGURATION_NODE,
new TypeReference<List<EntityName>>() {
}),
HttpMethod.GET,
MediaType.APPLICATION_FORM_URLENCODED,
API.CONFIGURATION_NODE_ENDPOINT + API.NAMES_PATH_SEGMENT);
}
}

View file

@ -0,0 +1,41 @@
/*
* 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.service.remote.webservice.api.exam;
import org.springframework.context.annotation.Lazy;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import com.fasterxml.jackson.core.type.TypeReference;
import ch.ethz.seb.sebserver.gbl.api.API;
import ch.ethz.seb.sebserver.gbl.api.EntityType;
import ch.ethz.seb.sebserver.gbl.model.Page;
import ch.ethz.seb.sebserver.gbl.model.exam.ExamConfigurationMap;
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCall;
@Lazy
@Component
@GuiProfile
public class GetExamConfigMappingsPage extends RestCall<Page<ExamConfigurationMap>> {
protected GetExamConfigMappingsPage() {
super(new TypeKey<>(
CallType.GET_PAGE,
EntityType.EXAM_CONFIGURATION_MAP,
new TypeReference<Page<ExamConfigurationMap>>() {
}),
HttpMethod.GET,
MediaType.APPLICATION_FORM_URLENCODED,
API.EXAM_CONFIGURATION_MAP_ENDPOINT);
}
}

View file

@ -0,0 +1,40 @@
/*
* 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.service.remote.webservice.api.exam;
import org.springframework.context.annotation.Lazy;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import com.fasterxml.jackson.core.type.TypeReference;
import ch.ethz.seb.sebserver.gbl.api.API;
import ch.ethz.seb.sebserver.gbl.api.EntityType;
import ch.ethz.seb.sebserver.gbl.model.exam.ExamConfigurationMap;
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCall;
@Lazy
@Component
@GuiProfile
public class NewExamConfigMapping extends RestCall<ExamConfigurationMap> {
protected NewExamConfigMapping() {
super(new TypeKey<>(
CallType.NEW,
EntityType.EXAM_CONFIGURATION_MAP,
new TypeReference<ExamConfigurationMap>() {
}),
HttpMethod.POST,
MediaType.APPLICATION_FORM_URLENCODED,
API.EXAM_CONFIGURATION_MAP_ENDPOINT);
}
}

View file

@ -0,0 +1,40 @@
/*
* 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.service.remote.webservice.api.exam;
import org.springframework.context.annotation.Lazy;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import com.fasterxml.jackson.core.type.TypeReference;
import ch.ethz.seb.sebserver.gbl.api.API;
import ch.ethz.seb.sebserver.gbl.api.EntityType;
import ch.ethz.seb.sebserver.gbl.model.exam.ExamConfigurationMap;
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCall;
@Lazy
@Component
@GuiProfile
public class SaveExamConfigMapping extends RestCall<ExamConfigurationMap> {
protected SaveExamConfigMapping() {
super(new TypeKey<>(
CallType.SAVE,
EntityType.EXAM_CONFIGURATION_MAP,
new TypeReference<ExamConfigurationMap>() {
}),
HttpMethod.PUT,
MediaType.APPLICATION_JSON_UTF8,
API.EXAM_CONFIGURATION_MAP_ENDPOINT);
}
}

View file

@ -101,7 +101,6 @@ public class EntityTable<ROW extends Entity> {
layout.verticalSpacing = 0; layout.verticalSpacing = 0;
this.composite.setLayout(layout); this.composite.setLayout(layout);
GridData gridData = new GridData(SWT.FILL, SWT.TOP, true, false); GridData gridData = new GridData(SWT.FILL, SWT.TOP, true, false);
// gridData.heightHint = (pageSize + 2) * 40;
this.composite.setLayoutData(gridData); this.composite.setLayoutData(gridData);
// TODO just for debugging, remove when tested // TODO just for debugging, remove when tested
@ -223,6 +222,19 @@ public class EntityTable<ROW extends Entity> {
return getRowDataId(selection[0]); return getRowDataId(selection[0]);
} }
public ROW getFirstRowData() {
if (!this.hasAnyContent()) {
return null;
}
final TableItem item = this.table.getItem(0);
if (item == null) {
return null;
}
return getRowData(item);
}
public ROW getSelectedROWData() { public ROW getSelectedROWData() {
final TableItem[] selection = this.table.getSelection(); final TableItem[] selection = this.table.getSelection();
if (selection == null || selection.length == 0) { if (selection == null || selection.length == 0) {
@ -296,9 +308,6 @@ public class EntityTable<ROW extends Entity> {
// TODO error handling // TODO error handling
}); });
final GridData gridData = (GridData) this.composite.getLayoutData();
gridData.heightHint = (this.table.getItemCount() + 2) * 50;
this.composite.layout(true, true); this.composite.layout(true, true);
} }
@ -405,9 +414,9 @@ public class EntityTable<ROW extends Entity> {
private static void addBooleanCell(final TableItem item, final int index, final Object value) { private static void addBooleanCell(final TableItem item, final int index, final Object value) {
if ((Boolean) value) { if ((Boolean) value) {
item.setImage(index, ImageIcon.ACTIVE.getImage(item.getDisplay())); item.setImage(index, ImageIcon.YES.getImage(item.getDisplay()));
} else { } else {
item.setImage(index, ImageIcon.INACTIVE.getImage(item.getDisplay())); item.setImage(index, ImageIcon.NO.getImage(item.getDisplay()));
} }
} }

View file

@ -0,0 +1,17 @@
/*
* 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.widget;
public class PopupListSelection {
public PopupListSelection() {
// TODO Auto-generated constructor stub
}
}

View file

@ -68,6 +68,7 @@ public class WidgetFactory {
ADD_BOX("add_box.png"), ADD_BOX("add_box.png"),
REMOVE_BOX("remove_box.png"), REMOVE_BOX("remove_box.png"),
EDIT("edit.png"), EDIT("edit.png"),
EDIT_SETTINGS("settings.png"),
TEST("test.png"), TEST("test.png"),
IMPORT("import.png"), IMPORT("import.png"),
CANCEL("cancel.png"), CANCEL("cancel.png"),
@ -75,10 +76,13 @@ public class WidgetFactory {
SHOW("show.png"), SHOW("show.png"),
ACTIVE("active.png"), ACTIVE("active.png"),
INACTIVE("inactive.png"), INACTIVE("inactive.png"),
YES("yes.png"),
NO("no.png"),
SAVE("save.png"), SAVE("save.png"),
NEW("new.png"), NEW("new.png"),
DELETE("delete.png"), DELETE("delete.png"),
SEARCH("lens.png"), SEARCH("lens.png"),
UNDO("undo.png"),
COLOR("color.png"); COLOR("color.png");
private String fileName; private String fileName;

View file

@ -8,7 +8,7 @@
package ch.ethz.seb.sebserver.webservice.servicelayer.dao; package ch.ethz.seb.sebserver.webservice.servicelayer.dao;
import ch.ethz.seb.sebserver.gbl.model.sebconfig.ExamConfigurationMap; import ch.ethz.seb.sebserver.gbl.model.exam.ExamConfigurationMap;
import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.BulkActionSupportDAO; import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.BulkActionSupportDAO;
public interface ExamConfigurationMapDAO extends public interface ExamConfigurationMapDAO extends

View file

@ -15,6 +15,7 @@ import org.springframework.util.MultiValueMap;
import ch.ethz.seb.sebserver.gbl.api.POSTMapper; import ch.ethz.seb.sebserver.gbl.api.POSTMapper;
import ch.ethz.seb.sebserver.gbl.model.Entity; import ch.ethz.seb.sebserver.gbl.model.Entity;
import ch.ethz.seb.sebserver.gbl.model.exam.Exam; import ch.ethz.seb.sebserver.gbl.model.exam.Exam;
import ch.ethz.seb.sebserver.gbl.model.exam.ExamConfigurationMap;
import ch.ethz.seb.sebserver.gbl.model.exam.Indicator; import ch.ethz.seb.sebserver.gbl.model.exam.Indicator;
import ch.ethz.seb.sebserver.gbl.model.exam.QuizData; import ch.ethz.seb.sebserver.gbl.model.exam.QuizData;
import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetup; import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetup;
@ -22,7 +23,6 @@ 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.ConfigurationAttribute;
import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode; import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode;
import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationValue; import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationValue;
import ch.ethz.seb.sebserver.gbl.model.sebconfig.ExamConfigurationMap;
import ch.ethz.seb.sebserver.gbl.model.sebconfig.Orientation; import ch.ethz.seb.sebserver.gbl.model.sebconfig.Orientation;
import ch.ethz.seb.sebserver.gbl.model.user.UserInfo; import ch.ethz.seb.sebserver.gbl.model.user.UserInfo;
import ch.ethz.seb.sebserver.gbl.util.Utils; import ch.ethz.seb.sebserver.gbl.util.Utils;
@ -100,7 +100,7 @@ public class FilterMap extends POSTMapper {
} }
public Long getIndicatorExamId() { public Long getIndicatorExamId() {
return getLong(Indicator.FILTER_ATTR_EXAM); return getLong(Indicator.FILTER_ATTR_EXAM_ID);
} }
public String getIndicatorName() { public String getIndicatorName() {

View file

@ -213,10 +213,10 @@ public class ConfigurationNodeDAOImpl implements ConfigurationNodeDAO {
data.id, data.id,
null, null,
null, null,
null,
data.name, data.name,
data.description, data.description,
null, null,
null,
(data.status != null) ? data.status.name() : ConfigurationStatus.CONSTRUCTION.name()); (data.status != null) ? data.status.name() : ConfigurationStatus.CONSTRUCTION.name());
this.configurationNodeRecordMapper.updateByPrimaryKeySelective(newRecord); this.configurationNodeRecordMapper.updateByPrimaryKeySelective(newRecord);

View file

@ -19,6 +19,7 @@ import java.util.function.Function;
import java.util.function.Predicate; import java.util.function.Predicate;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import org.apache.commons.lang3.StringUtils;
import org.mybatis.dynamic.sql.SqlBuilder; import org.mybatis.dynamic.sql.SqlBuilder;
import org.springframework.context.annotation.Lazy; import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@ -29,7 +30,8 @@ import ch.ethz.seb.sebserver.gbl.api.APIMessage.APIMessageException;
import ch.ethz.seb.sebserver.gbl.api.APIMessage.ErrorMessage; import ch.ethz.seb.sebserver.gbl.api.APIMessage.ErrorMessage;
import ch.ethz.seb.sebserver.gbl.api.EntityType; import ch.ethz.seb.sebserver.gbl.api.EntityType;
import ch.ethz.seb.sebserver.gbl.model.EntityKey; import ch.ethz.seb.sebserver.gbl.model.EntityKey;
import ch.ethz.seb.sebserver.gbl.model.sebconfig.ExamConfigurationMap; import ch.ethz.seb.sebserver.gbl.model.exam.ExamConfigurationMap;
import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode.ConfigurationStatus;
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile; import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
import ch.ethz.seb.sebserver.gbl.util.Result; import ch.ethz.seb.sebserver.gbl.util.Result;
import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.ConfigurationNodeRecordMapper; import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.ConfigurationNodeRecordMapper;
@ -79,7 +81,7 @@ public class ExamConfigurationMapDAOImpl implements ExamConfigurationMapDAO {
@Transactional(readOnly = true) @Transactional(readOnly = true)
public Result<ExamConfigurationMap> byPK(final Long id) { public Result<ExamConfigurationMap> byPK(final Long id) {
return recordById(id) return recordById(id)
.flatMap(ExamConfigurationMapDAOImpl::toDomainModel); .flatMap(this::toDomainModel);
} }
@Override @Override
@ -91,7 +93,7 @@ public class ExamConfigurationMapDAOImpl implements ExamConfigurationMapDAO {
.build() .build()
.execute() .execute()
.stream() .stream()
.map(ExamConfigurationMapDAOImpl::toDomainModel) .map(this::toDomainModel)
.flatMap(DAOLoggingSupport::logAndSkipOnError) .flatMap(DAOLoggingSupport::logAndSkipOnError)
.collect(Collectors.toList()); .collect(Collectors.toList());
}); });
@ -117,7 +119,7 @@ public class ExamConfigurationMapDAOImpl implements ExamConfigurationMapDAO {
.build() .build()
.execute() .execute()
.stream() .stream()
.map(ExamConfigurationMapDAOImpl::toDomainModel) .map(this::toDomainModel)
.flatMap(DAOLoggingSupport::logAndSkipOnError) .flatMap(DAOLoggingSupport::logAndSkipOnError)
.filter(predicate) .filter(predicate)
.collect(Collectors.toList())); .collect(Collectors.toList()));
@ -139,7 +141,7 @@ public class ExamConfigurationMapDAOImpl implements ExamConfigurationMapDAO {
this.examConfigurationMapRecordMapper.insert(newRecord); this.examConfigurationMapRecordMapper.insert(newRecord);
return newRecord; return newRecord;
}) })
.flatMap(ExamConfigurationMapDAOImpl::toDomainModel) .flatMap(this::toDomainModel)
.onError(TransactionHandler::rollback); .onError(TransactionHandler::rollback);
} }
@ -159,7 +161,7 @@ public class ExamConfigurationMapDAOImpl implements ExamConfigurationMapDAO {
this.examConfigurationMapRecordMapper.updateByPrimaryKeySelective(newRecord); this.examConfigurationMapRecordMapper.updateByPrimaryKeySelective(newRecord);
return this.examConfigurationMapRecordMapper.selectByPrimaryKey(data.id); return this.examConfigurationMapRecordMapper.selectByPrimaryKey(data.id);
}) })
.flatMap(ExamConfigurationMapDAOImpl::toDomainModel) .flatMap(this::toDomainModel)
.onError(TransactionHandler::rollback); .onError(TransactionHandler::rollback);
} }
@ -223,15 +225,25 @@ public class ExamConfigurationMapDAOImpl implements ExamConfigurationMapDAO {
}); });
} }
private static Result<ExamConfigurationMap> toDomainModel(final ExamConfigurationMapRecord record) { private Result<ExamConfigurationMap> toDomainModel(final ExamConfigurationMapRecord record) {
return Result.tryCatch(() -> new ExamConfigurationMap( return Result.tryCatch(() -> {
record.getId(),
record.getInstitutionId(), final ConfigurationNodeRecord selectByPrimaryKey = this.configurationNodeRecordMapper
record.getExamId(), .selectByPrimaryKey(record.getConfigurationNodeId());
record.getConfigurationNodeId(), final String status = selectByPrimaryKey.getStatus();
record.getUserNames(),
null, return new ExamConfigurationMap(
null)); record.getId(),
record.getInstitutionId(),
record.getExamId(),
record.getConfigurationNodeId(),
record.getUserNames(),
null,
null,
selectByPrimaryKey.getName(),
selectByPrimaryKey.getDescription(),
(StringUtils.isNotBlank(status)) ? ConfigurationStatus.valueOf(status) : null);
});
} }
private Result<ExamConfigurationMap> checkMappingIntegrity(final ExamConfigurationMap data) { private Result<ExamConfigurationMap> checkMappingIntegrity(final ExamConfigurationMap data) {

View file

@ -30,9 +30,9 @@ import org.springframework.web.bind.annotation.RequestParam;
import ch.ethz.seb.sebserver.gbl.Constants; import ch.ethz.seb.sebserver.gbl.Constants;
import ch.ethz.seb.sebserver.gbl.api.API; import ch.ethz.seb.sebserver.gbl.api.API;
import ch.ethz.seb.sebserver.gbl.api.API.BulkActionType; import ch.ethz.seb.sebserver.gbl.api.API.BulkActionType;
import ch.ethz.seb.sebserver.gbl.api.authorization.PrivilegeType;
import ch.ethz.seb.sebserver.gbl.api.EntityType; import ch.ethz.seb.sebserver.gbl.api.EntityType;
import ch.ethz.seb.sebserver.gbl.api.POSTMapper; import ch.ethz.seb.sebserver.gbl.api.POSTMapper;
import ch.ethz.seb.sebserver.gbl.api.authorization.PrivilegeType;
import ch.ethz.seb.sebserver.gbl.model.Entity; import ch.ethz.seb.sebserver.gbl.model.Entity;
import ch.ethz.seb.sebserver.gbl.model.EntityKey; import ch.ethz.seb.sebserver.gbl.model.EntityKey;
import ch.ethz.seb.sebserver.gbl.model.EntityName; import ch.ethz.seb.sebserver.gbl.model.EntityName;

View file

@ -0,0 +1,121 @@
/*
* 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.webservice.weblayer.api;
import org.mybatis.dynamic.sql.SqlTable;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import ch.ethz.seb.sebserver.gbl.api.API;
import ch.ethz.seb.sebserver.gbl.api.APIMessage;
import ch.ethz.seb.sebserver.gbl.api.APIMessage.APIMessageException;
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.GrantEntity;
import ch.ethz.seb.sebserver.gbl.model.exam.ExamConfigurationMap;
import ch.ethz.seb.sebserver.gbl.model.user.PasswordChange;
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.ExamConfigurationMapRecordDynamicSqlSupport;
import ch.ethz.seb.sebserver.webservice.servicelayer.PaginationService;
import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.AuthorizationService;
import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.BulkActionService;
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.EntityDAO;
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ExamDAO;
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.UserActivityLogDAO;
import ch.ethz.seb.sebserver.webservice.servicelayer.validation.BeanValidationService;
@WebServiceProfile
@RestController
@RequestMapping("/${sebserver.webservice.api.admin.endpoint}" + API.EXAM_CONFIGURATION_MAP_ENDPOINT)
public class ExamConfigurationMappingController extends EntityController<ExamConfigurationMap, ExamConfigurationMap> {
private final ExamDAO examDao;
protected ExamConfigurationMappingController(
final AuthorizationService authorization,
final BulkActionService bulkActionService,
final EntityDAO<ExamConfigurationMap, ExamConfigurationMap> entityDAO,
final UserActivityLogDAO userActivityLogDAO,
final PaginationService paginationService,
final BeanValidationService beanValidationService,
final ExamDAO examDao) {
super(
authorization,
bulkActionService,
entityDAO,
userActivityLogDAO,
paginationService,
beanValidationService);
this.examDao = examDao;
}
@Override
protected ExamConfigurationMap createNew(final POSTMapper postParams) {
final Long institutionId = postParams.getLong(API.PARAM_INSTITUTION_ID);
return new ExamConfigurationMap(institutionId, postParams);
}
@Override
protected SqlTable getSQLTableOfEntity() {
return ExamConfigurationMapRecordDynamicSqlSupport.examConfigurationMapRecord;
}
@Override
protected EntityType getGrantEntityType() {
return EntityType.EXAM;
}
@Override
protected GrantEntity toGrantEntity(final ExamConfigurationMap entity) {
if (entity == null) {
return null;
}
return this.examDao
.byPK(entity.examId)
.getOrThrow();
}
@Override
protected Result<ExamConfigurationMap> checkCreateAccess(final ExamConfigurationMap entity) {
final GrantEntity grantEntity = toGrantEntity(entity);
this.authorization.checkWrite(grantEntity);
return Result.of(entity);
}
@Override
protected Result<ExamConfigurationMap> validForCreate(final ExamConfigurationMap entity) {
return super.validForCreate(entity)
.map(this::checkPasswordMatch);
}
@Override
protected Result<ExamConfigurationMap> validForSave(final ExamConfigurationMap entity) {
return super.validForSave(entity)
.map(this::checkPasswordMatch);
}
private ExamConfigurationMap checkPasswordMatch(final ExamConfigurationMap entity) {
if (entity.hasEncryptionSecret() && !entity.encryptSecret.equals(entity.confirmEncryptSecret)) {
throw new APIMessageException(APIMessage.fieldValidationError(
new FieldError(
Domain.EXAM_CONFIGURATION_MAP.TYPE_NAME,
PasswordChange.ATTR_NAME_PASSWORD,
"examConfigMapping:confirm_encrypt_secret:password.mismatch")));
}
return entity;
}
}

View file

@ -272,7 +272,27 @@ sebserver.exam.status.UP_COMING=Up Coming
sebserver.exam.status.RUNNING=Running sebserver.exam.status.RUNNING=Running
sebserver.exam.status.FINISHED=Finished sebserver.exam.status.FINISHED=Finished
sebserver.exam.indicator.list.actions=Selected Indicator sebserver.exam.configuration.list.actions=SEB Configuration
sebserver.exam.configuration.list.title=SEB Configuration
sebserver.exam.configuration.list.column.name=Name
sebserver.exam.configuration.list.column.description=Description
sebserver.exam.configuration.list.column.status=Status
sebserver.exam.configuration.list.empty=There is currently no SEB Configuration defined for this Exam. Please add one
sebserver.exam.configuration.action.list.new=Add
sebserver.exam.configuration.action.list.modify=Edit
sebserver.exam.configuration.action.list.delete=Delete
sebserver.exam.configuration.action.save=Save
sebserver.exam.configuration.form.title.new=Add SEB Configuration Mapping
sebserver.exam.configuration.form.title=SEB Configuration Mapping
sebserver.exam.configuration.form.name=SEB Configuration
sebserver.exam.configuration.form.encryptSecret=Encryption Password
sebserver.exam.configuration.form.description=Description
sebserver.exam.configuration.form.status=Status
sebserver.exam.configuration.form.encryptSecret.confirm=Confirm Password
sebserver.exam.indicator.list.actions=Indicator
sebserver.exam.indicator.list.title=Indicators sebserver.exam.indicator.list.title=Indicators
sebserver.exam.indicator.list.column.type=Type sebserver.exam.indicator.list.column.type=Type
sebserver.exam.indicator.list.column.name=Name sebserver.exam.indicator.list.column.name=Name
@ -285,9 +305,9 @@ sebserver.exam.indicator.type.ERROR_COUNT=Error Count
sebserver.exam.indicator.info.pleaseSelect=Please Select an Indicator first sebserver.exam.indicator.info.pleaseSelect=Please Select an Indicator first
sebserver.exam.indicator.action.list.new=New Indicator sebserver.exam.indicator.action.list.new=New
sebserver.exam.indicator.action.list.modify=Edit sebserver.exam.indicator.action.list.modify=Edit Selected
sebserver.exam.indicator.action.list.delete=Delete sebserver.exam.indicator.action.list.delete=Delete Selected
sebserver.exam.indicator.action.save=Save sebserver.exam.indicator.action.save=Save
sebserver.exam.indicator.form.title=Indicator sebserver.exam.indicator.form.title=Indicator

View file

@ -40,7 +40,6 @@ sebserver.error.unexpected=Unexpected Error
sebserver.page.message=Information sebserver.page.message=Information
sebserver.dialog.confirm.title=Confirmation sebserver.dialog.confirm.title=Confirmation
sebserver.dialog.confirm.deactivation=Note that there are {0} other entities that belong to this entity.<br/>These will also be deactivated by deactivating this entity.<br/><br/>Are You sure you want to deactivate this entity?
sebserver.dialog.confirm.deactivation.noDependencies=Are You sure you want to deactivate? sebserver.dialog.confirm.deactivation.noDependencies=Are You sure you want to deactivate?
################################ ################################
@ -266,7 +265,7 @@ sebserver.exam.type.MANAGED=Managed Devices
sebserver.exam.type.BYOD=Bring Your Own Device sebserver.exam.type.BYOD=Bring Your Own Device
sebserver.exam.type.VDI=VDI (Virtual Desktop Infrastructure) sebserver.exam.type.VDI=VDI (Virtual Desktop Infrastructure)
sebserver.exam.indicator.list.actions=Selected Indicator sebserver.exam.indicator.list.actions=Indicator
sebserver.exam.indicator.list.title=Indicators sebserver.exam.indicator.list.title=Indicators
sebserver.exam.indicator.list.column.type=Type sebserver.exam.indicator.list.column.type=Type
sebserver.exam.indicator.list.column.name=Name sebserver.exam.indicator.list.column.name=Name
@ -279,9 +278,9 @@ sebserver.exam.indicator.type.ERROR_COUNT=Error Count
sebserver.exam.indicator.info.pleaseSelect=Please select an indicator first sebserver.exam.indicator.info.pleaseSelect=Please select an indicator first
sebserver.exam.indicator.action.list.new=New Indicator sebserver.exam.indicator.action.list.new=New
sebserver.exam.indicator.action.list.modify=Edit sebserver.exam.indicator.action.list.modify=Edit Selected
sebserver.exam.indicator.action.list.delete=Delete sebserver.exam.indicator.action.list.delete=Delete Selected
sebserver.exam.indicator.action.save=Save sebserver.exam.indicator.action.save=Save
sebserver.exam.indicator.form.title=Indicator sebserver.exam.indicator.form.title=Indicator

Binary file not shown.

After

Width:  |  Height:  |  Size: 148 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 218 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 174 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 132 B