SEBSERV-72 back- and front-end implementation

This commit is contained in:
anhefti 2019-10-21 12:11:01 +02:00
parent 4e40ee7f0e
commit 555d9a34e0
12 changed files with 365 additions and 63 deletions

View file

@ -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<AttributeType> 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<TemplateAttribute> typeComparator(final boolean descending) {
return (attr1, attr2) -> attr1.configAttribute.type.name().compareToIgnoreCase(
attr2.configAttribute.type.name()) * ((descending) ? -1 : 1);
}
public static final Comparator<TemplateAttribute> 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);
};
}
}

View file

@ -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<TemplateAttribute> 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);
}
}

View file

@ -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<TemplateAttribute> 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<TemplateAttribute>(
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<TemplateAttribute> attrTable) {
final PageAction attachView = this.examConfigurationService.attachToDefaultView(action);
// reload the list
attrTable.applyFilter();
return attachView;
}
}

View file

@ -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"),

View file

@ -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<AttributeType> 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<Tuple<String>> 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<Long, String> getExamNameMapping() {
final UserInfo userInfo = this.currentUser.get();
return this.restService.getBuilder(GetExamNames.class)

View file

@ -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<AttributeMapping> getAttributes(Long templateId);
Result<AttributeMapping> getAttributes(
final TemplateAttribute attribute,
final Orientation defaultOrientation);
List<View> getViews(AttributeMapping allAttributes);
ViewContext createViewContext(

View file

@ -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<AttributeMapping> getAttributes(
final TemplateAttribute attribute,
final Orientation defaultOrientation) {
final List<Orientation> orientations = getOrientations(attribute.templateId);
if (attribute.getOrientation() == null) {
orientations.add(defaultOrientation);
}
return Result.tryCatch(() -> {
return new AttributeMapping(
attribute.templateId,
getAttributes(),
orientations);
});
}
private List<Orientation> 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<ConfigurationAttribute> getAttributes() {
return this.restService
.getBuilder(GetConfigAttributes.class)
.call()
.onError(t -> log.error("Failed to get all ConfigurationAttribute"))
.getOrThrow();
}
@Override
public List<View> getViews(final AttributeMapping allAttributes) {
final Collection<Long> viewIds = allAttributes.getViewIds();

View file

@ -19,15 +19,6 @@ import ch.ethz.seb.sebserver.gbl.util.Result;
public interface ConfigurationValueDAO extends EntityDAO<ConfigurationValue, ConfigurationValue> {
/** NOTE: Deletion is not supported for ConfigurationValue.
* A ConfigurationValue get automatically deleted on deletion of a Configuration */
@Override
default Result<Collection<EntityKey>> delete(final Set<EntityKey> 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.
*

View file

@ -229,6 +229,20 @@ public class ConfigurationValueDAOImpl implements ConfigurationValueDAO {
.onError(TransactionHandler::rollback);
}
@Override
@Transactional
public Result<Collection<EntityKey>> delete(final Set<EntityKey> 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<ConfigurationTableValues> getTableValues(
@ -355,26 +369,30 @@ public class ConfigurationValueDAOImpl implements ConfigurationValueDAO {
.flatMap(this::getAttributeMapping)
.map(attributeMapping -> {
final Set<EntityKey> 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<EntityKey> 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<EntityKey> result = new HashSet<>();
result.add(new EntityKey(newRec.getId(), EntityType.CONFIGURATION_VALUE));

View file

@ -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<TemplateAttribute> getViewComparator(
final Long institutionId,
final Long templateId,
final boolean descending) {
final Map<Long, View> 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<AttributeType> extractTypes(final FilterMap filterMap) {
final EnumSet<AttributeType> 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<Long, View> 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;
}
}

View file

@ -342,7 +342,7 @@ public class ConfigurationNodeController extends EntityController<ConfigurationN
name = API.PARAM_INSTITUTION_ID,
required = true,
defaultValue = UserService.USERS_INSTITUTION_AS_DEFAULT) final Long institutionId,
@RequestParam(name = API.PARAM_VIEW_ID) final Long viewId) {
@RequestParam(name = API.PARAM_VIEW_ID, required = false) final Long viewId) {
checkModifyPrivilege(institutionId);

View file

@ -947,15 +947,34 @@ sebserver.configtemplate.form.name=Name
sebserver.configtemplate.form.description=Description
sebserver.configtemplate.action.save=Save Template
sebserver.configtemplate.attr.type.TEXT_FIELD=Text Field
sebserver.configtemplate.attr.type.PASSWORD_FIELD=Password Field
sebserver.configtemplate.attr.type.TEXT_AREA=Text Area
sebserver.configtemplate.attr.type.CHECKBOX=Checkbox
sebserver.configtemplate.attr.type.SLIDER=Slider
sebserver.configtemplate.attr.type.INTEGER=Number (Integer)
sebserver.configtemplate.attr.type.DECIMAL=Number (Decimal)
sebserver.configtemplate.attr.type.SINGLE_SELECTION=Single Selection
sebserver.configtemplate.attr.type.COMBO_SELECTION=Combo Selection
sebserver.configtemplate.attr.type.RADIO_SELECTION=Radio Selection
sebserver.configtemplate.attr.type.MULTI_SELECTION=Multi Selection
sebserver.configtemplate.attr.type.MULTI_CHECKBOX_SELECTION=Multi Selection (Checkbox)
sebserver.configtemplate.attr.type.FILE_UPLOAD=File Upload
sebserver.configtemplate.attr.type.TABLE=Table
sebserver.configtemplate.attr.type.INLINE_TABLE=Table
sebserver.configtemplate.attr.type.COMPOSITE_TABLE=Table
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.attrs.list.type=Type
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 From View
sebserver.configtemplate.attr.list.actions.attach-default-view=Attach To View
sebserver.configtemplate.attr.info.pleaseSelect=Please select an attribute first
sebserver.configtemplate.attr.form.title=Template Attribute