diff --git a/src/main/java/ch/ethz/seb/sebserver/gbl/model/sebconfig/AttributeType.java b/src/main/java/ch/ethz/seb/sebserver/gbl/model/sebconfig/AttributeType.java index 03b7e8b1..eb58b0d3 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gbl/model/sebconfig/AttributeType.java +++ b/src/main/java/ch/ethz/seb/sebserver/gbl/model/sebconfig/AttributeType.java @@ -48,7 +48,7 @@ public enum AttributeType { INLINE_TABLE(COMPOSITE_LIST), - ; + COMPOSITE_TABLE(COMPOSITE); public final AttributeValueType attributeValueType; diff --git a/src/main/java/ch/ethz/seb/sebserver/gbl/model/sebconfig/AttributeValueType.java b/src/main/java/ch/ethz/seb/sebserver/gbl/model/sebconfig/AttributeValueType.java index cb54decf..7ee9c381 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gbl/model/sebconfig/AttributeValueType.java +++ b/src/main/java/ch/ethz/seb/sebserver/gbl/model/sebconfig/AttributeValueType.java @@ -20,8 +20,8 @@ public enum AttributeValueType { BASE64_BINARY, /** A list of single values of the same type */ LIST, - /** A composite of different typed values like a Map or Dictionary */ + /** A composite of different typed values like a map or dictionary */ COMPOSITE, - /** A list of composites of the same type like a Table */ + /** A list of composites (list of dictionary) of the same type like a Table */ COMPOSITE_LIST } diff --git a/src/main/java/ch/ethz/seb/sebserver/gbl/model/sebconfig/ConfigurationAttribute.java b/src/main/java/ch/ethz/seb/sebserver/gbl/model/sebconfig/ConfigurationAttribute.java index 0f65a065..2bd1c48e 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gbl/model/sebconfig/ConfigurationAttribute.java +++ b/src/main/java/ch/ethz/seb/sebserver/gbl/model/sebconfig/ConfigurationAttribute.java @@ -8,13 +8,23 @@ package ch.ethz.seb.sebserver.gbl.model.sebconfig; +import java.util.Arrays; +import java.util.Collections; +import java.util.Map; +import java.util.stream.Collectors; + import javax.validation.constraints.NotNull; import javax.validation.constraints.Size; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 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.api.POSTMapper; import ch.ethz.seb.sebserver.gbl.model.Domain; @@ -24,8 +34,25 @@ import ch.ethz.seb.sebserver.gbl.model.Entity; @JsonIgnoreProperties(ignoreUnknown = true) public final class ConfigurationAttribute implements Entity { + private static final Logger log = LoggerFactory.getLogger(ConfigurationAttribute.class); + + /** This configuration attribute dependency key can be used to set a specific localized text key prefix for + * resources. This is usually convenient if two different attributes use the same resources and to avoid + * to multiply the resources for each attribute with the attribute name prefix, we can set a specific + * resourceLocTextKey prefix to use. */ public static final String DEPENDENCY_RESOURCE_LOC_TEXT_KEY = "resourceLocTextKey"; + /** This configuration attribute dependency key indicates the group identifier for grouped COMOSITE_TYPE types */ + public static final String DEPENDENCY_GROUP_ID = "groupId"; + + /** This configuration attribute dependency key indicates if a default value should be created even if the + * attribute is a child attribute and normally no default value is generated on creation. */ + public static final String DEPENDENCY_CREATE_DEFAULT_VALUE = "createDefaultValue"; + + /** his configuration attribute dependency key indicates if the input field should be shown in the directly + * in the View even if the attribute is a child attribute and is usually shown in a table or composite. */ + public static final String DEPENDENCY_SHOW_IN_VIEW = "showInView"; + public static final String FILTER_ATTR_PARENT_ID = "parentId"; public static final String FILTER_ATTR_TYPE = "type"; @@ -156,4 +183,55 @@ public final class ConfigurationAttribute implements Entity { return builder.toString(); } + public static boolean hasDependency( + final String dependencyName, + final ConfigurationAttribute attribute) { + + if (StringUtils.isBlank(attribute.dependencies)) { + return false; + } + + return attribute.dependencies.contains(dependencyName); + } + + public static String getDependencyValue( + final String dependencyName, + final ConfigurationAttribute attribute) { + + return getDependencyValue(dependencyName, attribute.dependencies); + } + + public static String getDependencyValue( + final String dependencyName, + final String dependnciesString) { + + if (StringUtils.isBlank(dependnciesString)) { + return null; + } + + return getAttributeDependencyMap(dependnciesString).get(dependencyName); + } + + public static Map getAttributeDependencyMap(final ConfigurationAttribute attribute) { + if (StringUtils.isBlank(attribute.dependencies)) { + return Collections.emptyMap(); + } + + return getAttributeDependencyMap(attribute.dependencies); + } + + public static Map getAttributeDependencyMap(final String dependnciesString) { + try { + return Arrays.asList(StringUtils.split(dependnciesString, Constants.LIST_SEPARATOR)) + .stream() + .map(s -> StringUtils.split(s, Constants.FORM_URL_ENCODED_NAME_VALUE_SEPARATOR)) + .collect(Collectors.toMap(pair -> pair[0], pair -> pair[1])); + } catch (final Exception e) { + log.error("Unexpected error while trying to parse dependency map of: {}", + dependnciesString, + e); + return Collections.emptyMap(); + } + } + } diff --git a/src/main/java/ch/ethz/seb/sebserver/gbl/model/sebconfig/ConfigurationNode.java b/src/main/java/ch/ethz/seb/sebserver/gbl/model/sebconfig/ConfigurationNode.java index ca7f65a8..f2640c23 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gbl/model/sebconfig/ConfigurationNode.java +++ b/src/main/java/ch/ethz/seb/sebserver/gbl/model/sebconfig/ConfigurationNode.java @@ -57,6 +57,7 @@ public final class ConfigurationNode implements GrantEntity { @JsonProperty(CONFIGURATION_NODE.ATTR_NAME) public final String name; + @Size(max = 4000, message = "configurationNode:description:size:{min}:{max}:${validatedValue}") @JsonProperty(CONFIGURATION_NODE.ATTR_DESCRIPTION) public final String description; diff --git a/src/main/java/ch/ethz/seb/sebserver/gbl/util/Utils.java b/src/main/java/ch/ethz/seb/sebserver/gbl/util/Utils.java index 4e3f0ae2..efe9b465 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gbl/util/Utils.java +++ b/src/main/java/ch/ethz/seb/sebserver/gbl/util/Utils.java @@ -34,7 +34,6 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import ch.ethz.seb.sebserver.gbl.Constants; -import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationAttribute; public final class Utils { @@ -294,22 +293,4 @@ public final class Utils { return toCharArray(CharBuffer.wrap(chars)); } - public static Map getAttributeDependencyMap(final ConfigurationAttribute attribute) { - if (StringUtils.isBlank(attribute.dependencies)) { - return Collections.emptyMap(); - } - - try { - return Arrays.asList(StringUtils.split(attribute.dependencies, Constants.LIST_SEPARATOR)) - .stream() - .map(s -> StringUtils.split(s, Constants.EMBEDDED_LIST_SEPARATOR)) - .collect(Collectors.toMap(pair -> pair[0], pair -> pair[1])); - } catch (final Exception e) { - log.error("Unexpected error while trying to parse dependency map of ConfigurationAttribute: {}", - attribute, - e); - return Collections.emptyMap(); - } - } - } diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/form/SelectionFieldBuilder.java b/src/main/java/ch/ethz/seb/sebserver/gui/form/SelectionFieldBuilder.java index e0b8366f..fc12e403 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/form/SelectionFieldBuilder.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/form/SelectionFieldBuilder.java @@ -65,11 +65,14 @@ public final class SelectionFieldBuilder extends FieldBuilder { } private void buildInput(final FormBuilder builder, final Label lab) { - + final String actionKey = (this.label != null) ? this.label.name + ".action" : null; final Selection selection = builder.widgetFactory.selectionLocalized( this.type, builder.formParent, - this.itemsSupplier); + this.itemsSupplier, + null, + null, + actionKey); final GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, false, this.spanInput, 1); ((Control) selection).setLayoutData(gridData); diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/form/TextFieldBuilder.java b/src/main/java/ch/ethz/seb/sebserver/gui/form/TextFieldBuilder.java index 2bb20f6b..2157d1fb 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/form/TextFieldBuilder.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/form/TextFieldBuilder.java @@ -59,6 +59,9 @@ public final class TextFieldBuilder extends FieldBuilder { : builder.widgetFactory.textInput(builder.formParent, this.isPassword); final GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, false, this.spanInput, 1); + if (this.isArea) { + gridData.heightHint = 50; + } textInput.setLayoutData(gridData); if (this.value != null) { textInput.setText(this.value); diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/InputFieldBuilder.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/InputFieldBuilder.java index 4cf60790..6d18986a 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/InputFieldBuilder.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/InputFieldBuilder.java @@ -8,6 +8,7 @@ package ch.ethz.seb.sebserver.gui.service.examconfig; +import org.apache.commons.lang3.BooleanUtils; import org.eclipse.rap.rwt.RWT; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.GridData; @@ -71,12 +72,18 @@ public interface InputFieldBuilder { final GridData gridData = new GridData( SWT.FILL, SWT.FILL, true, false, - (orientation != null && attribute.parentId == null) ? orientation.width() : 1, - (orientation != null && attribute.parentId == null) ? orientation.height() : 1); + (orientation != null && isOnView(attribute)) ? orientation.width() : 1, + (orientation != null && isOnView(attribute)) ? orientation.height() : 1); comp.setLayoutData(gridData); return comp; } + private static boolean isOnView(final ConfigurationAttribute attribute) { + return attribute.parentId == null || BooleanUtils.toBoolean(ConfigurationAttribute.getDependencyValue( + ConfigurationAttribute.DEPENDENCY_SHOW_IN_VIEW, + attribute)); + } + static Label createErrorLabel(final Composite innerGrid) { final Label errorLabel = new Label(innerGrid, SWT.NONE); errorLabel.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/ValueChangeRule.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/ValueChangeRule.java index d2a6750c..8506a787 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/ValueChangeRule.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/ValueChangeRule.java @@ -18,7 +18,7 @@ public interface ValueChangeRule { void applyRule( ViewContext context, - ConfigurationAttribute attribut, + ConfigurationAttribute attribute, ConfigurationValue value); } diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/impl/AbstractTableFieldBuilder.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/impl/AbstractTableFieldBuilder.java new file mode 100644 index 00000000..29eeaefc --- /dev/null +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/impl/AbstractTableFieldBuilder.java @@ -0,0 +1,335 @@ +/* + * 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.examconfig.impl; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import org.apache.commons.lang3.BooleanUtils; +import org.apache.commons.lang3.StringUtils; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Table; +import org.eclipse.swt.widgets.TableColumn; +import org.eclipse.swt.widgets.TableItem; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import ch.ethz.seb.sebserver.gbl.Constants; +import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationAttribute; +import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationTableValues; +import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationTableValues.TableValue; +import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationValue; +import ch.ethz.seb.sebserver.gbl.model.sebconfig.Orientation; +import ch.ethz.seb.sebserver.gui.service.examconfig.ExamConfigurationService; +import ch.ethz.seb.sebserver.gui.service.examconfig.InputFieldBuilder; +import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestService; +import ch.ethz.seb.sebserver.gui.widget.WidgetFactory; +import ch.ethz.seb.sebserver.gui.widget.WidgetFactory.ImageIcon; + +public abstract class AbstractTableFieldBuilder implements InputFieldBuilder { + + private static final Logger log = LoggerFactory.getLogger(AbstractTableFieldBuilder.class); + + protected final RestService restService; + protected final WidgetFactory widgetFactory; + protected InputFieldBuilderSupplier inputFieldBuilderSupplier; + + protected AbstractTableFieldBuilder( + final RestService restService, + final WidgetFactory widgetFactory) { + + this.restService = restService; + this.widgetFactory = widgetFactory; + } + + @Override + public void init(final InputFieldBuilderSupplier inputFieldBuilderSupplier) { + this.inputFieldBuilderSupplier = inputFieldBuilderSupplier; + } + + protected Table createTable(final Composite parent, final TableContext tableContext) { + final Table table = new Table(parent, SWT.NONE | SWT.V_SCROLL); + table.setLayout(new GridLayout()); + final GridData gridData = new GridData( + SWT.FILL, SWT.FILL, + true, false, + (tableContext.orientation != null) ? tableContext.orientation.width() : 1, + (tableContext.orientation != null) ? tableContext.orientation.height() : 1); + gridData.heightHint = tableContext.orientation.height * 20 + 40; + table.setLayoutData(gridData); + table.setHeaderVisible(true); + table.addListener(SWT.Resize, event -> adaptColumnWidth(table, tableContext)); + return table; + } + + protected TableContext createTableContext(final ConfigurationAttribute attribute, final ViewContext viewContext) { + final TableContext tableContext = new TableContext( + this.inputFieldBuilderSupplier, + this.widgetFactory, + this.restService, + attribute, + viewContext); + return tableContext; + } + + protected void setSelectionListener(final Table table, final AbstractTableInputField tableField) { + table.addListener(SWT.MouseDoubleClick, event -> { + final int selectionIndex = table.getSelectionIndex(); + if (selectionIndex >= 0) { + tableField.openForm(selectionIndex); + } + }); + } + + protected void adaptColumnWidth( + final Table table, + final TableContext tableContext) { + + try { + final int currentTableWidth = table.getClientArea().width - 50; + final TableColumn[] columns = table.getColumns(); + final List orientations = tableContext + .getColumnAttributes() + .stream() + .map(attr -> tableContext.getOrientation(attr.id)) + .collect(Collectors.toList()); + final Integer div = orientations + .stream() + .map(o -> o.width) + .reduce(0, (acc, val) -> acc + val); + final int widthUnit = currentTableWidth / div; + for (int i = 0; i < columns.length - 2; i++) { + columns[i].setWidth(widthUnit * orientations.get(i).width); + } + } catch (final Exception e) { + log.warn("Failed to adaptColumnWidth: ", e); + } + } + + protected static void setValueToCell( + final TableContext tableContext, + final TableItem item, + final int cellIndex, + final ConfigurationAttribute attribute, + final TableValue tableValue) { + + switch (attribute.type) { + case CHECKBOX: { + item.setImage( + cellIndex, + (BooleanUtils.toBoolean((tableValue != null) ? tableValue.value : null)) + ? ImageIcon.YES.getImage(item.getDisplay()) + : ImageIcon.NO.getImage(item.getDisplay())); + break; + } + case SINGLE_SELECTION: { + final String key = ExamConfigurationService.ATTRIBUTE_LABEL_LOC_TEXT_PREFIX + + attribute.getName() + "." + + tableValue.value; + item.setText( + cellIndex, + tableContext.i18nSupport().getText(key, getValue(attribute, tableValue))); + break; + } + default: { + item.setText(cellIndex, getValue(attribute, tableValue)); + } + } + } + + private static String getValue( + final ConfigurationAttribute attribute, + final TableValue tableValue) { + + if (tableValue == null) { + if (StringUtils.isBlank(attribute.defaultValue)) { + return Constants.EMPTY_NOTE; + } else { + return attribute.defaultValue; + } + } else { + if (StringUtils.isBlank(tableValue.value)) { + return Constants.EMPTY_NOTE; + } else { + return tableValue.value; + } + } + } + + static abstract class AbstractTableInputField extends AbstractInputField { + + protected final TableContext tableContext; + + protected AbstractTableInputField( + final ConfigurationAttribute attribute, + final Orientation orientation, + final Table control, + final Label errorLabel, + final TableContext tableContext) { + + super(attribute, orientation, control, errorLabel); + this.tableContext = tableContext; + } + + @Override + public ConfigurationValue initValue(final Collection values) { + clearTable(); + // get all child values as TableValues + final List tableValues = getChildValues( + this.tableContext, + this.attribute, + values); + + initValue(tableValues); + return null; + } + + abstract void initValue(final List tableValues); + + abstract void openForm(final int selectionIndex); + + abstract void applyTableRowValues(final int index); + + protected List getChildValues( + final TableContext tableContext, + final ConfigurationAttribute attribute, + final Collection values) { + + return values.stream() + .filter(v -> isChildValue(tableContext, attribute, v)) + .map(TableValue::of) + .collect(Collectors.toList()); + } + + protected boolean isChildValue( + final TableContext tableContext, + final ConfigurationAttribute attribute, + final ConfigurationValue value) { + + if (!tableContext.getViewContext().attributeMapping.attributeIdMapping + .containsKey(value.attributeId)) { + + return false; + } + + ConfigurationAttribute attr = tableContext.getAttribute(value.attributeId); + while (attr.parentId != null) { + if (attribute.id.equals(attr.parentId)) { + return true; + } + attr = tableContext.getAttribute(attr.parentId); + } + + return false; + } + + protected Map> createRowIndexMap(final List tableValues) { + final Map> indexMapping = new HashMap<>(); + for (final TableValue tableValue : tableValues) { + final Map rowValues = indexMapping.computeIfAbsent( + tableValue.listIndex, + key -> new HashMap<>()); + rowValues.put(tableValue.attributeId, tableValue); + } + return indexMapping; + } + + protected void valuesFromIndexMap( + final List> values, + final Map> indexMapping) { + + values.clear(); + final List rows = new ArrayList<>(indexMapping.keySet()); + rows.sort((i1, i2) -> i1.compareTo(i2)); + rows + .stream() + .forEach(i -> { + final Map rowValues = indexMapping.get(i); + values.add(rowValues); + // addTableRow(rowValues); + }); +// for (int i = 0; i < rows.size(); i++) { +// final Map rowValues = indexMapping.get(i); +// values.add(rowValues); +// addTableRow(rowValues); +// } + } + + protected void applyFormValues( + final List> values, + final Map rowValues, + final int index) { + + if (values != null && !values.isEmpty()) { + values.remove(index); + values.add(index, rowValues); + applyTableRowValues(index); + } + + // send values to web-service + this.tableContext.getValueChangeListener() + .tableChanged(extractTableValue(values)); + } + + protected ConfigurationTableValues extractTableValue(final List> values) { + final List collect = values + .stream() + .flatMap(map -> map.values().stream()) + .collect(Collectors.toList()); + + return new ConfigurationTableValues( + this.tableContext.getInstitutionId(), + this.tableContext.getConfigurationId(), + this.attribute.id, + collect); + } + + @Override + public void setDefaultValue() { + // NOTE this just empty the list for now + // TODO do we need default values for lists? + clearTable(); + final List values = new ArrayList<>(); + this.tableContext.getValueChangeListener().tableChanged( + new ConfigurationTableValues( + this.tableContext.getInstitutionId(), + this.tableContext.getConfigurationId(), + this.attribute.id, + values)); + } + + void clearTable() { + this.control.setSelection(-1); + if (this.control.getItemCount() > 0) { + for (final TableItem item : this.control.getItems()) { + item.dispose(); + } + } + } + + @Override + protected void setValueToControl(final String value) { + throw new UnsupportedOperationException(); + } + + @Override + public String getValue() { + throw new UnsupportedOperationException(); + } + } + +} diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/impl/CompositeTableFieldBuilder.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/impl/CompositeTableFieldBuilder.java new file mode 100644 index 00000000..e08936bf --- /dev/null +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/impl/CompositeTableFieldBuilder.java @@ -0,0 +1,259 @@ +/* + * 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.examconfig.impl; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.commons.lang3.StringUtils; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Table; +import org.eclipse.swt.widgets.TableColumn; +import org.eclipse.swt.widgets.TableItem; +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.Constants; +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.ConfigurationTableValues.TableValue; +import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationValue; +import ch.ethz.seb.sebserver.gbl.model.sebconfig.Orientation; +import ch.ethz.seb.sebserver.gbl.profile.GuiProfile; +import ch.ethz.seb.sebserver.gui.service.examconfig.ExamConfigurationService; +import ch.ethz.seb.sebserver.gui.service.examconfig.InputField; +import ch.ethz.seb.sebserver.gui.service.i18n.I18nSupport; +import ch.ethz.seb.sebserver.gui.service.i18n.LocTextKey; +import ch.ethz.seb.sebserver.gui.service.page.impl.ModalInputDialog; +import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestService; +import ch.ethz.seb.sebserver.gui.widget.WidgetFactory; + +@Lazy +@Component +@GuiProfile +public class CompositeTableFieldBuilder extends AbstractTableFieldBuilder { + + private static final Logger log = LoggerFactory.getLogger(CompositeTableFieldBuilder.class); + + private static final String TABLE_ENTRY_NAME = "TABLE_ENTRY"; + private static final String TABLE_COLUMN_NAME_KEY = "TABLE_COLUMN_NAME"; + + protected CompositeTableFieldBuilder( + final RestService restService, + final WidgetFactory widgetFactory) { + + super(restService, widgetFactory); + } + + @Override + public boolean builderFor( + final ConfigurationAttribute attribute, + final Orientation orientation) { + + if (attribute == null) { + return false; + } + + return AttributeType.COMPOSITE_TABLE == attribute.type; + } + + @Override + public InputField createInputField( + final Composite parent, + final ConfigurationAttribute attribute, + final ViewContext viewContext) { + + final I18nSupport i18nSupport = viewContext.getI18nSupport(); + final TableContext tableContext = createTableContext(attribute, viewContext); + final Table table = createTable(parent, tableContext); + + final String resources = attribute.getResources(); + final String[] columnsAndRows = StringUtils.split( + resources, + Constants.EMBEDDED_LIST_SEPARATOR); + final String[] columns = (columnsAndRows.length == 2) + ? StringUtils.split(columnsAndRows[0], Constants.LIST_SEPARATOR) + : new String[] { TABLE_ENTRY_NAME }; + final String[] rows = (columnsAndRows.length == 2) + ? StringUtils.split(columnsAndRows[1], Constants.LIST_SEPARATOR) + : StringUtils.split(columnsAndRows[0], Constants.LIST_SEPARATOR); + + final String attributeNameKey = ExamConfigurationService.attributeNameKey(attribute); + for (int i = 0; i < columns.length; i++) { + final TableColumn column = this.widgetFactory.tableColumnLocalized( + table, + new LocTextKey(attributeNameKey + "." + columns[i]), + new LocTextKey(attributeNameKey + "." + columns[i] + ".tootlip")); + + column.setData(TABLE_COLUMN_NAME_KEY, columns[i]); + column.setWidth(100); + column.setResizable(false); + column.setMoveable(false); + } + + for (int i = 0; i < rows.length; i++) { + final TableItem item = new TableItem(table, SWT.NONE); + for (int j = 0; j < columns.length; j++) { + if (TABLE_ENTRY_NAME.equals(columns[j])) { + item.setText(j, i18nSupport.getText( + ExamConfigurationService.ATTRIBUTE_LABEL_LOC_TEXT_PREFIX + rows[i], + rows[i])); + } + } + } + + final CompositeTableInputField tableField = new CompositeTableInputField( + tableContext, + table, + Arrays.asList(columns), + Arrays.asList(rows)); + + setSelectionListener(table, tableField); + return tableField; + } + + @Override + protected void adaptColumnWidth( + final Table table, + final TableContext tableContext) { + + try { + final int currentTableWidth = table.getClientArea().width - 50; + final TableColumn[] columns = table.getColumns(); + final int widthUnit = currentTableWidth / (columns.length + 2); + for (int i = 0; i < columns.length; i++) { + final int factor = (TABLE_ENTRY_NAME.equals(columns[i].getData(TABLE_COLUMN_NAME_KEY))) ? 4 : 1; + columns[i].setWidth(widthUnit * factor); + } + } catch (final Exception e) { + log.warn("Failed to adaptColumnWidth: ", e); + } + } + + static final class CompositeTableInputField extends AbstractTableInputField { + + final List columns; + final List rows; + final List> values; + + CompositeTableInputField( + final TableContext tableContext, + final Table control, + final List columns, + final List rows) { + + super(tableContext.attribute, tableContext.orientation, control, null, tableContext); + this.values = new ArrayList<>(); + this.columns = columns; + this.rows = rows; + } + + @Override + void initValue(final List tableValues) { + valuesFromIndexMap(this.values, createRowIndexMap(tableValues)); + for (int i = 0; i < this.values.size(); i++) { + setRowValues(i, this.values.get(i)); + } + } + + @Override + protected void applyTableRowValues(final int index) { + setRowValues(index, this.values.get(index)); + } + + private void setRowValues(final int index, final Map map) { + final TableItem rowItem = this.control.getItem(index); + for (final TableValue val : map.values()) { + final Orientation orientation = this.tableContext.getOrientation(val.attributeId); + final String groupId = orientation.getGroupId(); + if (StringUtils.isNoneBlank(groupId)) { + final int cellIndex = this.columns.indexOf(groupId); + if (cellIndex >= 0) { + setValueToCell( + this.tableContext, + rowItem, + cellIndex, + this.tableContext.getAttribute(val.attributeId), + val); + } + } + } + } + + @Override + protected void openForm(final int selectionIndex) { + final String row = this.rows.get(selectionIndex); + final Map rowValues = this.values.get(selectionIndex); + final TableRowFormBuilder builder = new TableRowFormBuilder( + this.tableContext, + rowValues, + row); + + new ModalInputDialog>( + this.control.getShell(), + this.tableContext.getWidgetFactory()) + .setDialogWidth(500) + .open( + new LocTextKey(ExamConfigurationService.ATTRIBUTE_LABEL_LOC_TEXT_PREFIX + row), + rowVals -> applyFormValues(this.values, rowVals, selectionIndex), + () -> this.tableContext.getValueChangeListener() + .tableChanged(extractTableValue(this.values)), + builder); + } + + @Override + protected Map> createRowIndexMap(final List tableValues) { + final Map> indexMapping = new HashMap<>(); + for (final TableValue tableValue : tableValues) { + final ConfigurationAttribute attribute = this.tableContext + .getViewContext() + .getAttribute(tableValue.attributeId); + final String groupId = ConfigurationAttribute.getDependencyValue( + ConfigurationAttribute.DEPENDENCY_GROUP_ID, + attribute); + final int index = this.rows.indexOf(groupId); + final Map rowValues = indexMapping.computeIfAbsent( + index, + key -> new HashMap<>()); + rowValues.put(tableValue.attributeId, tableValue); + } + return indexMapping; + } + + @Override + void clearTable() { + // nothing to clear for this table type + } + + @Override + protected boolean isChildValue( + final TableContext tableContext, + final ConfigurationAttribute attribute, + final ConfigurationValue value) { + + final boolean childValue = super.isChildValue(tableContext, attribute, value); + if (childValue) { + final ConfigurationAttribute attr = tableContext.getAttribute(value.attributeId); + return ConfigurationAttribute.hasDependency( + ConfigurationAttribute.DEPENDENCY_GROUP_ID, + attr); + } + + return childValue; + } + + } + +} 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 41e6b806..51cf1935 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 @@ -166,7 +166,6 @@ public class ExamConfigurationServiceImpl implements ExamConfigurationService { gridLayout.verticalSpacing = 0; composite.setLayout(gridLayout); final GridData gridData = new GridData(SWT.FILL, SWT.TOP, true, false); - gridData.heightHint = 200; composite.setLayoutData(gridData); final ViewGridBuilder viewGridBuilder = new ViewGridBuilder( diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/impl/LabelBuilder.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/impl/LabelBuilder.java index 28b75abd..86631ec1 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/impl/LabelBuilder.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/impl/LabelBuilder.java @@ -8,9 +8,6 @@ package ch.ethz.seb.sebserver.gui.service.examconfig.impl; -import java.util.Objects; - -import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Label; import org.springframework.context.annotation.Lazy; @@ -20,14 +17,22 @@ 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.Orientation; import ch.ethz.seb.sebserver.gbl.profile.GuiProfile; +import ch.ethz.seb.sebserver.gui.service.examconfig.ExamConfigurationService; import ch.ethz.seb.sebserver.gui.service.examconfig.InputField; import ch.ethz.seb.sebserver.gui.service.examconfig.InputFieldBuilder; +import ch.ethz.seb.sebserver.gui.widget.WidgetFactory; @Lazy @Component @GuiProfile public class LabelBuilder implements InputFieldBuilder { + private final WidgetFactory widgetFactory; + + protected LabelBuilder(final WidgetFactory widgetFactory) { + this.widgetFactory = widgetFactory; + } + @Override public boolean builderFor( final ConfigurationAttribute attribute, @@ -46,12 +51,9 @@ public class LabelBuilder implements InputFieldBuilder { final ConfigurationAttribute attribute, final ViewContext viewContext) { - Objects.requireNonNull(parent); - Objects.requireNonNull(attribute); - Objects.requireNonNull(viewContext); - - final Label label = new Label(parent, SWT.NONE); - label.setText(attribute.name); + final Label label = this.widgetFactory.labelLocalized( + parent, + ExamConfigurationService.attributeNameLocKey(attribute)); return new LabelField( attribute, diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/impl/SelectionFieldBuilder.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/impl/SelectionFieldBuilder.java index 50fe2a2a..f5664a3e 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/impl/SelectionFieldBuilder.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/impl/SelectionFieldBuilder.java @@ -11,7 +11,6 @@ package ch.ethz.seb.sebserver.gui.service.examconfig.impl; import java.util.Arrays; import java.util.Collections; import java.util.List; -import java.util.Map; import java.util.stream.Collectors; import org.apache.commons.lang3.StringUtils; @@ -19,7 +18,6 @@ import org.apache.commons.lang3.StringUtils; import ch.ethz.seb.sebserver.gbl.Constants; import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationAttribute; import ch.ethz.seb.sebserver.gbl.util.Tuple; -import ch.ethz.seb.sebserver.gbl.util.Utils; import ch.ethz.seb.sebserver.gui.service.examconfig.ExamConfigurationService; public abstract class SelectionFieldBuilder { @@ -47,11 +45,14 @@ public abstract class SelectionFieldBuilder { return Collections.emptyList(); } - final Map attributeDependencyMap = Utils.getAttributeDependencyMap(attribute); final String prefix = - (attributeDependencyMap.containsKey(ConfigurationAttribute.DEPENDENCY_RESOURCE_LOC_TEXT_KEY)) - ? attributeDependencyMap.get(ConfigurationAttribute.DEPENDENCY_RESOURCE_LOC_TEXT_KEY) + "." - : ExamConfigurationService.ATTRIBUTE_LABEL_LOC_TEXT_PREFIX + attribute.name + "."; + (ConfigurationAttribute.hasDependency( + ConfigurationAttribute.DEPENDENCY_RESOURCE_LOC_TEXT_KEY, + attribute)) + ? ConfigurationAttribute.getDependencyValue( + ConfigurationAttribute.DEPENDENCY_RESOURCE_LOC_TEXT_KEY, + attribute) + "." + : ExamConfigurationService.ATTRIBUTE_LABEL_LOC_TEXT_PREFIX + attribute.name + "."; return Arrays.asList(StringUtils.split( attribute.resources, diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/impl/TableContext.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/impl/TableContext.java index 57e7cf15..a9b6887a 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/impl/TableContext.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/impl/TableContext.java @@ -16,21 +16,18 @@ import java.util.Objects; import java.util.Set; import java.util.stream.Collectors; -import org.apache.commons.lang3.BooleanUtils; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import ch.ethz.seb.sebserver.gbl.Constants; import ch.ethz.seb.sebserver.gbl.model.Domain; import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationAttribute; import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationTableValues.TableValue; import ch.ethz.seb.sebserver.gbl.model.sebconfig.Orientation; -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; import ch.ethz.seb.sebserver.gui.service.examconfig.InputFieldBuilder; import ch.ethz.seb.sebserver.gui.service.examconfig.ValueChangeListener; +import ch.ethz.seb.sebserver.gui.service.i18n.I18nSupport; import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestService; import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.GetExamConfigTableRowValues; import ch.ethz.seb.sebserver.gui.widget.WidgetFactory; @@ -78,6 +75,10 @@ public class TableContext { .collect(Collectors.toList()); } + public I18nSupport i18nSupport() { + return this.viewContext.i18nSupport; + } + public InputFieldBuilderSupplier getInputFieldBuilderSupplier() { return this.inputFieldBuilderSupplier; } @@ -102,6 +103,20 @@ public class TableContext { return this.rowAttributes; } + public List getRowAttributes(final String rowGroupId) { + if (StringUtils.isBlank(rowGroupId)) { + return getRowAttributes(); + } else { + return this.rowAttributes + .stream() + .filter(attr -> rowGroupId.equals(ConfigurationAttribute.getDependencyValue( + ConfigurationAttribute.DEPENDENCY_GROUP_ID, + attr))) + .sorted(rowAttributeComparator(this.viewContext)) + .collect(Collectors.toList()); + } + } + public List getColumnAttributes() { return this.columnAttributes; } @@ -188,31 +203,4 @@ public class TableContext { }; } - public String getRowValue(final TableValue tableValue) { - if (tableValue == null || StringUtils.isBlank(tableValue.value)) { - return Constants.EMPTY_NOTE; - } - - final ConfigurationAttribute attribute = this.viewContext.getAttribute(tableValue.attributeId); - if (attribute != null) { - switch (attribute.type) { - case CHECKBOX: { - return BooleanUtils.toBoolean(tableValue.value) - ? this.viewContext.i18nSupport.getText(ResourceService.ACTIVE_TEXT_KEY) - : this.viewContext.i18nSupport.getText(ResourceService.INACTIVE_TEXT_KEY); - } - case SINGLE_SELECTION: { - final String key = ExamConfigurationService.ATTRIBUTE_LABEL_LOC_TEXT_PREFIX + - attribute.getName() + "." + - tableValue.value; - return this.viewContext.i18nSupport.getText(key, tableValue.value); - } - default: - return tableValue.value; - } - } - - return tableValue.value; - } - } diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/impl/TableFieldBuilder.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/impl/TableFieldBuilder.java index 54c8a433..f61d569c 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/impl/TableFieldBuilder.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/impl/TableFieldBuilder.java @@ -9,37 +9,27 @@ package ch.ethz.seb.sebserver.gui.service.examconfig.impl; import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.function.Function; import java.util.stream.Collectors; -import org.apache.commons.lang3.BooleanUtils; import org.eclipse.swt.SWT; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Table; import org.eclipse.swt.widgets.TableColumn; import org.eclipse.swt.widgets.TableItem; -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.model.sebconfig.AttributeType; import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationAttribute; -import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationTableValues; import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationTableValues.TableValue; -import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationValue; import ch.ethz.seb.sebserver.gbl.model.sebconfig.Orientation; import ch.ethz.seb.sebserver.gbl.profile.GuiProfile; import ch.ethz.seb.sebserver.gui.service.examconfig.ExamConfigurationService; import ch.ethz.seb.sebserver.gui.service.examconfig.InputField; -import ch.ethz.seb.sebserver.gui.service.examconfig.InputFieldBuilder; -import ch.ethz.seb.sebserver.gui.service.i18n.I18nSupport; +import ch.ethz.seb.sebserver.gui.service.i18n.LocTextKey; import ch.ethz.seb.sebserver.gui.service.page.impl.ModalInputDialog; import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestService; import ch.ethz.seb.sebserver.gui.widget.WidgetFactory; @@ -48,27 +38,13 @@ import ch.ethz.seb.sebserver.gui.widget.WidgetFactory.ImageIcon; @Lazy @Component @GuiProfile -public class TableFieldBuilder implements InputFieldBuilder { - - private static final Logger log = LoggerFactory.getLogger(TableFieldBuilder.class); - - private static final String ROW_VALUE_KEY = "RowValues"; - - private final RestService restService; - private final WidgetFactory widgetFactory; - private InputFieldBuilderSupplier inputFieldBuilderSupplier; +public class TableFieldBuilder extends AbstractTableFieldBuilder { protected TableFieldBuilder( final RestService restService, final WidgetFactory widgetFactory) { - this.restService = restService; - this.widgetFactory = widgetFactory; - } - - @Override - public void init(final InputFieldBuilderSupplier inputFieldBuilderSupplier) { - this.inputFieldBuilderSupplier = inputFieldBuilderSupplier; + super(restService, widgetFactory); } @Override @@ -89,35 +65,20 @@ public class TableFieldBuilder implements InputFieldBuilder { final ConfigurationAttribute attribute, final ViewContext viewContext) { - final I18nSupport i18nSupport = viewContext.getI18nSupport(); - final TableContext tableContext = new TableContext( - this.inputFieldBuilderSupplier, - this.widgetFactory, - this.restService, - attribute, - viewContext); - - final Table table = new Table(parent, SWT.NONE | SWT.H_SCROLL); - table.setLayout(new GridLayout()); - final GridData gridData = new GridData( - SWT.FILL, SWT.FILL, - true, false, - (tableContext.orientation != null) ? tableContext.orientation.width() : 1, - (tableContext.orientation != null) ? tableContext.orientation.height() : 1); - gridData.heightHint = tableContext.orientation.height * 20 + 40; - table.setLayoutData(gridData); - table.setHeaderVisible(true); - table.addListener(SWT.Resize, event -> adaptColumnWidth(table, tableContext)); + final TableContext tableContext = createTableContext(attribute, viewContext); + final Table table = createTable(parent, tableContext); for (final ConfigurationAttribute columnAttribute : tableContext.getColumnAttributes()) { - final TableColumn column = new TableColumn(table, SWT.NONE); - final String text = i18nSupport.getText( - ExamConfigurationService.ATTRIBUTE_LABEL_LOC_TEXT_PREFIX + - columnAttribute.name, - columnAttribute.name); - column.setText(text); + final TableColumn column = this.widgetFactory.tableColumnLocalized( + table, + new LocTextKey(ExamConfigurationService.ATTRIBUTE_LABEL_LOC_TEXT_PREFIX + + columnAttribute.name), + new LocTextKey(ExamConfigurationService.ATTRIBUTE_LABEL_LOC_TEXT_PREFIX + + columnAttribute.name + + ".tootltip")); column.setWidth(100); column.setResizable(false); + column.setMoveable(false); } final TableInputField tableField = new TableInputField( @@ -149,107 +110,28 @@ public class TableFieldBuilder implements InputFieldBuilder { } }); - table.addListener(SWT.MouseDoubleClick, event -> { - final int selectionIndex = table.getSelectionIndex(); - if (selectionIndex >= 0) { - tableField.openForm(selectionIndex); - } - }); - + setSelectionListener(table, tableField); return tableField; } - private void adaptColumnWidth( - final Table table, - final TableContext tableContext) { + static final class TableInputField extends AbstractTableInputField { - try { - final int currentTableWidth = table.getClientArea().width - 50; - final TableColumn[] columns = table.getColumns(); - final List orientations = tableContext - .getColumnAttributes() - .stream() - .map(attr -> tableContext.getOrientation(attr.id)) - .collect(Collectors.toList()); - final Integer div = orientations - .stream() - .map(o -> o.width) - .reduce(0, (acc, val) -> acc + val); - final int widthUnit = currentTableWidth / div; - for (int i = 0; i < columns.length - 2; i++) { - columns[i].setWidth(widthUnit * orientations.get(i).width); - } - } catch (final Exception e) { - log.warn("Failed to adaptColumnWidth: ", e); - } - } - - static final class TableInputField extends AbstractInputField
{ - - private final TableContext tableContext; - - private List> values; + private final List> values; TableInputField( final TableContext tableContext, final Table control) { - super(tableContext.attribute, tableContext.orientation, control, null); - this.tableContext = tableContext; + super(tableContext.attribute, tableContext.orientation, control, null, tableContext); + this.values = new ArrayList<>(); } @Override - public ConfigurationValue initValue(final Collection values) { - clearTable(); - // get all child values as TableValues - final List tableValues = values.stream() - .filter(this::isChildValue) - .map(TableValue::of) - .collect(Collectors.toList()); - - initValue(tableValues); - - return null; - } - void initValue(final List tableValues) { - final Map> _initValue = new HashMap<>(); - for (final TableValue tableValue : tableValues) { - final Map rowValues = _initValue.computeIfAbsent( - tableValue.listIndex, - key -> new HashMap<>()); - rowValues.put(tableValue.attributeId, tableValue); + valuesFromIndexMap(this.values, createRowIndexMap(tableValues)); + for (int i = 0; i < this.values.size(); i++) { + addTableRow(i, this.values.get(i)); } - - final List rows = new ArrayList<>(_initValue.keySet()); - rows.sort((i1, i2) -> i1.compareTo(i2)); - - this.values = new ArrayList<>(); - rows - .stream() - .forEach(i -> { - final Map rowValues = _initValue.get(i); - this.values.add(rowValues); - addTableRow(rowValues); - }); - } - - private boolean isChildValue(final ConfigurationValue value) { - if (!this.tableContext.getViewContext().attributeMapping.attributeIdMapping - .containsKey(value.attributeId)) { - - return false; - } - - ConfigurationAttribute attr = this.tableContext.getAttribute(value.attributeId); - while (attr.parentId != null) { - if (this.attribute.id.equals(attr.parentId)) { - return true; - } - attr = this.tableContext.getAttribute(attr.parentId); - } - - return false; } private void deleteRow(final int selectionIndex) { @@ -257,7 +139,7 @@ public class TableFieldBuilder implements InputFieldBuilder { this.values.remove(selectionIndex); // send new values to web-service this.tableContext.getValueChangeListener() - .tableChanged(extractTableValue()); + .tableChanged(extractTableValue(this.values)); } private void addRow() { @@ -271,21 +153,22 @@ public class TableFieldBuilder implements InputFieldBuilder { Function.identity())); this.values.add(rowValues); - addTableRow(rowValues); + addTableRow(this.values.size() - 1, rowValues); this.control.layout(); // send new values to web-service this.tableContext.getValueChangeListener() - .tableChanged(extractTableValue()); + .tableChanged(extractTableValue(this.values)); } - private void addTableRow(final Map rowValues) { + protected void addTableRow(final int index, final Map rowValues) { new TableItem(this.control, SWT.NONE); - applyTableRowValues(this.values.size() - 1); + applyTableRowValues(index); // TODO try to add delete button within table row? } - private void applyTableRowValues(final int index) { + @Override + protected void applyTableRowValues(final int index) { final TableItem item = this.control.getItem(index); final Map rowValues = this.values.get(index); @@ -293,26 +176,14 @@ public class TableFieldBuilder implements InputFieldBuilder { for (final ConfigurationAttribute attr : this.tableContext.getColumnAttributes()) { if (rowValues.containsKey(attr.id)) { final TableValue tableValue = rowValues.get(attr.id); - if (attr.type == AttributeType.CHECKBOX) { - - item.setImage( - cellIndex, - (BooleanUtils.toBoolean((tableValue != null) ? tableValue.value : null)) - ? ImageIcon.YES.getImage(this.control.getDisplay()) - : ImageIcon.NO.getImage(this.control.getDisplay())); - } else { - item.setText( - cellIndex, - this.tableContext.getRowValue(tableValue)); - } + setValueToCell(this.tableContext, item, cellIndex, attr, tableValue); } cellIndex++; } - - item.setData(ROW_VALUE_KEY, item); } - private void openForm(final int selectionIndex) { + @Override + protected void openForm(final int selectionIndex) { final Map rowValues = this.values.get(selectionIndex); final TableRowFormBuilder builder = new TableRowFormBuilder( this.tableContext, @@ -327,69 +198,12 @@ public class TableFieldBuilder implements InputFieldBuilder { ExamConfigurationService.getTablePopupTitleKey( this.attribute, this.tableContext.getViewContext().i18nSupport), - values -> applyFormValues(values, selectionIndex), + rowVals -> applyFormValues(this.values, rowVals, selectionIndex), () -> this.tableContext.getValueChangeListener() - .tableChanged(extractTableValue()), + .tableChanged(extractTableValue(this.values)), builder); } - private void applyFormValues(final Map values, final int index) { - if (values != null && !values.isEmpty()) { - this.values.remove(index); - this.values.add(index, values); - applyTableRowValues(index); - } - - // send values to web-service - this.tableContext.getValueChangeListener() - .tableChanged(extractTableValue()); - } - - private ConfigurationTableValues extractTableValue() { - final List collect = this.values - .stream() - .flatMap(map -> map.values().stream()) - .collect(Collectors.toList()); - - return new ConfigurationTableValues( - this.tableContext.getInstitutionId(), - this.tableContext.getConfigurationId(), - this.attribute.id, - collect); - } - - @Override - public void setDefaultValue() { - // NOTE this just empty the list for now - // TODO do we need default values for lists? - clearTable(); - final List values = new ArrayList<>(); - this.tableContext.getValueChangeListener().tableChanged( - new ConfigurationTableValues( - this.tableContext.getInstitutionId(), - this.tableContext.getConfigurationId(), - this.attribute.id, - values)); - } - - private void clearTable() { - this.control.setSelection(-1); - if (this.control.getItemCount() > 0) { - for (final TableItem item : this.control.getItems()) { - item.dispose(); - } - } - } - - @Override - protected void setValueToControl(final String value) { - throw new UnsupportedOperationException(); - } - - @Override - public String getValue() { - throw new UnsupportedOperationException(); - } } } diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/impl/TableRowFormBuilder.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/impl/TableRowFormBuilder.java index dbcd62c1..4cdbd105 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/impl/TableRowFormBuilder.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/impl/TableRowFormBuilder.java @@ -25,11 +25,11 @@ import org.eclipse.swt.widgets.Label; 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.ConfigurationTableValues.TableValue; +import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationValue; import ch.ethz.seb.sebserver.gbl.model.sebconfig.Orientation; import ch.ethz.seb.sebserver.gui.service.examconfig.ExamConfigurationService; import ch.ethz.seb.sebserver.gui.service.examconfig.InputField; import ch.ethz.seb.sebserver.gui.service.examconfig.InputFieldBuilder; -import ch.ethz.seb.sebserver.gui.service.examconfig.impl.TableFieldBuilder.TableInputField; import ch.ethz.seb.sebserver.gui.service.i18n.LocTextKey; import ch.ethz.seb.sebserver.gui.service.page.ModalInputDialogComposer; import ch.ethz.seb.sebserver.gui.service.page.PageService; @@ -40,6 +40,7 @@ public class TableRowFormBuilder implements ModalInputDialogComposer rowValues; private final int listIndex; + private final String rowGroupId; public TableRowFormBuilder( final TableContext tableContext, @@ -49,6 +50,18 @@ public class TableRowFormBuilder implements ModalInputDialogComposer rowValues, + final String rowGroupId) { + + this.tableContext = tableContext; + this.rowValues = rowValues; + this.listIndex = 0; + this.rowGroupId = rowGroupId; } @Override @@ -67,11 +80,25 @@ public class TableRowFormBuilder implements ModalInputDialogComposer inputFields = new ArrayList<>(); - for (final ConfigurationAttribute attribute : this.tableContext.getRowAttributes()) { + for (final ConfigurationAttribute attribute : this.tableContext.getRowAttributes(this.rowGroupId)) { createLabel(grid, attribute); inputFields.add(createInputField(grid, attribute)); } + for (final InputField inputField : inputFields) { + final ConfigurationAttribute attribute = inputField.getAttribute(); + this.tableContext.getValueChangeListener().notifyGUI( + this.tableContext.getViewContext(), + attribute, + new ConfigurationValue( + null, + null, + null, + attribute.id, + this.listIndex, + inputField.getValue())); + } + // when the pop-up gets closed we have to remove the input fields from the view context grid.addDisposeListener(event -> { this.tableContext.flushInputFields(this.rowValues.keySet()); @@ -103,14 +130,8 @@ public class TableRowFormBuilder implements ModalInputDialogComposer(this.rowValues.values())); - } else { - inputField.initValue( - this.rowValues.get(attribute.id).value, - this.listIndex); - } - + final TableValue initValue = this.rowValues.get(attribute.id); + inputField.initValue((initValue != null) ? initValue.value : null, this.listIndex); // we have to register the input field within the ViewContext to receive error messages this.tableContext.registerInputField(inputField); diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/impl/TextFieldBuilder.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/impl/TextFieldBuilder.java index 68379780..72151667 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/impl/TextFieldBuilder.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/impl/TextFieldBuilder.java @@ -64,14 +64,23 @@ public class TextFieldBuilder implements InputFieldBuilder { .createInnerGrid(parent, attribute, orientation); final Text text; - if (attribute.type == AttributeType.INTEGER || - attribute.type == AttributeType.DECIMAL) { - - text = new Text(innerGrid, SWT.RIGHT | SWT.BORDER); - } else { - text = new Text(innerGrid, SWT.LEFT | SWT.BORDER); + final GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, false); + switch (attribute.type) { + case INTEGER: + case DECIMAL: { + text = new Text(innerGrid, SWT.RIGHT | SWT.BORDER); + break; + } + case TEXT_AREA: { + text = new Text(innerGrid, SWT.LEFT | SWT.BORDER | SWT.MULTI); + gridData.heightHint = 50; + break; + } + default: { + text = new Text(innerGrid, SWT.LEFT | SWT.BORDER); + } } - text.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); + text.setLayoutData(gridData); final LocTextKey toolTipKey = ExamConfigurationService.getToolTipKey( attribute, diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/impl/ViewContext.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/impl/ViewContext.java index f3febb0a..f4c8dc82 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/impl/ViewContext.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/impl/ViewContext.java @@ -96,10 +96,6 @@ public final class ViewContext { public View getView() { return this.view; } -// -// public AttributeMapping getAttributeMapping() { -// return this.attributeMapping; -// } public Collection getChildAttributes(final Long id) { return this.attributeMapping.childAttributeMapping.get(id); diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/impl/ViewGridBuilder.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/impl/ViewGridBuilder.java index 2e026149..4fc18003 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/impl/ViewGridBuilder.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/impl/ViewGridBuilder.java @@ -12,6 +12,7 @@ import java.util.Arrays; import java.util.HashSet; import java.util.Set; +import org.apache.commons.lang3.BooleanUtils; import org.apache.commons.lang3.StringUtils; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.GridData; @@ -71,8 +72,12 @@ public class ViewGridBuilder { log.debug("Add SEB Configuration Attribute: " + attribute); } - // ignore nested attributes here - if (attribute.parentId != null) { + // ignore nested attributes here (if not propagated to show up in view) + if (attribute.parentId != null && + !BooleanUtils.toBoolean(ConfigurationAttribute.getDependencyValue( + ConfigurationAttribute.DEPENDENCY_SHOW_IN_VIEW, + attribute))) { + return this; } diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/impl/rules/AllowFlashFullscreenRule.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/impl/rules/AllowFlashFullscreenRule.java index b4f1cba2..2df93091 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/impl/rules/AllowFlashFullscreenRule.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/impl/rules/AllowFlashFullscreenRule.java @@ -34,7 +34,7 @@ public class AllowFlashFullscreenRule implements ValueChangeRule { @Override public void applyRule( final ViewContext context, - final ConfigurationAttribute attribut, + final ConfigurationAttribute attribute, final ConfigurationValue value) { if (BooleanUtils.toBoolean(value.value)) { diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/impl/rules/BrowserViewModeRule.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/impl/rules/BrowserViewModeRule.java index de6a5823..f5ec725d 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/impl/rules/BrowserViewModeRule.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/impl/rules/BrowserViewModeRule.java @@ -39,7 +39,7 @@ public class BrowserViewModeRule implements ValueChangeRule { @Override public void applyRule( final ViewContext context, - final ConfigurationAttribute attribut, + final ConfigurationAttribute attribute, final ConfigurationValue value) { if (StringUtils.isBlank(value.value)) { diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/impl/rules/ExitKeySequenceChangeRule.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/impl/rules/ExitKeySequenceChangeRule.java index f94f2ba6..f41791f8 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/impl/rules/ExitKeySequenceChangeRule.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/impl/rules/ExitKeySequenceChangeRule.java @@ -34,7 +34,7 @@ public class ExitKeySequenceChangeRule implements ValueChangeRule { @Override public void applyRule( final ViewContext context, - final ConfigurationAttribute attribut, + final ConfigurationAttribute attribute, final ConfigurationValue value) { if (BooleanUtils.toBoolean(value.value)) { diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/impl/rules/HideToolbarDefaultRule.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/impl/rules/HideToolbarDefaultRule.java index 64b0d256..817b8f56 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/impl/rules/HideToolbarDefaultRule.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/impl/rules/HideToolbarDefaultRule.java @@ -34,7 +34,7 @@ public class HideToolbarDefaultRule implements ValueChangeRule { @Override public void applyRule( final ViewContext context, - final ConfigurationAttribute attribut, + final ConfigurationAttribute attribute, final ConfigurationValue value) { if (BooleanUtils.toBoolean(value.value)) { diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/impl/rules/ProxyPasswordRule.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/impl/rules/ProxyPasswordRule.java new file mode 100644 index 00000000..4a93bc4d --- /dev/null +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/impl/rules/ProxyPasswordRule.java @@ -0,0 +1,62 @@ +/* + * 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.examconfig.impl.rules; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.commons.lang3.BooleanUtils; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Service; + +import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationAttribute; +import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationValue; +import ch.ethz.seb.sebserver.gbl.profile.GuiProfile; +import ch.ethz.seb.sebserver.gbl.util.Tuple; +import ch.ethz.seb.sebserver.gui.service.examconfig.ValueChangeRule; +import ch.ethz.seb.sebserver.gui.service.examconfig.impl.ViewContext; + +@Lazy +@Service +@GuiProfile +public class ProxyPasswordRule implements ValueChangeRule { + + public static final String KEY_HTTP_PWD_REQUIRED = "HTTPRequiresPassword"; + + private final Map> observed; + + public ProxyPasswordRule() { + this.observed = new HashMap<>(); + this.observed.put(KEY_HTTP_PWD_REQUIRED, new Tuple<>("HTTPUsername", "HTTPPassword")); + } + + @Override + public boolean observesAttribute(final ConfigurationAttribute attribute) { + return this.observed.containsKey(attribute.name); + } + + @Override + public void applyRule( + final ViewContext context, + final ConfigurationAttribute attribute, + final ConfigurationValue value) { + + final Tuple tuple = this.observed.get(attribute.name); + if (tuple != null) { + if (BooleanUtils.toBoolean(value.value)) { + context.enable(tuple._1); + context.enable(tuple._2); + } else { + context.disable(tuple._1); + context.disable(tuple._2); + } + } + } + +} diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/i18n/I18nSupport.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/i18n/I18nSupport.java index 9ca1e046..3cd083f9 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/service/i18n/I18nSupport.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/i18n/I18nSupport.java @@ -94,4 +94,6 @@ public interface I18nSupport { * @return the text in current language parsed from localized text */ String getText(String key, Locale locale, String def, Object... args); + boolean hasText(LocTextKey locTooltipKey); + } diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/i18n/impl/I18nSupportImpl.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/i18n/impl/I18nSupportImpl.java index 75b98623..d29c70ac 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/service/i18n/impl/I18nSupportImpl.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/i18n/impl/I18nSupportImpl.java @@ -32,6 +32,7 @@ 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.service.i18n.I18nSupport; +import ch.ethz.seb.sebserver.gui.service.i18n.LocTextKey; import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.CurrentUser; @Lazy @@ -168,4 +169,13 @@ public class I18nSupportImpl implements I18nSupport { return this.messageSource.getMessage(key, args, def, locale); } + @Override + public boolean hasText(final LocTextKey key) { + if (key == null) { + return false; + } + + return getText(key.name, (String) null) != null; + } + } diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/i18n/impl/PolyglotPageServiceImpl.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/i18n/impl/PolyglotPageServiceImpl.java index 2234b605..6da4cfa4 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/service/i18n/impl/PolyglotPageServiceImpl.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/i18n/impl/PolyglotPageServiceImpl.java @@ -155,7 +155,7 @@ public final class PolyglotPageServiceImpl implements PolyglotPageService { tableColumn.setData(POLYGLOT_ITEM_TEXT_DATA_KEY, locTextKey); tableColumn.setText(this.i18nSupport.getText(locTextKey)); - if (locTooltipKey != null) { + if (this.i18nSupport.hasText(locTooltipKey)) { tableColumn.setData(POLYGLOT_ITEM_TOOLTIP_DATA_KEY, locTooltipKey); tableColumn.setToolTipText(this.i18nSupport.getText(locTooltipKey)); } @@ -178,7 +178,7 @@ public final class PolyglotPageServiceImpl implements PolyglotPageService { tabItem.setData(POLYGLOT_ITEM_TEXT_DATA_KEY, locTextKey); tabItem.setText(this.i18nSupport.getText(locTextKey)); - if (locTooltipKey != null) { + if (this.i18nSupport.hasText(locTooltipKey)) { tabItem.setData(POLYGLOT_ITEM_TOOLTIP_DATA_KEY, locTooltipKey); tabItem.setToolTipText(this.i18nSupport.getText(locTooltipKey)); } diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/page/impl/PageServiceImpl.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/page/impl/PageServiceImpl.java index cee0babb..9b4b561b 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/service/page/impl/PageServiceImpl.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/page/impl/PageServiceImpl.java @@ -189,7 +189,7 @@ public class PageServiceImpl implements PageService { .getUISession() .getHttpSession(); - log.debug("SET session PageState: {} : {}", pageAction.definition.targetState, httpSession.getId()); + log.debug("Set session PageState: {} : {}", pageAction.definition.targetState, httpSession.getId()); httpSession.setAttribute(ATTR_PAGE_STATE, pageAction.definition.targetState); } catch (final Exception e) { diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/table/EntityTable.java b/src/main/java/ch/ethz/seb/sebserver/gui/table/EntityTable.java index 863dc27d..61e6c0aa 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/table/EntityTable.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/table/EntityTable.java @@ -308,7 +308,8 @@ public class EntityTable { // TODO error handling }); - this.composite.layout(true, true); + this.composite.getParent().layout(true, true); + PageService.updateScrolledComposite(this.composite); } private Page createTableRowsFromPage(final Page page) { diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/widget/ColorSelection.java b/src/main/java/ch/ethz/seb/sebserver/gui/widget/ColorSelection.java index b225e92e..fadd4911 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/widget/ColorSelection.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/widget/ColorSelection.java @@ -33,6 +33,8 @@ public final class ColorSelection extends Composite implements Selection { private static final long serialVersionUID = 4775375044147842526L; private static final Logger log = LoggerFactory.getLogger(ColorSelection.class); + private static final LocTextKey DEFAULT_SELECT_TOOLTIP_KEY = new LocTextKey("sebserver.overall.action.select"); + private static final int ACTION_COLUMN_WIDTH = 20; private final ColorDialog colorDialog; private final Composite colorField; @@ -40,7 +42,11 @@ public final class ColorSelection extends Composite implements Selection { private Listener listener = null; - ColorSelection(final Composite parent, final WidgetFactory widgetFactory) { + ColorSelection( + final Composite parent, + final WidgetFactory widgetFactory, + final String tooltipKeyPrefix) { + super(parent, SWT.NONE); final GridLayout gridLayout = new GridLayout(2, false); gridLayout.verticalSpacing = 1; @@ -60,7 +66,9 @@ public final class ColorSelection extends Composite implements Selection { final Label imageButton = widgetFactory.imageButton( ImageIcon.COLOR, this, - new LocTextKey("Set Color"), + (StringUtils.isNoneBlank(tooltipKeyPrefix) + ? new LocTextKey(tooltipKeyPrefix) + : DEFAULT_SELECT_TOOLTIP_KEY), this::addColorSelection); final GridData actionCell = new GridData(SWT.LEFT, SWT.CENTER, true, false); diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/widget/MultiSelectionCombo.java b/src/main/java/ch/ethz/seb/sebserver/gui/widget/MultiSelectionCombo.java index 3d99d4d0..38f2de11 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/widget/MultiSelectionCombo.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/widget/MultiSelectionCombo.java @@ -41,6 +41,9 @@ public final class MultiSelectionCombo extends Composite implements Selection { private static final long serialVersionUID = -7787134114963647332L; private static final int ACTION_COLUMN_WIDTH = 20; + private static final LocTextKey DEFAULT_ADD_TOOLTIP_KEY = new LocTextKey("sebserver.overall.add"); + private static final LocTextKey DEFAULT_REMOVE_TOOLTIP_KEY = new LocTextKey("sebserver.overall.remove"); + private final WidgetFactory widgetFactory; private final Combo combo; private final LocTextKey addTextKey; @@ -64,10 +67,10 @@ public final class MultiSelectionCombo extends Composite implements Selection { this.widgetFactory = widgetFactory; this.addTextKey = (locTextPrefix != null) ? new LocTextKey(locTextPrefix + ".add") - : new LocTextKey("sebserver.overall.add"); + : DEFAULT_ADD_TOOLTIP_KEY; this.removeTextKey = (locTextPrefix != null) ? new LocTextKey(locTextPrefix + ".remove") - : new LocTextKey("sebserver.overall.remove"); + : DEFAULT_REMOVE_TOOLTIP_KEY; final GridLayout gridLayout = new GridLayout(2, false); gridLayout.verticalSpacing = 1; diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/widget/ThresholdList.java b/src/main/java/ch/ethz/seb/sebserver/gui/widget/ThresholdList.java index 94847fdf..ff36fc81 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/widget/ThresholdList.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/widget/ThresholdList.java @@ -36,10 +36,11 @@ public final class ThresholdList extends Composite { private static final long serialVersionUID = -2305091471607040280L; private static final int ACTION_COLUMN_WIDTH = 20; - private static final LocTextKey valueTextKey = new LocTextKey("sebserver.exam.indicator.thresholds.list.value"); - private static final LocTextKey colorTextKey = new LocTextKey("sebserver.exam.indicator.thresholds.list.color"); - private static final LocTextKey addTextKey = new LocTextKey("sebserver.exam.indicator.thresholds.list.add"); - private static final LocTextKey removeTextKey = new LocTextKey("sebserver.exam.indicator.thresholds.list.remove"); + private static final String COLOR_SELECTION_TEXT_KEY = "sebserver.exam.indicator.thresholds.select.color"; + private static final LocTextKey VALUE_TEXT_KEY = new LocTextKey("sebserver.exam.indicator.thresholds.list.value"); + private static final LocTextKey COLOR_TEXT_KEY = new LocTextKey("sebserver.exam.indicator.thresholds.list.color"); + private static final LocTextKey ADD_TEXT_KEY = new LocTextKey("sebserver.exam.indicator.thresholds.list.add"); + private static final LocTextKey REMOVE_TEXT_KEY = new LocTextKey("sebserver.exam.indicator.thresholds.list.remove"); private final WidgetFactory widgetFactory; private final List thresholds = new ArrayList<>(); @@ -62,18 +63,24 @@ public final class ThresholdList extends Composite { this.addListener(SWT.Resize, this::adaptColumnWidth); - final Label valueTitle = widgetFactory.labelLocalized(this, CustomVariant.TITLE_LABEL, valueTextKey); + final Label valueTitle = widgetFactory.labelLocalized( + this, + CustomVariant.TITLE_LABEL, + VALUE_TEXT_KEY); this.valueCell = new GridData(SWT.FILL, SWT.CENTER, true, false); valueTitle.setLayoutData(this.valueCell); - final Label colorTitle = widgetFactory.labelLocalized(this, CustomVariant.TITLE_LABEL, colorTextKey); + final Label colorTitle = widgetFactory.labelLocalized( + this, + CustomVariant.TITLE_LABEL, + COLOR_TEXT_KEY); this.colorCell = new GridData(SWT.FILL, SWT.CENTER, true, false); colorTitle.setLayoutData(this.colorCell); final Label imageButton = widgetFactory.imageButton( ImageIcon.ADD_BOX, this, - addTextKey, + ADD_TEXT_KEY, this::addThreshold); this.actionCell = new GridData(SWT.LEFT, SWT.CENTER, true, false); imageButton.setLayoutData(this.actionCell); @@ -120,7 +127,9 @@ public final class ThresholdList extends Composite { final GridData valueCell = new GridData(SWT.FILL, SWT.CENTER, true, false); valueInput.setLayoutData(valueCell); - final Selection selector = this.widgetFactory.selectionLocalized(Type.COLOR, this, null); + final Selection selector = this.widgetFactory.selectionLocalized( + Type.COLOR, this, null, null, null, + COLOR_SELECTION_TEXT_KEY); final GridData selectorCell = new GridData(SWT.FILL, SWT.CENTER, true, false); selectorCell.horizontalIndent = 2; selector.adaptToControl().setLayoutData(selectorCell); @@ -128,7 +137,7 @@ public final class ThresholdList extends Composite { final Label imageButton = this.widgetFactory.imageButton( ImageIcon.REMOVE_BOX, this, - removeTextKey, + REMOVE_TEXT_KEY, null); final GridData actionCell = new GridData(SWT.FILL, SWT.CENTER, true, false); imageButton.setLayoutData(actionCell); diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/widget/WidgetFactory.java b/src/main/java/ch/ethz/seb/sebserver/gui/widget/WidgetFactory.java index a18d8c47..e9145a10 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/widget/WidgetFactory.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/widget/WidgetFactory.java @@ -281,7 +281,8 @@ public class WidgetFactory { } public Text textAreaInput(final Composite content) { - return new Text(content, SWT.LEFT | SWT.BORDER | SWT.MULTI); + final Text textArea = new Text(content, SWT.LEFT | SWT.BORDER | SWT.MULTI); + return textArea; } public Text textInput(final Composite content, final boolean password) { @@ -477,7 +478,7 @@ public class WidgetFactory { selection = new MultiSelectionCheckbox(parent); break; case COLOR: - selection = new ColorSelection(parent, this); + selection = new ColorSelection(parent, this, actionLocTextPrefix); break; default: throw new IllegalArgumentException("Unsupported Selection.Type: " + type); diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/PaginationServiceImpl.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/PaginationServiceImpl.java index cfe7ec50..45ce75cf 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/PaginationServiceImpl.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/PaginationServiceImpl.java @@ -230,12 +230,6 @@ public class PaginationServiceImpl implements PaginationService { // Exam Table final Map examTableMap = new HashMap<>(); - examTableMap.put( - Domain.EXAM.ATTR_INSTITUTION_ID, - ExamRecordDynamicSqlSupport.institutionId.name()); - examTableMap.put( - Domain.EXAM.ATTR_LMS_SETUP_ID, - ExamRecordDynamicSqlSupport.lmsSetupId.name()); examTableMap.put( Domain.EXAM.ATTR_TYPE, ExamRecordDynamicSqlSupport.type.name()); diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ConfigurationDAOImpl.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ConfigurationDAOImpl.java index af29cee6..26274530 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ConfigurationDAOImpl.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ConfigurationDAOImpl.java @@ -210,6 +210,7 @@ public class ConfigurationDAOImpl implements ConfigurationDAO { // with the current attribute values // TODO batch here for better performance + // http://pretius.com/how-to-use-mybatis-effectively-perform-batch-db-operations/ allValues.stream() .map(oldValRec -> new ConfigurationValueRecord( null, diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ConfigurationNodeDAOImpl.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ConfigurationNodeDAOImpl.java index 66185e86..4a5bc701 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ConfigurationNodeDAOImpl.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ConfigurationNodeDAOImpl.java @@ -31,6 +31,7 @@ import org.springframework.transaction.annotation.Transactional; import ch.ethz.seb.sebserver.gbl.api.APIMessage.FieldValidationException; import ch.ethz.seb.sebserver.gbl.api.EntityType; import ch.ethz.seb.sebserver.gbl.model.EntityKey; +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.ConfigurationNode.ConfigurationStatus; import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode.ConfigurationType; @@ -44,6 +45,7 @@ import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.ConfigurationReco import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.ConfigurationRecordMapper; import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.ConfigurationValueRecordDynamicSqlSupport; import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.ConfigurationValueRecordMapper; +import ch.ethz.seb.sebserver.webservice.datalayer.batis.model.ConfigurationAttributeRecord; import ch.ethz.seb.sebserver.webservice.datalayer.batis.model.ConfigurationNodeRecord; import ch.ethz.seb.sebserver.webservice.datalayer.batis.model.ConfigurationRecord; import ch.ethz.seb.sebserver.webservice.datalayer.batis.model.ConfigurationValueRecord; @@ -361,6 +363,8 @@ public class ConfigurationNodeDAOImpl implements ConfigurationNodeDAO { .build() .execute() .stream() + // filter child attributes of tables. No default value for tables. Use templates for that + .filter(ConfigurationNodeDAOImpl::filterChildAttribute) .forEach(attrRec -> { final String value = templateValues.getOrDefault( attrRec.getId(), @@ -379,6 +383,17 @@ public class ConfigurationNodeDAOImpl implements ConfigurationNodeDAO { }); } + private static boolean filterChildAttribute(final ConfigurationAttributeRecord rec) { + + if (rec.getParentId() == null) { + return true; + } + + return BooleanUtils.toBoolean(ConfigurationAttribute.getDependencyValue( + ConfigurationAttribute.DEPENDENCY_CREATE_DEFAULT_VALUE, + rec.getDependencies())); + } + /* * Get values from template with configuration attribute id mapped to the value * returns empty list if no template available 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 8ec8b629..6f34f657 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 @@ -28,6 +28,7 @@ import org.springframework.stereotype.Component; import org.springframework.transaction.annotation.Transactional; import ch.ethz.seb.sebserver.gbl.api.EntityType; +import ch.ethz.seb.sebserver.gbl.model.sebconfig.AttributeType; import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationTableValues; import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationTableValues.TableValue; import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationValue; @@ -293,50 +294,109 @@ public class ConfigurationValueDAOImpl implements ConfigurationValueDAO { .flatMap(val -> attributeRecordById(val.attributeId)) .map(attributeRecord -> { - final Map attributeMap = this.configurationAttributeRecordMapper - .selectByExample() - .where( - ConfigurationAttributeRecordDynamicSqlSupport.parentId, - isEqualTo(attributeRecord.getId())) - .build() - .execute() - .stream() - .collect(Collectors.toMap(rec -> rec.getId(), Function.identity())); - - final List columnAttributeIds = attributeMap.values() - .stream() - .map(a -> a.getId()) - .collect(Collectors.toList()); - - // first delete all old values of this table - this.configurationValueRecordMapper.deleteByExample() - .where( - ConfigurationValueRecordDynamicSqlSupport.configurationId, - isEqualTo(value.configurationId)) - .and( - ConfigurationValueRecordDynamicSqlSupport.configurationAttributeId, - SqlBuilder.isIn(columnAttributeIds)) - .build() - .execute(); - - // then add the new values - for (final TableValue tableValue : value.values) { - final ConfigurationAttributeRecord columnAttr = attributeMap.get(tableValue.attributeId); - final ConfigurationValueRecord valueRecord = new ConfigurationValueRecord( - null, - value.institutionId, - value.configurationId, - columnAttr.getId(), - tableValue.listIndex, - tableValue.value); - - this.configurationValueRecordMapper.insert(valueRecord); + final String type = attributeRecord.getType(); + if (AttributeType.TABLE.name().equals(type)) { + saveAsTable(value, attributeRecord); + } else { + saveAsComposite(value); } return value; }); } + private void saveAsTable( + final ConfigurationTableValues value, + final ConfigurationAttributeRecord attributeRecord) { + + final Map attributeMap = + this.configurationAttributeRecordMapper + .selectByExample() + .where( + ConfigurationAttributeRecordDynamicSqlSupport.parentId, + isEqualTo(attributeRecord.getId())) + .build() + .execute() + .stream() + .collect(Collectors.toMap(rec -> rec.getId(), Function.identity())); + + final List columnAttributeIds = attributeMap.values() + .stream() + .map(a -> a.getId()) + .collect(Collectors.toList()); + + // first delete all old values of this table + this.configurationValueRecordMapper.deleteByExample() + .where( + ConfigurationValueRecordDynamicSqlSupport.configurationId, + isEqualTo(value.configurationId)) + .and( + ConfigurationValueRecordDynamicSqlSupport.configurationAttributeId, + SqlBuilder.isIn(columnAttributeIds)) + .build() + .execute(); + + // then add the new values + // TODO optimize with batching + for (final TableValue tableValue : value.values) { + final ConfigurationAttributeRecord columnAttr = attributeMap.get(tableValue.attributeId); + final ConfigurationValueRecord valueRecord = new ConfigurationValueRecord( + null, + value.institutionId, + value.configurationId, + columnAttr.getId(), + tableValue.listIndex, + tableValue.value); + + this.configurationValueRecordMapper.insert(valueRecord); + } + } + + private void saveAsComposite(final ConfigurationTableValues value) { + // TODO optimize with batching + for (final TableValue tableValue : value.values) { + + final List valuePK = this.configurationValueRecordMapper.selectIdsByExample() + .where( + ConfigurationValueRecordDynamicSqlSupport.configurationId, + isEqualTo(value.configurationId)) + .and( + ConfigurationValueRecordDynamicSqlSupport.configurationAttributeId, + isEqualTo(tableValue.attributeId)) + .and( + ConfigurationValueRecordDynamicSqlSupport.listIndex, + isEqualTo(tableValue.listIndex)) + .build() + .execute(); + + if (valuePK != null && valuePK.size() > 1) { + throw new IllegalStateException("Expected no more then one element"); + } + + if (valuePK == null || valuePK.isEmpty()) { + // insert + this.configurationValueRecordMapper.insert( + new ConfigurationValueRecord( + null, + value.institutionId, + value.configurationId, + tableValue.attributeId, + tableValue.listIndex, + tableValue.value)); + } else { + // update + this.configurationValueRecordMapper.updateByPrimaryKey( + new ConfigurationValueRecord( + valuePK.iterator().next(), + value.institutionId, + value.configurationId, + tableValue.attributeId, + tableValue.listIndex, + tableValue.value)); + } + } + } + private Result attributeRecord(final ConfigurationValue value) { return attributeRecordById(value.attributeId); } diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/SebClientConfigService.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/SebClientConfigService.java index 68ad422a..a2796c22 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/SebClientConfigService.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/SebClientConfigService.java @@ -16,39 +16,28 @@ import ch.ethz.seb.sebserver.gbl.util.Result; public interface SebClientConfigService { static String SEB_CLIENT_CONFIG_EXAMPLE_XML = - "\r\n" + - "" + "\r\n" + - "" + - "" + - "sebMode" + - "1" + - "sebServerFallback" + - "" + - "sebServerURL" + - "%s" + - "sebServerConfiguration" + - "" + - "" + - "institution" + - "%s" + - "clientName" + - "%s" + - "clientSecret" + - "%s" + - "accessTokenEndpoint" + - "%s" + - "handshakeEndpoint" + - "%s" + - "examConfigEndpoint" + - "%s" + - "pingEndpoint" + - "%s" + - "eventEndpoint" + - "%s" + - "" + - "" + - "" + + "\r\n" + + " \r\n" + + " sebMode\r\n" + + " 1\r\n" + + " sebServerFallback\r\n" + + " \r\n" + + " sebServerURL\r\n" + + " %s\r\n" + + " sebServerConfiguration\r\n" + + " \r\n" + + " institution\r\n" + + " %s\r\n" + + " clientName\r\n" + + " %s\r\n" + + " clientSecret\r\n" + + " %s\r\n" + + " apiDiscovery\r\n" + + " %s\r\n" + + " \r\n" + + " \r\n" + ""; boolean hasSebClientConfigurationForInstitution(Long institutionId); diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/impl/SebClientConfigServiceImpl.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/impl/SebClientConfigServiceImpl.java index f4e8888e..37a7c047 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/impl/SebClientConfigServiceImpl.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/impl/SebClientConfigServiceImpl.java @@ -24,7 +24,6 @@ import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import org.springframework.web.util.UriComponentsBuilder; -import ch.ethz.seb.sebserver.gbl.api.API; import ch.ethz.seb.sebserver.gbl.model.institution.Institution; import ch.ethz.seb.sebserver.gbl.model.sebconfig.SebClientConfig; import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile; @@ -54,7 +53,6 @@ public class SebClientConfigServiceImpl implements SebClientConfigService { private final String httpScheme; private final String serverAddress; private final String serverPort; - private final String sebClientAPIEndpoint; protected SebClientConfigServiceImpl( final InstitutionDAO institutionDAO, @@ -64,8 +62,7 @@ public class SebClientConfigServiceImpl implements SebClientConfigService { final ZipService zipService, @Value("${sebserver.webservice.http.scheme}") final String httpScheme, @Value("${server.address}") final String serverAddress, - @Value("${server.port}") final String serverPort, - @Value("${sebserver.webservice.api.exam.endpoint}") final String sebClientAPIEndpoint) { + @Value("${server.port}") final String serverPort) { this.institutionDAO = institutionDAO; this.sebClientConfigDAO = sebClientConfigDAO; @@ -75,7 +72,6 @@ public class SebClientConfigServiceImpl implements SebClientConfigService { this.httpScheme = httpScheme; this.serverAddress = serverAddress; this.serverPort = serverPort; - this.sebClientAPIEndpoint = sebClientAPIEndpoint; } @Override @@ -136,11 +132,7 @@ public class SebClientConfigServiceImpl implements SebClientConfigService { String.valueOf(config.institutionId), plainClientId, plainClientSecret, - API.OAUTH_TOKEN_ENDPOINT, - this.sebClientAPIEndpoint + API.EXAM_API_HANDSHAKE_ENDPOINT, - this.sebClientAPIEndpoint + API.EXAM_API_CONFIGURATION_REQUEST_ENDPOINT, - this.sebClientAPIEndpoint + API.EXAM_API_PING_ENDPOINT, - this.sebClientAPIEndpoint + API.EXAM_API_EVENT_ENDPOINT); + "TODO:/exam-api/discovery"); PipedOutputStream pOut = null; PipedInputStream pIn = null; diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ExamAdministrationController.java b/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ExamAdministrationController.java index c3cc2e8a..ecde95cd 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ExamAdministrationController.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ExamAdministrationController.java @@ -27,9 +27,9 @@ 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.APIMessage.APIMessageException; -import ch.ethz.seb.sebserver.gbl.api.authorization.PrivilegeType; import ch.ethz.seb.sebserver.gbl.api.EntityType; 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; @@ -140,11 +140,16 @@ public class ExamAdministrationController extends ActivatableEntityController( exams.size() / pSize, pageNum, sort, - exams.subList(pageNum * pSize, pageNum * pSize + pSize)); + exams.subList(start, end)); } } diff --git a/src/main/resources/config/application-dev-ws.properties b/src/main/resources/config/application-dev-ws.properties index de070111..ea67b7a9 100644 --- a/src/main/resources/config/application-dev-ws.properties +++ b/src/main/resources/config/application-dev-ws.properties @@ -4,7 +4,7 @@ server.servlet.context-path=/ spring.datasource.initialize=true spring.datasource.initialization-mode=always -spring.datasource.url=jdbc:mariadb://localhost:6603/SEBServer?useSSL=false&createDatabaseIfNotExist=true&default-character-set=utf8mb4 +spring.datasource.url=jdbc:mariadb://localhost:6603/SEBServer?useSSL=false spring.datasource.driver-class-name=org.mariadb.jdbc.Driver spring.datasource.platform=dev spring.datasource.hikari.max-lifetime=600000 diff --git a/src/main/resources/messages.properties b/src/main/resources/messages.properties index 89f5103d..13e0774c 100644 --- a/src/main/resources/messages.properties +++ b/src/main/resources/messages.properties @@ -23,6 +23,7 @@ sebserver.overall.status.inactive=Inactive sebserver.overall.action.add=Add; sebserver.overall.action.remove=Remove +sebserver.overall.action.select=Please Select ################################ # Form validation and messages @@ -265,6 +266,7 @@ sebserver.exam.form.endtime=End Time sebserver.exam.form.status=Status sebserver.exam.form.type=Exam Type sebserver.exam.form.supporter=Exam Supporter +sebserver.exam.form.supporter.add=Add as supporter for this exam sebserver.exam.type.UNDEFINED=Not Defined sebserver.exam.type.MANAGED=Managed @@ -319,7 +321,9 @@ sebserver.exam.indicator.form.exam=Exam sebserver.exam.indicator.form.name=Name sebserver.exam.indicator.form.type=Type sebserver.exam.indicator.form.color=Default Color +sebserver.exam.indicator.form.color.action=Please select a color sebserver.exam.indicator.form.thresholds=Thresholds +sebserver.exam.indicator.thresholds.select.color=Please select a color sebserver.exam.indicator.thresholds.list.title=Thresholds sebserver.exam.indicator.thresholds.list.value=Value @@ -570,7 +574,7 @@ sebserver.examconfig.props.label.allowSwitchToApplications=Allow switching to th sebserver.examconfig.props.label.allowFlashFullscreen=Allow Flash to switch to fullscreen mode (Mac) sebserver.examconfig.props.label.permittedProcesses.row.title=Permitted Processes sebserver.examconfig.props.label.permittedProcesses=Permitted Processes -sebserver.examconfig.props.label.permittedProcesses.active=Activity +sebserver.examconfig.props.label.permittedProcesses.active=Active sebserver.examconfig.props.label.permittedProcesses.os=OS sebserver.examconfig.props.label.permittedProcesses.os.0=Win sebserver.examconfig.props.label.permittedProcesses.os.1=OS X @@ -594,7 +598,7 @@ sebserver.examconfig.props.label.permittedProcesses.strongKill=Force quit (risk sebserver.examconfig.props.label.prohibitedProcesses.row.title=Prohibited Processes sebserver.examconfig.props.label.prohibitedProcesses=Prohibited Processes -sebserver.examconfig.props.label.prohibitedProcesses.active=Activity +sebserver.examconfig.props.label.prohibitedProcesses.active=Active sebserver.examconfig.props.label.prohibitedProcesses.os=OS sebserver.examconfig.props.label.prohibitedProcesses.os.0=Win sebserver.examconfig.props.label.prohibitedProcesses.os.1=OS X @@ -604,16 +608,80 @@ sebserver.examconfig.props.label.prohibitedProcesses.originalName=Original Name sebserver.examconfig.props.label.prohibitedProcesses.identifier=Identifier sebserver.examconfig.props.label.prohibitedProcesses.strongKill=Force quit (risk of data loss) +sebserver.examconfig.props.group.urlFilter=Fitler sebserver.examconfig.props.label.URLFilterEnable=Activate URL Filtering sebserver.examconfig.props.label.URLFilterEnableContentFilter=Filter also embedded content sebserver.examconfig.props.label.URLFilterRules=Filter -sebserver.examconfig.props.label.URLFilterRules.active=Activity +sebserver.examconfig.props.label.URLFilterRules.row.title=URL Filter +sebserver.examconfig.props.label.URLFilterRules.active=Active sebserver.examconfig.props.label.URLFilterRules.regex=Regex sebserver.examconfig.props.label.URLFilterRules.expression=Expression sebserver.examconfig.props.label.URLFilterRules.action=Action sebserver.examconfig.props.label.URLFilterRules.action.0=Block sebserver.examconfig.props.label.URLFilterRules.action.1=Allow +sebserver.examconfig.props.group.proxies=Proxies +sebserver.examconfig.props.label.proxySettingsPolicy=proxy settings policy +sebserver.examconfig.props.label.proxySettingsPolicy.0=Use system proxy setting +sebserver.examconfig.props.label.proxySettingsPolicy.0.tooltip=System proxy settings of the exam client computer are used +sebserver.examconfig.props.label.proxySettingsPolicy.1=Use SEB proxy settings +sebserver.examconfig.props.label.proxySettingsPolicy.1.tooltip=Proxy settings provided in these SEB settings are used +sebserver.examconfig.props.label.proxies=Double-click a protocol to configure: +sebserver.examconfig.props.label.ExcludeSimpleHostnames=Exclude simple hostnames +sebserver.examconfig.props.label.ExceptionsList=Bypass proxy settings for these hosts and domains +sebserver.examconfig.props.label.ExceptionsList.tooltip=Separate hosts / domains with comma +sebserver.examconfig.props.label.FTPPassive=Use Passive FTP Mode (PASV) + +sebserver.examconfig.props.label.proxies.active=Active +sebserver.examconfig.props.label.proxies.TABLE_ENTRY=Protocol +sebserver.examconfig.props.label.autoDiscovery=Auto Proxy Discovery +sebserver.examconfig.props.label.AutoDiscoveryEnabled=Auto discovery enabled +sebserver.examconfig.props.label.autoConfiguration=Automatic Proxy Configuration +sebserver.examconfig.props.label.AutoConfigurationEnabled=Auto configuration enabeld +sebserver.examconfig.props.label.AutoConfigurationURL=Proxy configuration file URL +sebserver.examconfig.props.label.AutoConfigurationJavaScript=Proxy configuration JavaScript + +sebserver.examconfig.props.label.http=Web Proxy (HTTP) +sebserver.examconfig.props.label.HTTPEnable=Web proxy eneabled +sebserver.examconfig.props.label.HTTPProxy=Web proxy server +sebserver.examconfig.props.label.HTTPPort=Web proxy port +sebserver.examconfig.props.label.HTTPRequiresPassword=Proxy server requires password +sebserver.examconfig.props.label.HTTPUsername=Username +sebserver.examconfig.props.label.HTTPPassword=Password + +sebserver.examconfig.props.label.https=Secure Web Proxy (HTTPS) +sebserver.examconfig.props.label.HTTPSEnable=Secure web proxy eneabled +sebserver.examconfig.props.label.HTTPSProxy=Secure web proxy server +sebserver.examconfig.props.label.HTTPSPort=Secure web proxy port +sebserver.examconfig.props.label.HTTPSRequiresPassword=Proxy server requires password +sebserver.examconfig.props.label.HTTPSUsername=Username +sebserver.examconfig.props.label.HTTPSPassword=Password + +sebserver.examconfig.props.label.ftp=FTP Proxy +sebserver.examconfig.props.label.FTPEnable=FTP proxy eneabled +sebserver.examconfig.props.label.FTPProxy=FTP proxy server +sebserver.examconfig.props.label.FTPPort=FTP proxy port +sebserver.examconfig.props.label.FTPRequiresPassword=Proxy server requires password +sebserver.examconfig.props.label.FTPUsername=Username +sebserver.examconfig.props.label.FTPPassword=Password + +sebserver.examconfig.props.label.socks=SOCKS Proxy +sebserver.examconfig.props.label.SOCKSEnable=SOCKS proxy eneabled +sebserver.examconfig.props.label.SOCKSProxy=SOCKS proxy server +sebserver.examconfig.props.label.SOCKSPort=SOCKS proxy port +sebserver.examconfig.props.label.SOCKSRequiresPassword=Proxy server requires password +sebserver.examconfig.props.label.SOCKSUsername=Username +sebserver.examconfig.props.label.SOCKSPassword=Password + +sebserver.examconfig.props.label.rtsp=Streaming Proxy (RTSP) +sebserver.examconfig.props.label.RTSPEnable=RTSP proxy eneabled +sebserver.examconfig.props.label.RTSPProxy=RTSP proxy server +sebserver.examconfig.props.label.RTSPPort=RTSP proxy port +sebserver.examconfig.props.label.RTSPRequiresPassword=Proxy server requires password +sebserver.examconfig.props.label.RTSPUsername=Username +sebserver.examconfig.props.label.RTSPPassword=Password + + sebserver.examconfig.props.group.servicePolicy=SEB Service policy sebserver.examconfig.props.label.sebServicePolicy.0=allow to run SEB without service sebserver.examconfig.props.label.sebServicePolicy.1=display warning when service is not running diff --git a/src/main/resources/schema-dev.sql b/src/main/resources/schema-dev.sql index ca7ff137..94222ae9 100644 --- a/src/main/resources/schema-dev.sql +++ b/src/main/resources/schema-dev.sql @@ -1,5 +1,5 @@ -- MySQL Script generated by MySQL Workbench --- Fri May 24 11:57:07 2019 +-- Wed May 29 15:30:50 2019 -- Model: New Model Version: 1.0 -- MySQL Workbench Forward Engineering @@ -10,13 +10,20 @@ SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='TRADITIONAL,ALLOW_INVALID_DATES'; -- ----------------------------------------------------- -- Schema SEBServer -- ----------------------------------------------------- +DROP SCHEMA IF EXISTS `SEBServer` ; -- ----------------------------------------------------- --- Table `institution` +-- Schema SEBServer -- ----------------------------------------------------- -DROP TABLE IF EXISTS `institution` ; +CREATE SCHEMA IF NOT EXISTS `SEBServer` DEFAULT CHARACTER SET utf8mb4 ; +USE `SEBServer` ; -CREATE TABLE IF NOT EXISTS `institution` ( +-- ----------------------------------------------------- +-- Table `SEBServer`.`institution` +-- ----------------------------------------------------- +DROP TABLE IF EXISTS `SEBServer`.`institution` ; + +CREATE TABLE IF NOT EXISTS `SEBServer`.`institution` ( `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, `name` VARCHAR(255) NOT NULL, `url_suffix` VARCHAR(45) NULL, @@ -29,11 +36,11 @@ CREATE TABLE IF NOT EXISTS `institution` ( -- ----------------------------------------------------- --- Table `lms_setup` +-- Table `SEBServer`.`lms_setup` -- ----------------------------------------------------- -DROP TABLE IF EXISTS `lms_setup` ; +DROP TABLE IF EXISTS `SEBServer`.`lms_setup` ; -CREATE TABLE IF NOT EXISTS `lms_setup` ( +CREATE TABLE IF NOT EXISTS `SEBServer`.`lms_setup` ( `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, `institution_id` BIGINT UNSIGNED NOT NULL, `name` VARCHAR(255) NOT NULL, @@ -47,18 +54,18 @@ CREATE TABLE IF NOT EXISTS `lms_setup` ( INDEX `setupInstitutionRef_idx` (`institution_id` ASC), CONSTRAINT `setupInstitutionRef` FOREIGN KEY (`institution_id`) - REFERENCES `institution` (`id`) + REFERENCES `SEBServer`.`institution` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION) ; -- ----------------------------------------------------- --- Table `exam` +-- Table `SEBServer`.`exam` -- ----------------------------------------------------- -DROP TABLE IF EXISTS `exam` ; +DROP TABLE IF EXISTS `SEBServer`.`exam` ; -CREATE TABLE IF NOT EXISTS `exam` ( +CREATE TABLE IF NOT EXISTS `SEBServer`.`exam` ( `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, `institution_id` BIGINT UNSIGNED NOT NULL, `lms_setup_id` BIGINT UNSIGNED NOT NULL, @@ -74,23 +81,23 @@ CREATE TABLE IF NOT EXISTS `exam` ( INDEX `institution_key_idx` (`institution_id` ASC), CONSTRAINT `examLmsSetupRef` FOREIGN KEY (`lms_setup_id`) - REFERENCES `lms_setup` (`id`) + REFERENCES `SEBServer`.`lms_setup` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION, CONSTRAINT `examInstitutionRef` FOREIGN KEY (`institution_id`) - REFERENCES `institution` (`id`) + REFERENCES `SEBServer`.`institution` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION) ; -- ----------------------------------------------------- --- Table `client_connection` +-- Table `SEBServer`.`client_connection` -- ----------------------------------------------------- -DROP TABLE IF EXISTS `client_connection` ; +DROP TABLE IF EXISTS `SEBServer`.`client_connection` ; -CREATE TABLE IF NOT EXISTS `client_connection` ( +CREATE TABLE IF NOT EXISTS `SEBServer`.`client_connection` ( `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, `exam_id` BIGINT UNSIGNED NULL, `status` VARCHAR(45) NOT NULL, @@ -103,18 +110,18 @@ CREATE TABLE IF NOT EXISTS `client_connection` ( INDEX `connection_exam_ref_idx` (`exam_id` ASC), CONSTRAINT `clientConnectionExamRef` FOREIGN KEY (`exam_id`) - REFERENCES `exam` (`id`) + REFERENCES `SEBServer`.`exam` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION) ; -- ----------------------------------------------------- --- Table `client_event` +-- Table `SEBServer`.`client_event` -- ----------------------------------------------------- -DROP TABLE IF EXISTS `client_event` ; +DROP TABLE IF EXISTS `SEBServer`.`client_event` ; -CREATE TABLE IF NOT EXISTS `client_event` ( +CREATE TABLE IF NOT EXISTS `SEBServer`.`client_event` ( `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, `connection_id` BIGINT UNSIGNED NOT NULL, `user_identifier` VARCHAR(255) NOT NULL, @@ -126,18 +133,18 @@ CREATE TABLE IF NOT EXISTS `client_event` ( INDEX `eventConnectionRef_idx` (`connection_id` ASC), CONSTRAINT `eventConnectionRef` FOREIGN KEY (`connection_id`) - REFERENCES `client_connection` (`id`) + REFERENCES `SEBServer`.`client_connection` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION) ; -- ----------------------------------------------------- --- Table `indicator` +-- Table `SEBServer`.`indicator` -- ----------------------------------------------------- -DROP TABLE IF EXISTS `indicator` ; +DROP TABLE IF EXISTS `SEBServer`.`indicator` ; -CREATE TABLE IF NOT EXISTS `indicator` ( +CREATE TABLE IF NOT EXISTS `SEBServer`.`indicator` ( `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, `exam_id` BIGINT UNSIGNED NOT NULL, `type` VARCHAR(45) NOT NULL, @@ -147,18 +154,18 @@ CREATE TABLE IF NOT EXISTS `indicator` ( PRIMARY KEY (`id`), CONSTRAINT `exam_ref` FOREIGN KEY (`exam_id`) - REFERENCES `exam` (`id`) + REFERENCES `SEBServer`.`exam` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION) ; -- ----------------------------------------------------- --- Table `configuration_node` +-- Table `SEBServer`.`configuration_node` -- ----------------------------------------------------- -DROP TABLE IF EXISTS `configuration_node` ; +DROP TABLE IF EXISTS `SEBServer`.`configuration_node` ; -CREATE TABLE IF NOT EXISTS `configuration_node` ( +CREATE TABLE IF NOT EXISTS `SEBServer`.`configuration_node` ( `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, `institution_id` BIGINT UNSIGNED NOT NULL, `template_id` BIGINT UNSIGNED NULL, @@ -171,18 +178,18 @@ CREATE TABLE IF NOT EXISTS `configuration_node` ( INDEX `configurationInstitutionRef_idx` (`institution_id` ASC), CONSTRAINT `configurationInstitutionRef` FOREIGN KEY (`institution_id`) - REFERENCES `institution` (`id`) + REFERENCES `SEBServer`.`institution` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION) ; -- ----------------------------------------------------- --- Table `configuration` +-- Table `SEBServer`.`configuration` -- ----------------------------------------------------- -DROP TABLE IF EXISTS `configuration` ; +DROP TABLE IF EXISTS `SEBServer`.`configuration` ; -CREATE TABLE IF NOT EXISTS `configuration` ( +CREATE TABLE IF NOT EXISTS `SEBServer`.`configuration` ( `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, `institution_id` BIGINT UNSIGNED NOT NULL, `configuration_node_id` BIGINT UNSIGNED NOT NULL, @@ -194,23 +201,23 @@ CREATE TABLE IF NOT EXISTS `configuration` ( INDEX `config_institution_ref_idx` (`institution_id` ASC), CONSTRAINT `configuration_node_ref` FOREIGN KEY (`configuration_node_id`) - REFERENCES `configuration_node` (`id`) + REFERENCES `SEBServer`.`configuration_node` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION, CONSTRAINT `config_institution_ref` FOREIGN KEY (`institution_id`) - REFERENCES `institution` (`id`) + REFERENCES `SEBServer`.`institution` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION) ; -- ----------------------------------------------------- --- Table `configuration_attribute` +-- Table `SEBServer`.`configuration_attribute` -- ----------------------------------------------------- -DROP TABLE IF EXISTS `configuration_attribute` ; +DROP TABLE IF EXISTS `SEBServer`.`configuration_attribute` ; -CREATE TABLE IF NOT EXISTS `configuration_attribute` ( +CREATE TABLE IF NOT EXISTS `SEBServer`.`configuration_attribute` ( `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, `name` VARCHAR(45) NOT NULL, `type` VARCHAR(45) NOT NULL, @@ -223,52 +230,53 @@ CREATE TABLE IF NOT EXISTS `configuration_attribute` ( INDEX `parent_ref_idx` (`parent_id` ASC), CONSTRAINT `parent_ref` FOREIGN KEY (`parent_id`) - REFERENCES `configuration_attribute` (`id`) + REFERENCES `SEBServer`.`configuration_attribute` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION) ; -- ----------------------------------------------------- --- Table `configuration_value` +-- Table `SEBServer`.`configuration_value` -- ----------------------------------------------------- -DROP TABLE IF EXISTS `configuration_value` ; +DROP TABLE IF EXISTS `SEBServer`.`configuration_value` ; -CREATE TABLE IF NOT EXISTS `configuration_value` ( +CREATE TABLE IF NOT EXISTS `SEBServer`.`configuration_value` ( `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, `institution_id` BIGINT UNSIGNED NOT NULL, `configuration_id` BIGINT UNSIGNED NOT NULL, `configuration_attribute_id` BIGINT UNSIGNED NOT NULL, `list_index` INT NOT NULL DEFAULT 0, - `value` VARCHAR(20000) NULL, + `value` VARCHAR(16000) NULL, + `configuration_valuecol` VARCHAR(45) NULL, PRIMARY KEY (`id`), INDEX `configuration_value_ref_idx` (`configuration_id` ASC), INDEX `configuration_attribute_ref_idx` (`configuration_attribute_id` ASC), INDEX `configuration_value_institution_ref_idx` (`institution_id` ASC), CONSTRAINT `configuration_ref` FOREIGN KEY (`configuration_id`) - REFERENCES `configuration` (`id`) + REFERENCES `SEBServer`.`configuration` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION, CONSTRAINT `configuration_value_attribute_ref` FOREIGN KEY (`configuration_attribute_id`) - REFERENCES `configuration_attribute` (`id`) + REFERENCES `SEBServer`.`configuration_attribute` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION, CONSTRAINT `configuration_value_institution_ref` FOREIGN KEY (`institution_id`) - REFERENCES `institution` (`id`) + REFERENCES `SEBServer`.`institution` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION) ; -- ----------------------------------------------------- --- Table `view` +-- Table `SEBServer`.`view` -- ----------------------------------------------------- -DROP TABLE IF EXISTS `view` ; +DROP TABLE IF EXISTS `SEBServer`.`view` ; -CREATE TABLE IF NOT EXISTS `view` ( +CREATE TABLE IF NOT EXISTS `SEBServer`.`view` ( `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, `name` VARCHAR(255) NULL, `columns` INT NOT NULL, @@ -278,11 +286,11 @@ CREATE TABLE IF NOT EXISTS `view` ( -- ----------------------------------------------------- --- Table `orientation` +-- Table `SEBServer`.`orientation` -- ----------------------------------------------------- -DROP TABLE IF EXISTS `orientation` ; +DROP TABLE IF EXISTS `SEBServer`.`orientation` ; -CREATE TABLE IF NOT EXISTS `orientation` ( +CREATE TABLE IF NOT EXISTS `SEBServer`.`orientation` ( `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, `config_attribute_id` BIGINT UNSIGNED NOT NULL, `template_id` BIGINT UNSIGNED NULL, @@ -298,23 +306,23 @@ CREATE TABLE IF NOT EXISTS `orientation` ( INDEX `orientation_view_ref_idx` (`view_id` ASC), CONSTRAINT `config_attribute_orientation_ref` FOREIGN KEY (`config_attribute_id`) - REFERENCES `configuration_attribute` (`id`) + REFERENCES `SEBServer`.`configuration_attribute` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION, CONSTRAINT `orientation_view_ref` FOREIGN KEY (`view_id`) - REFERENCES `view` (`id`) + REFERENCES `SEBServer`.`view` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION) ; -- ----------------------------------------------------- --- Table `exam_configuration_map` +-- Table `SEBServer`.`exam_configuration_map` -- ----------------------------------------------------- -DROP TABLE IF EXISTS `exam_configuration_map` ; +DROP TABLE IF EXISTS `SEBServer`.`exam_configuration_map` ; -CREATE TABLE IF NOT EXISTS `exam_configuration_map` ( +CREATE TABLE IF NOT EXISTS `SEBServer`.`exam_configuration_map` ( `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, `institution_id` BIGINT UNSIGNED NOT NULL, `exam_id` BIGINT UNSIGNED NOT NULL, @@ -327,28 +335,28 @@ CREATE TABLE IF NOT EXISTS `exam_configuration_map` ( INDEX `exam_config_institution_ref_idx` (`institution_id` ASC), CONSTRAINT `exam_map_ref` FOREIGN KEY (`exam_id`) - REFERENCES `exam` (`id`) + REFERENCES `SEBServer`.`exam` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION, CONSTRAINT `configuration_map_ref` FOREIGN KEY (`configuration_node_id`) - REFERENCES `configuration_node` (`id`) + REFERENCES `SEBServer`.`configuration_node` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION, CONSTRAINT `exam_config_institution_ref` FOREIGN KEY (`institution_id`) - REFERENCES `institution` (`id`) + REFERENCES `SEBServer`.`institution` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION) ; -- ----------------------------------------------------- --- Table `user` +-- Table `SEBServer`.`user` -- ----------------------------------------------------- -DROP TABLE IF EXISTS `user` ; +DROP TABLE IF EXISTS `SEBServer`.`user` ; -CREATE TABLE IF NOT EXISTS `user` ( +CREATE TABLE IF NOT EXISTS `SEBServer`.`user` ( `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, `institution_id` BIGINT UNSIGNED NOT NULL, `uuid` VARCHAR(255) NOT NULL, @@ -363,18 +371,18 @@ CREATE TABLE IF NOT EXISTS `user` ( INDEX `institutionRef_idx` (`institution_id` ASC), CONSTRAINT `userInstitutionRef` FOREIGN KEY (`institution_id`) - REFERENCES `institution` (`id`) + REFERENCES `SEBServer`.`institution` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION) ; -- ----------------------------------------------------- --- Table `user_role` +-- Table `SEBServer`.`user_role` -- ----------------------------------------------------- -DROP TABLE IF EXISTS `user_role` ; +DROP TABLE IF EXISTS `SEBServer`.`user_role` ; -CREATE TABLE IF NOT EXISTS `user_role` ( +CREATE TABLE IF NOT EXISTS `SEBServer`.`user_role` ( `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, `user_id` BIGINT UNSIGNED NOT NULL, `role_name` VARCHAR(45) NOT NULL, @@ -382,18 +390,18 @@ CREATE TABLE IF NOT EXISTS `user_role` ( INDEX `user_ref_idx` (`user_id` ASC), CONSTRAINT `user_ref` FOREIGN KEY (`user_id`) - REFERENCES `user` (`id`) + REFERENCES `SEBServer`.`user` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION) ; -- ----------------------------------------------------- --- Table `oauth_access_token` +-- Table `SEBServer`.`oauth_access_token` -- ----------------------------------------------------- -DROP TABLE IF EXISTS `oauth_access_token` ; +DROP TABLE IF EXISTS `SEBServer`.`oauth_access_token` ; -CREATE TABLE IF NOT EXISTS `oauth_access_token` ( +CREATE TABLE IF NOT EXISTS `SEBServer`.`oauth_access_token` ( `token_id` VARCHAR(255) NULL, `token` BLOB NULL, `authentication_id` VARCHAR(255) NULL, @@ -405,11 +413,11 @@ CREATE TABLE IF NOT EXISTS `oauth_access_token` ( -- ----------------------------------------------------- --- Table `oauth_refresh_token` +-- Table `SEBServer`.`oauth_refresh_token` -- ----------------------------------------------------- -DROP TABLE IF EXISTS `oauth_refresh_token` ; +DROP TABLE IF EXISTS `SEBServer`.`oauth_refresh_token` ; -CREATE TABLE IF NOT EXISTS `oauth_refresh_token` ( +CREATE TABLE IF NOT EXISTS `SEBServer`.`oauth_refresh_token` ( `token_id` VARCHAR(255) NULL, `token` BLOB NULL, `authentication` BLOB NULL) @@ -417,11 +425,11 @@ CREATE TABLE IF NOT EXISTS `oauth_refresh_token` ( -- ----------------------------------------------------- --- Table `threshold` +-- Table `SEBServer`.`threshold` -- ----------------------------------------------------- -DROP TABLE IF EXISTS `threshold` ; +DROP TABLE IF EXISTS `SEBServer`.`threshold` ; -CREATE TABLE IF NOT EXISTS `threshold` ( +CREATE TABLE IF NOT EXISTS `SEBServer`.`threshold` ( `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, `indicator_id` BIGINT UNSIGNED NOT NULL, `value` DECIMAL(10,4) NOT NULL, @@ -430,18 +438,18 @@ CREATE TABLE IF NOT EXISTS `threshold` ( INDEX `indicator_threshold_id_idx` (`indicator_id` ASC), CONSTRAINT `indicator_threshold_id` FOREIGN KEY (`indicator_id`) - REFERENCES `indicator` (`id`) + REFERENCES `SEBServer`.`indicator` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION) ; -- ----------------------------------------------------- --- Table `user_activity_log` +-- Table `SEBServer`.`user_activity_log` -- ----------------------------------------------------- -DROP TABLE IF EXISTS `user_activity_log` ; +DROP TABLE IF EXISTS `SEBServer`.`user_activity_log` ; -CREATE TABLE IF NOT EXISTS `user_activity_log` ( +CREATE TABLE IF NOT EXISTS `SEBServer`.`user_activity_log` ( `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, `user_uuid` VARCHAR(255) NOT NULL, `timestamp` BIGINT NOT NULL, @@ -454,11 +462,11 @@ CREATE TABLE IF NOT EXISTS `user_activity_log` ( -- ----------------------------------------------------- --- Table `additional_attributes` +-- Table `SEBServer`.`additional_attributes` -- ----------------------------------------------------- -DROP TABLE IF EXISTS `additional_attributes` ; +DROP TABLE IF EXISTS `SEBServer`.`additional_attributes` ; -CREATE TABLE IF NOT EXISTS `additional_attributes` ( +CREATE TABLE IF NOT EXISTS `SEBServer`.`additional_attributes` ( `id` BIGINT UNSIGNED NOT NULL, `entity_type` VARCHAR(45) NOT NULL, `entity_id` BIGINT UNSIGNED NOT NULL, @@ -469,11 +477,11 @@ CREATE TABLE IF NOT EXISTS `additional_attributes` ( -- ----------------------------------------------------- --- Table `seb_client_configuration` +-- Table `SEBServer`.`seb_client_configuration` -- ----------------------------------------------------- -DROP TABLE IF EXISTS `seb_client_configuration` ; +DROP TABLE IF EXISTS `SEBServer`.`seb_client_configuration` ; -CREATE TABLE IF NOT EXISTS `seb_client_configuration` ( +CREATE TABLE IF NOT EXISTS `SEBServer`.`seb_client_configuration` ( `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, `institution_id` BIGINT UNSIGNED NOT NULL, `name` VARCHAR(255) NOT NULL, @@ -486,18 +494,18 @@ CREATE TABLE IF NOT EXISTS `seb_client_configuration` ( INDEX `sebClientCredentialsInstitutionRef_idx` (`institution_id` ASC), CONSTRAINT `sebClientConfigInstitutionRef` FOREIGN KEY (`institution_id`) - REFERENCES `institution` (`id`) + REFERENCES `SEBServer`.`institution` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION) ; -- ----------------------------------------------------- --- Table `webservice_server_info` +-- Table `SEBServer`.`webservice_server_info` -- ----------------------------------------------------- -DROP TABLE IF EXISTS `webservice_server_info` ; +DROP TABLE IF EXISTS `SEBServer`.`webservice_server_info` ; -CREATE TABLE IF NOT EXISTS `webservice_server_info` ( +CREATE TABLE IF NOT EXISTS `SEBServer`.`webservice_server_info` ( `id` BIGINT UNSIGNED NOT NULL, `uuid` VARCHAR(255) NOT NULL, `service_address` VARCHAR(255) NOT NULL, diff --git a/src/main/resources/static/css/sebserver.css b/src/main/resources/static/css/sebserver.css index 510ccfba..683c435a 100644 --- a/src/main/resources/static/css/sebserver.css +++ b/src/main/resources/static/css/sebserver.css @@ -233,7 +233,7 @@ Text.error { Text[MULTI] { padding: 5px 10px 5px 10px; - height: 50px; + height: 100px; } Text[BORDER], Text[MULTI][BORDER] { @@ -250,6 +250,7 @@ Text[BORDER]:focused, Text[MULTI][BORDER]:focused { Text[BORDER]:disabled, Text[MULTI][BORDER]:disabled, Text[BORDER]:read-only, Text[MULTI][BORDER]:read-only { box-shadow: none; + color: #CFCFCF; }