new seb restrcition strategy and minor fixes
This commit is contained in:
parent
09eb17a630
commit
b6466d8f1d
19 changed files with 207 additions and 85 deletions
|
@ -117,6 +117,7 @@ public final class API {
|
|||
public static final String EXAM_ADMINISTRATION_DOWNLOAD_CONFIG_PATH_SEGMENT = "/download-config";
|
||||
public static final String EXAM_ADMINISTRATION_CONSISTENCY_CHECK_PATH_SEGMENT = "/check-consistency";
|
||||
public static final String EXAM_ADMINISTRATION_SEB_RESTRICTION_PATH_SEGMENT = "/seb-restriction";
|
||||
public static final String EXAM_ADMINISTRATION_CHECK_RESTRICTION_PATH_SEGMENT = "/check-seb-restriction";
|
||||
|
||||
public static final String EXAM_INDICATOR_ENDPOINT = "/indicator";
|
||||
|
||||
|
|
|
@ -48,7 +48,7 @@ public final class Exam implements GrantEntity {
|
|||
null,
|
||||
null,
|
||||
ExamStatus.FINISHED,
|
||||
Boolean.FALSE,
|
||||
// Boolean.FALSE,
|
||||
null,
|
||||
Boolean.FALSE,
|
||||
null);
|
||||
|
@ -117,8 +117,8 @@ public final class Exam implements GrantEntity {
|
|||
@JsonProperty(EXAM.ATTR_STATUS)
|
||||
public final ExamStatus status;
|
||||
|
||||
@JsonProperty(EXAM.ATTR_LMS_SEB_RESTRICTION)
|
||||
public final Boolean lmsSebRestriction;
|
||||
// @JsonProperty(EXAM.ATTR_LMS_SEB_RESTRICTION)
|
||||
// public final Boolean lmsSebRestriction;
|
||||
|
||||
@JsonProperty(EXAM.ATTR_BROWSER_KEYS)
|
||||
public final String browserExamKeys;
|
||||
|
@ -145,7 +145,7 @@ public final class Exam implements GrantEntity {
|
|||
@JsonProperty(EXAM.ATTR_OWNER) final String owner,
|
||||
@JsonProperty(EXAM.ATTR_SUPPORTER) final Collection<String> supporter,
|
||||
@JsonProperty(EXAM.ATTR_STATUS) final ExamStatus status,
|
||||
@JsonProperty(EXAM.ATTR_LMS_SEB_RESTRICTION) final Boolean lmsSebRestriction,
|
||||
// @JsonProperty(EXAM.ATTR_LMS_SEB_RESTRICTION) final Boolean lmsSebRestriction,
|
||||
@JsonProperty(EXAM.ATTR_BROWSER_KEYS) final String browserExamKeys,
|
||||
@JsonProperty(EXAM.ATTR_ACTIVE) final Boolean active,
|
||||
@JsonProperty(EXAM.ATTR_LASTUPDATE) final String lastUpdate) {
|
||||
|
@ -163,7 +163,7 @@ public final class Exam implements GrantEntity {
|
|||
this.quitPassword = quitPassword;
|
||||
this.owner = owner;
|
||||
this.status = (status != null) ? status : getStatusFromDate(startTime, endTime);
|
||||
this.lmsSebRestriction = (lmsSebRestriction != null) ? lmsSebRestriction : Boolean.FALSE;
|
||||
// this.lmsSebRestriction = (lmsSebRestriction != null) ? lmsSebRestriction : Boolean.FALSE;
|
||||
this.browserExamKeys = browserExamKeys;
|
||||
this.active = (active != null) ? active : Boolean.TRUE;
|
||||
this.lastUpdate = lastUpdate;
|
||||
|
@ -191,7 +191,7 @@ public final class Exam implements GrantEntity {
|
|||
EXAM.ATTR_STATUS,
|
||||
ExamStatus.class,
|
||||
getStatusFromDate(this.startTime, this.endTime));
|
||||
this.lmsSebRestriction = mapper.getBoolean(EXAM.ATTR_LMS_SEB_RESTRICTION);
|
||||
// this.lmsSebRestriction = mapper.getBoolean(EXAM.ATTR_LMS_SEB_RESTRICTION);
|
||||
this.browserExamKeys = mapper.getString(EXAM.ATTR_BROWSER_KEYS);
|
||||
this.active = mapper.getBoolean(EXAM.ATTR_ACTIVE);
|
||||
this.supporter = mapper.getStringSet(EXAM.ATTR_SUPPORTER);
|
||||
|
@ -216,7 +216,7 @@ public final class Exam implements GrantEntity {
|
|||
this.quitPassword = null;
|
||||
this.owner = null;
|
||||
this.status = (status != null) ? status : getStatusFromDate(this.startTime, this.endTime);
|
||||
this.lmsSebRestriction = null;
|
||||
// this.lmsSebRestriction = null;
|
||||
this.browserExamKeys = null;
|
||||
this.active = null;
|
||||
this.supporter = null;
|
||||
|
@ -314,9 +314,9 @@ public final class Exam implements GrantEntity {
|
|||
return this.status;
|
||||
}
|
||||
|
||||
public Boolean getLmsSebRestriction() {
|
||||
return this.lmsSebRestriction;
|
||||
}
|
||||
// public Boolean getLmsSebRestriction() {
|
||||
// return this.lmsSebRestriction;
|
||||
// }
|
||||
|
||||
public String getBrowserExamKeys() {
|
||||
return this.browserExamKeys;
|
||||
|
@ -357,8 +357,8 @@ public final class Exam implements GrantEntity {
|
|||
builder.append(this.supporter);
|
||||
builder.append(", status=");
|
||||
builder.append(this.status);
|
||||
builder.append(", lmsSebRestriction=");
|
||||
builder.append(this.lmsSebRestriction);
|
||||
// builder.append(", lmsSebRestriction=");
|
||||
// builder.append(this.lmsSebRestriction);
|
||||
builder.append(", browserExamKeys=");
|
||||
builder.append(this.browserExamKeys);
|
||||
builder.append(", active=");
|
||||
|
|
|
@ -39,13 +39,13 @@ public final class LmsSetup implements GrantEntity, Activatable {
|
|||
|
||||
public enum Features {
|
||||
COURSE_API,
|
||||
SEA_RESTRICTION,
|
||||
SEB_RESTRICTION,
|
||||
COURSE_STRUCTURE_API,
|
||||
}
|
||||
|
||||
public enum LmsType {
|
||||
MOCKUP(Features.COURSE_API),
|
||||
OPEN_EDX(Features.COURSE_API, Features.SEA_RESTRICTION),
|
||||
OPEN_EDX(Features.COURSE_API, Features.SEB_RESTRICTION),
|
||||
MOODLE(Features.COURSE_API);
|
||||
|
||||
public final EnumSet<Features> features;
|
||||
|
|
|
@ -636,4 +636,16 @@ public final class Utils {
|
|||
.toString();
|
||||
}
|
||||
|
||||
public static String truncateText(final String text, final int toChars) {
|
||||
if (text == null || toChars < 3) {
|
||||
return text;
|
||||
}
|
||||
|
||||
if (text.length() <= toChars) {
|
||||
return text;
|
||||
}
|
||||
|
||||
return StringUtils.truncate(text, toChars - 3) + "...";
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -65,6 +65,7 @@ import ch.ethz.seb.sebserver.gui.service.remote.download.DownloadService;
|
|||
import ch.ethz.seb.sebserver.gui.service.remote.download.SebExamConfigDownload;
|
||||
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.CheckSebRestriction;
|
||||
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;
|
||||
|
@ -222,7 +223,7 @@ public class ExamForm implements TemplateComposer {
|
|||
.call()
|
||||
.getOr(Collections.emptyList());
|
||||
if (warnings != null && !warnings.isEmpty()) {
|
||||
showConsistencyChecks(warnings, formContext.getParent());
|
||||
showConsistencyChecks(warnings, formContext.getParent());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -234,7 +235,7 @@ public class ExamForm implements TemplateComposer {
|
|||
formContext.getParent(),
|
||||
titleKey);
|
||||
if (warnings != null && !warnings.isEmpty()) {
|
||||
GridData gridData = (GridData) content.getLayoutData();
|
||||
final GridData gridData = (GridData) content.getLayoutData();
|
||||
gridData.verticalIndent = 10;
|
||||
}
|
||||
|
||||
|
@ -248,6 +249,12 @@ public class ExamForm implements TemplateComposer {
|
|||
|| examStatus == ExamStatus.RUNNING
|
||||
&& currentUser.get().hasRole(UserRole.EXAM_ADMIN);
|
||||
final boolean sebRestrictionAvailable = testSebRestrictionAPI(exam);
|
||||
final boolean isRestricted = readonly && sebRestrictionAvailable && this.restService
|
||||
.getBuilder(CheckSebRestriction.class)
|
||||
.withURIVariable(API.PARAM_MODEL_ID, exam.getModelId())
|
||||
.call()
|
||||
.onError(e -> log.error("Unexpected error while trying to verify seb restriction settings: ", e))
|
||||
.getOr(false);
|
||||
|
||||
// The Exam form
|
||||
final FormHandle<Exam> formHandle = this.pageService.formBuilder(
|
||||
|
@ -399,12 +406,14 @@ public class ExamForm implements TemplateComposer {
|
|||
.newAction(ActionDefinition.EXAM_ENABLE_SEB_RESTRICTION)
|
||||
.withEntityKey(entityKey)
|
||||
.withExec(action -> ExamSebRestrictionSettings.setSebRestriction(action, true, this.restService))
|
||||
.publishIf(() -> sebRestrictionAvailable && readonly && BooleanUtils.isFalse(exam.lmsSebRestriction))
|
||||
.publishIf(() -> sebRestrictionAvailable && readonly && modifyGrant && !importFromQuizData
|
||||
&& BooleanUtils.isFalse(isRestricted))
|
||||
|
||||
.newAction(ActionDefinition.EXAM_DISABLE_SEB_RESTRICTION)
|
||||
.withEntityKey(entityKey)
|
||||
.withExec(action -> ExamSebRestrictionSettings.setSebRestriction(action, false, this.restService))
|
||||
.publishIf(() -> sebRestrictionAvailable && readonly && BooleanUtils.isTrue(exam.lmsSebRestriction));
|
||||
.publishIf(() -> sebRestrictionAvailable && readonly && modifyGrant && !importFromQuizData
|
||||
&& BooleanUtils.isTrue(isRestricted));
|
||||
|
||||
// additional data in read-only view
|
||||
if (readonly && !importFromQuizData) {
|
||||
|
@ -413,8 +422,7 @@ public class ExamForm implements TemplateComposer {
|
|||
this.widgetFactory.addFormSubContextHeader(
|
||||
content,
|
||||
CONFIG_LIST_TITLE_KEY,
|
||||
CONFIG_LIST_TITLE_TOOLTIP_KEY
|
||||
);
|
||||
CONFIG_LIST_TITLE_TOOLTIP_KEY);
|
||||
|
||||
final EntityTable<ExamConfigurationMap> configurationTable =
|
||||
this.pageService.entityTableBuilder(this.restService.getRestCall(GetExamConfigMappingsPage.class))
|
||||
|
@ -506,8 +514,7 @@ public class ExamForm implements TemplateComposer {
|
|||
this.widgetFactory.addFormSubContextHeader(
|
||||
content,
|
||||
INDICATOR_LIST_TITLE_KEY,
|
||||
INDICATOR_LIST_TITLE_TOOLTIP_KEY
|
||||
);
|
||||
INDICATOR_LIST_TITLE_TOOLTIP_KEY);
|
||||
|
||||
final EntityTable<Indicator> indicatorTable =
|
||||
this.pageService.entityTableBuilder(this.restService.getRestCall(GetIndicatorPage.class))
|
||||
|
@ -597,7 +604,7 @@ public class ExamForm implements TemplateComposer {
|
|||
.withURIVariable(API.PARAM_MODEL_ID, String.valueOf(exam.lmsSetupId))
|
||||
.call()
|
||||
.onError(t -> log.error("Failed to check SEB restriction API: ", t))
|
||||
.map(lmsSetup -> lmsSetup.lmsType.features.contains(Features.SEA_RESTRICTION))
|
||||
.map(lmsSetup -> lmsSetup.lmsType.features.contains(Features.SEB_RESTRICTION))
|
||||
.getOr(false);
|
||||
}
|
||||
|
||||
|
|
|
@ -114,11 +114,18 @@ public class RegisterPage implements TemplateComposer {
|
|||
@Override
|
||||
public void compose(final PageContext pageContext) {
|
||||
|
||||
final Composite outer = new Composite(pageContext.getParent(), SWT.NONE);
|
||||
final GridLayout outerLayout = new GridLayout();
|
||||
outerLayout.marginLeft = 50;
|
||||
outerLayout.marginRight = 50;
|
||||
outer.setLayout(outerLayout);
|
||||
outer.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
|
||||
|
||||
final Composite parent = PageService.createManagedVScrolledComposite(
|
||||
pageContext.getParent(),
|
||||
outer,
|
||||
scrolledComposite -> {
|
||||
final Composite result = new Composite(scrolledComposite, SWT.NONE);
|
||||
result.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
|
||||
result.setLayoutData(new GridData(SWT.CENTER, SWT.FILL, true, true));
|
||||
final GridLayout contentOutlaying = new GridLayout();
|
||||
contentOutlaying.marginHeight = 0;
|
||||
contentOutlaying.marginWidth = 0;
|
||||
|
@ -147,7 +154,6 @@ public class RegisterPage implements TemplateComposer {
|
|||
.sorted(ResourceService.RESOURCE_COMPARATOR)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
|
||||
this.widgetFactory.labelLocalizedTitle(parent, TITLE_TEXT_KEY);
|
||||
|
||||
// The UserAccount form
|
||||
|
|
|
@ -198,6 +198,9 @@ public final class PageAction {
|
|||
PageAction.this.getName(),
|
||||
e.getMessage(),
|
||||
Utils.getErrorCauseMessage(e));
|
||||
PageAction.this.pageContext.notifyError(
|
||||
PageContext.UNEXPECTED_ERROR_KEY,
|
||||
e);
|
||||
return Result.ofError(e);
|
||||
} catch (final Exception e) {
|
||||
log.error("Failed to execute action: {} | error: {} | cause: {}",
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* Copyright (c) 2020 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.profile.GuiProfile;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCall;
|
||||
|
||||
@Lazy
|
||||
@Component
|
||||
@GuiProfile
|
||||
public class CheckSebRestriction extends RestCall<Boolean> {
|
||||
|
||||
public CheckSebRestriction() {
|
||||
super(new TypeKey<>(
|
||||
CallType.UNDEFINED,
|
||||
EntityType.EXAM_SEB_RESTRICTION,
|
||||
new TypeReference<Boolean>() {
|
||||
}),
|
||||
HttpMethod.GET,
|
||||
MediaType.APPLICATION_JSON_UTF8,
|
||||
API.EXAM_ADMINISTRATION_ENDPOINT
|
||||
+ API.MODEL_ID_VAR_PATH_SEGMENT
|
||||
+ API.EXAM_ADMINISTRATION_CHECK_RESTRICTION_PATH_SEGMENT);
|
||||
}
|
||||
|
||||
}
|
|
@ -19,6 +19,7 @@ import org.eclipse.swt.widgets.Listener;
|
|||
|
||||
import ch.ethz.seb.sebserver.gbl.Constants;
|
||||
import ch.ethz.seb.sebserver.gbl.util.Tuple;
|
||||
import ch.ethz.seb.sebserver.gbl.util.Utils;
|
||||
|
||||
public final class SingleSelection extends Combo implements Selection {
|
||||
|
||||
|
@ -41,7 +42,7 @@ public final class SingleSelection extends Combo implements Selection {
|
|||
this.valueMapping.clear();
|
||||
this.keyMapping.clear();
|
||||
this.valueMapping.addAll(mapping.stream()
|
||||
.map(t -> t._2)
|
||||
.map(t -> Utils.truncateText(t._2, 100))
|
||||
.collect(Collectors.toList()));
|
||||
this.keyMapping.addAll(mapping.stream()
|
||||
.map(t -> t._1)
|
||||
|
|
|
@ -8,6 +8,44 @@
|
|||
|
||||
package ch.ethz.seb.sebserver.gui.widget;
|
||||
|
||||
import static ch.ethz.seb.sebserver.gui.service.i18n.PolyglotPageService.POLYGLOT_WIDGET_FUNCTION_KEY;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.eclipse.rap.rwt.RWT;
|
||||
import org.eclipse.rap.rwt.client.service.JavaScriptExecutor;
|
||||
import org.eclipse.rap.rwt.widgets.WidgetUtil;
|
||||
import org.eclipse.swt.SWT;
|
||||
import org.eclipse.swt.graphics.Device;
|
||||
import org.eclipse.swt.graphics.Image;
|
||||
import org.eclipse.swt.graphics.ImageData;
|
||||
import org.eclipse.swt.layout.GridData;
|
||||
import org.eclipse.swt.layout.GridLayout;
|
||||
import org.eclipse.swt.widgets.Button;
|
||||
import org.eclipse.swt.widgets.ColorDialog;
|
||||
import org.eclipse.swt.widgets.Composite;
|
||||
import org.eclipse.swt.widgets.DateTime;
|
||||
import org.eclipse.swt.widgets.Group;
|
||||
import org.eclipse.swt.widgets.Label;
|
||||
import org.eclipse.swt.widgets.Listener;
|
||||
import org.eclipse.swt.widgets.TabFolder;
|
||||
import org.eclipse.swt.widgets.TabItem;
|
||||
import org.eclipse.swt.widgets.Table;
|
||||
import org.eclipse.swt.widgets.TableColumn;
|
||||
import org.eclipse.swt.widgets.Text;
|
||||
import org.eclipse.swt.widgets.Tree;
|
||||
import org.eclipse.swt.widgets.TreeItem;
|
||||
import org.eclipse.swt.widgets.Widget;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.model.exam.Indicator.IndicatorType;
|
||||
import ch.ethz.seb.sebserver.gbl.model.exam.Indicator.Threshold;
|
||||
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
|
||||
|
@ -19,29 +57,6 @@ import ch.ethz.seb.sebserver.gui.service.i18n.PolyglotPageService;
|
|||
import ch.ethz.seb.sebserver.gui.service.page.PageService;
|
||||
import ch.ethz.seb.sebserver.gui.service.page.impl.DefaultPageLayout;
|
||||
import ch.ethz.seb.sebserver.gui.service.push.ServerPushService;
|
||||
import org.eclipse.rap.rwt.RWT;
|
||||
import org.eclipse.rap.rwt.client.service.JavaScriptExecutor;
|
||||
import org.eclipse.rap.rwt.widgets.WidgetUtil;
|
||||
import org.eclipse.swt.SWT;
|
||||
import org.eclipse.swt.graphics.Device;
|
||||
import org.eclipse.swt.graphics.Image;
|
||||
import org.eclipse.swt.graphics.ImageData;
|
||||
import org.eclipse.swt.layout.GridData;
|
||||
import org.eclipse.swt.layout.GridLayout;
|
||||
import org.eclipse.swt.widgets.*;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import static ch.ethz.seb.sebserver.gui.service.i18n.PolyglotPageService.POLYGLOT_WIDGET_FUNCTION_KEY;
|
||||
|
||||
@Lazy
|
||||
@Service
|
||||
|
@ -151,7 +166,7 @@ public class WidgetFactory {
|
|||
TEXT_H1("h1"),
|
||||
TEXT_H2("h2"),
|
||||
TEXT_H3("h3"),
|
||||
SUBTITLE( "subtitle"),
|
||||
SUBTITLE("subtitle"),
|
||||
IMAGE_BUTTON("imageButton"),
|
||||
TEXT_ACTION("action"),
|
||||
TEXT_READONLY("readonlyText"),
|
||||
|
@ -179,7 +194,9 @@ public class WidgetFactory {
|
|||
|
||||
LIST_NAVIGATION("list-nav"),
|
||||
PLAIN_PWD("pwdplain"),
|
||||
COLOR_BOX("colorbox")
|
||||
COLOR_BOX("colorbox"),
|
||||
|
||||
REGISTER_FORM("register")
|
||||
|
||||
;
|
||||
|
||||
|
@ -228,8 +245,8 @@ public class WidgetFactory {
|
|||
labelLocalizedTitle.setLayoutData(gridData);
|
||||
|
||||
// sub title if defined in language properties
|
||||
LocTextKey subTitleTextKey = new LocTextKey(title.name + SUB_TITLE_TExT_SUFFIX);
|
||||
if (i18nSupport.hasText(subTitleTextKey)) {
|
||||
final LocTextKey subTitleTextKey = new LocTextKey(title.name + SUB_TITLE_TExT_SUFFIX);
|
||||
if (this.i18nSupport.hasText(subTitleTextKey)) {
|
||||
final GridData gridDataSub = new GridData(SWT.FILL, SWT.FILL, true, false);
|
||||
final Label labelLocalizedSubTitle = labelLocalized(
|
||||
defaultPageLayout,
|
||||
|
@ -241,20 +258,21 @@ public class WidgetFactory {
|
|||
return defaultPageLayout;
|
||||
}
|
||||
|
||||
public void addFormSubContextHeader(final Composite parent, final LocTextKey titleTextKey, final LocTextKey tooltipTextKey) {
|
||||
GridData gridData = new GridData(SWT.FILL, SWT.BOTTOM, true, false);
|
||||
public void addFormSubContextHeader(final Composite parent, final LocTextKey titleTextKey,
|
||||
final LocTextKey tooltipTextKey) {
|
||||
final GridData gridData = new GridData(SWT.FILL, SWT.BOTTOM, true, false);
|
||||
gridData.horizontalIndent = 8;
|
||||
gridData.verticalIndent = 10;
|
||||
Label subContextLabel = labelLocalized(
|
||||
final Label subContextLabel = labelLocalized(
|
||||
parent,
|
||||
CustomVariant.TEXT_H3,
|
||||
titleTextKey,
|
||||
tooltipTextKey);
|
||||
subContextLabel.setLayoutData(gridData);
|
||||
GridData gridData1 = new GridData(SWT.FILL, SWT.BOTTOM, true, false);
|
||||
final GridData gridData1 = new GridData(SWT.FILL, SWT.BOTTOM, true, false);
|
||||
gridData1.heightHint = 5;
|
||||
gridData1.horizontalIndent = 8;
|
||||
Label subContextSeparator = labelSeparator(parent);
|
||||
final Label subContextSeparator = labelSeparator(parent);
|
||||
subContextSeparator.setLayoutData(gridData1);
|
||||
}
|
||||
|
||||
|
@ -289,7 +307,7 @@ public class WidgetFactory {
|
|||
|
||||
public Composite createWarningPanel(final Composite parent) {
|
||||
final Composite composite = new Composite(parent, SWT.NONE);
|
||||
GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, false);
|
||||
final GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, false);
|
||||
composite.setLayoutData(gridData);
|
||||
final GridLayout gridLayout = new GridLayout(1, true);
|
||||
gridLayout.marginWidth = 20;
|
||||
|
@ -379,7 +397,7 @@ public class WidgetFactory {
|
|||
|
||||
public Label labelLocalizedTitle(final Composite content, final LocTextKey locTextKey) {
|
||||
final Label labelLocalized = labelLocalized(content, CustomVariant.TEXT_H1, locTextKey);
|
||||
GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, false);
|
||||
final GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, false);
|
||||
labelLocalized.setLayoutData(gridData);
|
||||
return labelLocalized;
|
||||
}
|
||||
|
|
|
@ -107,7 +107,8 @@ public class ExamDAOImpl implements ExamDAO {
|
|||
.execute()
|
||||
: this.examRecordMapper.selectByExample()
|
||||
.build()
|
||||
.execute()).flatMap(this::toDomainModel);
|
||||
.execute())
|
||||
.flatMap(this::toDomainModel);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -210,9 +211,7 @@ public class ExamDAOImpl implements ExamDAO {
|
|||
(exam.status != null)
|
||||
? exam.status.name()
|
||||
: null,
|
||||
(exam.lmsSebRestriction != null)
|
||||
? BooleanUtils.toIntegerObject(exam.lmsSebRestriction)
|
||||
: null,
|
||||
1, // seb restriction (deprecated)
|
||||
null, // updating
|
||||
null, // lastUpdate
|
||||
null // active
|
||||
|
@ -259,6 +258,10 @@ public class ExamDAOImpl implements ExamDAO {
|
|||
// used to save instead of create a new one
|
||||
if (records != null && records.size() > 0) {
|
||||
final ExamRecord examRecord = records.get(0);
|
||||
// if another institution tries to import an exam that already exists
|
||||
if (!exam.institutionId.equals(examRecord.getInstitutionId())) {
|
||||
throw new IllegalStateException("Exam cannot be imported twice from different institutions");
|
||||
}
|
||||
final ExamRecord newRecord = new ExamRecord(
|
||||
examRecord.getId(),
|
||||
null, null, null, null, null,
|
||||
|
@ -266,7 +269,7 @@ public class ExamDAOImpl implements ExamDAO {
|
|||
null, // quitPassword
|
||||
null, // browser keys
|
||||
null, // status
|
||||
null, // lmsSebRestriction
|
||||
null, // lmsSebRestriction (deprecated)
|
||||
null, // updating
|
||||
null, // lastUpdate
|
||||
BooleanUtils.toIntegerObject(exam.active));
|
||||
|
@ -288,7 +291,7 @@ public class ExamDAOImpl implements ExamDAO {
|
|||
null, // quitPassword
|
||||
null, // browser keys
|
||||
(exam.status != null) ? exam.status.name() : ExamStatus.UP_COMING.name(),
|
||||
BooleanUtils.toInteger(exam.lmsSebRestriction),
|
||||
1, // seb restriction (deprecated)
|
||||
BooleanUtils.toInteger(false),
|
||||
null, // lastUpdate
|
||||
BooleanUtils.toInteger(true));
|
||||
|
@ -752,7 +755,7 @@ public class ExamDAOImpl implements ExamDAO {
|
|||
record.getOwner(),
|
||||
supporter,
|
||||
status,
|
||||
BooleanUtils.toBooleanObject((quizData != null) ? record.getLmsSebRestriction() : null),
|
||||
// BooleanUtils.toBooleanObject((quizData != null) ? record.getLmsSebRestriction() : null),
|
||||
record.getBrowserKeys(),
|
||||
BooleanUtils.toBooleanObject((quizData != null) ? record.getActive() : null),
|
||||
record.getLastupdate());
|
||||
|
|
|
@ -17,13 +17,15 @@ public interface ExamAdminService {
|
|||
*
|
||||
* @param exam The Exam to add the default indicator
|
||||
* @return the Exam with added default indicator */
|
||||
Result<Exam> addDefaultIndicator(final Exam exam);
|
||||
Result<Exam> addDefaultIndicator(Exam exam);
|
||||
|
||||
/** Applies all additional SEB restriction attributes that are defined by the
|
||||
* type of the LMS of a given Exam to this given Exam.
|
||||
*
|
||||
*
|
||||
* @param exam the Exam to apply all additional SEB restriction attributes
|
||||
* @return the Exam */
|
||||
Result<Exam> applyAdditionalSEBRestrictions(final Exam exam);
|
||||
Result<Exam> applyAdditionalSEBRestrictions(Exam exam);
|
||||
|
||||
Result<Boolean> isRestricted(Exam exam);
|
||||
|
||||
}
|
||||
|
|
|
@ -127,4 +127,15 @@ public class ExamAdminServiceImpl implements ExamAdminService {
|
|||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result<Boolean> isRestricted(final Exam exam) {
|
||||
if (exam == null) {
|
||||
return Result.of(false);
|
||||
}
|
||||
|
||||
return this.lmsAPIService
|
||||
.getLmsAPITemplate(exam.lmsSetupId)
|
||||
.map(lmsAPI -> !lmsAPI.getSebClientRestriction(exam).hasError());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -121,7 +121,6 @@ public class SebRestrictionServiceImpl implements SebRestrictionService {
|
|||
null, null, null, null, null, null, null, null, null, null, null,
|
||||
exam.supporter,
|
||||
exam.status,
|
||||
exam.lmsSebRestriction,
|
||||
(browserExamKeys != null && !browserExamKeys.isEmpty())
|
||||
? StringUtils.join(browserExamKeys, Constants.LIST_SEPARATOR_CHAR)
|
||||
: StringUtils.EMPTY,
|
||||
|
@ -157,7 +156,7 @@ public class SebRestrictionServiceImpl implements SebRestrictionService {
|
|||
public Result<Exam> applySebClientRestriction(final Exam exam) {
|
||||
if (!this.lmsAPIService
|
||||
.getLmsSetup(exam.lmsSetupId)
|
||||
.getOrThrow().lmsType.features.contains(Features.SEA_RESTRICTION)) {
|
||||
.getOrThrow().lmsType.features.contains(Features.SEB_RESTRICTION)) {
|
||||
|
||||
return Result.of(exam);
|
||||
}
|
||||
|
|
|
@ -14,7 +14,6 @@ import java.util.Objects;
|
|||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.apache.commons.lang3.BooleanUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
|
@ -31,6 +30,7 @@ import ch.ethz.seb.sebserver.gbl.util.Result;
|
|||
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ConfigurationDAO;
|
||||
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.exam.ExamAdminService;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.session.ExamConfigUpdateService;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.session.ExamSessionService;
|
||||
|
||||
|
@ -46,19 +46,22 @@ public class ExamConfigUpdateServiceImpl implements ExamConfigUpdateService {
|
|||
private final ExamConfigurationMapDAO examConfigurationMapDAO;
|
||||
private final ExamSessionService examSessionService;
|
||||
private final ExamUpdateHandler examUpdateHandler;
|
||||
private final ExamAdminService examAdminService;
|
||||
|
||||
protected ExamConfigUpdateServiceImpl(
|
||||
final ExamDAO examDAO,
|
||||
final ConfigurationDAO configurationDAO,
|
||||
final ExamConfigurationMapDAO examConfigurationMapDAO,
|
||||
final ExamSessionService examSessionService,
|
||||
final ExamUpdateHandler examUpdateHandler) {
|
||||
final ExamUpdateHandler examUpdateHandler,
|
||||
final ExamAdminService examAdminService) {
|
||||
|
||||
this.examDAO = examDAO;
|
||||
this.configurationDAO = configurationDAO;
|
||||
this.examConfigurationMapDAO = examConfigurationMapDAO;
|
||||
this.examSessionService = examSessionService;
|
||||
this.examUpdateHandler = examUpdateHandler;
|
||||
this.examAdminService = examAdminService;
|
||||
}
|
||||
|
||||
// processing:
|
||||
|
@ -127,7 +130,8 @@ public class ExamConfigUpdateServiceImpl implements ExamConfigUpdateService {
|
|||
|
||||
// generate the new Config Key and update the Config Key within the LMSSetup API for each exam (delete old Key and add new Key)
|
||||
for (final Exam exam : exams) {
|
||||
if (exam.getStatus() == ExamStatus.RUNNING && BooleanUtils.isTrue(exam.lmsSebRestriction)) {
|
||||
if (exam.getStatus() == ExamStatus.RUNNING || this.examAdminService.isRestricted(exam).getOr(false)) {
|
||||
|
||||
this.examUpdateHandler
|
||||
.getSebRestrictionService()
|
||||
.applySebClientRestriction(exam)
|
||||
|
@ -197,7 +201,7 @@ public class ExamConfigUpdateServiceImpl implements ExamConfigUpdateService {
|
|||
.getOrThrow();
|
||||
|
||||
// update seb client restriction if the feature is activated for the exam
|
||||
if (exam.lmsSebRestriction) {
|
||||
if (this.examAdminService.isRestricted(exam).getOr(false)) {
|
||||
this.examUpdateHandler
|
||||
.getSebRestrictionService()
|
||||
.applySebClientRestriction(exam)
|
||||
|
|
|
@ -125,7 +125,7 @@ public class ExamSessionServiceImpl implements ExamSessionService {
|
|||
// if SEB restriction is not available no consistency violation message is added
|
||||
final LmsSetup lmsSetup = this.lmsAPIService.getLmsSetup(exam.lmsSetupId)
|
||||
.getOr(null);
|
||||
if (lmsSetup != null && lmsSetup.lmsType.features.contains(Features.SEA_RESTRICTION)) {
|
||||
if (lmsSetup != null && lmsSetup.lmsType.features.contains(Features.SEB_RESTRICTION)) {
|
||||
this.lmsAPIService.getLmsAPITemplate(exam.lmsSetupId)
|
||||
.map(t -> {
|
||||
if (t.testCourseRestrictionAPI().isOk()) {
|
||||
|
|
|
@ -22,7 +22,6 @@ import javax.servlet.http.HttpServletRequest;
|
|||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.validation.Valid;
|
||||
|
||||
import org.apache.commons.lang3.BooleanUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.mybatis.dynamic.sql.SqlTable;
|
||||
import org.slf4j.Logger;
|
||||
|
@ -227,6 +226,24 @@ public class ExamAdministrationController extends EntityController<Exam, Exam> {
|
|||
.getOrThrow();
|
||||
}
|
||||
|
||||
@RequestMapping(
|
||||
path = API.MODEL_ID_VAR_PATH_SEGMENT
|
||||
+ API.EXAM_ADMINISTRATION_CHECK_RESTRICTION_PATH_SEGMENT,
|
||||
method = RequestMethod.GET,
|
||||
produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
|
||||
public Boolean checkSebRestriction(
|
||||
@PathVariable final Long modelId,
|
||||
@RequestParam(
|
||||
name = API.PARAM_INSTITUTION_ID,
|
||||
required = true,
|
||||
defaultValue = UserService.USERS_INSTITUTION_AS_DEFAULT) final Long institutionId) {
|
||||
|
||||
checkReadPrivilege(institutionId);
|
||||
return this.examDAO.byPK(modelId)
|
||||
.flatMap(this.examAdminService::isRestricted)
|
||||
.getOrThrow();
|
||||
}
|
||||
|
||||
// ****************************************************************************
|
||||
// **** SEB Restriction
|
||||
|
||||
|
@ -266,7 +283,7 @@ public class ExamAdministrationController extends EntityController<Exam, Exam> {
|
|||
return this.entityDAO.byPK(examId)
|
||||
.flatMap(this.authorization::checkModify)
|
||||
.flatMap(exam -> this.sebRestrictionService.saveSebRestrictionToExam(exam, sebRestriction))
|
||||
.flatMap(exam -> BooleanUtils.isTrue(exam.lmsSebRestriction)
|
||||
.flatMap(exam -> this.examAdminService.isRestricted(exam).getOrThrow()
|
||||
? this.applySebRestriction(exam, true)
|
||||
: Result.of(exam))
|
||||
.getOrThrow();
|
||||
|
@ -397,7 +414,7 @@ public class ExamAdministrationController extends EntityController<Exam, Exam> {
|
|||
final LmsSetup lmsSetup = this.lmsAPIService.getLmsSetup(exam.lmsSetupId)
|
||||
.getOrThrow();
|
||||
|
||||
if (!lmsSetup.lmsType.features.contains(Features.SEA_RESTRICTION)) {
|
||||
if (!lmsSetup.lmsType.features.contains(Features.SEB_RESTRICTION)) {
|
||||
return Result.ofError(new UnsupportedOperationException(
|
||||
"SEB Restriction feature not available for LMS type: " + lmsSetup.lmsType));
|
||||
}
|
||||
|
@ -405,7 +422,7 @@ public class ExamAdministrationController extends EntityController<Exam, Exam> {
|
|||
if (restrict) {
|
||||
if (!this.lmsAPIService
|
||||
.getLmsSetup(exam.lmsSetupId)
|
||||
.getOrThrow().lmsType.features.contains(Features.SEA_RESTRICTION)) {
|
||||
.getOrThrow().lmsType.features.contains(Features.SEB_RESTRICTION)) {
|
||||
|
||||
return Result.ofError(new APIMessageException(
|
||||
APIMessage.ErrorMessage.ILLEGAL_API_ARGUMENT
|
||||
|
|
|
@ -809,7 +809,6 @@ public class UseCasesIntegrationTest extends GuiIntegrationTest {
|
|||
null, null,
|
||||
Utils.immutableCollectionOf(userId),
|
||||
ExamStatus.RUNNING,
|
||||
true,
|
||||
null,
|
||||
true,
|
||||
null);
|
||||
|
|
|
@ -65,7 +65,6 @@ public class ExamAPITest extends AdministrationAPIIntegrationTester {
|
|||
exam.owner,
|
||||
Arrays.asList("user5"),
|
||||
null,
|
||||
true,
|
||||
null,
|
||||
true,
|
||||
null))
|
||||
|
@ -97,7 +96,6 @@ public class ExamAPITest extends AdministrationAPIIntegrationTester {
|
|||
exam.owner,
|
||||
Arrays.asList("user2"),
|
||||
null,
|
||||
true,
|
||||
null,
|
||||
true,
|
||||
null))
|
||||
|
|
Loading…
Reference in a new issue