SEBSERV-218 implemented
This commit is contained in:
parent
a979d4c13b
commit
3b4c168c43
7 changed files with 159 additions and 12 deletions
|
@ -8,6 +8,10 @@
|
|||
|
||||
package ch.ethz.seb.sebserver.gui.content.configs;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.eclipse.swt.widgets.Composite;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
|
@ -19,13 +23,16 @@ import ch.ethz.seb.sebserver.gbl.api.EntityType;
|
|||
import ch.ethz.seb.sebserver.gbl.model.Domain;
|
||||
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
|
||||
import ch.ethz.seb.sebserver.gbl.model.EntityProcessingReport;
|
||||
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.ConfigurationStatus;
|
||||
import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode.ConfigurationType;
|
||||
import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationValue;
|
||||
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.gbl.util.Result;
|
||||
import ch.ethz.seb.sebserver.gbl.util.Utils;
|
||||
import ch.ethz.seb.sebserver.gui.content.action.ActionDefinition;
|
||||
import ch.ethz.seb.sebserver.gui.form.FormBuilder;
|
||||
import ch.ethz.seb.sebserver.gui.form.FormHandle;
|
||||
|
@ -40,6 +47,8 @@ import ch.ethz.seb.sebserver.gui.service.page.TemplateComposer;
|
|||
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.seb.examconfig.DeleteExamConfiguration;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.GetConfigurationValues;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.GetConfigurations;
|
||||
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;
|
||||
|
@ -75,6 +84,8 @@ public class ConfigTemplateForm implements TemplateComposer {
|
|||
new LocTextKey("sebserver.configtemplate.attrs.list.view");
|
||||
private static final LocTextKey ATTRIBUTES_LIST_GROUP_TEXT_KEY =
|
||||
new LocTextKey("sebserver.configtemplate.attrs.list.group");
|
||||
private static final LocTextKey ATTRIBUTES_LIST_VALUE_TEXT_KEY =
|
||||
new LocTextKey("sebserver.configtemplate.attrs.list.value");
|
||||
private static final LocTextKey ATTRIBUTES_LIST_TYPE_TEXT_KEY =
|
||||
new LocTextKey("sebserver.configtemplate.attrs.list.type");
|
||||
private static final LocTextKey EMPTY_ATTRIBUTE_SELECTION_TEXT_KEY =
|
||||
|
@ -205,6 +216,20 @@ public class ConfigTemplateForm implements TemplateComposer {
|
|||
TemplateAttribute.FILTER_ATTR_TYPE,
|
||||
this.resourceService::getAttributeTypeResources);
|
||||
|
||||
// TODO move this to an supplier that also can be updated
|
||||
// the follow-up configuration
|
||||
final Configuration configuration = this.restService
|
||||
.getBuilder(GetConfigurations.class)
|
||||
.withQueryParam(Configuration.FILTER_ATTR_CONFIGURATION_NODE_ID, examConfig.getModelId())
|
||||
.withQueryParam(Configuration.FILTER_ATTR_FOLLOWUP, Constants.TRUE_STRING)
|
||||
.call()
|
||||
.map(Utils::toSingleton)
|
||||
.onError(error -> pageContext.notifyLoadError(EntityType.CONFIGURATION, error))
|
||||
.getOrThrow();
|
||||
final AttributeValueSupplier attributeValueSupplier = new AttributeValueSupplier(
|
||||
this.pageService,
|
||||
configuration.getModelId());
|
||||
|
||||
final EntityTable<TemplateAttribute> attrTable =
|
||||
this.pageService.entityTableBuilder(
|
||||
Domain.CONFIGURATION_NODE.TYPE_NAME + "_Template",
|
||||
|
@ -213,6 +238,7 @@ public class ConfigTemplateForm implements TemplateComposer {
|
|||
API.PARAM_PARENT_MODEL_ID,
|
||||
entityKey.modelId))
|
||||
.withPaging(15)
|
||||
|
||||
.withColumn(new ColumnDefinition<>(
|
||||
Domain.CONFIGURATION_ATTRIBUTE.ATTR_NAME,
|
||||
ATTRIBUTES_LIST_NAME_TEXT_KEY,
|
||||
|
@ -220,6 +246,7 @@ public class ConfigTemplateForm implements TemplateComposer {
|
|||
.withFilter(this.nameFilter)
|
||||
.sortable()
|
||||
.widthProportion(3))
|
||||
|
||||
.withColumn(new ColumnDefinition<TemplateAttribute>(
|
||||
Domain.CONFIGURATION_ATTRIBUTE.ATTR_TYPE,
|
||||
ATTRIBUTES_LIST_TYPE_TEXT_KEY,
|
||||
|
@ -227,6 +254,7 @@ public class ConfigTemplateForm implements TemplateComposer {
|
|||
.withFilter(typeFilter)
|
||||
.sortable()
|
||||
.widthProportion(1))
|
||||
|
||||
.withColumn(new ColumnDefinition<>(
|
||||
Domain.ORIENTATION.ATTR_VIEW_ID,
|
||||
ATTRIBUTES_LIST_VIEW_TEXT_KEY,
|
||||
|
@ -234,6 +262,7 @@ public class ConfigTemplateForm implements TemplateComposer {
|
|||
.withFilter(viewFilter)
|
||||
.sortable()
|
||||
.widthProportion(1))
|
||||
|
||||
.withColumn(new ColumnDefinition<>(
|
||||
Domain.ORIENTATION.ATTR_GROUP_ID,
|
||||
ATTRIBUTES_LIST_GROUP_TEXT_KEY,
|
||||
|
@ -241,6 +270,13 @@ public class ConfigTemplateForm implements TemplateComposer {
|
|||
.withFilter(this.groupFilter)
|
||||
.sortable()
|
||||
.widthProportion(1))
|
||||
|
||||
.withColumn(new ColumnDefinition<TemplateAttribute>(
|
||||
Domain.CONFIGURATION_VALUE.ATTR_VALUE,
|
||||
ATTRIBUTES_LIST_VALUE_TEXT_KEY,
|
||||
attr -> attributeValueSupplier.getAttributeValue(attr.getConfigAttribute().id))
|
||||
.widthProportion(1))
|
||||
|
||||
.withDefaultActionIf(
|
||||
() -> modifyGrant,
|
||||
() -> pageActionBuilder
|
||||
|
@ -271,7 +307,7 @@ public class ConfigTemplateForm implements TemplateComposer {
|
|||
.withParentEntityKey(entityKey)
|
||||
.withSelect(
|
||||
attrTable::getMultiSelection,
|
||||
action -> this.resetToDefaults(action, attrTable),
|
||||
action -> this.resetToDefaults(attributeValueSupplier, action, attrTable),
|
||||
EMPTY_ATTRIBUTE_SELECTION_TEXT_KEY)
|
||||
.noEventPropagation()
|
||||
.publishIf(() -> modifyGrant, false)
|
||||
|
@ -378,12 +414,14 @@ public class ConfigTemplateForm implements TemplateComposer {
|
|||
}
|
||||
|
||||
private PageAction resetToDefaults(
|
||||
final AttributeValueSupplier attributeValueSupplier,
|
||||
final PageAction action,
|
||||
final EntityTable<TemplateAttribute> attrTable) {
|
||||
|
||||
final PageAction resetToDefaults = this.examConfigurationService.resetToDefaults(action);
|
||||
// reload the list
|
||||
attrTable.applyFilter();
|
||||
attributeValueSupplier.update();
|
||||
attrTable.updateCurrentPage();
|
||||
return resetToDefaults;
|
||||
}
|
||||
|
||||
|
@ -392,8 +430,8 @@ public class ConfigTemplateForm implements TemplateComposer {
|
|||
final EntityTable<TemplateAttribute> attrTable) {
|
||||
|
||||
final PageAction removeFormView = this.examConfigurationService.removeFromView(action);
|
||||
// reload the list
|
||||
attrTable.applyFilter();
|
||||
// reload the page
|
||||
attrTable.updateCurrentPage();
|
||||
return removeFormView;
|
||||
}
|
||||
|
||||
|
@ -402,9 +440,54 @@ public class ConfigTemplateForm implements TemplateComposer {
|
|||
final EntityTable<TemplateAttribute> attrTable) {
|
||||
|
||||
final PageAction attachView = this.examConfigurationService.attachToDefaultView(action);
|
||||
// reload the list
|
||||
attrTable.applyFilter();
|
||||
// reload the page
|
||||
attrTable.updateCurrentPage();
|
||||
return attachView;
|
||||
}
|
||||
|
||||
private final class AttributeValueSupplier {
|
||||
|
||||
private final PageService pageService;
|
||||
private final String configurationId;
|
||||
private final Map<Long, String> attrValueMapping = new HashMap<>();
|
||||
|
||||
public AttributeValueSupplier(
|
||||
final PageService pageService,
|
||||
final String configurationId) {
|
||||
|
||||
this.pageService = pageService;
|
||||
this.configurationId = configurationId;
|
||||
update();
|
||||
}
|
||||
|
||||
public String getAttributeValue(final Long attributeId) {
|
||||
if (this.attrValueMapping.containsKey(attributeId)) {
|
||||
return this.attrValueMapping.get(attributeId);
|
||||
} else {
|
||||
return Constants.EMPTY_NOTE;
|
||||
}
|
||||
}
|
||||
|
||||
private void update() {
|
||||
this.attrValueMapping.clear();
|
||||
|
||||
this.pageService.getRestService()
|
||||
.getBuilder(GetConfigurationValues.class)
|
||||
.withQueryParam(
|
||||
ConfigurationValue.FILTER_ATTR_CONFIGURATION_ID,
|
||||
this.configurationId)
|
||||
.call()
|
||||
.getOrElse(Collections::emptyList)
|
||||
.stream()
|
||||
.forEach(val -> {
|
||||
if (this.attrValueMapping.containsKey(val.attributeId)) {
|
||||
this.attrValueMapping.put(val.attributeId,
|
||||
this.attrValueMapping.get(val.attributeId) + "," + val.value);
|
||||
} else {
|
||||
this.attrValueMapping.put(val.attributeId, val.value);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -72,6 +72,11 @@ public class ExamConfigurationServiceImpl implements ExamConfigurationService {
|
|||
|
||||
private static final Logger log = LoggerFactory.getLogger(ExamConfigurationServiceImpl.class);
|
||||
|
||||
public static final LocTextKey ACTION_ERROR_TITLE =
|
||||
new LocTextKey("sebserver.configtemplate.action.error.title");
|
||||
public static final LocTextKey ACTION_ERROR_MSG =
|
||||
new LocTextKey("sebserver.configtemplate.action.error.noview.message");
|
||||
|
||||
private final RestService restService;
|
||||
private final JSONMapper jsonMapper;
|
||||
private final WidgetFactory widgetFactory;
|
||||
|
@ -254,12 +259,14 @@ public class ExamConfigurationServiceImpl implements ExamConfigurationService {
|
|||
final Set<EntityKey> selection = action.getMultiSelection();
|
||||
if (selection != null && !selection.isEmpty()) {
|
||||
selection.forEach(entityKey -> callTemplateAction(
|
||||
action,
|
||||
ResetTemplateValues.class,
|
||||
parentEntityKey.modelId,
|
||||
entityKey.modelId));
|
||||
} else {
|
||||
final EntityKey entityKey = action.getEntityKey();
|
||||
callTemplateAction(
|
||||
action,
|
||||
ResetTemplateValues.class,
|
||||
parentEntityKey.modelId,
|
||||
entityKey.modelId);
|
||||
|
@ -274,12 +281,14 @@ public class ExamConfigurationServiceImpl implements ExamConfigurationService {
|
|||
final Set<EntityKey> selection = action.getMultiSelection();
|
||||
if (selection != null && !selection.isEmpty()) {
|
||||
selection.forEach(entityKey -> callTemplateAction(
|
||||
action,
|
||||
RemoveOrientation.class,
|
||||
parentEntityKey.modelId,
|
||||
entityKey.modelId));
|
||||
} else {
|
||||
final EntityKey entityKey = action.getEntityKey();
|
||||
callTemplateAction(
|
||||
action,
|
||||
RemoveOrientation.class,
|
||||
parentEntityKey.modelId,
|
||||
entityKey.modelId);
|
||||
|
@ -294,21 +303,23 @@ public class ExamConfigurationServiceImpl implements ExamConfigurationService {
|
|||
final Set<EntityKey> selection = action.getMultiSelection();
|
||||
if (selection != null && !selection.isEmpty()) {
|
||||
selection.forEach(entityKey -> callTemplateAction(
|
||||
action,
|
||||
AttachDefaultOrientation.class,
|
||||
parentEntityKey.modelId,
|
||||
entityKey.modelId));
|
||||
} else {
|
||||
final EntityKey entityKey = action.getEntityKey();
|
||||
callTemplateAction(
|
||||
action,
|
||||
AttachDefaultOrientation.class,
|
||||
parentEntityKey.modelId,
|
||||
entityKey.modelId);
|
||||
}
|
||||
|
||||
return action;
|
||||
}
|
||||
|
||||
private void callTemplateAction(
|
||||
final PageAction action,
|
||||
final Class<? extends RestCall<TemplateAttribute>> actionType,
|
||||
final String templateId,
|
||||
final String attributeId) {
|
||||
|
@ -317,7 +328,11 @@ public class ExamConfigurationServiceImpl implements ExamConfigurationService {
|
|||
.withURIVariable(API.PARAM_PARENT_MODEL_ID, templateId)
|
||||
.withURIVariable(API.PARAM_MODEL_ID, attributeId)
|
||||
.call()
|
||||
.getOrThrow();
|
||||
.onError(error -> {
|
||||
action.pageContext().publishPageMessage(
|
||||
ACTION_ERROR_TITLE,
|
||||
ACTION_ERROR_MSG);
|
||||
});
|
||||
}
|
||||
|
||||
private static final class ValueChangeListenerImpl implements ValueChangeListener {
|
||||
|
|
|
@ -300,6 +300,10 @@ public class EntityTable<ROW extends ModelIdAware> {
|
|||
applyFilter();
|
||||
}
|
||||
|
||||
public void updateCurrentPage() {
|
||||
this.selectPage(this.pageNumber);
|
||||
}
|
||||
|
||||
public void applyFilter() {
|
||||
try {
|
||||
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* Copyright (c) 2022 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.webservice.servicelayer.dao;
|
||||
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.api.EntityType;
|
||||
|
||||
@ResponseStatus(HttpStatus.NOT_FOUND)
|
||||
public class NoResourceFoundException extends RuntimeException {
|
||||
|
||||
private static final long serialVersionUID = 4347712679241097195L;
|
||||
public final EntityType entityType;
|
||||
|
||||
public NoResourceFoundException(final EntityType entityType, final String message) {
|
||||
super("Resource " + entityType + " not found: " + message);
|
||||
this.entityType = entityType;
|
||||
}
|
||||
|
||||
}
|
|
@ -25,6 +25,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.EntityType;
|
||||
import ch.ethz.seb.sebserver.gbl.model.Domain;
|
||||
import ch.ethz.seb.sebserver.gbl.model.PageSortOrder;
|
||||
import ch.ethz.seb.sebserver.gbl.model.sebconfig.AttributeType;
|
||||
|
@ -39,6 +40,7 @@ import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ConfigurationAttributeD
|
|||
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ConfigurationDAO;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ConfigurationValueDAO;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.FilterMap;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.NoResourceFoundException;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.OrientationDAO;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ViewDAO;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.ExamConfigTemplateService;
|
||||
|
@ -172,7 +174,13 @@ public class ExamConfigTemplateServiceImpl implements ExamConfigTemplateService
|
|||
return Result.tryCatch(() -> {
|
||||
final Orientation orientation = getOrientation(templateId, attributeId);
|
||||
|
||||
this.orientationDAO.delete(new HashSet<>(Arrays.asList(orientation.getEntityKey())))
|
||||
if (orientation == null) {
|
||||
throw new NoResourceFoundException(EntityType.ORIENTATION,
|
||||
"No default view found for attribute: " + attributeId);
|
||||
}
|
||||
|
||||
this.orientationDAO
|
||||
.delete(new HashSet<>(Arrays.asList(orientation.getEntityKey())))
|
||||
.getOrThrow();
|
||||
|
||||
final TemplateAttribute attribute = getAttribute(institutionId, templateId, attributeId)
|
||||
|
@ -198,8 +206,14 @@ public class ExamConfigTemplateServiceImpl implements ExamConfigTemplateService
|
|||
final Orientation orientation = getOrientation(templateId, attributeId);
|
||||
final Orientation devOrientation = getOrientation(ConfigurationNode.DEFAULT_TEMPLATE_ID, attributeId);
|
||||
|
||||
if (devOrientation == null) {
|
||||
throw new NoResourceFoundException(EntityType.ORIENTATION,
|
||||
"No default view found for attribute: " + attributeId);
|
||||
}
|
||||
|
||||
if (orientation != null) {
|
||||
this.orientationDAO.delete(new HashSet<>(Arrays.asList(orientation.getEntityKey())))
|
||||
this.orientationDAO
|
||||
.delete(new HashSet<>(Arrays.asList(orientation.getEntityKey())))
|
||||
.getOrThrow();
|
||||
}
|
||||
|
||||
|
@ -246,7 +260,7 @@ public class ExamConfigTemplateServiceImpl implements ExamConfigTemplateService
|
|||
|
||||
return this.orientationDAO.allMatching(filterMap)
|
||||
.get(error -> {
|
||||
log.warn("Unexpecrted error while get Orientation: ", error);
|
||||
log.warn("Unexpected error while get Orientation: ", error);
|
||||
return Collections.emptyList();
|
||||
})
|
||||
.stream()
|
||||
|
|
|
@ -455,7 +455,6 @@ public class ZoomProctoringService implements ExamProctoringService {
|
|||
e);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -1667,7 +1667,11 @@ sebserver.configtemplate.attrs.list.group=Group
|
|||
sebserver.configtemplate.attrs.list.group.tooltip=The group on the view/tab where the exam configuration attribute belongs to<br/><br/>{0}
|
||||
sebserver.configtemplate.attrs.list.type=Type
|
||||
sebserver.configtemplate.attrs.list.type.tooltip=The type of the exam configuration attribute<br/><br/>{0}
|
||||
sebserver.configtemplate.attrs.list.value=Value
|
||||
sebserver.configtemplate.attrs.list.value.tooltip=The settings value that is set as default value for this template
|
||||
|
||||
sebserver.configtemplate.action.error.title=Action Failed
|
||||
sebserver.configtemplate.action.error.noview.message=This setting has no default view<br/>and cannot be attached/detached from a view
|
||||
sebserver.configtemplate.attr.list.actions=
|
||||
sebserver.configtemplate.attr.list.actions.modify=Edit Attribute
|
||||
sebserver.configtemplate.attr.list.actions.setdefault=Set Default Values
|
||||
|
@ -1675,6 +1679,7 @@ sebserver.configtemplate.attr.list.actions.removeview=Remove From View
|
|||
sebserver.configtemplate.attr.list.actions.attach-default-view=Attach To View
|
||||
sebserver.configtemplate.attr.info.pleaseSelect=At first please select an Attribute from the list
|
||||
|
||||
|
||||
sebserver.configtemplate.attr.form.title=Configuration Template Attribute
|
||||
sebserver.configtemplate.attr.form.title.subtitle=
|
||||
sebserver.configtemplate.attr.form.name=Name
|
||||
|
|
Loading…
Reference in a new issue