SEBSERV-44 SEBSERV-45 Exam - SEB Configuration mapping implementation
This commit is contained in:
parent
322f1c640d
commit
a57f937724
36 changed files with 1011 additions and 111 deletions
|
@ -6,7 +6,7 @@
|
|||
* 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;
|
||||
|
||||
|
@ -16,9 +16,12 @@ 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.CONFIGURATION_NODE;
|
||||
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.sebconfig.ConfigurationNode.ConfigurationStatus;
|
||||
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public final class ExamConfigurationMap implements GrantEntity {
|
||||
|
@ -35,14 +38,23 @@ public final class ExamConfigurationMap implements GrantEntity {
|
|||
@JsonProperty(EXAM_CONFIGURATION_MAP.ATTR_INSTITUTION_ID)
|
||||
public final Long institutionId;
|
||||
|
||||
@NotNull
|
||||
@NotNull(message = "examConfigurationMap:examId:notNull")
|
||||
@JsonProperty(EXAM_CONFIGURATION_MAP.ATTR_EXAM_ID)
|
||||
public final Long examId;
|
||||
|
||||
@NotNull
|
||||
@NotNull(message = "examConfigurationMap:configurationNodeId:notNull")
|
||||
@JsonProperty(EXAM_CONFIGURATION_MAP.ATTR_CONFIGURATION_NODE_ID)
|
||||
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)
|
||||
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_CONFIGURATION_NODE_ID) final Long configurationNodeId,
|
||||
@JsonProperty(EXAM_CONFIGURATION_MAP.ATTR_USER_NAMES) final String userNames,
|
||||
@JsonProperty(SEB_CLIENT_CONFIGURATION.ATTR_ENCRYPT_SECRET) final CharSequence encryptSecret,
|
||||
@JsonProperty(ATTR_CONFIRM_ENCRYPT_SECRET) final CharSequence confirmEncryptSecret) {
|
||||
@JsonProperty(EXAM_CONFIGURATION_MAP.ATTR_ENCRYPT_SECRET) final CharSequence encryptSecret,
|
||||
@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.institutionId = institutionId;
|
||||
|
@ -69,6 +85,24 @@ public final class ExamConfigurationMap implements GrantEntity {
|
|||
this.userNames = userNames;
|
||||
this.encryptSecret = encryptSecret;
|
||||
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
|
||||
|
@ -122,6 +156,18 @@ public final class ExamConfigurationMap implements GrantEntity {
|
|||
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
|
||||
public String toString() {
|
||||
final StringBuilder builder = new StringBuilder();
|
||||
|
@ -133,10 +179,20 @@ public final class ExamConfigurationMap implements GrantEntity {
|
|||
builder.append(this.examId);
|
||||
builder.append(", 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(this.userNames);
|
||||
builder.append("]");
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
|
@ -29,7 +29,7 @@ import ch.ethz.seb.sebserver.gbl.util.Utils;
|
|||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
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 {
|
||||
LAST_PING,
|
||||
|
|
|
@ -8,6 +8,9 @@
|
|||
|
||||
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 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.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.exam.Exam.ExamStatus;
|
||||
import ch.ethz.seb.sebserver.gbl.model.exam.Indicator;
|
||||
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.impl.PageAction;
|
||||
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.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.SaveExam;
|
||||
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 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 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");
|
||||
private final static LocTextKey typeColumnKey =
|
||||
private final static LocTextKey INDICATOR_TYPE_COLUMN_KEY =
|
||||
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");
|
||||
private final static LocTextKey thresholdColumnKey =
|
||||
private final static LocTextKey INDICATOR_THRESHOLD_COLUMN_KEY =
|
||||
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");
|
||||
|
||||
protected ExamForm(
|
||||
|
@ -162,7 +190,6 @@ public class ExamForm implements TemplateComposer {
|
|||
.putStaticValueIf(isNew,
|
||||
QuizData.QUIZ_ATTR_ID,
|
||||
exam.externalId)
|
||||
|
||||
.addField(FormBuilder.singleSelection(
|
||||
Domain.EXAM.ATTR_LMS_SETUP_ID,
|
||||
FORM_LMSSETUP_TEXT_KEY,
|
||||
|
@ -237,35 +264,102 @@ public class ExamForm implements TemplateComposer {
|
|||
.publishIf(() -> !readonly);
|
||||
|
||||
// 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
|
||||
widgetFactory.labelLocalized(
|
||||
content,
|
||||
CustomVariant.TEXT_H3,
|
||||
listTitleKey);
|
||||
INDICATOR_LIST_TITLE_KEY);
|
||||
|
||||
final EntityTable<Indicator> indicatorTable =
|
||||
this.pageService.entityTableBuilder(restService.getRestCall(GetIndicators.class))
|
||||
.withRestCallAdapter(builder -> builder.withQueryParam(
|
||||
Indicator.FILTER_ATTR_EXAM,
|
||||
Indicator.FILTER_ATTR_EXAM_ID,
|
||||
entityKey.modelId))
|
||||
.withEmptyMessage(new LocTextKey("sebserver.exam.indicator.list.empty"))
|
||||
.withEmptyMessage(INDICATOR_EMPTY_LIST_MESSAGE)
|
||||
.withPaging(5)
|
||||
.hideNavigation()
|
||||
.withColumn(new ColumnDefinition<>(
|
||||
Domain.INDICATOR.ATTR_NAME,
|
||||
nameColumnKey,
|
||||
INDICATOR_NAME_COLUMN_KEY,
|
||||
Indicator::getName,
|
||||
false))
|
||||
.withColumn(new ColumnDefinition<>(
|
||||
Domain.INDICATOR.ATTR_TYPE,
|
||||
typeColumnKey,
|
||||
INDICATOR_TYPE_COLUMN_KEY,
|
||||
this::indicatorTypeName,
|
||||
false))
|
||||
.withColumn(new ColumnDefinition<>(
|
||||
Domain.THRESHOLD.REFERENCE_NAME,
|
||||
thresholdColumnKey,
|
||||
INDICATOR_THRESHOLD_COLUMN_KEY,
|
||||
ExamForm::thresholdsValue,
|
||||
false))
|
||||
.withDefaultActionIf(
|
||||
|
@ -285,18 +379,20 @@ public class ExamForm implements TemplateComposer {
|
|||
|
||||
.newAction(ActionDefinition.EXAM_INDICATOR_MODIFY_FROM_LIST)
|
||||
.withParentEntityKey(entityKey)
|
||||
.withSelect(indicatorTable::getSelection, PageAction::applySingleSelection, emptySelectionTextKey)
|
||||
.withSelect(
|
||||
indicatorTable::getSelection,
|
||||
PageAction::applySingleSelection,
|
||||
INDICATOR_EMPTY_SELECTION_TEXT_KEY)
|
||||
.publishIf(() -> modifyGrant && indicatorTable.hasAnyContent() && editable)
|
||||
|
||||
.newAction(ActionDefinition.EXAM_INDICATOR_DELETE_FROM_LIST)
|
||||
.withEntityKey(entityKey)
|
||||
.withSelect(indicatorTable::getSelection, this::deleteSelectedIndicator, emptySelectionTextKey)
|
||||
.withSelect(
|
||||
indicatorTable::getSelection,
|
||||
this::deleteSelectedIndicator,
|
||||
INDICATOR_EMPTY_SELECTION_TEXT_KEY)
|
||||
.publishIf(() -> modifyGrant && indicatorTable.hasAnyContent() && editable);
|
||||
|
||||
// TODO List of attached SEB Configurations
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private PageAction deleteSelectedIndicator(final PageAction action) {
|
||||
|
@ -308,6 +404,15 @@ public class ExamForm implements TemplateComposer {
|
|||
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) {
|
||||
return restService.getBuilder(GetExam.class)
|
||||
.withURIVariable(API.PARAM_MODEL_ID, entityKey.modelId)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -43,6 +43,10 @@ public class IndicatorForm implements TemplateComposer {
|
|||
|
||||
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 =
|
||||
new LocTextKey("sebserver.exam.indicator.form.thresholds");
|
||||
private static final LocTextKey FORM_COLOR_TEXT_KEY =
|
||||
|
@ -100,10 +104,9 @@ public class IndicatorForm implements TemplateComposer {
|
|||
final PageContext formContext = pageContext.withEntityKey(indicator.getEntityKey());
|
||||
|
||||
// the default page layout
|
||||
final LocTextKey titleKey = new LocTextKey(
|
||||
(isNew)
|
||||
? "sebserver.exam.indicator.form.title.new"
|
||||
: "sebserver.exam.indicator.form.title");
|
||||
final LocTextKey titleKey = (isNew)
|
||||
? NEW_INDICATOR_TILE_TEXT_KEY
|
||||
: INDICATOR_TILE_TEXT_KEY;
|
||||
final Composite content = widgetFactory.defaultPageLayout(
|
||||
formContext.getParent(),
|
||||
titleKey);
|
||||
|
|
|
@ -8,14 +8,11 @@
|
|||
|
||||
package ch.ethz.seb.sebserver.gui.content;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.eclipse.swt.widgets.Composite;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.Constants;
|
||||
import ch.ethz.seb.sebserver.gbl.api.EntityType;
|
||||
import ch.ethz.seb.sebserver.gbl.model.Domain;
|
||||
import ch.ethz.seb.sebserver.gbl.model.Entity;
|
||||
|
@ -114,7 +111,7 @@ public class SebExamConfigList implements TemplateComposer {
|
|||
() -> new ColumnDefinition<>(
|
||||
Domain.LMS_SETUP.ATTR_INSTITUTION_ID,
|
||||
INSTITUTION_TEXT_KEY,
|
||||
examConfigInstitutionNameFunction(this.resourceService),
|
||||
this.resourceService::localizedExamConfigInstitutionName,
|
||||
this.institutionFilter,
|
||||
false))
|
||||
.withColumn(new ColumnDefinition<>(
|
||||
|
@ -132,7 +129,7 @@ public class SebExamConfigList implements TemplateComposer {
|
|||
.withColumn(new ColumnDefinition<>(
|
||||
Domain.CONFIGURATION_NODE.ATTR_STATUS,
|
||||
STATUS_TEXT_KEY,
|
||||
this::examConfigStatusName,
|
||||
this.resourceService::localizedExamConfigStatusName,
|
||||
this.statusFilter,
|
||||
true))
|
||||
.withDefaultAction(pageActionBuilder
|
||||
|
@ -141,7 +138,6 @@ public class SebExamConfigList implements TemplateComposer {
|
|||
.compose(content);
|
||||
|
||||
final GrantCheck examConfigGrant = this.currentUser.grantCheck(EntityType.CONFIGURATION_NODE);
|
||||
|
||||
pageActionBuilder
|
||||
|
||||
.newAction(ActionDefinition.SEB_EXAM_CONFIG_NEW)
|
||||
|
@ -160,20 +156,4 @@ public class SebExamConfigList implements TemplateComposer {
|
|||
.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());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -134,7 +134,8 @@ public class SebExamConfigPropForm implements TemplateComposer {
|
|||
.addField(FormBuilder.text(
|
||||
Domain.CONFIGURATION_NODE.ATTR_DESCRIPTION,
|
||||
FORM_DESCRIPTION_TEXT_KEY,
|
||||
examConfig.description).asArea())
|
||||
examConfig.description)
|
||||
.asArea())
|
||||
.addField(FormBuilder.singleSelection(
|
||||
Domain.CONFIGURATION_NODE.ATTR_STATUS,
|
||||
FORM_STATUS_TEXT_KEY,
|
||||
|
|
|
@ -17,7 +17,8 @@ public enum ActionCategory {
|
|||
LMS_SETUP_LIST(new LocTextKey("sebserver.lmssetup.list.actions"), 1),
|
||||
QUIZ_LIST(new LocTextKey("sebserver.quizdiscovery.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_EXAM_CONFIG_LIST(new LocTextKey("sebserver.examconfig.list.actions"), 1),
|
||||
VARIA(new LocTextKey("sebserver.overall.action.category.varia"), 100),
|
||||
|
|
|
@ -228,10 +228,37 @@ public enum ActionDefinition {
|
|||
PageStateDefinition.EXAM_VIEW,
|
||||
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(
|
||||
new LocTextKey("sebserver.exam.indicator.action.list.new"),
|
||||
ImageIcon.NEW,
|
||||
PageStateDefinition.INDICATOR_EDIT),
|
||||
PageStateDefinition.INDICATOR_EDIT,
|
||||
ActionCategory.INDICATOR_LIST),
|
||||
EXAM_INDICATOR_MODIFY_FROM_LIST(
|
||||
new LocTextKey("sebserver.exam.indicator.action.list.modify"),
|
||||
ImageIcon.EDIT,
|
||||
|
@ -325,7 +352,7 @@ public enum ActionDefinition {
|
|||
ActionCategory.FORM),
|
||||
SEB_EXAM_CONFIG_MODIFY(
|
||||
new LocTextKey("sebserver.examconfig.action.modify"),
|
||||
ImageIcon.EDIT,
|
||||
ImageIcon.EDIT_SETTINGS,
|
||||
PageStateDefinition.SEB_EXAM_CONFIG_EDIT,
|
||||
ActionCategory.FORM),
|
||||
SEB_EXAM_CONFIG_CANCEL_MODIFY(
|
||||
|
@ -341,7 +368,7 @@ public enum ActionDefinition {
|
|||
|
||||
SEB_EXAM_CONFIG_MODIFY_FROM_LIST(
|
||||
new LocTextKey("sebserver.examconfig.action.list.modify"),
|
||||
ImageIcon.EDIT,
|
||||
ImageIcon.EDIT_SETTINGS,
|
||||
PageStateDefinition.SEB_EXAM_CONFIG_EDIT,
|
||||
ActionCategory.SEB_EXAM_CONFIG_LIST),
|
||||
|
||||
|
@ -352,7 +379,7 @@ public enum ActionDefinition {
|
|||
ActionCategory.SEB_EXAM_CONFIG_LIST),
|
||||
SEB_EXAM_CONFIG_UNDO(
|
||||
new LocTextKey("sebserver.examconfig.action.undo"),
|
||||
ImageIcon.SAVE,
|
||||
ImageIcon.UNDO,
|
||||
PageStateDefinition.SEB_EXAM_CONFIG_EDIT,
|
||||
ActionCategory.SEB_EXAM_CONFIG_LIST),
|
||||
|
||||
|
|
|
@ -119,9 +119,9 @@ public class ActionPane implements TemplateComposer {
|
|||
}
|
||||
}
|
||||
|
||||
final Label labelSeparator = this.widgetFactory.labelSeparator(composite);
|
||||
final GridData separatorLayout = new GridData(SWT.FILL, SWT.TOP, true, false);
|
||||
labelSeparator.setLayoutData(separatorLayout);
|
||||
// final Label labelSeparator = this.widgetFactory.labelSeparator(composite);
|
||||
// final GridData separatorLayout = new GridData(SWT.FILL, SWT.TOP, true, false);
|
||||
// labelSeparator.setLayoutData(separatorLayout);
|
||||
|
||||
// title
|
||||
if (category.title != null) {
|
||||
|
@ -140,7 +140,7 @@ public class ActionPane implements TemplateComposer {
|
|||
composite,
|
||||
SWT.SINGLE | SWT.FULL_SELECTION);
|
||||
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);
|
||||
final Template template = new Template();
|
||||
final ImageCell imageCell = new ImageCell(template);
|
||||
|
|
|
@ -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.ExamList;
|
||||
import ch.ethz.seb.sebserver.gui.content.ExamSebConfigMapForm;
|
||||
import ch.ethz.seb.sebserver.gui.content.IndicatorForm;
|
||||
import ch.ethz.seb.sebserver.gui.content.InstitutionForm;
|
||||
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_VIEW(Type.FORM_VIEW, 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),
|
||||
|
||||
SEB_CLIENT_CONFIG_LIST(Type.LIST_VIEW, SebClientConfigList.class, ActivityDefinition.SEB_CLIENT_CONFIG),
|
||||
|
|
|
@ -143,6 +143,24 @@ public final class Form implements FormBinding {
|
|||
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() {
|
||||
process(
|
||||
name -> true,
|
||||
|
@ -208,11 +226,13 @@ public final class Form implements FormBinding {
|
|||
private FormFieldAccessor createAccessor(final Label label, final Label field) {
|
||||
return new FormFieldAccessor(label, field) {
|
||||
@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) {
|
||||
return new FormFieldAccessor(label, text) {
|
||||
@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) {
|
||||
|
@ -234,6 +254,7 @@ public final class Form implements FormBinding {
|
|||
jsonValueAdapter,
|
||||
selection.type() != Type.SINGLE) {
|
||||
@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) {
|
||||
|
@ -356,6 +377,10 @@ public final class Form implements FormBinding {
|
|||
|
||||
public abstract String getStringValue();
|
||||
|
||||
public void setStringValue(final String value) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public void setVisible(final boolean visible) {
|
||||
this.label.setVisible(visible);
|
||||
this.control.setVisible(visible);
|
||||
|
|
|
@ -256,7 +256,7 @@ public class FormBuilder {
|
|||
Label valueLabel(final Composite parent, final String value, final int hspan) {
|
||||
final Label label = new Label(parent, SWT.NONE);
|
||||
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;
|
||||
label.setLayoutData(gridData);
|
||||
return label;
|
||||
|
|
|
@ -24,17 +24,23 @@ import org.springframework.stereotype.Service;
|
|||
|
||||
import ch.ethz.seb.sebserver.gbl.Constants;
|
||||
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.Indicator.IndicatorType;
|
||||
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.ConfigurationType;
|
||||
import ch.ethz.seb.sebserver.gbl.model.user.UserInfo;
|
||||
import ch.ethz.seb.sebserver.gbl.model.user.UserRole;
|
||||
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.gui.service.i18n.I18nSupport;
|
||||
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.exam.GetExamConfigMappingNames;
|
||||
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.useraccount.GetUserAccountNames;
|
||||
|
@ -105,6 +111,28 @@ public class ResourceService {
|
|||
.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() {
|
||||
return UserRole.publicRolesForUser(this.currentUser.get())
|
||||
.stream()
|
||||
|
@ -125,7 +153,6 @@ public class ResourceService {
|
|||
}
|
||||
|
||||
public Function<String, String> getInstitutionNameFunction() {
|
||||
|
||||
final Map<String, String> idNameMap = this.restService.getBuilder(GetInstitutionNames.class)
|
||||
.withQueryParam(Entity.FILTER_ATTR_ACTIVE, Constants.TRUE_STRING)
|
||||
.call()
|
||||
|
@ -248,4 +275,41 @@ public class ResourceService {
|
|||
: 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();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -298,8 +298,8 @@ public class TableFieldBuilder implements InputFieldBuilder {
|
|||
item.setImage(
|
||||
cellIndex,
|
||||
(BooleanUtils.toBoolean((tableValue != null) ? tableValue.value : null))
|
||||
? ImageIcon.ACTIVE.getImage(this.control.getDisplay())
|
||||
: ImageIcon.INACTIVE.getImage(this.control.getDisplay()));
|
||||
? ImageIcon.YES.getImage(this.control.getDisplay())
|
||||
: ImageIcon.NO.getImage(this.control.getDisplay()));
|
||||
} else {
|
||||
item.setText(
|
||||
cellIndex,
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -101,7 +101,6 @@ public class EntityTable<ROW extends Entity> {
|
|||
layout.verticalSpacing = 0;
|
||||
this.composite.setLayout(layout);
|
||||
GridData gridData = new GridData(SWT.FILL, SWT.TOP, true, false);
|
||||
// gridData.heightHint = (pageSize + 2) * 40;
|
||||
this.composite.setLayoutData(gridData);
|
||||
|
||||
// TODO just for debugging, remove when tested
|
||||
|
@ -223,6 +222,19 @@ public class EntityTable<ROW extends Entity> {
|
|||
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() {
|
||||
final TableItem[] selection = this.table.getSelection();
|
||||
if (selection == null || selection.length == 0) {
|
||||
|
@ -296,9 +308,6 @@ public class EntityTable<ROW extends Entity> {
|
|||
// TODO error handling
|
||||
});
|
||||
|
||||
final GridData gridData = (GridData) this.composite.getLayoutData();
|
||||
gridData.heightHint = (this.table.getItemCount() + 2) * 50;
|
||||
|
||||
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) {
|
||||
if ((Boolean) value) {
|
||||
item.setImage(index, ImageIcon.ACTIVE.getImage(item.getDisplay()));
|
||||
item.setImage(index, ImageIcon.YES.getImage(item.getDisplay()));
|
||||
} else {
|
||||
item.setImage(index, ImageIcon.INACTIVE.getImage(item.getDisplay()));
|
||||
item.setImage(index, ImageIcon.NO.getImage(item.getDisplay()));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
}
|
|
@ -68,6 +68,7 @@ public class WidgetFactory {
|
|||
ADD_BOX("add_box.png"),
|
||||
REMOVE_BOX("remove_box.png"),
|
||||
EDIT("edit.png"),
|
||||
EDIT_SETTINGS("settings.png"),
|
||||
TEST("test.png"),
|
||||
IMPORT("import.png"),
|
||||
CANCEL("cancel.png"),
|
||||
|
@ -75,10 +76,13 @@ public class WidgetFactory {
|
|||
SHOW("show.png"),
|
||||
ACTIVE("active.png"),
|
||||
INACTIVE("inactive.png"),
|
||||
YES("yes.png"),
|
||||
NO("no.png"),
|
||||
SAVE("save.png"),
|
||||
NEW("new.png"),
|
||||
DELETE("delete.png"),
|
||||
SEARCH("lens.png"),
|
||||
UNDO("undo.png"),
|
||||
COLOR("color.png");
|
||||
|
||||
private String fileName;
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
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;
|
||||
|
||||
public interface ExamConfigurationMapDAO extends
|
||||
|
|
|
@ -15,6 +15,7 @@ import org.springframework.util.MultiValueMap;
|
|||
import ch.ethz.seb.sebserver.gbl.api.POSTMapper;
|
||||
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.ExamConfigurationMap;
|
||||
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.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.ConfigurationNode;
|
||||
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.user.UserInfo;
|
||||
import ch.ethz.seb.sebserver.gbl.util.Utils;
|
||||
|
@ -100,7 +100,7 @@ public class FilterMap extends POSTMapper {
|
|||
}
|
||||
|
||||
public Long getIndicatorExamId() {
|
||||
return getLong(Indicator.FILTER_ATTR_EXAM);
|
||||
return getLong(Indicator.FILTER_ATTR_EXAM_ID);
|
||||
}
|
||||
|
||||
public String getIndicatorName() {
|
||||
|
|
|
@ -213,10 +213,10 @@ public class ConfigurationNodeDAOImpl implements ConfigurationNodeDAO {
|
|||
data.id,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
data.name,
|
||||
data.description,
|
||||
null,
|
||||
null,
|
||||
(data.status != null) ? data.status.name() : ConfigurationStatus.CONSTRUCTION.name());
|
||||
|
||||
this.configurationNodeRecordMapper.updateByPrimaryKeySelective(newRecord);
|
||||
|
|
|
@ -19,6 +19,7 @@ import java.util.function.Function;
|
|||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.mybatis.dynamic.sql.SqlBuilder;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
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.EntityType;
|
||||
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.util.Result;
|
||||
import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.ConfigurationNodeRecordMapper;
|
||||
|
@ -79,7 +81,7 @@ public class ExamConfigurationMapDAOImpl implements ExamConfigurationMapDAO {
|
|||
@Transactional(readOnly = true)
|
||||
public Result<ExamConfigurationMap> byPK(final Long id) {
|
||||
return recordById(id)
|
||||
.flatMap(ExamConfigurationMapDAOImpl::toDomainModel);
|
||||
.flatMap(this::toDomainModel);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -91,7 +93,7 @@ public class ExamConfigurationMapDAOImpl implements ExamConfigurationMapDAO {
|
|||
.build()
|
||||
.execute()
|
||||
.stream()
|
||||
.map(ExamConfigurationMapDAOImpl::toDomainModel)
|
||||
.map(this::toDomainModel)
|
||||
.flatMap(DAOLoggingSupport::logAndSkipOnError)
|
||||
.collect(Collectors.toList());
|
||||
});
|
||||
|
@ -117,7 +119,7 @@ public class ExamConfigurationMapDAOImpl implements ExamConfigurationMapDAO {
|
|||
.build()
|
||||
.execute()
|
||||
.stream()
|
||||
.map(ExamConfigurationMapDAOImpl::toDomainModel)
|
||||
.map(this::toDomainModel)
|
||||
.flatMap(DAOLoggingSupport::logAndSkipOnError)
|
||||
.filter(predicate)
|
||||
.collect(Collectors.toList()));
|
||||
|
@ -139,7 +141,7 @@ public class ExamConfigurationMapDAOImpl implements ExamConfigurationMapDAO {
|
|||
this.examConfigurationMapRecordMapper.insert(newRecord);
|
||||
return newRecord;
|
||||
})
|
||||
.flatMap(ExamConfigurationMapDAOImpl::toDomainModel)
|
||||
.flatMap(this::toDomainModel)
|
||||
.onError(TransactionHandler::rollback);
|
||||
}
|
||||
|
||||
|
@ -159,7 +161,7 @@ public class ExamConfigurationMapDAOImpl implements ExamConfigurationMapDAO {
|
|||
this.examConfigurationMapRecordMapper.updateByPrimaryKeySelective(newRecord);
|
||||
return this.examConfigurationMapRecordMapper.selectByPrimaryKey(data.id);
|
||||
})
|
||||
.flatMap(ExamConfigurationMapDAOImpl::toDomainModel)
|
||||
.flatMap(this::toDomainModel)
|
||||
.onError(TransactionHandler::rollback);
|
||||
}
|
||||
|
||||
|
@ -223,15 +225,25 @@ public class ExamConfigurationMapDAOImpl implements ExamConfigurationMapDAO {
|
|||
});
|
||||
}
|
||||
|
||||
private static Result<ExamConfigurationMap> toDomainModel(final ExamConfigurationMapRecord record) {
|
||||
return Result.tryCatch(() -> new ExamConfigurationMap(
|
||||
record.getId(),
|
||||
record.getInstitutionId(),
|
||||
record.getExamId(),
|
||||
record.getConfigurationNodeId(),
|
||||
record.getUserNames(),
|
||||
null,
|
||||
null));
|
||||
private Result<ExamConfigurationMap> toDomainModel(final ExamConfigurationMapRecord record) {
|
||||
return Result.tryCatch(() -> {
|
||||
|
||||
final ConfigurationNodeRecord selectByPrimaryKey = this.configurationNodeRecordMapper
|
||||
.selectByPrimaryKey(record.getConfigurationNodeId());
|
||||
final String status = selectByPrimaryKey.getStatus();
|
||||
|
||||
return new ExamConfigurationMap(
|
||||
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) {
|
||||
|
|
|
@ -30,9 +30,9 @@ import org.springframework.web.bind.annotation.RequestParam;
|
|||
import ch.ethz.seb.sebserver.gbl.Constants;
|
||||
import ch.ethz.seb.sebserver.gbl.api.API;
|
||||
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.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.EntityKey;
|
||||
import ch.ethz.seb.sebserver.gbl.model.EntityName;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -272,7 +272,27 @@ sebserver.exam.status.UP_COMING=Up Coming
|
|||
sebserver.exam.status.RUNNING=Running
|
||||
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.column.type=Type
|
||||
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.action.list.new=New Indicator
|
||||
sebserver.exam.indicator.action.list.modify=Edit
|
||||
sebserver.exam.indicator.action.list.delete=Delete
|
||||
sebserver.exam.indicator.action.list.new=New
|
||||
sebserver.exam.indicator.action.list.modify=Edit Selected
|
||||
sebserver.exam.indicator.action.list.delete=Delete Selected
|
||||
sebserver.exam.indicator.action.save=Save
|
||||
|
||||
sebserver.exam.indicator.form.title=Indicator
|
||||
|
|
|
@ -40,7 +40,6 @@ sebserver.error.unexpected=Unexpected Error
|
|||
sebserver.page.message=Information
|
||||
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?
|
||||
|
||||
################################
|
||||
|
@ -266,7 +265,7 @@ sebserver.exam.type.MANAGED=Managed Devices
|
|||
sebserver.exam.type.BYOD=Bring Your Own Device
|
||||
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.column.type=Type
|
||||
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.action.list.new=New Indicator
|
||||
sebserver.exam.indicator.action.list.modify=Edit
|
||||
sebserver.exam.indicator.action.list.delete=Delete
|
||||
sebserver.exam.indicator.action.list.new=New
|
||||
sebserver.exam.indicator.action.list.modify=Edit Selected
|
||||
sebserver.exam.indicator.action.list.delete=Delete Selected
|
||||
sebserver.exam.indicator.action.save=Save
|
||||
|
||||
sebserver.exam.indicator.form.title=Indicator
|
||||
|
|
BIN
src/main/resources/static/images/no.png
Normal file
BIN
src/main/resources/static/images/no.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 148 B |
BIN
src/main/resources/static/images/settings.png
Normal file
BIN
src/main/resources/static/images/settings.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 218 B |
BIN
src/main/resources/static/images/undo.png
Normal file
BIN
src/main/resources/static/images/undo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 174 B |
BIN
src/main/resources/static/images/yes.png
Normal file
BIN
src/main/resources/static/images/yes.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 132 B |
Loading…
Reference in a new issue