SEBSERV-73 added exam reference table to exam config view page
This commit is contained in:
parent
fb13c62eeb
commit
bac8aba3eb
13 changed files with 238 additions and 48 deletions
|
@ -10,6 +10,8 @@ package ch.ethz.seb.sebserver.gbl.model.exam;
|
|||
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
import org.joda.time.DateTime;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
|
@ -20,9 +22,11 @@ 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;
|
||||
import ch.ethz.seb.sebserver.gbl.model.Domain.EXAM_CONFIGURATION_MAP;
|
||||
import ch.ethz.seb.sebserver.gbl.model.Entity;
|
||||
import ch.ethz.seb.sebserver.gbl.model.GrantEntity;
|
||||
import ch.ethz.seb.sebserver.gbl.model.exam.Exam.ExamType;
|
||||
import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode.ConfigurationStatus;
|
||||
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
|
@ -44,6 +48,18 @@ public final class ExamConfigurationMap implements GrantEntity {
|
|||
@JsonProperty(EXAM_CONFIGURATION_MAP.ATTR_EXAM_ID)
|
||||
public final Long examId;
|
||||
|
||||
@JsonProperty(QuizData.QUIZ_ATTR_NAME)
|
||||
public final String examName;
|
||||
|
||||
@JsonProperty(QuizData.QUIZ_ATTR_DESCRIPTION)
|
||||
public final String examDescription;
|
||||
|
||||
@JsonProperty(QuizData.QUIZ_ATTR_START_TIME)
|
||||
public final DateTime examStartTime;
|
||||
|
||||
@JsonProperty(EXAM.ATTR_TYPE)
|
||||
public final ExamType examType;
|
||||
|
||||
@NotNull(message = "examConfigurationMap:configurationNodeId:notNull")
|
||||
@JsonProperty(EXAM_CONFIGURATION_MAP.ATTR_CONFIGURATION_NODE_ID)
|
||||
public final Long configurationNodeId;
|
||||
|
@ -71,11 +87,14 @@ public final class ExamConfigurationMap implements GrantEntity {
|
|||
@JsonProperty(EXAM_CONFIGURATION_MAP.ATTR_ID) final Long id,
|
||||
@JsonProperty(EXAM_CONFIGURATION_MAP.ATTR_INSTITUTION_ID) final Long institutionId,
|
||||
@JsonProperty(EXAM_CONFIGURATION_MAP.ATTR_EXAM_ID) final Long examId,
|
||||
@JsonProperty(QuizData.QUIZ_ATTR_NAME) final String examName,
|
||||
@JsonProperty(QuizData.QUIZ_ATTR_DESCRIPTION) final String examDescription,
|
||||
@JsonProperty(QuizData.QUIZ_ATTR_START_TIME) final DateTime examStartTime,
|
||||
@JsonProperty(EXAM.ATTR_TYPE) final ExamType examType,
|
||||
@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_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) {
|
||||
|
@ -83,6 +102,10 @@ public final class ExamConfigurationMap implements GrantEntity {
|
|||
this.id = id;
|
||||
this.institutionId = institutionId;
|
||||
this.examId = examId;
|
||||
this.examName = examName;
|
||||
this.examDescription = examDescription;
|
||||
this.examStartTime = examStartTime;
|
||||
this.examType = examType;
|
||||
this.configurationNodeId = configurationNodeId;
|
||||
this.userNames = userNames;
|
||||
this.encryptSecret = encryptSecret;
|
||||
|
@ -97,6 +120,12 @@ public final class ExamConfigurationMap implements GrantEntity {
|
|||
this.id = null;
|
||||
this.institutionId = institutionId;
|
||||
this.examId = postParams.getLong(Domain.EXAM_CONFIGURATION_MAP.ATTR_EXAM_ID);
|
||||
|
||||
this.examName = postParams.getString(QuizData.QUIZ_ATTR_NAME);
|
||||
this.examDescription = postParams.getString(QuizData.QUIZ_ATTR_DESCRIPTION);
|
||||
this.examStartTime = postParams.getDateTime(QuizData.QUIZ_ATTR_START_TIME);
|
||||
this.examType = postParams.getEnum(EXAM.ATTR_TYPE, ExamType.class);
|
||||
|
||||
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);
|
||||
|
@ -137,6 +166,22 @@ public final class ExamConfigurationMap implements GrantEntity {
|
|||
return this.examId;
|
||||
}
|
||||
|
||||
public String getExamName() {
|
||||
return this.examName;
|
||||
}
|
||||
|
||||
public String getExamDescription() {
|
||||
return this.examDescription;
|
||||
}
|
||||
|
||||
public DateTime getExamStartTime() {
|
||||
return this.examStartTime;
|
||||
}
|
||||
|
||||
public ExamType getExamType() {
|
||||
return this.examType;
|
||||
}
|
||||
|
||||
public Long getConfigurationNodeId() {
|
||||
return this.configurationNodeId;
|
||||
}
|
||||
|
@ -178,6 +223,10 @@ public final class ExamConfigurationMap implements GrantEntity {
|
|||
this.id,
|
||||
this.institutionId,
|
||||
this.examId,
|
||||
this.examName,
|
||||
this.examDescription,
|
||||
this.examStartTime,
|
||||
this.examType,
|
||||
this.configurationNodeId,
|
||||
this.userNames,
|
||||
Constants.EMPTY_NOTE,
|
||||
|
@ -196,6 +245,14 @@ public final class ExamConfigurationMap implements GrantEntity {
|
|||
builder.append(this.institutionId);
|
||||
builder.append(", examId=");
|
||||
builder.append(this.examId);
|
||||
builder.append(", examName=");
|
||||
builder.append(this.examName);
|
||||
builder.append(", examDescription=");
|
||||
builder.append(this.examDescription);
|
||||
builder.append(", examStartTime=");
|
||||
builder.append(this.examStartTime);
|
||||
builder.append(", examType=");
|
||||
builder.append(this.examType);
|
||||
builder.append(", configurationNodeId=");
|
||||
builder.append(this.configurationNodeId);
|
||||
builder.append(", configName=");
|
||||
|
@ -206,12 +263,18 @@ public final class ExamConfigurationMap implements GrantEntity {
|
|||
builder.append(this.configStatus);
|
||||
builder.append(", userNames=");
|
||||
builder.append(this.userNames);
|
||||
builder.append(", encryptSecret=");
|
||||
builder.append(this.encryptSecret);
|
||||
builder.append(", confirmEncryptSecret=");
|
||||
builder.append(this.confirmEncryptSecret);
|
||||
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);
|
||||
return new ExamConfigurationMap(
|
||||
null, exam.institutionId, exam.id, exam.name, exam.description, exam.startTime, exam.type,
|
||||
null, null, null, null, null, null, null);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
package ch.ethz.seb.sebserver.gui.content;
|
||||
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.BooleanSupplier;
|
||||
import java.util.function.Function;
|
||||
|
||||
|
@ -25,8 +26,9 @@ import ch.ethz.seb.sebserver.gbl.api.EntityType;
|
|||
import ch.ethz.seb.sebserver.gbl.model.Domain;
|
||||
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.QuizData;
|
||||
import ch.ethz.seb.sebserver.gbl.model.exam.Exam.ExamStatus;
|
||||
import ch.ethz.seb.sebserver.gbl.model.exam.ExamConfigurationMap;
|
||||
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.user.UserRole;
|
||||
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
|
||||
|
@ -43,6 +45,7 @@ import ch.ethz.seb.sebserver.gui.service.page.TemplateComposer;
|
|||
import ch.ethz.seb.sebserver.gui.service.page.impl.PageAction;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestService;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.CheckExamConsistency;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.GetExam;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.GetExamPage;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.CurrentUser;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.CurrentUser.GrantCheck;
|
||||
|
@ -58,23 +61,25 @@ import ch.ethz.seb.sebserver.gui.widget.WidgetFactory.CustomVariant;
|
|||
@GuiProfile
|
||||
public class ExamList implements TemplateComposer {
|
||||
|
||||
private static final LocTextKey PAGE_TITLE_KEY =
|
||||
static final String EXAM_LIST_COLUMN_STARTTIME =
|
||||
"sebserver.exam.list.column.starttime";
|
||||
static final LocTextKey PAGE_TITLE_KEY =
|
||||
new LocTextKey("sebserver.exam.list.title");
|
||||
private static final LocTextKey NO_MODIFY_PRIVILEGE_ON_OTHER_INSTITUION =
|
||||
static final LocTextKey NO_MODIFY_PRIVILEGE_ON_OTHER_INSTITUION =
|
||||
new LocTextKey("sebserver.exam.list.action.no.modify.privilege");
|
||||
private final static LocTextKey EMPTY_SELECTION_TEXT_KEY =
|
||||
final static LocTextKey EMPTY_SELECTION_TEXT_KEY =
|
||||
new LocTextKey("sebserver.exam.info.pleaseSelect");
|
||||
private final static LocTextKey COLUMN_TITLE_INSTITUTION_KEY =
|
||||
final static LocTextKey COLUMN_TITLE_INSTITUTION_KEY =
|
||||
new LocTextKey("sebserver.exam.list.column.institution");
|
||||
private final static LocTextKey COLUMN_TITLE_LMS_KEY =
|
||||
final static LocTextKey COLUMN_TITLE_LMS_KEY =
|
||||
new LocTextKey("sebserver.exam.list.column.lmssetup");
|
||||
private final static LocTextKey COLUMN_TITLE_NAME_KEY =
|
||||
final static LocTextKey COLUMN_TITLE_NAME_KEY =
|
||||
new LocTextKey("sebserver.exam.list.column.name");
|
||||
private final static LocTextKey COLUMN_TITLE_TYPE_KEY =
|
||||
final static LocTextKey COLUMN_TITLE_TYPE_KEY =
|
||||
new LocTextKey("sebserver.exam.list.column.type");
|
||||
private final static LocTextKey NO_MODIFY_OF_OUT_DATED_EXAMS =
|
||||
final static LocTextKey NO_MODIFY_OF_OUT_DATED_EXAMS =
|
||||
new LocTextKey("sebserver.exam.list.modify.out.dated");
|
||||
private final static LocTextKey EMPTY_LIST_TEXT_KEY =
|
||||
final static LocTextKey EMPTY_LIST_TEXT_KEY =
|
||||
new LocTextKey("sebserver.exam.list.empty");
|
||||
|
||||
private final TableFilterAttribute institutionFilter;
|
||||
|
@ -139,8 +144,8 @@ public class ExamList implements TemplateComposer {
|
|||
this.pageService.entityTableBuilder(restService.getRestCall(GetExamPage.class))
|
||||
.withEmptyMessage(EMPTY_LIST_TEXT_KEY)
|
||||
.withPaging(this.pageSize)
|
||||
.withRowDecorator(this::decorateOnExamConsistency)
|
||||
|
||||
.withRowDecorator(decorateOnExamConsistency(this.pageService))
|
||||
|
||||
.withColumnIf(
|
||||
isSebAdmin,
|
||||
() -> new ColumnDefinition<Exam>(
|
||||
|
@ -167,7 +172,7 @@ public class ExamList implements TemplateComposer {
|
|||
.withColumn(new ColumnDefinition<>(
|
||||
QuizData.QUIZ_ATTR_START_TIME,
|
||||
new LocTextKey(
|
||||
"sebserver.exam.list.column.starttime",
|
||||
EXAM_LIST_COLUMN_STARTTIME,
|
||||
i18nSupport.getUsersTimeZoneTitleSuffix()),
|
||||
Exam::getStartTime)
|
||||
.withFilter(new TableFilterAttribute(
|
||||
|
@ -178,7 +183,7 @@ public class ExamList implements TemplateComposer {
|
|||
.toString()))
|
||||
.sortable())
|
||||
|
||||
.withColumn(new ColumnDefinition<>(
|
||||
.withColumn(new ColumnDefinition<Exam>(
|
||||
Domain.EXAM.ATTR_TYPE,
|
||||
COLUMN_TITLE_TYPE_KEY,
|
||||
this.resourceService::localizedExamTypeName)
|
||||
|
@ -205,13 +210,13 @@ public class ExamList implements TemplateComposer {
|
|||
.newAction(ActionDefinition.EXAM_MODIFY_FROM_LIST)
|
||||
.withSelect(
|
||||
table.getGrantedSelection(currentUser, NO_MODIFY_PRIVILEGE_ON_OTHER_INSTITUION),
|
||||
action -> this.modifyExam(action, table),
|
||||
action -> modifyExam(action, table),
|
||||
EMPTY_SELECTION_TEXT_KEY)
|
||||
.publishIf(() -> userGrant.im() && table.hasAnyContent());
|
||||
|
||||
}
|
||||
|
||||
private PageAction modifyExam(final PageAction action, final EntityTable<Exam> table) {
|
||||
static final PageAction modifyExam(final PageAction action, final EntityTable<Exam> table) {
|
||||
final Exam exam = table.getSelectedROWData();
|
||||
|
||||
if (exam == null) {
|
||||
|
@ -227,27 +232,41 @@ public class ExamList implements TemplateComposer {
|
|||
|
||||
return action.withEntityKey(action.getSingleSelection());
|
||||
}
|
||||
|
||||
private void decorateOnExamConsistency(TableItem item, Exam exam) {
|
||||
|
||||
static final BiConsumer<TableItem, ExamConfigurationMap> decorateOnExamMapConsistency(
|
||||
final PageService pageService) {
|
||||
|
||||
return (item, examMap) -> {
|
||||
pageService.getRestService().getBuilder(GetExam.class)
|
||||
.withURIVariable(API.PARAM_MODEL_ID, String.valueOf(examMap.examId))
|
||||
.call()
|
||||
.ifPresent(exam -> decorateOnExamConsistency(item, exam, pageService));
|
||||
};
|
||||
}
|
||||
|
||||
static final BiConsumer<TableItem, Exam> decorateOnExamConsistency(final PageService pageService) {
|
||||
return (item, exam) -> decorateOnExamConsistency(item, exam, pageService);
|
||||
}
|
||||
|
||||
static final void decorateOnExamConsistency(final TableItem item, final Exam exam,
|
||||
final PageService pageService) {
|
||||
if (exam.getStatus() != ExamStatus.RUNNING) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.pageService.getRestService().getBuilder(CheckExamConsistency.class)
|
||||
.withURIVariable(API.PARAM_MODEL_ID, exam.getModelId())
|
||||
.call()
|
||||
.ifPresent(warnings -> {
|
||||
if (warnings != null && !warnings.isEmpty()) {
|
||||
item.setData(RWT.CUSTOM_VARIANT, CustomVariant.WARNING.key);
|
||||
}
|
||||
});
|
||||
|
||||
pageService.getRestService().getBuilder(CheckExamConsistency.class)
|
||||
.withURIVariable(API.PARAM_MODEL_ID, exam.getModelId())
|
||||
.call()
|
||||
.ifPresent(warnings -> {
|
||||
if (warnings != null && !warnings.isEmpty()) {
|
||||
item.setData(RWT.CUSTOM_VARIANT, CustomVariant.WARNING.key);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static Function<Exam, String> examLmsSetupNameFunction(final ResourceService resourceService) {
|
||||
return exam -> resourceService.getLmsSetupNameFunction()
|
||||
.apply(String.valueOf(exam.lmsSetupId));
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -101,7 +101,7 @@ public class MonitoringRunningExamList implements TemplateComposer {
|
|||
Exam::getName)
|
||||
.withFilter(this.nameFilter)
|
||||
.sortable())
|
||||
.withColumn(new ColumnDefinition<>(
|
||||
.withColumn(new ColumnDefinition<Exam>(
|
||||
Domain.EXAM.ATTR_TYPE,
|
||||
COLUMN_TITLE_TYPE_KEY,
|
||||
this.resourceService::localizedExamTypeName)
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
package ch.ethz.seb.sebserver.gui.content;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
|
@ -48,7 +49,7 @@ public final class SebExamConfigImport {
|
|||
|
||||
dialog.open(
|
||||
SebExamConfigPropForm.FORM_IMPORT_TEXT_KEY,
|
||||
formHandle -> doImport(
|
||||
(Consumer<FormHandle<ConfigurationNode>>) formHandle -> doImport(
|
||||
pageService,
|
||||
formHandle),
|
||||
importFormContext::cancelUpload,
|
||||
|
|
|
@ -25,6 +25,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.ExamConfigurationMap;
|
||||
import ch.ethz.seb.sebserver.gbl.model.exam.QuizData;
|
||||
import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigKey;
|
||||
import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode;
|
||||
import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode.ConfigurationStatus;
|
||||
|
@ -38,6 +39,7 @@ 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.PageService.PageActionBuilder;
|
||||
import ch.ethz.seb.sebserver.gui.service.page.TemplateComposer;
|
||||
import ch.ethz.seb.sebserver.gui.service.page.impl.ModalInputDialog;
|
||||
import ch.ethz.seb.sebserver.gui.service.page.impl.PageAction;
|
||||
|
@ -45,12 +47,15 @@ import ch.ethz.seb.sebserver.gui.service.remote.download.DownloadService;
|
|||
import ch.ethz.seb.sebserver.gui.service.remote.download.SebExamConfigPlaintextDownload;
|
||||
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.exam.GetExamConfigMappingsPage;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.ExportConfigKey;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.GetExamConfigNode;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.NewExamConfig;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.SaveExamConfig;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.CurrentUser;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.CurrentUser.EntityGrantCheck;
|
||||
import ch.ethz.seb.sebserver.gui.table.ColumnDefinition;
|
||||
import ch.ethz.seb.sebserver.gui.table.EntityTable;
|
||||
import ch.ethz.seb.sebserver.gui.widget.WidgetFactory;
|
||||
import ch.ethz.seb.sebserver.gui.widget.WidgetFactory.CustomVariant;
|
||||
|
||||
|
@ -88,7 +93,6 @@ public class SebExamConfigPropForm implements TemplateComposer {
|
|||
|
||||
static final LocTextKey FORM_COPY_TEXT_KEY =
|
||||
new LocTextKey("sebserver.examconfig.action.copy");
|
||||
|
||||
static final LocTextKey SAVE_CONFIRM_STATE_CHANGE_WHILE_ATTACHED =
|
||||
new LocTextKey("sebserver.examconfig.action.state-change.confirm");
|
||||
|
||||
|
@ -199,7 +203,8 @@ public class SebExamConfigPropForm implements TemplateComposer {
|
|||
final boolean settingsReadonly = examConfig.status == ConfigurationStatus.IN_USE;
|
||||
final UrlLauncher urlLauncher = RWT.getClient().getService(UrlLauncher.class);
|
||||
final PageContext actionContext = formContext.clearEntityKeys();
|
||||
this.pageService.pageActionBuilder(actionContext)
|
||||
final PageActionBuilder actionBuilder = this.pageService.pageActionBuilder(actionContext);
|
||||
actionBuilder
|
||||
|
||||
.newAction(ActionDefinition.SEB_EXAM_CONFIG_NEW)
|
||||
.publishIf(() -> writeGrant && isReadonly)
|
||||
|
@ -258,6 +263,45 @@ public class SebExamConfigPropForm implements TemplateComposer {
|
|||
.withExec(this.pageService.backToCurrentFunction())
|
||||
.publishIf(() -> !isReadonly);
|
||||
|
||||
if (isAttachedToExam) {
|
||||
final EntityTable<ExamConfigurationMap> table =
|
||||
this.pageService.entityTableBuilder(this.restService.getRestCall(GetExamConfigMappingsPage.class))
|
||||
.withRestCallAdapter(restCall -> restCall.withQueryParam(
|
||||
ExamConfigurationMap.FILTER_ATTR_CONFIG_ID, examConfig.getModelId()))
|
||||
.withPaging(1)
|
||||
.hideNavigation()
|
||||
.withRowDecorator(ExamList.decorateOnExamMapConsistency(this.pageService))
|
||||
|
||||
.withColumn(new ColumnDefinition<>(
|
||||
QuizData.QUIZ_ATTR_NAME,
|
||||
ExamList.COLUMN_TITLE_NAME_KEY,
|
||||
ExamConfigurationMap::getExamName))
|
||||
|
||||
.withColumn(new ColumnDefinition<>(
|
||||
QuizData.QUIZ_ATTR_START_TIME,
|
||||
new LocTextKey(
|
||||
ExamList.EXAM_LIST_COLUMN_STARTTIME,
|
||||
this.pageService.getI18nSupport().getUsersTimeZoneTitleSuffix()),
|
||||
ExamConfigurationMap::getExamStartTime))
|
||||
|
||||
.withColumn(new ColumnDefinition<ExamConfigurationMap>(
|
||||
Domain.EXAM.ATTR_TYPE,
|
||||
ExamList.COLUMN_TITLE_TYPE_KEY,
|
||||
resourceService::localizedExamTypeName))
|
||||
|
||||
.withDefaultAction(actionBuilder
|
||||
.newAction(ActionDefinition.EXAM_VIEW_FROM_LIST)
|
||||
.create())
|
||||
|
||||
.compose(pageContext.copyOf(content));
|
||||
|
||||
actionBuilder
|
||||
|
||||
.newAction(ActionDefinition.EXAM_VIEW_FROM_LIST)
|
||||
.withSelect(table::getSelection, PageAction::applySingleSelection,
|
||||
ExamList.EMPTY_SELECTION_TEXT_KEY)
|
||||
.publishIf(table::hasAnyContent);
|
||||
}
|
||||
}
|
||||
|
||||
private LocTextKey stateChangeConfirm(
|
||||
|
|
|
@ -447,6 +447,15 @@ public class ResourceService {
|
|||
.getText(SEB_CONNECTION_STATUS_KEY_PREFIX + name, name);
|
||||
}
|
||||
|
||||
public String localizedExamTypeName(final ExamConfigurationMap examMap) {
|
||||
if (examMap.examType == null) {
|
||||
return Constants.EMPTY_NOTE;
|
||||
}
|
||||
|
||||
return this.i18nSupport
|
||||
.getText(ResourceService.EXAM_TYPE_PREFIX + examMap.examType.name());
|
||||
}
|
||||
|
||||
public String localizedExamTypeName(final Exam exam) {
|
||||
if (exam.type == null) {
|
||||
return Constants.EMPTY_NOTE;
|
||||
|
|
|
@ -13,6 +13,7 @@ import java.util.Arrays;
|
|||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.eclipse.swt.SWT;
|
||||
|
@ -209,15 +210,14 @@ public class CompositeTableFieldBuilder extends AbstractTableFieldBuilder {
|
|||
if (this.tableContext.getViewContext().readonly) {
|
||||
dialog.open(
|
||||
new LocTextKey(ExamConfigurationService.ATTRIBUTE_LABEL_LOC_TEXT_PREFIX + row),
|
||||
rowVals -> {
|
||||
},
|
||||
() -> {
|
||||
},
|
||||
builder);
|
||||
} else {
|
||||
dialog.open(
|
||||
new LocTextKey(ExamConfigurationService.ATTRIBUTE_LABEL_LOC_TEXT_PREFIX + row),
|
||||
rowVals -> applyFormValues(this.values, rowVals, selectionIndex),
|
||||
(Consumer<Map<Long, TableValue>>) rowVals -> applyFormValues(
|
||||
this.values,
|
||||
rowVals,
|
||||
selectionIndex),
|
||||
() -> this.tableContext.getValueChangeListener()
|
||||
.tableChanged(extractTableValue(this.values)),
|
||||
builder);
|
||||
|
|
|
@ -11,6 +11,7 @@ package ch.ethz.seb.sebserver.gui.service.examconfig.impl;
|
|||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
|
@ -199,7 +200,10 @@ public class TableFieldBuilder extends AbstractTableFieldBuilder {
|
|||
ExamConfigurationService.getTablePopupTitleKey(
|
||||
this.attribute,
|
||||
this.tableContext.getViewContext().i18nSupport),
|
||||
rowVals -> applyFormValues(this.values, rowVals, selectionIndex),
|
||||
(Consumer<Map<Long, TableValue>>) rowVals -> applyFormValues(
|
||||
this.values,
|
||||
rowVals,
|
||||
selectionIndex),
|
||||
() -> this.tableContext.getValueChangeListener()
|
||||
.tableChanged(extractTableValue(this.values)),
|
||||
builder);
|
||||
|
|
|
@ -67,6 +67,17 @@ public class ModalInputDialog<T> extends Dialog {
|
|||
return this;
|
||||
}
|
||||
|
||||
public void open(
|
||||
final LocTextKey title,
|
||||
final ModalInputDialogComposer<T> contentComposer) {
|
||||
|
||||
open(
|
||||
title,
|
||||
(Predicate<T>) t -> true,
|
||||
() -> {
|
||||
}, contentComposer);
|
||||
}
|
||||
|
||||
public void open(
|
||||
final LocTextKey title,
|
||||
final Consumer<T> callback,
|
||||
|
|
|
@ -55,7 +55,6 @@ import ch.ethz.seb.sebserver.gui.service.page.impl.PageAction;
|
|||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCall;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.CurrentUser;
|
||||
import ch.ethz.seb.sebserver.gui.widget.WidgetFactory;
|
||||
import ch.ethz.seb.sebserver.gui.widget.WidgetFactory.CustomVariant;
|
||||
import ch.ethz.seb.sebserver.gui.widget.WidgetFactory.ImageIcon;
|
||||
|
||||
public class EntityTable<ROW extends Entity> {
|
||||
|
|
|
@ -30,6 +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.exam.Exam;
|
||||
import ch.ethz.seb.sebserver.gbl.model.exam.Exam.ExamType;
|
||||
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;
|
||||
|
@ -49,6 +51,7 @@ import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.BulkAction;
|
|||
import ch.ethz.seb.sebserver.webservice.servicelayer.client.ClientCredentialService;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.DAOLoggingSupport;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ExamConfigurationMapDAO;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ExamDAO;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.FilterMap;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ResourceNotFoundException;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.TransactionHandler;
|
||||
|
@ -62,17 +65,20 @@ public class ExamConfigurationMapDAOImpl implements ExamConfigurationMapDAO {
|
|||
private final ExamConfigurationMapRecordMapper examConfigurationMapRecordMapper;
|
||||
private final ConfigurationNodeRecordMapper configurationNodeRecordMapper;
|
||||
private final ClientCredentialService clientCredentialService;
|
||||
private final ExamDAO examDAO;
|
||||
|
||||
protected ExamConfigurationMapDAOImpl(
|
||||
final ExamRecordMapper examRecordMapper,
|
||||
final ExamConfigurationMapRecordMapper examConfigurationMapRecordMapper,
|
||||
final ConfigurationNodeRecordMapper configurationNodeRecordMapper,
|
||||
final ClientCredentialService clientCredentialService) {
|
||||
final ClientCredentialService clientCredentialService,
|
||||
final ExamDAO examDAO) {
|
||||
|
||||
this.examRecordMapper = examRecordMapper;
|
||||
this.examConfigurationMapRecordMapper = examConfigurationMapRecordMapper;
|
||||
this.configurationNodeRecordMapper = configurationNodeRecordMapper;
|
||||
this.clientCredentialService = clientCredentialService;
|
||||
this.examDAO = examDAO;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -340,20 +346,27 @@ public class ExamConfigurationMapDAOImpl implements ExamConfigurationMapDAO {
|
|||
private Result<ExamConfigurationMap> toDomainModel(final ExamConfigurationMapRecord record) {
|
||||
return Result.tryCatch(() -> {
|
||||
|
||||
final ConfigurationNodeRecord selectByPrimaryKey = this.configurationNodeRecordMapper
|
||||
final ConfigurationNodeRecord config = this.configurationNodeRecordMapper
|
||||
.selectByPrimaryKey(record.getConfigurationNodeId());
|
||||
final String status = selectByPrimaryKey.getStatus();
|
||||
final String status = config.getStatus();
|
||||
|
||||
final Exam exam = this.examDAO.byPK(record.getExamId())
|
||||
.getOr(null);
|
||||
|
||||
return new ExamConfigurationMap(
|
||||
record.getId(),
|
||||
record.getInstitutionId(),
|
||||
record.getExamId(),
|
||||
(exam != null) ? exam.name : null,
|
||||
(exam != null) ? exam.description : null,
|
||||
(exam != null) ? exam.startTime : null,
|
||||
(exam != null) ? exam.type : ExamType.UNDEFINED,
|
||||
record.getConfigurationNodeId(),
|
||||
record.getUserNames(),
|
||||
null,
|
||||
null,
|
||||
selectByPrimaryKey.getName(),
|
||||
selectByPrimaryKey.getDescription(),
|
||||
config.getName(),
|
||||
config.getDescription(),
|
||||
(StringUtils.isNotBlank(status)) ? ConfigurationStatus.valueOf(status) : null);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -320,7 +320,9 @@ public abstract class EntityController<T extends Entity, M extends Entity> {
|
|||
BulkActionType.HARD_DELETE,
|
||||
entityType,
|
||||
new EntityName(modelId, entityType, entity.getName()))))
|
||||
|
||||
.flatMap(this::logBulkAction)
|
||||
.flatMap(this::notifyDeleted)
|
||||
.getOrThrow();
|
||||
}
|
||||
|
||||
|
@ -370,6 +372,10 @@ public abstract class EntityController<T extends Entity, M extends Entity> {
|
|||
return Result.of(entity);
|
||||
}
|
||||
|
||||
protected Result<EntityProcessingReport> notifyDeleted(final EntityProcessingReport deletionReport) {
|
||||
return Result.of(deletionReport);
|
||||
}
|
||||
|
||||
protected Result<T> checkReadAccess(final T entity) {
|
||||
final GrantEntity grantEntity = toGrantEntity(entity);
|
||||
if (grantEntity != null) {
|
||||
|
|
|
@ -20,6 +20,7 @@ import ch.ethz.seb.sebserver.gbl.api.APIMessage.ErrorMessage;
|
|||
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.EntityProcessingReport;
|
||||
import ch.ethz.seb.sebserver.gbl.model.GrantEntity;
|
||||
import ch.ethz.seb.sebserver.gbl.model.exam.ExamConfigurationMap;
|
||||
import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode;
|
||||
|
@ -119,7 +120,7 @@ public class ExamConfigurationMappingController extends EntityController<ExamCon
|
|||
// update the attached configurations state to "In Use"
|
||||
return this.configurationNodeDAO.save(new ConfigurationNode(
|
||||
entity.configurationNodeId,
|
||||
entity.institutionId,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
|
@ -129,6 +130,26 @@ public class ExamConfigurationMappingController extends EntityController<ExamCon
|
|||
.map(config -> entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Result<EntityProcessingReport> notifyDeleted(final EntityProcessingReport deletionReport) {
|
||||
// update the attached configurations state to "Ready"
|
||||
deletionReport.source
|
||||
.stream()
|
||||
.forEach(entityKey -> {
|
||||
this.configurationNodeDAO.save(new ConfigurationNode(
|
||||
Long.parseLong(entityKey.modelId),
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
ConfigurationStatus.READY_TO_USE));
|
||||
});
|
||||
|
||||
return super.notifyDeleted(deletionReport);
|
||||
}
|
||||
|
||||
private ExamConfigurationMap checkPasswordMatch(final ExamConfigurationMap entity) {
|
||||
if (entity.hasEncryptionSecret() && !entity.encryptSecret.equals(entity.confirmEncryptSecret)) {
|
||||
throw new APIMessageException(APIMessage.fieldValidationError(
|
||||
|
|
Loading…
Add table
Reference in a new issue