From 663662d50e314e695503445e868191589569ca32 Mon Sep 17 00:00:00 2001 From: anhefti Date: Mon, 23 Dec 2019 13:21:59 +0100 Subject: [PATCH] info monitoring disable --- .../gbl/model/session/ClientConnection.java | 11 ++ .../gui/content/InstitutionForm.java | 6 +- .../gui/content/MonitoringRunningExam.java | 52 +++++--- .../gui/form/CheckboxFieldBuilder.java | 13 +- .../seb/sebserver/gui/form/FieldBuilder.java | 124 ++++++++++++++++++ .../gui/form/FileUploadFieldBuilder.java | 14 +- .../ch/ethz/seb/sebserver/gui/form/Form.java | 29 ---- .../seb/sebserver/gui/form/FormBuilder.java | 55 +------- .../gui/form/ImageUploadFieldBuilder.java | 14 +- .../gui/form/SelectionFieldBuilder.java | 25 ++-- .../sebserver/gui/form/TextFieldBuilder.java | 20 +-- .../gui/form/ThresholdListBuilder.java | 13 +- .../examconfig/impl/PassworFieldBuilder.java | 4 +- .../impl/SingleSelectionFieldBuilder.java | 4 +- .../examconfig/impl/TextFieldBuilder.java | 4 +- .../service/session/InstructionProcessor.java | 78 +++++++++-- .../sebserver/gui/widget/WidgetFactory.java | 11 +- .../impl/SebClientConnectionServiceImpl.java | 12 +- .../api/ExamMonitoringController.java | 6 +- src/main/resources/messages.properties | 6 +- src/main/resources/static/images/help.png | Bin 0 -> 643 bytes 21 files changed, 309 insertions(+), 192 deletions(-) create mode 100644 src/main/resources/static/images/help.png diff --git a/src/main/java/ch/ethz/seb/sebserver/gbl/model/session/ClientConnection.java b/src/main/java/ch/ethz/seb/sebserver/gbl/model/session/ClientConnection.java index cdb53f36..052e06a8 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gbl/model/session/ClientConnection.java +++ b/src/main/java/ch/ethz/seb/sebserver/gbl/model/session/ClientConnection.java @@ -8,6 +8,7 @@ package ch.ethz.seb.sebserver.gbl.model.session; +import java.util.EnumSet; import java.util.function.Predicate; import com.fasterxml.jackson.annotation.JsonCreator; @@ -234,4 +235,14 @@ public final class ClientConnection implements GrantEntity { return connection -> connection.status == status; } + public static Predicate getStatusPredicate(final ConnectionStatus... status) { + final EnumSet stati = EnumSet.allOf(ConnectionStatus.class); + if (status != null) { + for (int i = 0; i < status.length; i++) { + stati.add(status[i]); + } + } + return connection -> stati.contains(connection.status); + } + } diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/content/InstitutionForm.java b/src/main/java/ch/ethz/seb/sebserver/gui/content/InstitutionForm.java index 6352bf3e..b77ce902 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/content/InstitutionForm.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/content/InstitutionForm.java @@ -110,11 +110,13 @@ public class InstitutionForm implements TemplateComposer { .addField(FormBuilder.text( Domain.INSTITUTION.ATTR_NAME, FORM_NAME_TEXT_KEY, - institution.name)) + institution.name) + .withInfoLeft(new LocTextKey("some info text here!\nwith line brake"))) .addField(FormBuilder.text( Domain.INSTITUTION.ATTR_URL_SUFFIX, FORM_URL_SUFFIX_TEXT_KEY, - institution.urlSuffix)) + institution.urlSuffix) + .withInfoRight(new LocTextKey("some info text here!\nwith line brake"))) .addField(FormBuilder.imageUpload( Domain.INSTITUTION.ATTR_LOGO_IMAGE, FORM_LOGO_IMAGE_TEXT_KEY, diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/content/MonitoringRunningExam.java b/src/main/java/ch/ethz/seb/sebserver/gui/content/MonitoringRunningExam.java index 4032a17d..9c5fcc8e 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/content/MonitoringRunningExam.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/content/MonitoringRunningExam.java @@ -9,11 +9,9 @@ package ch.ethz.seb.sebserver.gui.content; import java.util.Collection; -import java.util.Set; import java.util.function.BooleanSupplier; import java.util.function.Consumer; import java.util.function.Function; -import java.util.function.Predicate; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.GridData; @@ -31,7 +29,6 @@ import ch.ethz.seb.sebserver.gbl.model.Domain; import ch.ethz.seb.sebserver.gbl.model.EntityKey; import ch.ethz.seb.sebserver.gbl.model.exam.Exam; import ch.ethz.seb.sebserver.gbl.model.exam.Indicator; -import ch.ethz.seb.sebserver.gbl.model.session.ClientConnection; import ch.ethz.seb.sebserver.gbl.model.session.ClientConnection.ConnectionStatus; import ch.ethz.seb.sebserver.gbl.model.session.ClientConnectionData; import ch.ethz.seb.sebserver.gbl.model.user.UserRole; @@ -71,6 +68,8 @@ public class MonitoringRunningExam implements TemplateComposer { new LocTextKey("sebserver.monitoring.exam.connection.action.instruction.quit.selected.confirm"); private static final LocTextKey CONFIRM_QUIT_ALL = new LocTextKey("sebserver.monitoring.exam.connection.action.instruction.quit.all.confirm"); + private static final LocTextKey CONFIRM_DISABLE_SELECTED = + new LocTextKey("sebserver.monitoring.exam.connection.action.instruction.disable.selected.confirm"); private final ServerPushService serverPushService; private final PageService pageService; @@ -183,7 +182,19 @@ public class MonitoringRunningExam implements TemplateComposer { action -> this.quitSebClients(action, clientTable, false), EMPTY_SELECTION_TEXT_KEY) .noEventPropagation() - .publishIf(privilege); + .publishIf(privilege) + + .newAction(ActionDefinition.MONITOR_EXAM_DISABLE_SELECTED_CONNECTION) + .withEntityKey(entityKey) + .withConfirm(() -> CONFIRM_DISABLE_SELECTED) + .withSelect( + clientTable::getSelection, + action -> this.disableSebClients(action, clientTable, false), + EMPTY_SELECTION_TEXT_KEY) + .noEventPropagation() + .publishIf(privilege) + + ; clientTable.hideStatus(ConnectionStatus.DISABLED); @@ -228,6 +239,7 @@ public class MonitoringRunningExam implements TemplateComposer { return action -> { clientTable.showStatus(status); + clientTable.removeSelection(); return action; }; } @@ -238,6 +250,7 @@ public class MonitoringRunningExam implements TemplateComposer { return action -> { clientTable.hideStatus(status); + clientTable.removeSelection(); return action; }; } @@ -247,20 +260,27 @@ public class MonitoringRunningExam implements TemplateComposer { final ClientConnectionTable clientTable, final boolean all) { - final Predicate activePredicate = ClientConnection - .getStatusPredicate(ConnectionStatus.ACTIVE); - - final Set connectionTokens = clientTable.getConnectionTokens( - activePredicate, - !all); - - if (connectionTokens.isEmpty()) { - return action; - } - this.instructionProcessor.propagateSebQuitInstruction( clientTable.getExam().id, - connectionTokens, + statesPredicate -> clientTable.getConnectionTokens( + statesPredicate, + !all), + action.pageContext()); + + clientTable.removeSelection(); + return action; + } + + private PageAction disableSebClients( + final PageAction action, + final ClientConnectionTable clientTable, + final boolean all) { + + this.instructionProcessor.disableConnection( + clientTable.getExam().id, + statesPredicate -> clientTable.getConnectionTokens( + statesPredicate, + !all), action.pageContext()); clientTable.removeSelection(); diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/form/CheckboxFieldBuilder.java b/src/main/java/ch/ethz/seb/sebserver/gui/form/CheckboxFieldBuilder.java index a486e8e7..e6fc0aa3 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/form/CheckboxFieldBuilder.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/form/CheckboxFieldBuilder.java @@ -26,15 +26,8 @@ public class CheckboxFieldBuilder extends FieldBuilder { @Override void build(final FormBuilder builder) { final boolean readonly = builder.readonly || this.readonly; - final Label lab = (this.label != null) - ? builder.labelLocalized( - builder.formParent, - this.label, - this.defaultLabel, - this.spanLabel) - : null; - - final Composite fieldGrid = Form.createFieldGrid(builder.formParent, this.spanInput); + final Label titleLabel = createTitleLabel(builder.formParent, builder, this); + final Composite fieldGrid = createFieldGrid(builder.formParent, this.spanInput); final Button checkbox = builder.widgetFactory.buttonLocalized( fieldGrid, SWT.CHECK, @@ -48,7 +41,7 @@ public class CheckboxFieldBuilder extends FieldBuilder { checkbox.setEnabled(false); } - builder.form.putField(this.name, lab, checkbox); + builder.form.putField(this.name, titleLabel, checkbox); } } diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/form/FieldBuilder.java b/src/main/java/ch/ethz/seb/sebserver/gui/form/FieldBuilder.java index 1d418655..a1c23132 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/form/FieldBuilder.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/form/FieldBuilder.java @@ -10,17 +10,31 @@ package ch.ethz.seb.sebserver.gui.form; import java.util.function.BooleanSupplier; +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.Label; + import ch.ethz.seb.sebserver.gui.service.i18n.LocTextKey; +import ch.ethz.seb.sebserver.gui.widget.WidgetFactory; +import ch.ethz.seb.sebserver.gui.widget.WidgetFactory.CustomVariant; public abstract class FieldBuilder { int spanLabel = -1; int spanInput = -1; int spanEmptyCell = -1; + int titleValign = SWT.TOP; Boolean autoEmptyCellSeparation = null; String group = null; boolean readonly = false; boolean visible = true; String defaultLabel = null; + LocTextKey infoText; + boolean infoLeft = false; + boolean infoRight = false; final String name; final LocTextKey label; @@ -42,6 +56,18 @@ public abstract class FieldBuilder { return this; } + public FieldBuilder withInfoLeft(final LocTextKey infoText) { + this.infoText = infoText; + this.infoLeft = true; + return this; + } + + public FieldBuilder withInfoRight(final LocTextKey infoText) { + this.infoText = infoText; + this.infoRight = true; + return this; + } + public FieldBuilder withInputSpan(final int span) { this.spanInput = span; return this; @@ -79,4 +105,102 @@ public abstract class FieldBuilder { abstract void build(FormBuilder builder); + protected static Label createTitleLabel( + final Composite parent, + final FormBuilder builder, + final FieldBuilder fieldBuilder) { + + final Composite infoGrid = new Composite(parent, SWT.NONE); + final GridLayout gridLayout = new GridLayout(2, false); + gridLayout.verticalSpacing = 0; + gridLayout.marginHeight = 0; + gridLayout.marginWidth = 0; + gridLayout.marginRight = 0; + infoGrid.setLayout(gridLayout); + + final GridData gridData = new GridData(SWT.LEFT, SWT.TOP, false, false); + infoGrid.setLayoutData(gridData); + + if (fieldBuilder.infoText != null && fieldBuilder.infoLeft) { + final Label info = builder.widgetFactory.imageButton( + WidgetFactory.ImageIcon.HELP, + infoGrid, + fieldBuilder.infoText); + info.setLayoutData(new GridData(SWT.LEFT, SWT.TOP, false, false)); + } + final Label lab = (fieldBuilder.label != null) + ? labelLocalized( + builder.widgetFactory, + infoGrid, + fieldBuilder.label, + fieldBuilder.defaultLabel, + (fieldBuilder.spanLabel > 0) ? fieldBuilder.spanLabel : 1, + fieldBuilder.titleValign) + : null; + + if (fieldBuilder.infoText != null && fieldBuilder.infoRight) { + final Label info = builder.widgetFactory.imageButton( + WidgetFactory.ImageIcon.HELP, + infoGrid, + fieldBuilder.infoText); + info.setLayoutData(new GridData(SWT.LEFT, SWT.TOP, false, false)); + } + + return lab; + } + + public static Label labelLocalized( + final WidgetFactory widgetFactory, + final Composite parent, + final LocTextKey locTextKey, + final String defaultText, + final int hspan) { + + return labelLocalized(widgetFactory, parent, locTextKey, defaultText, hspan, SWT.CENTER); + } + + public static final Label labelLocalized( + final WidgetFactory widgetFactory, + final Composite parent, + final LocTextKey locTextKey, + final String defaultText, + final int hspan, + final int verticalAlignment) { + + final Label label = widgetFactory.labelLocalized( + parent, + locTextKey, + (StringUtils.isNotBlank(defaultText) ? defaultText : locTextKey.name)); + final GridData gridData = new GridData(SWT.LEFT, verticalAlignment, true, true, hspan, 1); + gridData.heightHint = FormBuilder.FORM_ROW_HEIGHT; + label.setLayoutData(gridData); + label.setData(RWT.CUSTOM_VARIANT, CustomVariant.TITLE_LABEL.key); + return label; + } + + 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 = 0; + gridLayout.marginWidth = 0; + gridLayout.marginRight = 0; + fieldGrid.setLayout(gridLayout); + + final GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, true); + gridData.horizontalSpan = hspan; + fieldGrid.setLayoutData(gridData); + + return fieldGrid; + } + + public static Label createErrorLabel(final Composite innerGrid) { + final Label errorLabel = new Label(innerGrid, SWT.NONE); + final GridData gridData = new GridData(SWT.FILL, SWT.CENTER, true, true); + errorLabel.setLayoutData(gridData); + errorLabel.setVisible(false); + errorLabel.setData(RWT.CUSTOM_VARIANT, CustomVariant.ERROR.key); + return errorLabel; + } + } \ No newline at end of file diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/form/FileUploadFieldBuilder.java b/src/main/java/ch/ethz/seb/sebserver/gui/form/FileUploadFieldBuilder.java index 7cbb59b2..508310e4 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/form/FileUploadFieldBuilder.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/form/FileUploadFieldBuilder.java @@ -34,14 +34,8 @@ public class FileUploadFieldBuilder extends FieldBuilder { @Override void build(final FormBuilder builder) { - - final Label lab = builder.labelLocalized( - builder.formParent, - this.label, - this.defaultLabel, - 1); - - final Composite fieldGrid = Form.createFieldGrid(builder.formParent, this.spanInput); + final Label titleLabel = createTitleLabel(builder.formParent, builder, this); + final Composite fieldGrid = createFieldGrid(builder.formParent, this.spanInput); final FileUploadSelection fileUpload = builder.widgetFactory.fileUploadSelection( fieldGrid, builder.readonly || this.readonly, @@ -50,8 +44,8 @@ public class FileUploadFieldBuilder extends FieldBuilder { fileUpload.setLayoutData(gridData); fileUpload.setFileName(this.value); - final Label errorLabel = Form.createErrorLabel(fieldGrid); - builder.form.putField(this.name, lab, fileUpload, errorLabel); + final Label errorLabel = createErrorLabel(fieldGrid); + builder.form.putField(this.name, titleLabel, fileUpload, errorLabel); builder.setFieldVisible(this.visible, this.name); } 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 82f74bfa..6f6e9b24 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 @@ -21,12 +21,8 @@ import java.util.function.Predicate; import org.apache.commons.lang3.BooleanUtils; import org.apache.commons.lang3.StringUtils; import org.eclipse.rap.rwt.RWT; -import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Color; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; -import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Text; @@ -512,29 +508,4 @@ public final class Form implements FormBinding { } } - 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 = 0; - gridLayout.marginWidth = 0; - gridLayout.marginRight = 0; - fieldGrid.setLayout(gridLayout); - - final GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, true); - gridData.horizontalSpan = hspan; - fieldGrid.setLayoutData(gridData); - - return fieldGrid; - } - - public static Label createErrorLabel(final Composite innerGrid) { - final Label errorLabel = new Label(innerGrid, SWT.NONE); - final GridData gridData = new GridData(SWT.FILL, SWT.CENTER, true, true); - errorLabel.setLayoutData(gridData); - 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 db14e2f8..dc59e9eb 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 @@ -15,7 +15,6 @@ import java.util.function.BooleanSupplier; import java.util.function.Supplier; 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.widgets.Composite; @@ -24,7 +23,6 @@ import org.eclipse.swt.widgets.TabItem; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import ch.ethz.seb.sebserver.gbl.Constants; import ch.ethz.seb.sebserver.gbl.model.Entity; import ch.ethz.seb.sebserver.gbl.model.exam.Indicator; import ch.ethz.seb.sebserver.gbl.util.Tuple; @@ -35,11 +33,10 @@ import ch.ethz.seb.sebserver.gui.service.page.PageService; import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCall; import ch.ethz.seb.sebserver.gui.widget.Selection; import ch.ethz.seb.sebserver.gui.widget.WidgetFactory; -import ch.ethz.seb.sebserver.gui.widget.WidgetFactory.CustomVariant; public class FormBuilder { - private static final int FORM_ROW_HEIGHT = 25; + public static final int FORM_ROW_HEIGHT = 25; private static final Logger log = LoggerFactory.getLogger(FormBuilder.class); @@ -283,54 +280,4 @@ public class FormBuilder { (supportedFiles != null) ? Arrays.asList(supportedFiles) : Collections.emptyList()); } - Label labelLocalized( - final Composite parent, - final LocTextKey locTextKey, - final String defaultText, - final int hspan) { - - return labelLocalized(parent, locTextKey, defaultText, hspan, SWT.CENTER); - } - - Label labelLocalized( - final Composite parent, - final LocTextKey locTextKey, - final String defaultText, - final int hspan, - final int verticalAlignment) { - - final Label label = this.widgetFactory.labelLocalized( - parent, - locTextKey, - (StringUtils.isNotBlank(defaultText) ? defaultText : locTextKey.name)); - final GridData gridData = new GridData(SWT.LEFT, verticalAlignment, true, true, hspan, 1); - gridData.heightHint = FORM_ROW_HEIGHT; - label.setLayoutData(gridData); - label.setData(RWT.CUSTOM_VARIANT, CustomVariant.TITLE_LABEL.key); - return label; - } - - Label valueLabel( - final Composite parent, - final String value, - final int hspan, - final boolean centered) { - - final Label label = new Label(parent, SWT.NONE); - label.setText((StringUtils.isNotBlank(value)) ? value : Constants.EMPTY_NOTE); - final GridData gridData = new GridData( - SWT.FILL, - (centered) ? SWT.CENTER : SWT.TOP, - true, false, - hspan, 1); - - if (centered) { - label.setAlignment(SWT.CENTER); - label.setData(RWT.CUSTOM_VARIANT, CustomVariant.FORM_CENTER.key); - } - - label.setLayoutData(gridData); - 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 2334326b..c43d3ac2 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 @@ -37,14 +37,8 @@ public final class ImageUploadFieldBuilder extends FieldBuilder { @Override void build(final FormBuilder builder) { - - final Label lab = builder.labelLocalized( - builder.formParent, - this.label, - this.defaultLabel, - 1); - - final Composite fieldGrid = Form.createFieldGrid(builder.formParent, this.spanInput); + final Label titleLabel = createTitleLabel(builder.formParent, builder, this); + final Composite fieldGrid = createFieldGrid(builder.formParent, this.spanInput); final ImageUploadSelection imageUpload = builder.widgetFactory.imageUploadLocalized( fieldGrid, new LocTextKey("sebserver.overall.upload"), @@ -55,8 +49,8 @@ public final class ImageUploadFieldBuilder extends FieldBuilder { imageUpload.setLayoutData(gridData); imageUpload.setImageBase64(this.value); - final Label errorLabel = Form.createErrorLabel(fieldGrid); - builder.form.putField(this.name, lab, imageUpload, errorLabel); + final Label errorLabel = createErrorLabel(fieldGrid); + builder.form.putField(this.name, titleLabel, 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 3a7e9eb2..8e77c5a6 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 @@ -55,25 +55,18 @@ public final class SelectionFieldBuilder extends FieldBuilder { @Override void build(final FormBuilder builder) { - final Label lab = (this.label != null) - ? builder.labelLocalized( - builder.formParent, - this.label, - this.defaultLabel, - this.spanLabel, - SWT.TOP) - : null; + final Label titleLabel = createTitleLabel(builder.formParent, builder, this); if (builder.readonly || this.readonly) { - buildReadOnly(builder, lab); + buildReadOnly(builder, titleLabel); } else { - buildInput(builder, lab); + buildInput(builder, titleLabel); } } - private void buildInput(final FormBuilder builder, final Label lab) { + private void buildInput(final FormBuilder builder, final Label titleLabel) { - final Composite fieldGrid = Form.createFieldGrid(builder.formParent, this.spanInput); + final Composite fieldGrid = createFieldGrid(builder.formParent, this.spanInput); final String actionKey = (this.label != null) ? this.label.name + ".action" : null; final Selection selection = builder.widgetFactory.selectionLocalized( this.type, @@ -87,8 +80,8 @@ public final class SelectionFieldBuilder extends FieldBuilder { ((Control) selection).setLayoutData(gridData); selection.select(this.value); - final Label errorLabel = Form.createErrorLabel(fieldGrid); - builder.form.putField(this.name, lab, selection, errorLabel); + final Label errorLabel = createErrorLabel(fieldGrid); + builder.form.putField(this.name, titleLabel, selection, errorLabel); if (this.selectionListener != null) { ((Control) selection).addListener(SWT.Selection, e -> { @@ -100,7 +93,7 @@ public final class SelectionFieldBuilder extends FieldBuilder { } /* Build the read-only representation of the selection field */ - private void buildReadOnly(final FormBuilder builder, final Label lab) { + private void buildReadOnly(final FormBuilder builder, final Label titleLabel) { if (this.type == Type.MULTI || this.type == Type.MULTI_COMBO) { final Composite composite = new Composite(builder.formParent, SWT.NONE); final GridLayout gridLayout = new GridLayout(1, true); @@ -127,7 +120,7 @@ public final class SelectionFieldBuilder extends FieldBuilder { } else { builder.form.putReadonlyField( this.name, - lab, + titleLabel, buildReadonlyLabel(builder.formParent, this.value, this.spanInput)); builder.setFieldVisible(this.visible, this.name); } 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 f76cbf79..1be63e22 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 @@ -52,6 +52,7 @@ public final class TextFieldBuilder extends FieldBuilder { public TextFieldBuilder asArea() { this.isArea = true; + this.titleValign = SWT.CENTER; return this; } @@ -63,16 +64,8 @@ public final class TextFieldBuilder extends FieldBuilder { @Override void build(final FormBuilder builder) { final boolean readonly = builder.readonly || this.readonly; - final Label lab = (this.label != null) - ? builder.labelLocalized( - builder.formParent, - this.label, - this.defaultLabel, - this.spanLabel, - (this.isArea) ? SWT.TOP : SWT.CENTER) - : null; - - final Composite fieldGrid = Form.createFieldGrid(builder.formParent, this.spanInput); + final Label titleLabel = createTitleLabel(builder.formParent, builder, this); + final Composite fieldGrid = createFieldGrid(builder.formParent, this.spanInput); final Text textInput = (this.isNumber) ? builder.widgetFactory.numberInput(fieldGrid, this.numberCheck, readonly) : (this.isArea) @@ -95,12 +88,13 @@ public final class TextFieldBuilder extends FieldBuilder { if (readonly) { textInput.setEditable(false); - builder.form.putReadonlyField(this.name, lab, textInput); + builder.form.putReadonlyField(this.name, titleLabel, textInput); } else { - final Label errorLabel = Form.createErrorLabel(fieldGrid); - builder.form.putField(this.name, lab, textInput, errorLabel); + final Label errorLabel = createErrorLabel(fieldGrid); + builder.form.putField(this.name, titleLabel, textInput, errorLabel); builder.setFieldVisible(this.visible, this.name); } } + } \ No newline at end of file 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 581705e9..ca4a8bb8 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 @@ -39,18 +39,13 @@ public class ThresholdListBuilder extends FieldBuilder> { @Override void build(final FormBuilder builder) { - final Label lab = builder.labelLocalized( - builder.formParent, - this.label, - this.defaultLabel, - this.spanLabel); - + final Label titleLabel = createTitleLabel(builder.formParent, builder, this); if (builder.readonly || this.readonly) { // No read-only view needed for this so far? return; } else { - final Composite fieldGrid = Form.createFieldGrid(builder.formParent, this.spanInput); + final Composite fieldGrid = createFieldGrid(builder.formParent, this.spanInput); final ThresholdList thresholdList = builder.widgetFactory.thresholdList( fieldGrid, @@ -68,8 +63,8 @@ public class ThresholdListBuilder extends FieldBuilder> { final GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, false); thresholdList.setLayoutData(gridData); - final Label errorLabel = Form.createErrorLabel(fieldGrid); - builder.form.putField(this.name, lab, thresholdList, errorLabel); + final Label errorLabel = createErrorLabel(fieldGrid); + builder.form.putField(this.name, titleLabel, thresholdList, errorLabel); builder.setFieldVisible(this.visible, this.name); } 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 6e01655b..bb3b12fc 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 @@ -29,7 +29,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.form.FieldBuilder; 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; @@ -82,7 +82,7 @@ public class PassworFieldBuilder implements InputFieldBuilder { orientation, passwordInput, confirmInput, - Form.createErrorLabel(innerGrid)); + FieldBuilder.createErrorLabel(innerGrid)); if (viewContext.readonly) { passwordInput.setEditable(false); 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 2b2a8aa6..fd351acc 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,7 +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.form.FieldBuilder; 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; @@ -74,7 +74,7 @@ public class SingleSelectionFieldBuilder extends SelectionFieldBuilder implement attribute, orientation, selection, - Form.createErrorLabel(innerGrid)); + FieldBuilder.createErrorLabel(innerGrid)); if (viewContext.readonly) { selection.setEnabled(false); 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 797a0c18..8b0a7ed3 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 @@ -25,7 +25,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.form.FieldBuilder; 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; @@ -102,7 +102,7 @@ public class TextFieldBuilder implements InputFieldBuilder { attribute, orientation, text, - Form.createErrorLabel(innerGrid)); + FieldBuilder.createErrorLabel(innerGrid)); if (viewContext.readonly) { text.setEditable(false); diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/session/InstructionProcessor.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/session/InstructionProcessor.java index f3b7c348..ef3b2add 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/service/session/InstructionProcessor.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/session/InstructionProcessor.java @@ -10,6 +10,11 @@ package ch.ethz.seb.sebserver.gui.service.session; import java.util.Collection; import java.util.Set; +import java.util.function.Function; +import java.util.function.Predicate; +import java.util.function.Supplier; +import java.util.stream.Collectors; +import java.util.stream.Stream; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; @@ -23,14 +28,17 @@ import ch.ethz.seb.sebserver.gbl.Constants; import ch.ethz.seb.sebserver.gbl.api.API; import ch.ethz.seb.sebserver.gbl.api.APIMessage; import ch.ethz.seb.sebserver.gbl.api.JSONMapper; +import ch.ethz.seb.sebserver.gbl.model.Domain; +import ch.ethz.seb.sebserver.gbl.model.session.ClientConnection; +import ch.ethz.seb.sebserver.gbl.model.session.ClientConnection.ConnectionStatus; import ch.ethz.seb.sebserver.gbl.model.session.ClientInstruction; import ch.ethz.seb.sebserver.gbl.model.session.ClientInstruction.InstructionType; import ch.ethz.seb.sebserver.gbl.profile.GuiProfile; -import ch.ethz.seb.sebserver.gbl.util.Utils; import ch.ethz.seb.sebserver.gui.service.page.PageContext; import ch.ethz.seb.sebserver.gui.service.page.PageService; import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCallError; import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestService; +import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.session.DisableClientConnection; import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.session.PropagateInstruction; @Lazy @@ -53,15 +61,23 @@ public class InstructionProcessor { final String connectionToken, final PageContext pageContext) { - propagateSebQuitInstruction(examId, Utils.immutableSetOf(connectionToken), pageContext); + propagateSebQuitInstruction( + examId, + p -> Stream.of(connectionToken).collect(Collectors.toSet()), + pageContext); + } public void propagateSebQuitInstruction( final Long examId, - final Set connectionTokens, + final Function, Set> selectionFunction, final PageContext pageContext) { - if (examId == null || connectionTokens == null || connectionTokens.isEmpty()) { + final Set connectionTokens = selectionFunction + .apply(ClientConnection.getStatusPredicate(ConnectionStatus.ACTIVE)); + + if (connectionTokens.isEmpty()) { + // TODO message return; } @@ -75,15 +91,59 @@ public class InstructionProcessor { null, examId, InstructionType.SEB_QUIT, - StringUtils.join(connectionTokens, Constants.COMMA), + StringUtils.join(connectionTokens, Constants.LIST_SEPARATOR), null); - try { - final String response = this.restService.getBuilder(PropagateInstruction.class) + processInstruction(() -> { + return this.restService.getBuilder(PropagateInstruction.class) .withURIVariable(API.PARAM_MODEL_ID, String.valueOf(examId)) .withBody(clientInstruction) .call() .getOrThrow(); + }, + pageContext); + + } + + public void disableConnection( + final Long examId, + final Function, Set> selectionFunction, + final PageContext pageContext) { + + final Set connectionTokens = selectionFunction + .apply(ClientConnection.getStatusPredicate( + ConnectionStatus.CONNECTION_REQUESTED, + ConnectionStatus.UNDEFINED, + ConnectionStatus.CLOSED, + ConnectionStatus.AUTHENTICATED)); + + if (connectionTokens.isEmpty()) { + // TOOD message + return; + } + + if (log.isDebugEnabled()) { + log.debug("Disable SEB client connections for exam: {} and connections: {}", + examId, + connectionTokens); + } + + processInstruction(() -> { + return this.restService.getBuilder(DisableClientConnection.class) + .withURIVariable(API.PARAM_MODEL_ID, String.valueOf(examId)) + .withFormParam( + Domain.CLIENT_CONNECTION.ATTR_CONNECTION_TOKEN, + StringUtils.join(connectionTokens, Constants.LIST_SEPARATOR)) + .call() + .getOrThrow(); + }, + pageContext); + + } + + private void processInstruction(final Supplier apiCall, final PageContext pageContext) { + try { + final String response = apiCall.get(); if (StringUtils.isNotBlank(response)) { try { @@ -93,7 +153,7 @@ public class InstructionProcessor { }); pageContext.notifyUnexpectedError(new RestCallError( - "Failed to propagate SEB quit instruction: ", + "Failed to propagate SEB client instruction: ", errorMessage)); } catch (final Exception e) { @@ -101,7 +161,7 @@ public class InstructionProcessor { } } } catch (final Exception e) { - log.error("Failed to propagate SEB quit instruction: ", e); + log.error("Failed to propagate SEB client instruction: ", e); } } 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 4724456a..2716871a 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 @@ -100,7 +100,8 @@ public class WidgetFactory { INDICATOR("indicator.png"), TEMPLATE("template.png"), DISABLE("disable.png"), - SEND_QUIT("send-quit.png"); + SEND_QUIT("send-quit.png"), + HELP("help.png"); private String fileName; private ImageData image = null; @@ -502,6 +503,14 @@ public class WidgetFactory { return label; } + public Label imageButton( + final ImageIcon type, + final Composite parent, + final LocTextKey toolTip) { + + return this.imageButton(type, parent, toolTip, null); + } + public Label imageButton( final ImageIcon type, final Composite parent, diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/SebClientConnectionServiceImpl.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/SebClientConnectionServiceImpl.java index 848e7c9b..bdb98590 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/SebClientConnectionServiceImpl.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/SebClientConnectionServiceImpl.java @@ -11,6 +11,7 @@ package ch.ethz.seb.sebserver.webservice.servicelayer.session.impl; import java.security.Principal; import java.util.Objects; import java.util.UUID; +import java.util.function.Predicate; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; @@ -374,6 +375,13 @@ public class SebClientConnectionServiceImpl implements SebClientConnectionServic }); } + private static final Predicate DISABLE_STATE_PREDICATE = ClientConnection + .getStatusPredicate( + ConnectionStatus.UNDEFINED, + ConnectionStatus.CONNECTION_REQUESTED, + ConnectionStatus.AUTHENTICATED, + ConnectionStatus.CLOSED); + @Override public Result disableConnection(final String connectionToken, final Long institutionId) { return Result.tryCatch(() -> { @@ -390,9 +398,7 @@ public class SebClientConnectionServiceImpl implements SebClientConnectionServic .getOrThrow(); ClientConnection updatedClientConnection; - if (clientConnection.status == ConnectionStatus.CONNECTION_REQUESTED || - clientConnection.status == ConnectionStatus.UNDEFINED || - clientConnection.status == ConnectionStatus.AUTHENTICATED) { + if (DISABLE_STATE_PREDICATE.test(clientConnection)) { updatedClientConnection = saveInState( clientConnection, diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ExamMonitoringController.java b/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ExamMonitoringController.java index 89f4971d..01e2c3ae 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ExamMonitoringController.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ExamMonitoringController.java @@ -231,7 +231,8 @@ public class ExamMonitoringController { required = true, defaultValue = UserService.USERS_INSTITUTION_AS_DEFAULT) final Long institutionId, @PathVariable(name = API.PARAM_MODEL_ID, required = true) final Long examId, - @PathVariable(name = Domain.CLIENT_CONNECTION.ATTR_CONNECTION_TOKEN, + @RequestParam( + name = Domain.CLIENT_CONNECTION.ATTR_CONNECTION_TOKEN, required = true) final String connectionToken) { if (connectionToken.contains(Constants.LIST_SEPARATOR)) { @@ -242,7 +243,8 @@ public class ExamMonitoringController { .onError(error -> log.error("Failed to disable SEB client connection: {}", token)); } } else { - this.sebClientConnectionService.disableConnection(connectionToken, institutionId) + this.sebClientConnectionService + .disableConnection(connectionToken, institutionId) .getOrThrow(); } diff --git a/src/main/resources/messages.properties b/src/main/resources/messages.properties index 426f296c..34f10c6b 100644 --- a/src/main/resources/messages.properties +++ b/src/main/resources/messages.properties @@ -1065,12 +1065,14 @@ sebserver.monitoring.connection.list.column.vdiAddress=IP Address (VDI) sebserver.monitoring.exam.connection.emptySelection=Please select a connection from the list sebserver.monitoring.exam.connection.title=SEB Client Connection sebserver.monitoring.exam.connection.list.actions=Selected Connection -sebserver.monitoring.exam.connection.action.view=View Details +sebserver.monitoring.exam.connection.action.view=Back To Monitoring sebserver.monitoring.exam.connection.action.instruction.quit=Send SEB Quit sebserver.monitoring.exam.connection.action.instruction.quit.all=Send SEB Quit -sebserver.monitoring.exam.connection.action.instruction.quit.all.confirm=Are you sure to quit this SEB client connection? +sebserver.monitoring.exam.connection.action.instruction.quit.confirm=Are you sure to quit this SEB client connection? sebserver.monitoring.exam.connection.action.instruction.quit.selected.confirm=Are you sure to quit all selected, active SEB client connections? sebserver.monitoring.exam.connection.action.instruction.quit.all.confirm=Are you sure to quit all active SEB client connections? +sebserver.monitoring.exam.connection.action.instruction.disable.selected.confirm=Are you sure to disable all selected SEB client connections? +sebserver.monitoring.exam.connection.action.instruction.disable.all.confirm=Are you sure to disable all active SEB client connections? sebserver.monitoring.exam.connection.action.disable=Mark As Disabled sebserver.monitoring.exam.connection.action.hide.requested=Hide Requested sebserver.monitoring.exam.connection.action.show.requested=Show Requested diff --git a/src/main/resources/static/images/help.png b/src/main/resources/static/images/help.png new file mode 100644 index 0000000000000000000000000000000000000000..35df5b56e5b97927f5125fac79116649519b7e60 GIT binary patch literal 643 zcmV-}0(||6P)w*{mdKb8}OpqoWFk!EPf%larHbG#ZkW9%!{%l*?r-%fjh&GBPs4 z(a{m{c${{-jnnDG2M6hPyS%-<0bqDM9)iIjl}ZIkI2;ZDN~IFbW|Py?Qv!hi0OfKS!!QU2gCCm> z!yu7Jkjv$$R4QLr@Or(htgL()0rvOzF-?HuV45alV`F_E!yzf% dPx%ji{{eD}fH{f*nxX&z002ovPDHLkV1nl}JTCwM literal 0 HcmV?d00001