From da0d56baee84f13787c0949dc7967ff617164430 Mon Sep 17 00:00:00 2001 From: anhefti Date: Mon, 22 Jul 2019 12:36:54 +0200 Subject: [PATCH] SEBSERV-50 adapt normal form error handling to exam form error handling --- .../gui/content/activity/ActivitiesPane.java | 6 +- .../ch/ethz/seb/sebserver/gui/form/Form.java | 113 +++++++++++------- .../seb/sebserver/gui/form/FormBuilder.java | 1 + .../gui/form/ImageUploadFieldBuilder.java | 13 +- .../gui/form/SelectionFieldBuilder.java | 10 +- .../sebserver/gui/form/TextFieldBuilder.java | 19 +-- .../gui/form/ThresholdListBuilder.java | 11 +- .../service/examconfig/InputFieldBuilder.java | 11 -- .../examconfig/impl/PassworFieldBuilder.java | 3 +- .../impl/SingleSelectionFieldBuilder.java | 3 +- .../examconfig/impl/TextFieldBuilder.java | 3 +- .../seb/sebserver/gui/widget/ImageUpload.java | 47 +++++++- .../sebserver/gui/widget/WidgetFactory.java | 9 +- .../weblayer/api/ClientEventController.java | 4 - src/main/resources/messages.properties | 1 + 15 files changed, 172 insertions(+), 82 deletions(-) diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/content/activity/ActivitiesPane.java b/src/main/java/ch/ethz/seb/sebserver/gui/content/activity/ActivitiesPane.java index 70d3aeb8..e72f7078 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/content/activity/ActivitiesPane.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/content/activity/ActivitiesPane.java @@ -107,8 +107,10 @@ public class ActivitiesPane implements TemplateComposer { } // User Account - // if current user has base or institutional read privilege for User Account, show list - if (this.currentUser.hasInstitutionalPrivilege(PrivilegeType.READ, EntityType.USER)) { + // if current user has role seb-server admin or institutional-admin, show list + if (this.currentUser.get().hasRole(UserRole.SEB_SERVER_ADMIN) || + this.currentUser.get().hasRole(UserRole.INSTITUTIONAL_ADMIN)) { + final TreeItem userAccounts = this.widgetFactory.treeItemLocalized( navigation, ActivityDefinition.USER_ACCOUNT.displayName); diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/form/Form.java b/src/main/java/ch/ethz/seb/sebserver/gui/form/Form.java index dac11754..e650fc6b 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/form/Form.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/form/Form.java @@ -20,6 +20,10 @@ import java.util.function.Predicate; import org.apache.commons.lang3.StringUtils; 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.Label; 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.Type; import ch.ethz.seb.sebserver.gui.widget.ThresholdList; +import ch.ethz.seb.sebserver.gui.widget.WidgetFactory.CustomVariant; public final class Form implements FormBinding { @@ -112,35 +117,28 @@ public final class Form implements FormBinding { 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)); return this; } - public Form putField(final String name, final Label label, final Text field) { - this.formFields.add(name, createAccessor(label, field)); + Form putField(final String name, final Label label, final Text field, final Label errorLabel) { + this.formFields.add(name, createAccessor(label, field, errorLabel)); return this; } - public void putField(final String name, final Label label, final Selection field) { - this.formFields.add(name, createAccessor(label, field)); + void putField(final String name, final Label label, final Selection field, final Label errorLabel) { + this.formFields.add(name, createAccessor(label, field, errorLabel)); } - public void putField(final String name, final Label label, final ThresholdList field) { - this.formFields.add(name, createAccessor(label, field)); + void putField(final String name, final Label label, final ThresholdList field, final Label errorLabel) { + this.formFields.add(name, createAccessor(label, field, errorLabel)); } - public void putField( - final String name, - final Label label, - final Selection field, - final BiConsumer, 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)); + void putField(final String name, final Label label, final ImageUpload imageUpload, final Label errorLabel) { + final FormFieldAccessor createAccessor = createAccessor(label, imageUpload, errorLabel); + imageUpload.setErrorHandler(createAccessor::setError); + this.formFields.add(name, createAccessor); } public String getFieldValue(final String attributeName) { @@ -224,41 +222,43 @@ public final class Form implements FormBinding { // following are FormFieldAccessor implementations for all field types //@formatter:off 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 void setStringValue(final String value) { field.setText( (value == null) ? StringUtils.EMPTY : value); } }; } - private FormFieldAccessor createAccessor(final Label label, final Text text) { - return new FormFieldAccessor(label, text) { + private FormFieldAccessor createAccessor(final Label label, final Text text, final Label errorLabel) { + return new FormFieldAccessor(label, text, errorLabel) { @Override public String getStringValue() { return text.getText(); } @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()) { case MULTI: case MULTI_COMBO: - return createAccessor(label, selection, Form::adaptCommaSeparatedStringToJsonArray); - default : return createAccessor(label, selection, null); + return createAccessor(label, selection, Form::adaptCommaSeparatedStringToJsonArray, errorLabel); + default : return createAccessor(label, selection, null, null); } } private FormFieldAccessor createAccessor( final Label label, final Selection selection, - final BiConsumer, ObjectNode> jsonValueAdapter) { + final BiConsumer, ObjectNode> jsonValueAdapter, + final Label errorLabel) { return new FormFieldAccessor( label, selection.adaptToControl(), jsonValueAdapter, - selection.type() != Type.SINGLE) { + selection.type() != Type.SINGLE, + errorLabel) { @Override public String getStringValue() { return selection.getSelectionValue(); } @Override public void setStringValue(final String value) { selection.select(value); } }; } - private FormFieldAccessor createAccessor(final Label label, final ThresholdList thresholdList) { - return new FormFieldAccessor(label, thresholdList, null, true) { + private FormFieldAccessor createAccessor(final Label label, final ThresholdList thresholdList, final Label errorLabel) { + return new FormFieldAccessor(label, thresholdList, null, true, errorLabel) { @Override public String getStringValue() { return ThresholdListBuilder .thresholdsToFormURLEncodedStringValue(thresholdList.getThresholds()); @@ -275,8 +275,8 @@ public final class Form implements FormBinding { } }; } - private FormFieldAccessor createAccessor(final Label label, final ImageUpload imageUpload) { - return new FormFieldAccessor(label, imageUpload) { + private FormFieldAccessor createAccessor(final Label label, final ImageUpload imageUpload, final Label errorLabel) { + return new FormFieldAccessor(label, imageUpload, errorLabel) { @Override public String getStringValue() { return imageUpload.getImageBase64(); } }; } @@ -347,22 +347,25 @@ public final class Form implements FormBinding { public final Label label; public final Control control; + private final Label errorLabel; private final BiConsumer, ObjectNode> jsonValueAdapter; private boolean hasError; private final boolean listValue; - FormFieldAccessor(final Label label, final Control control) { - this(label, control, null, false); + FormFieldAccessor(final Label label, final Control control, final Label errorLabel) { + this(label, control, null, false, errorLabel); } FormFieldAccessor( final Label label, final Control control, final BiConsumer, ObjectNode> jsonValueAdapter, - final boolean listValue) { + final boolean listValue, + final Label errorLabel) { this.label = label; this.control = control; + this.errorLabel = errorLabel; if (jsonValueAdapter != null) { this.jsonValueAdapter = jsonValueAdapter; } else { @@ -390,21 +393,51 @@ public final class Form implements FormBinding { 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) { - this.control.setData(RWT.CUSTOM_VARIANT, "error"); - this.control.setToolTipText(errorTooltip); - this.hasError = true; + this.errorLabel.setText(errorMessage); + this.errorLabel.setVisible(true); } } public void resetError() { + if (this.errorLabel == null) { + return; + } + if (this.hasError) { - this.control.setData(RWT.CUSTOM_VARIANT, null); - this.control.setToolTipText(null); - this.hasError = false; + this.errorLabel.setVisible(false); + this.errorLabel.setText(""); } } } + 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; + } + } diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/form/FormBuilder.java b/src/main/java/ch/ethz/seb/sebserver/gui/form/FormBuilder.java index 38c67bc2..a2db1888 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/form/FormBuilder.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/form/FormBuilder.java @@ -248,6 +248,7 @@ public class FormBuilder { final Label label = this.widgetFactory.labelLocalized(parent, locTextKey); final GridData gridData = new GridData(SWT.LEFT, SWT.TOP, true, false, hspan, 1); gridData.verticalIndent = 4; + gridData.heightHint = 20; label.setLayoutData(gridData); label.setData(RWT.CUSTOM_VARIANT, CustomVariant.TITLE_LABEL.key); return label; diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/form/ImageUploadFieldBuilder.java b/src/main/java/ch/ethz/seb/sebserver/gui/form/ImageUploadFieldBuilder.java index d559e453..79eb6a80 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/form/ImageUploadFieldBuilder.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/form/ImageUploadFieldBuilder.java @@ -10,6 +10,7 @@ package ch.ethz.seb.sebserver.gui.form; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Label; import ch.ethz.seb.sebserver.gui.service.i18n.LocTextKey; @@ -23,15 +24,19 @@ public final class ImageUploadFieldBuilder extends FieldBuilder { @Override 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( - builder.formParent, + fieldGrid, new LocTextKey("sebserver.overall.upload"), 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.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); } diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/form/SelectionFieldBuilder.java b/src/main/java/ch/ethz/seb/sebserver/gui/form/SelectionFieldBuilder.java index fc12e403..a85f7442 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/form/SelectionFieldBuilder.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/form/SelectionFieldBuilder.java @@ -65,19 +65,23 @@ public final class SelectionFieldBuilder extends FieldBuilder { } 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 Selection selection = builder.widgetFactory.selectionLocalized( this.type, - builder.formParent, + fieldGrid, this.itemsSupplier, null, null, 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); 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) { ((Control) selection).addListener(SWT.Selection, e -> { diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/form/TextFieldBuilder.java b/src/main/java/ch/ethz/seb/sebserver/gui/form/TextFieldBuilder.java index 2157d1fb..2e728c45 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/form/TextFieldBuilder.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/form/TextFieldBuilder.java @@ -10,6 +10,7 @@ package ch.ethz.seb.sebserver.gui.form; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Text; @@ -52,13 +53,15 @@ public final class TextFieldBuilder extends FieldBuilder { builder.valueLabel(builder.formParent, this.value, this.spanInput)); builder.setFieldVisible(this.visible, this.name); } 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) { gridData.heightHint = 50; } @@ -66,7 +69,9 @@ public final class TextFieldBuilder extends FieldBuilder { if (this.value != null) { 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); } } diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/form/ThresholdListBuilder.java b/src/main/java/ch/ethz/seb/sebserver/gui/form/ThresholdListBuilder.java index cb019c96..ed9b1707 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/form/ThresholdListBuilder.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/form/ThresholdListBuilder.java @@ -14,6 +14,7 @@ import java.util.stream.Collectors; import org.apache.commons.lang3.StringUtils; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Label; import ch.ethz.seb.sebserver.gbl.Constants; @@ -39,13 +40,17 @@ public class ThresholdListBuilder extends FieldBuilder> { // TODO do we need a read-only view for this? return; } else { + + final Composite fieldGrid = Form.createFieldGrid(builder.formParent, this.spanInput); final ThresholdList thresholdList = builder.widgetFactory.thresholdList( - builder.formParent, + fieldGrid, 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); - 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); } diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/InputFieldBuilder.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/InputFieldBuilder.java index 8a839238..a777c6da 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/InputFieldBuilder.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/InputFieldBuilder.java @@ -9,18 +9,15 @@ 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; import org.eclipse.swt.layout.GridLayout; 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.Orientation; 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.widget.WidgetFactory.CustomVariant; public interface InputFieldBuilder { @@ -84,12 +81,4 @@ public interface InputFieldBuilder { 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; - } - } diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/impl/PassworFieldBuilder.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/impl/PassworFieldBuilder.java index 2706c9ef..7bb21176 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/impl/PassworFieldBuilder.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/impl/PassworFieldBuilder.java @@ -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.Orientation; 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.InputFieldBuilder; import ch.ethz.seb.sebserver.gui.service.i18n.LocTextKey; @@ -77,7 +78,7 @@ public class PassworFieldBuilder implements InputFieldBuilder { orientation, passwordInput, confirmInput, - InputFieldBuilder.createErrorLabel(innerGrid)); + Form.createErrorLabel(innerGrid)); final Listener valueChangeEventListener = event -> { passwordInputField.clearError(); diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/impl/SingleSelectionFieldBuilder.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/impl/SingleSelectionFieldBuilder.java index 6b86751b..d876f4ae 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/impl/SingleSelectionFieldBuilder.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/impl/SingleSelectionFieldBuilder.java @@ -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.Orientation; 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.InputField; import ch.ethz.seb.sebserver.gui.service.examconfig.InputFieldBuilder; @@ -73,7 +74,7 @@ public class SingleSelectionFieldBuilder extends SelectionFieldBuilder implement attribute, orientation, selection, - InputFieldBuilder.createErrorLabel(innerGrid)); + Form.createErrorLabel(innerGrid)); selection.setSelectionListener(event -> { singleSelectionInputField.clearError(); diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/impl/TextFieldBuilder.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/impl/TextFieldBuilder.java index 72151667..039d2007 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/impl/TextFieldBuilder.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/impl/TextFieldBuilder.java @@ -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.Orientation; 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.InputField; import ch.ethz.seb.sebserver.gui.service.examconfig.InputFieldBuilder; @@ -97,7 +98,7 @@ public class TextFieldBuilder implements InputFieldBuilder { attribute, orientation, text, - InputFieldBuilder.createErrorLabel(innerGrid)); + Form.createErrorLabel(innerGrid)); final Listener valueChangeEventListener = event -> { textInputField.clearError(); diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/widget/ImageUpload.java b/src/main/java/ch/ethz/seb/sebserver/gui/widget/ImageUpload.java index 3b8da299..fdd40a7f 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/widget/ImageUpload.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/widget/ImageUpload.java @@ -12,7 +12,12 @@ import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.nio.charset.StandardCharsets; +import java.util.Arrays; 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.io.IOUtils; @@ -33,24 +38,33 @@ import org.eclipse.swt.widgets.Composite; import org.slf4j.Logger; 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.ServerPushService; public final class ImageUpload extends Composite { private static final long serialVersionUID = 368264811155804533L; - private static final Logger log = LoggerFactory.getLogger(ImageUpload.class); - private transient final ServerPushService serverPushService; + public static final Set SUPPORTED_IMAGE_FILES = Collections.unmodifiableSet(new HashSet<>(Arrays.asList( + ".png"))); + + private final ServerPushService serverPushService; private final Composite imageCanvas; private final FileUpload fileUpload; + private Consumer errorHandler; private String imageBase64 = null; private boolean loadNewImage = 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.setLayout(new GridLayout(1, false)); @@ -87,6 +101,19 @@ public final class ImageUpload extends Composite { @Override 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.imageLoaded = false; ImageUpload.this.fileUpload.submit(uploadHandler.getUploadUrl()); @@ -96,6 +123,7 @@ public final class ImageUpload extends Composite { ImageUpload::wait, ImageUpload::update); } + }); } else { this.fileUpload = null; @@ -107,6 +135,10 @@ public final class ImageUpload extends Composite { } + public void setErrorHandler(final Consumer errorHandler) { + this.errorHandler = errorHandler; + } + public void setSelectionText(final String text) { if (this.fileUpload != null) { this.fileUpload.setToolTipText(text); @@ -158,6 +190,7 @@ public final class ImageUpload extends Composite { context.layout(); imageUpload.layout(); 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)); } + private static boolean fileSupported(final String fileName) { + return SUPPORTED_IMAGE_FILES + .stream() + .filter(fileType -> fileName.endsWith(fileType)) + .findFirst() + .isPresent(); + } + } diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/widget/WidgetFactory.java b/src/main/java/ch/ethz/seb/sebserver/gui/widget/WidgetFactory.java index 213a511c..bc8832da 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/widget/WidgetFactory.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/widget/WidgetFactory.java @@ -183,7 +183,7 @@ public class WidgetFactory { final Composite grid = new Composite(parent, SWT.NONE); final GridLayout layout = new GridLayout(rows, true); layout.horizontalSpacing = 10; - layout.verticalSpacing = 10; + //layout.verticalSpacing = 10; layout.marginBottom = 50; layout.marginLeft = 10; layout.marginTop = 0; @@ -534,7 +534,12 @@ public class WidgetFactory { final LocTextKey locTextKey, 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); return imageUpload; } diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ClientEventController.java b/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ClientEventController.java index c9b1e1bf..b63dc846 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ClientEventController.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ClientEventController.java @@ -146,8 +146,4 @@ public class ClientEventController extends EntityController