SEBSERV-29 new multi selection with combo supporter selection
This commit is contained in:
parent
94858b757a
commit
584a900529
24 changed files with 535 additions and 181 deletions
|
@ -14,6 +14,9 @@ import org.joda.time.format.DateTimeFormatter;
|
|||
/** Global Constants used in SEB Server web-service as well as in web-gui component */
|
||||
public final class Constants {
|
||||
|
||||
public static final String TRUE_STRING = Boolean.TRUE.toString();
|
||||
public static final String FALSE_STRING = Boolean.FALSE.toString();
|
||||
|
||||
public static final long SECOND_IN_MILLIS = 1000;
|
||||
public static final long MINUTE_IN_MILLIS = 60 * SECOND_IN_MILLIS;
|
||||
public static final long HOUR_IN_MILLIS = 60 * MINUTE_IN_MILLIS;
|
||||
|
|
|
@ -48,6 +48,7 @@ public final class UserInfo implements UserAccount, Activatable, Serializable {
|
|||
public static final String FILTER_ATTR_USER_NAME = "username";
|
||||
public static final String FILTER_ATTR_EMAIL = "email";
|
||||
public static final String FILTER_ATTR_LANGUAGE = "language";
|
||||
public static final String FILTER_ATTR_ROLE = "role";
|
||||
|
||||
/** The user's UUID */
|
||||
@JsonProperty(USER.ATTR_UUID)
|
||||
|
|
|
@ -10,7 +10,11 @@ package ch.ethz.seb.sebserver.gui.content;
|
|||
|
||||
import java.util.function.Function;
|
||||
|
||||
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;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
@ -28,6 +32,7 @@ import ch.ethz.seb.sebserver.gui.content.action.ActionDefinition;
|
|||
import ch.ethz.seb.sebserver.gui.service.ResourceService;
|
||||
import ch.ethz.seb.sebserver.gui.service.i18n.I18nSupport;
|
||||
import ch.ethz.seb.sebserver.gui.service.i18n.LocTextKey;
|
||||
import ch.ethz.seb.sebserver.gui.service.page.ModalInputDialog;
|
||||
import ch.ethz.seb.sebserver.gui.service.page.PageContext;
|
||||
import ch.ethz.seb.sebserver.gui.service.page.TemplateComposer;
|
||||
import ch.ethz.seb.sebserver.gui.service.page.action.Action;
|
||||
|
@ -131,6 +136,10 @@ public class ExamList implements TemplateComposer {
|
|||
final GrantCheck userGrant = currentUser.grantCheck(EntityType.EXAM);
|
||||
pageContext.clearEntityKeys()
|
||||
|
||||
.createAction(ActionDefinition.TEST_ACTION)
|
||||
.withExec(this::testModalInput)
|
||||
.publish()
|
||||
|
||||
.createAction(ActionDefinition.EXAM_IMPORT)
|
||||
.publishIf(userGrant::im)
|
||||
|
||||
|
@ -163,4 +172,29 @@ public class ExamList implements TemplateComposer {
|
|||
.getText("sebserver.exam.type." + exam.type.name());
|
||||
}
|
||||
|
||||
private Action testModalInput(final Action action) {
|
||||
final ModalInputDialog<String> dialog = new ModalInputDialog<>(
|
||||
action.pageContext().getParent().getShell(),
|
||||
this.widgetFactory);
|
||||
|
||||
dialog.open(
|
||||
"Test Input Dialog",
|
||||
action.pageContext(),
|
||||
value -> {
|
||||
System.out.println("********************** value: " + value);
|
||||
},
|
||||
pc -> {
|
||||
final Composite parent = pc.getParent();
|
||||
final Label label = new Label(parent, SWT.NONE);
|
||||
label.setText("Please Enter:");
|
||||
label.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
|
||||
|
||||
final Text text = new Text(parent, SWT.LEFT | SWT.BORDER);
|
||||
text.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
|
||||
return () -> text.getText();
|
||||
});
|
||||
|
||||
return action;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -319,7 +319,7 @@ public enum ActionDefinition {
|
|||
EXAM_INDICATOR_NEW(
|
||||
new LocTextKey("sebserver.exam.indicator.action.list.new"),
|
||||
ImageIcon.NEW,
|
||||
LmsSetupForm.class,
|
||||
IndicatorForm.class,
|
||||
EXAM_VIEW_FROM_LIST,
|
||||
ActionCategory.FORM,
|
||||
false),
|
||||
|
@ -350,6 +350,12 @@ public enum ActionDefinition {
|
|||
EXAM_VIEW_FROM_LIST,
|
||||
ActionCategory.FORM,
|
||||
true),
|
||||
TEST_ACTION(
|
||||
new LocTextKey("TEST"),
|
||||
ImageIcon.TEST,
|
||||
ExamList.class,
|
||||
EXAM_VIEW_LIST,
|
||||
ActionCategory.FORM),
|
||||
|
||||
;
|
||||
|
||||
|
|
|
@ -8,12 +8,12 @@
|
|||
|
||||
package ch.ethz.seb.sebserver.gui.form;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
|
@ -30,10 +30,10 @@ import com.fasterxml.jackson.databind.node.ObjectNode;
|
|||
|
||||
import ch.ethz.seb.sebserver.gbl.Constants;
|
||||
import ch.ethz.seb.sebserver.gbl.api.JSONMapper;
|
||||
import ch.ethz.seb.sebserver.gbl.util.Tuple;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.FormBinding;
|
||||
import ch.ethz.seb.sebserver.gui.widget.ImageUpload;
|
||||
import ch.ethz.seb.sebserver.gui.widget.MultiSelection;
|
||||
import ch.ethz.seb.sebserver.gui.widget.SingleSelection;
|
||||
import ch.ethz.seb.sebserver.gui.widget.Selection;
|
||||
|
||||
public final class Form implements FormBinding {
|
||||
|
||||
|
@ -42,8 +42,6 @@ public final class Form implements FormBinding {
|
|||
|
||||
private final Map<String, String> staticValues = new LinkedHashMap<>();
|
||||
private final MultiValueMap<String, FormFieldAccessor> formFields = new LinkedMultiValueMap<>();
|
||||
private final Map<String, Form> subForms = new LinkedHashMap<>();
|
||||
private final Map<String, List<Form>> subLists = new LinkedHashMap<>();
|
||||
private final Map<String, Set<String>> groups = new LinkedHashMap<>();
|
||||
|
||||
Form(final JSONMapper jsonMapper) {
|
||||
|
@ -104,40 +102,23 @@ public final class Form implements FormBinding {
|
|||
return this;
|
||||
}
|
||||
|
||||
public void putField(final String name, final Label label, final SingleSelection field) {
|
||||
public void putField(final String name, final Label label, final Selection field) {
|
||||
this.formFields.add(name, createAccessor(label, field));
|
||||
}
|
||||
|
||||
public void putField(final String name, final Label label, final MultiSelection field) {
|
||||
this.formFields.add(name, createAccessor(label, field));
|
||||
public void putField(
|
||||
final String name,
|
||||
final Label label,
|
||||
final Selection field,
|
||||
final BiConsumer<Tuple<String>, ObjectNode> jsonValueAdapter) {
|
||||
|
||||
this.formFields.add(name, createAccessor(label, field, jsonValueAdapter));
|
||||
}
|
||||
|
||||
public void putField(final String name, final Label label, final ImageUpload imageUpload) {
|
||||
this.formFields.add(name, createAccessor(label, imageUpload));
|
||||
}
|
||||
|
||||
public void putSubForm(final String name, final Form form) {
|
||||
this.subForms.put(name, form);
|
||||
}
|
||||
|
||||
public Form getSubForm(final String name) {
|
||||
return this.subForms.get(name);
|
||||
}
|
||||
|
||||
public void addSubForm(final String arrayName, final Form form) {
|
||||
final List<Form> array = this.subLists.computeIfAbsent(arrayName, k -> new ArrayList<>());
|
||||
array.add(form);
|
||||
}
|
||||
|
||||
public Form getSubForm(final String arrayName, final int index) {
|
||||
final List<Form> array = this.subLists.get(arrayName);
|
||||
if (array == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return array.get(index);
|
||||
}
|
||||
|
||||
public void allVisible() {
|
||||
process(
|
||||
name -> true,
|
||||
|
@ -196,30 +177,12 @@ public final class Form implements FormBinding {
|
|||
.filter(ffa -> StringUtils.isNoneBlank(ffa.getValue()))
|
||||
.forEach(ffa -> ffa.putJsonValue(entry.getKey(), this.objectRoot));
|
||||
}
|
||||
|
||||
for (final Map.Entry<String, Form> entry : this.subForms.entrySet()) {
|
||||
final Form subForm = entry.getValue();
|
||||
subForm.flush();
|
||||
final ObjectNode objectNode = this.jsonMapper.createObjectNode();
|
||||
this.objectRoot.set(entry.getKey(), objectNode);
|
||||
}
|
||||
|
||||
for (final Map.Entry<String, List<Form>> entry : this.subLists.entrySet()) {
|
||||
final List<Form> value = entry.getValue();
|
||||
final ArrayNode arrayNode = this.jsonMapper.createArrayNode();
|
||||
final int index = 0;
|
||||
for (final Form arrayForm : value) {
|
||||
arrayForm.flush();
|
||||
arrayNode.insert(index, arrayForm.objectRoot);
|
||||
}
|
||||
this.objectRoot.set(entry.getKey(), arrayNode);
|
||||
}
|
||||
}
|
||||
|
||||
// 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) {
|
||||
@Override public String getValue() { return null; }
|
||||
@Override public void setValue(final String value) { field.setText(value); }
|
||||
};
|
||||
|
@ -230,26 +193,20 @@ public final class Form implements FormBinding {
|
|||
@Override public void setValue(final String value) { text.setText(value); }
|
||||
};
|
||||
}
|
||||
private FormFieldAccessor createAccessor(final Label label, final SingleSelection singleSelection) {
|
||||
return new FormFieldAccessor(label, singleSelection) {
|
||||
@Override public String getValue() { return singleSelection.getSelectionValue(); }
|
||||
@Override public void setValue(final String value) { singleSelection.select(value); }
|
||||
};
|
||||
private FormFieldAccessor createAccessor(final Label label, final Selection selection) {
|
||||
switch (selection.type()) {
|
||||
case MULTI : return createAccessor(label, selection, Form::adaptCommaSeparatedStringToJsonArray);
|
||||
default : return createAccessor(label, selection, null);
|
||||
}
|
||||
}
|
||||
private FormFieldAccessor createAccessor(final Label label,final MultiSelection multiSelection) {
|
||||
return new FormFieldAccessor(label, multiSelection) {
|
||||
@Override public String getValue() { return multiSelection.getSelectionValue(); }
|
||||
@Override public void setValue(final String value) { multiSelection.select(value); }
|
||||
@Override public void putJsonValue(final String key, final ObjectNode objectRoot) {
|
||||
final String value = getValue();
|
||||
if (StringUtils.isNoneBlank(value)) {
|
||||
final ArrayNode arrayNode = objectRoot.putArray(key);
|
||||
final String[] split = StringUtils.split(value, Constants.LIST_SEPARATOR);
|
||||
for (int i = 0; i < split.length; i++) {
|
||||
arrayNode.add(split[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
private FormFieldAccessor createAccessor(
|
||||
final Label label,
|
||||
final Selection selection,
|
||||
final BiConsumer<Tuple<String>, ObjectNode> jsonValueAdapter) {
|
||||
|
||||
return new FormFieldAccessor(label, selection.adaptToControl(), jsonValueAdapter) {
|
||||
@Override public String getValue() { return selection.getSelectionValue(); }
|
||||
@Override public void setValue(final String value) { selection.select(value); }
|
||||
};
|
||||
}
|
||||
private FormFieldAccessor createAccessor(final Label label, final ImageUpload imageUpload) {
|
||||
|
@ -281,15 +238,44 @@ public final class Form implements FormBinding {
|
|||
}
|
||||
}
|
||||
|
||||
private static final void adaptCommaSeparatedStringToJsonArray(final Tuple<String> tuple,
|
||||
final ObjectNode jsonNode) {
|
||||
if (StringUtils.isNoneBlank(tuple._2)) {
|
||||
final ArrayNode arrayNode = jsonNode.putArray(tuple._1);
|
||||
final String[] split = StringUtils.split(tuple._2, Constants.LIST_SEPARATOR);
|
||||
for (int i = 0; i < split.length; i++) {
|
||||
arrayNode.add(split[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static abstract class FormFieldAccessor {
|
||||
|
||||
public final Label label;
|
||||
public final Control control;
|
||||
private final BiConsumer<Tuple<String>, ObjectNode> jsonValueAdapter;
|
||||
private boolean hasError;
|
||||
|
||||
public FormFieldAccessor(final Label label, final Control control) {
|
||||
FormFieldAccessor(final Label label, final Control control) {
|
||||
this(label, control, null);
|
||||
}
|
||||
|
||||
FormFieldAccessor(
|
||||
final Label label,
|
||||
final Control control,
|
||||
final BiConsumer<Tuple<String>, ObjectNode> jsonValueAdapter) {
|
||||
|
||||
this.label = label;
|
||||
this.control = control;
|
||||
if (jsonValueAdapter != null) {
|
||||
this.jsonValueAdapter = jsonValueAdapter;
|
||||
} else {
|
||||
this.jsonValueAdapter = (tuple, jsonObject) -> {
|
||||
if (StringUtils.isNoneBlank(tuple._2)) {
|
||||
jsonObject.put(tuple._1, tuple._2);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public abstract String getValue();
|
||||
|
@ -301,11 +287,8 @@ public final class Form implements FormBinding {
|
|||
this.control.setVisible(visible);
|
||||
}
|
||||
|
||||
public void putJsonValue(final String key, final ObjectNode objectRoot) {
|
||||
final String value = getValue();
|
||||
if (StringUtils.isNoneBlank(value)) {
|
||||
objectRoot.put(key, value);
|
||||
}
|
||||
public final void putJsonValue(final String key, final ObjectNode objectRoot) {
|
||||
this.jsonValueAdapter.accept(new Tuple<>(key, getValue()), objectRoot);
|
||||
}
|
||||
|
||||
public void setError(final String errorTooltip) {
|
||||
|
|
|
@ -30,6 +30,7 @@ import ch.ethz.seb.sebserver.gbl.util.Tuple;
|
|||
import ch.ethz.seb.sebserver.gui.service.i18n.PolyglotPageService;
|
||||
import ch.ethz.seb.sebserver.gui.service.page.PageContext;
|
||||
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;
|
||||
|
||||
|
@ -194,7 +195,7 @@ public class FormBuilder {
|
|||
final String value,
|
||||
final Supplier<List<Tuple<String>>> itemsSupplier) {
|
||||
|
||||
return new SelectionFieldBuilder(name, label, value, itemsSupplier);
|
||||
return new SelectionFieldBuilder(Selection.Type.SINGLE, name, label, value, itemsSupplier);
|
||||
}
|
||||
|
||||
public static SelectionFieldBuilder multiSelection(
|
||||
|
@ -203,8 +204,16 @@ public class FormBuilder {
|
|||
final String value,
|
||||
final Supplier<List<Tuple<String>>> itemsSupplier) {
|
||||
|
||||
return new SelectionFieldBuilder(name, label, value, itemsSupplier)
|
||||
.asMultiSelection();
|
||||
return new SelectionFieldBuilder(Selection.Type.MULTI, name, label, value, itemsSupplier);
|
||||
}
|
||||
|
||||
public static SelectionFieldBuilder multiComboSelection(
|
||||
final String name,
|
||||
final String label,
|
||||
final String value,
|
||||
final Supplier<List<Tuple<String>>> itemsSupplier) {
|
||||
|
||||
return new SelectionFieldBuilder(Selection.Type.MULTI_COMBO, name, label, value, itemsSupplier);
|
||||
}
|
||||
|
||||
public static ImageUploadFieldBuilder imageUpload(final String name, final String label, final String value) {
|
||||
|
|
|
@ -26,24 +26,25 @@ import org.eclipse.swt.widgets.Label;
|
|||
import ch.ethz.seb.sebserver.gbl.Constants;
|
||||
import ch.ethz.seb.sebserver.gbl.util.Tuple;
|
||||
import ch.ethz.seb.sebserver.gui.service.i18n.PolyglotPageService;
|
||||
import ch.ethz.seb.sebserver.gui.widget.MultiSelection;
|
||||
import ch.ethz.seb.sebserver.gui.widget.Selection;
|
||||
import ch.ethz.seb.sebserver.gui.widget.SingleSelection;
|
||||
import ch.ethz.seb.sebserver.gui.widget.Selection.Type;
|
||||
import ch.ethz.seb.sebserver.gui.widget.WidgetFactory.CustomVariant;
|
||||
|
||||
public final class SelectionFieldBuilder extends FieldBuilder {
|
||||
|
||||
final Supplier<List<Tuple<String>>> itemsSupplier;
|
||||
Consumer<Form> selectionListener = null;
|
||||
boolean multi = false;
|
||||
final Selection.Type type;
|
||||
|
||||
SelectionFieldBuilder(
|
||||
final Selection.Type type,
|
||||
final String name,
|
||||
final String label,
|
||||
final String value,
|
||||
final Supplier<List<Tuple<String>>> itemsSupplier) {
|
||||
|
||||
super(name, label, value);
|
||||
this.type = type;
|
||||
this.itemsSupplier = itemsSupplier;
|
||||
}
|
||||
|
||||
|
@ -52,11 +53,6 @@ public final class SelectionFieldBuilder extends FieldBuilder {
|
|||
return this;
|
||||
}
|
||||
|
||||
public SelectionFieldBuilder asMultiSelection() {
|
||||
this.multi = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
void build(final FormBuilder builder) {
|
||||
final Label lab = builder.labelLocalized(builder.formParent, this.label, this.spanLabel);
|
||||
|
@ -68,29 +64,29 @@ public final class SelectionFieldBuilder extends FieldBuilder {
|
|||
}
|
||||
|
||||
private void buildInput(final FormBuilder builder, final Label lab) {
|
||||
final Selection selection = (this.multi)
|
||||
? builder.widgetFactory.multiSelectionLocalized(builder.formParent, this.itemsSupplier)
|
||||
: builder.widgetFactory.singleSelectionLocalized(builder.formParent, this.itemsSupplier);
|
||||
|
||||
final Selection selection = builder.widgetFactory.selectionLocalized(
|
||||
this.type,
|
||||
builder.formParent,
|
||||
this.itemsSupplier);
|
||||
|
||||
final GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, false, this.spanInput, 1);
|
||||
((Control) selection).setLayoutData(gridData);
|
||||
selection.select(this.value);
|
||||
if (this.multi) {
|
||||
builder.form.putField(this.name, lab, selection.<MultiSelection> getTypeInstance());
|
||||
} else {
|
||||
builder.form.putField(this.name, lab, selection.<SingleSelection> getTypeInstance());
|
||||
}
|
||||
builder.form.putField(this.name, lab, selection);
|
||||
|
||||
if (this.selectionListener != null) {
|
||||
((Control) selection).addListener(SWT.Selection, e -> {
|
||||
this.selectionListener.accept(builder.form);
|
||||
});
|
||||
}
|
||||
|
||||
builder.setFieldVisible(this.visible, this.name);
|
||||
}
|
||||
|
||||
/* Build the read-only representation of the selection field */
|
||||
private void buildReadOnly(final FormBuilder builder, final Label lab) {
|
||||
if (this.multi) {
|
||||
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);
|
||||
gridLayout.horizontalSpacing = 0;
|
||||
|
@ -99,7 +95,11 @@ public final class SelectionFieldBuilder extends FieldBuilder {
|
|||
gridLayout.marginWidth = 0;
|
||||
composite.setLayout(gridLayout);
|
||||
if (StringUtils.isBlank(this.value)) {
|
||||
createMuliSelectionReadonlyLabel(composite, Constants.EMPTY_NOTE);
|
||||
final Label label = new Label(composite, SWT.NONE);
|
||||
final GridData gridData = new GridData(SWT.FILL, SWT.CENTER, true, true);
|
||||
label.setLayoutData(gridData);
|
||||
label.setData(RWT.CUSTOM_VARIANT, CustomVariant.SELECTION_READONLY.key);
|
||||
label.setText(this.value);
|
||||
} else {
|
||||
final Collection<String> keys = Arrays.asList(StringUtils.split(this.value, Constants.LIST_SEPARATOR));
|
||||
this.itemsSupplier.get()
|
||||
|
@ -137,12 +137,4 @@ public final class SelectionFieldBuilder extends FieldBuilder {
|
|||
return label;
|
||||
}
|
||||
|
||||
private void createMuliSelectionReadonlyLabel(final Composite composite, final String value) {
|
||||
final Label label = new Label(composite, SWT.NONE);
|
||||
final GridData gridData = new GridData(SWT.FILL, SWT.CENTER, true, true);
|
||||
label.setLayoutData(gridData);
|
||||
label.setData(RWT.CUSTOM_VARIANT, CustomVariant.SELECTION_READONLY.key);
|
||||
label.setText(value);
|
||||
}
|
||||
|
||||
}
|
|
@ -23,7 +23,7 @@ import org.springframework.context.annotation.Lazy;
|
|||
import org.springframework.stereotype.Service;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.Constants;
|
||||
import ch.ethz.seb.sebserver.gbl.model.Domain;
|
||||
import ch.ethz.seb.sebserver.gbl.model.Entity;
|
||||
import ch.ethz.seb.sebserver.gbl.model.exam.Exam.ExamType;
|
||||
import ch.ethz.seb.sebserver.gbl.model.exam.Indicator.IndicatorType;
|
||||
import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetup.LmsType;
|
||||
|
@ -104,7 +104,7 @@ public class ResourceService {
|
|||
|
||||
public List<Tuple<String>> institutionResource() {
|
||||
return this.restService.getBuilder(GetInstitutionNames.class)
|
||||
.withQueryParam(Domain.INSTITUTION.ATTR_ACTIVE, "true")
|
||||
.withQueryParam(Entity.FILTER_ATTR_ACTIVE, Constants.TRUE_STRING)
|
||||
.call()
|
||||
.getOr(Collections.emptyList())
|
||||
.stream()
|
||||
|
@ -115,7 +115,7 @@ public class ResourceService {
|
|||
public Function<String, String> getInstitutionNameFunction() {
|
||||
|
||||
final Map<String, String> idNameMap = this.restService.getBuilder(GetInstitutionNames.class)
|
||||
.withQueryParam(Domain.INSTITUTION.ATTR_ACTIVE, "true")
|
||||
.withQueryParam(Entity.FILTER_ATTR_ACTIVE, Constants.TRUE_STRING)
|
||||
.call()
|
||||
.getOr(Collections.emptyList())
|
||||
.stream()
|
||||
|
@ -133,8 +133,8 @@ public class ResourceService {
|
|||
final boolean isSEBAdmin = this.currentUser.get().hasRole(UserRole.SEB_SERVER_ADMIN);
|
||||
final String institutionId = (isSEBAdmin) ? "" : String.valueOf(this.currentUser.get().institutionId);
|
||||
return this.restService.getBuilder(GetLmsSetupNames.class)
|
||||
.withQueryParam(Domain.LMS_SETUP.ATTR_INSTITUTION_ID, institutionId)
|
||||
.withQueryParam(Domain.LMS_SETUP.ATTR_ACTIVE, "true")
|
||||
.withQueryParam(Entity.FILTER_ATTR_INSTITUTION, institutionId)
|
||||
.withQueryParam(Entity.FILTER_ATTR_ACTIVE, Constants.TRUE_STRING)
|
||||
.call()
|
||||
.getOr(Collections.emptyList())
|
||||
.stream()
|
||||
|
@ -146,8 +146,8 @@ public class ResourceService {
|
|||
final boolean isSEBAdmin = this.currentUser.get().hasRole(UserRole.SEB_SERVER_ADMIN);
|
||||
final String institutionId = (isSEBAdmin) ? "" : String.valueOf(this.currentUser.get().institutionId);
|
||||
final Map<String, String> idNameMap = this.restService.getBuilder(GetLmsSetupNames.class)
|
||||
.withQueryParam(Domain.LMS_SETUP.ATTR_INSTITUTION_ID, institutionId)
|
||||
.withQueryParam(Domain.INSTITUTION.ATTR_ACTIVE, "true")
|
||||
.withQueryParam(Entity.FILTER_ATTR_INSTITUTION, institutionId)
|
||||
.withQueryParam(Entity.FILTER_ATTR_ACTIVE, Constants.TRUE_STRING)
|
||||
.call()
|
||||
.getOr(Collections.emptyList())
|
||||
.stream()
|
||||
|
@ -196,11 +196,24 @@ public class ResourceService {
|
|||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public List<Tuple<String>> examSupporterResources() {
|
||||
final UserInfo userInfo = this.currentUser.get();
|
||||
return this.restService.getBuilder(GetUserAccountNames.class)
|
||||
.withQueryParam(Entity.FILTER_ATTR_INSTITUTION, String.valueOf(userInfo.institutionId))
|
||||
.withQueryParam(Entity.FILTER_ATTR_ACTIVE, Constants.TRUE_STRING)
|
||||
.withQueryParam(UserInfo.FILTER_ATTR_ROLE, UserRole.EXAM_SUPPORTER.name())
|
||||
.call()
|
||||
.getOr(Collections.emptyList())
|
||||
.stream()
|
||||
.map(entityName -> new Tuple<>(entityName.modelId, entityName.name))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public List<Tuple<String>> userResources() {
|
||||
final UserInfo userInfo = this.currentUser.get();
|
||||
return this.restService.getBuilder(GetUserAccountNames.class)
|
||||
.withQueryParam(Domain.USER.ATTR_INSTITUTION_ID, String.valueOf(userInfo.institutionId))
|
||||
.withQueryParam(Domain.USER.ATTR_ACTIVE, "true")
|
||||
.withQueryParam(Entity.FILTER_ATTR_INSTITUTION, String.valueOf(userInfo.institutionId))
|
||||
.withQueryParam(Entity.FILTER_ATTR_ACTIVE, Constants.TRUE_STRING)
|
||||
.call()
|
||||
.getOr(Collections.emptyList())
|
||||
.stream()
|
||||
|
|
|
@ -0,0 +1,101 @@
|
|||
/*
|
||||
* Copyright (c) 2019 ETH Zürich, Educational Development and Technology (LET)
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package ch.ethz.seb.sebserver.gui.service.page;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.eclipse.rap.rwt.RWT;
|
||||
import org.eclipse.swt.SWT;
|
||||
import org.eclipse.swt.graphics.Rectangle;
|
||||
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.Dialog;
|
||||
import org.eclipse.swt.widgets.Shell;
|
||||
|
||||
import ch.ethz.seb.sebserver.gui.service.i18n.LocTextKey;
|
||||
import ch.ethz.seb.sebserver.gui.widget.WidgetFactory;
|
||||
|
||||
public class ModalInputDialog<T> extends Dialog {
|
||||
|
||||
private static final long serialVersionUID = -3448614119078234374L;
|
||||
|
||||
private final WidgetFactory widgetFactory;
|
||||
|
||||
private T returnValue = null;
|
||||
|
||||
public ModalInputDialog(
|
||||
final Shell parent,
|
||||
final WidgetFactory widgetFactory) {
|
||||
|
||||
super(parent, SWT.BORDER | SWT.TITLE | SWT.APPLICATION_MODAL);
|
||||
this.widgetFactory = widgetFactory;
|
||||
}
|
||||
|
||||
public void open(
|
||||
final String title,
|
||||
final PageContext pageContext,
|
||||
final Consumer<T> callback,
|
||||
final ModalInputDialogComposer<T> contentComposer) {
|
||||
|
||||
// Create the dialog window
|
||||
final Shell shell = new Shell(getParent(), getStyle());
|
||||
shell.setText(getText());
|
||||
shell.setData(RWT.CUSTOM_VARIANT, "message");
|
||||
shell.setText(title);
|
||||
shell.setLayout(new GridLayout(2, true));
|
||||
shell.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
|
||||
|
||||
final Composite main = new Composite(shell, SWT.NONE);
|
||||
main.setLayout(new GridLayout());
|
||||
final GridData gridData = new GridData(SWT.FILL, SWT.TOP, true, true);
|
||||
gridData.horizontalSpan = 2;
|
||||
main.setLayoutData(gridData);
|
||||
|
||||
final PageContext internalPageContext = pageContext.copyOf(main);
|
||||
final Supplier<T> valueSuppier = contentComposer.compose(internalPageContext);
|
||||
|
||||
final Button ok = this.widgetFactory.buttonLocalized(
|
||||
shell,
|
||||
new LocTextKey("sebserver.overall.action.ok"));
|
||||
GridData data = new GridData(GridData.HORIZONTAL_ALIGN_END);
|
||||
data.widthHint = 100;
|
||||
ok.setLayoutData(data);
|
||||
ok.addListener(SWT.Selection, event -> {
|
||||
callback.accept(valueSuppier.get());
|
||||
this.returnValue = valueSuppier.get();
|
||||
shell.close();
|
||||
});
|
||||
|
||||
shell.setDefaultButton(ok);
|
||||
|
||||
final Button cancel = this.widgetFactory.buttonLocalized(
|
||||
shell,
|
||||
new LocTextKey("sebserver.overall.action.cancel"));
|
||||
data = new GridData(GridData.CENTER);
|
||||
data.widthHint = 100;
|
||||
cancel.setLayoutData(data);
|
||||
cancel.addListener(SWT.Selection, event -> {
|
||||
shell.close();
|
||||
});
|
||||
|
||||
shell.pack();
|
||||
final Rectangle bounds = shell.getBounds();
|
||||
final Rectangle bounds2 = super.getParent().getDisplay().getBounds();
|
||||
bounds.width = 400;
|
||||
bounds.x = (bounds2.width - bounds.width) / 2;
|
||||
bounds.y = (bounds2.height - bounds.height) / 2;
|
||||
shell.setBounds(bounds);
|
||||
|
||||
shell.open();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
/*
|
||||
* Copyright (c) 2019 ETH Zürich, Educational Development and Technology (LET)
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package ch.ethz.seb.sebserver.gui.service.page;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface ModalInputDialogComposer<T> {
|
||||
|
||||
Supplier<T> compose(PageContext pageContext);
|
||||
|
||||
}
|
|
@ -325,10 +325,6 @@ public class EntityTable<ROW extends Entity> {
|
|||
|
||||
index++;
|
||||
}
|
||||
|
||||
// NOTE this.layout() triggers the navigation to disappear unexpectedly!?
|
||||
//this.table.layout(true, true);
|
||||
//this.composite.layout(true, true);
|
||||
} catch (final Exception e) {
|
||||
log.warn("Failed to adaptColumnWidth: ", e);
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@ import ch.ethz.seb.sebserver.gbl.Constants;
|
|||
import ch.ethz.seb.sebserver.gbl.model.Entity;
|
||||
import ch.ethz.seb.sebserver.gui.service.i18n.LocTextKey;
|
||||
import ch.ethz.seb.sebserver.gui.table.ColumnDefinition.TableFilterAttribute;
|
||||
import ch.ethz.seb.sebserver.gui.widget.SingleSelection;
|
||||
import ch.ethz.seb.sebserver.gui.widget.Selection;
|
||||
import ch.ethz.seb.sebserver.gui.widget.WidgetFactory.ImageIcon;
|
||||
|
||||
public class TableFilter<ROW extends Entity> {
|
||||
|
@ -105,7 +105,7 @@ public class TableFilter<ROW extends Entity> {
|
|||
case TEXT:
|
||||
return new TextFilter(attribute);
|
||||
case SINGLE_SELECTION:
|
||||
return new Selection(attribute);
|
||||
return new SelectionFilter(attribute);
|
||||
case DATE:
|
||||
return new Date(attribute);
|
||||
default:
|
||||
|
@ -245,21 +245,24 @@ public class TableFilter<ROW extends Entity> {
|
|||
|
||||
}
|
||||
|
||||
private class Selection extends FilterComponent {
|
||||
private class SelectionFilter extends FilterComponent {
|
||||
|
||||
protected SingleSelection selector;
|
||||
protected Selection selector;
|
||||
|
||||
Selection(final TableFilterAttribute attribute) {
|
||||
SelectionFilter(final TableFilterAttribute attribute) {
|
||||
super(attribute);
|
||||
}
|
||||
|
||||
@Override
|
||||
FilterComponent build(final Composite parent) {
|
||||
this.selector = TableFilter.this.entityTable.widgetFactory
|
||||
.singleSelectionLocalized(
|
||||
.selectionLocalized(
|
||||
ch.ethz.seb.sebserver.gui.widget.Selection.Type.SINGLE,
|
||||
parent,
|
||||
this.attribute.resourceSupplier);
|
||||
this.selector.setLayoutData(this.rowData);
|
||||
this.selector
|
||||
.adaptToControl()
|
||||
.setLayoutData(this.rowData);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
|
@ -34,7 +34,7 @@ public class MultiSelection extends Composite implements Selection {
|
|||
private final List<Label> labels = new ArrayList<>();
|
||||
private final List<Label> selected = new ArrayList<>();
|
||||
|
||||
public MultiSelection(final Composite parent) {
|
||||
MultiSelection(final Composite parent) {
|
||||
super(parent, SWT.NONE);
|
||||
final GridLayout gridLayout = new GridLayout(1, true);
|
||||
gridLayout.verticalSpacing = 1;
|
||||
|
@ -44,6 +44,11 @@ public class MultiSelection extends Composite implements Selection {
|
|||
setLayout(gridLayout);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type type() {
|
||||
return Type.MULTI;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyNewMapping(final List<Tuple<String>> mapping) {
|
||||
final String selectionValue = getSelectionValue();
|
||||
|
@ -134,10 +139,4 @@ public class MultiSelection extends Composite implements Selection {
|
|||
deselectAll();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public MultiSelection getTypeInstance() {
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,131 @@
|
|||
/*
|
||||
* Copyright (c) 2019 ETH Zürich, Educational Development and Technology (LET)
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package ch.ethz.seb.sebserver.gui.widget;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.eclipse.swt.SWT;
|
||||
import org.eclipse.swt.custom.TableEditor;
|
||||
import org.eclipse.swt.layout.GridLayout;
|
||||
import org.eclipse.swt.widgets.Combo;
|
||||
import org.eclipse.swt.widgets.Composite;
|
||||
import org.eclipse.swt.widgets.Event;
|
||||
import org.eclipse.swt.widgets.Table;
|
||||
import org.eclipse.swt.widgets.TableColumn;
|
||||
import org.eclipse.swt.widgets.TableItem;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.Constants;
|
||||
import ch.ethz.seb.sebserver.gbl.util.Tuple;
|
||||
import ch.ethz.seb.sebserver.gui.service.i18n.LocTextKey;
|
||||
import ch.ethz.seb.sebserver.gui.widget.WidgetFactory.ImageIcon;
|
||||
|
||||
public class MultiSelectionCombo extends Composite implements Selection {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(MultiSelectionCombo.class);
|
||||
private static final long serialVersionUID = -7787134114963647332L;
|
||||
private static final int ACTION_COLUMN_WIDTH = 20;
|
||||
|
||||
private final WidgetFactory widgetFactory;
|
||||
private final Table table;
|
||||
private final Combo combo;
|
||||
private final List<String> selected = new ArrayList<>();
|
||||
private final List<Tuple<String>> mapping = new ArrayList<>();
|
||||
|
||||
MultiSelectionCombo(final Composite parent, final WidgetFactory widgetFactory) {
|
||||
super(parent, SWT.NONE);
|
||||
this.widgetFactory = widgetFactory;
|
||||
final GridLayout gridLayout = new GridLayout(1, true);
|
||||
gridLayout.verticalSpacing = 1;
|
||||
gridLayout.marginLeft = 0;
|
||||
gridLayout.marginHeight = 0;
|
||||
gridLayout.marginWidth = 0;
|
||||
setLayout(gridLayout);
|
||||
|
||||
this.table = new Table(this, SWT.NONE);
|
||||
|
||||
TableColumn column = new TableColumn(this.table, SWT.NONE);
|
||||
column = new TableColumn(this.table, SWT.NONE);
|
||||
column.setWidth(ACTION_COLUMN_WIDTH);
|
||||
this.table.setHeaderVisible(false);
|
||||
this.table.addListener(SWT.Resize, this::adaptColumnWidth);
|
||||
|
||||
final TableItem header = new TableItem(this.table, SWT.NONE);
|
||||
final TableEditor editor = new TableEditor(this.table);
|
||||
this.combo = new Combo(this.table, SWT.NONE);
|
||||
editor.grabHorizontal = true;
|
||||
editor.setEditor(this.combo, header, 0);
|
||||
|
||||
widgetFactory.imageButton(
|
||||
ImageIcon.ADD,
|
||||
this.table,
|
||||
new LocTextKey("Add"),
|
||||
this::addComboSelection);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type type() {
|
||||
return Type.MULTI_COMBO;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyNewMapping(final List<Tuple<String>> mapping) {
|
||||
this.selected.clear();
|
||||
this.mapping.clear();
|
||||
this.mapping.addAll(mapping);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void select(final String keys) {
|
||||
clear();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSelectionValue() {
|
||||
if (this.selected.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
return this.mapping
|
||||
.stream()
|
||||
.filter(t -> this.selected.contains(t._2))
|
||||
.map(t -> t._1)
|
||||
.reduce("", (s1, s2) -> s1.concat(Constants.LIST_SEPARATOR).concat(s2));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
this.selected.clear();
|
||||
this.table.remove(1, this.table.getItemCount());
|
||||
final List<String> names = this.mapping
|
||||
.stream()
|
||||
.map(t -> t._2)
|
||||
.collect(Collectors.toList());
|
||||
this.combo.setItems(names.toArray(new String[names.size()]));
|
||||
}
|
||||
|
||||
private void addComboSelection(final Event event) {
|
||||
|
||||
}
|
||||
|
||||
private void adaptColumnWidth(final Event event) {
|
||||
try {
|
||||
final int currentTableWidth = this.table.getParent().getClientArea().width;
|
||||
this.table.getColumn(0).setWidth(currentTableWidth - ACTION_COLUMN_WIDTH);
|
||||
} catch (final Exception e) {
|
||||
log.warn("Failed to adaptColumnWidth: ", e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -10,10 +10,20 @@ package ch.ethz.seb.sebserver.gui.widget;
|
|||
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.swt.widgets.Control;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.util.Tuple;
|
||||
|
||||
public interface Selection {
|
||||
|
||||
enum Type {
|
||||
SINGLE,
|
||||
MULTI,
|
||||
MULTI_COMBO
|
||||
}
|
||||
|
||||
Type type();
|
||||
|
||||
void applyNewMapping(final List<Tuple<String>> mapping);
|
||||
|
||||
void select(final String keys);
|
||||
|
@ -24,6 +34,10 @@ public interface Selection {
|
|||
|
||||
void setVisible(boolean visible);
|
||||
|
||||
<T extends Selection> T getTypeInstance();
|
||||
default Control adaptToControl() {
|
||||
return (Control) this;
|
||||
}
|
||||
|
||||
//<T extends Selection> T getTypeInstance();
|
||||
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ public class SingleSelection extends Combo implements Selection {
|
|||
final List<String> valueMapping;
|
||||
final List<String> keyMapping;
|
||||
|
||||
public SingleSelection(final Composite parent) {
|
||||
SingleSelection(final Composite parent) {
|
||||
super(parent, SWT.READ_ONLY);
|
||||
this.valueMapping = new ArrayList<>();
|
||||
this.keyMapping = new ArrayList<>();
|
||||
|
@ -72,10 +72,9 @@ public class SingleSelection extends Combo implements Selection {
|
|||
super.setItems(this.valueMapping.toArray(new String[this.valueMapping.size()]));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public SingleSelection getTypeInstance() {
|
||||
return this;
|
||||
public Type type() {
|
||||
return Type.SINGLE;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -60,6 +60,8 @@ public class WidgetFactory {
|
|||
public enum ImageIcon {
|
||||
MAXIMIZE("maximize.png"),
|
||||
MINIMIZE("minimize.png"),
|
||||
ADD("add.png"),
|
||||
REMOVE("remove.png"),
|
||||
EDIT("edit.png"),
|
||||
TEST("test.png"),
|
||||
IMPORT("import.png"),
|
||||
|
@ -307,27 +309,64 @@ public class WidgetFactory {
|
|||
return imageButton;
|
||||
}
|
||||
|
||||
public SingleSelection singleSelectionLocalized(
|
||||
public Selection selectionLocalized(
|
||||
final Selection.Type type,
|
||||
final Composite parent,
|
||||
final Supplier<List<Tuple<String>>> itemsSupplier) {
|
||||
|
||||
final SingleSelection singleSelection = new SingleSelection(parent);
|
||||
final Consumer<SingleSelection> updateFunction = ss -> ss.applyNewMapping(itemsSupplier.get());
|
||||
singleSelection.setData(POLYGLOT_WIDGET_FUNCTION_KEY, updateFunction);
|
||||
updateFunction.accept(singleSelection);
|
||||
return singleSelection;
|
||||
final Selection selection;
|
||||
switch (type) {
|
||||
case SINGLE:
|
||||
selection = new SingleSelection(parent);
|
||||
break;
|
||||
case MULTI:
|
||||
selection = new MultiSelection(parent);
|
||||
break;
|
||||
case MULTI_COMBO:
|
||||
selection = new MultiSelectionCombo(parent, this);
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("Unsupported Selection.Type: " + type);
|
||||
}
|
||||
|
||||
final Consumer<Selection> updateFunction = ss -> ss.applyNewMapping(itemsSupplier.get());
|
||||
selection.adaptToControl().setData(POLYGLOT_WIDGET_FUNCTION_KEY, updateFunction);
|
||||
updateFunction.accept(selection);
|
||||
return selection;
|
||||
}
|
||||
|
||||
public MultiSelection multiSelectionLocalized(
|
||||
final Composite parent,
|
||||
final Supplier<List<Tuple<String>>> itemsSupplier) {
|
||||
|
||||
final MultiSelection multiSelection = new MultiSelection(parent);
|
||||
final Consumer<MultiSelection> updateFunction = ss -> ss.applyNewMapping(itemsSupplier.get());
|
||||
multiSelection.setData(POLYGLOT_WIDGET_FUNCTION_KEY, updateFunction);
|
||||
updateFunction.accept(multiSelection);
|
||||
return multiSelection;
|
||||
}
|
||||
// public SingleSelection singleSelectionLocalized(
|
||||
// final Composite parent,
|
||||
// final Supplier<List<Tuple<String>>> itemsSupplier) {
|
||||
//
|
||||
// final SingleSelection singleSelection = new SingleSelection(parent);
|
||||
// final Consumer<SingleSelection> updateFunction = ss -> ss.applyNewMapping(itemsSupplier.get());
|
||||
// singleSelection.setData(POLYGLOT_WIDGET_FUNCTION_KEY, updateFunction);
|
||||
// updateFunction.accept(singleSelection);
|
||||
// return singleSelection;
|
||||
// }
|
||||
//
|
||||
// public MultiSelection multiSelectionLocalized(
|
||||
// final Composite parent,
|
||||
// final Supplier<List<Tuple<String>>> itemsSupplier) {
|
||||
//
|
||||
// final MultiSelection multiSelection = new MultiSelection(parent);
|
||||
// final Consumer<MultiSelection> updateFunction = ss -> ss.applyNewMapping(itemsSupplier.get());
|
||||
// multiSelection.setData(POLYGLOT_WIDGET_FUNCTION_KEY, updateFunction);
|
||||
// updateFunction.accept(multiSelection);
|
||||
// return multiSelection;
|
||||
// }
|
||||
//
|
||||
// public MultiSelectionCombo multiSelectionComboLocalized(
|
||||
// final Composite parent,
|
||||
// final Supplier<List<Tuple<String>>> itemsSupplier) {
|
||||
//
|
||||
// final MultiSelectionCombo multiSelection = new MultiSelectionCombo(parent, this);
|
||||
// final Consumer<MultiSelectionCombo> updateFunction = ss -> ss.applyNewMapping(itemsSupplier.get());
|
||||
// multiSelection.setData(POLYGLOT_WIDGET_FUNCTION_KEY, updateFunction);
|
||||
// updateFunction.accept(multiSelection);
|
||||
// return multiSelection;
|
||||
// }
|
||||
|
||||
public ImageUpload imageUploadLocalized(
|
||||
final Composite parent,
|
||||
|
|
|
@ -170,7 +170,7 @@ public class ClientCredentialServiceImpl implements ClientCredentialService {
|
|||
}
|
||||
|
||||
private final static char[] possibleCharacters = (new String(
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789~`!@#$%^&*()-_=+[{]}?"))
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789~`!@#$%^*()-_=+[{]}?"))
|
||||
.toCharArray();
|
||||
|
||||
private CharSequence getSalt(final CharSequence saltPlain) throws UnsupportedEncodingException {
|
||||
|
|
|
@ -67,6 +67,10 @@ public class FilterMap extends POSTMapper {
|
|||
return getString(UserInfo.FILTER_ATTR_LANGUAGE);
|
||||
}
|
||||
|
||||
public String getUserRole() {
|
||||
return getString(UserInfo.FILTER_ATTR_ROLE);
|
||||
}
|
||||
|
||||
public String getLmsSetupType() {
|
||||
return getString(LmsSetup.FILTER_ATTR_LMS_TYPE);
|
||||
}
|
||||
|
|
|
@ -150,33 +150,40 @@ public class UserDAOImpl implements UserDAO {
|
|||
@Override
|
||||
@Transactional(readOnly = true)
|
||||
public Result<Collection<UserInfo>> allMatching(final FilterMap filterMap, final Predicate<UserInfo> predicate) {
|
||||
return Result.tryCatch(() -> this.userRecordMapper
|
||||
.selectByExample()
|
||||
.where(
|
||||
UserRecordDynamicSqlSupport.active,
|
||||
isEqualToWhenPresent(filterMap.getActiveAsInt()))
|
||||
.and(
|
||||
UserRecordDynamicSqlSupport.institutionId,
|
||||
isEqualToWhenPresent(filterMap.getInstitutionId()))
|
||||
.and(
|
||||
UserRecordDynamicSqlSupport.name,
|
||||
isLikeWhenPresent(filterMap.getName()))
|
||||
.and(
|
||||
UserRecordDynamicSqlSupport.username,
|
||||
isLikeWhenPresent(filterMap.getUserUsername()))
|
||||
.and(
|
||||
UserRecordDynamicSqlSupport.email,
|
||||
isLikeWhenPresent(filterMap.getUserEmail()))
|
||||
.and(
|
||||
UserRecordDynamicSqlSupport.language,
|
||||
isLikeWhenPresent(filterMap.getUserLanguage()))
|
||||
.build()
|
||||
.execute()
|
||||
.stream()
|
||||
.map(this::toDomainModel)
|
||||
.flatMap(DAOLoggingSupport::logUnexpectedErrorAndSkip)
|
||||
.filter(predicate)
|
||||
.collect(Collectors.toList()));
|
||||
return Result.tryCatch(() -> {
|
||||
final String userRole = filterMap.getUserRole();
|
||||
final Predicate<UserInfo> _predicate = (StringUtils.isNotBlank(userRole))
|
||||
? predicate.and(ui -> ui.roles.contains(userRole))
|
||||
: predicate;
|
||||
|
||||
return this.userRecordMapper
|
||||
.selectByExample()
|
||||
.where(
|
||||
UserRecordDynamicSqlSupport.active,
|
||||
isEqualToWhenPresent(filterMap.getActiveAsInt()))
|
||||
.and(
|
||||
UserRecordDynamicSqlSupport.institutionId,
|
||||
isEqualToWhenPresent(filterMap.getInstitutionId()))
|
||||
.and(
|
||||
UserRecordDynamicSqlSupport.name,
|
||||
isLikeWhenPresent(filterMap.getName()))
|
||||
.and(
|
||||
UserRecordDynamicSqlSupport.username,
|
||||
isLikeWhenPresent(filterMap.getUserUsername()))
|
||||
.and(
|
||||
UserRecordDynamicSqlSupport.email,
|
||||
isLikeWhenPresent(filterMap.getUserEmail()))
|
||||
.and(
|
||||
UserRecordDynamicSqlSupport.language,
|
||||
isLikeWhenPresent(filterMap.getUserLanguage()))
|
||||
.build()
|
||||
.execute()
|
||||
.stream()
|
||||
.map(this::toDomainModel)
|
||||
.flatMap(DAOLoggingSupport::logUnexpectedErrorAndSkip)
|
||||
.filter(_predicate)
|
||||
.collect(Collectors.toList());
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -12,6 +12,8 @@ sebserver.overall.action.modify.cancel=Cancel
|
|||
sebserver.overall.action.modify.cancel.confirm=Are you sure to cancel? Modifications will be lost.
|
||||
sebserver.overall.action.filter=Apply Filter
|
||||
sebserver.overall.action.filter.clear=Clear Filter Criteria
|
||||
sebserver.overall.action.ok=OK
|
||||
sebserver.overall.action.cancel=Cancel
|
||||
|
||||
sebserver.overall.action.category.varia=Varia
|
||||
|
||||
|
|
|
@ -96,7 +96,7 @@ Label.selected {
|
|||
Label-SeparatorLine {
|
||||
background-image: none;
|
||||
background-color: transparent;
|
||||
border: 1px solid #595959;
|
||||
border: 1px solid #bdbdbd;
|
||||
border-radius: 0px;
|
||||
height: 1px;
|
||||
}
|
||||
|
|
BIN
src/main/resources/static/images/add.png
Normal file
BIN
src/main/resources/static/images/add.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 98 B |
BIN
src/main/resources/static/images/remove.png
Normal file
BIN
src/main/resources/static/images/remove.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 85 B |
Loading…
Reference in a new issue