SEBSERV-73 Exam Config changes and test fixes
This commit is contained in:
parent
83985cdbf7
commit
fb13c62eeb
19 changed files with 256 additions and 121 deletions
|
@ -9,6 +9,7 @@
|
||||||
package ch.ethz.seb.sebserver.gui.content;
|
package ch.ethz.seb.sebserver.gui.content;
|
||||||
|
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
import java.util.function.Predicate;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
import org.eclipse.swt.widgets.Composite;
|
import org.eclipse.swt.widgets.Composite;
|
||||||
|
@ -19,6 +20,7 @@ import ch.ethz.seb.sebserver.gbl.model.EntityKey;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigCopyInfo;
|
import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigCopyInfo;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode;
|
import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode;
|
||||||
import ch.ethz.seb.sebserver.gbl.util.Utils;
|
import ch.ethz.seb.sebserver.gbl.util.Utils;
|
||||||
|
import ch.ethz.seb.sebserver.gui.content.action.ActionDefinition;
|
||||||
import ch.ethz.seb.sebserver.gui.form.FormBuilder;
|
import ch.ethz.seb.sebserver.gui.form.FormBuilder;
|
||||||
import ch.ethz.seb.sebserver.gui.form.FormHandle;
|
import ch.ethz.seb.sebserver.gui.form.FormHandle;
|
||||||
import ch.ethz.seb.sebserver.gui.service.page.ModalInputDialogComposer;
|
import ch.ethz.seb.sebserver.gui.service.page.ModalInputDialogComposer;
|
||||||
|
@ -30,7 +32,7 @@ import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.Co
|
||||||
|
|
||||||
public final class SebExamConfigCopy {
|
public final class SebExamConfigCopy {
|
||||||
|
|
||||||
static Function<PageAction, PageAction> importConfigFunction(
|
static Function<PageAction, PageAction> copyConfigFunction(
|
||||||
final PageService pageService,
|
final PageService pageService,
|
||||||
final PageContext pageContext) {
|
final PageContext pageContext) {
|
||||||
|
|
||||||
|
@ -46,12 +48,14 @@ public final class SebExamConfigCopy {
|
||||||
pageService,
|
pageService,
|
||||||
action.pageContext());
|
action.pageContext());
|
||||||
|
|
||||||
|
final Predicate<FormHandle<ConfigCopyInfo>> doCopy = formHandle -> doCopy(
|
||||||
|
pageService,
|
||||||
|
pageContext,
|
||||||
|
formHandle);
|
||||||
|
|
||||||
dialog.open(
|
dialog.open(
|
||||||
SebExamConfigPropForm.FORM_COPY_TEXT_KEY,
|
SebExamConfigPropForm.FORM_COPY_TEXT_KEY,
|
||||||
formHandle -> doCopy(
|
doCopy,
|
||||||
pageService,
|
|
||||||
pageContext,
|
|
||||||
formHandle),
|
|
||||||
Utils.EMPTY_EXECUTION,
|
Utils.EMPTY_EXECUTION,
|
||||||
formContext);
|
formContext);
|
||||||
|
|
||||||
|
@ -59,7 +63,7 @@ public final class SebExamConfigCopy {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final void doCopy(
|
private static final boolean doCopy(
|
||||||
final PageService pageService,
|
final PageService pageService,
|
||||||
final PageContext pageContext,
|
final PageContext pageContext,
|
||||||
final FormHandle<ConfigCopyInfo> formHandle) {
|
final FormHandle<ConfigCopyInfo> formHandle) {
|
||||||
|
@ -67,13 +71,21 @@ public final class SebExamConfigCopy {
|
||||||
final ConfigurationNode newConfig = pageService.getRestService().getBuilder(CopyConfiguration.class)
|
final ConfigurationNode newConfig = pageService.getRestService().getBuilder(CopyConfiguration.class)
|
||||||
.withFormBinding(formHandle.getFormBinding())
|
.withFormBinding(formHandle.getFormBinding())
|
||||||
.call()
|
.call()
|
||||||
.getOrThrow();
|
.onError(formHandle::handleError)
|
||||||
|
.getOr(null);
|
||||||
|
|
||||||
final PageAction viewNewConfig = pageService.pageActionBuilder(pageContext.copy().clearAttributes())
|
if (newConfig == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
final PageAction viewNewConfig = pageService.pageActionBuilder(pageContext)
|
||||||
|
.newAction(ActionDefinition.SEB_EXAM_CONFIG_VIEW_PROP)
|
||||||
.withEntityKey(new EntityKey(newConfig.id, EntityType.CONFIGURATION_NODE))
|
.withEntityKey(new EntityKey(newConfig.id, EntityType.CONFIGURATION_NODE))
|
||||||
.create();
|
.create();
|
||||||
|
|
||||||
pageService.executePageAction(viewNewConfig);
|
pageService.executePageAction(viewNewConfig);
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final class CopyFormContext implements ModalInputDialogComposer<FormHandle<ConfigCopyInfo>> {
|
private static final class CopyFormContext implements ModalInputDialogComposer<FormHandle<ConfigCopyInfo>> {
|
||||||
|
@ -103,6 +115,9 @@ public final class SebExamConfigCopy {
|
||||||
Domain.CONFIGURATION_NODE.ATTR_DESCRIPTION,
|
Domain.CONFIGURATION_NODE.ATTR_DESCRIPTION,
|
||||||
SebExamConfigPropForm.FORM_DESCRIPTION_TEXT_KEY)
|
SebExamConfigPropForm.FORM_DESCRIPTION_TEXT_KEY)
|
||||||
.asArea())
|
.asArea())
|
||||||
|
.addField(FormBuilder.checkbox(
|
||||||
|
ConfigCopyInfo.ATTR_COPY_WITH_HISTORY,
|
||||||
|
SebExamConfigPropForm.FORM_HISTORY_TEXT_KEY))
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
return () -> formHandle;
|
return () -> formHandle;
|
||||||
|
|
|
@ -69,6 +69,8 @@ public class SebExamConfigPropForm implements TemplateComposer {
|
||||||
new LocTextKey("sebserver.examconfig.form.name");
|
new LocTextKey("sebserver.examconfig.form.name");
|
||||||
static final LocTextKey FORM_DESCRIPTION_TEXT_KEY =
|
static final LocTextKey FORM_DESCRIPTION_TEXT_KEY =
|
||||||
new LocTextKey("sebserver.examconfig.form.description");
|
new LocTextKey("sebserver.examconfig.form.description");
|
||||||
|
static final LocTextKey FORM_HISTORY_TEXT_KEY =
|
||||||
|
new LocTextKey("sebserver.examconfig.form.with-history");
|
||||||
static final LocTextKey FORM_TEMPLATE_TEXT_KEY =
|
static final LocTextKey FORM_TEMPLATE_TEXT_KEY =
|
||||||
new LocTextKey("sebserver.examconfig.form.template");
|
new LocTextKey("sebserver.examconfig.form.template");
|
||||||
static final LocTextKey FORM_STATUS_TEXT_KEY =
|
static final LocTextKey FORM_STATUS_TEXT_KEY =
|
||||||
|
@ -196,7 +198,8 @@ public class SebExamConfigPropForm implements TemplateComposer {
|
||||||
|
|
||||||
final boolean settingsReadonly = examConfig.status == ConfigurationStatus.IN_USE;
|
final boolean settingsReadonly = examConfig.status == ConfigurationStatus.IN_USE;
|
||||||
final UrlLauncher urlLauncher = RWT.getClient().getService(UrlLauncher.class);
|
final UrlLauncher urlLauncher = RWT.getClient().getService(UrlLauncher.class);
|
||||||
this.pageService.pageActionBuilder(formContext.clearEntityKeys())
|
final PageContext actionContext = formContext.clearEntityKeys();
|
||||||
|
this.pageService.pageActionBuilder(actionContext)
|
||||||
|
|
||||||
.newAction(ActionDefinition.SEB_EXAM_CONFIG_NEW)
|
.newAction(ActionDefinition.SEB_EXAM_CONFIG_NEW)
|
||||||
.publishIf(() -> writeGrant && isReadonly)
|
.publishIf(() -> writeGrant && isReadonly)
|
||||||
|
@ -237,6 +240,12 @@ public class SebExamConfigPropForm implements TemplateComposer {
|
||||||
.noEventPropagation()
|
.noEventPropagation()
|
||||||
.publishIf(() -> modifyGrant && isReadonly)
|
.publishIf(() -> modifyGrant && isReadonly)
|
||||||
|
|
||||||
|
.newAction(ActionDefinition.SEB_EXAM_CONFIG_COPY_CONFIG)
|
||||||
|
.withEntityKey(entityKey)
|
||||||
|
.withExec(SebExamConfigCopy.copyConfigFunction(this.pageService, actionContext))
|
||||||
|
.noEventPropagation()
|
||||||
|
.publishIf(() -> modifyGrant && isReadonly)
|
||||||
|
|
||||||
.newAction(ActionDefinition.SEB_EXAM_CONFIG_PROP_SAVE)
|
.newAction(ActionDefinition.SEB_EXAM_CONFIG_PROP_SAVE)
|
||||||
.withEntityKey(entityKey)
|
.withEntityKey(entityKey)
|
||||||
.withExec(formHandle::processFormSave)
|
.withExec(formHandle::processFormSave)
|
||||||
|
|
|
@ -155,6 +155,7 @@ public class SebExamConfigSettingsForm implements TemplateComposer {
|
||||||
return action;
|
return action;
|
||||||
})
|
})
|
||||||
.withSuccess(KEY_SAVE_TO_HISTORY_SUCCESS)
|
.withSuccess(KEY_SAVE_TO_HISTORY_SUCCESS)
|
||||||
|
.ignoreMoveAwayFromEdit()
|
||||||
.publishIf(() -> examConfigGrant.iw() && !readonly)
|
.publishIf(() -> examConfigGrant.iw() && !readonly)
|
||||||
|
|
||||||
.newAction(ActionDefinition.SEB_EXAM_CONFIG_UNDO)
|
.newAction(ActionDefinition.SEB_EXAM_CONFIG_UNDO)
|
||||||
|
@ -168,6 +169,7 @@ public class SebExamConfigSettingsForm implements TemplateComposer {
|
||||||
return action;
|
return action;
|
||||||
})
|
})
|
||||||
.withSuccess(KEY_UNDO_SUCCESS)
|
.withSuccess(KEY_UNDO_SUCCESS)
|
||||||
|
.ignoreMoveAwayFromEdit()
|
||||||
.publishIf(() -> examConfigGrant.iw() && !readonly)
|
.publishIf(() -> examConfigGrant.iw() && !readonly)
|
||||||
|
|
||||||
.newAction(ActionDefinition.SEB_EXAM_CONFIG_VIEW_PROP)
|
.newAction(ActionDefinition.SEB_EXAM_CONFIG_VIEW_PROP)
|
||||||
|
|
|
@ -392,7 +392,6 @@ public enum ActionDefinition {
|
||||||
SEB_EXAM_CONFIG_EXPORT_PLAIN_XML(
|
SEB_EXAM_CONFIG_EXPORT_PLAIN_XML(
|
||||||
new LocTextKey("sebserver.examconfig.action.export.plainxml"),
|
new LocTextKey("sebserver.examconfig.action.export.plainxml"),
|
||||||
ImageIcon.EXPORT,
|
ImageIcon.EXPORT,
|
||||||
PageStateDefinitionImpl.SEB_EXAM_CONFIG_VIEW,
|
|
||||||
ActionCategory.FORM),
|
ActionCategory.FORM),
|
||||||
SEB_EXAM_CONFIG_GET_CONFIG_KEY(
|
SEB_EXAM_CONFIG_GET_CONFIG_KEY(
|
||||||
new LocTextKey("sebserver.examconfig.action.get-config-key"),
|
new LocTextKey("sebserver.examconfig.action.get-config-key"),
|
||||||
|
@ -402,12 +401,9 @@ public enum ActionDefinition {
|
||||||
new LocTextKey("sebserver.examconfig.action.import-config"),
|
new LocTextKey("sebserver.examconfig.action.import-config"),
|
||||||
ImageIcon.IMPORT,
|
ImageIcon.IMPORT,
|
||||||
ActionCategory.FORM),
|
ActionCategory.FORM),
|
||||||
|
|
||||||
// TODO copy config action
|
|
||||||
// TODO
|
|
||||||
SEB_EXAM_CONFIG_COPY_CONFIG(
|
SEB_EXAM_CONFIG_COPY_CONFIG(
|
||||||
new LocTextKey("sebserver.examconfig.action.copy-config"),
|
new LocTextKey("sebserver.examconfig.action.copy"),
|
||||||
ImageIcon.IMPORT,
|
ImageIcon.COPY,
|
||||||
ActionCategory.FORM),
|
ActionCategory.FORM),
|
||||||
|
|
||||||
SEB_EXAM_CONFIG_MODIFY_FROM_LIST(
|
SEB_EXAM_CONFIG_MODIFY_FROM_LIST(
|
||||||
|
|
|
@ -0,0 +1,52 @@
|
||||||
|
/*
|
||||||
|
* 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.form;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.BooleanUtils;
|
||||||
|
import org.eclipse.swt.SWT;
|
||||||
|
import org.eclipse.swt.layout.GridData;
|
||||||
|
import org.eclipse.swt.widgets.Button;
|
||||||
|
import org.eclipse.swt.widgets.Composite;
|
||||||
|
import org.eclipse.swt.widgets.Label;
|
||||||
|
|
||||||
|
import ch.ethz.seb.sebserver.gui.service.i18n.LocTextKey;
|
||||||
|
|
||||||
|
public class CheckboxFieldBuilder extends FieldBuilder<String> {
|
||||||
|
|
||||||
|
protected CheckboxFieldBuilder(final String name, final LocTextKey label, final String value) {
|
||||||
|
super(name, label, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void build(final FormBuilder builder) {
|
||||||
|
final boolean readonly = builder.readonly || this.readonly;
|
||||||
|
final Label lab = builder.labelLocalized(
|
||||||
|
builder.formParent,
|
||||||
|
this.label,
|
||||||
|
this.defaultLabel,
|
||||||
|
this.spanLabel);
|
||||||
|
|
||||||
|
final Composite fieldGrid = Form.createFieldGrid(builder.formParent, this.spanInput);
|
||||||
|
final Button checkbox = builder.widgetFactory.buttonLocalized(
|
||||||
|
fieldGrid,
|
||||||
|
SWT.CHECK,
|
||||||
|
null, null);
|
||||||
|
|
||||||
|
final GridData gridData = new GridData(SWT.FILL, SWT.TOP, true, true);
|
||||||
|
checkbox.setLayoutData(gridData);
|
||||||
|
checkbox.setSelection(BooleanUtils.toBoolean(this.value));
|
||||||
|
|
||||||
|
if (readonly) {
|
||||||
|
checkbox.setEnabled(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.form.putField(this.name, lab, checkbox);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -18,12 +18,14 @@ import java.util.function.BiConsumer;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.BooleanUtils;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.eclipse.rap.rwt.RWT;
|
import org.eclipse.rap.rwt.RWT;
|
||||||
import org.eclipse.swt.SWT;
|
import org.eclipse.swt.SWT;
|
||||||
import org.eclipse.swt.graphics.Color;
|
import org.eclipse.swt.graphics.Color;
|
||||||
import org.eclipse.swt.layout.GridData;
|
import org.eclipse.swt.layout.GridData;
|
||||||
import org.eclipse.swt.layout.GridLayout;
|
import org.eclipse.swt.layout.GridLayout;
|
||||||
|
import org.eclipse.swt.widgets.Button;
|
||||||
import org.eclipse.swt.widgets.Composite;
|
import org.eclipse.swt.widgets.Composite;
|
||||||
import org.eclipse.swt.widgets.Control;
|
import org.eclipse.swt.widgets.Control;
|
||||||
import org.eclipse.swt.widgets.Label;
|
import org.eclipse.swt.widgets.Label;
|
||||||
|
@ -130,6 +132,11 @@ public final class Form implements FormBinding {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Form putField(final String name, final Label label, final Button checkbox) {
|
||||||
|
this.formFields.add(name, createAccessor(label, checkbox, null));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
void putField(final String name, final Label label, final Selection field, final Label errorLabel) {
|
void putField(final String name, final Label label, final Selection field, final Label errorLabel) {
|
||||||
this.formFields.add(name, createAccessor(label, field, errorLabel));
|
this.formFields.add(name, createAccessor(label, field, errorLabel));
|
||||||
}
|
}
|
||||||
|
@ -266,6 +273,12 @@ public final class Form implements FormBinding {
|
||||||
@Override public void setStringValue(final String value) {text.setText(value);}
|
@Override public void setStringValue(final String value) {text.setText(value);}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
private FormFieldAccessor createAccessor(final Label label, final Button checkbox, final Label errorLabel) {
|
||||||
|
return new FormFieldAccessor(label, checkbox, errorLabel) {
|
||||||
|
@Override public String getStringValue() {return BooleanUtils.toStringTrueFalse(checkbox.getSelection());}
|
||||||
|
@Override public void setStringValue(final String value) {checkbox.setSelection(BooleanUtils.toBoolean(value));}
|
||||||
|
};
|
||||||
|
}
|
||||||
private FormFieldAccessor createAccessor(final Label label, final Selection selection, final Label errorLabel) {
|
private FormFieldAccessor createAccessor(final Label label, final Selection selection, final Label errorLabel) {
|
||||||
switch (selection.type()) {
|
switch (selection.type()) {
|
||||||
case MULTI:
|
case MULTI:
|
||||||
|
|
|
@ -194,6 +194,14 @@ public class FormBuilder {
|
||||||
empty.setText("");
|
empty.setText("");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static CheckboxFieldBuilder checkbox(final String name, final LocTextKey label) {
|
||||||
|
return new CheckboxFieldBuilder(name, label, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static CheckboxFieldBuilder checkbox(final String name, final LocTextKey label, final String value) {
|
||||||
|
return new CheckboxFieldBuilder(name, label, value);
|
||||||
|
}
|
||||||
|
|
||||||
public static TextFieldBuilder text(final String name, final LocTextKey label) {
|
public static TextFieldBuilder text(final String name, final LocTextKey label) {
|
||||||
return new TextFieldBuilder(name, label, null);
|
return new TextFieldBuilder(name, label, null);
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
package ch.ethz.seb.sebserver.gui.service.page.impl;
|
package ch.ethz.seb.sebserver.gui.service.page.impl;
|
||||||
|
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
import java.util.function.Predicate;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
import org.eclipse.rap.rwt.RWT;
|
import org.eclipse.rap.rwt.RWT;
|
||||||
|
@ -72,6 +73,20 @@ public class ModalInputDialog<T> extends Dialog {
|
||||||
final Runnable cancelCallback,
|
final Runnable cancelCallback,
|
||||||
final ModalInputDialogComposer<T> contentComposer) {
|
final ModalInputDialogComposer<T> contentComposer) {
|
||||||
|
|
||||||
|
final Predicate<T> predicate = result -> {
|
||||||
|
callback.accept(result);
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
open(title, predicate, cancelCallback, contentComposer);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void open(
|
||||||
|
final LocTextKey title,
|
||||||
|
final Predicate<T> callback,
|
||||||
|
final Runnable cancelCallback,
|
||||||
|
final ModalInputDialogComposer<T> contentComposer) {
|
||||||
|
|
||||||
// Create the selection dialog window
|
// Create the selection dialog window
|
||||||
final Shell shell = new Shell(getParent(), getStyle());
|
final Shell shell = new Shell(getParent(), getStyle());
|
||||||
shell.setText(getText());
|
shell.setText(getText());
|
||||||
|
@ -98,8 +113,9 @@ public class ModalInputDialog<T> extends Dialog {
|
||||||
ok.addListener(SWT.Selection, event -> {
|
ok.addListener(SWT.Selection, event -> {
|
||||||
if (valueSuppier != null) {
|
if (valueSuppier != null) {
|
||||||
final T result = valueSuppier.get();
|
final T result = valueSuppier.get();
|
||||||
callback.accept(result);
|
if (callback.test(result)) {
|
||||||
shell.close();
|
shell.close();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
shell.close();
|
shell.close();
|
||||||
}
|
}
|
||||||
|
|
|
@ -71,6 +71,7 @@ public class WidgetFactory {
|
||||||
EDIT("edit.png"),
|
EDIT("edit.png"),
|
||||||
EDIT_SETTINGS("settings.png"),
|
EDIT_SETTINGS("settings.png"),
|
||||||
TEST("test.png"),
|
TEST("test.png"),
|
||||||
|
COPY("copy.png"),
|
||||||
IMPORT("import.png"),
|
IMPORT("import.png"),
|
||||||
CANCEL("cancel.png"),
|
CANCEL("cancel.png"),
|
||||||
CANCEL_EDIT("cancelEdit.png"),
|
CANCEL_EDIT("cancelEdit.png"),
|
||||||
|
|
|
@ -18,6 +18,7 @@ import java.util.function.Function;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import org.apache.commons.lang3.BooleanUtils;
|
import org.apache.commons.lang3.BooleanUtils;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.joda.time.DateTime;
|
import org.joda.time.DateTime;
|
||||||
import org.joda.time.DateTimeZone;
|
import org.joda.time.DateTimeZone;
|
||||||
import org.mybatis.dynamic.sql.SqlBuilder;
|
import org.mybatis.dynamic.sql.SqlBuilder;
|
||||||
|
@ -32,6 +33,7 @@ import org.springframework.stereotype.Component;
|
||||||
import ch.ethz.seb.sebserver.gbl.api.APIMessage.FieldValidationException;
|
import ch.ethz.seb.sebserver.gbl.api.APIMessage.FieldValidationException;
|
||||||
import ch.ethz.seb.sebserver.gbl.api.EntityType;
|
import ch.ethz.seb.sebserver.gbl.api.EntityType;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.sebconfig.AttributeType;
|
import ch.ethz.seb.sebserver.gbl.model.sebconfig.AttributeType;
|
||||||
|
import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigCopyInfo;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.sebconfig.Configuration;
|
import ch.ethz.seb.sebserver.gbl.model.sebconfig.Configuration;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationAttribute;
|
import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationAttribute;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode;
|
import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode;
|
||||||
|
@ -55,6 +57,7 @@ import ch.ethz.seb.sebserver.webservice.datalayer.batis.model.ConfigurationNodeR
|
||||||
import ch.ethz.seb.sebserver.webservice.datalayer.batis.model.ConfigurationRecord;
|
import ch.ethz.seb.sebserver.webservice.datalayer.batis.model.ConfigurationRecord;
|
||||||
import ch.ethz.seb.sebserver.webservice.datalayer.batis.model.ConfigurationValueRecord;
|
import ch.ethz.seb.sebserver.webservice.datalayer.batis.model.ConfigurationValueRecord;
|
||||||
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ResourceNotFoundException;
|
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ResourceNotFoundException;
|
||||||
|
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.TransactionHandler;
|
||||||
|
|
||||||
/** This service is internally used to implement MyBatis batch functionality for the most
|
/** This service is internally used to implement MyBatis batch functionality for the most
|
||||||
* intensive write operation on Configuration domain. */
|
* intensive write operation on Configuration domain. */
|
||||||
|
@ -317,7 +320,99 @@ class ConfigurationDAOBatchService {
|
||||||
.flatMap(ConfigurationDAOImpl::toDomainModel);
|
.flatMap(ConfigurationDAOImpl::toDomainModel);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<Configuration> copyConfiguration(
|
Result<ConfigurationNode> createCopy(
|
||||||
|
final Long institutionId,
|
||||||
|
final String newOwner,
|
||||||
|
final ConfigCopyInfo copyInfo) {
|
||||||
|
|
||||||
|
return Result.tryCatch(() -> {
|
||||||
|
final ConfigurationNodeRecord sourceNode = this.batchConfigurationNodeRecordMapper
|
||||||
|
.selectByPrimaryKey(copyInfo.configurationNodeId);
|
||||||
|
|
||||||
|
if (!sourceNode.getInstitutionId().equals(institutionId)) {
|
||||||
|
new IllegalArgumentException("Institution integrity violation");
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.copyNodeRecord(sourceNode, newOwner, copyInfo);
|
||||||
|
})
|
||||||
|
.flatMap(ConfigurationNodeDAOImpl::toDomainModel)
|
||||||
|
.onError(TransactionHandler::rollback);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ConfigurationNodeRecord copyNodeRecord(
|
||||||
|
final ConfigurationNodeRecord nodeRec,
|
||||||
|
final String newOwner,
|
||||||
|
final ConfigCopyInfo copyInfo) {
|
||||||
|
|
||||||
|
final ConfigurationNodeRecord newNodeRec = new ConfigurationNodeRecord(
|
||||||
|
null,
|
||||||
|
nodeRec.getInstitutionId(),
|
||||||
|
nodeRec.getTemplateId(),
|
||||||
|
StringUtils.isNotBlank(newOwner) ? newOwner : nodeRec.getOwner(),
|
||||||
|
copyInfo.getName(),
|
||||||
|
copyInfo.getDescription(),
|
||||||
|
nodeRec.getType(),
|
||||||
|
ConfigurationStatus.CONSTRUCTION.name());
|
||||||
|
this.batchConfigurationNodeRecordMapper.insert(newNodeRec);
|
||||||
|
this.batchSqlSessionTemplate.flushStatements();
|
||||||
|
|
||||||
|
final List<ConfigurationRecord> configs = this.batchConfigurationRecordMapper
|
||||||
|
.selectByExample()
|
||||||
|
.where(
|
||||||
|
ConfigurationRecordDynamicSqlSupport.configurationNodeId,
|
||||||
|
isEqualTo(nodeRec.getId()))
|
||||||
|
.build()
|
||||||
|
.execute();
|
||||||
|
|
||||||
|
if (BooleanUtils.toBoolean(copyInfo.withHistory)) {
|
||||||
|
configs
|
||||||
|
.stream()
|
||||||
|
.forEach(configRec -> this.copyConfiguration(
|
||||||
|
configRec.getInstitutionId(),
|
||||||
|
configRec.getId(),
|
||||||
|
newNodeRec.getId()));
|
||||||
|
} else {
|
||||||
|
configs
|
||||||
|
.stream()
|
||||||
|
.filter(configRec -> configRec.getVersionDate() == null)
|
||||||
|
.findFirst()
|
||||||
|
.ifPresent(configRec -> {
|
||||||
|
// No history means to create a first version and a follow-up with the copied values
|
||||||
|
final ConfigurationRecord newFirstVersion = new ConfigurationRecord(
|
||||||
|
null,
|
||||||
|
configRec.getInstitutionId(),
|
||||||
|
newNodeRec.getId(),
|
||||||
|
ConfigurationDAOBatchService.INITIAL_VERSION_NAME,
|
||||||
|
DateTime.now(DateTimeZone.UTC),
|
||||||
|
BooleanUtils.toInteger(false));
|
||||||
|
this.batchConfigurationRecordMapper.insert(newFirstVersion);
|
||||||
|
this.batchSqlSessionTemplate.flushStatements();
|
||||||
|
this.copyValues(
|
||||||
|
configRec.getInstitutionId(),
|
||||||
|
configRec.getId(),
|
||||||
|
newFirstVersion.getId());
|
||||||
|
// and copy the follow-up
|
||||||
|
final ConfigurationRecord followup = new ConfigurationRecord(
|
||||||
|
null,
|
||||||
|
configRec.getInstitutionId(),
|
||||||
|
newNodeRec.getId(),
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
BooleanUtils.toInteger(true));
|
||||||
|
this.batchConfigurationRecordMapper.insert(followup);
|
||||||
|
this.batchSqlSessionTemplate.flushStatements();
|
||||||
|
this.copyValues(
|
||||||
|
configRec.getInstitutionId(),
|
||||||
|
configRec.getId(),
|
||||||
|
followup.getId());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
this.batchSqlSessionTemplate.flushStatements();
|
||||||
|
return newNodeRec;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Result<Configuration> copyConfiguration(
|
||||||
final Long institutionId,
|
final Long institutionId,
|
||||||
final Long fromConfigurationId,
|
final Long fromConfigurationId,
|
||||||
final Long toConfigurationNodeId) {
|
final Long toConfigurationNodeId) {
|
||||||
|
@ -338,6 +433,7 @@ class ConfigurationDAOBatchService {
|
||||||
fromRecord.getVersionDate(),
|
fromRecord.getVersionDate(),
|
||||||
fromRecord.getFollowup());
|
fromRecord.getFollowup());
|
||||||
this.batchConfigurationRecordMapper.insert(configurationRecord);
|
this.batchConfigurationRecordMapper.insert(configurationRecord);
|
||||||
|
this.batchSqlSessionTemplate.flushStatements();
|
||||||
return configurationRecord;
|
return configurationRecord;
|
||||||
})
|
})
|
||||||
.flatMap(ConfigurationDAOImpl::toDomainModel)
|
.flatMap(ConfigurationDAOImpl::toDomainModel)
|
||||||
|
@ -347,14 +443,10 @@ class ConfigurationDAOBatchService {
|
||||||
fromConfigurationId,
|
fromConfigurationId,
|
||||||
newConfig.getId());
|
newConfig.getId());
|
||||||
return newConfig;
|
return newConfig;
|
||||||
})
|
|
||||||
.map(config -> {
|
|
||||||
this.batchSqlSessionTemplate.flushStatements();
|
|
||||||
return config;
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void copyValues(
|
private void copyValues(
|
||||||
final Long institutionId,
|
final Long institutionId,
|
||||||
final Long fromConfigId,
|
final Long fromConfigId,
|
||||||
final Long toConfigId) {
|
final Long toConfigId) {
|
||||||
|
|
|
@ -19,12 +19,7 @@ import java.util.function.Function;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import org.apache.commons.lang3.BooleanUtils;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
import org.joda.time.DateTime;
|
|
||||||
import org.joda.time.DateTimeZone;
|
|
||||||
import org.mybatis.dynamic.sql.SqlBuilder;
|
import org.mybatis.dynamic.sql.SqlBuilder;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
|
||||||
import org.springframework.context.annotation.Lazy;
|
import org.springframework.context.annotation.Lazy;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
@ -46,7 +41,6 @@ import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.ConfigurationReco
|
||||||
import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.ConfigurationValueRecordDynamicSqlSupport;
|
import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.ConfigurationValueRecordDynamicSqlSupport;
|
||||||
import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.ConfigurationValueRecordMapper;
|
import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.ConfigurationValueRecordMapper;
|
||||||
import ch.ethz.seb.sebserver.webservice.datalayer.batis.model.ConfigurationNodeRecord;
|
import ch.ethz.seb.sebserver.webservice.datalayer.batis.model.ConfigurationNodeRecord;
|
||||||
import ch.ethz.seb.sebserver.webservice.datalayer.batis.model.ConfigurationRecord;
|
|
||||||
import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.BulkAction;
|
import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.BulkAction;
|
||||||
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ConfigurationNodeDAO;
|
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ConfigurationNodeDAO;
|
||||||
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.DAOLoggingSupport;
|
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.DAOLoggingSupport;
|
||||||
|
@ -63,24 +57,18 @@ public class ConfigurationNodeDAOImpl implements ConfigurationNodeDAO {
|
||||||
private final ConfigurationNodeRecordMapper configurationNodeRecordMapper;
|
private final ConfigurationNodeRecordMapper configurationNodeRecordMapper;
|
||||||
private final ConfigurationValueRecordMapper configurationValueRecordMapper;
|
private final ConfigurationValueRecordMapper configurationValueRecordMapper;
|
||||||
private final ConfigurationDAOBatchService configurationDAOBatchService;
|
private final ConfigurationDAOBatchService configurationDAOBatchService;
|
||||||
private final String copyNamePrefix;
|
|
||||||
private final String copyNameSuffix;
|
|
||||||
|
|
||||||
protected ConfigurationNodeDAOImpl(
|
protected ConfigurationNodeDAOImpl(
|
||||||
final ConfigurationRecordMapper configurationRecordMapper,
|
final ConfigurationRecordMapper configurationRecordMapper,
|
||||||
final ConfigurationNodeRecordMapper configurationNodeRecordMapper,
|
final ConfigurationNodeRecordMapper configurationNodeRecordMapper,
|
||||||
final ConfigurationValueRecordMapper configurationValueRecordMapper,
|
final ConfigurationValueRecordMapper configurationValueRecordMapper,
|
||||||
final ConfigurationAttributeRecordMapper configurationAttributeRecordMapper,
|
final ConfigurationAttributeRecordMapper configurationAttributeRecordMapper,
|
||||||
final ConfigurationDAOBatchService ConfigurationDAOBatchService,
|
final ConfigurationDAOBatchService ConfigurationDAOBatchService) {
|
||||||
@Value("${sebserver.webservice.api.copy-name-prefix:Copy of }") final String copyNamePrefix,
|
|
||||||
@Value("${sebserver.webservice.api.copy-name-suffix:}") final String copyNameSuffix) {
|
|
||||||
|
|
||||||
this.configurationRecordMapper = configurationRecordMapper;
|
this.configurationRecordMapper = configurationRecordMapper;
|
||||||
this.configurationNodeRecordMapper = configurationNodeRecordMapper;
|
this.configurationNodeRecordMapper = configurationNodeRecordMapper;
|
||||||
this.configurationValueRecordMapper = configurationValueRecordMapper;
|
this.configurationValueRecordMapper = configurationValueRecordMapper;
|
||||||
this.configurationDAOBatchService = ConfigurationDAOBatchService;
|
this.configurationDAOBatchService = ConfigurationDAOBatchService;
|
||||||
this.copyNamePrefix = copyNamePrefix;
|
|
||||||
this.copyNameSuffix = copyNameSuffix;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -211,12 +199,7 @@ public class ConfigurationNodeDAOImpl implements ConfigurationNodeDAO {
|
||||||
final String newOwner,
|
final String newOwner,
|
||||||
final ConfigCopyInfo copyInfo) {
|
final ConfigCopyInfo copyInfo) {
|
||||||
|
|
||||||
return this.recordById(copyInfo.configurationNodeId)
|
return this.configurationDAOBatchService.createCopy(institutionId, newOwner, copyInfo);
|
||||||
.flatMap(nodeRec -> (nodeRec.getInstitutionId().equals(institutionId)
|
|
||||||
? Result.of(nodeRec)
|
|
||||||
: Result.ofError(new IllegalArgumentException("Institution integrity violation"))))
|
|
||||||
.map(nodeRec -> this.copyNodeRecord(nodeRec, newOwner, copyInfo))
|
|
||||||
.flatMap(ConfigurationNodeDAOImpl::toDomainModel);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -283,68 +266,6 @@ public class ConfigurationNodeDAOImpl implements ConfigurationNodeDAO {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private ConfigurationNodeRecord copyNodeRecord(
|
|
||||||
final ConfigurationNodeRecord nodeRec,
|
|
||||||
final String newOwner,
|
|
||||||
final ConfigCopyInfo copyInfo) {
|
|
||||||
|
|
||||||
final ConfigurationNodeRecord newNodeRec = new ConfigurationNodeRecord(
|
|
||||||
null,
|
|
||||||
nodeRec.getInstitutionId(),
|
|
||||||
nodeRec.getTemplateId(),
|
|
||||||
StringUtils.isNotBlank(newOwner) ? newOwner : nodeRec.getOwner(),
|
|
||||||
this.copyNamePrefix + nodeRec.getName() + this.copyNameSuffix,
|
|
||||||
nodeRec.getDescription(),
|
|
||||||
nodeRec.getType(),
|
|
||||||
ConfigurationStatus.CONSTRUCTION.name());
|
|
||||||
this.configurationNodeRecordMapper.insert(newNodeRec);
|
|
||||||
|
|
||||||
final List<ConfigurationRecord> configs = this.configurationRecordMapper
|
|
||||||
.selectByExample()
|
|
||||||
.where(
|
|
||||||
ConfigurationRecordDynamicSqlSupport.configurationNodeId,
|
|
||||||
isEqualTo(nodeRec.getId()))
|
|
||||||
.build()
|
|
||||||
.execute();
|
|
||||||
|
|
||||||
if (BooleanUtils.toBoolean(copyInfo.withHistory)) {
|
|
||||||
configs
|
|
||||||
.stream()
|
|
||||||
.forEach(configRec -> this.configurationDAOBatchService.copyConfiguration(
|
|
||||||
configRec.getInstitutionId(),
|
|
||||||
configRec.getId(),
|
|
||||||
newNodeRec.getId()));
|
|
||||||
} else {
|
|
||||||
configs
|
|
||||||
.stream()
|
|
||||||
.filter(configRec -> configRec.getVersionDate() == null)
|
|
||||||
.findFirst()
|
|
||||||
.map(configRec -> {
|
|
||||||
// No history means to create a first version and a follow-up with the copied values
|
|
||||||
final ConfigurationRecord newFirstVersion = new ConfigurationRecord(
|
|
||||||
null,
|
|
||||||
configRec.getInstitutionId(),
|
|
||||||
configRec.getConfigurationNodeId(),
|
|
||||||
ConfigurationDAOBatchService.INITIAL_VERSION_NAME,
|
|
||||||
DateTime.now(DateTimeZone.UTC),
|
|
||||||
BooleanUtils.toInteger(false));
|
|
||||||
this.configurationRecordMapper.insert(newFirstVersion);
|
|
||||||
this.configurationDAOBatchService.copyValues(
|
|
||||||
configRec.getInstitutionId(),
|
|
||||||
configRec.getId(),
|
|
||||||
newFirstVersion.getId());
|
|
||||||
// and copy the follow-up
|
|
||||||
this.configurationDAOBatchService.copyConfiguration(
|
|
||||||
configRec.getInstitutionId(),
|
|
||||||
configRec.getId(),
|
|
||||||
newNodeRec.getId());
|
|
||||||
return configRec;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return newNodeRec;
|
|
||||||
}
|
|
||||||
|
|
||||||
static Result<ConfigurationNode> toDomainModel(final ConfigurationNodeRecord record) {
|
static Result<ConfigurationNode> toDomainModel(final ConfigurationNodeRecord record) {
|
||||||
return Result.tryCatch(() -> new ConfigurationNode(
|
return Result.tryCatch(() -> new ConfigurationNode(
|
||||||
record.getId(),
|
record.getId(),
|
||||||
|
|
|
@ -257,6 +257,12 @@ public class ExamAdministrationController extends ActivatableEntityController<Ex
|
||||||
.getOrThrow();
|
.getOrThrow();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Result<Exam> validForCreate(final Exam entity) {
|
||||||
|
return super.validForCreate(entity)
|
||||||
|
.map(this::checkExamSupporterRole);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Result<Exam> validForSave(final Exam entity) {
|
protected Result<Exam> validForSave(final Exam entity) {
|
||||||
return super.validForSave(entity)
|
return super.validForSave(entity)
|
||||||
|
|
|
@ -34,8 +34,6 @@ sebserver.webservice.api.exam.accessTokenValiditySeconds=3600
|
||||||
sebserver.webservice.api.exam.event-handling-strategy=ASYNC_BATCH_STORE_STRATEGY
|
sebserver.webservice.api.exam.event-handling-strategy=ASYNC_BATCH_STORE_STRATEGY
|
||||||
sebserver.webservice.api.exam.enable-indicator-cache=true
|
sebserver.webservice.api.exam.enable-indicator-cache=true
|
||||||
sebserver.webservice.api.pagination.maxPageSize=500
|
sebserver.webservice.api.pagination.maxPageSize=500
|
||||||
sebserver.webservice.api.copy-name-prefix=Copy of
|
|
||||||
sebserver.webservice.api.copy-name-suffix=
|
|
||||||
# comma separated list of known possible OpenEdX API access token request endpoints
|
# comma separated list of known possible OpenEdX API access token request endpoints
|
||||||
sebserver.webservice.lms.openedx.api.token.request.paths=/oauth2/access_token
|
sebserver.webservice.lms.openedx.api.token.request.paths=/oauth2/access_token
|
||||||
sebserver.webservice.lms.address.alias=lms.mockup.com=lms.address.alias
|
sebserver.webservice.lms.address.alias=lms.mockup.com=lms.address.alias
|
||||||
|
|
|
@ -496,13 +496,8 @@ INSERT IGNORE INTO orientation VALUES
|
||||||
|
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
INSERT IGNORE INTO configuration_node VALUES
|
INSERT IGNORE INTO configuration_node VALUES
|
||||||
(1, 1, 0, 'super-admin', 'test', null, 'EXAM_CONFIG', 'READY_TO_USE')
|
(1, 1, 0, 'super-admin', 'test', null, 'EXAM_CONFIG', 'IN_USE')
|
||||||
;
|
;
|
||||||
|
|
||||||
INSERT IGNORE INTO configuration VALUES
|
INSERT IGNORE INTO configuration VALUES
|
||||||
|
|
|
@ -450,6 +450,7 @@ sebserver.examconfig.action.saveToHistory=Save / Publish
|
||||||
sebserver.examconfig.action.saveToHistory.success=Successfully saved in history
|
sebserver.examconfig.action.saveToHistory.success=Successfully saved in history
|
||||||
sebserver.examconfig.action.undo=Undo
|
sebserver.examconfig.action.undo=Undo
|
||||||
sebserver.examconfig.action.undo.success=Successfully reverted to last saved state
|
sebserver.examconfig.action.undo.success=Successfully reverted to last saved state
|
||||||
|
sebserver.examconfig.action.copy=Copy Configuration
|
||||||
sebserver.examconfig.action.export.plainxml=Export Configuration
|
sebserver.examconfig.action.export.plainxml=Export Configuration
|
||||||
sebserver.examconfig.action.get-config-key=Export Config-Key
|
sebserver.examconfig.action.get-config-key=Export Config-Key
|
||||||
sebserver.examconfig.action.import-config=Import Configuration
|
sebserver.examconfig.action.import-config=Import Configuration
|
||||||
|
@ -462,6 +463,7 @@ sebserver.examconfig.form.title.new=Add Exam Configuration
|
||||||
sebserver.examconfig.form.title=Exam Configuration
|
sebserver.examconfig.form.title=Exam Configuration
|
||||||
sebserver.examconfig.form.name=Name
|
sebserver.examconfig.form.name=Name
|
||||||
sebserver.examconfig.form.description=Description
|
sebserver.examconfig.form.description=Description
|
||||||
|
sebserver.examconfig.form.with-history=With History
|
||||||
sebserver.examconfig.form.template=From Template
|
sebserver.examconfig.form.template=From Template
|
||||||
sebserver.examconfig.form.status=Status
|
sebserver.examconfig.form.status=Status
|
||||||
sebserver.examconfig.form.config-key.title=Config Key
|
sebserver.examconfig.form.config-key.title=Config Key
|
||||||
|
|
BIN
src/main/resources/static/images/copy.png
Normal file
BIN
src/main/resources/static/images/copy.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 165 B |
|
@ -679,6 +679,7 @@ public class UseCasesIntegrationTest extends GuiIntegrationTest {
|
||||||
.getBuilder(ImportAsExam.class)
|
.getBuilder(ImportAsExam.class)
|
||||||
.withFormParam(QuizData.QUIZ_ATTR_LMS_SETUP_ID, String.valueOf(quizData.lmsSetupId))
|
.withFormParam(QuizData.QUIZ_ATTR_LMS_SETUP_ID, String.valueOf(quizData.lmsSetupId))
|
||||||
.withFormParam(QuizData.QUIZ_ATTR_ID, quizData.id)
|
.withFormParam(QuizData.QUIZ_ATTR_ID, quizData.id)
|
||||||
|
.withFormParam(Domain.EXAM.ATTR_SUPPORTER, userId)
|
||||||
.call();
|
.call();
|
||||||
|
|
||||||
assertNotNull(newExamResult);
|
assertNotNull(newExamResult);
|
||||||
|
@ -687,7 +688,7 @@ public class UseCasesIntegrationTest extends GuiIntegrationTest {
|
||||||
|
|
||||||
assertEquals("Demo Quiz 1", newExam.name);
|
assertEquals("Demo Quiz 1", newExam.name);
|
||||||
assertEquals(ExamType.UNDEFINED, newExam.type);
|
assertEquals(ExamType.UNDEFINED, newExam.type);
|
||||||
assertTrue(newExam.supporter.isEmpty());
|
assertFalse(newExam.supporter.isEmpty());
|
||||||
|
|
||||||
// create Exam with type and supporter examSupport2
|
// create Exam with type and supporter examSupport2
|
||||||
final Exam examForSave = new Exam(
|
final Exam examForSave = new Exam(
|
||||||
|
|
|
@ -37,12 +37,13 @@ public class ExamAPITest extends AdministrationAPIIntegrationTester {
|
||||||
sebAdminAccess,
|
sebAdminAccess,
|
||||||
"LmsSetupMock",
|
"LmsSetupMock",
|
||||||
"quiz2",
|
"quiz2",
|
||||||
ExamType.MANAGED);
|
ExamType.MANAGED,
|
||||||
|
"user5");
|
||||||
|
|
||||||
assertNotNull(exam);
|
assertNotNull(exam);
|
||||||
assertEquals("quiz2", exam.getExternalId());
|
assertEquals("quiz2", exam.getExternalId());
|
||||||
assertEquals(ExamType.MANAGED, exam.getType());
|
assertEquals(ExamType.MANAGED, exam.getType());
|
||||||
assertTrue(exam.getSupporter().isEmpty());
|
assertFalse(exam.getSupporter().isEmpty());
|
||||||
|
|
||||||
// add ExamSupporter
|
// add ExamSupporter
|
||||||
final Exam newExam = new RestAPITestHelper()
|
final Exam newExam = new RestAPITestHelper()
|
||||||
|
|
|
@ -43,6 +43,7 @@ public class ExamImportTest extends AdministrationAPIIntegrationTester {
|
||||||
.withMethod(HttpMethod.POST)
|
.withMethod(HttpMethod.POST)
|
||||||
.withAttribute(QuizData.QUIZ_ATTR_LMS_SETUP_ID, lmsSetup1.getModelId())
|
.withAttribute(QuizData.QUIZ_ATTR_LMS_SETUP_ID, lmsSetup1.getModelId())
|
||||||
.withAttribute(QuizData.QUIZ_ATTR_ID, "quiz1")
|
.withAttribute(QuizData.QUIZ_ATTR_ID, "quiz1")
|
||||||
|
.withAttribute(Domain.EXAM.ATTR_SUPPORTER, "user1")
|
||||||
.withExpectedStatus(HttpStatus.OK)
|
.withExpectedStatus(HttpStatus.OK)
|
||||||
.getAsObject(new TypeReference<Exam>() {
|
.getAsObject(new TypeReference<Exam>() {
|
||||||
});
|
});
|
||||||
|
@ -58,7 +59,8 @@ public class ExamImportTest extends AdministrationAPIIntegrationTester {
|
||||||
getSebAdminAccess(),
|
getSebAdminAccess(),
|
||||||
"LmsSetupMock",
|
"LmsSetupMock",
|
||||||
"quiz2",
|
"quiz2",
|
||||||
ExamType.MANAGED);
|
ExamType.MANAGED,
|
||||||
|
"user5");
|
||||||
|
|
||||||
assertNotNull(exam2);
|
assertNotNull(exam2);
|
||||||
assertEquals("quiz2", exam2.getExternalId());
|
assertEquals("quiz2", exam2.getExternalId());
|
||||||
|
@ -76,7 +78,8 @@ public class ExamImportTest extends AdministrationAPIIntegrationTester {
|
||||||
getAdminInstitution2Access(),
|
getAdminInstitution2Access(),
|
||||||
"LmsSetupMock",
|
"LmsSetupMock",
|
||||||
"quiz2",
|
"quiz2",
|
||||||
ExamType.MANAGED);
|
ExamType.MANAGED,
|
||||||
|
"user7");
|
||||||
fail("AssertionError expected here");
|
fail("AssertionError expected here");
|
||||||
} catch (final AssertionError ae) {
|
} catch (final AssertionError ae) {
|
||||||
assertEquals("Response status expected:<200> but was:<403>", ae.getMessage());
|
assertEquals("Response status expected:<200> but was:<403>", ae.getMessage());
|
||||||
|
@ -89,7 +92,8 @@ public class ExamImportTest extends AdministrationAPIIntegrationTester {
|
||||||
getExamAdmin1(), // this exam administrator is on Institution 2
|
getExamAdmin1(), // this exam administrator is on Institution 2
|
||||||
"LmsSetupMock2",
|
"LmsSetupMock2",
|
||||||
"quiz2",
|
"quiz2",
|
||||||
ExamType.MANAGED);
|
ExamType.MANAGED,
|
||||||
|
"user7");
|
||||||
|
|
||||||
assertNotNull(exam2);
|
assertNotNull(exam2);
|
||||||
assertEquals("quiz2", exam2.getExternalId());
|
assertEquals("quiz2", exam2.getExternalId());
|
||||||
|
@ -106,7 +110,8 @@ public class ExamImportTest extends AdministrationAPIIntegrationTester {
|
||||||
getExamAdmin1(), // this exam administrator is on Institution 2
|
getExamAdmin1(), // this exam administrator is on Institution 2
|
||||||
"LmsSetupMock",
|
"LmsSetupMock",
|
||||||
"quiz2",
|
"quiz2",
|
||||||
ExamType.MANAGED);
|
ExamType.MANAGED,
|
||||||
|
"user7");
|
||||||
fail("AssertionError expected here");
|
fail("AssertionError expected here");
|
||||||
} catch (final AssertionError ae) {
|
} catch (final AssertionError ae) {
|
||||||
assertEquals("Response status expected:<200> but was:<403>", ae.getMessage());
|
assertEquals("Response status expected:<200> but was:<403>", ae.getMessage());
|
||||||
|
@ -119,7 +124,8 @@ public class ExamImportTest extends AdministrationAPIIntegrationTester {
|
||||||
final String tokenForExamImport,
|
final String tokenForExamImport,
|
||||||
final String lmsSetupName,
|
final String lmsSetupName,
|
||||||
final String importQuizName,
|
final String importQuizName,
|
||||||
final ExamType examType) throws Exception {
|
final ExamType examType,
|
||||||
|
final String supporter) throws Exception {
|
||||||
|
|
||||||
// create new active LmsSetup Mock with seb-admin
|
// create new active LmsSetup Mock with seb-admin
|
||||||
final LmsSetup lmsSetup1 = QuizDataTest.createLmsSetupMock(
|
final LmsSetup lmsSetup1 = QuizDataTest.createLmsSetupMock(
|
||||||
|
@ -135,6 +141,7 @@ public class ExamImportTest extends AdministrationAPIIntegrationTester {
|
||||||
.withMethod(HttpMethod.POST)
|
.withMethod(HttpMethod.POST)
|
||||||
.withAttribute(QuizData.QUIZ_ATTR_LMS_SETUP_ID, lmsSetup1.getModelId())
|
.withAttribute(QuizData.QUIZ_ATTR_LMS_SETUP_ID, lmsSetup1.getModelId())
|
||||||
.withAttribute(QuizData.QUIZ_ATTR_ID, importQuizName)
|
.withAttribute(QuizData.QUIZ_ATTR_ID, importQuizName)
|
||||||
|
.withAttribute(Domain.EXAM.ATTR_SUPPORTER, supporter)
|
||||||
.withAttribute(Domain.EXAM.ATTR_TYPE, examType.name())
|
.withAttribute(Domain.EXAM.ATTR_TYPE, examType.name())
|
||||||
.withExpectedStatus(HttpStatus.OK)
|
.withExpectedStatus(HttpStatus.OK)
|
||||||
.getAsObject(new TypeReference<Exam>() {
|
.getAsObject(new TypeReference<Exam>() {
|
||||||
|
|
Loading…
Add table
Reference in a new issue