SEBSERV-50 adapt normal form error handling to exam form error handling

This commit is contained in:
anhefti 2019-07-22 12:36:54 +02:00
parent ba49611c1c
commit da0d56baee
15 changed files with 172 additions and 82 deletions

View file

@ -107,8 +107,10 @@ public class ActivitiesPane implements TemplateComposer {
} }
// User Account // User Account
// if current user has base or institutional read privilege for User Account, show list // if current user has role seb-server admin or institutional-admin, show list
if (this.currentUser.hasInstitutionalPrivilege(PrivilegeType.READ, EntityType.USER)) { if (this.currentUser.get().hasRole(UserRole.SEB_SERVER_ADMIN) ||
this.currentUser.get().hasRole(UserRole.INSTITUTIONAL_ADMIN)) {
final TreeItem userAccounts = this.widgetFactory.treeItemLocalized( final TreeItem userAccounts = this.widgetFactory.treeItemLocalized(
navigation, navigation,
ActivityDefinition.USER_ACCOUNT.displayName); ActivityDefinition.USER_ACCOUNT.displayName);

View file

@ -20,6 +20,10 @@ import java.util.function.Predicate;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.eclipse.rap.rwt.RWT; import org.eclipse.rap.rwt.RWT;
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.Control; import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text; import org.eclipse.swt.widgets.Text;
@ -39,6 +43,7 @@ import ch.ethz.seb.sebserver.gui.widget.ImageUpload;
import ch.ethz.seb.sebserver.gui.widget.Selection; import ch.ethz.seb.sebserver.gui.widget.Selection;
import ch.ethz.seb.sebserver.gui.widget.Selection.Type; import ch.ethz.seb.sebserver.gui.widget.Selection.Type;
import ch.ethz.seb.sebserver.gui.widget.ThresholdList; import ch.ethz.seb.sebserver.gui.widget.ThresholdList;
import ch.ethz.seb.sebserver.gui.widget.WidgetFactory.CustomVariant;
public final class Form implements FormBinding { public final class Form implements FormBinding {
@ -112,35 +117,28 @@ public final class Form implements FormBinding {
return !this.formFields.isEmpty(); return !this.formFields.isEmpty();
} }
public Form putField(final String name, final Label label, final Label field) { Form putField(final String name, final Label label, final Label field) {
this.formFields.add(name, createAccessor(label, field)); this.formFields.add(name, createAccessor(label, field));
return this; return this;
} }
public Form putField(final String name, final Label label, final Text field) { Form putField(final String name, final Label label, final Text field, final Label errorLabel) {
this.formFields.add(name, createAccessor(label, field)); this.formFields.add(name, createAccessor(label, field, errorLabel));
return this; return this;
} }
public void putField(final String name, final Label label, final Selection field) { void putField(final String name, final Label label, final Selection field, final Label errorLabel) {
this.formFields.add(name, createAccessor(label, field)); this.formFields.add(name, createAccessor(label, field, errorLabel));
} }
public void putField(final String name, final Label label, final ThresholdList field) { void putField(final String name, final Label label, final ThresholdList field, final Label errorLabel) {
this.formFields.add(name, createAccessor(label, field)); this.formFields.add(name, createAccessor(label, field, errorLabel));
} }
public void putField( void putField(final String name, final Label label, final ImageUpload imageUpload, final Label errorLabel) {
final String name, final FormFieldAccessor createAccessor = createAccessor(label, imageUpload, errorLabel);
final Label label, imageUpload.setErrorHandler(createAccessor::setError);
final Selection field, this.formFields.add(name, createAccessor);
final BiConsumer<Tuple<String>, ObjectNode> jsonValueAdapter) {
this.formFields.add(name, createAccessor(label, field, jsonValueAdapter));
}
public void putField(final String name, final Label label, final ImageUpload imageUpload) {
this.formFields.add(name, createAccessor(label, imageUpload));
} }
public String getFieldValue(final String attributeName) { public String getFieldValue(final String attributeName) {
@ -224,41 +222,43 @@ public final class Form implements FormBinding {
// following are FormFieldAccessor implementations for all field types // following are FormFieldAccessor implementations for all field types
//@formatter:off //@formatter:off
private FormFieldAccessor createAccessor(final Label label, final Label field) { private FormFieldAccessor createAccessor(final Label label, final Label field) {
return new FormFieldAccessor(label, field) { return new FormFieldAccessor(label, field, null) {
@Override public String getStringValue() { return null; } @Override public String getStringValue() { return null; }
@Override public void setStringValue(final String value) { field.setText( (value == null) ? StringUtils.EMPTY : value); } @Override public void setStringValue(final String value) { field.setText( (value == null) ? StringUtils.EMPTY : value); }
}; };
} }
private FormFieldAccessor createAccessor(final Label label, final Text text) { private FormFieldAccessor createAccessor(final Label label, final Text text, final Label errorLabel) {
return new FormFieldAccessor(label, text) { return new FormFieldAccessor(label, text, errorLabel) {
@Override public String getStringValue() { return text.getText(); } @Override public String getStringValue() { return text.getText(); }
@Override public void setStringValue(final String value) { text.setText( (value == null) ? StringUtils.EMPTY : value); } @Override public void setStringValue(final String value) { text.setText( (value == null) ? StringUtils.EMPTY : value); }
}; };
} }
private FormFieldAccessor createAccessor(final Label label, final Selection selection) { private FormFieldAccessor createAccessor(final Label label, final Selection selection, final Label errorLabel) {
switch (selection.type()) { switch (selection.type()) {
case MULTI: case MULTI:
case MULTI_COMBO: case MULTI_COMBO:
return createAccessor(label, selection, Form::adaptCommaSeparatedStringToJsonArray); return createAccessor(label, selection, Form::adaptCommaSeparatedStringToJsonArray, errorLabel);
default : return createAccessor(label, selection, null); default : return createAccessor(label, selection, null, null);
} }
} }
private FormFieldAccessor createAccessor( private FormFieldAccessor createAccessor(
final Label label, final Label label,
final Selection selection, final Selection selection,
final BiConsumer<Tuple<String>, ObjectNode> jsonValueAdapter) { final BiConsumer<Tuple<String>, ObjectNode> jsonValueAdapter,
final Label errorLabel) {
return new FormFieldAccessor( return new FormFieldAccessor(
label, label,
selection.adaptToControl(), selection.adaptToControl(),
jsonValueAdapter, jsonValueAdapter,
selection.type() != Type.SINGLE) { selection.type() != Type.SINGLE,
errorLabel) {
@Override public String getStringValue() { return selection.getSelectionValue(); } @Override public String getStringValue() { return selection.getSelectionValue(); }
@Override public void setStringValue(final String value) { selection.select(value); } @Override public void setStringValue(final String value) { selection.select(value); }
}; };
} }
private FormFieldAccessor createAccessor(final Label label, final ThresholdList thresholdList) { private FormFieldAccessor createAccessor(final Label label, final ThresholdList thresholdList, final Label errorLabel) {
return new FormFieldAccessor(label, thresholdList, null, true) { return new FormFieldAccessor(label, thresholdList, null, true, errorLabel) {
@Override public String getStringValue() { @Override public String getStringValue() {
return ThresholdListBuilder return ThresholdListBuilder
.thresholdsToFormURLEncodedStringValue(thresholdList.getThresholds()); .thresholdsToFormURLEncodedStringValue(thresholdList.getThresholds());
@ -275,8 +275,8 @@ public final class Form implements FormBinding {
} }
}; };
} }
private FormFieldAccessor createAccessor(final Label label, final ImageUpload imageUpload) { private FormFieldAccessor createAccessor(final Label label, final ImageUpload imageUpload, final Label errorLabel) {
return new FormFieldAccessor(label, imageUpload) { return new FormFieldAccessor(label, imageUpload, errorLabel) {
@Override public String getStringValue() { return imageUpload.getImageBase64(); } @Override public String getStringValue() { return imageUpload.getImageBase64(); }
}; };
} }
@ -347,22 +347,25 @@ public final class Form implements FormBinding {
public final Label label; public final Label label;
public final Control control; public final Control control;
private final Label errorLabel;
private final BiConsumer<Tuple<String>, ObjectNode> jsonValueAdapter; private final BiConsumer<Tuple<String>, ObjectNode> jsonValueAdapter;
private boolean hasError; private boolean hasError;
private final boolean listValue; private final boolean listValue;
FormFieldAccessor(final Label label, final Control control) { FormFieldAccessor(final Label label, final Control control, final Label errorLabel) {
this(label, control, null, false); this(label, control, null, false, errorLabel);
} }
FormFieldAccessor( FormFieldAccessor(
final Label label, final Label label,
final Control control, final Control control,
final BiConsumer<Tuple<String>, ObjectNode> jsonValueAdapter, final BiConsumer<Tuple<String>, ObjectNode> jsonValueAdapter,
final boolean listValue) { final boolean listValue,
final Label errorLabel) {
this.label = label; this.label = label;
this.control = control; this.control = control;
this.errorLabel = errorLabel;
if (jsonValueAdapter != null) { if (jsonValueAdapter != null) {
this.jsonValueAdapter = jsonValueAdapter; this.jsonValueAdapter = jsonValueAdapter;
} else { } else {
@ -390,21 +393,51 @@ public final class Form implements FormBinding {
this.jsonValueAdapter.accept(new Tuple<>(key, getStringValue()), objectRoot); this.jsonValueAdapter.accept(new Tuple<>(key, getStringValue()), objectRoot);
} }
public void setError(final String errorTooltip) { public void setError(final String errorMessage) {
if (this.errorLabel == null) {
return;
}
if (!this.hasError) { if (!this.hasError) {
this.control.setData(RWT.CUSTOM_VARIANT, "error"); this.errorLabel.setText(errorMessage);
this.control.setToolTipText(errorTooltip); this.errorLabel.setVisible(true);
this.hasError = true;
} }
} }
public void resetError() { public void resetError() {
if (this.errorLabel == null) {
return;
}
if (this.hasError) { if (this.hasError) {
this.control.setData(RWT.CUSTOM_VARIANT, null); this.errorLabel.setVisible(false);
this.control.setToolTipText(null); this.errorLabel.setText("");
this.hasError = false;
} }
} }
} }
public static Composite createFieldGrid(final Composite parent, final int hspan) {
final Composite fieldGrid = new Composite(parent, SWT.NONE);
final GridLayout gridLayout = new GridLayout();
gridLayout.verticalSpacing = 0;
gridLayout.marginHeight = 1;
gridLayout.marginWidth = 0;
gridLayout.marginRight = 5;
fieldGrid.setLayout(gridLayout);
final GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, false);
gridData.horizontalSpan = hspan;
fieldGrid.setLayoutData(gridData);
return fieldGrid;
}
public static Label createErrorLabel(final Composite innerGrid) {
final Label errorLabel = new Label(innerGrid, SWT.NONE);
errorLabel.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
errorLabel.setVisible(false);
errorLabel.setData(RWT.CUSTOM_VARIANT, CustomVariant.ERROR.key);
return errorLabel;
}
} }

View file

@ -248,6 +248,7 @@ public class FormBuilder {
final Label label = this.widgetFactory.labelLocalized(parent, locTextKey); final Label label = this.widgetFactory.labelLocalized(parent, locTextKey);
final GridData gridData = new GridData(SWT.LEFT, SWT.TOP, true, false, hspan, 1); final GridData gridData = new GridData(SWT.LEFT, SWT.TOP, true, false, hspan, 1);
gridData.verticalIndent = 4; gridData.verticalIndent = 4;
gridData.heightHint = 20;
label.setLayoutData(gridData); label.setLayoutData(gridData);
label.setData(RWT.CUSTOM_VARIANT, CustomVariant.TITLE_LABEL.key); label.setData(RWT.CUSTOM_VARIANT, CustomVariant.TITLE_LABEL.key);
return label; return label;

View file

@ -10,6 +10,7 @@ package ch.ethz.seb.sebserver.gui.form;
import org.eclipse.swt.SWT; import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Label;
import ch.ethz.seb.sebserver.gui.service.i18n.LocTextKey; import ch.ethz.seb.sebserver.gui.service.i18n.LocTextKey;
@ -23,15 +24,19 @@ public final class ImageUploadFieldBuilder extends FieldBuilder<String> {
@Override @Override
void build(final FormBuilder builder) { void build(final FormBuilder builder) {
final Label lab = builder.labelLocalized(builder.formParent, this.label, this.spanLabel);
final Label lab = builder.labelLocalized(builder.formParent, this.label, 1);
final Composite fieldGrid = Form.createFieldGrid(builder.formParent, this.spanInput);
final ImageUpload imageUpload = builder.widgetFactory.imageUploadLocalized( final ImageUpload imageUpload = builder.widgetFactory.imageUploadLocalized(
builder.formParent, fieldGrid,
new LocTextKey("sebserver.overall.upload"), new LocTextKey("sebserver.overall.upload"),
builder.readonly || this.readonly); builder.readonly || this.readonly);
final GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, false, this.spanInput, 1); final GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, false);
imageUpload.setLayoutData(gridData); imageUpload.setLayoutData(gridData);
imageUpload.setImageBase64(this.value); imageUpload.setImageBase64(this.value);
builder.form.putField(this.name, lab, imageUpload);
final Label errorLabel = Form.createErrorLabel(fieldGrid);
builder.form.putField(this.name, lab, imageUpload, errorLabel);
builder.setFieldVisible(this.visible, this.name); builder.setFieldVisible(this.visible, this.name);
} }

View file

@ -65,19 +65,23 @@ public final class SelectionFieldBuilder extends FieldBuilder<String> {
} }
private void buildInput(final FormBuilder builder, final Label lab) { private void buildInput(final FormBuilder builder, final Label lab) {
final Composite fieldGrid = Form.createFieldGrid(builder.formParent, this.spanInput);
final String actionKey = (this.label != null) ? this.label.name + ".action" : null; final String actionKey = (this.label != null) ? this.label.name + ".action" : null;
final Selection selection = builder.widgetFactory.selectionLocalized( final Selection selection = builder.widgetFactory.selectionLocalized(
this.type, this.type,
builder.formParent, fieldGrid,
this.itemsSupplier, this.itemsSupplier,
null, null,
null, null,
actionKey); actionKey);
final GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, false, this.spanInput, 1); final GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, false);
((Control) selection).setLayoutData(gridData); ((Control) selection).setLayoutData(gridData);
selection.select(this.value); selection.select(this.value);
builder.form.putField(this.name, lab, selection);
final Label errorLabel = Form.createErrorLabel(fieldGrid);
builder.form.putField(this.name, lab, selection, errorLabel);
if (this.selectionListener != null) { if (this.selectionListener != null) {
((Control) selection).addListener(SWT.Selection, e -> { ((Control) selection).addListener(SWT.Selection, e -> {

View file

@ -10,6 +10,7 @@ package ch.ethz.seb.sebserver.gui.form;
import org.eclipse.swt.SWT; import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text; import org.eclipse.swt.widgets.Text;
@ -52,13 +53,15 @@ public final class TextFieldBuilder extends FieldBuilder<String> {
builder.valueLabel(builder.formParent, this.value, this.spanInput)); builder.valueLabel(builder.formParent, this.value, this.spanInput));
builder.setFieldVisible(this.visible, this.name); builder.setFieldVisible(this.visible, this.name);
} else { } else {
final Text textInput = (this.isNumber)
? builder.widgetFactory.numberInput(builder.formParent, null)
: (this.isArea)
? builder.widgetFactory.textAreaInput(builder.formParent)
: builder.widgetFactory.textInput(builder.formParent, this.isPassword);
final GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, false, this.spanInput, 1); final Composite fieldGrid = Form.createFieldGrid(builder.formParent, this.spanInput);
final Text textInput = (this.isNumber)
? builder.widgetFactory.numberInput(fieldGrid, null)
: (this.isArea)
? builder.widgetFactory.textAreaInput(fieldGrid)
: builder.widgetFactory.textInput(fieldGrid, this.isPassword);
final GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, false);
if (this.isArea) { if (this.isArea) {
gridData.heightHint = 50; gridData.heightHint = 50;
} }
@ -66,7 +69,9 @@ public final class TextFieldBuilder extends FieldBuilder<String> {
if (this.value != null) { if (this.value != null) {
textInput.setText(this.value); textInput.setText(this.value);
} }
builder.form.putField(this.name, lab, textInput);
final Label errorLabel = Form.createErrorLabel(fieldGrid);
builder.form.putField(this.name, lab, textInput, errorLabel);
builder.setFieldVisible(this.visible, this.name); builder.setFieldVisible(this.visible, this.name);
} }
} }

View file

@ -14,6 +14,7 @@ import java.util.stream.Collectors;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.eclipse.swt.SWT; import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Label;
import ch.ethz.seb.sebserver.gbl.Constants; import ch.ethz.seb.sebserver.gbl.Constants;
@ -39,13 +40,17 @@ public class ThresholdListBuilder extends FieldBuilder<Collection<Threshold>> {
// TODO do we need a read-only view for this? // TODO do we need a read-only view for this?
return; return;
} else { } else {
final Composite fieldGrid = Form.createFieldGrid(builder.formParent, this.spanInput);
final ThresholdList thresholdList = builder.widgetFactory.thresholdList( final ThresholdList thresholdList = builder.widgetFactory.thresholdList(
builder.formParent, fieldGrid,
this.value); this.value);
final GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, false, this.spanInput, 1); final GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, false);
thresholdList.setLayoutData(gridData); thresholdList.setLayoutData(gridData);
builder.form.putField(this.name, lab, thresholdList);
final Label errorLabel = Form.createErrorLabel(fieldGrid);
builder.form.putField(this.name, lab, thresholdList, errorLabel);
builder.setFieldVisible(this.visible, this.name); builder.setFieldVisible(this.visible, this.name);
} }

View file

@ -9,18 +9,15 @@
package ch.ethz.seb.sebserver.gui.service.examconfig; package ch.ethz.seb.sebserver.gui.service.examconfig;
import org.apache.commons.lang3.BooleanUtils; import org.apache.commons.lang3.BooleanUtils;
import org.eclipse.rap.rwt.RWT;
import org.eclipse.swt.SWT; import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationAttribute; import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationAttribute;
import ch.ethz.seb.sebserver.gbl.model.sebconfig.Orientation; import ch.ethz.seb.sebserver.gbl.model.sebconfig.Orientation;
import ch.ethz.seb.sebserver.gui.service.examconfig.impl.InputFieldBuilderSupplier; import ch.ethz.seb.sebserver.gui.service.examconfig.impl.InputFieldBuilderSupplier;
import ch.ethz.seb.sebserver.gui.service.examconfig.impl.ViewContext; import ch.ethz.seb.sebserver.gui.service.examconfig.impl.ViewContext;
import ch.ethz.seb.sebserver.gui.widget.WidgetFactory.CustomVariant;
public interface InputFieldBuilder { public interface InputFieldBuilder {
@ -84,12 +81,4 @@ public interface InputFieldBuilder {
attribute)); 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));
errorLabel.setVisible(false);
errorLabel.setData(RWT.CUSTOM_VARIANT, CustomVariant.ERROR.key);
return errorLabel;
}
} }

View file

@ -28,6 +28,7 @@ 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.ConfigurationAttribute;
import ch.ethz.seb.sebserver.gbl.model.sebconfig.Orientation; import ch.ethz.seb.sebserver.gbl.model.sebconfig.Orientation;
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile; import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
import ch.ethz.seb.sebserver.gui.form.Form;
import ch.ethz.seb.sebserver.gui.service.examconfig.InputField; 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.InputFieldBuilder;
import ch.ethz.seb.sebserver.gui.service.i18n.LocTextKey; import ch.ethz.seb.sebserver.gui.service.i18n.LocTextKey;
@ -77,7 +78,7 @@ public class PassworFieldBuilder implements InputFieldBuilder {
orientation, orientation,
passwordInput, passwordInput,
confirmInput, confirmInput,
InputFieldBuilder.createErrorLabel(innerGrid)); Form.createErrorLabel(innerGrid));
final Listener valueChangeEventListener = event -> { final Listener valueChangeEventListener = event -> {
passwordInputField.clearError(); passwordInputField.clearError();

View file

@ -19,6 +19,7 @@ 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.ConfigurationAttribute;
import ch.ethz.seb.sebserver.gbl.model.sebconfig.Orientation; import ch.ethz.seb.sebserver.gbl.model.sebconfig.Orientation;
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile; import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
import ch.ethz.seb.sebserver.gui.form.Form;
import ch.ethz.seb.sebserver.gui.service.examconfig.ExamConfigurationService; 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.InputField;
import ch.ethz.seb.sebserver.gui.service.examconfig.InputFieldBuilder; import ch.ethz.seb.sebserver.gui.service.examconfig.InputFieldBuilder;
@ -73,7 +74,7 @@ public class SingleSelectionFieldBuilder extends SelectionFieldBuilder implement
attribute, attribute,
orientation, orientation,
selection, selection,
InputFieldBuilder.createErrorLabel(innerGrid)); Form.createErrorLabel(innerGrid));
selection.setSelectionListener(event -> { selection.setSelectionListener(event -> {
singleSelectionInputField.clearError(); singleSelectionInputField.clearError();

View file

@ -24,6 +24,7 @@ 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.ConfigurationAttribute;
import ch.ethz.seb.sebserver.gbl.model.sebconfig.Orientation; import ch.ethz.seb.sebserver.gbl.model.sebconfig.Orientation;
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile; import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
import ch.ethz.seb.sebserver.gui.form.Form;
import ch.ethz.seb.sebserver.gui.service.examconfig.ExamConfigurationService; 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.InputField;
import ch.ethz.seb.sebserver.gui.service.examconfig.InputFieldBuilder; import ch.ethz.seb.sebserver.gui.service.examconfig.InputFieldBuilder;
@ -97,7 +98,7 @@ public class TextFieldBuilder implements InputFieldBuilder {
attribute, attribute,
orientation, orientation,
text, text,
InputFieldBuilder.createErrorLabel(innerGrid)); Form.createErrorLabel(innerGrid));
final Listener valueChangeEventListener = event -> { final Listener valueChangeEventListener = event -> {
textInputField.clearError(); textInputField.clearError();

View file

@ -12,7 +12,12 @@ import java.io.ByteArrayInputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Base64; import java.util.Base64;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.function.Consumer;
import org.apache.commons.codec.binary.Base64InputStream; import org.apache.commons.codec.binary.Base64InputStream;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
@ -33,24 +38,33 @@ import org.eclipse.swt.widgets.Composite;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import ch.ethz.seb.sebserver.gui.service.i18n.I18nSupport;
import ch.ethz.seb.sebserver.gui.service.push.ServerPushContext; import ch.ethz.seb.sebserver.gui.service.push.ServerPushContext;
import ch.ethz.seb.sebserver.gui.service.push.ServerPushService; import ch.ethz.seb.sebserver.gui.service.push.ServerPushService;
public final class ImageUpload extends Composite { public final class ImageUpload extends Composite {
private static final long serialVersionUID = 368264811155804533L; private static final long serialVersionUID = 368264811155804533L;
private static final Logger log = LoggerFactory.getLogger(ImageUpload.class); private static final Logger log = LoggerFactory.getLogger(ImageUpload.class);
private transient final ServerPushService serverPushService; public static final Set<String> SUPPORTED_IMAGE_FILES = Collections.unmodifiableSet(new HashSet<>(Arrays.asList(
".png")));
private final ServerPushService serverPushService;
private final Composite imageCanvas; private final Composite imageCanvas;
private final FileUpload fileUpload; private final FileUpload fileUpload;
private Consumer<String> errorHandler;
private String imageBase64 = null; private String imageBase64 = null;
private boolean loadNewImage = false; private boolean loadNewImage = false;
private boolean imageLoaded = false; private boolean imageLoaded = false;
ImageUpload(final Composite parent, final ServerPushService serverPushService, final boolean readonly) { ImageUpload(
final Composite parent,
final ServerPushService serverPushService,
final I18nSupport i18nSupport,
final boolean readonly) {
super(parent, SWT.NONE); super(parent, SWT.NONE);
super.setLayout(new GridLayout(1, false)); super.setLayout(new GridLayout(1, false));
@ -87,6 +101,19 @@ public final class ImageUpload extends Composite {
@Override @Override
public void widgetSelected(final SelectionEvent event) { public void widgetSelected(final SelectionEvent event) {
final String fileName = ImageUpload.this.fileUpload.getFileName();
if (fileName == null || !fileSupported(fileName)) {
if (ImageUpload.this.errorHandler != null) {
final String text = i18nSupport.getText(
"sebserver.institution.form.logoImage.unsupportedFileType",
"Unsupported image file type selected");
ImageUpload.this.errorHandler.accept(text);
}
log.warn("Unsupported image file selected: {}", fileName);
return;
}
ImageUpload.this.loadNewImage = true; ImageUpload.this.loadNewImage = true;
ImageUpload.this.imageLoaded = false; ImageUpload.this.imageLoaded = false;
ImageUpload.this.fileUpload.submit(uploadHandler.getUploadUrl()); ImageUpload.this.fileUpload.submit(uploadHandler.getUploadUrl());
@ -96,6 +123,7 @@ public final class ImageUpload extends Composite {
ImageUpload::wait, ImageUpload::wait,
ImageUpload::update); ImageUpload::update);
} }
}); });
} else { } else {
this.fileUpload = null; this.fileUpload = null;
@ -107,6 +135,10 @@ public final class ImageUpload extends Composite {
} }
public void setErrorHandler(final Consumer<String> errorHandler) {
this.errorHandler = errorHandler;
}
public void setSelectionText(final String text) { public void setSelectionText(final String text) {
if (this.fileUpload != null) { if (this.fileUpload != null) {
this.fileUpload.setToolTipText(text); this.fileUpload.setToolTipText(text);
@ -158,6 +190,7 @@ public final class ImageUpload extends Composite {
context.layout(); context.layout();
imageUpload.layout(); imageUpload.layout();
imageUpload.loadNewImage = false; imageUpload.loadNewImage = false;
imageUpload.errorHandler.accept("");
} }
} }
@ -170,4 +203,12 @@ public final class ImageUpload extends Composite {
imageUpload.imageCanvas.setBackgroundImage(new Image(imageUpload.imageCanvas.getDisplay(), imageData)); imageUpload.imageCanvas.setBackgroundImage(new Image(imageUpload.imageCanvas.getDisplay(), imageData));
} }
private static boolean fileSupported(final String fileName) {
return SUPPORTED_IMAGE_FILES
.stream()
.filter(fileType -> fileName.endsWith(fileType))
.findFirst()
.isPresent();
}
} }

View file

@ -183,7 +183,7 @@ public class WidgetFactory {
final Composite grid = new Composite(parent, SWT.NONE); final Composite grid = new Composite(parent, SWT.NONE);
final GridLayout layout = new GridLayout(rows, true); final GridLayout layout = new GridLayout(rows, true);
layout.horizontalSpacing = 10; layout.horizontalSpacing = 10;
layout.verticalSpacing = 10; //layout.verticalSpacing = 10;
layout.marginBottom = 50; layout.marginBottom = 50;
layout.marginLeft = 10; layout.marginLeft = 10;
layout.marginTop = 0; layout.marginTop = 0;
@ -534,7 +534,12 @@ public class WidgetFactory {
final LocTextKey locTextKey, final LocTextKey locTextKey,
final boolean readonly) { final boolean readonly) {
final ImageUpload imageUpload = new ImageUpload(parent, this.serverPushService, readonly); final ImageUpload imageUpload = new ImageUpload(
parent,
this.serverPushService,
this.i18nSupport,
readonly);
this.polyglotPageService.injectI18n(imageUpload, locTextKey); this.polyglotPageService.injectI18n(imageUpload, locTextKey);
return imageUpload; return imageUpload;
} }

View file

@ -146,8 +146,4 @@ public class ClientEventController extends EntityController<ClientEvent, ClientE
EntityType.CLIENT_EVENT); EntityType.CLIENT_EVENT);
} }
private void noModifyAccess() {
}
} }

View file

@ -101,6 +101,7 @@ sebserver.institution.form.title=Institution
sebserver.institution.form.name=Name sebserver.institution.form.name=Name
sebserver.institution.form.urlSuffix=URL Suffix sebserver.institution.form.urlSuffix=URL Suffix
sebserver.institution.form.logoImage=Logo Image sebserver.institution.form.logoImage=Logo Image
sebserver.institution.form.logoImage.unsupportedFileType=The selected file is not or an unsupported image type
################################ ################################