diff --git a/src/main/java/ch/ethz/seb/sebserver/gbl/model/sebconfig/TemplateAttribute.java b/src/main/java/ch/ethz/seb/sebserver/gbl/model/sebconfig/TemplateAttribute.java index 65682434..b7a67f45 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gbl/model/sebconfig/TemplateAttribute.java +++ b/src/main/java/ch/ethz/seb/sebserver/gbl/model/sebconfig/TemplateAttribute.java @@ -9,6 +9,7 @@ package ch.ethz.seb.sebserver.gbl.model.sebconfig; import java.util.Comparator; +import java.util.EnumSet; import javax.validation.constraints.NotNull; @@ -17,6 +18,7 @@ import org.apache.commons.lang3.StringUtils; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; +import ch.ethz.seb.sebserver.gbl.Constants; 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; @@ -28,6 +30,7 @@ public final class TemplateAttribute implements Entity { public static final String FILTER_ATTR_VIEW = "view"; public static final String FILTER_ATTR_GROUP = "group"; + public static final String FILTER_ATTR_TYPE = "type"; @NotNull @JsonProperty(CONFIGURATION.ATTR_INSTITUTION_ID) @@ -133,6 +136,15 @@ public final class TemplateAttribute implements Entity { && this.orientation.groupId.contains(groupId); } + @JsonIgnore + public boolean hasType(final EnumSet types) { + if (types == null || types.isEmpty()) { + return true; + } + + return types.contains(this.configAttribute.type); + } + @Override public String toString() { final StringBuilder builder = new StringBuilder(); @@ -153,4 +165,23 @@ public final class TemplateAttribute implements Entity { attr2.configAttribute.name) * ((descending) ? -1 : 1); } + public static final Comparator typeComparator(final boolean descending) { + return (attr1, attr2) -> attr1.configAttribute.type.name().compareToIgnoreCase( + attr2.configAttribute.type.name()) * ((descending) ? -1 : 1); + } + + public static final Comparator groupComparator(final boolean descending) { + return (attr1, attr2) -> { + final Orientation o1 = attr1.getOrientation(); + final Orientation o2 = attr2.getOrientation(); + final String name1 = (o1 != null && o1.getGroupId() != null) + ? o1.getGroupId() + : Constants.EMPTY_NOTE; + final String name2 = (o2 != null && o2.getGroupId() != null) + ? o2.getGroupId() + : Constants.EMPTY_NOTE; + return name1.compareToIgnoreCase(name2) * ((descending) ? -1 : 1); + }; + } + } diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/content/ConfigTemplateAttributeForm.java b/src/main/java/ch/ethz/seb/sebserver/gui/content/ConfigTemplateAttributeForm.java index bf384c63..6bf5cb29 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/content/ConfigTemplateAttributeForm.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/content/ConfigTemplateAttributeForm.java @@ -22,14 +22,15 @@ 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.Configuration; +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.TemplateAttribute; +import ch.ethz.seb.sebserver.gbl.model.sebconfig.TitleOrientation; import ch.ethz.seb.sebserver.gbl.model.sebconfig.View; -import ch.ethz.seb.sebserver.gbl.model.user.UserInfo; import ch.ethz.seb.sebserver.gbl.profile.GuiProfile; 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; import ch.ethz.seb.sebserver.gui.service.ResourceService; import ch.ethz.seb.sebserver.gui.service.examconfig.ExamConfigurationService; import ch.ethz.seb.sebserver.gui.service.examconfig.InputField; @@ -42,8 +43,10 @@ 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.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.GetTemplateAttribute; 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.widget.WidgetFactory; import ch.ethz.seb.sebserver.gui.widget.WidgetFactory.CustomVariant; @@ -89,11 +92,19 @@ public class ConfigTemplateAttributeForm implements TemplateComposer { public void compose(final PageContext pageContext) { final WidgetFactory widgetFactory = this.pageService.getWidgetFactory(); - final UserInfo user = this.currentUser.get(); final EntityKey attributeKey = pageContext.getEntityKey(); final EntityKey templateKey = pageContext.getParentEntityKey(); final Long templateId = Long.valueOf(templateKey.modelId); + final ConfigurationNode template = this.restService + .getBuilder(GetExamConfigNode.class) + .withURIVariable(API.PARAM_MODEL_ID, templateKey.modelId) + .call() + .get(pageContext::notifyError); + + final EntityGrantCheck entityGrant = this.currentUser.entityGrantCheck(template); + final boolean modifyGrant = entityGrant.m(); + // the attribute final TemplateAttribute attribute = this.restService.getBuilder(GetTemplateAttribute.class) .withURIVariable(API.PARAM_PARENT_MODEL_ID, templateKey.modelId) @@ -119,7 +130,7 @@ public class ConfigTemplateAttributeForm implements TemplateComposer { final boolean hasView = attribute.getOrientation() != null; - final FormHandle formHandle = this.pageService.formBuilder( + this.pageService.formBuilder( formContext, 4) .readonly(true) // TODO change this for next version .addField(FormBuilder.text( @@ -129,7 +140,7 @@ public class ConfigTemplateAttributeForm implements TemplateComposer { .addField(FormBuilder.text( Domain.CONFIGURATION_ATTRIBUTE.ATTR_TYPE, FORM_TYPE_TEXT_KEY, - () -> attribute.getConfigAttribute().getType().name())) + () -> this.resourceService.getAttributeTypeName(attribute))) .addFieldIf( () -> hasView, () -> FormBuilder.singleSelection( @@ -156,13 +167,10 @@ public class ConfigTemplateAttributeForm implements TemplateComposer { final PageContext valueContext = formContext.copyOf(grid); - final InputFieldBuilder inputFieldBuilder = this.examConfigurationService.getInputFieldBuilder( - attribute.getConfigAttribute(), - attribute.getOrientation()); + final Orientation defaultOrientation = getDefaultOrientation(attribute); final AttributeMapping attributeMapping = this.examConfigurationService - .getAttributes(templateId) + .getAttributes(attribute, defaultOrientation) .getOrThrow(); - final ViewContext viewContext = this.examConfigurationService.createViewContext( valueContext, configuration, @@ -170,6 +178,10 @@ public class ConfigTemplateAttributeForm implements TemplateComposer { attributeMapping, 1); + final InputFieldBuilder inputFieldBuilder = this.examConfigurationService.getInputFieldBuilder( + attribute.getConfigAttribute(), + defaultOrientation); + final InputField createInputField = inputFieldBuilder.createInputField( content, attribute.getConfigAttribute(), @@ -188,12 +200,41 @@ public class ConfigTemplateAttributeForm implements TemplateComposer { .withParentEntityKey(templateKey) .withExec(this.examConfigurationService::resetToDefaults) .ignoreMoveAwayFromEdit() - .publish() + .publishIf(() -> modifyGrant) + + .newAction(ActionDefinition.SEB_EXAM_CONFIG_TEMPLATE_ATTR_REMOVE_VIEW) + .withEntityKey(attributeKey) + .withParentEntityKey(templateKey) + .withExec(this.examConfigurationService::removeFromView) + .ignoreMoveAwayFromEdit() + .publishIf(() -> modifyGrant && hasView) + + .newAction(ActionDefinition.SEB_EXAM_CONFIG_TEMPLATE_ATTR_ATTACH_DEFAULT_VIEW) + .withEntityKey(attributeKey) + .withParentEntityKey(templateKey) + .withExec(this.examConfigurationService::attachToDefaultView) + .ignoreMoveAwayFromEdit() + .publishIf(() -> modifyGrant && !hasView) .newAction(ActionDefinition.SEB_EXAM_CONFIG_TEMPLATE_ATTR_FORM_EDIT_TEMPLATE) .withEntityKey(templateKey) + .ignoreMoveAwayFromEdit() .publish(); } + private Orientation getDefaultOrientation(final TemplateAttribute attribute) { + return new Orientation( + -1L, + attribute.getConfigAttribute().id, + attribute.templateId, + null, + null, + 0, + 0, + 2, + 1, + TitleOrientation.NONE); + } + } diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/content/ConfigTemplateForm.java b/src/main/java/ch/ethz/seb/sebserver/gui/content/ConfigTemplateForm.java index 7bc4abc3..de1c200c 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/content/ConfigTemplateForm.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/content/ConfigTemplateForm.java @@ -70,6 +70,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_TYPE_TEXT_KEY = + new LocTextKey("sebserver.configtemplate.attrs.list.type"); private static final LocTextKey EMPTY_ATTRIBUTE_SELECTION_TEXT_KEY = new LocTextKey("sebserver.configtemplate.attr.info.pleaseSelect"); @@ -166,6 +168,7 @@ public class ConfigTemplateForm implements TemplateComposer { FORM_DESCRIPTION_TEXT_KEY, examConfig.description) .asArea()) + .buildFor((isNew) ? this.restService.getRestCall(NewExamConfig.class) : this.restService.getRestCall(SaveExamConfig.class)); @@ -184,6 +187,10 @@ public class ConfigTemplateForm implements TemplateComposer { CriteriaType.SINGLE_SELECTION, TemplateAttribute.FILTER_ATTR_VIEW, () -> this.resourceService.getViewResources(entityKey.modelId)); + final TableFilterAttribute typeFilter = new TableFilterAttribute( + CriteriaType.SINGLE_SELECTION, + TemplateAttribute.FILTER_ATTR_TYPE, + () -> this.resourceService.getAttributeTypeResources()); final EntityTable attrTable = this.pageService.entityTableBuilder(this.restService.getRestCall(GetTemplateAttributePage.class)) @@ -197,6 +204,12 @@ public class ConfigTemplateForm implements TemplateComposer { TemplateAttribute::getName) .withFilter(this.nameFilter) .sortable()) + .withColumn(new ColumnDefinition( + Domain.CONFIGURATION_ATTRIBUTE.ATTR_TYPE, + ATTRIBUTES_LIST_TYPE_TEXT_KEY, + resourceService::getAttributeTypeName) + .withFilter(typeFilter) + .sortable()) .withColumn(new ColumnDefinition<>( Domain.ORIENTATION.ATTR_VIEW_ID, ATTRIBUTES_LIST_VIEW_TEXT_KEY, @@ -234,7 +247,7 @@ public class ConfigTemplateForm implements TemplateComposer { .noEventPropagation() .publishIf(() -> attrTable.hasAnyContent()) - .newAction(ActionDefinition.SEB_EXAM_CONFIG_TEMPLATE_ATTR_REMOVE_VIEW) + .newAction(ActionDefinition.SEB_EXAM_CONFIG_TEMPLATE_ATTR_LIST_REMOVE_VIEW) .withParentEntityKey(entityKey) .withSelect( attrTable::getSelection, @@ -243,7 +256,14 @@ public class ConfigTemplateForm implements TemplateComposer { .noEventPropagation() .publishIf(() -> attrTable.hasAnyContent()) - ; + .newAction(ActionDefinition.SEB_EXAM_CONFIG_TEMPLATE_ATTR_LIST_ATTACH_DEFAULT_VIEW) + .withParentEntityKey(entityKey) + .withSelect( + attrTable::getSelection, + action -> this.attachView(action, attrTable), + EMPTY_ATTRIBUTE_SELECTION_TEXT_KEY) + .noEventPropagation() + .publishIf(() -> attrTable.hasAnyContent()); } pageActionBuilder @@ -288,4 +308,14 @@ public class ConfigTemplateForm implements TemplateComposer { return removeFormView; } + private final PageAction attachView( + final PageAction action, + final EntityTable attrTable) { + + final PageAction attachView = this.examConfigurationService.attachToDefaultView(action); + // reload the list + attrTable.applyFilter(); + return attachView; + } + } diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/content/action/ActionDefinition.java b/src/main/java/ch/ethz/seb/sebserver/gui/content/action/ActionDefinition.java index e85f3cf9..022e74e0 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/content/action/ActionDefinition.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/content/action/ActionDefinition.java @@ -461,22 +461,37 @@ public enum ActionDefinition { ImageIcon.SAVE, PageStateDefinitionImpl.SEB_EXAM_CONFIG_TEMPLATE_VIEW, ActionCategory.SEB_CONFIG_TEMPLATE_ATTRIBUTE_LIST), - SEB_EXAM_CONFIG_TEMPLATE_ATTR_REMOVE_VIEW( + SEB_EXAM_CONFIG_TEMPLATE_ATTR_LIST_REMOVE_VIEW( new LocTextKey("sebserver.configtemplate.attr.list.actions.removeview"), - ImageIcon.DELETE, + ImageIcon.REMOVE, PageStateDefinitionImpl.SEB_EXAM_CONFIG_TEMPLATE_VIEW, ActionCategory.SEB_CONFIG_TEMPLATE_ATTRIBUTE_LIST), + SEB_EXAM_CONFIG_TEMPLATE_ATTR_LIST_ATTACH_DEFAULT_VIEW( + new LocTextKey("sebserver.configtemplate.attr.list.actions.attach-default-view"), + ImageIcon.ADD, + PageStateDefinitionImpl.SEB_EXAM_CONFIG_TEMPLATE_VIEW, + ActionCategory.SEB_CONFIG_TEMPLATE_ATTRIBUTE_LIST), + SEB_EXAM_CONFIG_TEMPLATE_ATTR_REMOVE_VIEW( + new LocTextKey("sebserver.configtemplate.attr.list.actions.removeview"), + ImageIcon.REMOVE, + PageStateDefinitionImpl.SEB_EXAM_CONFIG_TEMPLATE_ATTRIBUTE_EDIT, + ActionCategory.FORM), + SEB_EXAM_CONFIG_TEMPLATE_ATTR_ATTACH_DEFAULT_VIEW( + new LocTextKey("sebserver.configtemplate.attr.list.actions.attach-default-view"), + ImageIcon.ADD, + PageStateDefinitionImpl.SEB_EXAM_CONFIG_TEMPLATE_ATTRIBUTE_EDIT, + ActionCategory.FORM), SEB_EXAM_CONFIG_TEMPLATE_ATTR_FORM_SET_DEFAULT( new LocTextKey("sebserver.configtemplate.attr.action.setdefault"), ImageIcon.UNDO, PageStateDefinitionImpl.SEB_EXAM_CONFIG_TEMPLATE_ATTRIBUTE_EDIT, - ActionCategory.SEB_CONFIG_TEMPLATE_ATTRIBUTE_LIST), + ActionCategory.FORM), SEB_EXAM_CONFIG_TEMPLATE_ATTR_FORM_EDIT_TEMPLATE( new LocTextKey("sebserver.configtemplate.attr.action.template"), ImageIcon.SHOW, PageStateDefinitionImpl.SEB_EXAM_CONFIG_TEMPLATE_VIEW, - ActionCategory.SEB_CONFIG_TEMPLATE_ATTRIBUTE_LIST), + ActionCategory.FORM), RUNNING_EXAM_VIEW_LIST( new LocTextKey("sebserver.monitoring.action.list"), diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/ResourceService.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/ResourceService.java index ae811bc3..b39a5c43 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/service/ResourceService.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/ResourceService.java @@ -38,6 +38,7 @@ import ch.ethz.seb.sebserver.gbl.model.exam.Exam.ExamType; import ch.ethz.seb.sebserver.gbl.model.exam.ExamConfigurationMap; import ch.ethz.seb.sebserver.gbl.model.exam.Indicator.IndicatorType; import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetup.LmsType; +import ch.ethz.seb.sebserver.gbl.model.sebconfig.AttributeType; 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; @@ -95,6 +96,12 @@ public class ResourceService { public static final String EXAM_INDICATOR_TYPE_PREFIX = "sebserver.exam.indicator.type."; public static final String LMSSETUP_TYPE_PREFIX = "sebserver.lmssetup.type."; public static final String LMSSETUP_PROXY_AUTH_TYPE_PREFIX = "sebserver.lmssetup.form.proxy.auth-type."; + public static final String CONFIG_ATTRIBUTE_TYPE_PREFIX = "sebserver.configtemplate.attr.type."; + + public static final EnumSet ATTRIBUTE_TYPES_NOT_DISPLAYED = EnumSet.of( + AttributeType.LABEL, + AttributeType.COMPOSITE_TABLE, + AttributeType.INLINE_TABLE); public static final String CLIENT_EVENT_TYPE_PREFIX = "sebserver.monitoring.exam.connection.event.type."; public static final String USER_ACTIVITY_TYPE_PREFIX = "sebserver.overall.types.activityType."; @@ -494,6 +501,43 @@ public class ResourceService { return attr -> mapping.get(attr.getViewModelId()); } + public List> getAttributeTypeResources() { + return Arrays.asList(AttributeType.values()) + .stream() + .filter(type -> !ATTRIBUTE_TYPES_NOT_DISPLAYED.contains(type)) + .map(type -> new Tuple<>(getAttributeTypeFilterName(type), getAttributeTypeName(type))) + .sorted(RESOURCE_COMPARATOR) + .collect(Collectors.toList()); + } + + public String getAttributeTypeName(final TemplateAttribute attribute) { + if (attribute != null && attribute.getConfigAttribute() != null) { + return getAttributeTypeName(attribute.getConfigAttribute().type); + } + + return Constants.EMPTY_NOTE; + } + + private String getAttributeTypeFilterName(final AttributeType type) { + if (type == AttributeType.TABLE) { + return type.name() + + Constants.LIST_SEPARATOR + + AttributeType.COMPOSITE_TABLE.name() + + Constants.LIST_SEPARATOR + + AttributeType.INLINE_TABLE.name(); + } else { + return type.name(); + } + } + + public String getAttributeTypeName(final AttributeType type) { + if (type == null) { + return Constants.EMPTY_NOTE; + } + return this.i18nSupport + .getText(CONFIG_ATTRIBUTE_TYPE_PREFIX + type.name()); + } + public Map getExamNameMapping() { final UserInfo userInfo = this.currentUser.get(); return this.restService.getBuilder(GetExamNames.class) diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/ExamConfigurationService.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/ExamConfigurationService.java index 60422aec..a617e432 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/ExamConfigurationService.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/ExamConfigurationService.java @@ -17,6 +17,7 @@ import org.eclipse.swt.widgets.Composite; import ch.ethz.seb.sebserver.gbl.model.sebconfig.Configuration; import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationAttribute; import ch.ethz.seb.sebserver.gbl.model.sebconfig.Orientation; +import ch.ethz.seb.sebserver.gbl.model.sebconfig.TemplateAttribute; import ch.ethz.seb.sebserver.gbl.model.sebconfig.View; import ch.ethz.seb.sebserver.gbl.util.Result; import ch.ethz.seb.sebserver.gui.service.examconfig.impl.AttributeMapping; @@ -42,6 +43,10 @@ public interface ExamConfigurationService { Result getAttributes(Long templateId); + Result getAttributes( + final TemplateAttribute attribute, + final Orientation defaultOrientation); + List getViews(AttributeMapping allAttributes); ViewContext createViewContext( diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/impl/ExamConfigurationServiceImpl.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/impl/ExamConfigurationServiceImpl.java index 2d2cc35c..cc5ba825 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/impl/ExamConfigurationServiceImpl.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/impl/ExamConfigurationServiceImpl.java @@ -108,20 +108,46 @@ public class ExamConfigurationServiceImpl implements ExamConfigurationService { return Result.tryCatch(() -> { return new AttributeMapping( templateId, - this.restService - .getBuilder(GetConfigAttributes.class) - .call() - .onError(t -> log.error("Failed to get all ConfigurationAttribute")) - .getOrThrow(), - this.restService - .getBuilder(GetOrientations.class) - .withQueryParam(Orientation.FILTER_ATTR_TEMPLATE_ID, String.valueOf(templateId)) - .call() - .onError(t -> log.error("Failed to get all Orientation of template {}", templateId, t)) - .getOrThrow()); + getAttributes(), + getOrientations(templateId)); }); } + @Override + public Result getAttributes( + final TemplateAttribute attribute, + final Orientation defaultOrientation) { + + final List orientations = getOrientations(attribute.templateId); + if (attribute.getOrientation() == null) { + orientations.add(defaultOrientation); + } + + return Result.tryCatch(() -> { + return new AttributeMapping( + attribute.templateId, + getAttributes(), + orientations); + }); + } + + private List getOrientations(final Long templateId) { + return this.restService + .getBuilder(GetOrientations.class) + .withQueryParam(Orientation.FILTER_ATTR_TEMPLATE_ID, String.valueOf(templateId)) + .call() + .onError(t -> log.error("Failed to get all Orientation of template {}", templateId, t)) + .getOrThrow(); + } + + private List getAttributes() { + return this.restService + .getBuilder(GetConfigAttributes.class) + .call() + .onError(t -> log.error("Failed to get all ConfigurationAttribute")) + .getOrThrow(); + } + @Override public List getViews(final AttributeMapping allAttributes) { final Collection viewIds = allAttributes.getViewIds(); diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/ConfigurationValueDAO.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/ConfigurationValueDAO.java index 5fa8e89a..3d69d416 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/ConfigurationValueDAO.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/ConfigurationValueDAO.java @@ -19,15 +19,6 @@ import ch.ethz.seb.sebserver.gbl.util.Result; public interface ConfigurationValueDAO extends EntityDAO { - /** NOTE: Deletion is not supported for ConfigurationValue. - * A ConfigurationValue get automatically deleted on deletion of a Configuration */ - @Override - default Result> delete(final Set all) { - throw new UnsupportedOperationException( - "Deletion is not supported for ConfigurationValue. A ConfigurationValue get " - + "automatically deleted on deletion of a Configuration"); - } - /** Use this to get all ConfigurationValue for a specific configuration and for a all * root attributes that are not child attributes. * diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ConfigurationValueDAOImpl.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ConfigurationValueDAOImpl.java index 1bf6934d..0ba5a028 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ConfigurationValueDAOImpl.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ConfigurationValueDAOImpl.java @@ -229,6 +229,20 @@ public class ConfigurationValueDAOImpl implements ConfigurationValueDAO { .onError(TransactionHandler::rollback); } + @Override + @Transactional + public Result> delete(final Set all) { + return Result.tryCatch(() -> { + return extractPKsFromKeys(all) + .stream() + .map(pk -> { + this.configurationValueRecordMapper.deleteByPrimaryKey(pk); + return new EntityKey(pk, EntityType.CONFIGURATION_VALUE); + }) + .collect(Collectors.toList()); + }); + } + @Override @Transactional(readOnly = true) public Result getTableValues( @@ -355,26 +369,30 @@ public class ConfigurationValueDAOImpl implements ConfigurationValueDAO { .flatMap(this::getAttributeMapping) .map(attributeMapping -> { - final Set tableValues = this.configurationValueRecordMapper.selectByExample() - .where( - ConfigurationValueRecordDynamicSqlSupport.institutionId, - isEqualTo(institutionId)) - .and( - ConfigurationValueRecordDynamicSqlSupport.configurationId, - isEqualTo(configurationId)) - .and( - ConfigurationValueRecordDynamicSqlSupport.configurationAttributeId, - SqlBuilder.isIn(new ArrayList<>(attributeMapping.keySet()))) - .build() - .execute() - .stream() - .map(r -> new EntityKey(r.getId(), EntityType.CONFIGURATION_VALUE)) - .collect(Collectors.toSet()); + final Set tableValues = new HashSet<>(); + if (attributeMapping != null && !attributeMapping.isEmpty()) { - // if there are table values, delete them first - if (tableValues != null && !tableValues.isEmpty()) { - this.delete(tableValues) - .getOrThrow(); + tableValues.addAll(this.configurationValueRecordMapper.selectByExample() + .where( + ConfigurationValueRecordDynamicSqlSupport.institutionId, + isEqualTo(institutionId)) + .and( + ConfigurationValueRecordDynamicSqlSupport.configurationId, + isEqualTo(configurationId)) + .and( + ConfigurationValueRecordDynamicSqlSupport.configurationAttributeId, + SqlBuilder.isIn(new ArrayList<>(attributeMapping.keySet()))) + .build() + .execute() + .stream() + .map(r -> new EntityKey(r.getId(), EntityType.CONFIGURATION_VALUE)) + .collect(Collectors.toSet())); + + // if there are table values, delete them first + if (tableValues != null && !tableValues.isEmpty()) { + this.delete(tableValues) + .getOrThrow(); + } } // get the attribute value reset to defaultValue and save @@ -404,9 +422,14 @@ public class ConfigurationValueDAOImpl implements ConfigurationValueDAO { final ConfigurationValueRecord oldRec = values.get(0); final ConfigurationValueRecord newRec = new ConfigurationValueRecord( - oldRec.getId(), null, null, null, null, defaultValue); + oldRec.getId(), + oldRec.getInstitutionId(), + oldRec.getConfigurationId(), + oldRec.getConfigurationAttributeId(), + oldRec.getListIndex(), + defaultValue); - this.configurationValueRecordMapper.updateByPrimaryKeySelective(newRec); + this.configurationValueRecordMapper.updateByPrimaryKey(newRec); final HashSet result = new HashSet<>(); result.add(new EntityKey(newRec.getId(), EntityType.CONFIGURATION_VALUE)); diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/impl/SebExamConfigTemplateServiceImpl.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/impl/SebExamConfigTemplateServiceImpl.java index 5c66e0c8..771ceb9c 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/impl/SebExamConfigTemplateServiceImpl.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/impl/SebExamConfigTemplateServiceImpl.java @@ -10,6 +10,8 @@ package ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.impl; import java.util.Arrays; import java.util.Collections; +import java.util.Comparator; +import java.util.EnumSet; import java.util.HashSet; import java.util.List; import java.util.Map; @@ -22,12 +24,15 @@ import org.slf4j.LoggerFactory; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; +import ch.ethz.seb.sebserver.gbl.Constants; 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; import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationAttribute; 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.TemplateAttribute; +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.webservice.servicelayer.dao.ConfigurationAttributeDAO; @@ -88,14 +93,30 @@ public class SebExamConfigTemplateServiceImpl implements SebExamConfigTemplateSe .map(attr -> new TemplateAttribute(institutionId, templateId, 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))) + && attr.isInView(filterMap.getLong(TemplateAttribute.FILTER_ATTR_VIEW)) + && attr.hasType(extractTypes(filterMap))) .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)); + if (sortBy.equals(Domain.CONFIGURATION_ATTRIBUTE.ATTR_NAME)) { + Collections.sort( + attrs, + TemplateAttribute.nameComparator(sortOrder == PageSortOrder.DESCENDING)); + } else if (sortBy.equals(Domain.CONFIGURATION_ATTRIBUTE.ATTR_TYPE)) { + Collections.sort( + attrs, + TemplateAttribute.typeComparator(sortOrder == PageSortOrder.DESCENDING)); + } else if (sortBy.equals(Domain.ORIENTATION.ATTR_VIEW_ID)) { + Collections.sort(attrs, this.getViewComparator( + institutionId, + templateId, + sortOrder == PageSortOrder.DESCENDING)); + } else if (sortBy.equals(Domain.ORIENTATION.ATTR_GROUP_ID)) { + Collections.sort( + attrs, + TemplateAttribute.groupComparator(sortOrder == PageSortOrder.DESCENDING)); } } return attrs; @@ -203,7 +224,7 @@ public class SebExamConfigTemplateServiceImpl implements SebExamConfigTemplateSe devOrientation.height, devOrientation.title); - this.orientationDAO.save(newOrientation) + this.orientationDAO.createNew(newOrientation) .getOrThrow(); final TemplateAttribute attribute = getAttribute(institutionId, templateId, attributeId) @@ -234,4 +255,60 @@ public class SebExamConfigTemplateServiceImpl implements SebExamConfigTemplateSe .orElse(null); } + private Comparator getViewComparator( + final Long institutionId, + final Long templateId, + final boolean descending) { + + final Map viewMap = this.viewDAO.allMatching(new FilterMap.Builder() + .add(View.FILTER_ATTR_INSTITUTION, String.valueOf(institutionId)) + .add(View.FILTER_ATTR_TEMPLATE, String.valueOf(templateId)) + .create()) + .getOrThrow() + .stream() + .collect(Collectors.toMap(v -> v.id, Function.identity())); + + return (attr1, attr2) -> { + + return getViewName(attr1, viewMap) + .compareToIgnoreCase(getViewName(attr2, viewMap)) + * ((descending) ? -1 : 1); + + }; + } + + private EnumSet extractTypes(final FilterMap filterMap) { + final EnumSet result = EnumSet.noneOf(AttributeType.class); + final String types = filterMap.getString(TemplateAttribute.FILTER_ATTR_TYPE); + if (StringUtils.isBlank(types)) { + return result; + } + + final String[] split = StringUtils.split(types, Constants.LIST_SEPARATOR); + if (split != null) { + for (int i = 0; i < split.length; i++) { + result.add(AttributeType.valueOf(split[i])); + } + } + + return result; + } + + private static final String getViewName( + final TemplateAttribute attribute, + final Map viewMap) { + + final Orientation orientation = attribute.getOrientation(); + if (orientation == null || orientation.viewId == null) { + return Constants.EMPTY_NOTE; + } + + final View view = viewMap.get(orientation.viewId); + if (view != null) { + return view.name; + } + + return Constants.EMPTY_NOTE; + } + } diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ConfigurationNodeController.java b/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ConfigurationNodeController.java index eaec0516..7ac42f57 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ConfigurationNodeController.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ConfigurationNodeController.java @@ -342,7 +342,7 @@ public class ConfigurationNodeController extends EntityController