info monitoring disable

This commit is contained in:
anhefti 2019-12-23 13:21:59 +01:00
parent 0e528a3c86
commit 663662d50e
21 changed files with 309 additions and 192 deletions

View file

@ -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<ClientConnection> getStatusPredicate(final ConnectionStatus... status) {
final EnumSet<ConnectionStatus> 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);
}
}

View file

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

View file

@ -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<ClientConnection> activePredicate = ClientConnection
.getStatusPredicate(ConnectionStatus.ACTIVE);
final Set<String> 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();

View file

@ -26,15 +26,8 @@ public class CheckboxFieldBuilder extends FieldBuilder<String> {
@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<String> {
checkbox.setEnabled(false);
}
builder.form.putField(this.name, lab, checkbox);
builder.form.putField(this.name, titleLabel, checkbox);
}
}

View file

@ -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<T> {
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<T> {
return this;
}
public FieldBuilder<T> withInfoLeft(final LocTextKey infoText) {
this.infoText = infoText;
this.infoLeft = true;
return this;
}
public FieldBuilder<T> withInfoRight(final LocTextKey infoText) {
this.infoText = infoText;
this.infoRight = true;
return this;
}
public FieldBuilder<T> withInputSpan(final int span) {
this.spanInput = span;
return this;
@ -79,4 +105,102 @@ public abstract class FieldBuilder<T> {
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;
}
}

View file

@ -34,14 +34,8 @@ public class FileUploadFieldBuilder extends FieldBuilder<String> {
@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<String> {
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);
}

View file

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

View file

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

View file

@ -37,14 +37,8 @@ public final class ImageUploadFieldBuilder extends FieldBuilder<String> {
@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<String> {
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);
}

View file

@ -55,25 +55,18 @@ public final class SelectionFieldBuilder extends FieldBuilder<String> {
@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<String> {
((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<String> {
}
/* 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<String> {
} else {
builder.form.putReadonlyField(
this.name,
lab,
titleLabel,
buildReadonlyLabel(builder.formParent, this.value, this.spanInput));
builder.setFieldVisible(this.visible, this.name);
}

View file

@ -52,6 +52,7 @@ public final class TextFieldBuilder extends FieldBuilder<String> {
public TextFieldBuilder asArea() {
this.isArea = true;
this.titleValign = SWT.CENTER;
return this;
}
@ -63,16 +64,8 @@ public final class TextFieldBuilder extends FieldBuilder<String> {
@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<String> {
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);
}
}
}

View file

@ -39,18 +39,13 @@ public class ThresholdListBuilder extends FieldBuilder<Collection<Threshold>> {
@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<Collection<Threshold>> {
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);
}

View file

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

View file

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

View file

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

View file

@ -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<String> connectionTokens,
final Function<Predicate<ClientConnection>, Set<String>> selectionFunction,
final PageContext pageContext) {
if (examId == null || connectionTokens == null || connectionTokens.isEmpty()) {
final Set<String> 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<Predicate<ClientConnection>, Set<String>> selectionFunction,
final PageContext pageContext) {
final Set<String> 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<String> 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);
}
}

View file

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

View file

@ -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<ClientConnection> DISABLE_STATE_PREDICATE = ClientConnection
.getStatusPredicate(
ConnectionStatus.UNDEFINED,
ConnectionStatus.CONNECTION_REQUESTED,
ConnectionStatus.AUTHENTICATED,
ConnectionStatus.CLOSED);
@Override
public Result<ClientConnection> 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,

View file

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

View file

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 643 B