SEBSERV-105 GUI implementation and bug-fix
This commit is contained in:
parent
151b6b734a
commit
45fb04955b
16 changed files with 236 additions and 91 deletions
|
@ -35,6 +35,7 @@ public final class Constants {
|
||||||
public static final long HOUR_IN_MILLIS = 60 * MINUTE_IN_MILLIS;
|
public static final long HOUR_IN_MILLIS = 60 * MINUTE_IN_MILLIS;
|
||||||
public static final long DAY_IN_MILLIS = 24 * HOUR_IN_MILLIS;
|
public static final long DAY_IN_MILLIS = 24 * HOUR_IN_MILLIS;
|
||||||
|
|
||||||
|
public static final Character CARRIAGE_RETURN = '\n';
|
||||||
public static final Character CURLY_BRACE_OPEN = '{';
|
public static final Character CURLY_BRACE_OPEN = '{';
|
||||||
public static final Character CURLY_BRACE_CLOSE = '}';
|
public static final Character CURLY_BRACE_CLOSE = '}';
|
||||||
public static final Character COLON = ':';
|
public static final Character COLON = ':';
|
||||||
|
|
|
@ -93,7 +93,7 @@ public class OpenEdxSebRestriction {
|
||||||
public final Collection<String> permissionComponents;
|
public final Collection<String> permissionComponents;
|
||||||
|
|
||||||
@JsonProperty(ATTR_USER_BANNING_ENABLED)
|
@JsonProperty(ATTR_USER_BANNING_ENABLED)
|
||||||
public final boolean banningEnabled;
|
public final Boolean banningEnabled;
|
||||||
|
|
||||||
@JsonCreator
|
@JsonCreator
|
||||||
OpenEdxSebRestriction(
|
OpenEdxSebRestriction(
|
||||||
|
|
|
@ -175,6 +175,56 @@ public final class Utils {
|
||||||
.collect(Collectors.toList()));
|
.collect(Collectors.toList()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Collection<String> getListOfLines(final String list) {
|
||||||
|
if (list == null) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
return Arrays.asList(StringUtils.split(
|
||||||
|
streamlineCarriageReturn(list),
|
||||||
|
Constants.CARRIAGE_RETURN));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String convertCarriageReturnToListSeparator(final String value) {
|
||||||
|
if (value == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return streamlineCarriageReturn(value.trim())
|
||||||
|
.replace(Constants.CARRIAGE_RETURN, Constants.LIST_SEPARATOR_CHAR);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String convertListSeparatorToCarriageReturn(final String value) {
|
||||||
|
if (value == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return value
|
||||||
|
.trim()
|
||||||
|
.replace(Constants.LIST_SEPARATOR_CHAR, Constants.CARRIAGE_RETURN);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String streamlineCarriageReturn(final String value) {
|
||||||
|
if (value == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return value.replace('\r', '\n')
|
||||||
|
.replace("\r\n", "\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Collection<String> getListFromString(final String list) {
|
||||||
|
return getListFromString(list, Constants.LIST_SEPARATOR);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Collection<String> getListFromString(final String list, final String separator) {
|
||||||
|
if (list == null) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
return Arrays.asList(StringUtils.split(list, separator));
|
||||||
|
}
|
||||||
|
|
||||||
public static Result<Long> dateTimeStringToTimestamp(final String startTime) {
|
public static Result<Long> dateTimeStringToTimestamp(final String startTime) {
|
||||||
return Result.tryCatch(() -> {
|
return Result.tryCatch(() -> {
|
||||||
return DateTime.parse(startTime, Constants.STANDARD_DATE_TIME_FORMATTER).getMillis();
|
return DateTime.parse(startTime, Constants.STANDARD_DATE_TIME_FORMATTER).getMillis();
|
||||||
|
|
|
@ -394,6 +394,8 @@ public class ExamForm implements TemplateComposer {
|
||||||
// additional data in read-only view
|
// additional data in read-only view
|
||||||
if (readonly && !importFromQuizData) {
|
if (readonly && !importFromQuizData) {
|
||||||
|
|
||||||
|
this.widgetFactory.labelSeparator(content);
|
||||||
|
|
||||||
// List of SEB Configuration
|
// List of SEB Configuration
|
||||||
this.widgetFactory.labelLocalized(
|
this.widgetFactory.labelLocalized(
|
||||||
content,
|
content,
|
||||||
|
@ -479,6 +481,8 @@ public class ExamForm implements TemplateComposer {
|
||||||
.noEventPropagation()
|
.noEventPropagation()
|
||||||
.publishIf(() -> userGrantCheck.r() && configurationTable.hasAnyContent());
|
.publishIf(() -> userGrantCheck.r() && configurationTable.hasAnyContent());
|
||||||
|
|
||||||
|
this.widgetFactory.labelSeparator(content);
|
||||||
|
|
||||||
// List of Indicators
|
// List of Indicators
|
||||||
this.widgetFactory.labelLocalized(
|
this.widgetFactory.labelLocalized(
|
||||||
content,
|
content,
|
||||||
|
|
|
@ -8,6 +8,9 @@
|
||||||
|
|
||||||
package ch.ethz.seb.sebserver.gui.content;
|
package ch.ethz.seb.sebserver.gui.content;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
|
@ -16,14 +19,14 @@ import java.util.function.Supplier;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.eclipse.swt.widgets.Composite;
|
import org.eclipse.swt.widgets.Composite;
|
||||||
|
|
||||||
|
import ch.ethz.seb.sebserver.gbl.Constants;
|
||||||
import ch.ethz.seb.sebserver.gbl.api.API;
|
import ch.ethz.seb.sebserver.gbl.api.API;
|
||||||
import ch.ethz.seb.sebserver.gbl.api.JSONMapper;
|
|
||||||
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
|
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.exam.OpenEdxSebRestriction;
|
import ch.ethz.seb.sebserver.gbl.model.exam.OpenEdxSebRestriction;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.exam.SebRestriction;
|
import ch.ethz.seb.sebserver.gbl.model.exam.SebRestriction;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetup.LmsType;
|
import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetup.LmsType;
|
||||||
import ch.ethz.seb.sebserver.gbl.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.Form;
|
||||||
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.ResourceService;
|
import ch.ethz.seb.sebserver.gui.service.ResourceService;
|
||||||
|
@ -54,6 +57,10 @@ public class ExamSebRestrictionSettings {
|
||||||
new LocTextKey("sebserver.exam.form.sebrestriction.WHITELIST_PATHS");
|
new LocTextKey("sebserver.exam.form.sebrestriction.WHITELIST_PATHS");
|
||||||
private final static LocTextKey SEB_RESTRICTION_FORM_EDX_PERMISSIONS =
|
private final static LocTextKey SEB_RESTRICTION_FORM_EDX_PERMISSIONS =
|
||||||
new LocTextKey("sebserver.exam.form.sebrestriction.PERMISSION_COMPONENTS");
|
new LocTextKey("sebserver.exam.form.sebrestriction.PERMISSION_COMPONENTS");
|
||||||
|
private final static LocTextKey SEB_RESTRICTION_FORM_EDX_BLACKLIST_CHAPTERS =
|
||||||
|
new LocTextKey("sebserver.exam.form.sebrestriction.BLACKLIST_CHAPTERS");
|
||||||
|
private final static LocTextKey SEB_RESTRICTION_FORM_EDX_USER_BANNING_ENABLED =
|
||||||
|
new LocTextKey("sebserver.exam.form.sebrestriction.USER_BANNING_ENABLED");
|
||||||
|
|
||||||
static final String PAGE_CONTEXT_ATTR_LMS_TYPE = "ATTR_LMS_TYPE";
|
static final String PAGE_CONTEXT_ATTR_LMS_TYPE = "ATTR_LMS_TYPE";
|
||||||
|
|
||||||
|
@ -66,7 +73,8 @@ public class ExamSebRestrictionSettings {
|
||||||
new ModalInputDialog<FormHandle<?>>(
|
new ModalInputDialog<FormHandle<?>>(
|
||||||
action.pageContext().getParent().getShell(),
|
action.pageContext().getParent().getShell(),
|
||||||
pageService.getWidgetFactory())
|
pageService.getWidgetFactory())
|
||||||
.setVeryLargeDialogWidth();
|
.setDialogWidth(740)
|
||||||
|
.setDialogHeight(400);
|
||||||
|
|
||||||
final SebRestrictionPropertiesForm bindFormContext = new SebRestrictionPropertiesForm(
|
final SebRestrictionPropertiesForm bindFormContext = new SebRestrictionPropertiesForm(
|
||||||
pageService,
|
pageService,
|
||||||
|
@ -96,19 +104,35 @@ public class ExamSebRestrictionSettings {
|
||||||
final LmsType lmsType = getLmsType(pageContext);
|
final LmsType lmsType = getLmsType(pageContext);
|
||||||
SebRestriction bodyValue = null;
|
SebRestriction bodyValue = null;
|
||||||
try {
|
try {
|
||||||
final JSONMapper jsonMapper = pageService.getJSONMapper();
|
final Form form = formHandle.getForm();
|
||||||
if (lmsType == LmsType.OPEN_EDX) {
|
final Collection<String> browserKeys = Utils.getListOfLines(
|
||||||
final OpenEdxSebRestriction edxProperties = jsonMapper.readValue(
|
form.getFieldValue(SebRestriction.ATTR_BROWSER_KEYS));
|
||||||
formHandle.getFormBinding().getFormAsJson(),
|
|
||||||
OpenEdxSebRestriction.class);
|
|
||||||
bodyValue = SebRestriction.from(Long.parseLong(entityKey.modelId), edxProperties);
|
|
||||||
} else {
|
|
||||||
bodyValue = jsonMapper.readValue(
|
|
||||||
formHandle.getFormBinding().getFormAsJson(),
|
|
||||||
SebRestriction.class);
|
|
||||||
}
|
|
||||||
} catch (final Exception e) {
|
|
||||||
|
|
||||||
|
final Map<String, String> additionalAttributes = new HashMap<>();
|
||||||
|
if (lmsType == LmsType.OPEN_EDX) {
|
||||||
|
additionalAttributes.put(
|
||||||
|
OpenEdxSebRestriction.ATTR_PERMISSION_COMPONENTS,
|
||||||
|
form.getFieldValue(OpenEdxSebRestriction.ATTR_PERMISSION_COMPONENTS));
|
||||||
|
additionalAttributes.put(
|
||||||
|
OpenEdxSebRestriction.ATTR_WHITELIST_PATHS,
|
||||||
|
form.getFieldValue(OpenEdxSebRestriction.ATTR_WHITELIST_PATHS));
|
||||||
|
additionalAttributes.put(
|
||||||
|
OpenEdxSebRestriction.ATTR_USER_BANNING_ENABLED,
|
||||||
|
form.getFieldValue(OpenEdxSebRestriction.ATTR_USER_BANNING_ENABLED));
|
||||||
|
additionalAttributes.put(
|
||||||
|
OpenEdxSebRestriction.ATTR_BLACKLIST_CHAPTERS,
|
||||||
|
Utils.convertCarriageReturnToListSeparator(
|
||||||
|
form.getFieldValue(OpenEdxSebRestriction.ATTR_BLACKLIST_CHAPTERS)));
|
||||||
|
}
|
||||||
|
|
||||||
|
bodyValue = new SebRestriction(
|
||||||
|
Long.parseLong(entityKey.modelId),
|
||||||
|
null,
|
||||||
|
browserKeys,
|
||||||
|
additionalAttributes);
|
||||||
|
|
||||||
|
} catch (final Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
return !pageService
|
return !pageService
|
||||||
|
@ -116,17 +140,8 @@ public class ExamSebRestrictionSettings {
|
||||||
.getBuilder(SaveSebRestriction.class)
|
.getBuilder(SaveSebRestriction.class)
|
||||||
.withURIVariable(API.PARAM_MODEL_ID, entityKey.modelId)
|
.withURIVariable(API.PARAM_MODEL_ID, entityKey.modelId)
|
||||||
.withBody(bodyValue)
|
.withBody(bodyValue)
|
||||||
//.withFormBinding(formHandle.getFormBinding())
|
|
||||||
.call()
|
.call()
|
||||||
.onError(formHandle::handleError)
|
.onError(formHandle::handleError)
|
||||||
.map(mapping -> {
|
|
||||||
pageService.executePageAction(
|
|
||||||
pageService.pageActionBuilder(pageContext.clearEntityKeys())
|
|
||||||
.newAction(ActionDefinition.EXAM_VIEW_FROM_LIST)
|
|
||||||
.withEntityKey(pageContext.getParentEntityKey())
|
|
||||||
.create());
|
|
||||||
return mapping;
|
|
||||||
})
|
|
||||||
.hasError();
|
.hasError();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -152,15 +167,22 @@ public class ExamSebRestrictionSettings {
|
||||||
final EntityKey entityKey = this.pageContext.getEntityKey();
|
final EntityKey entityKey = this.pageContext.getEntityKey();
|
||||||
final LmsType lmsType = getLmsType(this.pageContext);
|
final LmsType lmsType = getLmsType(this.pageContext);
|
||||||
|
|
||||||
|
final Composite content = this.pageService
|
||||||
|
.getWidgetFactory()
|
||||||
|
.createPopupScrollComposite(parent);
|
||||||
|
|
||||||
final SebRestriction sebRestriction = restService
|
final SebRestriction sebRestriction = restService
|
||||||
.getBuilder(GetSebRestriction.class)
|
.getBuilder(GetSebRestriction.class)
|
||||||
.withURIVariable(API.PARAM_MODEL_ID, entityKey.modelId)
|
.withURIVariable(API.PARAM_MODEL_ID, entityKey.modelId)
|
||||||
.call()
|
.call()
|
||||||
.getOrThrow();
|
.getOrThrow();
|
||||||
|
|
||||||
final PageContext formContext = this.pageContext.clearEntityKeys();
|
final PageContext formContext = this.pageContext
|
||||||
|
.copyOf(content)
|
||||||
|
.clearEntityKeys();
|
||||||
|
|
||||||
final FormHandle<SebRestriction> formHandle = this.pageService.formBuilder(
|
final FormHandle<SebRestriction> formHandle = this.pageService.formBuilder(
|
||||||
formContext.copyOf(parent), 3)
|
formContext, 3)
|
||||||
.withDefaultSpanEmptyCell(0)
|
.withDefaultSpanEmptyCell(0)
|
||||||
.withEmptyCellSeparation(false)
|
.withEmptyCellSeparation(false)
|
||||||
.readonly(false)
|
.readonly(false)
|
||||||
|
@ -168,14 +190,14 @@ public class ExamSebRestrictionSettings {
|
||||||
.addField(FormBuilder.text(
|
.addField(FormBuilder.text(
|
||||||
SebRestriction.ATTR_CONFIG_KEYS,
|
SebRestriction.ATTR_CONFIG_KEYS,
|
||||||
SEB_RESTRICTION_FORM_CONFIG_KEYS,
|
SEB_RESTRICTION_FORM_CONFIG_KEYS,
|
||||||
StringUtils.join(sebRestriction.getConfigKeys(), '\n'))
|
StringUtils.join(sebRestriction.getConfigKeys(), Constants.CARRIAGE_RETURN))
|
||||||
.asArea(25)
|
.asArea(50)
|
||||||
.readonly(true))
|
.readonly(true))
|
||||||
|
|
||||||
.addField(FormBuilder.text(
|
.addField(FormBuilder.text(
|
||||||
SebRestriction.ATTR_BROWSER_KEYS,
|
SebRestriction.ATTR_BROWSER_KEYS,
|
||||||
SEB_RESTRICTION_FORM_BROWSER_KEYS,
|
SEB_RESTRICTION_FORM_BROWSER_KEYS,
|
||||||
StringUtils.join(sebRestriction.getBrowserExamKeys(), '\n'))
|
StringUtils.join(sebRestriction.getBrowserExamKeys(), Constants.CARRIAGE_RETURN))
|
||||||
.asArea())
|
.asArea())
|
||||||
|
|
||||||
.addFieldIf(
|
.addFieldIf(
|
||||||
|
@ -196,6 +218,26 @@ public class ExamSebRestrictionSettings {
|
||||||
.get(OpenEdxSebRestriction.ATTR_PERMISSION_COMPONENTS),
|
.get(OpenEdxSebRestriction.ATTR_PERMISSION_COMPONENTS),
|
||||||
() -> resourceService.sebRestrictionPermissionResources()))
|
() -> resourceService.sebRestrictionPermissionResources()))
|
||||||
|
|
||||||
|
.addFieldIf(
|
||||||
|
() -> lmsType == LmsType.OPEN_EDX,
|
||||||
|
() -> FormBuilder.text(
|
||||||
|
OpenEdxSebRestriction.ATTR_BLACKLIST_CHAPTERS,
|
||||||
|
SEB_RESTRICTION_FORM_EDX_BLACKLIST_CHAPTERS,
|
||||||
|
Utils.convertListSeparatorToCarriageReturn(
|
||||||
|
sebRestriction
|
||||||
|
.getAdditionalProperties()
|
||||||
|
.get(OpenEdxSebRestriction.ATTR_BLACKLIST_CHAPTERS)))
|
||||||
|
.asArea())
|
||||||
|
|
||||||
|
.addFieldIf(
|
||||||
|
() -> lmsType == LmsType.OPEN_EDX,
|
||||||
|
() -> FormBuilder.checkbox(
|
||||||
|
OpenEdxSebRestriction.ATTR_USER_BANNING_ENABLED,
|
||||||
|
SEB_RESTRICTION_FORM_EDX_USER_BANNING_ENABLED,
|
||||||
|
sebRestriction
|
||||||
|
.getAdditionalProperties()
|
||||||
|
.get(OpenEdxSebRestriction.ATTR_USER_BANNING_ENABLED)))
|
||||||
|
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
return () -> formHandle;
|
return () -> formHandle;
|
||||||
|
|
|
@ -149,6 +149,7 @@ public class SebExamConfigList implements TemplateComposer {
|
||||||
|
|
||||||
// configuration template table
|
// configuration template table
|
||||||
widgetFactory.label(content, "");
|
widgetFactory.label(content, "");
|
||||||
|
widgetFactory.labelSeparator(content);
|
||||||
widgetFactory.labelLocalizedTitle(
|
widgetFactory.labelLocalizedTitle(
|
||||||
content,
|
content,
|
||||||
TITLE_TEMPLATE_TEXT_KEY);
|
TITLE_TEMPLATE_TEXT_KEY);
|
||||||
|
@ -192,7 +193,8 @@ public class SebExamConfigList implements TemplateComposer {
|
||||||
.publishIf(examConfigGrant::iw)
|
.publishIf(examConfigGrant::iw)
|
||||||
|
|
||||||
.newAction(ActionDefinition.SEB_EXAM_CONFIG_VIEW_PROP_FROM_LIST)
|
.newAction(ActionDefinition.SEB_EXAM_CONFIG_VIEW_PROP_FROM_LIST)
|
||||||
.withSelect(configTable::getSelection, PageAction::applySingleSelectionAsEntityKey, EMPTY_SELECTION_TEXT_KEY)
|
.withSelect(configTable::getSelection, PageAction::applySingleSelectionAsEntityKey,
|
||||||
|
EMPTY_SELECTION_TEXT_KEY)
|
||||||
.publishIf(() -> configTable.hasAnyContent())
|
.publishIf(() -> configTable.hasAnyContent())
|
||||||
|
|
||||||
.newAction(ActionDefinition.SEB_EXAM_CONFIG_MODIFY_PROP_FROM_LIST)
|
.newAction(ActionDefinition.SEB_EXAM_CONFIG_MODIFY_PROP_FROM_LIST)
|
||||||
|
|
|
@ -289,6 +289,7 @@ public class SebExamConfigPropForm implements TemplateComposer {
|
||||||
|
|
||||||
if (isAttachedToExam) {
|
if (isAttachedToExam) {
|
||||||
|
|
||||||
|
widgetFactory.labelSeparator(content);
|
||||||
widgetFactory.labelLocalized(
|
widgetFactory.labelLocalized(
|
||||||
content,
|
content,
|
||||||
CustomVariant.TEXT_H3,
|
CustomVariant.TEXT_H3,
|
||||||
|
|
|
@ -250,12 +250,12 @@ public enum ActionDefinition {
|
||||||
ActionCategory.FORM),
|
ActionCategory.FORM),
|
||||||
EXAM_ENABLE_SEB_RESTRICTION(
|
EXAM_ENABLE_SEB_RESTRICTION(
|
||||||
new LocTextKey("sebserver.exam.action.sebrestriction.enable"),
|
new LocTextKey("sebserver.exam.action.sebrestriction.enable"),
|
||||||
ImageIcon.LOCK,
|
ImageIcon.UNLOCK,
|
||||||
PageStateDefinitionImpl.EXAM_VIEW,
|
PageStateDefinitionImpl.EXAM_VIEW,
|
||||||
ActionCategory.FORM),
|
ActionCategory.FORM),
|
||||||
EXAM_DISABLE_SEB_RESTRICTION(
|
EXAM_DISABLE_SEB_RESTRICTION(
|
||||||
new LocTextKey("sebserver.exam.action.sebrestriction.disable"),
|
new LocTextKey("sebserver.exam.action.sebrestriction.disable"),
|
||||||
ImageIcon.UNLOCK,
|
ImageIcon.LOCK,
|
||||||
PageStateDefinitionImpl.EXAM_VIEW,
|
PageStateDefinitionImpl.EXAM_VIEW,
|
||||||
ActionCategory.FORM),
|
ActionCategory.FORM),
|
||||||
|
|
||||||
|
|
|
@ -611,7 +611,7 @@ public class ResourceService {
|
||||||
return Arrays.asList(WhiteListPath.values())
|
return Arrays.asList(WhiteListPath.values())
|
||||||
.stream()
|
.stream()
|
||||||
.map(type -> new Tuple<>(
|
.map(type -> new Tuple<>(
|
||||||
type.name(),
|
type.key,
|
||||||
this.i18nSupport.getText(SEB_RESTRICTION_WHITE_LIST_PREFIX + type.name(), type.key)))
|
this.i18nSupport.getText(SEB_RESTRICTION_WHITE_LIST_PREFIX + type.name(), type.key)))
|
||||||
.sorted(RESOURCE_COMPARATOR)
|
.sorted(RESOURCE_COMPARATOR)
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
|
@ -621,7 +621,7 @@ public class ResourceService {
|
||||||
return Arrays.asList(PermissionComponent.values())
|
return Arrays.asList(PermissionComponent.values())
|
||||||
.stream()
|
.stream()
|
||||||
.map(type -> new Tuple<>(
|
.map(type -> new Tuple<>(
|
||||||
type.name(),
|
type.key,
|
||||||
this.i18nSupport.getText(SEB_RESTRICTION_PERMISSIONS_PREFIX + type.name(), type.key)))
|
this.i18nSupport.getText(SEB_RESTRICTION_PERMISSIONS_PREFIX + type.name(), type.key)))
|
||||||
.sorted(RESOURCE_COMPARATOR)
|
.sorted(RESOURCE_COMPARATOR)
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
|
|
|
@ -501,7 +501,7 @@ public class WidgetFactory {
|
||||||
|
|
||||||
public Label labelSeparator(final Composite parent) {
|
public Label labelSeparator(final Composite parent) {
|
||||||
final Label label = new Label(parent, SWT.SEPARATOR | SWT.HORIZONTAL);
|
final Label label = new Label(parent, SWT.SEPARATOR | SWT.HORIZONTAL);
|
||||||
final GridData data = new GridData(SWT.FILL, SWT.TOP, true, true);
|
final GridData data = new GridData(SWT.FILL, SWT.TOP, true, false);
|
||||||
label.setLayoutData(data);
|
label.setLayoutData(data);
|
||||||
return label;
|
return label;
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,7 +38,7 @@ public interface AdditionalAttributesDAO {
|
||||||
* @param entityId the entity identifier (primary key)
|
* @param entityId the entity identifier (primary key)
|
||||||
* @param name the name of the attribute
|
* @param name the name of the attribute
|
||||||
* @param value the value of the attribute */
|
* @param value the value of the attribute */
|
||||||
void saveAdditionalAttribute(
|
Result<AdditionalAttributeRecord> saveAdditionalAttribute(
|
||||||
EntityType type,
|
EntityType type,
|
||||||
Long entityId,
|
Long entityId,
|
||||||
String name,
|
String name,
|
||||||
|
|
|
@ -59,53 +59,60 @@ public class AdditionalAttributesDAOImpl implements AdditionalAttributesDAO {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
public void saveAdditionalAttribute(
|
public Result<AdditionalAttributeRecord> saveAdditionalAttribute(
|
||||||
final EntityType type,
|
final EntityType type,
|
||||||
final Long entityId,
|
final Long entityId,
|
||||||
final String name,
|
final String name,
|
||||||
final String value) {
|
final String value) {
|
||||||
|
|
||||||
if (value == null) {
|
return Result.tryCatch(() -> {
|
||||||
this.delete(entityId, name);
|
if (value == null) {
|
||||||
return;
|
Result.ofError(new IllegalArgumentException(
|
||||||
}
|
"value cannot be null. Use delete to delete an additional attribute"));
|
||||||
|
}
|
||||||
|
|
||||||
final Optional<Long> id = this.additionalAttributeRecordMapperer
|
final Optional<Long> id = this.additionalAttributeRecordMapperer
|
||||||
.selectIdsByExample()
|
.selectIdsByExample()
|
||||||
.where(
|
.where(
|
||||||
AdditionalAttributeRecordDynamicSqlSupport.entityType,
|
AdditionalAttributeRecordDynamicSqlSupport.entityType,
|
||||||
SqlBuilder.isEqualTo(type.name()))
|
SqlBuilder.isEqualTo(type.name()))
|
||||||
.and(
|
.and(
|
||||||
AdditionalAttributeRecordDynamicSqlSupport.entityId,
|
AdditionalAttributeRecordDynamicSqlSupport.entityId,
|
||||||
SqlBuilder.isEqualTo(entityId))
|
SqlBuilder.isEqualTo(entityId))
|
||||||
.and(
|
.and(
|
||||||
AdditionalAttributeRecordDynamicSqlSupport.name,
|
AdditionalAttributeRecordDynamicSqlSupport.name,
|
||||||
SqlBuilder.isEqualTo(name))
|
SqlBuilder.isEqualTo(name))
|
||||||
.build()
|
.build()
|
||||||
.execute()
|
.execute()
|
||||||
.stream()
|
.stream()
|
||||||
.findFirst();
|
.findFirst();
|
||||||
|
|
||||||
if (id.isPresent()) {
|
if (id.isPresent()) {
|
||||||
final AdditionalAttributeRecord rec = new AdditionalAttributeRecord(
|
final AdditionalAttributeRecord rec = new AdditionalAttributeRecord(
|
||||||
id.get(),
|
id.get(),
|
||||||
type.name(),
|
type.name(),
|
||||||
entityId,
|
entityId,
|
||||||
name,
|
name,
|
||||||
value);
|
value);
|
||||||
this.additionalAttributeRecordMapperer
|
this.additionalAttributeRecordMapperer
|
||||||
.updateByPrimaryKeySelective(rec);
|
.updateByPrimaryKeySelective(rec);
|
||||||
} else {
|
|
||||||
final AdditionalAttributeRecord rec = new AdditionalAttributeRecord(
|
|
||||||
null,
|
|
||||||
type.name(),
|
|
||||||
entityId,
|
|
||||||
name,
|
|
||||||
value);
|
|
||||||
this.additionalAttributeRecordMapperer
|
|
||||||
.insert(rec);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
return this.additionalAttributeRecordMapperer
|
||||||
|
.selectByPrimaryKey(rec.getId());
|
||||||
|
} else {
|
||||||
|
final AdditionalAttributeRecord rec = new AdditionalAttributeRecord(
|
||||||
|
null,
|
||||||
|
type.name(),
|
||||||
|
entityId,
|
||||||
|
name,
|
||||||
|
value);
|
||||||
|
this.additionalAttributeRecordMapperer
|
||||||
|
.insert(rec);
|
||||||
|
|
||||||
|
return this.additionalAttributeRecordMapperer
|
||||||
|
.selectByPrimaryKey(rec.getId());
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -206,11 +206,17 @@ public class ExamDAOImpl implements ExamDAO {
|
||||||
(exam.supporter != null)
|
(exam.supporter != null)
|
||||||
? StringUtils.join(exam.supporter, Constants.LIST_SEPARATOR_CHAR)
|
? StringUtils.join(exam.supporter, Constants.LIST_SEPARATOR_CHAR)
|
||||||
: null,
|
: null,
|
||||||
(exam.type != null) ? exam.type.name() : null,
|
(exam.type != null)
|
||||||
|
? exam.type.name()
|
||||||
|
: null,
|
||||||
exam.quitPassword,
|
exam.quitPassword,
|
||||||
null, // browser keys
|
exam.browserExamKeys,
|
||||||
(exam.status != null) ? exam.status.name() : null,
|
(exam.status != null)
|
||||||
BooleanUtils.toIntegerObject(exam.lmsSebRestriction),
|
? exam.status.name()
|
||||||
|
: null,
|
||||||
|
(exam.lmsSebRestriction != null)
|
||||||
|
? BooleanUtils.toIntegerObject(exam.lmsSebRestriction)
|
||||||
|
: null,
|
||||||
null, // updating
|
null, // updating
|
||||||
null, // lastUpdate
|
null, // lastUpdate
|
||||||
null // active
|
null // active
|
||||||
|
|
|
@ -29,10 +29,9 @@ public interface SebRestrictionService {
|
||||||
* and given additional restriction properties within the AdditionalAttrtibutes linked
|
* and given additional restriction properties within the AdditionalAttrtibutes linked
|
||||||
* to the given Exam.
|
* to the given Exam.
|
||||||
*
|
*
|
||||||
*
|
* @param exam the Exam instance to save the SEB restrictions for
|
||||||
* @param exam
|
* @param sebRestriction SebRestriction data containing generic and LMS specific restriction attributes
|
||||||
* @param sebRestriction
|
* @return Result refer to the given Exam instance or to an error if happened */
|
||||||
* @return */
|
|
||||||
Result<Exam> saveSebRestrictionToExam(Exam exam, SebRestriction sebRestriction);
|
Result<Exam> saveSebRestrictionToExam(Exam exam, SebRestriction sebRestriction);
|
||||||
|
|
||||||
/** Used to apply SEB Client restriction within the LMS API for a specified Exam.
|
/** Used to apply SEB Client restriction within the LMS API for a specified Exam.
|
||||||
|
|
|
@ -118,7 +118,10 @@ public class SebRestrictionServiceImpl implements SebRestrictionService {
|
||||||
final Collection<String> browserExamKeys = sebRestriction.getBrowserExamKeys();
|
final Collection<String> browserExamKeys = sebRestriction.getBrowserExamKeys();
|
||||||
final Exam newExam = new Exam(
|
final Exam newExam = new Exam(
|
||||||
exam.id,
|
exam.id,
|
||||||
null, null, null, null, null, null, null, null, null, null, null, null, null, null,
|
null, null, null, null, null, null, null, null, null, null, null,
|
||||||
|
exam.supporter,
|
||||||
|
exam.status,
|
||||||
|
exam.lmsSebRestriction,
|
||||||
(browserExamKeys != null && !browserExamKeys.isEmpty())
|
(browserExamKeys != null && !browserExamKeys.isEmpty())
|
||||||
? StringUtils.join(browserExamKeys, Constants.LIST_SEPARATOR_CHAR)
|
? StringUtils.join(browserExamKeys, Constants.LIST_SEPARATOR_CHAR)
|
||||||
: StringUtils.EMPTY,
|
: StringUtils.EMPTY,
|
||||||
|
|
|
@ -10,6 +10,7 @@ package ch.ethz.seb.sebserver.webservice.weblayer.api;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -36,6 +37,7 @@ import org.springframework.web.bind.annotation.RequestMethod;
|
||||||
import org.springframework.web.bind.annotation.RequestParam;
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import ch.ethz.seb.sebserver.gbl.Constants;
|
||||||
import ch.ethz.seb.sebserver.gbl.api.API;
|
import ch.ethz.seb.sebserver.gbl.api.API;
|
||||||
import ch.ethz.seb.sebserver.gbl.api.APIMessage;
|
import ch.ethz.seb.sebserver.gbl.api.APIMessage;
|
||||||
import ch.ethz.seb.sebserver.gbl.api.APIMessage.APIMessageException;
|
import ch.ethz.seb.sebserver.gbl.api.APIMessage.APIMessageException;
|
||||||
|
@ -47,10 +49,12 @@ import ch.ethz.seb.sebserver.gbl.model.Domain.EXAM;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.Page;
|
import ch.ethz.seb.sebserver.gbl.model.Page;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.PageSortOrder;
|
import ch.ethz.seb.sebserver.gbl.model.PageSortOrder;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.exam.Exam;
|
import ch.ethz.seb.sebserver.gbl.model.exam.Exam;
|
||||||
|
import ch.ethz.seb.sebserver.gbl.model.exam.OpenEdxSebRestriction;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.exam.QuizData;
|
import ch.ethz.seb.sebserver.gbl.model.exam.QuizData;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.exam.SebRestriction;
|
import ch.ethz.seb.sebserver.gbl.model.exam.SebRestriction;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetup;
|
import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetup;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetup.Features;
|
import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetup.Features;
|
||||||
|
import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetup.LmsType;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.user.UserRole;
|
import ch.ethz.seb.sebserver.gbl.model.user.UserRole;
|
||||||
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
|
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
|
||||||
import ch.ethz.seb.sebserver.gbl.util.Result;
|
import ch.ethz.seb.sebserver.gbl.util.Result;
|
||||||
|
@ -60,6 +64,7 @@ import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.Authorization
|
||||||
import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.UserService;
|
import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.UserService;
|
||||||
import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.impl.SEBServerUser;
|
import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.impl.SEBServerUser;
|
||||||
import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.BulkActionService;
|
import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.BulkActionService;
|
||||||
|
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.AdditionalAttributesDAO;
|
||||||
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ExamDAO;
|
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.FilterMap;
|
||||||
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.UserActivityLogDAO;
|
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.UserActivityLogDAO;
|
||||||
|
@ -79,6 +84,7 @@ public class ExamAdministrationController extends EntityController<Exam, Exam> {
|
||||||
|
|
||||||
private final ExamDAO examDAO;
|
private final ExamDAO examDAO;
|
||||||
private final UserDAO userDAO;
|
private final UserDAO userDAO;
|
||||||
|
private final AdditionalAttributesDAO additionalAttributesDAO;
|
||||||
private final LmsAPIService lmsAPIService;
|
private final LmsAPIService lmsAPIService;
|
||||||
private final ExamConfigService sebExamConfigService;
|
private final ExamConfigService sebExamConfigService;
|
||||||
private final ExamSessionService examSessionService;
|
private final ExamSessionService examSessionService;
|
||||||
|
@ -95,7 +101,8 @@ public class ExamAdministrationController extends EntityController<Exam, Exam> {
|
||||||
final UserDAO userDAO,
|
final UserDAO userDAO,
|
||||||
final ExamConfigService sebExamConfigService,
|
final ExamConfigService sebExamConfigService,
|
||||||
final ExamSessionService examSessionService,
|
final ExamSessionService examSessionService,
|
||||||
final SebRestrictionService sebRestrictionService) {
|
final SebRestrictionService sebRestrictionService,
|
||||||
|
final AdditionalAttributesDAO additionalAttributesDAO) {
|
||||||
|
|
||||||
super(authorization,
|
super(authorization,
|
||||||
bulkActionService,
|
bulkActionService,
|
||||||
|
@ -106,6 +113,7 @@ public class ExamAdministrationController extends EntityController<Exam, Exam> {
|
||||||
|
|
||||||
this.examDAO = examDAO;
|
this.examDAO = examDAO;
|
||||||
this.userDAO = userDAO;
|
this.userDAO = userDAO;
|
||||||
|
this.additionalAttributesDAO = additionalAttributesDAO;
|
||||||
this.lmsAPIService = lmsAPIService;
|
this.lmsAPIService = lmsAPIService;
|
||||||
this.sebExamConfigService = sebExamConfigService;
|
this.sebExamConfigService = sebExamConfigService;
|
||||||
this.examSessionService = examSessionService;
|
this.examSessionService = examSessionService;
|
||||||
|
@ -278,7 +286,6 @@ public class ExamAdministrationController extends EntityController<Exam, Exam> {
|
||||||
@PathVariable(API.PARAM_MODEL_ID) final Long examlId) {
|
@PathVariable(API.PARAM_MODEL_ID) final Long examlId) {
|
||||||
|
|
||||||
checkModifyPrivilege(institutionId);
|
checkModifyPrivilege(institutionId);
|
||||||
|
|
||||||
return this.entityDAO.byPK(examlId)
|
return this.entityDAO.byPK(examlId)
|
||||||
.flatMap(this.authorization::checkModify)
|
.flatMap(this.authorization::checkModify)
|
||||||
.flatMap(exam -> this.applySebRestriction(exam, true))
|
.flatMap(exam -> this.applySebRestriction(exam, true))
|
||||||
|
@ -328,6 +335,33 @@ public class ExamAdministrationController extends EntityController<Exam, Exam> {
|
||||||
.getOrThrow();
|
.getOrThrow();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Result<Exam> notifyCreated(final Exam entity) {
|
||||||
|
return Result.tryCatch(() -> {
|
||||||
|
|
||||||
|
final LmsSetup lmsSetup = this.lmsAPIService.getLmsSetup(entity.lmsSetupId)
|
||||||
|
.getOrThrow();
|
||||||
|
|
||||||
|
// if we have an Open edX LMS involved, add additional initial SEB restriction attributes
|
||||||
|
if (lmsSetup.lmsType == LmsType.OPEN_EDX) {
|
||||||
|
final List<String> permissions = Arrays.asList(
|
||||||
|
OpenEdxSebRestriction.PermissionComponent.ALWAYS_ALLOW_STUFF.key,
|
||||||
|
OpenEdxSebRestriction.PermissionComponent.CHECK_CONFIG_KEY.key);
|
||||||
|
|
||||||
|
this.additionalAttributesDAO.saveAdditionalAttribute(
|
||||||
|
EntityType.EXAM,
|
||||||
|
entity.id,
|
||||||
|
SebRestrictionService.SEB_RESTRICTION_ADDITIONAL_PROPERTY_NAME_PREFIX +
|
||||||
|
OpenEdxSebRestriction.ATTR_PERMISSION_COMPONENTS,
|
||||||
|
StringUtils.join(permissions, Constants.LIST_SEPARATOR_CHAR))
|
||||||
|
.getOrThrow();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return entity;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Result<Exam> validForCreate(final Exam entity) {
|
protected Result<Exam> validForCreate(final Exam entity) {
|
||||||
return super.validForCreate(entity)
|
return super.validForCreate(entity)
|
||||||
|
@ -381,10 +415,6 @@ public class ExamAdministrationController extends EntityController<Exam, Exam> {
|
||||||
"SEB Restriction feature not available for LMS type: " + lmsSetup.lmsType));
|
"SEB Restriction feature not available for LMS type: " + lmsSetup.lmsType));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (BooleanUtils.toBoolean(exam.lmsSebRestriction) == restrict) {
|
|
||||||
return Result.of(exam);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (restrict) {
|
if (restrict) {
|
||||||
if (!this.lmsAPIService
|
if (!this.lmsAPIService
|
||||||
.getLmsSetup(exam.lmsSetupId)
|
.getLmsSetup(exam.lmsSetupId)
|
||||||
|
|
Loading…
Reference in a new issue