SEBSERV-72 back and front-end implementation
This commit is contained in:
parent
80effa4fe9
commit
b71968628c
29 changed files with 1070 additions and 68 deletions
|
@ -8,6 +8,8 @@
|
|||
|
||||
package ch.ethz.seb.sebserver.gbl.api;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode;
|
||||
|
||||
public final class API {
|
||||
|
||||
public enum BulkActionType {
|
||||
|
@ -25,6 +27,7 @@ public final class API {
|
|||
public static final String PARAM_ENTITY_TYPE = "entityType";
|
||||
public static final String PARAM_BULK_ACTION_TYPE = "bulkActionType";
|
||||
public static final String PARAM_CLIENT_CONFIG_SECRET = "client_config_secret";
|
||||
public static final String DEFAULT_CONFIG_TEMPLATE_ID = String.valueOf(ConfigurationNode.DEFAULT_TEMPLATE_ID);
|
||||
|
||||
public static final String INSTITUTION_VAR_PATH_SEGMENT = "/{" + PARAM_INSTITUTION_ID + "}";
|
||||
public static final String MODEL_ID_VAR_PATH_SEGMENT = "/{" + PARAM_MODEL_ID + "}";
|
||||
|
@ -124,6 +127,10 @@ public final class API {
|
|||
public static final String IMPORT_PASSWORD_ATTR_NAME = "importFilePassword";
|
||||
public static final String IMPORT_FILE_ATTR_NAME = "importFile";
|
||||
|
||||
public static final String TEMPLATE_ATTRIBUTE_ENDPOINT = "/template-attribute";
|
||||
|
||||
public static final String CONFIGURATION_TEMPLATE_ENDPOINT = "/exam-config-template";
|
||||
|
||||
public static final String ORIENTATION_ENDPOINT = "/orientation";
|
||||
public static final String VIEW_ENDPOINT = ORIENTATION_ENDPOINT + "/view";
|
||||
|
||||
|
|
|
@ -0,0 +1,156 @@
|
|||
/*
|
||||
* 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.gbl.model.sebconfig;
|
||||
|
||||
import java.util.Comparator;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.api.EntityType;
|
||||
import ch.ethz.seb.sebserver.gbl.model.Domain.CONFIGURATION;
|
||||
import ch.ethz.seb.sebserver.gbl.model.Entity;
|
||||
|
||||
public final class TemplateAttribute implements Entity {
|
||||
|
||||
public static final String ATTR_CONFIG_ATTRIBUTE = "configAttribute";
|
||||
public static final String ATTR_ORIENTATION = "orientation";
|
||||
|
||||
public static final String FILTER_ATTR_VIEW = "view";
|
||||
public static final String FILTER_ATTR_GROUP = "group";
|
||||
|
||||
@NotNull
|
||||
@JsonProperty(CONFIGURATION.ATTR_INSTITUTION_ID)
|
||||
public final Long institutionId;
|
||||
|
||||
@NotNull
|
||||
@JsonProperty(CONFIGURATION.ATTR_CONFIGURATION_NODE_ID)
|
||||
public final Long templateId;
|
||||
|
||||
@NotNull
|
||||
@JsonProperty(ATTR_CONFIG_ATTRIBUTE)
|
||||
private final ConfigurationAttribute configAttribute;
|
||||
|
||||
@JsonProperty(ATTR_ORIENTATION)
|
||||
private final Orientation orientation;
|
||||
|
||||
public TemplateAttribute(
|
||||
@JsonProperty(CONFIGURATION.ATTR_INSTITUTION_ID) final Long institutionId,
|
||||
@JsonProperty(CONFIGURATION.ATTR_CONFIGURATION_NODE_ID) final Long templateId,
|
||||
@JsonProperty(ATTR_CONFIG_ATTRIBUTE) final ConfigurationAttribute configAttribute,
|
||||
@JsonProperty(ATTR_ORIENTATION) final Orientation orientation) {
|
||||
|
||||
this.institutionId = institutionId;
|
||||
this.templateId = templateId;
|
||||
this.configAttribute = configAttribute;
|
||||
this.orientation = orientation;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getModelId() {
|
||||
return this.institutionId != null
|
||||
? String.valueOf(this.institutionId)
|
||||
: null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityType entityType() {
|
||||
return EntityType.CONFIGURATION_NODE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return this.configAttribute.name;
|
||||
}
|
||||
|
||||
public Long getInstitutionId() {
|
||||
return this.institutionId;
|
||||
}
|
||||
|
||||
public Long getTemplateId() {
|
||||
return this.templateId;
|
||||
}
|
||||
|
||||
public ConfigurationAttribute getConfigAttribute() {
|
||||
return this.configAttribute;
|
||||
}
|
||||
|
||||
public Orientation getOrientation() {
|
||||
return this.orientation;
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
public String getViewModelId() {
|
||||
if (this.orientation == null || this.orientation.viewId == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return String.valueOf(this.orientation.viewId);
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
public String getGroupId() {
|
||||
if (this.orientation == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return this.orientation.groupId;
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
public boolean isNameLike(final String name) {
|
||||
if (StringUtils.isBlank(name)) {
|
||||
return true;
|
||||
}
|
||||
return this.configAttribute.name.contains(name);
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
public boolean isInView(final Long viewId) {
|
||||
if (viewId == null) {
|
||||
return true;
|
||||
}
|
||||
return this.orientation != null && this.orientation.viewId.equals(viewId);
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
public boolean isGroupLike(final String groupId) {
|
||||
if (StringUtils.isBlank(groupId)) {
|
||||
return true;
|
||||
}
|
||||
return this.orientation != null
|
||||
&& this.orientation.groupId != null
|
||||
&& this.orientation.groupId.contains(groupId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
final StringBuilder builder = new StringBuilder();
|
||||
builder.append("TemplateAttribute [institutionId=");
|
||||
builder.append(this.institutionId);
|
||||
builder.append(", templateId=");
|
||||
builder.append(this.templateId);
|
||||
builder.append(", configAttribute=");
|
||||
builder.append(this.configAttribute);
|
||||
builder.append(", orientation=");
|
||||
builder.append(this.orientation);
|
||||
builder.append("]");
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
public static final Comparator<TemplateAttribute> nameComparator(final boolean descending) {
|
||||
return (attr1, attr2) -> attr1.configAttribute.name.compareToIgnoreCase(
|
||||
attr2.configAttribute.name) * ((descending) ? -1 : 1);
|
||||
}
|
||||
|
||||
}
|
|
@ -22,6 +22,8 @@ import ch.ethz.seb.sebserver.gbl.model.Entity;
|
|||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class View implements Entity {
|
||||
|
||||
public static final String FILTER_ATTR_TEMPLATE = "templateId";
|
||||
|
||||
@JsonProperty(VIEW.ATTR_ID)
|
||||
public final Long id;
|
||||
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* 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.content;
|
||||
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
|
||||
import ch.ethz.seb.sebserver.gui.service.ResourceService;
|
||||
import ch.ethz.seb.sebserver.gui.service.page.PageContext;
|
||||
import ch.ethz.seb.sebserver.gui.service.page.PageService;
|
||||
import ch.ethz.seb.sebserver.gui.service.page.TemplateComposer;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestService;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.CurrentUser;
|
||||
|
||||
@Lazy
|
||||
@Component
|
||||
@GuiProfile
|
||||
public class ConfigTemplateAttributeForm implements TemplateComposer {
|
||||
|
||||
private final PageService pageService;
|
||||
private final RestService restService;
|
||||
private final CurrentUser currentUser;
|
||||
private final ResourceService resourceService;
|
||||
|
||||
protected ConfigTemplateAttributeForm(
|
||||
final PageService pageService,
|
||||
final RestService restService,
|
||||
final CurrentUser currentUser) {
|
||||
|
||||
this.pageService = pageService;
|
||||
this.restService = restService;
|
||||
this.currentUser = currentUser;
|
||||
this.resourceService = pageService.getResourceService();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void compose(final PageContext pageContext) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,243 @@
|
|||
/*
|
||||
* 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.content;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.eclipse.swt.widgets.Composite;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.api.API;
|
||||
import ch.ethz.seb.sebserver.gbl.model.Domain;
|
||||
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
|
||||
import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode;
|
||||
import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode.ConfigurationStatus;
|
||||
import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode.ConfigurationType;
|
||||
import ch.ethz.seb.sebserver.gbl.model.sebconfig.TemplateAttribute;
|
||||
import ch.ethz.seb.sebserver.gbl.model.user.UserInfo;
|
||||
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
|
||||
import ch.ethz.seb.sebserver.gui.content.action.ActionDefinition;
|
||||
import ch.ethz.seb.sebserver.gui.form.FormBuilder;
|
||||
import ch.ethz.seb.sebserver.gui.form.FormHandle;
|
||||
import ch.ethz.seb.sebserver.gui.service.ResourceService;
|
||||
import ch.ethz.seb.sebserver.gui.service.i18n.LocTextKey;
|
||||
import ch.ethz.seb.sebserver.gui.service.page.PageContext;
|
||||
import ch.ethz.seb.sebserver.gui.service.page.PageService;
|
||||
import ch.ethz.seb.sebserver.gui.service.page.TemplateComposer;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestService;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.GetExamConfigNode;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.GetTemplateAttributePage;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.NewExamConfig;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.SaveExamConfig;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.CurrentUser;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.CurrentUser.EntityGrantCheck;
|
||||
import ch.ethz.seb.sebserver.gui.table.ColumnDefinition;
|
||||
import ch.ethz.seb.sebserver.gui.table.ColumnDefinition.TableFilterAttribute;
|
||||
import ch.ethz.seb.sebserver.gui.table.EntityTable;
|
||||
import ch.ethz.seb.sebserver.gui.table.TableFilter.CriteriaType;
|
||||
import ch.ethz.seb.sebserver.gui.widget.WidgetFactory;
|
||||
|
||||
@Lazy
|
||||
@Component
|
||||
@GuiProfile
|
||||
public class ConfigTemplateForm implements TemplateComposer {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(ConfigTemplateForm.class);
|
||||
|
||||
private static final LocTextKey FORM_TITLE_NEW =
|
||||
new LocTextKey("sebserver.configtemplate.form.title.new");
|
||||
private static final LocTextKey FORM_TITLE =
|
||||
new LocTextKey("sebserver.configtemplate.form.title");
|
||||
private static final LocTextKey FORM_NAME_TEXT_KEY =
|
||||
new LocTextKey("sebserver.configtemplate.form.name");
|
||||
private static final LocTextKey FORM_DESCRIPTION_TEXT_KEY =
|
||||
new LocTextKey("sebserver.configtemplate.form.description");
|
||||
private static final LocTextKey ATTRIBUTES_LIST_TITLE_TEXT_KEY =
|
||||
new LocTextKey("sebserver.configtemplate.attrs.list.title");
|
||||
private static final LocTextKey ATTRIBUTES_LIST_NAME_TEXT_KEY =
|
||||
new LocTextKey("sebserver.configtemplate.attrs.list.name");
|
||||
private static final LocTextKey ATTRIBUTES_LIST_VIEW_TEXT_KEY =
|
||||
new LocTextKey("sebserver.configtemplate.attrs.list.view");
|
||||
private static final LocTextKey ATTRIBUTES_LIST_GROUP_TEXT_KEY =
|
||||
new LocTextKey("sebserver.configtemplate.attrs.list.group");
|
||||
|
||||
private final PageService pageService;
|
||||
private final RestService restService;
|
||||
private final CurrentUser currentUser;
|
||||
private final ResourceService resourceService;
|
||||
|
||||
private final TableFilterAttribute nameFilter =
|
||||
new TableFilterAttribute(CriteriaType.TEXT, TemplateAttribute.FILTER_ATTR_NAME);
|
||||
private final TableFilterAttribute groupFilter =
|
||||
new TableFilterAttribute(CriteriaType.TEXT, TemplateAttribute.FILTER_ATTR_GROUP);
|
||||
|
||||
protected ConfigTemplateForm(
|
||||
final PageService pageService,
|
||||
final RestService restService,
|
||||
final CurrentUser currentUser) {
|
||||
|
||||
this.pageService = pageService;
|
||||
this.restService = restService;
|
||||
this.currentUser = currentUser;
|
||||
this.resourceService = pageService.getResourceService();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void compose(final PageContext pageContext) {
|
||||
|
||||
final WidgetFactory widgetFactory = this.pageService.getWidgetFactory();
|
||||
final ResourceService resourceService = this.pageService.getResourceService();
|
||||
|
||||
final UserInfo user = this.currentUser.get();
|
||||
final EntityKey entityKey = pageContext.getEntityKey();
|
||||
final boolean isNew = entityKey == null;
|
||||
|
||||
// get data or create new. Handle error if happen
|
||||
final ConfigurationNode examConfig = (isNew)
|
||||
? ConfigurationNode.createNewTemplate(user.institutionId)
|
||||
: this.restService
|
||||
.getBuilder(GetExamConfigNode.class)
|
||||
.withURIVariable(API.PARAM_MODEL_ID, entityKey.modelId)
|
||||
.call()
|
||||
.get(pageContext::notifyError);
|
||||
|
||||
if (examConfig == null) {
|
||||
log.error("Failed to get ConfigurationNode for Template. "
|
||||
+ "Error was notified to the User. "
|
||||
+ "See previous logs for more infomation");
|
||||
return;
|
||||
}
|
||||
|
||||
final EntityGrantCheck entityGrant = this.currentUser.entityGrantCheck(examConfig);
|
||||
final boolean writeGrant = entityGrant.w();
|
||||
final boolean modifyGrant = entityGrant.m();
|
||||
final boolean isReadonly = pageContext.isReadonly();
|
||||
|
||||
// new PageContext with actual EntityKey
|
||||
final PageContext formContext = pageContext
|
||||
.withEntityKey(examConfig.getEntityKey());
|
||||
|
||||
// the default page layout with interactive title
|
||||
final LocTextKey titleKey = (isNew)
|
||||
? FORM_TITLE_NEW
|
||||
: FORM_TITLE;
|
||||
final Composite content = widgetFactory.defaultPageLayout(
|
||||
formContext.getParent(),
|
||||
titleKey);
|
||||
|
||||
// The SebClientConfig form
|
||||
final FormHandle<ConfigurationNode> formHandle = this.pageService.formBuilder(
|
||||
formContext.copyOf(content), 4)
|
||||
.readonly(isReadonly)
|
||||
.putStaticValueIf(() -> !isNew,
|
||||
Domain.CONFIGURATION_NODE.ATTR_ID,
|
||||
examConfig.getModelId())
|
||||
.putStaticValue(
|
||||
Domain.CONFIGURATION_NODE.ATTR_INSTITUTION_ID,
|
||||
String.valueOf(examConfig.getInstitutionId()))
|
||||
.putStaticValue(
|
||||
Domain.CONFIGURATION_NODE.ATTR_TYPE,
|
||||
ConfigurationType.TEMPLATE.name())
|
||||
.putStaticValue(
|
||||
Domain.CONFIGURATION_NODE.ATTR_STATUS,
|
||||
ConfigurationStatus.IN_USE.name())
|
||||
.addField(FormBuilder.text(
|
||||
Domain.CONFIGURATION_NODE.ATTR_NAME,
|
||||
FORM_NAME_TEXT_KEY,
|
||||
examConfig.name))
|
||||
.addField(FormBuilder.text(
|
||||
Domain.CONFIGURATION_NODE.ATTR_DESCRIPTION,
|
||||
FORM_DESCRIPTION_TEXT_KEY,
|
||||
examConfig.description)
|
||||
.asArea())
|
||||
.buildFor((isNew)
|
||||
? this.restService.getRestCall(NewExamConfig.class)
|
||||
: this.restService.getRestCall(SaveExamConfig.class));
|
||||
|
||||
if (isReadonly) {
|
||||
|
||||
widgetFactory.label(content, "");
|
||||
widgetFactory.labelLocalizedTitle(
|
||||
content,
|
||||
ATTRIBUTES_LIST_TITLE_TEXT_KEY);
|
||||
|
||||
final TableFilterAttribute viewFilter = new TableFilterAttribute(
|
||||
CriteriaType.SINGLE_SELECTION,
|
||||
TemplateAttribute.FILTER_ATTR_VIEW,
|
||||
() -> this.resourceService.getViewResources(entityKey.modelId));
|
||||
|
||||
final EntityTable<TemplateAttribute> attrTable =
|
||||
this.pageService.entityTableBuilder(this.restService.getRestCall(GetTemplateAttributePage.class))
|
||||
.withRestCallAdapter(restCall -> restCall.withURIVariable(
|
||||
API.PARAM_MODEL_ID,
|
||||
entityKey.modelId))
|
||||
.withPaging(15)
|
||||
.withColumn(new ColumnDefinition<>(
|
||||
Domain.CONFIGURATION_ATTRIBUTE.ATTR_NAME,
|
||||
ATTRIBUTES_LIST_NAME_TEXT_KEY,
|
||||
TemplateAttribute::getName)
|
||||
.withFilter(this.nameFilter)
|
||||
.sortable())
|
||||
.withColumn(new ColumnDefinition<>(
|
||||
Domain.ORIENTATION.ATTR_VIEW_ID,
|
||||
ATTRIBUTES_LIST_VIEW_TEXT_KEY,
|
||||
getViewNameFunction(entityKey))
|
||||
.withFilter(viewFilter)
|
||||
.sortable())
|
||||
.withColumn(new ColumnDefinition<>(
|
||||
Domain.ORIENTATION.ATTR_GROUP_ID,
|
||||
ATTRIBUTES_LIST_GROUP_TEXT_KEY,
|
||||
TemplateAttribute::getGroupId)
|
||||
.withFilter(this.groupFilter)
|
||||
.sortable())
|
||||
// .withDefaultAction(pageActionBuilder
|
||||
// .newAction(ActionDefinition.SEB_EXAM_CONFIG_TEMPLATE_VIEW_FROM_LIST)
|
||||
// .create())
|
||||
.compose(pageContext.copyOf(content));
|
||||
|
||||
// TODO list of all attributes with filter
|
||||
}
|
||||
|
||||
this.pageService.pageActionBuilder(formContext.clearEntityKeys())
|
||||
|
||||
.newAction(ActionDefinition.SEB_EXAM_CONFIG_TEMPLATE_NEW)
|
||||
.publishIf(() -> writeGrant && isReadonly)
|
||||
|
||||
.newAction(ActionDefinition.SEB_EXAM_CONFIG_TEMPLATE_MODIFY)
|
||||
.withEntityKey(entityKey)
|
||||
.publishIf(() -> modifyGrant && isReadonly)
|
||||
|
||||
.newAction(ActionDefinition.SEB_EXAM_CONFIG_TEMPLATE_SAVE)
|
||||
.withEntityKey(entityKey)
|
||||
.withExec(formHandle::processFormSave)
|
||||
.ignoreMoveAwayFromEdit()
|
||||
.publishIf(() -> !isReadonly)
|
||||
|
||||
.newAction(ActionDefinition.SEB_EXAM_CONFIG_TEMPLATE_CANCEL_MODIFY)
|
||||
.withEntityKey(entityKey)
|
||||
.withExec(this.pageService.backToCurrentFunction())
|
||||
.publishIf(() -> !isReadonly);
|
||||
|
||||
}
|
||||
|
||||
private final Function<TemplateAttribute, String> getViewNameFunction(final EntityKey templateId) {
|
||||
final Map<String, String> mapping = this.resourceService.getViewResources(templateId.modelId)
|
||||
.stream()
|
||||
.collect(Collectors.toMap(tuple -> tuple._1, tuple -> tuple._2));
|
||||
|
||||
return attr -> mapping.get(attr.getViewModelId());
|
||||
}
|
||||
|
||||
}
|
|
@ -9,7 +9,6 @@
|
|||
package ch.ethz.seb.sebserver.gui.content;
|
||||
|
||||
import org.eclipse.swt.widgets.Composite;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
|
@ -17,6 +16,7 @@ import ch.ethz.seb.sebserver.gbl.api.EntityType;
|
|||
import ch.ethz.seb.sebserver.gbl.model.Domain;
|
||||
import ch.ethz.seb.sebserver.gbl.model.Entity;
|
||||
import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode;
|
||||
import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode.ConfigurationType;
|
||||
import ch.ethz.seb.sebserver.gbl.model.user.UserRole;
|
||||
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
|
||||
import ch.ethz.seb.sebserver.gui.content.action.ActionDefinition;
|
||||
|
@ -35,6 +35,7 @@ import ch.ethz.seb.sebserver.gui.table.ColumnDefinition;
|
|||
import ch.ethz.seb.sebserver.gui.table.ColumnDefinition.TableFilterAttribute;
|
||||
import ch.ethz.seb.sebserver.gui.table.EntityTable;
|
||||
import ch.ethz.seb.sebserver.gui.table.TableFilter.CriteriaType;
|
||||
import ch.ethz.seb.sebserver.gui.widget.WidgetFactory;
|
||||
|
||||
@Lazy
|
||||
@Component
|
||||
|
@ -43,10 +44,14 @@ public class SebExamConfigList implements TemplateComposer {
|
|||
|
||||
private static final LocTextKey NO_MODIFY_PRIVILEGE_ON_OTHER_INSTITUION =
|
||||
new LocTextKey("sebserver.examconfig.list.action.no.modify.privilege");
|
||||
private static final LocTextKey EMPTY_LIST_TEXT_KEY =
|
||||
private static final LocTextKey EMPTY_CONFIG_LIST_TEXT_KEY =
|
||||
new LocTextKey("sebserver.examconfig.list.empty");
|
||||
private static final LocTextKey TITLE_TEXT_KEY =
|
||||
private static final LocTextKey EMPTY_TEMPLATE_LIST_TEXT_KEY =
|
||||
new LocTextKey("sebserver.configtemplate.list.empty");
|
||||
private static final LocTextKey TITLE_CONFIGURATION_TEXT_KEY =
|
||||
new LocTextKey("sebserver.examconfig.list.title");
|
||||
private static final LocTextKey TITLE_TEMPLATE_TEXT_KEY =
|
||||
new LocTextKey("sebserver.configtemplate.list.title");
|
||||
private static final LocTextKey INSTITUTION_TEXT_KEY =
|
||||
new LocTextKey("sebserver.examconfig.list.column.institution");
|
||||
private static final LocTextKey NAME_TEXT_KEY =
|
||||
|
@ -57,6 +62,8 @@ public class SebExamConfigList implements TemplateComposer {
|
|||
new LocTextKey("sebserver.examconfig.list.column.status");
|
||||
private static final LocTextKey EMPTY_SELECTION_TEXT_KEY =
|
||||
new LocTextKey("sebserver.examconfig.info.pleaseSelect");
|
||||
private static final LocTextKey EMPTY_TEMPLATE_SELECTION_TEXT_KEY =
|
||||
new LocTextKey("sebserver.configtemplate.info.pleaseSelect");
|
||||
|
||||
private final TableFilterAttribute institutionFilter;
|
||||
private final TableFilterAttribute nameFilter =
|
||||
|
@ -67,19 +74,16 @@ public class SebExamConfigList implements TemplateComposer {
|
|||
private final RestService restService;
|
||||
private final CurrentUser currentUser;
|
||||
private final ResourceService resourceService;
|
||||
private final int pageSize;
|
||||
|
||||
protected SebExamConfigList(
|
||||
final PageService pageService,
|
||||
final RestService restService,
|
||||
final CurrentUser currentUser,
|
||||
@Value("${sebserver.gui.list.page.size:20}") final Integer pageSize) {
|
||||
final CurrentUser currentUser) {
|
||||
|
||||
this.pageService = pageService;
|
||||
this.restService = restService;
|
||||
this.currentUser = currentUser;
|
||||
this.resourceService = pageService.getResourceService();
|
||||
this.pageSize = pageSize;
|
||||
|
||||
this.institutionFilter = new TableFilterAttribute(
|
||||
CriteriaType.SINGLE_SELECTION,
|
||||
|
@ -94,20 +98,24 @@ public class SebExamConfigList implements TemplateComposer {
|
|||
|
||||
@Override
|
||||
public void compose(final PageContext pageContext) {
|
||||
final WidgetFactory widgetFactory = this.pageService.getWidgetFactory();
|
||||
|
||||
final Composite content = this.pageService.getWidgetFactory().defaultPageLayout(
|
||||
final Composite content = widgetFactory.defaultPageLayout(
|
||||
pageContext.getParent(),
|
||||
TITLE_TEXT_KEY);
|
||||
TITLE_CONFIGURATION_TEXT_KEY);
|
||||
|
||||
final boolean isSEBAdmin = this.currentUser.get().hasRole(UserRole.SEB_SERVER_ADMIN);
|
||||
final PageActionBuilder pageActionBuilder =
|
||||
this.pageService.pageActionBuilder(pageContext.clearEntityKeys());
|
||||
|
||||
// table
|
||||
final EntityTable<ConfigurationNode> table =
|
||||
// exam configuration table
|
||||
final EntityTable<ConfigurationNode> configTable =
|
||||
this.pageService.entityTableBuilder(this.restService.getRestCall(GetExamConfigNodePage.class))
|
||||
.withEmptyMessage(EMPTY_LIST_TEXT_KEY)
|
||||
.withPaging(this.pageSize)
|
||||
.withStaticFilter(
|
||||
Domain.CONFIGURATION_NODE.ATTR_TYPE,
|
||||
ConfigurationType.EXAM_CONFIG.name())
|
||||
.withEmptyMessage(EMPTY_CONFIG_LIST_TEXT_KEY)
|
||||
.withPaging(6)
|
||||
.withColumnIf(
|
||||
() -> isSEBAdmin,
|
||||
() -> new ColumnDefinition<>(
|
||||
|
@ -139,27 +147,80 @@ public class SebExamConfigList implements TemplateComposer {
|
|||
.create())
|
||||
.compose(pageContext.copyOf(content));
|
||||
|
||||
// configuration template table
|
||||
widgetFactory.label(content, "");
|
||||
widgetFactory.labelLocalizedTitle(
|
||||
content,
|
||||
TITLE_TEMPLATE_TEXT_KEY);
|
||||
|
||||
final EntityTable<ConfigurationNode> templateTable =
|
||||
this.pageService.entityTableBuilder(this.restService.getRestCall(GetExamConfigNodePage.class))
|
||||
.withStaticFilter(
|
||||
Domain.CONFIGURATION_NODE.ATTR_TYPE,
|
||||
ConfigurationType.TEMPLATE.name())
|
||||
.withEmptyMessage(EMPTY_TEMPLATE_LIST_TEXT_KEY)
|
||||
.withPaging(6)
|
||||
.withColumnIf(
|
||||
() -> isSEBAdmin,
|
||||
() -> new ColumnDefinition<>(
|
||||
Domain.LMS_SETUP.ATTR_INSTITUTION_ID,
|
||||
INSTITUTION_TEXT_KEY,
|
||||
this.resourceService::localizedExamConfigInstitutionName)
|
||||
.withFilter(this.institutionFilter)
|
||||
.sortable())
|
||||
.withColumn(new ColumnDefinition<>(
|
||||
Domain.CONFIGURATION_NODE.ATTR_NAME,
|
||||
NAME_TEXT_KEY,
|
||||
ConfigurationNode::getName)
|
||||
.withFilter(this.nameFilter)
|
||||
.sortable())
|
||||
.withColumn(new ColumnDefinition<>(
|
||||
Domain.CONFIGURATION_NODE.ATTR_DESCRIPTION,
|
||||
DESCRIPTION_TEXT_KEY,
|
||||
ConfigurationNode::getDescription)
|
||||
.withFilter(this.nameFilter)
|
||||
.sortable())
|
||||
.withDefaultAction(pageActionBuilder
|
||||
.newAction(ActionDefinition.SEB_EXAM_CONFIG_TEMPLATE_VIEW_FROM_LIST)
|
||||
.create())
|
||||
.compose(pageContext.copyOf(content));
|
||||
|
||||
final GrantCheck examConfigGrant = this.currentUser.grantCheck(EntityType.CONFIGURATION_NODE);
|
||||
pageActionBuilder
|
||||
|
||||
// Exam Configuration actions...
|
||||
.newAction(ActionDefinition.SEB_EXAM_CONFIG_NEW)
|
||||
.publishIf(examConfigGrant::iw)
|
||||
|
||||
.newAction(ActionDefinition.SEB_EXAM_CONFIG_VIEW_PROP_FROM_LIST)
|
||||
.withSelect(table::getSelection, PageAction::applySingleSelection, EMPTY_SELECTION_TEXT_KEY)
|
||||
.publishIf(() -> table.hasAnyContent())
|
||||
.withSelect(configTable::getSelection, PageAction::applySingleSelection, EMPTY_SELECTION_TEXT_KEY)
|
||||
.publishIf(() -> configTable.hasAnyContent())
|
||||
|
||||
.newAction(ActionDefinition.SEB_EXAM_CONFIG_MODIFY_PROP_FROM_LIST)
|
||||
.withSelect(
|
||||
table.getGrantedSelection(this.currentUser, NO_MODIFY_PRIVILEGE_ON_OTHER_INSTITUION),
|
||||
configTable.getGrantedSelection(this.currentUser, NO_MODIFY_PRIVILEGE_ON_OTHER_INSTITUION),
|
||||
PageAction::applySingleSelection, EMPTY_SELECTION_TEXT_KEY)
|
||||
.publishIf(() -> examConfigGrant.im() && table.hasAnyContent())
|
||||
.publishIf(() -> examConfigGrant.im() && configTable.hasAnyContent())
|
||||
|
||||
.newAction(ActionDefinition.SEB_EXAM_CONFIG_MODIFY_FROM_LIST)
|
||||
.withSelect(
|
||||
table.getGrantedSelection(this.currentUser, NO_MODIFY_PRIVILEGE_ON_OTHER_INSTITUION),
|
||||
configTable.getGrantedSelection(this.currentUser, NO_MODIFY_PRIVILEGE_ON_OTHER_INSTITUION),
|
||||
PageAction::applySingleSelection, EMPTY_SELECTION_TEXT_KEY)
|
||||
.publishIf(() -> examConfigGrant.im() && table.hasAnyContent());
|
||||
.publishIf(() -> examConfigGrant.im() && configTable.hasAnyContent())
|
||||
|
||||
// Exam Configuration template actions...
|
||||
.newAction(ActionDefinition.SEB_EXAM_CONFIG_TEMPLATE_NEW)
|
||||
.publishIf(examConfigGrant::iw)
|
||||
|
||||
.newAction(ActionDefinition.SEB_EXAM_CONFIG_TEMPLATE_VIEW_FROM_LIST)
|
||||
.withSelect(templateTable::getSelection, PageAction::applySingleSelection,
|
||||
EMPTY_TEMPLATE_SELECTION_TEXT_KEY)
|
||||
.publishIf(() -> templateTable.hasAnyContent())
|
||||
|
||||
.newAction(ActionDefinition.SEB_EXAM_CONFIG_TEMPLATE_MODIFY_FROM_LIST)
|
||||
.withSelect(
|
||||
templateTable.getGrantedSelection(this.currentUser, NO_MODIFY_PRIVILEGE_ON_OTHER_INSTITUION),
|
||||
PageAction::applySingleSelection, EMPTY_TEMPLATE_SELECTION_TEXT_KEY)
|
||||
.publishIf(() -> examConfigGrant.im() && templateTable.hasAnyContent());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -113,15 +113,11 @@ public class SebExamConfigPropForm implements TemplateComposer {
|
|||
|
||||
final UserInfo user = this.currentUser.get();
|
||||
final EntityKey entityKey = pageContext.getEntityKey();
|
||||
final EntityKey parentEntityKey = pageContext.getParentEntityKey();
|
||||
|
||||
final boolean isNew = entityKey == null;
|
||||
|
||||
// get data or create new. Handle error if happen
|
||||
final ConfigurationNode examConfig = (isNew)
|
||||
? ConfigurationNode.createNewExamConfig((parentEntityKey != null)
|
||||
? Long.valueOf(parentEntityKey.modelId)
|
||||
: user.institutionId)
|
||||
? ConfigurationNode.createNewExamConfig(user.institutionId)
|
||||
: this.restService
|
||||
.getBuilder(GetExamConfigNode.class)
|
||||
.withURIVariable(API.PARAM_MODEL_ID, entityKey.modelId)
|
||||
|
|
|
@ -21,6 +21,8 @@ public enum ActionCategory {
|
|||
INDICATOR_LIST(new LocTextKey("sebserver.exam.indicator.list.actions"), 2),
|
||||
SEB_CLIENT_CONFIG_LIST(new LocTextKey("sebserver.clientconfig.list.actions"), 1),
|
||||
SEB_EXAM_CONFIG_LIST(new LocTextKey("sebserver.examconfig.list.actions"), 1),
|
||||
SEB_CONFIG_TEMPLATE_LIST(new LocTextKey("sebserver.configtemplate.list.actions"), 2),
|
||||
SEB_CONFIG_TEMPLATE_ATTRIBUTE_LIST(new LocTextKey("sebserver.configtemplate.attr.list.actions"), 1),
|
||||
RUNNING_EXAM_LIST(new LocTextKey("sebserver.monitoring.exam.list.actions"), 1),
|
||||
CLIENT_EVENT_LIST(new LocTextKey("sebserver.monitoring.exam.connection.list.actions"), 1),
|
||||
LOGS_USER_ACTIVITY_LIST(new LocTextKey("sebserver.userlogs.list.actions"), 1),
|
||||
|
|
|
@ -415,6 +415,58 @@ public enum ActionDefinition {
|
|||
PageStateDefinitionImpl.SEB_EXAM_CONFIG_EDIT,
|
||||
ActionCategory.FORM),
|
||||
|
||||
SEB_EXAM_CONFIG_TEMPLATE_NEW(
|
||||
new LocTextKey("sebserver.exam.configtemplate.action.list.new"),
|
||||
ImageIcon.NEW,
|
||||
PageStateDefinitionImpl.SEB_EXAM_CONFIG_TEMPLATE_EDIT,
|
||||
ActionCategory.VARIA),
|
||||
SEB_EXAM_CONFIG_TEMPLATE_VIEW_FROM_LIST(
|
||||
new LocTextKey("sebserver.configtemplate.action.list.view"),
|
||||
ImageIcon.SHOW,
|
||||
PageStateDefinitionImpl.SEB_EXAM_CONFIG_TEMPLATE_VIEW,
|
||||
ActionCategory.SEB_CONFIG_TEMPLATE_LIST),
|
||||
SEB_EXAM_CONFIG_TEMPLATE_VIEW(
|
||||
new LocTextKey("sebserver.configtemplate.action.view"),
|
||||
ImageIcon.SHOW,
|
||||
PageStateDefinitionImpl.SEB_EXAM_CONFIG_TEMPLATE_VIEW,
|
||||
ActionCategory.FORM),
|
||||
SEB_EXAM_CONFIG_TEMPLATE_MODIFY_FROM_LIST(
|
||||
new LocTextKey("sebserver.configtemplate.action.list.modify"),
|
||||
ImageIcon.EDIT,
|
||||
PageStateDefinitionImpl.SEB_EXAM_CONFIG_TEMPLATE_EDIT,
|
||||
ActionCategory.SEB_CONFIG_TEMPLATE_LIST),
|
||||
SEB_EXAM_CONFIG_TEMPLATE_MODIFY(
|
||||
new LocTextKey("sebserver.configtemplate.action.modify"),
|
||||
ImageIcon.EDIT,
|
||||
PageStateDefinitionImpl.SEB_EXAM_CONFIG_TEMPLATE_EDIT,
|
||||
ActionCategory.FORM),
|
||||
SEB_EXAM_CONFIG_TEMPLATE_CANCEL_MODIFY(
|
||||
new LocTextKey("sebserver.overall.action.modify.cancel"),
|
||||
ImageIcon.CANCEL,
|
||||
PageStateDefinitionImpl.SEB_EXAM_CONFIG_TEMPLATE_VIEW,
|
||||
ActionCategory.FORM),
|
||||
SEB_EXAM_CONFIG_TEMPLATE_SAVE(
|
||||
new LocTextKey("sebserver.configtemplate.action.save"),
|
||||
ImageIcon.SAVE,
|
||||
PageStateDefinitionImpl.SEB_EXAM_CONFIG_TEMPLATE_VIEW,
|
||||
ActionCategory.FORM),
|
||||
|
||||
SEB_EXAM_CONFIG_TEMPLATE_ATTR_EDIT(
|
||||
new LocTextKey("sebserver.configtemplate.attr.list.actions.modify"),
|
||||
ImageIcon.EDIT,
|
||||
PageStateDefinitionImpl.SEB_EXAM_CONFIG_TEMPLATE_ATTRIBUTE_VIEW,
|
||||
ActionCategory.SEB_CONFIG_TEMPLATE_ATTRIBUTE_LIST),
|
||||
SEB_EXAM_CONFIG_TEMPLATE_ATTR_SET_DEFAULT(
|
||||
new LocTextKey("sebserver.configtemplate.attr.list.actions.setdefault"),
|
||||
ImageIcon.SAVE,
|
||||
PageStateDefinitionImpl.SEB_EXAM_CONFIG_TEMPLATE_ATTRIBUTE_VIEW,
|
||||
ActionCategory.SEB_CONFIG_TEMPLATE_ATTRIBUTE_LIST),
|
||||
SEB_EXAM_CONFIG_TEMPLATE_ATTR_REMOVE_VIEW(
|
||||
new LocTextKey("sebserver.configtemplate.attr.list.actions.removeview"),
|
||||
ImageIcon.DELETE,
|
||||
PageStateDefinitionImpl.SEB_EXAM_CONFIG_TEMPLATE_ATTRIBUTE_VIEW,
|
||||
ActionCategory.SEB_CONFIG_TEMPLATE_ATTRIBUTE_LIST),
|
||||
|
||||
RUNNING_EXAM_VIEW_LIST(
|
||||
new LocTextKey("sebserver.monitoring.action.list"),
|
||||
PageStateDefinitionImpl.MONITORING_RUNNING_EXAM_LIST),
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
|
||||
package ch.ethz.seb.sebserver.gui.content.activity;
|
||||
|
||||
import ch.ethz.seb.sebserver.gui.content.ConfigTemplateAttributeForm;
|
||||
import ch.ethz.seb.sebserver.gui.content.ConfigTemplateForm;
|
||||
import ch.ethz.seb.sebserver.gui.content.ExamForm;
|
||||
import ch.ethz.seb.sebserver.gui.content.ExamList;
|
||||
import ch.ethz.seb.sebserver.gui.content.ExamSebConfigMapForm;
|
||||
|
@ -67,6 +69,18 @@ public enum PageStateDefinitionImpl implements PageStateDefinition {
|
|||
SEB_EXAM_CONFIG_PROP_EDIT(Type.FORM_EDIT, SebExamConfigPropForm.class, ActivityDefinition.SEB_EXAM_CONFIG),
|
||||
SEB_EXAM_CONFIG_EDIT(Type.FORM_VIEW, SebExamConfigSettingsForm.class, ActivityDefinition.SEB_EXAM_CONFIG),
|
||||
|
||||
SEB_EXAM_CONFIG_TEMPLATE_VIEW(Type.FORM_VIEW, ConfigTemplateForm.class, ActivityDefinition.SEB_EXAM_CONFIG),
|
||||
SEB_EXAM_CONFIG_TEMPLATE_EDIT(Type.FORM_EDIT, ConfigTemplateForm.class, ActivityDefinition.SEB_EXAM_CONFIG),
|
||||
|
||||
SEB_EXAM_CONFIG_TEMPLATE_ATTRIBUTE_VIEW(
|
||||
Type.FORM_VIEW,
|
||||
ConfigTemplateAttributeForm.class,
|
||||
ActivityDefinition.SEB_EXAM_CONFIG),
|
||||
SEB_EXAM_CONFIG_TEMPLATE_ATTRIBUTE_EDIT(
|
||||
Type.FORM_EDIT,
|
||||
ConfigTemplateAttributeForm.class,
|
||||
ActivityDefinition.SEB_EXAM_CONFIG),
|
||||
|
||||
MONITORING_RUNNING_EXAM_LIST(Type.LIST_VIEW, MonitoringRunningExamList.class, ActivityDefinition.MONITORING_EXAMS),
|
||||
MONITORING_RUNNING_EXAM(Type.FORM_VIEW, MonitoringRunningExam.class, ActivityDefinition.MONITORING_EXAMS),
|
||||
MONITORING_CLIENT_CONNECTION(Type.FORM_VIEW, MonitoringClientConnection.class, ActivityDefinition.MONITORING_EXAMS),
|
||||
|
|
|
@ -27,6 +27,7 @@ import org.springframework.context.annotation.Lazy;
|
|||
import org.springframework.stereotype.Service;
|
||||
|
||||
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.api.ProxyData.ProxyAuthType;
|
||||
import ch.ethz.seb.sebserver.gbl.model.Entity;
|
||||
|
@ -40,6 +41,7 @@ import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetup.LmsType;
|
|||
import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode;
|
||||
import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode.ConfigurationStatus;
|
||||
import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode.ConfigurationType;
|
||||
import ch.ethz.seb.sebserver.gbl.model.sebconfig.View;
|
||||
import ch.ethz.seb.sebserver.gbl.model.session.ClientConnection.ConnectionStatus;
|
||||
import ch.ethz.seb.sebserver.gbl.model.session.ClientEvent;
|
||||
import ch.ethz.seb.sebserver.gbl.model.session.ClientEvent.EventType;
|
||||
|
@ -58,6 +60,7 @@ import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.GetExamNames
|
|||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.GetExams;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.institution.GetInstitutionNames;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.lmssetup.GetLmsSetupNames;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.GetViews;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.useraccount.GetUserAccountNames;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.CurrentUser;
|
||||
|
||||
|
@ -465,6 +468,23 @@ public class ResourceService {
|
|||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public List<Tuple<String>> getViewResources() {
|
||||
return getViewResources(API.DEFAULT_CONFIG_TEMPLATE_ID);
|
||||
}
|
||||
|
||||
public List<Tuple<String>> getViewResources(final String templateId) {
|
||||
return this.restService.getBuilder(GetViews.class)
|
||||
.withQueryParam(
|
||||
View.FILTER_ATTR_TEMPLATE,
|
||||
templateId)
|
||||
.call()
|
||||
.getOr(Collections.emptyList())
|
||||
.stream()
|
||||
.map(view -> new Tuple<>(view.getModelId(), view.name))
|
||||
.sorted(RESOURCE_COMPARATOR)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public Map<Long, String> getExamNameMapping() {
|
||||
final UserInfo userInfo = this.currentUser.get();
|
||||
return this.restService.getBuilder(GetExamNames.class)
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* 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.service.remote.webservice.api.seb.examconfig;
|
||||
|
||||
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.Page;
|
||||
import ch.ethz.seb.sebserver.gbl.model.sebconfig.TemplateAttribute;
|
||||
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCall;
|
||||
|
||||
@Lazy
|
||||
@Component
|
||||
@GuiProfile
|
||||
public class GetTemplateAttributePage extends RestCall<Page<TemplateAttribute>> {
|
||||
|
||||
public GetTemplateAttributePage() {
|
||||
super(new TypeKey<>(
|
||||
CallType.GET_PAGE,
|
||||
EntityType.CONFIGURATION_NODE,
|
||||
new TypeReference<Page<TemplateAttribute>>() {
|
||||
}),
|
||||
HttpMethod.GET,
|
||||
MediaType.APPLICATION_FORM_URLENCODED,
|
||||
API.CONFIGURATION_NODE_ENDPOINT
|
||||
+ API.MODEL_ID_VAR_PATH_SEGMENT
|
||||
+ API.TEMPLATE_ATTRIBUTE_ENDPOINT);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* 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.service.remote.webservice.api.seb.examconfig;
|
||||
|
||||
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.Page;
|
||||
import ch.ethz.seb.sebserver.gbl.model.sebconfig.View;
|
||||
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCall;
|
||||
|
||||
@Lazy
|
||||
@Component
|
||||
@GuiProfile
|
||||
public class GetViewPage extends RestCall<Page<View>> {
|
||||
|
||||
public GetViewPage() {
|
||||
super(new TypeKey<>(
|
||||
CallType.GET_PAGE,
|
||||
EntityType.VIEW,
|
||||
new TypeReference<Page<View>>() {
|
||||
}),
|
||||
HttpMethod.GET,
|
||||
MediaType.APPLICATION_FORM_URLENCODED,
|
||||
API.VIEW_ENDPOINT);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* 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.service.remote.webservice.api.seb.examconfig;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
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.sebconfig.View;
|
||||
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.PageToListCallAdapter;
|
||||
|
||||
@Lazy
|
||||
@Component
|
||||
@GuiProfile
|
||||
public class GetViews extends PageToListCallAdapter<View> {
|
||||
|
||||
public GetViews() {
|
||||
super(
|
||||
GetViewPage.class,
|
||||
EntityType.VIEW,
|
||||
new TypeReference<List<View>>() {
|
||||
},
|
||||
API.VIEW_ENDPOINT);
|
||||
}
|
||||
|
||||
}
|
|
@ -36,6 +36,7 @@ import org.eclipse.swt.widgets.Widget;
|
|||
import org.joda.time.DateTime;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.Constants;
|
||||
import ch.ethz.seb.sebserver.gbl.model.Entity;
|
||||
|
@ -78,6 +79,7 @@ public class EntityTable<ROW extends Entity> {
|
|||
private final TableFilter<ROW> filter;
|
||||
private final Table table;
|
||||
private final TableNavigator navigator;
|
||||
private final MultiValueMap<String, String> staticQueryParams;
|
||||
|
||||
int pageNumber = 1;
|
||||
int pageSize;
|
||||
|
@ -96,7 +98,8 @@ public class EntityTable<ROW extends Entity> {
|
|||
final int pageSize,
|
||||
final LocTextKey emptyMessage,
|
||||
final Function<EntityTable<ROW>, PageAction> defaultActionFunction,
|
||||
final boolean hideNavigation) {
|
||||
final boolean hideNavigation,
|
||||
final MultiValueMap<String, String> staticQueryParams) {
|
||||
|
||||
this.composite = new Composite(pageContext.getParent(), type);
|
||||
this.pageService = pageService;
|
||||
|
@ -116,6 +119,7 @@ public class EntityTable<ROW extends Entity> {
|
|||
this.composite.setLayout(layout);
|
||||
GridData gridData = new GridData(SWT.FILL, SWT.TOP, true, false);
|
||||
this.composite.setLayoutData(gridData);
|
||||
this.staticQueryParams = staticQueryParams;
|
||||
|
||||
// TODO just for debugging, remove when tested
|
||||
// this.composite.setBackground(new Color(parent.getDisplay(), new RGB(0, 200, 0)));
|
||||
|
@ -375,6 +379,7 @@ public class EntityTable<ROW extends Entity> {
|
|||
.withPaging(pageNumber, pageSize)
|
||||
.withSorting(sortColumn, sortOrder)
|
||||
.withQueryParams((this.filter != null) ? this.filter.getFilterParameter() : null)
|
||||
.withQueryParams(this.staticQueryParams)
|
||||
.apply(this.restCallAdapter)
|
||||
.call()
|
||||
.map(this::createTableRowsFromPage)
|
||||
|
@ -494,7 +499,8 @@ public class EntityTable<ROW extends Entity> {
|
|||
item.setText(index, this.i18nSupport.formatDisplayDate((DateTime) value));
|
||||
} else {
|
||||
if (value != null) {
|
||||
item.setText(index, String.valueOf(value));
|
||||
final String val = String.valueOf(value).replace('\n', ' ');
|
||||
item.setText(index, val);
|
||||
} else {
|
||||
item.setText(index, Constants.EMPTY_NOTE);
|
||||
}
|
||||
|
|
|
@ -15,6 +15,8 @@ import java.util.function.Function;
|
|||
import java.util.function.Supplier;
|
||||
|
||||
import org.eclipse.swt.SWT;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.model.Entity;
|
||||
import ch.ethz.seb.sebserver.gbl.model.Page;
|
||||
|
@ -28,6 +30,7 @@ public class TableBuilder<ROW extends Entity> {
|
|||
|
||||
private final PageService pageService;
|
||||
final RestCall<Page<ROW>> restCall;
|
||||
private final MultiValueMap<String, String> staticQueryParams;
|
||||
final List<ColumnDefinition<ROW>> columns = new ArrayList<>();
|
||||
LocTextKey emptyMessage;
|
||||
private Function<EntityTable<ROW>, PageAction> defaultActionFunction;
|
||||
|
@ -42,6 +45,7 @@ public class TableBuilder<ROW extends Entity> {
|
|||
|
||||
this.pageService = pageService;
|
||||
this.restCall = restCall;
|
||||
this.staticQueryParams = new LinkedMultiValueMap<>();
|
||||
}
|
||||
|
||||
public TableBuilder<ROW> hideNavigation() {
|
||||
|
@ -85,6 +89,11 @@ public class TableBuilder<ROW extends Entity> {
|
|||
return this;
|
||||
}
|
||||
|
||||
public TableBuilder<ROW> withStaticFilter(final String name, final String value) {
|
||||
this.staticQueryParams.add(name, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public TableBuilder<ROW> withDefaultActionIf(
|
||||
final BooleanSupplier condition,
|
||||
final Supplier<PageAction> actionSupplier) {
|
||||
|
@ -128,7 +137,8 @@ public class TableBuilder<ROW extends Entity> {
|
|||
this.pageSize,
|
||||
this.emptyMessage,
|
||||
this.defaultActionFunction,
|
||||
this.hideNavigation);
|
||||
this.hideNavigation,
|
||||
this.staticQueryParams);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@ public interface ConfigurationAttributeDAO extends EntityDAO<ConfigurationAttrib
|
|||
|
||||
/** Use this to get all ConfigurationAttribute that are root attributes and no child
|
||||
* attributes (has no parent reference).
|
||||
*
|
||||
*
|
||||
* @return Collection of all ConfigurationAttribute that are root attributes */
|
||||
Result<Collection<ConfigurationAttribute>> getAllRootAttributes();
|
||||
|
||||
|
|
|
@ -9,17 +9,25 @@
|
|||
package ch.ethz.seb.sebserver.webservice.servicelayer.dao;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
|
||||
import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode;
|
||||
import ch.ethz.seb.sebserver.gbl.model.sebconfig.Orientation;
|
||||
import ch.ethz.seb.sebserver.gbl.util.Result;
|
||||
|
||||
public interface OrientationDAO extends EntityDAO<Orientation, Orientation> {
|
||||
|
||||
/** Use this to delete all Orientation of a defined template.
|
||||
*
|
||||
*
|
||||
* @param templateId the template identifier (PK)
|
||||
* @return Collection of all EntityKey of Orientations that has been deleted */
|
||||
Result<Collection<EntityKey>> deleteAllOfTemplate(Long templateId);
|
||||
|
||||
Result<ConfigurationNode> copyDefaultOrientationsForTemplate(
|
||||
ConfigurationNode node,
|
||||
Map<Long, Long> viewMapping);
|
||||
|
||||
Result<Collection<Orientation>> getAllOfTemplate(Long templateId);
|
||||
|
||||
}
|
||||
|
|
|
@ -8,8 +8,14 @@
|
|||
|
||||
package ch.ethz.seb.sebserver.webservice.servicelayer.dao;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode;
|
||||
import ch.ethz.seb.sebserver.gbl.model.sebconfig.View;
|
||||
import ch.ethz.seb.sebserver.gbl.util.Result;
|
||||
|
||||
public interface ViewDAO extends EntityDAO<View, View> {
|
||||
|
||||
Result<Map<Long, Long>> copyDefaultViewsForTemplate(ConfigurationNode node);
|
||||
|
||||
}
|
||||
|
|
|
@ -113,10 +113,10 @@ public class ConfigurationNodeDAOImpl implements ConfigurationNodeDAO {
|
|||
SqlBuilder.isEqualToWhenPresent(filterMap.getInstitutionId()))
|
||||
.and(
|
||||
ConfigurationNodeRecordDynamicSqlSupport.name,
|
||||
SqlBuilder.isEqualToWhenPresent(filterMap.getName()))
|
||||
SqlBuilder.isLikeWhenPresent(filterMap.getName()))
|
||||
.and(
|
||||
ConfigurationNodeRecordDynamicSqlSupport.description,
|
||||
SqlBuilder.isEqualToWhenPresent(filterMap.getConfigNodeDesc()))
|
||||
SqlBuilder.isLikeWhenPresent(filterMap.getConfigNodeDesc()))
|
||||
.and(
|
||||
ConfigurationNodeRecordDynamicSqlSupport.type,
|
||||
SqlBuilder.isEqualToWhenPresent(filterMap.getConfigNodeType()))
|
||||
|
|
|
@ -105,7 +105,7 @@ public class InstitutionDAOImpl implements InstitutionDAO {
|
|||
SqlBuilder.isEqualToWhenPresent(filterMap.getActiveAsInt()))
|
||||
.and(
|
||||
InstitutionRecordDynamicSqlSupport.name,
|
||||
SqlBuilder.isEqualToWhenPresent(filterMap.getName()))
|
||||
SqlBuilder.isLikeWhenPresent(filterMap.getName()))
|
||||
.build()
|
||||
.execute()
|
||||
.stream()
|
||||
|
|
|
@ -14,6 +14,7 @@ import static org.mybatis.dynamic.sql.SqlBuilder.isIn;
|
|||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
|
@ -25,6 +26,7 @@ import org.springframework.transaction.annotation.Transactional;
|
|||
|
||||
import ch.ethz.seb.sebserver.gbl.api.EntityType;
|
||||
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
|
||||
import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode;
|
||||
import ch.ethz.seb.sebserver.gbl.model.sebconfig.Orientation;
|
||||
import ch.ethz.seb.sebserver.gbl.model.sebconfig.TitleOrientation;
|
||||
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
|
||||
|
@ -151,6 +153,55 @@ public class OrientationDAOImpl implements OrientationDAO {
|
|||
.onError(TransactionHandler::rollback);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public Result<ConfigurationNode> copyDefaultOrientationsForTemplate(
|
||||
final ConfigurationNode node,
|
||||
final Map<Long, Long> viewMapping) {
|
||||
|
||||
return Result.tryCatch(() -> {
|
||||
this.orientationRecordMapper
|
||||
.selectByExample()
|
||||
.where(
|
||||
OrientationRecordDynamicSqlSupport.templateId,
|
||||
SqlBuilder.isEqualTo(ConfigurationNode.DEFAULT_TEMPLATE_ID))
|
||||
.build()
|
||||
.execute()
|
||||
.stream()
|
||||
.forEach(record -> createNew(new Orientation(
|
||||
null,
|
||||
record.getConfigAttributeId(),
|
||||
node.id,
|
||||
viewMapping.get(record.getViewId()),
|
||||
record.getGroupId(),
|
||||
record.getxPosition(),
|
||||
record.getyPosition(),
|
||||
record.getWidth(),
|
||||
record.getHeight(),
|
||||
record.getTitle() != null
|
||||
? TitleOrientation.valueOf(record.getTitle())
|
||||
: TitleOrientation.NONE)));
|
||||
|
||||
return node;
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(readOnly = true)
|
||||
public Result<Collection<Orientation>> getAllOfTemplate(final Long templateId) {
|
||||
return Result.tryCatch(() -> this.orientationRecordMapper
|
||||
.selectByExample()
|
||||
.where(
|
||||
OrientationRecordDynamicSqlSupport.templateId,
|
||||
SqlBuilder.isEqualToWhenPresent(templateId))
|
||||
.build()
|
||||
.execute()
|
||||
.stream()
|
||||
.map(OrientationDAOImpl::toDomainModel)
|
||||
.flatMap(DAOLoggingSupport::logAndSkipOnError)
|
||||
.collect(Collectors.toList()));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public Result<Collection<EntityKey>> delete(final Set<EntityKey> all) {
|
||||
|
@ -215,5 +266,4 @@ public class OrientationDAOImpl implements OrientationDAO {
|
|||
record.getHeight(),
|
||||
TitleOrientation.valueOf(record.getTitle())));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ import static org.mybatis.dynamic.sql.SqlBuilder.isIn;
|
|||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
|
@ -24,9 +25,11 @@ import org.springframework.transaction.annotation.Transactional;
|
|||
|
||||
import ch.ethz.seb.sebserver.gbl.api.EntityType;
|
||||
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
|
||||
import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode;
|
||||
import ch.ethz.seb.sebserver.gbl.model.sebconfig.View;
|
||||
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
|
||||
import ch.ethz.seb.sebserver.gbl.util.Result;
|
||||
import ch.ethz.seb.sebserver.gbl.util.Tuple;
|
||||
import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.ViewRecordDynamicSqlSupport;
|
||||
import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.ViewRecordMapper;
|
||||
import ch.ethz.seb.sebserver.webservice.datalayer.batis.model.ViewRecord;
|
||||
|
@ -85,6 +88,9 @@ public class ViewDAOImpl implements ViewDAO {
|
|||
.where(
|
||||
ViewRecordDynamicSqlSupport.name,
|
||||
SqlBuilder.isEqualToWhenPresent(filterMap.getName()))
|
||||
.and(
|
||||
ViewRecordDynamicSqlSupport.templateId,
|
||||
SqlBuilder.isEqualToWhenPresent(filterMap.getLong(View.FILTER_ATTR_TEMPLATE)))
|
||||
.build()
|
||||
.execute()
|
||||
.stream()
|
||||
|
@ -132,6 +138,34 @@ public class ViewDAOImpl implements ViewDAO {
|
|||
.onError(TransactionHandler::rollback);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public Result<Map<Long, Long>> copyDefaultViewsForTemplate(final ConfigurationNode node) {
|
||||
return Result.tryCatch(() -> {
|
||||
// get all default views, copy them with new template_id and save
|
||||
return this.viewRecordMapper
|
||||
.selectByExample()
|
||||
.where(
|
||||
ViewRecordDynamicSqlSupport.templateId,
|
||||
SqlBuilder.isEqualTo(ConfigurationNode.DEFAULT_TEMPLATE_ID))
|
||||
.build()
|
||||
.execute()
|
||||
.stream()
|
||||
.map(view -> {
|
||||
final ViewRecord newRecord = new ViewRecord(
|
||||
null,
|
||||
view.getName(),
|
||||
view.getColumns(),
|
||||
view.getPosition(),
|
||||
node.id);
|
||||
this.viewRecordMapper.insert(newRecord);
|
||||
return new Tuple<>(view.getId(), newRecord.getId());
|
||||
})
|
||||
.collect(Collectors.toMap(t -> t._1, t -> t._2));
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public Result<Collection<EntityKey>> delete(final Set<EntityKey> all) {
|
||||
|
|
|
@ -12,18 +12,25 @@ import java.io.BufferedInputStream;
|
|||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.servlet.ServletOutputStream;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.mybatis.dynamic.sql.SqlTable;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestHeader;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
|
@ -34,11 +41,19 @@ import org.springframework.web.bind.annotation.RestController;
|
|||
import ch.ethz.seb.sebserver.gbl.api.API;
|
||||
import ch.ethz.seb.sebserver.gbl.api.APIMessage;
|
||||
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.Page;
|
||||
import ch.ethz.seb.sebserver.gbl.model.PageSortOrder;
|
||||
import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigKey;
|
||||
import ch.ethz.seb.sebserver.gbl.model.sebconfig.Configuration;
|
||||
import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode;
|
||||
import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode.ConfigurationType;
|
||||
import ch.ethz.seb.sebserver.gbl.model.sebconfig.Orientation;
|
||||
import ch.ethz.seb.sebserver.gbl.model.sebconfig.TemplateAttribute;
|
||||
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
|
||||
import ch.ethz.seb.sebserver.gbl.util.Result;
|
||||
import ch.ethz.seb.sebserver.gbl.util.Utils;
|
||||
import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.ConfigurationNodeRecordDynamicSqlSupport;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.PaginationService;
|
||||
|
@ -46,9 +61,13 @@ 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.impl.SEBServerUser;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.BulkActionService;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ConfigurationAttributeDAO;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ConfigurationDAO;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ConfigurationNodeDAO;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.FilterMap;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.OrientationDAO;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.UserActivityLogDAO;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ViewDAO;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.SebExamConfigService;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.validation.BeanValidationService;
|
||||
|
||||
|
@ -60,6 +79,9 @@ public class ConfigurationNodeController extends EntityController<ConfigurationN
|
|||
private static final Logger log = LoggerFactory.getLogger(ConfigurationNodeController.class);
|
||||
|
||||
private final ConfigurationDAO configurationDAO;
|
||||
private final ViewDAO viewDAO;
|
||||
private final OrientationDAO orientationDAO;
|
||||
private final ConfigurationAttributeDAO configurationAttributeDAO;
|
||||
private final SebExamConfigService sebExamConfigService;
|
||||
|
||||
protected ConfigurationNodeController(
|
||||
|
@ -70,6 +92,9 @@ public class ConfigurationNodeController extends EntityController<ConfigurationN
|
|||
final PaginationService paginationService,
|
||||
final BeanValidationService beanValidationService,
|
||||
final ConfigurationDAO configurationDAO,
|
||||
final ViewDAO viewDAO,
|
||||
final OrientationDAO orientationDAO,
|
||||
final ConfigurationAttributeDAO configurationAttributeDAO,
|
||||
final SebExamConfigService sebExamConfigService) {
|
||||
|
||||
super(authorization,
|
||||
|
@ -80,6 +105,9 @@ public class ConfigurationNodeController extends EntityController<ConfigurationN
|
|||
beanValidationService);
|
||||
|
||||
this.configurationDAO = configurationDAO;
|
||||
this.viewDAO = viewDAO;
|
||||
this.orientationDAO = orientationDAO;
|
||||
this.configurationAttributeDAO = configurationAttributeDAO;
|
||||
this.sebExamConfigService = sebExamConfigService;
|
||||
}
|
||||
|
||||
|
@ -206,4 +234,101 @@ public class ConfigurationNodeController extends EntityController<ConfigurationN
|
|||
}
|
||||
}
|
||||
|
||||
@RequestMapping(
|
||||
path = API.MODEL_ID_VAR_PATH_SEGMENT + API.TEMPLATE_ATTRIBUTE_ENDPOINT,
|
||||
method = RequestMethod.GET,
|
||||
consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE,
|
||||
produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
|
||||
public Page<TemplateAttribute> getTemplateAttributePage(
|
||||
@PathVariable final Long modelId,
|
||||
@RequestParam(
|
||||
name = API.PARAM_INSTITUTION_ID,
|
||||
required = true,
|
||||
defaultValue = UserService.USERS_INSTITUTION_AS_DEFAULT) final Long institutionId,
|
||||
@RequestParam(name = Page.ATTR_PAGE_NUMBER, required = false) final Integer pageNumber,
|
||||
@RequestParam(name = Page.ATTR_PAGE_SIZE, required = false) final Integer pageSize,
|
||||
@RequestParam(name = Page.ATTR_SORT, required = false) final String sort,
|
||||
@RequestParam final MultiValueMap<String, String> allRequestParams) {
|
||||
|
||||
// at least current user must have read access for specified entity type within its own institution
|
||||
checkReadPrivilege(institutionId);
|
||||
|
||||
final FilterMap filterMap = new FilterMap(allRequestParams);
|
||||
|
||||
// if current user has no read access for specified entity type within other institution
|
||||
// then the current users institutionId is put as a SQL filter criteria attribute to extends query performance
|
||||
if (!this.authorization.hasGrant(PrivilegeType.READ, getGrantEntityType())) {
|
||||
filterMap.putIfAbsent(API.PARAM_INSTITUTION_ID, String.valueOf(institutionId));
|
||||
}
|
||||
|
||||
final Map<Long, Orientation> orentiations = this.orientationDAO.getAllOfTemplate(modelId)
|
||||
.getOrThrow()
|
||||
.stream()
|
||||
.collect(Collectors.toMap(
|
||||
o -> o.attributeId,
|
||||
Function.identity()));
|
||||
|
||||
final List<TemplateAttribute> attrs = this.configurationAttributeDAO
|
||||
.getAllRootAttributes()
|
||||
.getOrThrow()
|
||||
.stream()
|
||||
.map(attr -> new TemplateAttribute(institutionId, modelId, attr, orentiations.get(attr.id)))
|
||||
.filter(attr -> attr.isNameLike(filterMap.getString(TemplateAttribute.FILTER_ATTR_NAME))
|
||||
&& attr.isGroupLike(filterMap.getString(TemplateAttribute.FILTER_ATTR_GROUP))
|
||||
&& attr.isInView(filterMap.getLong(TemplateAttribute.FILTER_ATTR_VIEW)))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
if (!StringUtils.isBlank(sort)) {
|
||||
final String sortBy = PageSortOrder.decode(sort);
|
||||
final PageSortOrder sortOrder = PageSortOrder.getSortOrder(sort);
|
||||
if (sortBy.equals(Domain.CONFIGURATION_NODE.ATTR_NAME)) {
|
||||
Collections.sort(attrs, TemplateAttribute.nameComparator(sortOrder == PageSortOrder.DESCENDING));
|
||||
}
|
||||
}
|
||||
|
||||
final int start = (pageNumber - 1) * pageSize;
|
||||
int end = start + pageSize;
|
||||
if (attrs.size() < end) {
|
||||
end = attrs.size();
|
||||
}
|
||||
|
||||
return new Page<>(
|
||||
attrs.size() / pageSize,
|
||||
pageNumber,
|
||||
sort,
|
||||
attrs.subList(start, end));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Result<ConfigurationNode> validForSave(final ConfigurationNode entity) {
|
||||
return super.validForSave(entity)
|
||||
.map(e -> {
|
||||
final ConfigurationNode existingNode = this.entityDAO.byPK(entity.id)
|
||||
.getOrThrow();
|
||||
if (existingNode.type != entity.type) {
|
||||
throw new APIConstraintViolationException(
|
||||
"The Type of ConfigurationNode cannot change after creation");
|
||||
}
|
||||
return e;
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Result<ConfigurationNode> notifyCreated(final ConfigurationNode entity) {
|
||||
return super.notifyCreated(entity)
|
||||
.map(this::createTemplate);
|
||||
}
|
||||
|
||||
private ConfigurationNode createTemplate(final ConfigurationNode node) {
|
||||
if (node.type != null && node.type == ConfigurationType.TEMPLATE) {
|
||||
// create views and orientations for node
|
||||
return this.viewDAO.copyDefaultViewsForTemplate(node)
|
||||
.flatMap(viewMapping -> this.orientationDAO.copyDefaultOrientationsForTemplate(
|
||||
node,
|
||||
viewMapping))
|
||||
.getOrThrow();
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
|
|||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.api.API;
|
||||
import ch.ethz.seb.sebserver.gbl.api.EntityType;
|
||||
import ch.ethz.seb.sebserver.gbl.api.POSTMapper;
|
||||
import ch.ethz.seb.sebserver.gbl.model.GrantEntity;
|
||||
import ch.ethz.seb.sebserver.gbl.model.sebconfig.View;
|
||||
|
@ -57,6 +58,11 @@ public class ViewController extends EntityController<View, View> {
|
|||
return ViewRecordDynamicSqlSupport.viewRecord;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected EntityType getGrantEntityType() {
|
||||
return EntityType.CONFIGURATION_NODE;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Result<View> checkCreateAccess(final View entity) {
|
||||
// Skips the entity based grant check
|
||||
|
|
|
@ -41,17 +41,17 @@ INSERT IGNORE INTO threshold VALUES
|
|||
;
|
||||
|
||||
INSERT IGNORE INTO view VALUES
|
||||
(1, 'general', 4, 1, null),
|
||||
(2, 'user_interface', 12, 2, null),
|
||||
(3, 'browser', 12, 3, null),
|
||||
(4, 'down_upload', 12, 4, null),
|
||||
(5, 'exam', 12, 5, null),
|
||||
(6, 'applications', 12, 6, null),
|
||||
(7, 'resources', 12, 7, null),
|
||||
(8, 'network', 12, 8, null),
|
||||
(9, 'security', 12, 9, null),
|
||||
(10, 'registry', 12, 10, null),
|
||||
(11, 'hooked_keys', 12, 11, null);
|
||||
(1, 'general', 4, 1, 0),
|
||||
(2, 'user_interface', 12, 2, 0),
|
||||
(3, 'browser', 12, 3, 0),
|
||||
(4, 'down_upload', 12, 4, 0),
|
||||
(5, 'exam', 12, 5, 0),
|
||||
(6, 'applications', 12, 6, 0),
|
||||
(7, 'resources', 12, 7, 0),
|
||||
(8, 'network', 12, 8, 0),
|
||||
(9, 'security', 12, 9, 0),
|
||||
(10, 'registry', 12, 10, 0),
|
||||
(11, 'hooked_keys', 12, 11, 0);
|
||||
|
||||
INSERT IGNORE INTO configuration_attribute VALUES
|
||||
(1, 'hashedAdminPassword', 'PASSWORD_FIELD', null, null, null, null, null),
|
||||
|
|
|
@ -14,17 +14,17 @@ INSERT IGNORE INTO user_role VALUES
|
|||
;
|
||||
|
||||
INSERT IGNORE INTO view VALUES
|
||||
(1, 'general', 4, 1, null),
|
||||
(2, 'user_interface', 12, 2, null),
|
||||
(3, 'browser', 12, 3, null),
|
||||
(4, 'down_upload', 12, 4, null),
|
||||
(5, 'exam', 12, 5, null),
|
||||
(6, 'applications', 12, 6, null),
|
||||
(7, 'resources', 12, 7, null),
|
||||
(8, 'network', 12, 8, null),
|
||||
(9, 'security', 12, 9, null),
|
||||
(10, 'registry', 12, 10, null),
|
||||
(11, 'hooked_keys', 12, 11, null);
|
||||
(1, 'general', 4, 1, 0),
|
||||
(2, 'user_interface', 12, 2, 0),
|
||||
(3, 'browser', 12, 3, 0),
|
||||
(4, 'down_upload', 12, 4, 0),
|
||||
(5, 'exam', 12, 5, 0),
|
||||
(6, 'applications', 12, 6, 0),
|
||||
(7, 'resources', 12, 7, 0),
|
||||
(8, 'network', 12, 8, 0),
|
||||
(9, 'security', 12, 9, 0),
|
||||
(10, 'registry', 12, 10, 0),
|
||||
(11, 'hooked_keys', 12, 11, 0);
|
||||
|
||||
INSERT IGNORE INTO configuration_attribute VALUES
|
||||
(1, 'hashedAdminPassword', 'PASSWORD_FIELD', null, null, null, null, null),
|
||||
|
|
|
@ -429,7 +429,7 @@ sebserver.examconfig.list.column.status=Status
|
|||
sebserver.examconfig.list.actions=Selected Configuration
|
||||
|
||||
sebserver.examconfig.list.empty=There is currently no SEB-Exam configuration available. Please create a new one
|
||||
sebserver.examconfig.info.pleaseSelect=Please Select an exam configuration first
|
||||
sebserver.examconfig.info.pleaseSelect=Please select an exam configuration first
|
||||
sebserver.examconfig.list.action.no.modify.privilege=No Access: An Exam Configuration from other institution cannot be modified.
|
||||
|
||||
sebserver.examconfig.action.list.new=Add Exam Configuration
|
||||
|
@ -925,6 +925,38 @@ sebserver.examconfig.props.validation.DecimalTypeValidator=Invalid decimal numbe
|
|||
sebserver.examconfig.props.validation.ExitKeySequenceValidator=Key is already in sequence
|
||||
sebserver.examconfig.props.validation.WindowsSizeValidator=Invalid number
|
||||
|
||||
################################
|
||||
# SEB Exam Configuration Template
|
||||
################################
|
||||
|
||||
sebserver.configtemplate.list.title=Configuration Templates
|
||||
sebserver.configtemplate.list.empty=There is currently no SEB-Exam configuration template available. Please create a new one
|
||||
sebserver.configtemplate.list.actions=Selected Template
|
||||
|
||||
sebserver.configtemplate.info.pleaseSelect=Please select an exam configuration template first
|
||||
|
||||
sebserver.exam.configtemplate.action.list.new=New Template
|
||||
sebserver.configtemplate.action.list.view=View Template
|
||||
sebserver.configtemplate.action.view=View Template
|
||||
sebserver.configtemplate.action.list.modify=Edit Template
|
||||
sebserver.configtemplate.action.modify=Edit Template
|
||||
|
||||
sebserver.configtemplate.form.title.new=New Template
|
||||
sebserver.configtemplate.form.title=Configuration Template
|
||||
sebserver.configtemplate.form.name=Name
|
||||
sebserver.configtemplate.form.description=Description
|
||||
sebserver.configtemplate.action.save=Save Template
|
||||
|
||||
sebserver.configtemplate.attrs.list.title=Configuration Attributes
|
||||
sebserver.configtemplate.attrs.list.name=Name
|
||||
sebserver.configtemplate.attrs.list.view=View
|
||||
sebserver.configtemplate.attrs.list.group=Group
|
||||
|
||||
sebserver.configtemplate.attr.list.actions=Selected Attribute
|
||||
sebserver.configtemplate.attr.list.actions.modify=Edit Attribute
|
||||
sebserver.configtemplate.attr.list.actions.setdefault=Set Default Values
|
||||
sebserver.configtemplate.attr.list.actions.removeview=Remove View
|
||||
|
||||
|
||||
################################
|
||||
# Monitoring
|
||||
|
|
|
@ -22,17 +22,17 @@ INSERT IGNORE INTO threshold VALUES
|
|||
;
|
||||
|
||||
INSERT IGNORE INTO view VALUES
|
||||
(1, 'general', 4, 1, null),
|
||||
(2, 'user_interface', 12, 2, null),
|
||||
(3, 'browser', 12, 3, null),
|
||||
(4, 'down_upload', 12, 4, null),
|
||||
(5, 'exam', 12, 5, null),
|
||||
(6, 'applications', 12, 6, null),
|
||||
(7, 'resources', 12, 7, null),
|
||||
(8, 'network', 12, 8, null),
|
||||
(9, 'security', 12, 9, null),
|
||||
(10, 'registry', 12, 10, null),
|
||||
(11, 'hooked_keys', 12, 11, null);
|
||||
(1, 'general', 4, 1, 0),
|
||||
(2, 'user_interface', 12, 2, 0),
|
||||
(3, 'browser', 12, 3, 0),
|
||||
(4, 'down_upload', 12, 4, 0),
|
||||
(5, 'exam', 12, 5, 0),
|
||||
(6, 'applications', 12, 6, 0),
|
||||
(7, 'resources', 12, 7, 0),
|
||||
(8, 'network', 12, 8, 0),
|
||||
(9, 'security', 12, 9, 0),
|
||||
(10, 'registry', 12, 10, 0),
|
||||
(11, 'hooked_keys', 12, 11, 0);
|
||||
|
||||
INSERT IGNORE INTO configuration_attribute VALUES
|
||||
(1, 'hashedAdminPassword', 'PASSWORD_FIELD', null, null, null, null, null),
|
||||
|
|
Loading…
Reference in a new issue