add warning if course imported twice and seb restriction readonly view
This commit is contained in:
parent
b6466d8f1d
commit
be7a7cef77
14 changed files with 174 additions and 42 deletions
|
@ -118,6 +118,7 @@ public final class API {
|
|||
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_ADMINISTRATION_CHECK_IMPORTED_PATH_SEGMENT = "/check-imported";
|
||||
|
||||
public static final String EXAM_INDICATOR_ENDPOINT = "/indicator";
|
||||
|
||||
|
|
|
@ -400,6 +400,7 @@ public class ExamForm implements TemplateComposer {
|
|||
.withURIVariable(API.PARAM_MODEL_ID, String.valueOf(exam.lmsSetupId))
|
||||
.call()
|
||||
.getOrThrow().lmsType.name())
|
||||
.withAttribute(PageContext.AttributeKeys.FORCE_READ_ONLY, String.valueOf(!modifyGrant))
|
||||
.noEventPropagation()
|
||||
.publishIf(() -> sebRestrictionAvailable && readonly)
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@ import java.util.function.Function;
|
|||
import java.util.function.Predicate;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.apache.commons.lang3.BooleanUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.eclipse.swt.widgets.Composite;
|
||||
|
||||
|
@ -104,6 +105,12 @@ public class ExamSebRestrictionSettings {
|
|||
final PageContext pageContext,
|
||||
final FormHandle<?> formHandle) {
|
||||
|
||||
final boolean isReadonly = BooleanUtils.toBoolean(
|
||||
pageContext.getAttribute(PageContext.AttributeKeys.FORCE_READ_ONLY));
|
||||
if (isReadonly) {
|
||||
return true;
|
||||
}
|
||||
|
||||
final EntityKey entityKey = pageContext.getEntityKey();
|
||||
final LmsType lmsType = getLmsType(pageContext);
|
||||
SebRestriction bodyValue = null;
|
||||
|
@ -170,6 +177,8 @@ public class ExamSebRestrictionSettings {
|
|||
final ResourceService resourceService = this.pageService.getResourceService();
|
||||
final EntityKey entityKey = this.pageContext.getEntityKey();
|
||||
final LmsType lmsType = getLmsType(this.pageContext);
|
||||
final boolean isReadonly = BooleanUtils.toBoolean(
|
||||
this.pageContext.getAttribute(PageContext.AttributeKeys.FORCE_READ_ONLY));
|
||||
|
||||
final Composite content = this.pageService
|
||||
.getWidgetFactory()
|
||||
|
@ -189,12 +198,12 @@ public class ExamSebRestrictionSettings {
|
|||
formContext)
|
||||
.withDefaultSpanInput(6)
|
||||
.withEmptyCellSeparation(false)
|
||||
.readonly(false)
|
||||
.readonly(isReadonly)
|
||||
|
||||
.addField(FormBuilder.text(
|
||||
"Info",
|
||||
SEB_RESTRICTION_FORM_INFO,
|
||||
pageService.getI18nSupport().getText(SEB_RESTRICTION_FORM_INFO_TEXT))
|
||||
this.pageService.getI18nSupport().getText(SEB_RESTRICTION_FORM_INFO_TEXT))
|
||||
.asArea(50)
|
||||
.asHTML()
|
||||
.readonly(true))
|
||||
|
@ -254,6 +263,7 @@ public class ExamSebRestrictionSettings {
|
|||
|
||||
return () -> formHandle;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static LmsType getLmsType(final PageContext pageContext) {
|
||||
|
|
|
@ -13,7 +13,6 @@ import java.util.Collection;
|
|||
import java.util.function.BooleanSupplier;
|
||||
import java.util.function.Function;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.Constants;
|
||||
import org.eclipse.swt.widgets.Composite;
|
||||
import org.joda.time.DateTime;
|
||||
import org.joda.time.DateTimeZone;
|
||||
|
@ -21,6 +20,8 @@ import org.springframework.beans.factory.annotation.Value;
|
|||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.Constants;
|
||||
import ch.ethz.seb.sebserver.gbl.api.API;
|
||||
import ch.ethz.seb.sebserver.gbl.api.EntityType;
|
||||
import ch.ethz.seb.sebserver.gbl.model.Entity;
|
||||
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
|
||||
|
@ -43,6 +44,7 @@ import ch.ethz.seb.sebserver.gui.service.page.TemplateComposer;
|
|||
import ch.ethz.seb.sebserver.gui.service.page.impl.ModalInputDialog;
|
||||
import ch.ethz.seb.sebserver.gui.service.page.impl.PageAction;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestService;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.CheckExamImported;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.quiz.GetQuizPage;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.CurrentUser;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.CurrentUser.GrantCheck;
|
||||
|
@ -55,7 +57,7 @@ import ch.ethz.seb.sebserver.gui.widget.WidgetFactory;
|
|||
@Lazy
|
||||
@Component
|
||||
@GuiProfile
|
||||
public class QuizDiscoveryList implements TemplateComposer {
|
||||
public class QuizLookupList implements TemplateComposer {
|
||||
|
||||
// localized text keys
|
||||
|
||||
|
@ -93,6 +95,8 @@ public class QuizDiscoveryList implements TemplateComposer {
|
|||
new LocTextKey("sebserver.quizdiscovery.quiz.details.endtime");
|
||||
private final static LocTextKey NO_IMPORT_OF_OUT_DATED_QUIZ =
|
||||
new LocTextKey("sebserver.quizdiscovery.quiz.import.out.dated");
|
||||
private final static LocTextKey TEXT_KEY_CONFIRM_EXISTING =
|
||||
new LocTextKey("sebserver.quizdiscovery.quiz.import.existing.confirm");
|
||||
|
||||
private final static String TEXT_KEY_ADDITIONAL_ATTR_PREFIX =
|
||||
"sebserver.quizdiscovery.quiz.details.additional.";
|
||||
|
@ -109,7 +113,7 @@ public class QuizDiscoveryList implements TemplateComposer {
|
|||
private final PageService pageService;
|
||||
private final int pageSize;
|
||||
|
||||
protected QuizDiscoveryList(
|
||||
protected QuizLookupList(
|
||||
final PageService pageService,
|
||||
final ResourceService resourceService,
|
||||
@Value("${sebserver.gui.list.page.size:20}") final Integer pageSize) {
|
||||
|
@ -232,6 +236,7 @@ public class QuizDiscoveryList implements TemplateComposer {
|
|||
.publishIf(table::hasAnyContent, false)
|
||||
|
||||
.newAction(ActionDefinition.QUIZ_DISCOVERY_EXAM_IMPORT)
|
||||
.withConfirm(importQuizConfirm(table, restService))
|
||||
.withSelect(
|
||||
table::getSelection,
|
||||
action -> this.importQuizData(action, table),
|
||||
|
@ -244,7 +249,31 @@ public class QuizDiscoveryList implements TemplateComposer {
|
|||
.apply(String.valueOf(quizData.lmsSetupId));
|
||||
}
|
||||
|
||||
private PageAction importQuizData(final PageAction action, final EntityTable<QuizData> table) {
|
||||
private Function<PageAction, LocTextKey> importQuizConfirm(
|
||||
final EntityTable<QuizData> table,
|
||||
final RestService restService) {
|
||||
|
||||
return action -> {
|
||||
action.getSingleSelection();
|
||||
final QuizData selectedROWData = table.getSingleSelectedROWData();
|
||||
|
||||
final Collection<EntityKey> existingImports = restService.getBuilder(CheckExamImported.class)
|
||||
.withURIVariable(API.PARAM_MODEL_ID, selectedROWData.id)
|
||||
.call()
|
||||
.getOrThrow();
|
||||
|
||||
if (existingImports != null && !existingImports.isEmpty()) {
|
||||
return TEXT_KEY_CONFIRM_EXISTING;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private PageAction importQuizData(
|
||||
final PageAction action,
|
||||
final EntityTable<QuizData> table) {
|
||||
|
||||
action.getSingleSelection();
|
||||
final QuizData selectedROWData = table.getSingleSelectedROWData();
|
||||
|
|
@ -21,7 +21,7 @@ import ch.ethz.seb.sebserver.gui.content.LmsSetupList;
|
|||
import ch.ethz.seb.sebserver.gui.content.MonitoringClientConnection;
|
||||
import ch.ethz.seb.sebserver.gui.content.MonitoringRunningExam;
|
||||
import ch.ethz.seb.sebserver.gui.content.MonitoringRunningExamList;
|
||||
import ch.ethz.seb.sebserver.gui.content.QuizDiscoveryList;
|
||||
import ch.ethz.seb.sebserver.gui.content.QuizLookupList;
|
||||
import ch.ethz.seb.sebserver.gui.content.SebClientConfigForm;
|
||||
import ch.ethz.seb.sebserver.gui.content.SebClientConfigList;
|
||||
import ch.ethz.seb.sebserver.gui.content.SebClientLogs;
|
||||
|
@ -52,7 +52,7 @@ public enum PageStateDefinitionImpl implements PageStateDefinition {
|
|||
LMS_SETUP_VIEW(Type.FORM_VIEW, LmsSetupForm.class, ActivityDefinition.LMS_SETUP),
|
||||
LMS_SETUP_EDIT(Type.FORM_EDIT, LmsSetupForm.class, ActivityDefinition.LMS_SETUP),
|
||||
|
||||
QUIZ_LIST(Type.LIST_VIEW, QuizDiscoveryList.class, ActivityDefinition.QUIZ_DISCOVERY),
|
||||
QUIZ_LIST(Type.LIST_VIEW, QuizLookupList.class, ActivityDefinition.QUIZ_DISCOVERY),
|
||||
|
||||
EXAM_LIST(Type.LIST_VIEW, ExamList.class, ActivityDefinition.EXAM),
|
||||
EXAM_VIEW(Type.FORM_VIEW, ExamForm.class, ActivityDefinition.EXAM),
|
||||
|
|
|
@ -14,7 +14,6 @@ import java.util.List;
|
|||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import ch.ethz.seb.sebserver.gui.service.page.PageService;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.eclipse.swt.SWT;
|
||||
import org.eclipse.swt.layout.GridData;
|
||||
|
@ -28,6 +27,7 @@ import ch.ethz.seb.sebserver.gbl.Constants;
|
|||
import ch.ethz.seb.sebserver.gbl.util.Tuple;
|
||||
import ch.ethz.seb.sebserver.gui.service.i18n.LocTextKey;
|
||||
import ch.ethz.seb.sebserver.gui.service.i18n.PolyglotPageService;
|
||||
import ch.ethz.seb.sebserver.gui.service.page.PageService;
|
||||
import ch.ethz.seb.sebserver.gui.widget.Selection;
|
||||
import ch.ethz.seb.sebserver.gui.widget.Selection.Type;
|
||||
|
||||
|
@ -73,7 +73,7 @@ public final class SelectionFieldBuilder extends FieldBuilder<String> {
|
|||
this.type,
|
||||
fieldGrid,
|
||||
this.itemsSupplier,
|
||||
(builder.pageService.getFormTooltipMode() == PageService.FormTooltipMode.INPUT) ? tooltip : null,
|
||||
(builder.pageService.getFormTooltipMode() == PageService.FormTooltipMode.INPUT) ? this.tooltip : null,
|
||||
null,
|
||||
actionKey);
|
||||
|
||||
|
@ -108,7 +108,7 @@ public final class SelectionFieldBuilder extends FieldBuilder<String> {
|
|||
final GridData gridData = new GridData(SWT.FILL, SWT.TOP, true, true);
|
||||
|
||||
label.setLayoutData(gridData);
|
||||
label.setText(this.value);
|
||||
label.setText((this.value != null) ? this.value : Constants.EMPTY_NOTE);
|
||||
} else {
|
||||
final Collection<String> keys = Arrays.asList(StringUtils.split(this.value, Constants.LIST_SEPARATOR));
|
||||
this.itemsSupplier.get()
|
||||
|
|
|
@ -32,6 +32,7 @@ public interface PageContext {
|
|||
String PAGE_TEMPLATE_COMPOSER_NAME = "ATTR_PAGE_TEMPLATE_COMPOSER_NAME";
|
||||
|
||||
String READ_ONLY = "READ_ONLY";
|
||||
String FORCE_READ_ONLY = "FORCE_READ_ONLY";
|
||||
String READ_ONLY_FROM = "READ_ONLY_FROM";
|
||||
|
||||
String ENTITY_ID = "ENTITY_ID";
|
||||
|
|
|
@ -129,8 +129,9 @@ public interface PageService {
|
|||
*
|
||||
* @param table the entity table
|
||||
* @param noSelectionText LocTextKey for missing selection message
|
||||
* @param testBeforeActivation a function to test before activation. This function shall throw an error if test fails.
|
||||
* My be null if no specific test is needed before activation
|
||||
* @param testBeforeActivation a function to test before activation. This function shall throw an error if test
|
||||
* fails.
|
||||
* My be null if no specific test is needed before activation
|
||||
* @return page action execution function for switching the activity */
|
||||
<T extends Entity & Activatable> Function<PageAction, PageAction> activationToggleActionFunction(
|
||||
EntityTable<T> table,
|
||||
|
@ -144,8 +145,8 @@ public interface PageService {
|
|||
* @param noSelectionText LocTextKey for missing selection message
|
||||
* @return page action execution function for switching the activity */
|
||||
default <T extends Entity & Activatable> Function<PageAction, PageAction> activationToggleActionFunction(
|
||||
EntityTable<T> table,
|
||||
LocTextKey noSelectionText) {
|
||||
final EntityTable<T> table,
|
||||
final LocTextKey noSelectionText) {
|
||||
return this.activationToggleActionFunction(table, noSelectionText, null);
|
||||
}
|
||||
|
||||
|
@ -399,7 +400,7 @@ public interface PageService {
|
|||
|
||||
private PageContext pageContext;
|
||||
private ActionDefinition definition;
|
||||
private Supplier<LocTextKey> confirm;
|
||||
private Function<PageAction, LocTextKey> confirm;
|
||||
private LocTextKey successMessage;
|
||||
private Supplier<Set<EntityKey>> selectionSupplier;
|
||||
private LocTextKey noSelectionMessage;
|
||||
|
@ -508,6 +509,11 @@ public interface PageService {
|
|||
}
|
||||
|
||||
public PageActionBuilder withConfirm(final Supplier<LocTextKey> confirm) {
|
||||
this.confirm = action -> confirm.get();
|
||||
return this;
|
||||
}
|
||||
|
||||
public PageActionBuilder withConfirm(final Function<PageAction, LocTextKey> confirm) {
|
||||
this.confirm = confirm;
|
||||
return this;
|
||||
}
|
||||
|
|
|
@ -35,7 +35,7 @@ public final class PageAction {
|
|||
private static final Logger log = LoggerFactory.getLogger(PageAction.class);
|
||||
|
||||
public final ActionDefinition definition;
|
||||
private final Supplier<LocTextKey> confirm;
|
||||
private final Function<PageAction, LocTextKey> confirm;
|
||||
private final Supplier<Set<EntityKey>> selectionSupplier;
|
||||
private final LocTextKey noSelectionMessage;
|
||||
private PageContext pageContext;
|
||||
|
@ -48,7 +48,7 @@ public final class PageAction {
|
|||
|
||||
public PageAction(
|
||||
final ActionDefinition definition,
|
||||
final Supplier<LocTextKey> confirm,
|
||||
final Function<PageAction, LocTextKey> confirm,
|
||||
final LocTextKey successMessage,
|
||||
final Supplier<Set<EntityKey>> selectionSupplier,
|
||||
final LocTextKey noSelectionMessage,
|
||||
|
@ -154,7 +154,7 @@ public final class PageAction {
|
|||
}
|
||||
}
|
||||
|
||||
final LocTextKey confirmMessage = this.confirm.get();
|
||||
final LocTextKey confirmMessage = this.confirm.apply(this);
|
||||
if (confirmMessage != null) {
|
||||
this.pageContext.applyConfirmDialog(confirmMessage,
|
||||
confirm -> callback.accept((confirm)
|
||||
|
@ -198,9 +198,6 @@ 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,44 @@
|
|||
/*
|
||||
* 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 java.util.Collection;
|
||||
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.api.API;
|
||||
import ch.ethz.seb.sebserver.gbl.api.EntityType;
|
||||
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
|
||||
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCall;
|
||||
|
||||
@Lazy
|
||||
@Component
|
||||
@GuiProfile
|
||||
public class CheckExamImported extends RestCall<Collection<EntityKey>> {
|
||||
|
||||
public CheckExamImported() {
|
||||
super(new TypeKey<>(
|
||||
CallType.UNDEFINED,
|
||||
EntityType.EXAM,
|
||||
new TypeReference<Collection<EntityKey>>() {
|
||||
}),
|
||||
HttpMethod.GET,
|
||||
MediaType.APPLICATION_FORM_URLENCODED,
|
||||
API.EXAM_ADMINISTRATION_ENDPOINT
|
||||
+ API.MODEL_ID_VAR_PATH_SEGMENT
|
||||
+ API.EXAM_ADMINISTRATION_CHECK_IMPORTED_PATH_SEGMENT);
|
||||
}
|
||||
|
||||
}
|
|
@ -28,6 +28,8 @@ public interface ExamDAO extends ActivatableEntityDAO<Exam, Exam>, BulkActionSup
|
|||
* happened */
|
||||
Result<Collection<Long>> allIdsOfInstitution(Long institutionId);
|
||||
|
||||
Result<Collection<Long>> allByQuizId(String quizId);
|
||||
|
||||
/** Updates the exam status for specified exam
|
||||
*
|
||||
* @param examId The exam identifier
|
||||
|
|
|
@ -111,6 +111,24 @@ public class ExamDAOImpl implements ExamDAO {
|
|||
.flatMap(this::toDomainModel);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result<Collection<Long>> allByQuizId(final String quizId) {
|
||||
return Result.tryCatch(() -> {
|
||||
return this.examRecordMapper.selectByExample()
|
||||
.where(
|
||||
ExamRecordDynamicSqlSupport.externalId,
|
||||
isEqualToWhenPresent(quizId))
|
||||
.and(
|
||||
ExamRecordDynamicSqlSupport.active,
|
||||
isEqualToWhenPresent(BooleanUtils.toIntegerObject(true)))
|
||||
.build()
|
||||
.execute()
|
||||
.stream()
|
||||
.map(rec -> rec.getId())
|
||||
.collect(Collectors.toList());
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(readOnly = true)
|
||||
public Result<Collection<Exam>> allMatching(final FilterMap filterMap, final Predicate<Exam> predicate) {
|
||||
|
@ -258,24 +276,24 @@ 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,
|
||||
(exam.type != null) ? exam.type.name() : ExamType.UNDEFINED.name(),
|
||||
null, // quitPassword
|
||||
null, // browser keys
|
||||
null, // status
|
||||
null, // lmsSebRestriction (deprecated)
|
||||
null, // updating
|
||||
null, // lastUpdate
|
||||
BooleanUtils.toIntegerObject(exam.active));
|
||||
// if the same institution tries to import an exam that already exists
|
||||
// open the existing. otherwise create new one if requested
|
||||
if (exam.institutionId.equals(examRecord.getInstitutionId())) {
|
||||
final ExamRecord newRecord = new ExamRecord(
|
||||
examRecord.getId(),
|
||||
null, null, null, null, null,
|
||||
(exam.type != null) ? exam.type.name() : ExamType.UNDEFINED.name(),
|
||||
null, // quitPassword
|
||||
null, // browser keys
|
||||
null, // status
|
||||
null, // lmsSebRestriction (deprecated)
|
||||
null, // updating
|
||||
null, // lastUpdate
|
||||
BooleanUtils.toIntegerObject(exam.active));
|
||||
|
||||
this.examRecordMapper.updateByPrimaryKeySelective(newRecord);
|
||||
return this.examRecordMapper.selectByPrimaryKey(examRecord.getId());
|
||||
this.examRecordMapper.updateByPrimaryKeySelective(newRecord);
|
||||
return this.examRecordMapper.selectByPrimaryKey(examRecord.getId());
|
||||
}
|
||||
}
|
||||
|
||||
final ExamRecord examRecord = new ExamRecord(
|
||||
|
|
|
@ -45,6 +45,7 @@ import ch.ethz.seb.sebserver.gbl.api.POSTMapper;
|
|||
import ch.ethz.seb.sebserver.gbl.api.authorization.PrivilegeType;
|
||||
import ch.ethz.seb.sebserver.gbl.model.Domain;
|
||||
import ch.ethz.seb.sebserver.gbl.model.Domain.EXAM;
|
||||
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
|
||||
import ch.ethz.seb.sebserver.gbl.model.Page;
|
||||
import ch.ethz.seb.sebserver.gbl.model.PageSortOrder;
|
||||
import ch.ethz.seb.sebserver.gbl.model.exam.Exam;
|
||||
|
@ -208,6 +209,27 @@ public class ExamAdministrationController extends EntityController<Exam, Exam> {
|
|||
}
|
||||
}
|
||||
|
||||
@RequestMapping(
|
||||
path = API.MODEL_ID_VAR_PATH_SEGMENT
|
||||
+ API.EXAM_ADMINISTRATION_CHECK_IMPORTED_PATH_SEGMENT,
|
||||
method = RequestMethod.GET,
|
||||
produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
|
||||
public Collection<EntityKey> checkImported(
|
||||
@PathVariable final String modelId,
|
||||
@RequestParam(
|
||||
name = API.PARAM_INSTITUTION_ID,
|
||||
required = true,
|
||||
defaultValue = UserService.USERS_INSTITUTION_AS_DEFAULT) final Long institutionId) {
|
||||
|
||||
checkReadPrivilege(institutionId);
|
||||
return this.examDAO.allByQuizId(modelId)
|
||||
.map(ids -> ids
|
||||
.stream()
|
||||
.map(id -> new EntityKey(id, EntityType.EXAM))
|
||||
.collect(Collectors.toList()))
|
||||
.getOrThrow();
|
||||
}
|
||||
|
||||
@RequestMapping(
|
||||
path = API.MODEL_ID_VAR_PATH_SEGMENT
|
||||
+ API.EXAM_ADMINISTRATION_CONSISTENCY_CHECK_PATH_SEGMENT,
|
||||
|
@ -226,6 +248,9 @@ public class ExamAdministrationController extends EntityController<Exam, Exam> {
|
|||
.getOrThrow();
|
||||
}
|
||||
|
||||
// ****************************************************************************
|
||||
// **** SEB Restriction
|
||||
|
||||
@RequestMapping(
|
||||
path = API.MODEL_ID_VAR_PATH_SEGMENT
|
||||
+ API.EXAM_ADMINISTRATION_CHECK_RESTRICTION_PATH_SEGMENT,
|
||||
|
@ -244,9 +269,6 @@ public class ExamAdministrationController extends EntityController<Exam, Exam> {
|
|||
.getOrThrow();
|
||||
}
|
||||
|
||||
// ****************************************************************************
|
||||
// **** SEB Restriction
|
||||
|
||||
@RequestMapping(
|
||||
path = API.MODEL_ID_VAR_PATH_SEGMENT
|
||||
+ API.EXAM_ADMINISTRATION_SEB_RESTRICTION_PATH_SEGMENT,
|
||||
|
|
|
@ -350,6 +350,7 @@ sebserver.quizdiscovery.action.list=LMS Exam Lookup
|
|||
sebserver.quizdiscovery.action.import=Import as Exam
|
||||
sebserver.quizdiscovery.quiz.import.out.dated=The Selected LMS exam is is already finished and can't be imported
|
||||
sebserver.quizdiscovery.action.details=Show LMS Exam Details
|
||||
sebserver.quizdiscovery.quiz.import.existing.confirm=This course was already imported and import it twice may lead to<br/> unexpected behavior within automated SEB restriction on LMS.<br/><br/> Do you want to import this course as exam anyways?
|
||||
|
||||
sebserver.quizdiscovery.quiz.details.title=LMS Exam Details
|
||||
sebserver.quizdiscovery.quiz.details.institution=Institution
|
||||
|
|
Loading…
Add table
Reference in a new issue