SEBSERV-27 User Account Form language and Time Zone selector
This commit is contained in:
parent
88356ed821
commit
422d816093
28 changed files with 772 additions and 354 deletions
|
@ -17,6 +17,8 @@ public final class Constants {
|
|||
public static final Character LIST_SEPARATOR_CHAR = ',';
|
||||
public static final String LIST_SEPARATOR = ",";
|
||||
public static final String EMPTY_NOTE = "--";
|
||||
public static final String FORM_URL_ENCODED_SEPARATOR = "&";
|
||||
public static final String FORM_URL_ENCODED_NAME_VALUE_SEPARATOR = "=";
|
||||
|
||||
/** Date-Time formatter without milliseconds using UTC time-zone. Pattern is yyyy-MM-dd HH:mm:ss */
|
||||
public static final DateTimeFormatter DATE_TIME_PATTERN_UTC_NO_MILLIS = DateTimeFormat
|
||||
|
|
|
@ -54,6 +54,10 @@ public class APIMessage implements Serializable {
|
|||
this.systemMessage = systemMessage;
|
||||
}
|
||||
|
||||
public boolean isOf(final APIMessage message) {
|
||||
return message != null && this.messageCode.equals(message.messageCode);
|
||||
}
|
||||
|
||||
public APIMessage of() {
|
||||
return new APIMessage(this.messageCode, this.systemMessage);
|
||||
}
|
||||
|
|
|
@ -11,7 +11,6 @@ package ch.ethz.seb.sebserver.gbl.model;
|
|||
import javax.validation.constraints.NotNull;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.api.EntityType;
|
||||
|
@ -24,20 +23,21 @@ public class EntityKey {
|
|||
@JsonProperty(value = "entityType", required = true)
|
||||
@NotNull
|
||||
public final EntityType entityType;
|
||||
@JsonIgnore
|
||||
public final boolean isIdPK;
|
||||
|
||||
@JsonCreator
|
||||
public EntityKey(
|
||||
@JsonProperty(value = "modelId", required = true) final String modelId,
|
||||
@JsonProperty(value = "entityType", required = true) final EntityType entityType) {
|
||||
|
||||
assert (modelId != null) : "modelId has null reference";
|
||||
assert (entityType != null) : "entityType has null reference";
|
||||
if (modelId == null) {
|
||||
throw new IllegalArgumentException("modelId has null reference");
|
||||
}
|
||||
if (entityType == null) {
|
||||
throw new IllegalArgumentException("entityType has null reference");
|
||||
}
|
||||
|
||||
this.modelId = modelId;
|
||||
this.entityType = entityType;
|
||||
this.isIdPK = entityType != EntityType.USER;
|
||||
}
|
||||
|
||||
public EntityKey(
|
||||
|
@ -46,7 +46,6 @@ public class EntityKey {
|
|||
|
||||
this.modelId = String.valueOf(pk);
|
||||
this.entityType = entityType;
|
||||
this.isIdPK = true;
|
||||
}
|
||||
|
||||
public String getModelId() {
|
||||
|
|
|
@ -13,12 +13,18 @@ import java.util.Set;
|
|||
|
||||
import org.joda.time.DateTimeZone;
|
||||
|
||||
public interface UserAccount {
|
||||
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.GrantEntity;
|
||||
|
||||
public interface UserAccount extends GrantEntity {
|
||||
|
||||
@Override
|
||||
String getModelId();
|
||||
|
||||
@Override
|
||||
Long getInstitutionId();
|
||||
|
||||
@Override
|
||||
String getName();
|
||||
|
||||
String getUsername();
|
||||
|
@ -39,4 +45,7 @@ public interface UserAccount {
|
|||
|
||||
String getRetypedNewPassword();
|
||||
|
||||
@Override
|
||||
EntityKey getEntityKey();
|
||||
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ import javax.validation.constraints.NotNull;
|
|||
import javax.validation.constraints.Size;
|
||||
|
||||
import org.apache.commons.lang3.BooleanUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.joda.time.DateTimeZone;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
|
@ -28,8 +29,8 @@ import ch.ethz.seb.sebserver.gbl.api.EntityType;
|
|||
import ch.ethz.seb.sebserver.gbl.model.Activatable;
|
||||
import ch.ethz.seb.sebserver.gbl.model.Domain.USER;
|
||||
import ch.ethz.seb.sebserver.gbl.model.Domain.USER_ROLE;
|
||||
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
|
||||
import ch.ethz.seb.sebserver.gbl.util.Utils;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.GrantEntity;
|
||||
|
||||
/** The user info domain model contains primary user information
|
||||
*
|
||||
|
@ -37,7 +38,7 @@ import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.GrantEntity;
|
|||
* to and from JSON within the Jackson library.
|
||||
*
|
||||
* This domain model is immutable and thread-save */
|
||||
public final class UserInfo implements UserAccount, GrantEntity, Activatable, Serializable {
|
||||
public final class UserInfo implements UserAccount, Activatable, Serializable {
|
||||
|
||||
private static final long serialVersionUID = 2526446136264377808L;
|
||||
|
||||
|
@ -197,6 +198,15 @@ public final class UserInfo implements UserAccount, GrantEntity, Activatable, Se
|
|||
return null;
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
@Override
|
||||
public EntityKey getEntityKey() {
|
||||
if (StringUtils.isBlank(this.uuid)) {
|
||||
return null;
|
||||
}
|
||||
return new EntityKey(this.uuid, entityType());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
|
|
|
@ -16,9 +16,11 @@ import javax.validation.constraints.Email;
|
|||
import javax.validation.constraints.NotNull;
|
||||
import javax.validation.constraints.Size;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.joda.time.DateTimeZone;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
|
@ -26,9 +28,9 @@ import ch.ethz.seb.sebserver.gbl.api.EntityType;
|
|||
import ch.ethz.seb.sebserver.gbl.api.POSTMapper;
|
||||
import ch.ethz.seb.sebserver.gbl.model.Domain.USER;
|
||||
import ch.ethz.seb.sebserver.gbl.model.Domain.USER_ROLE;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.GrantEntity;
|
||||
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
|
||||
|
||||
public final class UserMod implements UserAccount, GrantEntity {
|
||||
public final class UserMod implements UserAccount {
|
||||
|
||||
public static final String ATTR_NAME_NEW_PASSWORD = "newPassword";
|
||||
public static final String ATTR_NAME_RETYPED_NEW_PASSWORD = "retypedNewPassword";
|
||||
|
@ -71,10 +73,12 @@ public final class UserMod implements UserAccount, GrantEntity {
|
|||
@JsonProperty(USER_ROLE.REFERENCE_NAME)
|
||||
public final Set<String> roles;
|
||||
|
||||
@NotNull(message = "user:newPassword:notNull")
|
||||
@Size(min = 8, max = 255, message = "user:password:size:{min}:{max}:${validatedValue}")
|
||||
@JsonProperty(ATTR_NAME_NEW_PASSWORD)
|
||||
private final String newPassword;
|
||||
|
||||
@NotNull(message = "user:retypedNewPassword:notNull")
|
||||
@JsonProperty(ATTR_NAME_RETYPED_NEW_PASSWORD)
|
||||
private final String retypedNewPassword;
|
||||
|
||||
|
@ -140,9 +144,9 @@ public final class UserMod implements UserAccount, GrantEntity {
|
|||
this.name = null;
|
||||
this.username = null;
|
||||
this.email = null;
|
||||
this.locale = null;
|
||||
this.timeZone = null;
|
||||
this.roles = null;
|
||||
this.locale = Locale.ENGLISH;
|
||||
this.timeZone = DateTimeZone.UTC;
|
||||
this.roles = Collections.emptySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -223,6 +227,15 @@ public final class UserMod implements UserAccount, GrantEntity {
|
|||
return false;
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
@Override
|
||||
public EntityKey getEntityKey() {
|
||||
if (StringUtils.isBlank(this.uuid)) {
|
||||
return null;
|
||||
}
|
||||
return new EntityKey(this.uuid, entityType());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "UserMod [uuid=" + this.uuid + ", institutionId=" + this.institutionId + ", name=" + this.name
|
||||
|
|
|
@ -110,15 +110,9 @@ public class RAPConfiguration implements ApplicationConfiguration {
|
|||
|
||||
log.debug("Initialize Spring-Context on Servlet-Context: " + servletContext);
|
||||
|
||||
final WebApplicationContext cc = WebApplicationContextUtils.getRequiredWebApplicationContext(
|
||||
return WebApplicationContextUtils.getRequiredWebApplicationContext(
|
||||
servletContext);
|
||||
|
||||
if (cc == null) {
|
||||
log.error("Failed to initialize Spring-Context on Servlet-Context: " + servletContext);
|
||||
throw new RuntimeException(
|
||||
"Failed to initialize Spring-Context on Servlet-Context: " + servletContext);
|
||||
}
|
||||
return cc;
|
||||
} catch (final Exception e) {
|
||||
log.error("Failed to initialize Spring-Context on HttpSession: " + httpSession);
|
||||
throw new RuntimeException("Failed to initialize Spring-Context on HttpSession: " + httpSession);
|
||||
|
|
|
@ -23,12 +23,11 @@ import org.eclipse.swt.widgets.Combo;
|
|||
import org.eclipse.swt.widgets.Control;
|
||||
import org.eclipse.swt.widgets.Label;
|
||||
import org.eclipse.swt.widgets.Text;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
|
||||
import com.fasterxml.jackson.databind.node.ArrayNode;
|
||||
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.model.EntityKey;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.FormBinding;
|
||||
|
@ -40,6 +39,7 @@ public final class Form implements FormBinding {
|
|||
private final JSONMapper jsonMapper;
|
||||
private final ObjectNode objectRoot;
|
||||
|
||||
private final Map<String, String> staticValues = new LinkedHashMap<>();
|
||||
private final Map<String, FormFieldAccessor> formFields = new LinkedHashMap<>();
|
||||
private final Map<String, Form> subForms = new LinkedHashMap<>();
|
||||
private final Map<String, List<Form>> subLists = new LinkedHashMap<>();
|
||||
|
@ -69,16 +69,17 @@ public final class Form implements FormBinding {
|
|||
}
|
||||
|
||||
@Override
|
||||
public MultiValueMap<String, String> getFormAsQueryAttributes() {
|
||||
final LinkedMultiValueMap<String, String> result = new LinkedMultiValueMap<>();
|
||||
for (final Map.Entry<String, FormFieldAccessor> entry : this.formFields.entrySet()) {
|
||||
final String value = entry.getValue().getValue();
|
||||
if (StringUtils.isNoneBlank(value)) {
|
||||
result.add(entry.getKey(), value);
|
||||
}
|
||||
public String getFormUrlEncoded() {
|
||||
final StringBuffer buffer = new StringBuffer();
|
||||
for (final Map.Entry<String, String> entry : this.staticValues.entrySet()) {
|
||||
appendFormUrlEncoded(buffer, entry.getKey(), entry.getValue());
|
||||
}
|
||||
|
||||
return result;
|
||||
for (final Map.Entry<String, FormFieldAccessor> entry : this.formFields.entrySet()) {
|
||||
appendFormUrlEncoded(buffer, entry.getKey(), entry.getValue().getValue());
|
||||
}
|
||||
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
public String getValue(final String name) {
|
||||
|
@ -91,7 +92,9 @@ public final class Form implements FormBinding {
|
|||
}
|
||||
|
||||
public void putStatic(final String name, final String value) {
|
||||
this.objectRoot.put(name, value);
|
||||
if (StringUtils.isNoneBlank(value)) {
|
||||
this.staticValues.put(name, value);
|
||||
}
|
||||
}
|
||||
|
||||
public void addToGroup(final String groupName, final String fieldName) {
|
||||
|
@ -101,6 +104,10 @@ public final class Form implements FormBinding {
|
|||
}
|
||||
}
|
||||
|
||||
public boolean hasFields() {
|
||||
return !this.formFields.isEmpty();
|
||||
}
|
||||
|
||||
public Form putField(final String name, final Label label, final Label field) {
|
||||
this.formFields.put(name, createAccessor(label, field));
|
||||
return this;
|
||||
|
@ -172,6 +179,10 @@ public final class Form implements FormBinding {
|
|||
}
|
||||
|
||||
private void flush() {
|
||||
for (final Map.Entry<String, String> entry : this.staticValues.entrySet()) {
|
||||
this.objectRoot.put(entry.getKey(), entry.getValue());
|
||||
}
|
||||
|
||||
for (final Map.Entry<String, FormFieldAccessor> entry : this.formFields.entrySet()) {
|
||||
final FormFieldAccessor accessor = entry.getValue();
|
||||
if (accessor.control.isVisible()) {
|
||||
|
@ -229,6 +240,17 @@ public final class Form implements FormBinding {
|
|||
}
|
||||
//@formatter:on
|
||||
|
||||
private void appendFormUrlEncoded(final StringBuffer buffer, final String name, final String value) {
|
||||
if (StringUtils.isNoneBlank(value)) {
|
||||
if (buffer.length() > 0) {
|
||||
buffer.append(Constants.FORM_URL_ENCODED_SEPARATOR);
|
||||
}
|
||||
buffer.append(name)
|
||||
.append(Constants.FORM_URL_ENCODED_NAME_VALUE_SEPARATOR)
|
||||
.append(value);
|
||||
}
|
||||
}
|
||||
|
||||
public static abstract class FormFieldAccessor {
|
||||
|
||||
public final Label label;
|
||||
|
|
|
@ -12,18 +12,20 @@ import java.util.List;
|
|||
import java.util.function.BooleanSupplier;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.eclipse.swt.SWT;
|
||||
import org.eclipse.swt.layout.GridData;
|
||||
import org.eclipse.swt.layout.GridLayout;
|
||||
import org.eclipse.swt.widgets.Combo;
|
||||
import org.eclipse.swt.widgets.Composite;
|
||||
import org.eclipse.swt.widgets.Label;
|
||||
import org.eclipse.swt.widgets.TabItem;
|
||||
import org.eclipse.swt.widgets.Text;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.Constants;
|
||||
import ch.ethz.seb.sebserver.gbl.api.JSONMapper;
|
||||
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
|
||||
import ch.ethz.seb.sebserver.gbl.util.Tuple;
|
||||
|
@ -32,6 +34,7 @@ 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.service.widget.ImageUpload;
|
||||
import ch.ethz.seb.sebserver.gui.service.widget.SingleSelection;
|
||||
import ch.ethz.seb.sebserver.gui.service.widget.WidgetFactory;
|
||||
|
||||
public class FormBuilder {
|
||||
|
@ -45,6 +48,10 @@ public class FormBuilder {
|
|||
public final Form form;
|
||||
|
||||
private boolean readonly = false;
|
||||
private int defaultSpanLabel = 1;
|
||||
private int defaultSpanInput = 2;
|
||||
private int defaultSpanEmptyCell = 1;
|
||||
private boolean emptyCellSeparation = true;
|
||||
|
||||
FormBuilder(
|
||||
final EntityKey entityKey,
|
||||
|
@ -84,12 +91,47 @@ public class FormBuilder {
|
|||
return this;
|
||||
}
|
||||
|
||||
public FormBuilder withDefaultSpanLabel(final int span) {
|
||||
this.defaultSpanLabel = span;
|
||||
return this;
|
||||
}
|
||||
|
||||
public FormBuilder withDefaultSpanInput(final int span) {
|
||||
this.defaultSpanInput = span;
|
||||
return this;
|
||||
}
|
||||
|
||||
public FormBuilder withDefaultSpanEmptyCell(final int span) {
|
||||
this.defaultSpanEmptyCell = span;
|
||||
return this;
|
||||
}
|
||||
|
||||
public FormBuilder withEmptyCellSeparation(final boolean separation) {
|
||||
this.emptyCellSeparation = separation;
|
||||
return this;
|
||||
}
|
||||
|
||||
public FormBuilder addEmptyCellIf(final BooleanSupplier condition) {
|
||||
if (condition != null && condition.getAsBoolean()) {
|
||||
return addEmptyCell();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public FormBuilder addEmptyCell() {
|
||||
return addEmptyCell(1);
|
||||
}
|
||||
|
||||
public FormBuilder addEmptyCell(final int span) {
|
||||
this.widgetFactory.formEmpty(this.formParent, span, 1);
|
||||
empty(this.formParent, span, 1);
|
||||
return this;
|
||||
}
|
||||
|
||||
public FormBuilder putStaticValueIf(final BooleanSupplier condition, final String name, final String value) {
|
||||
if (condition != null && condition.getAsBoolean()) {
|
||||
return putStaticValue(name, value);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -102,128 +144,14 @@ public class FormBuilder {
|
|||
return this;
|
||||
}
|
||||
|
||||
public FormBuilder addTextField(
|
||||
final String name,
|
||||
final String label,
|
||||
final String value) {
|
||||
|
||||
return addTextField(name, label, value, 1, null);
|
||||
}
|
||||
|
||||
public FormBuilder addTextField(
|
||||
final String name,
|
||||
final String label,
|
||||
final String value,
|
||||
final int span) {
|
||||
|
||||
return addTextField(name, label, value, span, null);
|
||||
}
|
||||
|
||||
public FormBuilder addTextField(
|
||||
final String name,
|
||||
final String label,
|
||||
final String value,
|
||||
final int span,
|
||||
final String group) {
|
||||
|
||||
final Label lab = this.widgetFactory.formLabelLocalized(this.formParent, label);
|
||||
if (this.readonly) {
|
||||
this.form.putField(name, lab, this.widgetFactory.formValueLabel(this.formParent, value, span));
|
||||
} else {
|
||||
this.form.putField(name, lab, this.widgetFactory.formTextInput(this.formParent, value, span, 1));
|
||||
public FormBuilder addField(final FieldTemplate template) {
|
||||
if (template.condition == null || template.condition.getAsBoolean()) {
|
||||
template.spanLabel = (template.spanLabel < 0) ? this.defaultSpanLabel : template.spanLabel;
|
||||
template.spanInput = (template.spanInput < 0) ? this.defaultSpanInput : template.spanInput;
|
||||
template.spanEmptyCell = (template.spanEmptyCell < 0) ? this.defaultSpanEmptyCell : template.spanEmptyCell;
|
||||
template.autoEmptyCellSeparation = template.autoEmptyCellSeparation || this.emptyCellSeparation;
|
||||
template.build(this);
|
||||
}
|
||||
if (StringUtils.isNoneBlank(group)) {
|
||||
this.form.addToGroup(group, name);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public FormBuilder addSingleSelection(
|
||||
final String name,
|
||||
final String label,
|
||||
final String value,
|
||||
final List<Tuple<String>> items,
|
||||
final Consumer<Form> selectionListener) {
|
||||
|
||||
return addSingleSelection(name, label, value, items, selectionListener, 1, null);
|
||||
}
|
||||
|
||||
public FormBuilder addSingleSelection(
|
||||
final String name,
|
||||
final String label,
|
||||
final String value,
|
||||
final List<Tuple<String>> items,
|
||||
final Consumer<Form> selectionListener,
|
||||
final int span) {
|
||||
|
||||
return addSingleSelection(name, label, value, items, selectionListener, span, null);
|
||||
}
|
||||
|
||||
public FormBuilder addSingleSelection(
|
||||
final String name,
|
||||
final String label,
|
||||
final String value,
|
||||
final List<Tuple<String>> items,
|
||||
final Consumer<Form> selectionListener,
|
||||
final int span,
|
||||
final String group) {
|
||||
|
||||
final Label lab = this.widgetFactory.formLabelLocalized(this.formParent, label);
|
||||
if (this.readonly) {
|
||||
this.form.putField(name, lab, this.widgetFactory.formValueLabel(this.formParent, value, 2));
|
||||
} else {
|
||||
final Combo selection =
|
||||
this.widgetFactory.formSingleSelectionLocalized(this.formParent, value, items, span, 1);
|
||||
this.form.putField(name, lab, selection);
|
||||
if (selectionListener != null) {
|
||||
selection.addListener(SWT.Selection, e -> {
|
||||
selectionListener.accept(this.form);
|
||||
});
|
||||
}
|
||||
}
|
||||
if (StringUtils.isNoneBlank(group)) {
|
||||
this.form.addToGroup(group, name);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public FormBuilder addImageUploadIf(
|
||||
final BooleanSupplier condition,
|
||||
final String name,
|
||||
final String label,
|
||||
final String value,
|
||||
final int span) {
|
||||
|
||||
if (condition != null && condition.getAsBoolean()) {
|
||||
return addImageUpload(name, label, value, span);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public FormBuilder addImageUpload(
|
||||
final String name,
|
||||
final String label,
|
||||
final String value,
|
||||
final int span) {
|
||||
|
||||
return addImageUpload(name, label, value, span, null);
|
||||
}
|
||||
|
||||
public FormBuilder addImageUpload(
|
||||
final String name,
|
||||
final String label,
|
||||
final String value,
|
||||
final int span,
|
||||
final String group) {
|
||||
|
||||
final Label lab = this.widgetFactory.formLabelLocalized(this.formParent, label);
|
||||
final ImageUpload imageUpload = this.widgetFactory.formImageUpload(
|
||||
this.formParent,
|
||||
value,
|
||||
new LocTextKey("sebserver.overall.upload"),
|
||||
span, 1, this.readonly);
|
||||
this.form.putField(name, lab, imageUpload);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -239,4 +167,225 @@ public class FormBuilder {
|
|||
this.polyglotPageService.getI18nSupport());
|
||||
}
|
||||
|
||||
private void empty(final Composite parent, final int hspan, final int vspan) {
|
||||
final Label empty = new Label(parent, SWT.LEFT);
|
||||
empty.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, hspan, vspan));
|
||||
empty.setText("");
|
||||
}
|
||||
|
||||
public static TextField text(final String name, final String label, final String value) {
|
||||
return new TextField(name, label, value);
|
||||
}
|
||||
|
||||
public static SingleSelectionField singleSelection(
|
||||
final String name,
|
||||
final String label,
|
||||
final String value,
|
||||
final Supplier<List<Tuple<String>>> itemsSupplier) {
|
||||
return new SingleSelectionField(name, label, value, itemsSupplier);
|
||||
}
|
||||
|
||||
public static ImageUploadField imageUpload(final String name, final String label, final String value) {
|
||||
return new ImageUploadField(name, label, value);
|
||||
}
|
||||
|
||||
abstract static class FieldTemplate {
|
||||
int spanLabel = -1;
|
||||
int spanInput = -1;
|
||||
int spanEmptyCell = -1;
|
||||
boolean autoEmptyCellSeparation = false;
|
||||
String group = null;
|
||||
BooleanSupplier condition = null;
|
||||
|
||||
final String name;
|
||||
final String label;
|
||||
final String value;
|
||||
|
||||
protected FieldTemplate(final String name, final String label, final String value) {
|
||||
this.name = name;
|
||||
this.label = label;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public FieldTemplate withLabelSpan(final int span) {
|
||||
this.spanLabel = span;
|
||||
return this;
|
||||
}
|
||||
|
||||
public FieldTemplate withInputSpan(final int span) {
|
||||
this.spanInput = span;
|
||||
return this;
|
||||
}
|
||||
|
||||
public FieldTemplate withEmptyCellSpan(final int span) {
|
||||
this.spanEmptyCell = span;
|
||||
return this;
|
||||
}
|
||||
|
||||
public FieldTemplate withEmptyCellSeparation(final boolean separation) {
|
||||
this.autoEmptyCellSeparation = separation;
|
||||
return this;
|
||||
}
|
||||
|
||||
public FieldTemplate withGroup(final String group) {
|
||||
this.group = group;
|
||||
return this;
|
||||
}
|
||||
|
||||
public FieldTemplate withCondition(final BooleanSupplier condition) {
|
||||
this.condition = condition;
|
||||
return this;
|
||||
}
|
||||
|
||||
abstract void build(FormBuilder builder);
|
||||
|
||||
}
|
||||
|
||||
public static final class TextField extends FieldTemplate {
|
||||
|
||||
boolean isPassword = false;
|
||||
|
||||
TextField(final String name, final String label, final String value) {
|
||||
super(name, label, value);
|
||||
}
|
||||
|
||||
public TextField asPasswordField() {
|
||||
this.isPassword = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
void build(final FormBuilder builder) {
|
||||
if (this.isPassword && builder.readonly) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.autoEmptyCellSeparation && builder.form.hasFields()) {
|
||||
builder.addEmptyCell(this.spanEmptyCell);
|
||||
}
|
||||
|
||||
final Label lab = builder.labelLocalized(builder.formParent, this.label, this.spanLabel);
|
||||
if (builder.readonly) {
|
||||
builder.form.putField(this.name, lab,
|
||||
builder.valueLabel(builder.formParent, this.value, this.spanInput));
|
||||
} else {
|
||||
final Text textInput = new Text(builder.formParent, (this.isPassword)
|
||||
? SWT.LEFT | SWT.BORDER | SWT.PASSWORD
|
||||
: SWT.LEFT | SWT.BORDER);
|
||||
final GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, false, this.spanInput, 1);
|
||||
gridData.heightHint = 15;
|
||||
textInput.setLayoutData(gridData);
|
||||
if (this.value != null) {
|
||||
textInput.setText(this.value);
|
||||
}
|
||||
builder.form.putField(this.name, lab, textInput);
|
||||
}
|
||||
if (StringUtils.isNoneBlank(this.group)) {
|
||||
builder.form.addToGroup(this.group, this.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static final class SingleSelectionField extends FieldTemplate {
|
||||
|
||||
final Supplier<List<Tuple<String>>> itemsSupplier;
|
||||
boolean isLocalizationSupplied = false;
|
||||
Consumer<Form> selectionListener = null;
|
||||
|
||||
SingleSelectionField(
|
||||
final String name,
|
||||
final String label,
|
||||
final String value,
|
||||
final Supplier<List<Tuple<String>>> itemsSupplier) {
|
||||
|
||||
super(name, label, value);
|
||||
this.itemsSupplier = itemsSupplier;
|
||||
}
|
||||
|
||||
public SingleSelectionField withLocalizationSupplied() {
|
||||
this.isLocalizationSupplied = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public SingleSelectionField withSelectionListener(final Consumer<Form> selectionListener) {
|
||||
this.selectionListener = selectionListener;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
void build(final FormBuilder builder) {
|
||||
|
||||
if (this.autoEmptyCellSeparation && builder.form.hasFields()) {
|
||||
builder.addEmptyCell(this.spanEmptyCell);
|
||||
}
|
||||
|
||||
final Label lab = builder.labelLocalized(builder.formParent, this.label, this.spanLabel);
|
||||
if (builder.readonly) {
|
||||
builder.form.putField(
|
||||
this.name, lab,
|
||||
builder.valueLabel(builder.formParent, this.value, this.spanInput));
|
||||
} else {
|
||||
final SingleSelection selection = (this.isLocalizationSupplied)
|
||||
? builder.widgetFactory.singleSelectionLocalizedSupplier(
|
||||
builder.formParent,
|
||||
this.itemsSupplier)
|
||||
: builder.widgetFactory.singleSelectionLocalized(
|
||||
builder.formParent,
|
||||
this.itemsSupplier.get());
|
||||
final GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, false, this.spanInput, 1);
|
||||
gridData.heightHint = 25;
|
||||
selection.setLayoutData(gridData);
|
||||
selection.select(this.value);
|
||||
builder.form.putField(this.name, lab, selection);
|
||||
if (this.selectionListener != null) {
|
||||
selection.addListener(SWT.Selection, e -> {
|
||||
this.selectionListener.accept(builder.form);
|
||||
});
|
||||
}
|
||||
}
|
||||
if (StringUtils.isNoneBlank(this.group)) {
|
||||
builder.form.addToGroup(this.group, this.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static final class ImageUploadField extends FieldTemplate {
|
||||
|
||||
ImageUploadField(final String name, final String label, final String value) {
|
||||
super(name, label, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
void build(final FormBuilder builder) {
|
||||
|
||||
if (this.autoEmptyCellSeparation && builder.form.hasFields()) {
|
||||
builder.addEmptyCell(this.spanEmptyCell);
|
||||
}
|
||||
|
||||
final Label lab = builder.labelLocalized(builder.formParent, this.label, this.spanLabel);
|
||||
final ImageUpload imageUpload = builder.widgetFactory.formImageUpload(
|
||||
builder.formParent,
|
||||
this.value,
|
||||
new LocTextKey("sebserver.overall.upload"),
|
||||
this.spanInput, 1, builder.readonly);
|
||||
builder.form.putField(this.name, lab, imageUpload);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private Label labelLocalized(final Composite parent, final String locTextKey, final int hspan) {
|
||||
final Label label = this.widgetFactory.labelLocalized(parent, locTextKey);
|
||||
final GridData gridData = new GridData(SWT.RIGHT, SWT.CENTER, true, false, hspan, 1);
|
||||
label.setLayoutData(gridData);
|
||||
return label;
|
||||
}
|
||||
|
||||
private Label valueLabel(final Composite parent, final String value, final int hspan) {
|
||||
final Label label = new Label(parent, SWT.NONE);
|
||||
label.setText((StringUtils.isNoneBlank(value)) ? value : Constants.EMPTY_NOTE);
|
||||
final GridData gridData = new GridData(SWT.LEFT, SWT.CENTER, true, false, hspan, 1);
|
||||
label.setLayoutData(gridData);
|
||||
return label;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -68,23 +68,26 @@ public class FormHandle<T> {
|
|||
.map(result -> {
|
||||
this.pageContext.publishPageEvent(new ActionEvent(action, result));
|
||||
return result;
|
||||
}).onErrorDo(error -> {
|
||||
if (error instanceof RestCallError) {
|
||||
((RestCallError) error)
|
||||
.getErrorMessages()
|
||||
.stream()
|
||||
.map(FieldValidationError::new)
|
||||
.forEach(fve -> this.form.process(
|
||||
name -> name.equals(fve.fieldName),
|
||||
fieldAccessor -> showValidationError(fieldAccessor, fve)));
|
||||
} else {
|
||||
log.error("Unexpected error while trying to post form: ", error);
|
||||
this.pageContext.notifyError(error);
|
||||
}
|
||||
})
|
||||
.onErrorDo(this::handleError)
|
||||
.map(this.postPostHandle);
|
||||
}
|
||||
|
||||
private void handleError(final Throwable error) {
|
||||
if (error instanceof RestCallError) {
|
||||
((RestCallError) error)
|
||||
.getErrorMessages()
|
||||
.stream()
|
||||
.map(FieldValidationError::new)
|
||||
.forEach(fve -> this.form.process(
|
||||
name -> name.equals(fve.fieldName),
|
||||
fieldAccessor -> showValidationError(fieldAccessor, fve)));
|
||||
} else {
|
||||
log.error("Unexpected error while trying to post form: ", error);
|
||||
this.pageContext.notifyError(error);
|
||||
}
|
||||
}
|
||||
|
||||
private final void showValidationError(
|
||||
final FormFieldAccessor fieldAccessor,
|
||||
final FieldValidationError valError) {
|
||||
|
|
|
@ -9,9 +9,15 @@
|
|||
package ch.ethz.seb.sebserver.gui.service.i18n;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.joda.time.DateTime;
|
||||
import org.joda.time.DateTimeZone;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.util.Tuple;
|
||||
|
||||
public interface I18nSupport {
|
||||
|
||||
|
@ -72,4 +78,38 @@ public interface I18nSupport {
|
|||
* @return the text in current language parsed from localized text */
|
||||
String getText(String key, Locale locale, String def, Object... args);
|
||||
|
||||
default List<Tuple<String>> getLanguageResources() {
|
||||
return getLanguageResources(this);
|
||||
}
|
||||
|
||||
default List<Tuple<String>> getTimeZoneResources() {
|
||||
return getTimeZoneResources(this);
|
||||
}
|
||||
|
||||
/** Get a list of language key/name tuples for all supported languages in the
|
||||
* language of the current users locale.
|
||||
*
|
||||
* @param i18nSupport I18nSupport to get the actual current users locale
|
||||
* @return list of language key/name tuples for all supported languages in the language of the current users
|
||||
* locale */
|
||||
static List<Tuple<String>> getLanguageResources(final I18nSupport i18nSupport) {
|
||||
final Locale currentLocale = i18nSupport.getCurrentLocale();
|
||||
return i18nSupport.supportedLanguages()
|
||||
.stream()
|
||||
.map(locale -> new Tuple<>(locale.toLanguageTag(), locale.getDisplayLanguage(currentLocale)))
|
||||
.filter(tuple -> StringUtils.isNoneBlank(tuple._2))
|
||||
.sorted((t1, t2) -> t1._2.compareTo(t2._2))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
static List<Tuple<String>> getTimeZoneResources(final I18nSupport i18nSupport) {
|
||||
final Locale currentLocale = i18nSupport.getCurrentLocale();
|
||||
return DateTimeZone
|
||||
.getAvailableIDs()
|
||||
.stream()
|
||||
.map(id -> new Tuple<>(id, DateTimeZone.forID(id).getName(0, currentLocale) + " (" + id + ")"))
|
||||
.sorted((t1, t2) -> t1._2.compareTo(t2._2))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -154,6 +154,8 @@ public interface PageContext {
|
|||
|
||||
<T> T logoutOnError(Throwable error);
|
||||
|
||||
void publishPageMessage(LocTextKey title, LocTextKey message);
|
||||
|
||||
void publishPageMessage(PageMessageException pme);
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* 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.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.api.API;
|
||||
import ch.ethz.seb.sebserver.gbl.api.API.BulkActionType;
|
||||
import ch.ethz.seb.sebserver.gbl.model.Entity;
|
||||
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
|
||||
import ch.ethz.seb.sebserver.gbl.util.Tuple;
|
||||
import ch.ethz.seb.sebserver.gui.service.i18n.LocTextKey;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestService;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.institution.GetInstitutionDependency;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.institution.GetInstitutionNames;
|
||||
|
||||
public final class PageUtils {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(PageUtils.class);
|
||||
|
||||
public static final Supplier<LocTextKey> confirmDeactivation(
|
||||
final Entity entity,
|
||||
final RestService restService) {
|
||||
|
||||
return () -> {
|
||||
try {
|
||||
final Set<EntityKey> dependencies = restService.getBuilder(GetInstitutionDependency.class)
|
||||
.withURIVariable(API.PARAM_MODEL_ID, String.valueOf(entity.getModelId()))
|
||||
.withQueryParam(API.PARAM_BULK_ACTION_TYPE, BulkActionType.DEACTIVATE.name())
|
||||
.call()
|
||||
.getOrThrow();
|
||||
final int size = dependencies.size();
|
||||
if (size > 0) {
|
||||
return new LocTextKey("sebserver.dialog.confirm.deactivation", String.valueOf(size));
|
||||
} else {
|
||||
return new LocTextKey("sebserver.dialog.confirm.deactivation.noDependencies");
|
||||
}
|
||||
} catch (final Exception e) {
|
||||
log.error("Failed to get dependencyies for Entity: {}", entity, e);
|
||||
return new LocTextKey("sebserver.dialog.confirm.deactivation", "");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static List<Tuple<String>> getInstitutionSelectionResource(final RestService restService) {
|
||||
return restService.getBuilder(GetInstitutionNames.class)
|
||||
.call()
|
||||
.getOr(Collections.emptyList())
|
||||
.stream()
|
||||
.map(entityName -> new Tuple<>(entityName.modelId, entityName.name))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
}
|
|
@ -22,6 +22,7 @@ import ch.ethz.seb.sebserver.gui.service.page.PageContext;
|
|||
import ch.ethz.seb.sebserver.gui.service.page.PageMessageException;
|
||||
import ch.ethz.seb.sebserver.gui.service.page.event.ActionEvent;
|
||||
import ch.ethz.seb.sebserver.gui.service.page.event.ActionPublishEvent;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCallError;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestService;
|
||||
|
||||
public final class Action implements Runnable {
|
||||
|
@ -73,6 +74,16 @@ public final class Action implements Runnable {
|
|||
|
||||
} catch (final PageMessageException pme) {
|
||||
Action.this.pageContext.publishPageMessage(pme);
|
||||
|
||||
} catch (final RestCallError restCallError) {
|
||||
if (restCallError.isFieldValidationError()) {
|
||||
Action.this.pageContext.publishPageMessage(
|
||||
new LocTextKey("sebserver.form.validation.error.title"),
|
||||
new LocTextKey("sebserver.form.validation.error.message"));
|
||||
} else {
|
||||
log.error("Failed to execute action: {}", Action.this, restCallError);
|
||||
Action.this.pageContext.notifyError("action.error.unexpected.message", restCallError);
|
||||
}
|
||||
} catch (final Throwable t) {
|
||||
log.error("Failed to execute action: {}", Action.this, t);
|
||||
Action.this.pageContext.notifyError("action.error.unexpected.message", t);
|
||||
|
|
|
@ -9,9 +9,12 @@
|
|||
package ch.ethz.seb.sebserver.gui.service.page.action;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.function.Function;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.api.API;
|
||||
import ch.ethz.seb.sebserver.gbl.api.EntityType;
|
||||
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
|
||||
import ch.ethz.seb.sebserver.gbl.model.user.UserInfo;
|
||||
import ch.ethz.seb.sebserver.gbl.util.Result;
|
||||
import ch.ethz.seb.sebserver.gui.service.page.PageContext;
|
||||
import ch.ethz.seb.sebserver.gui.service.page.PageContext.AttributeKeys;
|
||||
|
@ -19,9 +22,18 @@ import ch.ethz.seb.sebserver.gui.service.page.PageMessageException;
|
|||
import ch.ethz.seb.sebserver.gui.service.page.activity.ActivitySelection;
|
||||
import ch.ethz.seb.sebserver.gui.service.page.activity.ActivitySelection.Activity;
|
||||
import ch.ethz.seb.sebserver.gui.service.page.event.ActivitySelectionEvent;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.useraccount.ActivateUserAccount;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.useraccount.DeactivateUserAccount;
|
||||
|
||||
public final class UserAccountActions {
|
||||
|
||||
public static Function<UserInfo, UserInfo> postSaveAdapter(final PageContext pageContext) {
|
||||
return userAccount -> {
|
||||
goToUserAccount(pageContext, userAccount.getModelId(), false);
|
||||
return userAccount;
|
||||
};
|
||||
}
|
||||
|
||||
public static Result<?> newUserAccount(final Action action) {
|
||||
return Result.of(goToUserAccount(action.pageContext, null, true));
|
||||
}
|
||||
|
@ -34,6 +46,46 @@ public final class UserAccountActions {
|
|||
return fromSelection(action, true);
|
||||
}
|
||||
|
||||
public static Result<?> editUserAccount(final Action action) {
|
||||
return Result.of(goToUserAccount(
|
||||
action.pageContext,
|
||||
action.pageContext.getAttribute(AttributeKeys.ENTITY_ID),
|
||||
true));
|
||||
}
|
||||
|
||||
public static Result<?> cancelEditUserAccount(final Action action) {
|
||||
if (action.pageContext.getEntityKey() == null) {
|
||||
final ActivitySelection toList = Activity.USER_ACCOUNT_LIST.createSelection();
|
||||
action.pageContext.publishPageEvent(new ActivitySelectionEvent(toList));
|
||||
return Result.of(toList);
|
||||
} else {
|
||||
return Result.of(goToUserAccount(
|
||||
action.pageContext,
|
||||
action.pageContext.getAttribute(AttributeKeys.ENTITY_ID),
|
||||
false));
|
||||
}
|
||||
}
|
||||
|
||||
public static Result<?> activateUserAccount(final Action action) {
|
||||
return action.restService
|
||||
.getBuilder(ActivateUserAccount.class)
|
||||
.withURIVariable(
|
||||
API.PARAM_MODEL_ID,
|
||||
action.pageContext.getAttribute(AttributeKeys.ENTITY_ID))
|
||||
.call()
|
||||
.map(report -> goToUserAccount(action.pageContext, report.getSingleSource().modelId, false));
|
||||
}
|
||||
|
||||
public static Result<?> deactivateUserAccount(final Action action) {
|
||||
return action.restService
|
||||
.getBuilder(DeactivateUserAccount.class)
|
||||
.withURIVariable(
|
||||
API.PARAM_MODEL_ID,
|
||||
action.pageContext.getAttribute(AttributeKeys.ENTITY_ID))
|
||||
.call()
|
||||
.map(report -> goToUserAccount(action.pageContext, report.getSingleSource().modelId, false));
|
||||
}
|
||||
|
||||
private static Result<?> fromSelection(final Action action, final boolean edit) {
|
||||
final Collection<String> selection = action.selectionSupplier.get();
|
||||
if (selection.isEmpty()) {
|
||||
|
@ -50,7 +102,6 @@ public final class UserAccountActions {
|
|||
|
||||
final ActivitySelection activitySelection = Activity.USER_ACCOUNT_FORM
|
||||
.createSelection()
|
||||
.withEntity(new EntityKey(modelId, EntityType.USER))
|
||||
.withAttribute(AttributeKeys.READ_ONLY, String.valueOf(!edit));
|
||||
|
||||
if (modelId != null) {
|
||||
|
|
|
@ -22,6 +22,7 @@ import ch.ethz.seb.sebserver.gui.service.page.TemplateComposer;
|
|||
import ch.ethz.seb.sebserver.gui.service.page.action.ActionPane;
|
||||
import ch.ethz.seb.sebserver.gui.service.page.content.InstitutionForm;
|
||||
import ch.ethz.seb.sebserver.gui.service.page.content.InstitutionList;
|
||||
import ch.ethz.seb.sebserver.gui.service.page.content.UserAccountForm;
|
||||
import ch.ethz.seb.sebserver.gui.service.page.content.UserAccountList;
|
||||
import ch.ethz.seb.sebserver.gui.service.page.impl.TODOTemplate;
|
||||
|
||||
|
@ -51,7 +52,7 @@ public class ActivitySelection {
|
|||
new LocTextKey("sebserver.activities.useraccount")),
|
||||
|
||||
USER_ACCOUNT_FORM(
|
||||
UserAccountList.class,
|
||||
UserAccountForm.class,
|
||||
ActionPane.class,
|
||||
new LocTextKey("sebserver.activities.useraccount")),
|
||||
|
||||
|
|
|
@ -8,9 +8,6 @@
|
|||
|
||||
package ch.ethz.seb.sebserver.gui.service.page.content;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.eclipse.swt.widgets.Composite;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
@ -18,23 +15,22 @@ import org.springframework.context.annotation.Lazy;
|
|||
import org.springframework.stereotype.Component;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.api.API;
|
||||
import ch.ethz.seb.sebserver.gbl.api.API.BulkActionType;
|
||||
import ch.ethz.seb.sebserver.gbl.authorization.PrivilegeType;
|
||||
import ch.ethz.seb.sebserver.gbl.model.Domain;
|
||||
import ch.ethz.seb.sebserver.gbl.model.Entity;
|
||||
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
|
||||
import ch.ethz.seb.sebserver.gbl.model.institution.Institution;
|
||||
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
|
||||
import ch.ethz.seb.sebserver.gui.service.form.FormBuilder;
|
||||
import ch.ethz.seb.sebserver.gui.service.form.FormHandle;
|
||||
import ch.ethz.seb.sebserver.gui.service.form.PageFormService;
|
||||
import ch.ethz.seb.sebserver.gui.service.i18n.LocTextKey;
|
||||
import ch.ethz.seb.sebserver.gui.service.page.PageContext;
|
||||
import ch.ethz.seb.sebserver.gui.service.page.PageUtils;
|
||||
import ch.ethz.seb.sebserver.gui.service.page.TemplateComposer;
|
||||
import ch.ethz.seb.sebserver.gui.service.page.action.ActionDefinition;
|
||||
import ch.ethz.seb.sebserver.gui.service.page.action.InstitutionActions;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestService;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.institution.GetInstitution;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.institution.GetInstitutionDependency;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.institution.NewInstitution;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.institution.SaveInstitution;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.CurrentUser;
|
||||
|
@ -71,7 +67,7 @@ public class InstitutionForm implements TemplateComposer {
|
|||
final WidgetFactory widgetFactory = this.pageFormService.getWidgetFactory();
|
||||
final EntityKey entityKey = pageContext.getEntityKey();
|
||||
|
||||
// get data or create new and handle error
|
||||
// get data or create new. Handle error if happen
|
||||
final Institution institution = (entityKey == null)
|
||||
? new Institution(null, null, null, null, false)
|
||||
: this.restService
|
||||
|
@ -103,35 +99,28 @@ public class InstitutionForm implements TemplateComposer {
|
|||
institution.name);
|
||||
final Composite content = widgetFactory.defaultPageLayout(
|
||||
formContext.getParent(),
|
||||
titleKey,
|
||||
ActionDefinition.INSTITUTION_SAVE,
|
||||
title -> event -> {
|
||||
final Entity entity = (Entity) event.source;
|
||||
widgetFactory.injectI18n(title, new LocTextKey(
|
||||
"sebserver.institution.form.title",
|
||||
entity.getName()));
|
||||
title.getParent().layout();
|
||||
});
|
||||
titleKey);
|
||||
|
||||
// The Institution form
|
||||
final FormHandle<Institution> formHandle = this.pageFormService.getBuilder(
|
||||
formContext.copyOf(content), 4)
|
||||
.readonly(pageContext.isReadonly())
|
||||
.putStaticValue("id", institution.getModelId())
|
||||
.addTextField(
|
||||
.putStaticValueIf(() -> entityKey != null,
|
||||
Domain.INSTITUTION.ATTR_ID,
|
||||
institution.getModelId())
|
||||
.addField(FormBuilder.text(
|
||||
Domain.INSTITUTION.ATTR_NAME,
|
||||
"sebserver.institution.form.name",
|
||||
institution.name, 2)
|
||||
.addEmptyCell()
|
||||
.addTextField(
|
||||
institution.name))
|
||||
.addField(FormBuilder.text(
|
||||
Domain.INSTITUTION.ATTR_URL_SUFFIX,
|
||||
"sebserver.institution.form.urlSuffix",
|
||||
institution.urlSuffix, 2)
|
||||
.addEmptyCell()
|
||||
.addImageUploadIf(() -> entityKey != null,
|
||||
institution.urlSuffix))
|
||||
.addField(FormBuilder.imageUpload(
|
||||
Domain.INSTITUTION.ATTR_LOGO_IMAGE,
|
||||
"sebserver.institution.form.logoImage",
|
||||
institution.logoImage, 2)
|
||||
institution.logoImage)
|
||||
.withCondition(() -> entityKey != null))
|
||||
.buildFor((entityKey == null)
|
||||
? this.restService.getRestCall(NewInstitution.class)
|
||||
: this.restService.getRestCall(SaveInstitution.class),
|
||||
|
@ -155,7 +144,7 @@ public class InstitutionForm implements TemplateComposer {
|
|||
} else {
|
||||
formContext.createAction(ActionDefinition.INSTITUTION_DEACTIVATE)
|
||||
.withExec(InstitutionActions::deactivateInstitution)
|
||||
.withConfirm(confirmDeactivation(institution))
|
||||
.withConfirm(PageUtils.confirmDeactivation(institution, this.restService))
|
||||
.publishIf(() -> modifyGrant);
|
||||
}
|
||||
|
||||
|
@ -170,25 +159,4 @@ public class InstitutionForm implements TemplateComposer {
|
|||
}
|
||||
}
|
||||
|
||||
private Supplier<LocTextKey> confirmDeactivation(final Institution institution) {
|
||||
return () -> {
|
||||
try {
|
||||
final Set<EntityKey> dependencies = this.restService.getBuilder(GetInstitutionDependency.class)
|
||||
.withURIVariable(API.PARAM_MODEL_ID, String.valueOf(institution.id))
|
||||
.withQueryParam(API.PARAM_BULK_ACTION_TYPE, BulkActionType.DEACTIVATE.name())
|
||||
.call()
|
||||
.getOrThrow();
|
||||
final int size = dependencies.size();
|
||||
if (size > 0) {
|
||||
return new LocTextKey("sebserver.institution.form.confirm.deactivation", String.valueOf(size));
|
||||
} else {
|
||||
return new LocTextKey("sebserver.institution.form.confirm.deactivation.noDependencies");
|
||||
}
|
||||
} catch (final Exception e) {
|
||||
log.error("Failed to get dependencyies for Institution: {}", institution, e);
|
||||
return new LocTextKey("sebserver.institution.form.confirm.deactivation", "");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -9,22 +9,36 @@
|
|||
package ch.ethz.seb.sebserver.gui.service.page.content;
|
||||
|
||||
import java.util.UUID;
|
||||
import java.util.function.BooleanSupplier;
|
||||
|
||||
import org.eclipse.swt.widgets.Composite;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.api.API;
|
||||
import ch.ethz.seb.sebserver.gbl.authorization.PrivilegeType;
|
||||
import ch.ethz.seb.sebserver.gbl.model.Domain;
|
||||
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
|
||||
import ch.ethz.seb.sebserver.gbl.model.user.UserAccount;
|
||||
import ch.ethz.seb.sebserver.gbl.model.user.UserInfo;
|
||||
import ch.ethz.seb.sebserver.gbl.model.user.UserMod;
|
||||
import ch.ethz.seb.sebserver.gbl.model.user.UserRole;
|
||||
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
|
||||
import ch.ethz.seb.sebserver.gui.service.form.FormBuilder;
|
||||
import ch.ethz.seb.sebserver.gui.service.form.FormHandle;
|
||||
import ch.ethz.seb.sebserver.gui.service.form.PageFormService;
|
||||
import ch.ethz.seb.sebserver.gui.service.i18n.LocTextKey;
|
||||
import ch.ethz.seb.sebserver.gui.service.page.PageContext;
|
||||
import ch.ethz.seb.sebserver.gui.service.page.PageUtils;
|
||||
import ch.ethz.seb.sebserver.gui.service.page.TemplateComposer;
|
||||
import ch.ethz.seb.sebserver.gui.service.page.action.ActionDefinition;
|
||||
import ch.ethz.seb.sebserver.gui.service.page.action.UserAccountActions;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestService;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.useraccount.GetUserAccount;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.useraccount.NewUserAccount;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.useraccount.SaveUserAccount;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.CurrentUser;
|
||||
import ch.ethz.seb.sebserver.gui.service.widget.WidgetFactory;
|
||||
|
||||
|
@ -58,9 +72,12 @@ public class UserAccountForm implements TemplateComposer {
|
|||
|
||||
final WidgetFactory widgetFactory = this.pageFormService.getWidgetFactory();
|
||||
final EntityKey entityKey = pageContext.getEntityKey();
|
||||
final BooleanSupplier isNew = () -> entityKey == null;
|
||||
final BooleanSupplier isNotNew = () -> !isNew.getAsBoolean();
|
||||
final BooleanSupplier isSEBAdmin = () -> this.currentUser.get().hasRole(UserRole.SEB_SERVER_ADMIN);
|
||||
|
||||
// get data or create new and handle error
|
||||
final UserAccount userAccount = (entityKey == null)
|
||||
// get data or create new. handle error if happen
|
||||
final UserAccount userAccount = isNew.getAsBoolean()
|
||||
? new UserMod(
|
||||
UUID.randomUUID().toString(),
|
||||
this.currentUser.get().institutionId)
|
||||
|
@ -72,10 +89,119 @@ public class UserAccountForm implements TemplateComposer {
|
|||
|
||||
if (userAccount == null) {
|
||||
log.error(
|
||||
"Failed to get UserAccount. Error was notified to the User. See previous logs for more infomation");
|
||||
"Failed to get UserAccount. "
|
||||
+ "Error was notified to the User. "
|
||||
+ "See previous logs for more infomation");
|
||||
return;
|
||||
}
|
||||
|
||||
// new PageContext with actual EntityKey
|
||||
final PageContext formContext = pageContext;
|
||||
pageContext.withEntityKey(userAccount.getEntityKey());
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("UserAccount Form for user {}", userAccount.getName());
|
||||
}
|
||||
|
||||
// the default page layout with title
|
||||
final LocTextKey titleKey = new LocTextKey(
|
||||
isNotNew.getAsBoolean()
|
||||
? "sebserver.useraccount.form.title"
|
||||
: "sebserver.useraccount.form.title.new",
|
||||
userAccount.getUsername());
|
||||
final Composite content = widgetFactory.defaultPageLayout(
|
||||
formContext.getParent(),
|
||||
titleKey);
|
||||
|
||||
// The UserAccount form
|
||||
final FormHandle<UserInfo> formHandle = this.pageFormService.getBuilder(
|
||||
formContext.copyOf(content), 4)
|
||||
.readonly(pageContext.isReadonly())
|
||||
.putStaticValueIf(isNotNew,
|
||||
Domain.USER.ATTR_UUID,
|
||||
userAccount.getModelId())
|
||||
.putStaticValueIf(isNew,
|
||||
Domain.USER.ATTR_TIMEZONE,
|
||||
userAccount.getTimeZone().getID())
|
||||
.addField(FormBuilder.singleSelection(
|
||||
Domain.USER.ATTR_INSTITUTION_ID,
|
||||
"sebserver.useraccount.form.institution",
|
||||
String.valueOf(userAccount.getInstitutionId()),
|
||||
() -> PageUtils.getInstitutionSelectionResource(this.restService))
|
||||
.withCondition(isSEBAdmin))
|
||||
.addField(FormBuilder.text(
|
||||
Domain.USER.ATTR_NAME,
|
||||
"sebserver.useraccount.form.name",
|
||||
userAccount.getName()))
|
||||
.addField(FormBuilder.text(
|
||||
Domain.USER.ATTR_USERNAME,
|
||||
"sebserver.useraccount.form.username",
|
||||
userAccount.getUsername()))
|
||||
.addField(FormBuilder.text(
|
||||
Domain.USER.ATTR_EMAIL,
|
||||
"sebserver.useraccount.form.mail",
|
||||
userAccount.getEmail()))
|
||||
.addField(FormBuilder.singleSelection(
|
||||
Domain.USER.ATTR_LOCALE,
|
||||
"sebserver.useraccount.form.language",
|
||||
userAccount.getTimeZone().getID(),
|
||||
() -> widgetFactory.getI18nSupport().getLanguageResources())
|
||||
.withLocalizationSupplied())
|
||||
.addField(FormBuilder.singleSelection(
|
||||
Domain.USER.ATTR_TIMEZONE,
|
||||
"sebserver.useraccount.form.timezone",
|
||||
userAccount.getTimeZone().getID(),
|
||||
() -> widgetFactory.getI18nSupport().getTimeZoneResources())
|
||||
.withLocalizationSupplied())
|
||||
// TODO add role selection (create multi selector)
|
||||
.addField(FormBuilder.text(
|
||||
UserMod.ATTR_NAME_NEW_PASSWORD,
|
||||
"sebserver.useraccount.form.password",
|
||||
null)
|
||||
.asPasswordField()
|
||||
.withCondition(isNew))
|
||||
.addField(FormBuilder.text(
|
||||
UserMod.ATTR_NAME_RETYPED_NEW_PASSWORD,
|
||||
"sebserver.useraccount.form.password.retyped",
|
||||
null)
|
||||
.asPasswordField()
|
||||
.withCondition(isNew))
|
||||
.buildFor((entityKey == null)
|
||||
? this.restService.getRestCall(NewUserAccount.class)
|
||||
: this.restService.getRestCall(SaveUserAccount.class),
|
||||
UserAccountActions.postSaveAdapter(pageContext));
|
||||
|
||||
// propagate content actions to action-pane
|
||||
final boolean writeGrant = this.currentUser.hasPrivilege(PrivilegeType.WRITE, userAccount);
|
||||
final boolean modifyGrant = this.currentUser.hasPrivilege(PrivilegeType.MODIFY, userAccount);
|
||||
if (pageContext.isReadonly()) {
|
||||
formContext.createAction(ActionDefinition.USER_ACCOUNT_NEW)
|
||||
.withExec(UserAccountActions::newUserAccount)
|
||||
.publishIf(() -> writeGrant);
|
||||
formContext.createAction(ActionDefinition.USER_ACCOUNT_MODIFY)
|
||||
.withExec(UserAccountActions::editUserAccount)
|
||||
.publishIf(() -> modifyGrant);
|
||||
|
||||
if (!userAccount.isActive()) {
|
||||
formContext.createAction(ActionDefinition.USER_ACCOUNT_ACTIVATE)
|
||||
.withExec(UserAccountActions::activateUserAccount)
|
||||
.publishIf(() -> modifyGrant);
|
||||
} else {
|
||||
formContext.createAction(ActionDefinition.USER_ACCOUNT_DEACTIVATE)
|
||||
.withExec(UserAccountActions::deactivateUserAccount)
|
||||
.withConfirm(PageUtils.confirmDeactivation(userAccount, this.restService))
|
||||
.publishIf(() -> modifyGrant);
|
||||
}
|
||||
|
||||
} else {
|
||||
formContext.createAction(ActionDefinition.USER_ACCOUNT_SAVE)
|
||||
.withExec(formHandle::postChanges)
|
||||
.publish()
|
||||
.createAction(ActionDefinition.USER_ACCOUNT_CANCEL_MODIFY)
|
||||
.withExec(UserAccountActions::cancelEditUserAccount)
|
||||
.withConfirm("sebserver.overall.action.modify.cancel.confirm")
|
||||
.publish();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -311,6 +311,17 @@ public class PageContextImpl implements PageContext {
|
|||
forwardToPage(this.composerService.loginPage(), pageContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void publishPageMessage(final LocTextKey title, final LocTextKey message) {
|
||||
final MessageBox messageBox = new Message(
|
||||
getShell(),
|
||||
this.i18nSupport.getText(title),
|
||||
this.i18nSupport.getText(message),
|
||||
SWT.NONE);
|
||||
messageBox.setMarkupEnabled(true);
|
||||
messageBox.open(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void publishPageMessage(final PageMessageException pme) {
|
||||
final MessageBox messageBox = new Message(
|
||||
|
|
|
@ -8,8 +8,6 @@
|
|||
|
||||
package ch.ethz.seb.sebserver.gui.service.remote.webservice.api;
|
||||
|
||||
import org.springframework.util.MultiValueMap;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
|
||||
|
||||
public interface FormBinding {
|
||||
|
@ -18,6 +16,6 @@ public interface FormBinding {
|
|||
|
||||
String getFormAsJson();
|
||||
|
||||
MultiValueMap<String, String> getFormAsQueryAttributes();
|
||||
String getFormUrlEncoded();
|
||||
|
||||
}
|
||||
|
|
|
@ -113,6 +113,7 @@ public abstract class RestCall<T> {
|
|||
}));
|
||||
} catch (final Exception e) {
|
||||
log.error("Unexpected error-response while webservice API call for: {}", builder, e);
|
||||
log.error("Unexpected error-response cause: ", t);
|
||||
restCallError.errors.add(APIMessage.ErrorMessage.UNEXPECTED.of(e));
|
||||
}
|
||||
|
||||
|
@ -147,6 +148,11 @@ public abstract class RestCall<T> {
|
|||
return this;
|
||||
}
|
||||
|
||||
public RestCallBuilder withHeaders(final MultiValueMap<String, String> params) {
|
||||
this.httpHeaders.addAll(params);
|
||||
return this;
|
||||
}
|
||||
|
||||
public RestCallBuilder withBody(final Object body) {
|
||||
if (body instanceof String) {
|
||||
this.body = String.valueOf(body);
|
||||
|
@ -198,7 +204,9 @@ public abstract class RestCall<T> {
|
|||
return withURIVariable(API.PARAM_MODEL_ID, formBinding.entityKey().modelId)
|
||||
.withBody(formBinding.getFormAsJson());
|
||||
} else {
|
||||
return withQueryParams(formBinding.getFormAsQueryAttributes());
|
||||
this.body = formBinding.getFormUrlEncoded();
|
||||
return this;
|
||||
//return withHeaders(formBinding.getFormAsQueryAttributes());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -37,6 +37,14 @@ public class RestCallError extends RuntimeException implements APIMessageError {
|
|||
return !this.errors.isEmpty();
|
||||
}
|
||||
|
||||
public boolean isFieldValidationError() {
|
||||
return this.errors
|
||||
.stream()
|
||||
.filter(error -> APIMessage.ErrorMessage.FIELD_VALIDATION.isOf(error))
|
||||
.findFirst()
|
||||
.isPresent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "RestCallError [errors=" + this.errors + "]";
|
||||
|
|
|
@ -26,7 +26,7 @@ import org.springframework.util.MultiValueMap;
|
|||
import ch.ethz.seb.sebserver.gbl.model.Entity;
|
||||
import ch.ethz.seb.sebserver.gui.service.i18n.LocTextKey;
|
||||
import ch.ethz.seb.sebserver.gui.service.table.ColumnDefinition.TableFilterAttribute;
|
||||
import ch.ethz.seb.sebserver.gui.service.widget.LanguageSelector;
|
||||
import ch.ethz.seb.sebserver.gui.service.widget.SingleSelection;
|
||||
import ch.ethz.seb.sebserver.gui.service.widget.WidgetFactory.ImageIcon;
|
||||
|
||||
public class TableFilter<ROW extends Entity> extends Composite {
|
||||
|
@ -232,7 +232,7 @@ public class TableFilter<ROW extends Entity> extends Composite {
|
|||
|
||||
private class LanguageFilter extends FilterComponent {
|
||||
|
||||
private LanguageSelector selector;
|
||||
private SingleSelection selector;
|
||||
|
||||
LanguageFilter(final TableFilterAttribute attribute) {
|
||||
super(attribute);
|
||||
|
@ -240,7 +240,12 @@ public class TableFilter<ROW extends Entity> extends Composite {
|
|||
|
||||
@Override
|
||||
FilterComponent build(final Composite parent) {
|
||||
this.selector = TableFilter.this.entityTable.widgetFactory.countrySelector(parent);
|
||||
this.selector = TableFilter.this.entityTable.widgetFactory
|
||||
.singleSelectionLocalizedSupplier(
|
||||
parent,
|
||||
() -> TableFilter.this.entityTable.widgetFactory
|
||||
.getI18nSupport()
|
||||
.getLanguageResources());
|
||||
this.selector.setLayoutData(this.rowData);
|
||||
return this;
|
||||
}
|
||||
|
@ -249,7 +254,6 @@ public class TableFilter<ROW extends Entity> extends Composite {
|
|||
FilterComponent reset() {
|
||||
if (this.selector != null) {
|
||||
this.selector.clear();
|
||||
this.selector.layout();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
|
|
@ -1,55 +0,0 @@
|
|||
/*
|
||||
* 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.widget;
|
||||
|
||||
import static ch.ethz.seb.sebserver.gui.service.i18n.PolyglotPageService.POLYGLOT_WIDGET_FUNCTION_KEY;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.eclipse.swt.widgets.Composite;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.util.Tuple;
|
||||
import ch.ethz.seb.sebserver.gui.service.i18n.I18nSupport;
|
||||
|
||||
public class LanguageSelector extends SingleSelection {
|
||||
|
||||
private static final long serialVersionUID = -8590909580787576722L;
|
||||
|
||||
private final Consumer<LanguageSelector> updateFunction;
|
||||
|
||||
public LanguageSelector(final Composite parent, final I18nSupport i18nSupport) {
|
||||
super(parent, getLanguages(i18nSupport));
|
||||
this.updateFunction = updateFunction(i18nSupport);
|
||||
this.setData(POLYGLOT_WIDGET_FUNCTION_KEY, this.updateFunction);
|
||||
}
|
||||
|
||||
private static final Consumer<LanguageSelector> updateFunction(final I18nSupport i18nSupport) {
|
||||
return selection -> selection.applyNewMapping(getLanguages(i18nSupport));
|
||||
}
|
||||
|
||||
public static final List<Tuple<String>> getLanguages(final I18nSupport i18nSupport) {
|
||||
final Locale currentLocale = i18nSupport.getCurrentLocale();
|
||||
return i18nSupport.supportedLanguages()
|
||||
.stream()
|
||||
.map(locale -> new Tuple<>(locale.toLanguageTag(), locale.getDisplayLanguage(currentLocale)))
|
||||
.filter(tuple -> StringUtils.isNoneBlank(tuple._2))
|
||||
.sorted((t1, t2) -> t1._2.compareTo(t2._2))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
super.clearSelection();
|
||||
this.updateFunction.accept(this);
|
||||
}
|
||||
|
||||
}
|
|
@ -33,6 +33,7 @@ public class SingleSelection extends Combo {
|
|||
}
|
||||
|
||||
protected void applyNewMapping(final List<Tuple<String>> mapping) {
|
||||
final String selectionValue = getSelectionValue();
|
||||
this.valueMapping.clear();
|
||||
this.keyMapping.clear();
|
||||
this.valueMapping.addAll(mapping.stream()
|
||||
|
@ -42,6 +43,7 @@ public class SingleSelection extends Combo {
|
|||
.map(t -> t._1)
|
||||
.collect(Collectors.toList()));
|
||||
super.setItems(this.valueMapping.toArray(new String[mapping.size()]));
|
||||
select(selectionValue);
|
||||
}
|
||||
|
||||
public void select(final String key) {
|
||||
|
@ -62,4 +64,9 @@ public class SingleSelection extends Combo {
|
|||
return this.keyMapping.get(selectionindex);
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
super.clearSelection();
|
||||
super.setItems(this.valueMapping.toArray(new String[this.valueMapping.size()]));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -16,8 +16,8 @@ import java.util.List;
|
|||
import java.util.Locale;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
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.graphics.Device;
|
||||
|
@ -34,7 +34,6 @@ import org.eclipse.swt.widgets.Listener;
|
|||
import org.eclipse.swt.widgets.Table;
|
||||
import org.eclipse.swt.widgets.TableColumn;
|
||||
import org.eclipse.swt.widgets.TableItem;
|
||||
import org.eclipse.swt.widgets.Text;
|
||||
import org.eclipse.swt.widgets.Tree;
|
||||
import org.eclipse.swt.widgets.TreeItem;
|
||||
import org.slf4j.Logger;
|
||||
|
@ -42,7 +41,6 @@ import org.slf4j.LoggerFactory;
|
|||
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.Entity;
|
||||
import ch.ethz.seb.sebserver.gbl.model.Page;
|
||||
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
|
||||
|
@ -311,68 +309,6 @@ public class WidgetFactory {
|
|||
return imageButton;
|
||||
}
|
||||
|
||||
public Label formLabelLocalized(final Composite parent, final String locTextKey) {
|
||||
final Label label = labelLocalized(parent, locTextKey);
|
||||
final GridData gridData = new GridData(SWT.RIGHT, SWT.CENTER, true, false);
|
||||
label.setLayoutData(gridData);
|
||||
return label;
|
||||
}
|
||||
|
||||
public Label formValueLabel(final Composite parent, final String value, final int span) {
|
||||
final Label label = new Label(parent, SWT.NONE);
|
||||
label.setText((StringUtils.isNoneBlank(value)) ? value : Constants.EMPTY_NOTE);
|
||||
final GridData gridData = new GridData(SWT.LEFT, SWT.CENTER, true, false, span, 1);
|
||||
label.setLayoutData(gridData);
|
||||
return label;
|
||||
}
|
||||
|
||||
public Text formTextInput(final Composite parent, final String value) {
|
||||
return formTextInput(parent, value, 1, 1);
|
||||
}
|
||||
|
||||
public Text formTextInput(final Composite parent, final String value, final int hspan, final int vspan) {
|
||||
final Text textInput = new Text(parent, SWT.LEFT | SWT.BORDER);
|
||||
final GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, false, hspan, vspan);
|
||||
gridData.heightHint = 15;
|
||||
textInput.setLayoutData(gridData);
|
||||
if (value != null) {
|
||||
textInput.setText(value);
|
||||
}
|
||||
return textInput;
|
||||
}
|
||||
|
||||
public Combo formSingleSelectionLocalized(
|
||||
final Composite parent,
|
||||
final String selection,
|
||||
final List<Tuple<String>> items) {
|
||||
|
||||
return formSingleSelectionLocalized(parent, selection, items, 1, 1);
|
||||
}
|
||||
|
||||
public Combo formSingleSelectionLocalized(
|
||||
final Composite parent,
|
||||
final String selection,
|
||||
final List<Tuple<String>> items,
|
||||
final int hspan, final int vspan) {
|
||||
|
||||
final SingleSelection combo = singleSelectionLocalized(parent, items);
|
||||
final GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, false, hspan, vspan);
|
||||
gridData.heightHint = 25;
|
||||
combo.setLayoutData(gridData);
|
||||
combo.select(selection);
|
||||
return combo;
|
||||
}
|
||||
|
||||
public void formEmpty(final Composite parent) {
|
||||
formEmpty(parent, 1, 1);
|
||||
}
|
||||
|
||||
public void formEmpty(final Composite parent, final int hspan, final int vspan) {
|
||||
final Label empty = new Label(parent, SWT.LEFT);
|
||||
empty.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, hspan, vspan));
|
||||
empty.setText("");
|
||||
}
|
||||
|
||||
public SingleSelection singleSelectionLocalized(
|
||||
final Composite parent,
|
||||
final List<Tuple<String>> items) {
|
||||
|
@ -382,10 +318,25 @@ public class WidgetFactory {
|
|||
return combo;
|
||||
}
|
||||
|
||||
public LanguageSelector countrySelector(final Composite parent) {
|
||||
return new LanguageSelector(parent, this.i18nSupport);
|
||||
public SingleSelection singleSelectionLocalizedSupplier(
|
||||
final Composite parent,
|
||||
final Supplier<List<Tuple<String>>> itemsSupplier) {
|
||||
|
||||
final Consumer<SingleSelection> updateFunction =
|
||||
selection -> selection.applyNewMapping(itemsSupplier.get());
|
||||
final SingleSelection selection = new SingleSelection(parent, itemsSupplier.get());
|
||||
selection.setData(POLYGLOT_WIDGET_FUNCTION_KEY, updateFunction);
|
||||
return selection;
|
||||
}
|
||||
|
||||
// public SingleSelection languageSelector(final Composite parent) {
|
||||
// final Consumer<SingleSelection> updateFunction =
|
||||
// selection -> selection.applyNewMapping(this.i18nSupport.getLanguageResources());
|
||||
// final SingleSelection selection = new SingleSelection(parent, this.i18nSupport.getLanguageResources());
|
||||
// selection.setData(POLYGLOT_WIDGET_FUNCTION_KEY, updateFunction);
|
||||
// return selection;
|
||||
// }
|
||||
|
||||
public ImageUpload formImageUpload(
|
||||
final Composite parent,
|
||||
final String value,
|
||||
|
|
|
@ -333,7 +333,7 @@ public class UserDaoImpl implements UserDAO {
|
|||
|
||||
@Override
|
||||
public List<Long> extractPKsFromKeys(final Collection<EntityKey> keys) {
|
||||
if (keys == null || keys.isEmpty() || keys.iterator().next().isIdPK) {
|
||||
if (keys == null || keys.isEmpty() || keys.iterator().next().entityType != EntityType.USER) {
|
||||
return UserDAO.super.extractPKsFromKeys(keys);
|
||||
} else {
|
||||
final List<String> uuids = keys.stream()
|
||||
|
|
|
@ -17,6 +17,8 @@ sebserver.overall.action.filter.clear=Clear Filter Criteria
|
|||
# Form validation and messages
|
||||
################################
|
||||
|
||||
sebserver.form.validation.error.title=Form Data Validation Failed
|
||||
sebserver.form.validation.error.message=There is missing or incorrect form data.
|
||||
sebserver.form.validation.fieldError.size=The size must be between {3} and {4}
|
||||
sebserver.form.validation.fieldError.name=Name is mandatory and must have a size between 3 and 255 character
|
||||
sebserver.form.validation.fieldError.urlSuffix=URL Suffix must have a size between 3 and 255 character
|
||||
|
@ -25,6 +27,9 @@ sebserver.error.unexpected=Unexpected Error
|
|||
sebserver.page.message=Information
|
||||
sebserver.dialog.confirm.title=Confirmation
|
||||
|
||||
sebserver.dialog.confirm.deactivation=Note that there are {0} other entities that belongs to this entity.<br/>Those will also be deactivated by deactivating this entity.<br/><br/>Are You sure to deactivate this entity?
|
||||
sebserver.dialog.confirm.deactivation.noDependencies=Are You sure to deactivate?
|
||||
|
||||
################################
|
||||
# Login Page
|
||||
################################
|
||||
|
@ -78,8 +83,7 @@ sebserver.institution.form.title=Institution : {0}
|
|||
sebserver.institution.form.name=Name
|
||||
sebserver.institution.form.urlSuffix=URL Suffix
|
||||
sebserver.institution.form.logoImage=Logo Image
|
||||
sebserver.institution.form.confirm.deactivation=Note that there are {0} other entities that belongs to this Institution.<br/>Those will also be deactivated by deactivating this Institution.<br/><br/>Are You sure to deactivate this Institution?
|
||||
sebserver.institution.form.confirm.deactivation.noDependencies=Are You sure to deactivate this Institution?
|
||||
|
||||
|
||||
################################
|
||||
# User Account
|
||||
|
@ -102,5 +106,16 @@ sebserver.useraccount.action.delete=Delete User Account
|
|||
|
||||
sebserver.useraccount.info.pleaseSelect=Please Select an User Account first.
|
||||
|
||||
sebserver.useraccount.form.title=User Account : {0}
|
||||
sebserver.useraccount.form.title.new=New User Account
|
||||
sebserver.useraccount.form.institution=Institution
|
||||
sebserver.useraccount.form.name=Name
|
||||
sebserver.useraccount.form.username=Username
|
||||
sebserver.useraccount.form.mail=E-Mail
|
||||
sebserver.useraccount.form.language=Language
|
||||
sebserver.useraccount.form.timezone=Time Zone
|
||||
sebserver.useraccount.form.password=Password
|
||||
sebserver.useraccount.form.password.retyped=Retyped Password
|
||||
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue