SEBSERV-44 SEBSERV-45 finished config tool and some bug fixes

This commit is contained in:
anhefti 2019-05-29 16:56:40 +02:00
parent 74306412e1
commit 84ac76efd7
45 changed files with 1253 additions and 522 deletions

View file

@ -48,7 +48,7 @@ public enum AttributeType {
INLINE_TABLE(COMPOSITE_LIST),
;
COMPOSITE_TABLE(COMPOSITE);
public final AttributeValueType attributeValueType;

View file

@ -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
}

View file

@ -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<String, String> getAttributeDependencyMap(final ConfigurationAttribute attribute) {
if (StringUtils.isBlank(attribute.dependencies)) {
return Collections.emptyMap();
}
return getAttributeDependencyMap(attribute.dependencies);
}
public static Map<String, String> 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();
}
}
}

View file

@ -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;

View file

@ -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<String, String> 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();
}
}
}

View file

@ -65,11 +65,14 @@ public final class SelectionFieldBuilder extends FieldBuilder<String> {
}
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);

View file

@ -59,6 +59,9 @@ public final class TextFieldBuilder extends FieldBuilder<String> {
: 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);

View file

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

View file

@ -18,7 +18,7 @@ public interface ValueChangeRule {
void applyRule(
ViewContext context,
ConfigurationAttribute attribut,
ConfigurationAttribute attribute,
ConfigurationValue value);
}

View file

@ -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<Orientation> 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<Table> {
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<ConfigurationValue> values) {
clearTable();
// get all child values as TableValues
final List<TableValue> tableValues = getChildValues(
this.tableContext,
this.attribute,
values);
initValue(tableValues);
return null;
}
abstract void initValue(final List<TableValue> tableValues);
abstract void openForm(final int selectionIndex);
abstract void applyTableRowValues(final int index);
protected List<TableValue> getChildValues(
final TableContext tableContext,
final ConfigurationAttribute attribute,
final Collection<ConfigurationValue> 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<Integer, Map<Long, TableValue>> createRowIndexMap(final List<TableValue> tableValues) {
final Map<Integer, Map<Long, TableValue>> indexMapping = new HashMap<>();
for (final TableValue tableValue : tableValues) {
final Map<Long, TableValue> rowValues = indexMapping.computeIfAbsent(
tableValue.listIndex,
key -> new HashMap<>());
rowValues.put(tableValue.attributeId, tableValue);
}
return indexMapping;
}
protected void valuesFromIndexMap(
final List<Map<Long, TableValue>> values,
final Map<Integer, Map<Long, TableValue>> indexMapping) {
values.clear();
final List<Integer> rows = new ArrayList<>(indexMapping.keySet());
rows.sort((i1, i2) -> i1.compareTo(i2));
rows
.stream()
.forEach(i -> {
final Map<Long, TableValue> rowValues = indexMapping.get(i);
values.add(rowValues);
// addTableRow(rowValues);
});
// for (int i = 0; i < rows.size(); i++) {
// final Map<Long, TableValue> rowValues = indexMapping.get(i);
// values.add(rowValues);
// addTableRow(rowValues);
// }
}
protected void applyFormValues(
final List<Map<Long, TableValue>> values,
final Map<Long, TableValue> 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<Map<Long, TableValue>> values) {
final List<TableValue> 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<TableValue> 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();
}
}
}

View file

@ -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<String> columns;
final List<String> rows;
final List<Map<Long, TableValue>> values;
CompositeTableInputField(
final TableContext tableContext,
final Table control,
final List<String> columns,
final List<String> rows) {
super(tableContext.attribute, tableContext.orientation, control, null, tableContext);
this.values = new ArrayList<>();
this.columns = columns;
this.rows = rows;
}
@Override
void initValue(final List<TableValue> 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<Long, TableValue> 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<Long, TableValue> rowValues = this.values.get(selectionIndex);
final TableRowFormBuilder builder = new TableRowFormBuilder(
this.tableContext,
rowValues,
row);
new ModalInputDialog<Map<Long, TableValue>>(
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<Integer, Map<Long, TableValue>> createRowIndexMap(final List<TableValue> tableValues) {
final Map<Integer, Map<Long, TableValue>> 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<Long, TableValue> 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;
}
}
}

View file

@ -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(

View file

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

View file

@ -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<String, String> 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,

View file

@ -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<ConfigurationAttribute> 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<ConfigurationAttribute> 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;
}
}

View file

@ -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<Orientation> 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<Table> {
private final TableContext tableContext;
private List<Map<Long, TableValue>> values;
private final List<Map<Long, TableValue>> 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<ConfigurationValue> values) {
clearTable();
// get all child values as TableValues
final List<TableValue> tableValues = values.stream()
.filter(this::isChildValue)
.map(TableValue::of)
.collect(Collectors.toList());
initValue(tableValues);
return null;
}
void initValue(final List<TableValue> tableValues) {
final Map<Integer, Map<Long, TableValue>> _initValue = new HashMap<>();
for (final TableValue tableValue : tableValues) {
final Map<Long, TableValue> 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<Integer> rows = new ArrayList<>(_initValue.keySet());
rows.sort((i1, i2) -> i1.compareTo(i2));
this.values = new ArrayList<>();
rows
.stream()
.forEach(i -> {
final Map<Long, TableValue> 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<Long, TableValue> rowValues) {
protected void addTableRow(final int index, final Map<Long, TableValue> 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<Long, TableValue> 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<Long, TableValue> 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<Long, TableValue> 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<TableValue> 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<TableValue> 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();
}
}
}

View file

@ -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<Map<Long, T
private final TableContext tableContext;
private final Map<Long, TableValue> rowValues;
private final int listIndex;
private final String rowGroupId;
public TableRowFormBuilder(
final TableContext tableContext,
@ -49,6 +50,18 @@ public class TableRowFormBuilder implements ModalInputDialogComposer<Map<Long, T
this.tableContext = tableContext;
this.rowValues = rowValues;
this.listIndex = listIndex;
this.rowGroupId = null;
}
public TableRowFormBuilder(
final TableContext tableContext,
final Map<Long, TableValue> 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<Map<Long, T
false);
final List<InputField> 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<Map<Long, T
attribute,
this.tableContext.getViewContext());
if (attribute.type == AttributeType.TABLE) {
((TableInputField) inputField).initValue(new ArrayList<>(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);

View file

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

View file

@ -96,10 +96,6 @@ public final class ViewContext {
public View getView() {
return this.view;
}
//
// public AttributeMapping getAttributeMapping() {
// return this.attributeMapping;
// }
public Collection<ConfigurationAttribute> getChildAttributes(final Long id) {
return this.attributeMapping.childAttributeMapping.get(id);

View file

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

View file

@ -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)) {

View file

@ -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)) {

View file

@ -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)) {

View file

@ -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)) {

View file

@ -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<String, Tuple<String>> 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<String> 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);
}
}
}
}

View file

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

View file

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

View file

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

View file

@ -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) {

View file

@ -308,7 +308,8 @@ public class EntityTable<ROW extends Entity> {
// TODO error handling
});
this.composite.layout(true, true);
this.composite.getParent().layout(true, true);
PageService.updateScrolledComposite(this.composite);
}
private Page<ROW> createTableRowsFromPage(final Page<ROW> page) {

View file

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

View file

@ -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;

View file

@ -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<Entry> 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);

View file

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

View file

@ -230,12 +230,6 @@ public class PaginationServiceImpl implements PaginationService {
// Exam Table
final Map<String, String> 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());

View file

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

View file

@ -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

View file

@ -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<Long, ConfigurationAttributeRecord> attributeMap = this.configurationAttributeRecordMapper
.selectByExample()
.where(
ConfigurationAttributeRecordDynamicSqlSupport.parentId,
isEqualTo(attributeRecord.getId()))
.build()
.execute()
.stream()
.collect(Collectors.toMap(rec -> rec.getId(), Function.identity()));
final List<Long> 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<Long, ConfigurationAttributeRecord> attributeMap =
this.configurationAttributeRecordMapper
.selectByExample()
.where(
ConfigurationAttributeRecordDynamicSqlSupport.parentId,
isEqualTo(attributeRecord.getId()))
.build()
.execute()
.stream()
.collect(Collectors.toMap(rec -> rec.getId(), Function.identity()));
final List<Long> 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<Long> 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<ConfigurationAttributeRecord> attributeRecord(final ConfigurationValue value) {
return attributeRecordById(value.attributeId);
}

View file

@ -16,39 +16,28 @@ import ch.ethz.seb.sebserver.gbl.util.Result;
public interface SebClientConfigService {
static String SEB_CLIENT_CONFIG_EXAMPLE_XML =
"<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n" +
"<!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">"
"<!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\r\n"
+
"<plist version=\"1.0\">" +
"<dict>" +
"<key>sebMode</key>" +
"<integer>1</integer>" +
"<key>sebServerFallback</key>" +
"<true />" +
"<key>sebServerURL</key>" +
"<string>%s</string>" +
"<key>sebServerConfiguration</key>" +
"<array>" +
"<dict>" +
"<key>institution</key>" +
"<string>%s</string>" +
"<key>clientName</key>" +
"<string>%s</string>" +
"<key>clientSecret</key>" +
"<string>%s</string>" +
"<key>accessTokenEndpoint</key>" +
"<string>%s</string>" +
"<key>handshakeEndpoint</key>" +
"<string>%s</string>" +
"<key>examConfigEndpoint</key>" +
"<string>%s</string>" +
"<key>pingEndpoint</key>" +
"<string>%s</string>" +
"<key>eventEndpoint</key>" +
"<string>%s</string>" +
"</dict>" +
"</array>" +
"</dict>" +
"<plist version=\"1.0\">\r\n" +
" <dict>\r\n" +
" <key>sebMode</key>\r\n" +
" <integer>1</integer>\r\n" +
" <key>sebServerFallback</key>\r\n" +
" <true />\r\n" +
" <key>sebServerURL</key>\r\n" +
" <string>%s</string>\r\n" +
" <key>sebServerConfiguration</key>\r\n" +
" <dict>\r\n" +
" <key>institution</key>\r\n" +
" <string>%s</string>\r\n" +
" <key>clientName</key>\r\n" +
" <string>%s</string>\r\n" +
" <key>clientSecret</key>\r\n" +
" <string>%s</string>\r\n" +
" <key>apiDiscovery</key>\r\n" +
" <string>%s</string>\r\n" +
" </dict>\r\n" +
" </dict>\r\n" +
"</plist>";
boolean hasSebClientConfigurationForInstitution(Long institutionId);

View file

@ -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;

View file

@ -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<Ex
Collections.reverse(exams);
}
final int start = (pageNum - 1) * pSize;
int end = start + pageSize;
if (exams.size() < end) {
end = exams.size();
}
return new Page<>(
exams.size() / pSize,
pageNum,
sort,
exams.subList(pageNum * pSize, pageNum * pSize + pSize));
exams.subList(start, end));
}
}

View file

@ -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

View file

@ -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

View file

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

View file

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