diff --git a/src/main/java/ch/ethz/seb/sebserver/gbl/Constants.java b/src/main/java/ch/ethz/seb/sebserver/gbl/Constants.java
index b1ec8883..09d4551a 100644
--- a/src/main/java/ch/ethz/seb/sebserver/gbl/Constants.java
+++ b/src/main/java/ch/ethz/seb/sebserver/gbl/Constants.java
@@ -1,136 +1,137 @@
-/*
- * Copyright (c) 2018 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.gbl;
-
-import java.util.Collection;
-
-import org.eclipse.swt.graphics.RGB;
-import org.joda.time.format.DateTimeFormat;
-import org.joda.time.format.DateTimeFormatter;
-import org.springframework.core.ParameterizedTypeReference;
-
-import com.fasterxml.jackson.core.type.TypeReference;
-
-import ch.ethz.seb.sebserver.gbl.api.APIMessage;
-import ch.ethz.seb.sebserver.gbl.api.authorization.Privilege;
-
-/** Global Constants used in SEB Server web-service as well as in web-gui component */
-public final class Constants {
-
- public static final String DEFAULT_LANG_CODE = "en";
- public static final String DEFAULT_TIME_ZONE_CODE = "UTC";
-
- public static final int SEB_FILE_HEADER_SIZE = 4;
- public static final int JN_CRYPTOR_ITERATIONS = 10000;
- public static final int JN_CRYPTOR_VERSION_HEADER_SIZE = 1;
-
- 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;
- public static final long DAY_IN_MILLIS = 24 * HOUR_IN_MILLIS;
-
- public static final Character CARRIAGE_RETURN = '\n';
- public static final Character CURLY_BRACE_OPEN = '{';
- public static final Character CURLY_BRACE_CLOSE = '}';
- public static final Character SQUARE_BRACE_OPEN = '[';
- public static final Character SQUARE_BRACE_CLOSE = ']';
- public static final Character COLON = ':';
- public static final Character SEMICOLON = ';';
- public static final Character PERCENTAGE = '%';
- public static final Character SLASH = '/';
- public static final Character BACKSLASH = '\\';
- public static final Character QUOTE = '\'';
- public static final Character DOUBLE_QUOTE = '"';
- public static final Character COMMA = ',';
- public static final Character PIPE = '|';
- public static final Character AMPERSAND = '&';
- public static final Character EQUALITY_SIGN = '=';
- public static final Character LIST_SEPARATOR_CHAR = COMMA;
- public static final Character COMPLEX_VALUE_SEPARATOR = COLON;
-
- public static final String NULL = "null";
- public static final String PERCENTAGE_STRING = Constants.PERCENTAGE.toString();
- public static final String LIST_SEPARATOR = COMMA.toString();
- public static final String EMBEDDED_LIST_SEPARATOR = PIPE.toString();
- public static final String NO_NAME = "NONE";
- public static final String EMPTY_NOTE = "--";
- public static final String FORM_URL_ENCODED_SEPARATOR = AMPERSAND.toString();
- public static final String FORM_URL_ENCODED_NAME_VALUE_SEPARATOR = EQUALITY_SIGN.toString();
- public static final String URL_PORT_SEPARATOR = COLON.toString();
- public static final String URL_ADDRESS_SEPARATOR = COLON.toString() + SLASH.toString() + SLASH.toString();
- public static final String URL_PATH_SEPARATOR = SLASH.toString();
-
- public static final String DEFAULT_DATE_TIME_FORMAT = "yyyy-MM-dd'T'HH:mm:ss'Z'";
- public static final String TIME_ZONE_OFFSET_TAIL_FORMAT = "|ZZ";
-
- //public static final String DEFAULT_DIPLAY_DATE_TIME_FORMAT = "MM-dd-yyyy HH:mm:ss";
- public static final String DEFAULT_DISPLAY_DATE_FORMAT = "MM-dd-yyyy";
- public static final String DEFAULT_TIME_FORMAT = "HH:mm:ss";
-
- public static final DateTimeFormatter STANDARD_DATE_TIME_FORMATTER = DateTimeFormat
- .forPattern(DEFAULT_DATE_TIME_FORMAT)
- .withZoneUTC();
-
- public static final String XML_VERSION_HEADER =
- "";
- public static final String XML_DOCTYPE_HEADER =
- "";
- public static final String XML_PLIST_START_V1 =
- "";
- public static final String XML_PLIST_END =
- "";
- public static final String XML_DICT_START =
- "";
- public static final String XML_DICT_END =
- "";
-
- public static final String XML_PLIST_NAME = "plist";
- public static final String XML_PLIST_DICT_NAME = "dict";
- public static final String XML_PLIST_ARRAY_NAME = "array";
- public static final String XML_PLIST_KEY_NAME = "key";
- public static final String XML_PLIST_BOOLEAN_TRUE = "true";
- public static final String XML_PLIST_BOOLEAN_FALSE = "false";
- public static final String XML_PLIST_STRING = "string";
- public static final String XML_PLIST_DATA = "data";
- public static final String XML_PLIST_INTEGER = "integer";
-
- public static final String OAUTH2_GRANT_TYPE_PASSWORD = "password";
- public static final String OAUTH2_CLIENT_SECRET = "client_secret";
- public static final String OAUTH2_GRANT_TYPE_REFRESH_TOKEN = "refresh_token";
- public static final String OAUTH2_GRANT_TYPE_CLIENT_CREDENTIALS = "client_credentials";
- public static final String OAUTH2_SCOPE_READ = "read";
- public static final String OAUTH2_SCOPE_WRITE = "write";
-
- public static final int RWT_MOUSE_BUTTON_1 = 1;
- public static final int RWT_MOUSE_BUTTON_2 = 2;
- public static final int RWT_MOUSE_BUTTON_3 = 3;
-
- public static final int GZIP_HEADER_LENGTH = 4;
- public static final int GZIP_ID1 = 0x1F;
- public static final int GZIP_ID2 = 0x8B;
- public static final int GZIP_CM = 8;
-
- public static final RGB WHITE_RGB = new RGB(255, 255, 255);
- public static final RGB BLACK_RGB = new RGB(0, 0, 0);
-
- public static final TypeReference> TYPE_REFERENCE_API_MESSAGE =
- new TypeReferenceAPIMessage();
- public static final ParameterizedTypeReference> TYPE_REFERENCE_PRIVILEGES =
- new TypeReferencePrivileges();
-
- public static final class TypeReferenceAPIMessage extends TypeReference> {
- }
-
- public static final class TypeReferencePrivileges extends ParameterizedTypeReference> {
- }
-
-}
+/*
+ * Copyright (c) 2018 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.gbl;
+
+import java.util.Collection;
+
+import org.eclipse.swt.graphics.RGB;
+import org.joda.time.format.DateTimeFormat;
+import org.joda.time.format.DateTimeFormatter;
+import org.springframework.core.ParameterizedTypeReference;
+
+import com.fasterxml.jackson.core.type.TypeReference;
+
+import ch.ethz.seb.sebserver.gbl.api.APIMessage;
+import ch.ethz.seb.sebserver.gbl.api.authorization.Privilege;
+
+/** Global Constants used in SEB Server web-service as well as in web-gui component */
+public final class Constants {
+
+ public static final String DEFAULT_LANG_CODE = "en";
+ public static final String DEFAULT_TIME_ZONE_CODE = "UTC";
+ public static final String TOOLTIP_TEXT_KEY_SUFFIX = ".tooltip";
+
+ public static final int SEB_FILE_HEADER_SIZE = 4;
+ public static final int JN_CRYPTOR_ITERATIONS = 10000;
+ public static final int JN_CRYPTOR_VERSION_HEADER_SIZE = 1;
+
+ 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;
+ public static final long DAY_IN_MILLIS = 24 * HOUR_IN_MILLIS;
+
+ public static final Character CARRIAGE_RETURN = '\n';
+ public static final Character CURLY_BRACE_OPEN = '{';
+ public static final Character CURLY_BRACE_CLOSE = '}';
+ public static final Character SQUARE_BRACE_OPEN = '[';
+ public static final Character SQUARE_BRACE_CLOSE = ']';
+ public static final Character COLON = ':';
+ public static final Character SEMICOLON = ';';
+ public static final Character PERCENTAGE = '%';
+ public static final Character SLASH = '/';
+ public static final Character BACKSLASH = '\\';
+ public static final Character QUOTE = '\'';
+ public static final Character DOUBLE_QUOTE = '"';
+ public static final Character COMMA = ',';
+ public static final Character PIPE = '|';
+ public static final Character AMPERSAND = '&';
+ public static final Character EQUALITY_SIGN = '=';
+ public static final Character LIST_SEPARATOR_CHAR = COMMA;
+ public static final Character COMPLEX_VALUE_SEPARATOR = COLON;
+
+ public static final String NULL = "null";
+ public static final String PERCENTAGE_STRING = Constants.PERCENTAGE.toString();
+ public static final String LIST_SEPARATOR = COMMA.toString();
+ public static final String EMBEDDED_LIST_SEPARATOR = PIPE.toString();
+ public static final String NO_NAME = "NONE";
+ public static final String EMPTY_NOTE = "--";
+ public static final String FORM_URL_ENCODED_SEPARATOR = AMPERSAND.toString();
+ public static final String FORM_URL_ENCODED_NAME_VALUE_SEPARATOR = EQUALITY_SIGN.toString();
+ public static final String URL_PORT_SEPARATOR = COLON.toString();
+ public static final String URL_ADDRESS_SEPARATOR = COLON.toString() + SLASH.toString() + SLASH.toString();
+ public static final String URL_PATH_SEPARATOR = SLASH.toString();
+
+ public static final String DEFAULT_DATE_TIME_FORMAT = "yyyy-MM-dd'T'HH:mm:ss'Z'";
+ public static final String TIME_ZONE_OFFSET_TAIL_FORMAT = "|ZZ";
+
+ //public static final String DEFAULT_DIPLAY_DATE_TIME_FORMAT = "MM-dd-yyyy HH:mm:ss";
+ public static final String DEFAULT_DISPLAY_DATE_FORMAT = "MM-dd-yyyy";
+ public static final String DEFAULT_TIME_FORMAT = "HH:mm:ss";
+
+ public static final DateTimeFormatter STANDARD_DATE_TIME_FORMATTER = DateTimeFormat
+ .forPattern(DEFAULT_DATE_TIME_FORMAT)
+ .withZoneUTC();
+
+ public static final String XML_VERSION_HEADER =
+ "";
+ public static final String XML_DOCTYPE_HEADER =
+ "";
+ public static final String XML_PLIST_START_V1 =
+ "";
+ public static final String XML_PLIST_END =
+ "";
+ public static final String XML_DICT_START =
+ "";
+ public static final String XML_DICT_END =
+ "";
+
+ public static final String XML_PLIST_NAME = "plist";
+ public static final String XML_PLIST_DICT_NAME = "dict";
+ public static final String XML_PLIST_ARRAY_NAME = "array";
+ public static final String XML_PLIST_KEY_NAME = "key";
+ public static final String XML_PLIST_BOOLEAN_TRUE = "true";
+ public static final String XML_PLIST_BOOLEAN_FALSE = "false";
+ public static final String XML_PLIST_STRING = "string";
+ public static final String XML_PLIST_DATA = "data";
+ public static final String XML_PLIST_INTEGER = "integer";
+
+ public static final String OAUTH2_GRANT_TYPE_PASSWORD = "password";
+ public static final String OAUTH2_CLIENT_SECRET = "client_secret";
+ public static final String OAUTH2_GRANT_TYPE_REFRESH_TOKEN = "refresh_token";
+ public static final String OAUTH2_GRANT_TYPE_CLIENT_CREDENTIALS = "client_credentials";
+ public static final String OAUTH2_SCOPE_READ = "read";
+ public static final String OAUTH2_SCOPE_WRITE = "write";
+
+ public static final int RWT_MOUSE_BUTTON_1 = 1;
+ public static final int RWT_MOUSE_BUTTON_2 = 2;
+ public static final int RWT_MOUSE_BUTTON_3 = 3;
+
+ public static final int GZIP_HEADER_LENGTH = 4;
+ public static final int GZIP_ID1 = 0x1F;
+ public static final int GZIP_ID2 = 0x8B;
+ public static final int GZIP_CM = 8;
+
+ public static final RGB WHITE_RGB = new RGB(255, 255, 255);
+ public static final RGB BLACK_RGB = new RGB(0, 0, 0);
+
+ public static final TypeReference> TYPE_REFERENCE_API_MESSAGE =
+ new TypeReferenceAPIMessage();
+ public static final ParameterizedTypeReference> TYPE_REFERENCE_PRIVILEGES =
+ new TypeReferencePrivileges();
+
+ public static final class TypeReferenceAPIMessage extends TypeReference> {
+ }
+
+ public static final class TypeReferencePrivileges extends ParameterizedTypeReference> {
+ }
+
+}
diff --git a/src/main/java/ch/ethz/seb/sebserver/gbl/model/user/UserInfo.java b/src/main/java/ch/ethz/seb/sebserver/gbl/model/user/UserInfo.java
index a312d606..f828a0a5 100644
--- a/src/main/java/ch/ethz/seb/sebserver/gbl/model/user/UserInfo.java
+++ b/src/main/java/ch/ethz/seb/sebserver/gbl/model/user/UserInfo.java
@@ -1,360 +1,361 @@
-/*
- * Copyright (c) 2018 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.gbl.model.user;
-
-import java.io.Serializable;
-import java.util.Arrays;
-import java.util.EnumSet;
-import java.util.HashSet;
-import java.util.Locale;
-import java.util.Set;
-import java.util.stream.Collectors;
-
-import javax.validation.constraints.Email;
-import javax.validation.constraints.NotEmpty;
-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.DateTime;
-import org.joda.time.DateTimeZone;
-import org.springframework.util.CollectionUtils;
-
-import com.fasterxml.jackson.annotation.JsonCreator;
-import com.fasterxml.jackson.annotation.JsonIgnore;
-import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
-import com.fasterxml.jackson.annotation.JsonProperty;
-
-import ch.ethz.seb.sebserver.gbl.api.EntityType;
-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;
-
-/** The user info domain model contains primary user information
- *
- * This domain model is annotated and fully serializable and deserializable
- * to and from JSON within the Jackson library.
- *
- * This domain model is immutable and thread-save */
-@JsonIgnoreProperties(ignoreUnknown = true)
-public final class UserInfo implements UserAccount, Serializable {
-
- private static final long serialVersionUID = 2526446136264377808L;
-
- 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)
- public final String uuid;
-
- /** The foreign key identifier to the institution where the User belongs to */
- @NotNull
- @JsonProperty(USER.ATTR_INSTITUTION_ID)
- public final Long institutionId;
-
- @JsonProperty(USER.ATTR_CREATION_DATE)
- public final DateTime creationDate;
-
- /** First name of the user */
- @NotNull(message = "user:name:notNull")
- @Size(min = 3, max = 255, message = "user:name:size:{min}:{max}:${validatedValue}")
- @JsonProperty(USER.ATTR_NAME)
- public final String name;
-
- /** Surname of the user */
- @Size(max = 255, message = "user:surname:size:{min}:{max}:${validatedValue}")
- @JsonProperty(USER.ATTR_SURNAME)
- public final String surname;
-
- /** The internal user name */
- @NotNull(message = "user:username:notNull")
- @Size(min = 3, max = 255, message = "user:username:size:{min}:{max}:${validatedValue}")
- @JsonProperty(USER.ATTR_USERNAME)
- public final String username;
-
- /** E-mail address of the user */
- @Email(message = "user:email:email:_:_:${validatedValue}")
- @JsonProperty(USER.ATTR_EMAIL)
- public final String email;
-
- /** Indicates whether this user is still active or not */
- @NotNull
- @JsonProperty(USER.ATTR_ACTIVE)
- public final Boolean active;
-
- /** The users locale */
- @NotNull(message = "user:language:notNull")
- @JsonProperty(USER.ATTR_LANGUAGE)
- public final Locale language;
-
- /** The users time zone */
- @NotNull(message = "user:timeZone:notNull")
- @JsonProperty(USER.ATTR_TIMEZONE)
- public final DateTimeZone timeZone;
-
- /** The users roles in a unmodifiable set. Is never null */
- @NotNull(message = "user:userRoles:notNull")
- @NotEmpty(message = "user:userRoles:notNull")
- @JsonProperty(USER_ROLE.REFERENCE_NAME)
- public final Set roles;
-
- @JsonCreator
- public UserInfo(
- @JsonProperty(USER.ATTR_UUID) final String uuid,
- @JsonProperty(USER.ATTR_INSTITUTION_ID) final Long institutionId,
- @JsonProperty(USER.ATTR_CREATION_DATE) final DateTime creationDate,
- @JsonProperty(USER.ATTR_NAME) final String name,
- @JsonProperty(USER.ATTR_SURNAME) final String surname,
- @JsonProperty(USER.ATTR_USERNAME) final String username,
- @JsonProperty(USER.ATTR_EMAIL) final String email,
- @JsonProperty(USER.ATTR_ACTIVE) final Boolean active,
- @JsonProperty(USER.ATTR_LANGUAGE) final Locale language,
- @JsonProperty(USER.ATTR_TIMEZONE) final DateTimeZone timeZone,
- @JsonProperty(USER_ROLE.REFERENCE_NAME) final Set roles) {
-
- this.uuid = uuid;
- this.institutionId = institutionId;
- this.creationDate = creationDate;
- this.name = name;
- this.surname = surname;
- this.username = username;
- this.email = email;
- this.active = BooleanUtils.isTrue(active);
- this.language = language;
- this.timeZone = timeZone;
- this.roles = Utils.immutableSetOf(roles);
- }
-
- @Override
- public EntityType entityType() {
- return EntityType.USER;
- }
-
- @Override
- public String getModelId() {
- return this.uuid;
- }
-
- public String getUuid() {
- return this.uuid;
- }
-
- @Override
- public DateTime getCreationDate() {
- return this.creationDate;
- }
-
- @Override
- public Long getInstitutionId() {
- return this.institutionId;
- }
-
- @Override
- public String getOwnerId() {
- return this.uuid;
- }
-
- @Override
- public String getName() {
- return this.name;
- }
-
- @Override
- public String getSurname() {
- return this.surname;
- }
-
- @Override
- public String getUsername() {
- return this.username;
- }
-
- @Override
- public String getEmail() {
- return this.email;
- }
-
- @Override
- public Boolean getActive() {
- return this.active;
- }
-
- @Override
- public boolean isActive() {
- return this.active;
- }
-
- @Override
- public Locale getLanguage() {
- return this.language;
- }
-
- @Override
- public DateTimeZone getTimeZone() {
- return this.timeZone;
- }
-
- @Override
- public Set getRoles() {
- return this.roles;
- }
-
- @Override
- @JsonIgnore
- public EnumSet getUserRoles() {
- return EnumSet.copyOf(
- getRoles().stream()
- .map(r -> UserRole.valueOf(r))
- .collect(Collectors.toList()));
- }
-
- public boolean hasRole(final UserRole userRole) {
- if (userRole == null) {
- return false;
- }
- return this.roles.contains(userRole.name());
- }
-
- public boolean hasAnyRole(final UserRole... userRole) {
- if (userRole == null) {
- return false;
- }
- return CollectionUtils.containsAny(getUserRoles(), Arrays.asList(userRole));
- }
-
- @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;
- int result = 1;
- result = prime * result + ((this.uuid == null) ? 0 : this.uuid.hashCode());
- return result;
- }
-
- @Override
- public boolean equals(final Object obj) {
- if (this == obj)
- return true;
- if (obj == null)
- return false;
- if (getClass() != obj.getClass())
- return false;
- final UserInfo other = (UserInfo) obj;
- if (this.uuid == null) {
- if (other.uuid != null)
- return false;
- } else if (!this.uuid.equals(other.uuid))
- return false;
- return true;
- }
-
- @Override
- public String toString() {
- final StringBuilder builder = new StringBuilder();
- builder.append("UserInfo [uuid=");
- builder.append(this.uuid);
- builder.append(", institutionId=");
- builder.append(this.institutionId);
- builder.append(", creationDate=");
- builder.append(this.creationDate);
- builder.append(", name=");
- builder.append(this.name);
- builder.append(", surname=");
- builder.append(this.surname);
- builder.append(", username=");
- builder.append(this.username);
- builder.append(", email=");
- builder.append(this.email);
- builder.append(", active=");
- builder.append(this.active);
- builder.append(", language=");
- builder.append(this.language);
- builder.append(", timeZone=");
- builder.append(this.timeZone);
- builder.append(", roles=");
- builder.append(this.roles);
- builder.append("]");
- return builder.toString();
- }
-
- /** Use this to create a copy of a given UserInfo instance.
- *
- * @param userInfo UserInfo instance to copy
- * @return copied UserInfo instance */
- public static final UserInfo of(final UserInfo userInfo) {
- return new UserInfo(
- userInfo.getUuid(),
- userInfo.getInstitutionId(),
- userInfo.creationDate,
- userInfo.getName(),
- userInfo.getUsername(),
- userInfo.getSurname(),
- userInfo.getEmail(),
- userInfo.getActive(),
- userInfo.getLanguage(),
- userInfo.getTimeZone(),
- userInfo.roles);
- }
-
- /** Use this to create a copy of a given UserInfo by overriding available arguments.
- *
- * @param userInfo UserInfo instance to copy
- * @param name new name or null if the name of given userInfo should be taken
- * @param surname new surname or null if the name of given userInfo should be taken
- * @param username new username or null if the username of given userInfo should be taken
- * @param email new email or null if the email of given userInfo should be taken
- * @param language new language or null if the language of given userInfo should be taken
- * @param timeZone new timeZone or null if the timeZone of given userInfo should be taken
- * @param roles new timeZone or null if the roles of given userInfo should be taken
- * @return copied UserInfo instance with the given attributes */
- public static final UserInfo of(
- final UserInfo userInfo,
- final String name,
- final String username,
- final String surname,
- final String email,
- final Locale language,
- final DateTimeZone timeZone,
- final String... roles) {
-
- return new UserInfo(
- userInfo.getUuid(),
- userInfo.getInstitutionId(),
- userInfo.creationDate,
- (name != null) ? name : userInfo.getName(),
- (surname != null) ? surname : userInfo.getSurname(),
- (username != null) ? username : userInfo.getUsername(),
- (email != null) ? email : userInfo.getEmail(),
- userInfo.getActive(),
- (language != null) ? language : userInfo.getLanguage(),
- (timeZone != null) ? timeZone : userInfo.getTimeZone(),
- (roles != null) ? new HashSet<>(Arrays.asList(roles)) : userInfo.roles);
- }
-
- public static final UserInfo withEMail(final UserInfo userInfo, final String email) {
- return of(userInfo, null, null, null, email, null, null, (String[]) null);
- }
-
- public static final UserInfo withRoles(final UserInfo userInfo, final String... roles) {
- return of(userInfo, null, null, null, null, null, null, roles);
- }
-}
+/*
+ * Copyright (c) 2018 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.gbl.model.user;
+
+import java.io.Serializable;
+import java.util.Arrays;
+import java.util.EnumSet;
+import java.util.HashSet;
+import java.util.Locale;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import javax.validation.constraints.Email;
+import javax.validation.constraints.NotEmpty;
+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.DateTime;
+import org.joda.time.DateTimeZone;
+import org.springframework.util.CollectionUtils;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+import ch.ethz.seb.sebserver.gbl.api.EntityType;
+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;
+
+/** The user info domain model contains primary user information
+ *
+ * This domain model is annotated and fully serializable and deserializable
+ * to and from JSON within the Jackson library.
+ *
+ * This domain model is immutable and thread-save */
+@JsonIgnoreProperties(ignoreUnknown = true)
+public final class UserInfo implements UserAccount, Serializable {
+
+ private static final long serialVersionUID = 2526446136264377808L;
+
+ 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)
+ public final String uuid;
+
+ /** The foreign key identifier to the institution where the User belongs to */
+ @NotNull(message = "user:institutionId:notNull")
+ @JsonProperty(USER.ATTR_INSTITUTION_ID)
+ public final Long institutionId;
+
+ @JsonProperty(USER.ATTR_CREATION_DATE)
+ public final DateTime creationDate;
+
+ /** First name of the user */
+ @NotNull(message = "user:name:notNull")
+ @Size(max = 255, message = "user:name:size:{min}:{max}:${validatedValue}")
+ @JsonProperty(USER.ATTR_NAME)
+ public final String name;
+
+ /** Surname of the user */
+ @NotNull(message = "user:surname:notNull")
+ @Size(max = 255, message = "user:surname:size:{min}:{max}:${validatedValue}")
+ @JsonProperty(USER.ATTR_SURNAME)
+ public final String surname;
+
+ /** The internal user name */
+ @NotNull(message = "user:username:notNull")
+ @Size(min = 3, max = 255, message = "user:username:size:{min}:{max}:${validatedValue}")
+ @JsonProperty(USER.ATTR_USERNAME)
+ public final String username;
+
+ /** E-mail address of the user */
+ @Email(message = "user:email:email:_:_:${validatedValue}")
+ @JsonProperty(USER.ATTR_EMAIL)
+ public final String email;
+
+ /** Indicates whether this user is still active or not */
+ @NotNull
+ @JsonProperty(USER.ATTR_ACTIVE)
+ public final Boolean active;
+
+ /** The users locale */
+ @NotNull(message = "user:language:notNull")
+ @JsonProperty(USER.ATTR_LANGUAGE)
+ public final Locale language;
+
+ /** The users time zone */
+ @NotNull(message = "user:timeZone:notNull")
+ @JsonProperty(USER.ATTR_TIMEZONE)
+ public final DateTimeZone timeZone;
+
+ /** The users roles in a unmodifiable set. Is never null */
+ @NotNull(message = "user:userRoles:notNull")
+ @NotEmpty(message = "user:userRoles:notNull")
+ @JsonProperty(USER_ROLE.REFERENCE_NAME)
+ public final Set roles;
+
+ @JsonCreator
+ public UserInfo(
+ @JsonProperty(USER.ATTR_UUID) final String uuid,
+ @JsonProperty(USER.ATTR_INSTITUTION_ID) final Long institutionId,
+ @JsonProperty(USER.ATTR_CREATION_DATE) final DateTime creationDate,
+ @JsonProperty(USER.ATTR_NAME) final String name,
+ @JsonProperty(USER.ATTR_SURNAME) final String surname,
+ @JsonProperty(USER.ATTR_USERNAME) final String username,
+ @JsonProperty(USER.ATTR_EMAIL) final String email,
+ @JsonProperty(USER.ATTR_ACTIVE) final Boolean active,
+ @JsonProperty(USER.ATTR_LANGUAGE) final Locale language,
+ @JsonProperty(USER.ATTR_TIMEZONE) final DateTimeZone timeZone,
+ @JsonProperty(USER_ROLE.REFERENCE_NAME) final Set roles) {
+
+ this.uuid = uuid;
+ this.institutionId = institutionId;
+ this.creationDate = creationDate;
+ this.name = name;
+ this.surname = surname;
+ this.username = username;
+ this.email = email;
+ this.active = BooleanUtils.isTrue(active);
+ this.language = language;
+ this.timeZone = timeZone;
+ this.roles = Utils.immutableSetOf(roles);
+ }
+
+ @Override
+ public EntityType entityType() {
+ return EntityType.USER;
+ }
+
+ @Override
+ public String getModelId() {
+ return this.uuid;
+ }
+
+ public String getUuid() {
+ return this.uuid;
+ }
+
+ @Override
+ public DateTime getCreationDate() {
+ return this.creationDate;
+ }
+
+ @Override
+ public Long getInstitutionId() {
+ return this.institutionId;
+ }
+
+ @Override
+ public String getOwnerId() {
+ return this.uuid;
+ }
+
+ @Override
+ public String getName() {
+ return this.name;
+ }
+
+ @Override
+ public String getSurname() {
+ return this.surname;
+ }
+
+ @Override
+ public String getUsername() {
+ return this.username;
+ }
+
+ @Override
+ public String getEmail() {
+ return this.email;
+ }
+
+ @Override
+ public Boolean getActive() {
+ return this.active;
+ }
+
+ @Override
+ public boolean isActive() {
+ return this.active;
+ }
+
+ @Override
+ public Locale getLanguage() {
+ return this.language;
+ }
+
+ @Override
+ public DateTimeZone getTimeZone() {
+ return this.timeZone;
+ }
+
+ @Override
+ public Set getRoles() {
+ return this.roles;
+ }
+
+ @Override
+ @JsonIgnore
+ public EnumSet getUserRoles() {
+ return EnumSet.copyOf(
+ getRoles().stream()
+ .map(UserRole::valueOf)
+ .collect(Collectors.toList()));
+ }
+
+ public boolean hasRole(final UserRole userRole) {
+ if (userRole == null) {
+ return false;
+ }
+ return this.roles.contains(userRole.name());
+ }
+
+ public boolean hasAnyRole(final UserRole... userRole) {
+ if (userRole == null) {
+ return false;
+ }
+ return CollectionUtils.containsAny(getUserRoles(), Arrays.asList(userRole));
+ }
+
+ @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;
+ int result = 1;
+ result = prime * result + ((this.uuid == null) ? 0 : this.uuid.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ final UserInfo other = (UserInfo) obj;
+ if (this.uuid == null) {
+ if (other.uuid != null)
+ return false;
+ } else if (!this.uuid.equals(other.uuid))
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append("UserInfo [uuid=");
+ builder.append(this.uuid);
+ builder.append(", institutionId=");
+ builder.append(this.institutionId);
+ builder.append(", creationDate=");
+ builder.append(this.creationDate);
+ builder.append(", name=");
+ builder.append(this.name);
+ builder.append(", surname=");
+ builder.append(this.surname);
+ builder.append(", username=");
+ builder.append(this.username);
+ builder.append(", email=");
+ builder.append(this.email);
+ builder.append(", active=");
+ builder.append(this.active);
+ builder.append(", language=");
+ builder.append(this.language);
+ builder.append(", timeZone=");
+ builder.append(this.timeZone);
+ builder.append(", roles=");
+ builder.append(this.roles);
+ builder.append("]");
+ return builder.toString();
+ }
+
+ /** Use this to create a copy of a given UserInfo instance.
+ *
+ * @param userInfo UserInfo instance to copy
+ * @return copied UserInfo instance */
+ public static UserInfo of(final UserInfo userInfo) {
+ return new UserInfo(
+ userInfo.getUuid(),
+ userInfo.getInstitutionId(),
+ userInfo.creationDate,
+ userInfo.getName(),
+ userInfo.getUsername(),
+ userInfo.getSurname(),
+ userInfo.getEmail(),
+ userInfo.getActive(),
+ userInfo.getLanguage(),
+ userInfo.getTimeZone(),
+ userInfo.roles);
+ }
+
+ /** Use this to create a copy of a given UserInfo by overriding available arguments.
+ *
+ * @param userInfo UserInfo instance to copy
+ * @param name new name or null if the name of given userInfo should be taken
+ * @param surname new surname or null if the name of given userInfo should be taken
+ * @param username new username or null if the username of given userInfo should be taken
+ * @param email new email or null if the email of given userInfo should be taken
+ * @param language new language or null if the language of given userInfo should be taken
+ * @param timeZone new timeZone or null if the timeZone of given userInfo should be taken
+ * @param roles new timeZone or null if the roles of given userInfo should be taken
+ * @return copied UserInfo instance with the given attributes */
+ public static UserInfo of(
+ final UserInfo userInfo,
+ final String name,
+ final String username,
+ final String surname,
+ final String email,
+ final Locale language,
+ final DateTimeZone timeZone,
+ final String... roles) {
+
+ return new UserInfo(
+ userInfo.getUuid(),
+ userInfo.getInstitutionId(),
+ userInfo.creationDate,
+ (name != null) ? name : userInfo.getName(),
+ (surname != null) ? surname : userInfo.getSurname(),
+ (username != null) ? username : userInfo.getUsername(),
+ (email != null) ? email : userInfo.getEmail(),
+ userInfo.getActive(),
+ (language != null) ? language : userInfo.getLanguage(),
+ (timeZone != null) ? timeZone : userInfo.getTimeZone(),
+ (roles != null) ? new HashSet<>(Arrays.asList(roles)) : userInfo.roles);
+ }
+
+ public static UserInfo withEMail(final UserInfo userInfo, final String email) {
+ return of(userInfo, null, null, null, email, null, null, (String[]) null);
+ }
+
+ public static UserInfo withRoles(final UserInfo userInfo, final String... roles) {
+ return of(userInfo, null, null, null, null, null, null, roles);
+ }
+}
diff --git a/src/main/java/ch/ethz/seb/sebserver/gbl/model/user/UserMod.java b/src/main/java/ch/ethz/seb/sebserver/gbl/model/user/UserMod.java
index e18cd318..18f75ef1 100644
--- a/src/main/java/ch/ethz/seb/sebserver/gbl/model/user/UserMod.java
+++ b/src/main/java/ch/ethz/seb/sebserver/gbl/model/user/UserMod.java
@@ -1,284 +1,285 @@
-/*
- * Copyright (c) 2018 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.gbl.model.user;
-
-import java.util.Collections;
-import java.util.EnumSet;
-import java.util.List;
-import java.util.Locale;
-import java.util.Set;
-import java.util.UUID;
-import java.util.stream.Collectors;
-
-import javax.validation.constraints.Email;
-import javax.validation.constraints.NotEmpty;
-import javax.validation.constraints.NotNull;
-import javax.validation.constraints.Size;
-
-import org.apache.commons.lang3.StringUtils;
-import org.joda.time.DateTime;
-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;
-
-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.gbl.model.EntityKey;
-
-@JsonIgnoreProperties(ignoreUnknown = true)
-public final class UserMod implements UserAccount {
-
- @JsonProperty(USER.ATTR_UUID)
- public final String uuid;
-
- /** The foreign key identifier to the institution where the User belongs to */
- @NotNull(message = "user:institutionId:notNull")
- @JsonProperty(USER.ATTR_INSTITUTION_ID)
- public final Long institutionId;
-
- /** first (or full) name of the user */
- @NotNull(message = "user:name:notNull")
- @Size(min = 3, max = 255, message = "user:name:size:{min}:{max}:${validatedValue}")
- @JsonProperty(USER.ATTR_NAME)
- public final String name;
-
- /** surname of the user */
- @Size(max = 255, message = "user:surname:size:{min}:{max}:${validatedValue}")
- @JsonProperty(USER.ATTR_SURNAME)
- public final String surname;
-
- /** The internal user name */
- @NotNull(message = "user:username:notNull")
- @Size(min = 3, max = 255, message = "user:username:size:{min}:{max}:${validatedValue}")
- @JsonProperty(USER.ATTR_USERNAME)
- public final String username;
-
- /** E-mail address of the user */
- @Email(message = "user:email:email:_:_:${validatedValue}")
- @JsonProperty(USER.ATTR_EMAIL)
- public final String email;
-
- /** The users locale */
- @NotNull(message = "user:language:notNull")
- @JsonProperty(USER.ATTR_LANGUAGE)
- public final Locale language;
-
- /** The users time zone */
- @NotNull(message = "user:timeZone:notNull")
- @JsonProperty(USER.ATTR_TIMEZONE)
- public final DateTimeZone timeZone;
-
- /** The users roles in a unmodifiable set */
- @NotNull(message = "user:userRoles:notNull")
- @NotEmpty(message = "user:userRoles:notNull")
- @JsonProperty(USER_ROLE.REFERENCE_NAME)
- public final Set roles;
-
- @NotNull(message = "user:newPassword:notNull")
- @Size(min = 8, max = 255, message = "user:newPassword:size:{min}:{max}:${validatedValue}")
- @JsonProperty(PasswordChange.ATTR_NAME_NEW_PASSWORD)
- private final CharSequence newPassword;
-
- @NotNull(message = "user:confirmNewPassword:notNull")
- @JsonProperty(PasswordChange.ATTR_NAME_CONFIRM_NEW_PASSWORD)
- private final CharSequence confirmNewPassword;
-
- @JsonCreator
- public UserMod(
- @JsonProperty(USER.ATTR_UUID) final String uuid,
- @JsonProperty(USER.ATTR_INSTITUTION_ID) final Long institutionId,
- @JsonProperty(USER.ATTR_NAME) final String name,
- @JsonProperty(USER.ATTR_SURNAME) final String surname,
- @JsonProperty(USER.ATTR_USERNAME) final String username,
- @JsonProperty(PasswordChange.ATTR_NAME_NEW_PASSWORD) final CharSequence newPassword,
- @JsonProperty(PasswordChange.ATTR_NAME_CONFIRM_NEW_PASSWORD) final CharSequence confirmNewPassword,
- @JsonProperty(USER.ATTR_EMAIL) final String email,
- @JsonProperty(USER.ATTR_LANGUAGE) final Locale language,
- @JsonProperty(USER.ATTR_TIMEZONE) final DateTimeZone timeZone,
- @JsonProperty(USER_ROLE.REFERENCE_NAME) final Set roles) {
-
- this.uuid = uuid;
- this.institutionId = institutionId;
- this.newPassword = newPassword;
- this.confirmNewPassword = confirmNewPassword;
- this.name = name;
- this.surname = surname;
- this.username = username;
- this.email = email;
- this.language = (language != null) ? language : Locale.ENGLISH;
- this.timeZone = (timeZone != null) ? timeZone : DateTimeZone.UTC;
- this.roles = (roles != null)
- ? Collections.unmodifiableSet(roles)
- : Collections.emptySet();
- }
-
- public UserMod(final String modelId, final POSTMapper postAttrMapper) {
- this.uuid = modelId;
- this.institutionId = postAttrMapper.getLong(USER.ATTR_INSTITUTION_ID);
- this.newPassword = postAttrMapper.getString(PasswordChange.ATTR_NAME_NEW_PASSWORD);
- this.confirmNewPassword = postAttrMapper.getString(PasswordChange.ATTR_NAME_CONFIRM_NEW_PASSWORD);
- this.name = postAttrMapper.getString(USER.ATTR_NAME);
- this.surname = postAttrMapper.getString(USER.ATTR_SURNAME);
- this.username = postAttrMapper.getString(USER.ATTR_USERNAME);
- this.email = postAttrMapper.getString(USER.ATTR_EMAIL);
- this.language = postAttrMapper.getLocale(USER.ATTR_LANGUAGE);
- this.timeZone = postAttrMapper.getDateTimeZone(USER.ATTR_TIMEZONE);
- this.roles = postAttrMapper.getStringSet(USER_ROLE.REFERENCE_NAME);
- }
-
- @Override
- public String getModelId() {
- return this.uuid;
- }
-
- @Override
- public EntityType entityType() {
- return EntityType.USER;
- }
-
- @Override
- public Long getInstitutionId() {
- return this.institutionId;
- }
-
- @Override
- public DateTime getCreationDate() {
- return null;
- }
-
- @Override
- public String getOwnerId() {
- return this.uuid;
- }
-
- public CharSequence getNewPassword() {
- return this.newPassword;
- }
-
- @Override
- public String getName() {
- return this.name;
- }
-
- @Override
- public String getSurname() {
- return this.surname;
- }
-
- @Override
- public String getUsername() {
- return this.username;
- }
-
- @Override
- public String getEmail() {
- return this.email;
- }
-
- @Override
- public Locale getLanguage() {
- return this.language;
- }
-
- @Override
- public DateTimeZone getTimeZone() {
- return this.timeZone;
- }
-
- @Override
- public Set getRoles() {
- return this.roles;
- }
-
- @Override
- @JsonIgnore
- public EnumSet getUserRoles() {
- final List roles = getRoles()
- .stream()
- .map(r -> UserRole.valueOf(r))
- .collect(Collectors.toList());
- if (roles.isEmpty()) {
- return EnumSet.noneOf(UserRole.class);
- }
- return EnumSet.copyOf(roles);
- }
-
- public CharSequence getRetypedNewPassword() {
- return this.confirmNewPassword;
- }
-
- public boolean passwordChangeRequest() {
- return this.newPassword != null;
- }
-
- public boolean newPasswordMatch() {
- return passwordChangeRequest() && this.newPassword.equals(this.confirmNewPassword);
- }
-
- @Override
- public Boolean getActive() {
- return false;
- }
-
- @Override
- public boolean isActive() {
- return false;
- }
-
- @JsonIgnore
- @Override
- public EntityKey getEntityKey() {
- if (StringUtils.isBlank(this.uuid)) {
- return null;
- }
- return new EntityKey(this.uuid, entityType());
- }
-
- @Override
- public String toString() {
- final StringBuilder builder = new StringBuilder();
- builder.append("UserMod [uuid=");
- builder.append(this.uuid);
- builder.append(", institutionId=");
- builder.append(this.institutionId);
- builder.append(", name=");
- builder.append(this.name);
- builder.append(", surname=");
- builder.append(this.surname);
- builder.append(", username=");
- builder.append(this.username);
- builder.append(", email=");
- builder.append(this.email);
- builder.append(", language=");
- builder.append(this.language);
- builder.append(", timeZone=");
- builder.append(this.timeZone);
- builder.append(", roles=");
- builder.append(this.roles);
- builder.append(", newPassword=");
- builder.append(this.newPassword);
- builder.append(", confirmNewPassword=");
- builder.append(this.confirmNewPassword);
- builder.append("]");
- return builder.toString();
- }
-
- public static UserMod createNew(final Long institutionId) {
- return new UserMod(
- UUID.randomUUID().toString(),
- institutionId,
- null, null, null, null, null, null, null, null, null);
- }
-
-}
+/*
+ * Copyright (c) 2018 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.gbl.model.user;
+
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.List;
+import java.util.Locale;
+import java.util.Set;
+import java.util.UUID;
+import java.util.stream.Collectors;
+
+import javax.validation.constraints.Email;
+import javax.validation.constraints.NotEmpty;
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Size;
+
+import org.apache.commons.lang3.StringUtils;
+import org.joda.time.DateTime;
+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;
+
+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.gbl.model.EntityKey;
+
+@JsonIgnoreProperties(ignoreUnknown = true)
+public final class UserMod implements UserAccount {
+
+ @JsonProperty(USER.ATTR_UUID)
+ public final String uuid;
+
+ /** The foreign key identifier to the institution where the User belongs to */
+ @NotNull(message = "user:institutionId:notNull")
+ @JsonProperty(USER.ATTR_INSTITUTION_ID)
+ public final Long institutionId;
+
+ /** first (or full) name of the user */
+ @NotNull(message = "user:name:notNull")
+ @Size(max = 255, message = "user:name:size:{min}:{max}:${validatedValue}")
+ @JsonProperty(USER.ATTR_NAME)
+ public final String name;
+
+ /** surname of the user */
+ @NotNull(message = "user:surname:notNull")
+ @Size(max = 255, message = "user:surname:size:{min}:{max}:${validatedValue}")
+ @JsonProperty(USER.ATTR_SURNAME)
+ public final String surname;
+
+ /** The internal user name */
+ @NotNull(message = "user:username:notNull")
+ @Size(min = 3, max = 255, message = "user:username:size:{min}:{max}:${validatedValue}")
+ @JsonProperty(USER.ATTR_USERNAME)
+ public final String username;
+
+ /** E-mail address of the user */
+ @Email(message = "user:email:email:_:_:${validatedValue}")
+ @JsonProperty(USER.ATTR_EMAIL)
+ public final String email;
+
+ /** The users locale */
+ @NotNull(message = "user:language:notNull")
+ @JsonProperty(USER.ATTR_LANGUAGE)
+ public final Locale language;
+
+ /** The users time zone */
+ @NotNull(message = "user:timeZone:notNull")
+ @JsonProperty(USER.ATTR_TIMEZONE)
+ public final DateTimeZone timeZone;
+
+ /** The users roles in a unmodifiable set */
+ @NotNull(message = "user:userRoles:notNull")
+ @NotEmpty(message = "user:userRoles:notNull")
+ @JsonProperty(USER_ROLE.REFERENCE_NAME)
+ public final Set roles;
+
+ @NotNull(message = "user:newPassword:notNull")
+ @Size(min = 8, max = 255, message = "user:newPassword:size:{min}:{max}:${validatedValue}")
+ @JsonProperty(PasswordChange.ATTR_NAME_NEW_PASSWORD)
+ private final CharSequence newPassword;
+
+ @NotNull(message = "user:confirmNewPassword:notNull")
+ @JsonProperty(PasswordChange.ATTR_NAME_CONFIRM_NEW_PASSWORD)
+ private final CharSequence confirmNewPassword;
+
+ @JsonCreator
+ public UserMod(
+ @JsonProperty(USER.ATTR_UUID) final String uuid,
+ @JsonProperty(USER.ATTR_INSTITUTION_ID) final Long institutionId,
+ @JsonProperty(USER.ATTR_NAME) final String name,
+ @JsonProperty(USER.ATTR_SURNAME) final String surname,
+ @JsonProperty(USER.ATTR_USERNAME) final String username,
+ @JsonProperty(PasswordChange.ATTR_NAME_NEW_PASSWORD) final CharSequence newPassword,
+ @JsonProperty(PasswordChange.ATTR_NAME_CONFIRM_NEW_PASSWORD) final CharSequence confirmNewPassword,
+ @JsonProperty(USER.ATTR_EMAIL) final String email,
+ @JsonProperty(USER.ATTR_LANGUAGE) final Locale language,
+ @JsonProperty(USER.ATTR_TIMEZONE) final DateTimeZone timeZone,
+ @JsonProperty(USER_ROLE.REFERENCE_NAME) final Set roles) {
+
+ this.uuid = uuid;
+ this.institutionId = institutionId;
+ this.newPassword = newPassword;
+ this.confirmNewPassword = confirmNewPassword;
+ this.name = name;
+ this.surname = surname;
+ this.username = username;
+ this.email = email;
+ this.language = (language != null) ? language : Locale.ENGLISH;
+ this.timeZone = (timeZone != null) ? timeZone : DateTimeZone.UTC;
+ this.roles = (roles != null)
+ ? Collections.unmodifiableSet(roles)
+ : Collections.emptySet();
+ }
+
+ public UserMod(final String modelId, final POSTMapper postAttrMapper) {
+ this.uuid = modelId;
+ this.institutionId = postAttrMapper.getLong(USER.ATTR_INSTITUTION_ID);
+ this.newPassword = postAttrMapper.getString(PasswordChange.ATTR_NAME_NEW_PASSWORD);
+ this.confirmNewPassword = postAttrMapper.getString(PasswordChange.ATTR_NAME_CONFIRM_NEW_PASSWORD);
+ this.name = postAttrMapper.getString(USER.ATTR_NAME);
+ this.surname = postAttrMapper.getString(USER.ATTR_SURNAME);
+ this.username = postAttrMapper.getString(USER.ATTR_USERNAME);
+ this.email = postAttrMapper.getString(USER.ATTR_EMAIL);
+ this.language = postAttrMapper.getLocale(USER.ATTR_LANGUAGE);
+ this.timeZone = postAttrMapper.getDateTimeZone(USER.ATTR_TIMEZONE);
+ this.roles = postAttrMapper.getStringSet(USER_ROLE.REFERENCE_NAME);
+ }
+
+ @Override
+ public String getModelId() {
+ return this.uuid;
+ }
+
+ @Override
+ public EntityType entityType() {
+ return EntityType.USER;
+ }
+
+ @Override
+ public Long getInstitutionId() {
+ return this.institutionId;
+ }
+
+ @Override
+ public DateTime getCreationDate() {
+ return null;
+ }
+
+ @Override
+ public String getOwnerId() {
+ return this.uuid;
+ }
+
+ public CharSequence getNewPassword() {
+ return this.newPassword;
+ }
+
+ @Override
+ public String getName() {
+ return this.name;
+ }
+
+ @Override
+ public String getSurname() {
+ return this.surname;
+ }
+
+ @Override
+ public String getUsername() {
+ return this.username;
+ }
+
+ @Override
+ public String getEmail() {
+ return this.email;
+ }
+
+ @Override
+ public Locale getLanguage() {
+ return this.language;
+ }
+
+ @Override
+ public DateTimeZone getTimeZone() {
+ return this.timeZone;
+ }
+
+ @Override
+ public Set getRoles() {
+ return this.roles;
+ }
+
+ @Override
+ @JsonIgnore
+ public EnumSet getUserRoles() {
+ final List roles = getRoles()
+ .stream()
+ .map(r -> UserRole.valueOf(r))
+ .collect(Collectors.toList());
+ if (roles.isEmpty()) {
+ return EnumSet.noneOf(UserRole.class);
+ }
+ return EnumSet.copyOf(roles);
+ }
+
+ public CharSequence getRetypedNewPassword() {
+ return this.confirmNewPassword;
+ }
+
+ public boolean passwordChangeRequest() {
+ return this.newPassword != null;
+ }
+
+ public boolean newPasswordMatch() {
+ return passwordChangeRequest() && this.newPassword.equals(this.confirmNewPassword);
+ }
+
+ @Override
+ public Boolean getActive() {
+ return false;
+ }
+
+ @Override
+ public boolean isActive() {
+ return false;
+ }
+
+ @JsonIgnore
+ @Override
+ public EntityKey getEntityKey() {
+ if (StringUtils.isBlank(this.uuid)) {
+ return null;
+ }
+ return new EntityKey(this.uuid, entityType());
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append("UserMod [uuid=");
+ builder.append(this.uuid);
+ builder.append(", institutionId=");
+ builder.append(this.institutionId);
+ builder.append(", name=");
+ builder.append(this.name);
+ builder.append(", surname=");
+ builder.append(this.surname);
+ builder.append(", username=");
+ builder.append(this.username);
+ builder.append(", email=");
+ builder.append(this.email);
+ builder.append(", language=");
+ builder.append(this.language);
+ builder.append(", timeZone=");
+ builder.append(this.timeZone);
+ builder.append(", roles=");
+ builder.append(this.roles);
+ builder.append(", newPassword=");
+ builder.append(this.newPassword);
+ builder.append(", confirmNewPassword=");
+ builder.append(this.confirmNewPassword);
+ builder.append("]");
+ return builder.toString();
+ }
+
+ public static UserMod createNew(final Long institutionId) {
+ return new UserMod(
+ UUID.randomUUID().toString(),
+ institutionId,
+ null, null, null, null, null, null, null, null, null);
+ }
+
+}
diff --git a/src/main/java/ch/ethz/seb/sebserver/gbl/util/Tuple.java b/src/main/java/ch/ethz/seb/sebserver/gbl/util/Tuple.java
index 61dab764..7f2e67d5 100644
--- a/src/main/java/ch/ethz/seb/sebserver/gbl/util/Tuple.java
+++ b/src/main/java/ch/ethz/seb/sebserver/gbl/util/Tuple.java
@@ -1,70 +1,79 @@
-/*
- * Copyright (c) 2018 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.gbl.util;
-
-/** A tuple of two elements of the same type */
-public class Tuple {
-
- /** The first element of the tuple */
- public final T _1;
- /** The second element of the tuple */
- public final T _2;
-
- public Tuple(final T _1, final T _2) {
- super();
- this._1 = _1;
- this._2 = _2;
- }
-
- public T get_1() {
- return this._1;
- }
-
- public T get_2() {
- return this._2;
- }
-
- @Override
- public int hashCode() {
- final int prime = 31;
- int result = 1;
- result = prime * result + ((this._1 == null) ? 0 : this._1.hashCode());
- result = prime * result + ((this._2 == null) ? 0 : this._2.hashCode());
- return result;
- }
-
- @Override
- public boolean equals(final Object obj) {
- if (this == obj)
- return true;
- if (obj == null)
- return false;
- if (getClass() != obj.getClass())
- return false;
- @SuppressWarnings("rawtypes")
- final Tuple other = (Tuple) obj;
- if (this._1 == null) {
- if (other._1 != null)
- return false;
- } else if (!this._1.equals(other._1))
- return false;
- if (this._2 == null) {
- if (other._2 != null)
- return false;
- } else if (!this._2.equals(other._2))
- return false;
- return true;
- }
-
- @Override
- public String toString() {
- return "( " + this._1 + ", " + this._2 + ")";
- }
-
-}
+/*
+ * Copyright (c) 2018 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.gbl.util;
+
+/** A tuple of two elements of the same type */
+public class Tuple {
+
+ /** The first element of the tuple */
+ public final T _1;
+ /** The second element of the tuple */
+ public final T _2;
+
+ public Tuple(final T _1, final T _2) {
+ super();
+ this._1 = _1;
+ this._2 = _2;
+ }
+
+ public T get_1() {
+ return this._1;
+ }
+
+ public T get_2() {
+ return this._2;
+ }
+
+ @SuppressWarnings("unchecked")
+ public > TT adaptTo(Class type) {
+ if (type.equals(this.getClass())) {
+ return (TT) this;
+ }
+
+ return null;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((this._1 == null) ? 0 : this._1.hashCode());
+ result = prime * result + ((this._2 == null) ? 0 : this._2.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ @SuppressWarnings("rawtypes")
+ final Tuple other = (Tuple) obj;
+ if (this._1 == null) {
+ if (other._1 != null)
+ return false;
+ } else if (!this._1.equals(other._1))
+ return false;
+ if (this._2 == null) {
+ if (other._2 != null)
+ return false;
+ } else if (!this._2.equals(other._2))
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ return "( " + this._1 + ", " + this._2 + ")";
+ }
+
+}
diff --git a/src/main/java/ch/ethz/seb/sebserver/gbl/util/Tuple3.java b/src/main/java/ch/ethz/seb/sebserver/gbl/util/Tuple3.java
new file mode 100644
index 00000000..f244cec2
--- /dev/null
+++ b/src/main/java/ch/ethz/seb/sebserver/gbl/util/Tuple3.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2020 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.gbl.util;
+
+import java.util.Objects;
+
+/** A tuple of three elements of the same type */
+public class Tuple3 extends Tuple {
+
+ /** The third element of the tuple */
+ public final T _3;
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ if (!super.equals(o)) return false;
+ Tuple3> tuple3 = (Tuple3>) o;
+ return Objects.equals(_3, tuple3._3);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(super.hashCode(), _3);
+ }
+
+ public Tuple3(T _1, T _2, T _3) {
+ super(_1, _2);
+ this._3 = _3;
+ }
+
+ public T get_3() {
+ return _3;
+ }
+}
diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/content/ConfigTemplateAttributeForm.java b/src/main/java/ch/ethz/seb/sebserver/gui/content/ConfigTemplateAttributeForm.java
index 09ac97fd..b92eeb3e 100644
--- a/src/main/java/ch/ethz/seb/sebserver/gui/content/ConfigTemplateAttributeForm.java
+++ b/src/main/java/ch/ethz/seb/sebserver/gui/content/ConfigTemplateAttributeForm.java
@@ -1,253 +1,257 @@
-/*
- * 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.content;
-
-import java.util.Arrays;
-
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.layout.GridData;
-import org.eclipse.swt.layout.GridLayout;
-import org.eclipse.swt.widgets.Composite;
-import org.springframework.context.annotation.Lazy;
-import org.springframework.stereotype.Component;
-
-import ch.ethz.seb.sebserver.gbl.Constants;
-import ch.ethz.seb.sebserver.gbl.api.API;
-import ch.ethz.seb.sebserver.gbl.api.EntityType;
-import ch.ethz.seb.sebserver.gbl.model.Domain;
-import ch.ethz.seb.sebserver.gbl.model.EntityKey;
-import ch.ethz.seb.sebserver.gbl.model.sebconfig.Configuration;
-import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode;
-import ch.ethz.seb.sebserver.gbl.model.sebconfig.Orientation;
-import ch.ethz.seb.sebserver.gbl.model.sebconfig.TemplateAttribute;
-import ch.ethz.seb.sebserver.gbl.model.sebconfig.TitleOrientation;
-import ch.ethz.seb.sebserver.gbl.model.sebconfig.View;
-import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
-import ch.ethz.seb.sebserver.gbl.util.Utils;
-import ch.ethz.seb.sebserver.gui.content.action.ActionDefinition;
-import ch.ethz.seb.sebserver.gui.form.FormBuilder;
-import ch.ethz.seb.sebserver.gui.service.ResourceService;
-import ch.ethz.seb.sebserver.gui.service.examconfig.ExamConfigurationService;
-import ch.ethz.seb.sebserver.gui.service.examconfig.InputField;
-import ch.ethz.seb.sebserver.gui.service.examconfig.InputFieldBuilder;
-import ch.ethz.seb.sebserver.gui.service.examconfig.impl.AttributeMapping;
-import ch.ethz.seb.sebserver.gui.service.examconfig.impl.ViewContext;
-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.PageService;
-import ch.ethz.seb.sebserver.gui.service.page.TemplateComposer;
-import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestService;
-import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.GetConfigurations;
-import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.GetExamConfigNode;
-import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.GetTemplateAttribute;
-import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.CurrentUser;
-import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.CurrentUser.EntityGrantCheck;
-import ch.ethz.seb.sebserver.gui.widget.WidgetFactory;
-import ch.ethz.seb.sebserver.gui.widget.WidgetFactory.CustomVariant;
-
-@Lazy
-@Component
-@GuiProfile
-public class ConfigTemplateAttributeForm implements TemplateComposer {
-
- private static final LocTextKey FORM_TITLE =
- new LocTextKey("sebserver.configtemplate.attr.form.title");
- private static final LocTextKey FORM_NAME_TEXT_KEY =
- new LocTextKey("sebserver.configtemplate.attr.form.name");
- private static final LocTextKey FORM_TYPE_TEXT_KEY =
- new LocTextKey("sebserver.configtemplate.attr.form.type");
- private static final LocTextKey FORM_VIEW_TEXT_KEY =
- new LocTextKey("sebserver.configtemplate.attr.form.view");
- private static final LocTextKey FORM_GROUP_TEXT_KEY =
- new LocTextKey("sebserver.configtemplate.attr.form.group");
- private static final LocTextKey FORM_VALUE_TEXT_KEY =
- new LocTextKey("sebserver.configtemplate.attr.form.value");
-
- private final PageService pageService;
- private final RestService restService;
- private final CurrentUser currentUser;
- private final ResourceService resourceService;
- private final ExamConfigurationService examConfigurationService;
-
- protected ConfigTemplateAttributeForm(
- final PageService pageService,
- final RestService restService,
- final CurrentUser currentUser,
- final ExamConfigurationService examConfigurationService) {
-
- this.pageService = pageService;
- this.restService = restService;
- this.currentUser = currentUser;
- this.resourceService = pageService.getResourceService();
- this.examConfigurationService = examConfigurationService;
-
- }
-
- @Override
- public void compose(final PageContext pageContext) {
- final WidgetFactory widgetFactory = this.pageService.getWidgetFactory();
-
- final EntityKey attributeKey = pageContext.getEntityKey();
- final EntityKey templateKey = pageContext.getParentEntityKey();
- final Long templateId = Long.valueOf(templateKey.modelId);
-
- try {
-
- final ConfigurationNode template = this.restService
- .getBuilder(GetExamConfigNode.class)
- .withURIVariable(API.PARAM_MODEL_ID, templateKey.modelId)
- .call()
- .onError(error -> pageContext.notifyLoadError(EntityType.CONFIGURATION_NODE, error))
- .getOrThrow();
-
- final EntityGrantCheck entityGrant = this.currentUser.entityGrantCheck(template);
- final boolean modifyGrant = entityGrant.m();
-
- // the attribute
- final TemplateAttribute attribute = this.restService.getBuilder(GetTemplateAttribute.class)
- .withURIVariable(API.PARAM_PARENT_MODEL_ID, templateKey.modelId)
- .withURIVariable(API.PARAM_MODEL_ID, attributeKey.modelId)
- .call()
- .onError(error -> pageContext.notifyLoadError(EntityType.CONFIGURATION_NODE, error))
- .getOrThrow();
-
- // the follow-up configuration
- final Configuration configuration = this.restService.getBuilder(GetConfigurations.class)
- .withQueryParam(Configuration.FILTER_ATTR_CONFIGURATION_NODE_ID, templateKey.getModelId())
- .withQueryParam(Configuration.FILTER_ATTR_FOLLOWUP, Constants.TRUE_STRING)
- .call()
- .map(Utils::toSingleton)
- .onError(error -> pageContext.notifyLoadError(EntityType.CONFIGURATION, error))
- .getOrThrow();
-
- // the default page layout with title
- final Composite content = widgetFactory.defaultPageLayout(
- pageContext.getParent(),
- FORM_TITLE);
-
- final PageContext formContext = pageContext.copyOf(content);
-
- final boolean hasView = attribute.getOrientation() != null;
-
- this.pageService.formBuilder(formContext)
- .readonly(true) // TODO change this for next version
- .addField(FormBuilder.text(
- Domain.CONFIGURATION_ATTRIBUTE.ATTR_NAME,
- FORM_NAME_TEXT_KEY,
- attribute::getName))
- .addField(FormBuilder.text(
- Domain.CONFIGURATION_ATTRIBUTE.ATTR_TYPE,
- FORM_TYPE_TEXT_KEY,
- () -> this.resourceService.getAttributeTypeName(attribute)))
- .addFieldIf(
- () -> hasView,
- () -> FormBuilder.singleSelection(
- Domain.ORIENTATION.ATTR_VIEW_ID,
- FORM_VIEW_TEXT_KEY,
- attribute.getViewModelId(),
- () -> this.resourceService.getViewResources(templateKey.modelId)))
- .addFieldIf(
- () -> hasView,
- () -> FormBuilder.text(
- Domain.ORIENTATION.ATTR_GROUP_ID,
- FORM_GROUP_TEXT_KEY,
- attribute.getGroupId()))
- .build();
-
- final Composite valSpace = new Composite(content, SWT.NONE);
- valSpace.setLayout(new GridLayout());
- valSpace.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
-
- widgetFactory.labelLocalized(
- valSpace,
- CustomVariant.TEXT_H2,
- FORM_VALUE_TEXT_KEY);
-
- widgetFactory.labelSeparator(valSpace);
-
- final Composite grid = new Composite(valSpace, SWT.NONE);
- grid.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
- grid.setLayout(new GridLayout(6, true));
-
- final PageContext valueContext = formContext.copyOf(grid);
-
- final Orientation defaultOrientation = getDefaultOrientation(attribute);
- final AttributeMapping attributeMapping = this.examConfigurationService
- .getAttributes(attribute, defaultOrientation)
- .getOrThrow();
- final ViewContext viewContext = this.examConfigurationService.createViewContext(
- valueContext,
- configuration,
- new View(-1L, "template", 10, 0, templateId),
- attributeMapping,
- 1, false);
-
- final InputFieldBuilder inputFieldBuilder = this.examConfigurationService.getInputFieldBuilder(
- attribute.getConfigAttribute(),
- defaultOrientation);
-
- final InputField createInputField = inputFieldBuilder.createInputField(
- grid,
- attribute.getConfigAttribute(),
- viewContext);
-
- viewContext.registerInputField(createInputField);
-
- this.examConfigurationService.initInputFieldValues(
- configuration.id,
- Arrays.asList(viewContext));
-
- this.pageService.pageActionBuilder(formContext.clearEntityKeys())
-
- .newAction(ActionDefinition.SEB_EXAM_CONFIG_TEMPLATE_ATTR_FORM_SET_DEFAULT)
- .withEntityKey(attributeKey)
- .withParentEntityKey(templateKey)
- .withExec(this.examConfigurationService::resetToDefaults)
- .ignoreMoveAwayFromEdit()
- .publishIf(() -> modifyGrant)
-
- .newAction(ActionDefinition.SEB_EXAM_CONFIG_TEMPLATE_ATTR_REMOVE_VIEW)
- .withEntityKey(attributeKey)
- .withParentEntityKey(templateKey)
- .withExec(this.examConfigurationService::removeFromView)
- .ignoreMoveAwayFromEdit()
- .publishIf(() -> modifyGrant && hasView)
-
- .newAction(ActionDefinition.SEB_EXAM_CONFIG_TEMPLATE_ATTR_ATTACH_DEFAULT_VIEW)
- .withEntityKey(attributeKey)
- .withParentEntityKey(templateKey)
- .withExec(this.examConfigurationService::attachToDefaultView)
- .ignoreMoveAwayFromEdit()
- .publishIf(() -> modifyGrant && !hasView)
-
- .newAction(ActionDefinition.SEB_EXAM_CONFIG_TEMPLATE_ATTR_FORM_EDIT_TEMPLATE)
- .withEntityKey(templateKey)
- .ignoreMoveAwayFromEdit()
- .publish();
-
- } catch (final Exception e) {
- pageContext.notifyUnexpectedError(e);
- }
- }
-
- private Orientation getDefaultOrientation(final TemplateAttribute attribute) {
- return new Orientation(
- -1L,
- attribute.getConfigAttribute().id,
- attribute.templateId,
- null,
- null,
- 0,
- 0,
- 2,
- 1,
- TitleOrientation.NONE);
- }
-
-}
+/*
+ * 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.content;
+
+import java.util.Collections;
+
+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.Composite;
+import org.springframework.context.annotation.Lazy;
+import org.springframework.stereotype.Component;
+
+import ch.ethz.seb.sebserver.gbl.Constants;
+import ch.ethz.seb.sebserver.gbl.api.API;
+import ch.ethz.seb.sebserver.gbl.api.EntityType;
+import ch.ethz.seb.sebserver.gbl.model.Domain;
+import ch.ethz.seb.sebserver.gbl.model.EntityKey;
+import ch.ethz.seb.sebserver.gbl.model.sebconfig.Configuration;
+import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode;
+import ch.ethz.seb.sebserver.gbl.model.sebconfig.Orientation;
+import ch.ethz.seb.sebserver.gbl.model.sebconfig.TemplateAttribute;
+import ch.ethz.seb.sebserver.gbl.model.sebconfig.TitleOrientation;
+import ch.ethz.seb.sebserver.gbl.model.sebconfig.View;
+import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
+import ch.ethz.seb.sebserver.gbl.util.Utils;
+import ch.ethz.seb.sebserver.gui.content.action.ActionDefinition;
+import ch.ethz.seb.sebserver.gui.form.FormBuilder;
+import ch.ethz.seb.sebserver.gui.service.ResourceService;
+import ch.ethz.seb.sebserver.gui.service.examconfig.ExamConfigurationService;
+import ch.ethz.seb.sebserver.gui.service.examconfig.InputField;
+import ch.ethz.seb.sebserver.gui.service.examconfig.InputFieldBuilder;
+import ch.ethz.seb.sebserver.gui.service.examconfig.impl.AttributeMapping;
+import ch.ethz.seb.sebserver.gui.service.examconfig.impl.ViewContext;
+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.PageService;
+import ch.ethz.seb.sebserver.gui.service.page.TemplateComposer;
+import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestService;
+import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.GetConfigurations;
+import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.GetExamConfigNode;
+import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.GetTemplateAttribute;
+import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.CurrentUser;
+import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.CurrentUser.EntityGrantCheck;
+import ch.ethz.seb.sebserver.gui.widget.WidgetFactory;
+import ch.ethz.seb.sebserver.gui.widget.WidgetFactory.CustomVariant;
+
+@Lazy
+@Component
+@GuiProfile
+public class ConfigTemplateAttributeForm implements TemplateComposer {
+
+ private static final LocTextKey FORM_TITLE =
+ new LocTextKey("sebserver.configtemplate.attr.form.title");
+ private static final LocTextKey FORM_NAME_TEXT_KEY =
+ new LocTextKey("sebserver.configtemplate.attr.form.name");
+ private static final LocTextKey FORM_TYPE_TEXT_KEY =
+ new LocTextKey("sebserver.configtemplate.attr.form.type");
+ private static final LocTextKey FORM_VIEW_TEXT_KEY =
+ new LocTextKey("sebserver.configtemplate.attr.form.view");
+ private static final LocTextKey FORM_GROUP_TEXT_KEY =
+ new LocTextKey("sebserver.configtemplate.attr.form.group");
+ private static final LocTextKey FORM_VALUE_TEXT_KEY =
+ new LocTextKey("sebserver.configtemplate.attr.form.value");
+ private static final LocTextKey FORM_VALUE_TOOLTIP_TEXT_KEY =
+ new LocTextKey("sebserver.configtemplate.attr.form.value" + Constants.TOOLTIP_TEXT_KEY_SUFFIX);
+
+ private final PageService pageService;
+ private final RestService restService;
+ private final CurrentUser currentUser;
+ private final ResourceService resourceService;
+ private final ExamConfigurationService examConfigurationService;
+
+ protected ConfigTemplateAttributeForm(
+ final PageService pageService,
+ final RestService restService,
+ final CurrentUser currentUser,
+ final ExamConfigurationService examConfigurationService) {
+
+ this.pageService = pageService;
+ this.restService = restService;
+ this.currentUser = currentUser;
+ this.resourceService = pageService.getResourceService();
+ this.examConfigurationService = examConfigurationService;
+
+ }
+
+ @Override
+ public void compose(final PageContext pageContext) {
+ final WidgetFactory widgetFactory = this.pageService.getWidgetFactory();
+
+ final EntityKey attributeKey = pageContext.getEntityKey();
+ final EntityKey templateKey = pageContext.getParentEntityKey();
+ final Long templateId = Long.valueOf(templateKey.modelId);
+
+ try {
+
+ final ConfigurationNode template = this.restService
+ .getBuilder(GetExamConfigNode.class)
+ .withURIVariable(API.PARAM_MODEL_ID, templateKey.modelId)
+ .call()
+ .onError(error -> pageContext.notifyLoadError(EntityType.CONFIGURATION_NODE, error))
+ .getOrThrow();
+
+ final EntityGrantCheck entityGrant = this.currentUser.entityGrantCheck(template);
+ final boolean modifyGrant = entityGrant.m();
+
+ // the attribute
+ final TemplateAttribute attribute = this.restService.getBuilder(GetTemplateAttribute.class)
+ .withURIVariable(API.PARAM_PARENT_MODEL_ID, templateKey.modelId)
+ .withURIVariable(API.PARAM_MODEL_ID, attributeKey.modelId)
+ .call()
+ .onError(error -> pageContext.notifyLoadError(EntityType.CONFIGURATION_NODE, error))
+ .getOrThrow();
+
+ // the follow-up configuration
+ final Configuration configuration = this.restService.getBuilder(GetConfigurations.class)
+ .withQueryParam(Configuration.FILTER_ATTR_CONFIGURATION_NODE_ID, templateKey.getModelId())
+ .withQueryParam(Configuration.FILTER_ATTR_FOLLOWUP, Constants.TRUE_STRING)
+ .call()
+ .map(Utils::toSingleton)
+ .onError(error -> pageContext.notifyLoadError(EntityType.CONFIGURATION, error))
+ .getOrThrow();
+
+ // the default page layout with title
+ final Composite content = widgetFactory.defaultPageLayout(
+ pageContext.getParent(),
+ FORM_TITLE);
+
+ final PageContext formContext = pageContext.copyOf(content);
+
+ final boolean hasView = attribute.getOrientation() != null;
+
+ this.pageService.formBuilder(formContext)
+ .readonly(true) // TODO change this for next version
+ .addField(FormBuilder.text(
+ Domain.CONFIGURATION_ATTRIBUTE.ATTR_NAME,
+ FORM_NAME_TEXT_KEY,
+ attribute::getName))
+ .addField(FormBuilder.text(
+ Domain.CONFIGURATION_ATTRIBUTE.ATTR_TYPE,
+ FORM_TYPE_TEXT_KEY,
+ () -> this.resourceService.getAttributeTypeName(attribute)))
+ .addFieldIf(
+ () -> hasView,
+ () -> FormBuilder.singleSelection(
+ Domain.ORIENTATION.ATTR_VIEW_ID,
+ FORM_VIEW_TEXT_KEY,
+ attribute.getViewModelId(),
+ () -> this.resourceService.getViewResources(templateKey.modelId)))
+ .addFieldIf(
+ () -> hasView,
+ () -> FormBuilder.text(
+ Domain.ORIENTATION.ATTR_GROUP_ID,
+ FORM_GROUP_TEXT_KEY,
+ attribute.getGroupId()))
+ .build();
+
+ final Composite valSpace = new Composite(content, SWT.NONE);
+ valSpace.setLayout(new GridLayout());
+ valSpace.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
+
+ widgetFactory.label(content, StringUtils.EMPTY);
+ widgetFactory.labelLocalized(
+ valSpace,
+ CustomVariant.TEXT_H3,
+ FORM_VALUE_TEXT_KEY,
+ FORM_VALUE_TOOLTIP_TEXT_KEY);
+ widgetFactory.labelSeparator(valSpace);
+
+ final Composite grid = new Composite(valSpace, SWT.NONE);
+ grid.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
+ grid.setLayout(new GridLayout(6, true));
+
+ final PageContext valueContext = formContext.copyOf(grid);
+
+ final Orientation defaultOrientation = getDefaultOrientation(attribute);
+ final AttributeMapping attributeMapping = this.examConfigurationService
+ .getAttributes(attribute, defaultOrientation)
+ .getOrThrow();
+ final ViewContext viewContext = this.examConfigurationService.createViewContext(
+ valueContext,
+ configuration,
+ new View(-1L, "template", 10, 0, templateId),
+ attributeMapping,
+ 1, false);
+
+ final InputFieldBuilder inputFieldBuilder = this.examConfigurationService.getInputFieldBuilder(
+ attribute.getConfigAttribute(),
+ defaultOrientation);
+
+ final InputField createInputField = inputFieldBuilder.createInputField(
+ grid,
+ attribute.getConfigAttribute(),
+ viewContext);
+
+ viewContext.registerInputField(createInputField);
+
+ this.examConfigurationService.initInputFieldValues(
+ configuration.id,
+ Collections.singletonList(viewContext));
+
+ this.pageService.pageActionBuilder(formContext.clearEntityKeys())
+
+ .newAction(ActionDefinition.SEB_EXAM_CONFIG_TEMPLATE_ATTR_FORM_SET_DEFAULT)
+ .withEntityKey(attributeKey)
+ .withParentEntityKey(templateKey)
+ .withExec(this.examConfigurationService::resetToDefaults)
+ .ignoreMoveAwayFromEdit()
+ .publishIf(() -> modifyGrant)
+
+ .newAction(ActionDefinition.SEB_EXAM_CONFIG_TEMPLATE_ATTR_REMOVE_VIEW)
+ .withEntityKey(attributeKey)
+ .withParentEntityKey(templateKey)
+ .withExec(this.examConfigurationService::removeFromView)
+ .ignoreMoveAwayFromEdit()
+ .publishIf(() -> modifyGrant && hasView)
+
+ .newAction(ActionDefinition.SEB_EXAM_CONFIG_TEMPLATE_ATTR_ATTACH_DEFAULT_VIEW)
+ .withEntityKey(attributeKey)
+ .withParentEntityKey(templateKey)
+ .withExec(this.examConfigurationService::attachToDefaultView)
+ .ignoreMoveAwayFromEdit()
+ .publishIf(() -> modifyGrant && !hasView)
+
+ .newAction(ActionDefinition.SEB_EXAM_CONFIG_TEMPLATE_ATTR_FORM_EDIT_TEMPLATE)
+ .withEntityKey(templateKey)
+ .ignoreMoveAwayFromEdit()
+ .publish();
+
+ } catch (final Exception e) {
+ pageContext.notifyUnexpectedError(e);
+ }
+ }
+
+ private Orientation getDefaultOrientation(final TemplateAttribute attribute) {
+ return new Orientation(
+ -1L,
+ attribute.getConfigAttribute().id,
+ attribute.templateId,
+ null,
+ null,
+ 0,
+ 0,
+ 2,
+ 1,
+ TitleOrientation.NONE);
+ }
+
+}
diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/content/ConfigTemplateForm.java b/src/main/java/ch/ethz/seb/sebserver/gui/content/ConfigTemplateForm.java
index 4d0535ec..39ca82f6 100644
--- a/src/main/java/ch/ethz/seb/sebserver/gui/content/ConfigTemplateForm.java
+++ b/src/main/java/ch/ethz/seb/sebserver/gui/content/ConfigTemplateForm.java
@@ -1,348 +1,362 @@
-/*
- * 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.content;
-
-import org.apache.commons.lang3.StringUtils;
-import org.eclipse.swt.widgets.Composite;
-import org.springframework.context.annotation.Lazy;
-import org.springframework.stereotype.Component;
-
-import ch.ethz.seb.sebserver.gbl.Constants;
-import ch.ethz.seb.sebserver.gbl.api.API;
-import ch.ethz.seb.sebserver.gbl.api.EntityType;
-import ch.ethz.seb.sebserver.gbl.model.Domain;
-import ch.ethz.seb.sebserver.gbl.model.EntityKey;
-import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode;
-import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode.ConfigurationStatus;
-import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode.ConfigurationType;
-import ch.ethz.seb.sebserver.gbl.model.sebconfig.TemplateAttribute;
-import ch.ethz.seb.sebserver.gbl.model.user.UserInfo;
-import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
-import ch.ethz.seb.sebserver.gui.content.action.ActionDefinition;
-import ch.ethz.seb.sebserver.gui.form.FormBuilder;
-import ch.ethz.seb.sebserver.gui.form.FormHandle;
-import ch.ethz.seb.sebserver.gui.service.ResourceService;
-import ch.ethz.seb.sebserver.gui.service.examconfig.ExamConfigurationService;
-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.PageContext;
-import ch.ethz.seb.sebserver.gui.service.page.PageService;
-import ch.ethz.seb.sebserver.gui.service.page.PageService.PageActionBuilder;
-import ch.ethz.seb.sebserver.gui.service.page.TemplateComposer;
-import ch.ethz.seb.sebserver.gui.service.page.impl.PageAction;
-import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestService;
-import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.GetExamConfigNode;
-import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.GetTemplateAttributePage;
-import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.NewExamConfig;
-import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.SaveExamConfig;
-import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.CurrentUser;
-import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.CurrentUser.EntityGrantCheck;
-import ch.ethz.seb.sebserver.gui.table.ColumnDefinition;
-import ch.ethz.seb.sebserver.gui.table.ColumnDefinition.TableFilterAttribute;
-import ch.ethz.seb.sebserver.gui.table.EntityTable;
-import ch.ethz.seb.sebserver.gui.table.TableFilter.CriteriaType;
-import ch.ethz.seb.sebserver.gui.widget.WidgetFactory;
-
-@Lazy
-@Component
-@GuiProfile
-public class ConfigTemplateForm implements TemplateComposer {
-
- private static final LocTextKey FORM_TITLE_NEW =
- new LocTextKey("sebserver.configtemplate.form.title.new");
- private static final LocTextKey FORM_TITLE =
- new LocTextKey("sebserver.configtemplate.form.title");
- private static final LocTextKey FORM_NAME_TEXT_KEY =
- new LocTextKey("sebserver.configtemplate.form.name");
- private static final LocTextKey FORM_DESCRIPTION_TEXT_KEY =
- new LocTextKey("sebserver.configtemplate.form.description");
- private static final LocTextKey ATTRIBUTES_LIST_TITLE_TEXT_KEY =
- new LocTextKey("sebserver.configtemplate.attrs.list.title");
- private static final LocTextKey ATTRIBUTES_LIST_NAME_TEXT_KEY =
- new LocTextKey("sebserver.configtemplate.attrs.list.name");
- private static final LocTextKey ATTRIBUTES_LIST_VIEW_TEXT_KEY =
- new LocTextKey("sebserver.configtemplate.attrs.list.view");
- private static final LocTextKey ATTRIBUTES_LIST_GROUP_TEXT_KEY =
- new LocTextKey("sebserver.configtemplate.attrs.list.group");
- private static final LocTextKey ATTRIBUTES_LIST_TYPE_TEXT_KEY =
- new LocTextKey("sebserver.configtemplate.attrs.list.type");
- private static final LocTextKey EMPTY_ATTRIBUTE_SELECTION_TEXT_KEY =
- new LocTextKey("sebserver.configtemplate.attr.info.pleaseSelect");
-
- private final PageService pageService;
- private final RestService restService;
- private final CurrentUser currentUser;
- private final I18nSupport i18nSupport;
- private final ResourceService resourceService;
- private final ExamConfigurationService examConfigurationService;
-
- private final TableFilterAttribute nameFilter =
- new TableFilterAttribute(CriteriaType.TEXT, TemplateAttribute.FILTER_ATTR_NAME);
- private final TableFilterAttribute groupFilter =
- new TableFilterAttribute(CriteriaType.TEXT, TemplateAttribute.FILTER_ATTR_GROUP);
-
- protected ConfigTemplateForm(
- final PageService pageService,
- final RestService restService,
- final CurrentUser currentUser,
- final ExamConfigurationService examConfigurationService) {
-
- this.pageService = pageService;
- this.restService = restService;
- this.currentUser = currentUser;
- this.i18nSupport = pageService.getI18nSupport();
- this.resourceService = pageService.getResourceService();
- this.examConfigurationService = examConfigurationService;
-
- }
-
- @Override
- public void compose(final PageContext pageContext) {
-
- final WidgetFactory widgetFactory = this.pageService.getWidgetFactory();
- final ResourceService resourceService = this.pageService.getResourceService();
-
- final UserInfo user = this.currentUser.get();
- final EntityKey entityKey = pageContext.getEntityKey();
- final boolean isNew = entityKey == null;
-
- // get data or create new. Handle error if happen
- final ConfigurationNode examConfig = (isNew)
- ? ConfigurationNode.createNewTemplate(user.institutionId)
- : this.restService
- .getBuilder(GetExamConfigNode.class)
- .withURIVariable(API.PARAM_MODEL_ID, entityKey.modelId)
- .call()
- .onError(error -> pageContext.notifyLoadError(EntityType.CONFIGURATION_NODE, error))
- .getOrThrow();
-
- final EntityGrantCheck entityGrant = this.currentUser.entityGrantCheck(examConfig);
- final boolean writeGrant = entityGrant.w();
- final boolean modifyGrant = entityGrant.m();
- final boolean isReadonly = pageContext.isReadonly();
-
- // new PageContext with actual EntityKey
- final PageContext formContext = pageContext
- .withEntityKey(examConfig.getEntityKey());
-
- // the default page layout with interactive title
- final LocTextKey titleKey = (isNew)
- ? FORM_TITLE_NEW
- : FORM_TITLE;
- final Composite content = widgetFactory.defaultPageLayout(
- formContext.getParent(),
- titleKey);
-
- // The SebClientConfig form
- final FormHandle formHandle = this.pageService.formBuilder(
- formContext.copyOf(content))
- .readonly(isReadonly)
- .putStaticValueIf(() -> !isNew,
- Domain.CONFIGURATION_NODE.ATTR_ID,
- examConfig.getModelId())
- .putStaticValue(
- Domain.CONFIGURATION_NODE.ATTR_INSTITUTION_ID,
- String.valueOf(examConfig.getInstitutionId()))
- .putStaticValue(
- Domain.CONFIGURATION_NODE.ATTR_TYPE,
- ConfigurationType.TEMPLATE.name())
- .putStaticValue(
- Domain.CONFIGURATION_NODE.ATTR_STATUS,
- ConfigurationStatus.IN_USE.name())
- .addField(FormBuilder.text(
- Domain.CONFIGURATION_NODE.ATTR_NAME,
- FORM_NAME_TEXT_KEY,
- examConfig.name))
- .addField(FormBuilder.text(
- Domain.CONFIGURATION_NODE.ATTR_DESCRIPTION,
- FORM_DESCRIPTION_TEXT_KEY,
- examConfig.description)
- .asArea())
-
- .buildFor((isNew)
- ? this.restService.getRestCall(NewExamConfig.class)
- : this.restService.getRestCall(SaveExamConfig.class));
-
- final PageActionBuilder pageActionBuilder = this.pageService
- .pageActionBuilder(formContext.clearEntityKeys());
-
- if (isReadonly) {
-
- widgetFactory.label(content, "");
- widgetFactory.labelLocalizedTitle(
- content,
- ATTRIBUTES_LIST_TITLE_TEXT_KEY);
-
- final TableFilterAttribute viewFilter = new TableFilterAttribute(
- CriteriaType.SINGLE_SELECTION,
- TemplateAttribute.FILTER_ATTR_VIEW,
- () -> this.resourceService.getViewResources(entityKey.modelId));
- final TableFilterAttribute typeFilter = new TableFilterAttribute(
- CriteriaType.SINGLE_SELECTION,
- TemplateAttribute.FILTER_ATTR_TYPE,
- () -> this.resourceService.getAttributeTypeResources());
-
- final EntityTable attrTable =
- this.pageService.entityTableBuilder(
- Domain.CONFIGURATION_NODE.TYPE_NAME + "_Template",
- this.restService.getRestCall(GetTemplateAttributePage.class))
- .withRestCallAdapter(restCall -> restCall.withURIVariable(
- API.PARAM_PARENT_MODEL_ID,
- entityKey.modelId))
- .withPaging(15)
- .withColumn(new ColumnDefinition<>(
- Domain.CONFIGURATION_ATTRIBUTE.ATTR_NAME,
- ATTRIBUTES_LIST_NAME_TEXT_KEY,
- this::getAttributeName)
- .withFilter(this.nameFilter)
- .sortable()
- .widthProportion(3))
- .withColumn(new ColumnDefinition(
- Domain.CONFIGURATION_ATTRIBUTE.ATTR_TYPE,
- ATTRIBUTES_LIST_TYPE_TEXT_KEY,
- resourceService::getAttributeTypeName)
- .withFilter(typeFilter)
- .sortable()
- .widthProportion(1))
- .withColumn(new ColumnDefinition<>(
- Domain.ORIENTATION.ATTR_VIEW_ID,
- ATTRIBUTES_LIST_VIEW_TEXT_KEY,
- resourceService.getViewNameFunction(entityKey.modelId))
- .withFilter(viewFilter)
- .sortable()
- .widthProportion(1))
- .withColumn(new ColumnDefinition<>(
- Domain.ORIENTATION.ATTR_GROUP_ID,
- ATTRIBUTES_LIST_GROUP_TEXT_KEY,
- TemplateAttribute::getGroupId)
- .withFilter(this.groupFilter)
- .sortable()
- .widthProportion(1))
- .withDefaultAction(pageActionBuilder
- .newAction(ActionDefinition.SEB_EXAM_CONFIG_TEMPLATE_ATTR_EDIT)
- .withParentEntityKey(entityKey)
- .create())
- .compose(pageContext.copyOf(content));
-
- pageActionBuilder
-
- .newAction(ActionDefinition.SEB_EXAM_CONFIG_TEMPLATE_ATTR_EDIT)
- .withParentEntityKey(entityKey)
- .withSelect(
- attrTable::getSelection,
- PageAction::applySingleSelectionAsEntityKey,
- EMPTY_ATTRIBUTE_SELECTION_TEXT_KEY)
- .publishIf(() -> attrTable.hasAnyContent())
-
- .newAction(ActionDefinition.SEB_EXAM_CONFIG_TEMPLATE_ATTR_SET_DEFAULT)
- .withParentEntityKey(entityKey)
- .withSelect(
- attrTable::getSelection,
- action -> this.resetToDefaults(action, attrTable),
- EMPTY_ATTRIBUTE_SELECTION_TEXT_KEY)
- .noEventPropagation()
- .publishIf(() -> attrTable.hasAnyContent())
-
- .newAction(ActionDefinition.SEB_EXAM_CONFIG_TEMPLATE_ATTR_LIST_REMOVE_VIEW)
- .withParentEntityKey(entityKey)
- .withSelect(
- attrTable::getSelection,
- action -> this.removeFormView(action, attrTable),
- EMPTY_ATTRIBUTE_SELECTION_TEXT_KEY)
- .noEventPropagation()
- .publishIf(() -> attrTable.hasAnyContent())
-
- .newAction(ActionDefinition.SEB_EXAM_CONFIG_TEMPLATE_ATTR_LIST_ATTACH_DEFAULT_VIEW)
- .withParentEntityKey(entityKey)
- .withSelect(
- attrTable::getSelection,
- action -> this.attachView(action, attrTable),
- EMPTY_ATTRIBUTE_SELECTION_TEXT_KEY)
- .noEventPropagation()
- .publishIf(() -> attrTable.hasAnyContent());
- }
-
- pageActionBuilder
-
- .newAction(ActionDefinition.SEB_EXAM_CONFIG_TEMPLATE_NEW)
- .publishIf(() -> writeGrant && isReadonly)
-
- .newAction(ActionDefinition.SEB_EXAM_CONFIG_TEMPLATE_MODIFY)
- .withEntityKey(entityKey)
- .publishIf(() -> modifyGrant && isReadonly)
-
- .newAction(ActionDefinition.SEB_EXAM_CONFIG_TEMPLATE_CREATE_CONFIG)
- .withEntityKey(entityKey)
- .withExec(SebExamConfigCreationPopup.configCreationFunction(
- this.pageService,
- pageContext
- .withAttribute(
- PageContext.AttributeKeys.CREATE_FROM_TEMPLATE,
- Constants.TRUE_STRING)
- .withAttribute(
- PageContext.AttributeKeys.COPY_AS_TEMPLATE,
- Constants.FALSE_STRING)))
- .publishIf(() -> modifyGrant && isReadonly)
-
- .newAction(ActionDefinition.SEB_EXAM_CONFIG_TEMPLATE_SAVE)
- .withEntityKey(entityKey)
- .withExec(formHandle::processFormSave)
- .ignoreMoveAwayFromEdit()
- .publishIf(() -> !isReadonly)
-
- .newAction(ActionDefinition.SEB_EXAM_CONFIG_TEMPLATE_CANCEL_MODIFY)
- .withEntityKey(entityKey)
- .withExec(this.pageService.backToCurrentFunction())
- .publishIf(() -> !isReadonly);
-
- }
-
- private String getAttributeName(final TemplateAttribute attribute) {
-
- final String name = this.i18nSupport.getText(
- ExamConfigurationService.ATTRIBUTE_LABEL_LOC_TEXT_PREFIX + attribute.getName(),
- "");
- if (StringUtils.isNotBlank(name)) {
- return attribute.getName() + " (" + name + ")";
- } else {
- return attribute.getName();
- }
- }
-
- private final PageAction resetToDefaults(
- final PageAction action,
- final EntityTable attrTable) {
-
- final PageAction resetToDefaults = this.examConfigurationService.resetToDefaults(action);
- // reload the list
- attrTable.applyFilter();
- return resetToDefaults;
- }
-
- private final PageAction removeFormView(
- final PageAction action,
- final EntityTable attrTable) {
-
- final PageAction removeFormView = this.examConfigurationService.removeFromView(action);
- // reload the list
- attrTable.applyFilter();
- return removeFormView;
- }
-
- private final PageAction attachView(
- final PageAction action,
- final EntityTable attrTable) {
-
- final PageAction attachView = this.examConfigurationService.attachToDefaultView(action);
- // reload the list
- attrTable.applyFilter();
- return attachView;
- }
-
-}
+/*
+ * 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.content;
+
+import org.apache.commons.lang3.StringUtils;
+import org.eclipse.swt.widgets.Composite;
+import org.springframework.context.annotation.Lazy;
+import org.springframework.stereotype.Component;
+
+import ch.ethz.seb.sebserver.gbl.Constants;
+import ch.ethz.seb.sebserver.gbl.api.API;
+import ch.ethz.seb.sebserver.gbl.api.EntityType;
+import ch.ethz.seb.sebserver.gbl.model.Domain;
+import ch.ethz.seb.sebserver.gbl.model.EntityKey;
+import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode;
+import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode.ConfigurationStatus;
+import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode.ConfigurationType;
+import ch.ethz.seb.sebserver.gbl.model.sebconfig.TemplateAttribute;
+import ch.ethz.seb.sebserver.gbl.model.user.UserInfo;
+import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
+import ch.ethz.seb.sebserver.gui.content.action.ActionDefinition;
+import ch.ethz.seb.sebserver.gui.form.FormBuilder;
+import ch.ethz.seb.sebserver.gui.form.FormHandle;
+import ch.ethz.seb.sebserver.gui.service.ResourceService;
+import ch.ethz.seb.sebserver.gui.service.examconfig.ExamConfigurationService;
+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.PageContext;
+import ch.ethz.seb.sebserver.gui.service.page.PageService;
+import ch.ethz.seb.sebserver.gui.service.page.PageService.PageActionBuilder;
+import ch.ethz.seb.sebserver.gui.service.page.TemplateComposer;
+import ch.ethz.seb.sebserver.gui.service.page.impl.PageAction;
+import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestService;
+import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.GetExamConfigNode;
+import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.GetTemplateAttributePage;
+import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.NewExamConfig;
+import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.SaveExamConfig;
+import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.CurrentUser;
+import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.CurrentUser.EntityGrantCheck;
+import ch.ethz.seb.sebserver.gui.table.ColumnDefinition;
+import ch.ethz.seb.sebserver.gui.table.ColumnDefinition.TableFilterAttribute;
+import ch.ethz.seb.sebserver.gui.table.EntityTable;
+import ch.ethz.seb.sebserver.gui.table.TableFilter.CriteriaType;
+import ch.ethz.seb.sebserver.gui.widget.WidgetFactory;
+
+@Lazy
+@Component
+@GuiProfile
+public class ConfigTemplateForm implements TemplateComposer {
+
+ private static final LocTextKey FORM_TITLE_NEW =
+ new LocTextKey("sebserver.configtemplate.form.title.new");
+ private static final LocTextKey FORM_TITLE =
+ new LocTextKey("sebserver.configtemplate.form.title");
+ private static final LocTextKey FORM_NAME_TEXT_KEY =
+ new LocTextKey("sebserver.configtemplate.form.name");
+ private static final LocTextKey FORM_DESCRIPTION_TEXT_KEY =
+ new LocTextKey("sebserver.configtemplate.form.description");
+ private static final LocTextKey ATTRIBUTES_LIST_TITLE_TEXT_KEY =
+ new LocTextKey("sebserver.configtemplate.attrs.list.title");
+ private static final LocTextKey ATTRIBUTES_LIST_TITLE_TOOLTIP_TEXT_KEY =
+ new LocTextKey("sebserver.configtemplate.attrs.list.title" + Constants.TOOLTIP_TEXT_KEY_SUFFIX);
+ private static final LocTextKey ATTRIBUTES_LIST_NAME_TEXT_KEY =
+ new LocTextKey("sebserver.configtemplate.attrs.list.name");
+ private static final LocTextKey ATTRIBUTES_LIST_VIEW_TEXT_KEY =
+ new LocTextKey("sebserver.configtemplate.attrs.list.view");
+ private static final LocTextKey ATTRIBUTES_LIST_GROUP_TEXT_KEY =
+ new LocTextKey("sebserver.configtemplate.attrs.list.group");
+ private static final LocTextKey ATTRIBUTES_LIST_TYPE_TEXT_KEY =
+ new LocTextKey("sebserver.configtemplate.attrs.list.type");
+ private static final LocTextKey EMPTY_ATTRIBUTE_SELECTION_TEXT_KEY =
+ new LocTextKey("sebserver.configtemplate.attr.info.pleaseSelect");
+
+ private final PageService pageService;
+ private final RestService restService;
+ private final CurrentUser currentUser;
+ private final I18nSupport i18nSupport;
+ private final ResourceService resourceService;
+ private final ExamConfigurationService examConfigurationService;
+
+ private final TableFilterAttribute nameFilter =
+ new TableFilterAttribute(CriteriaType.TEXT, TemplateAttribute.FILTER_ATTR_NAME);
+ private final TableFilterAttribute groupFilter =
+ new TableFilterAttribute(CriteriaType.TEXT, TemplateAttribute.FILTER_ATTR_GROUP);
+
+ protected ConfigTemplateForm(
+ final PageService pageService,
+ final RestService restService,
+ final CurrentUser currentUser,
+ final ExamConfigurationService examConfigurationService) {
+
+ this.pageService = pageService;
+ this.restService = restService;
+ this.currentUser = currentUser;
+ this.i18nSupport = pageService.getI18nSupport();
+ this.resourceService = pageService.getResourceService();
+ this.examConfigurationService = examConfigurationService;
+
+ }
+
+ @Override
+ public void compose(final PageContext pageContext) {
+
+ final WidgetFactory widgetFactory = this.pageService.getWidgetFactory();
+ final ResourceService resourceService = this.pageService.getResourceService();
+
+ final UserInfo user = this.currentUser.get();
+ final EntityKey entityKey = pageContext.getEntityKey();
+ final boolean isNew = entityKey == null;
+
+ // get data or create new. Handle error if happen
+ final ConfigurationNode examConfig = (isNew)
+ ? ConfigurationNode.createNewTemplate(user.institutionId)
+ : this.restService
+ .getBuilder(GetExamConfigNode.class)
+ .withURIVariable(API.PARAM_MODEL_ID, entityKey.modelId)
+ .call()
+ .onError(error -> pageContext.notifyLoadError(EntityType.CONFIGURATION_NODE, error))
+ .getOrThrow();
+
+ final EntityGrantCheck entityGrant = this.currentUser.entityGrantCheck(examConfig);
+ final boolean writeGrant = entityGrant.w();
+ final boolean modifyGrant = entityGrant.m();
+ final boolean isReadonly = pageContext.isReadonly();
+
+ // new PageContext with actual EntityKey
+ final PageContext formContext = pageContext
+ .withEntityKey(examConfig.getEntityKey());
+
+ // the default page layout with interactive title
+ final LocTextKey titleKey = (isNew)
+ ? FORM_TITLE_NEW
+ : FORM_TITLE;
+ final Composite content = widgetFactory.defaultPageLayout(
+ formContext.getParent(),
+ titleKey);
+
+ // The SebClientConfig form
+ final FormHandle formHandle = this.pageService.formBuilder(
+ formContext.copyOf(content))
+ .readonly(isReadonly)
+ .putStaticValueIf(() -> !isNew,
+ Domain.CONFIGURATION_NODE.ATTR_ID,
+ examConfig.getModelId())
+ .putStaticValue(
+ Domain.CONFIGURATION_NODE.ATTR_INSTITUTION_ID,
+ String.valueOf(examConfig.getInstitutionId()))
+ .putStaticValue(
+ Domain.CONFIGURATION_NODE.ATTR_TYPE,
+ ConfigurationType.TEMPLATE.name())
+ .putStaticValue(
+ Domain.CONFIGURATION_NODE.ATTR_STATUS,
+ ConfigurationStatus.IN_USE.name())
+ .addField(FormBuilder.text(
+ Domain.CONFIGURATION_NODE.ATTR_NAME,
+ FORM_NAME_TEXT_KEY,
+ examConfig.name)
+ .mandatory(!isReadonly))
+ .addField(FormBuilder.text(
+ Domain.CONFIGURATION_NODE.ATTR_DESCRIPTION,
+ FORM_DESCRIPTION_TEXT_KEY,
+ examConfig.description)
+ .asArea())
+
+ .buildFor((isNew)
+ ? this.restService.getRestCall(NewExamConfig.class)
+ : this.restService.getRestCall(SaveExamConfig.class));
+
+ final PageActionBuilder pageActionBuilder = this.pageService
+ .pageActionBuilder(formContext.clearEntityKeys());
+
+ if (isReadonly) {
+
+ widgetFactory.label(content, StringUtils.EMPTY);
+ widgetFactory.labelLocalized(
+ content,
+ WidgetFactory.CustomVariant.TEXT_H3,
+ ATTRIBUTES_LIST_TITLE_TEXT_KEY,
+ ATTRIBUTES_LIST_TITLE_TOOLTIP_TEXT_KEY);
+ widgetFactory.labelSeparator(content);
+
+ final TableFilterAttribute viewFilter = new TableFilterAttribute(
+ CriteriaType.SINGLE_SELECTION,
+ TemplateAttribute.FILTER_ATTR_VIEW,
+ () -> this.resourceService.getViewResources(entityKey.modelId));
+ final TableFilterAttribute typeFilter = new TableFilterAttribute(
+ CriteriaType.SINGLE_SELECTION,
+ TemplateAttribute.FILTER_ATTR_TYPE,
+ this.resourceService::getAttributeTypeResources);
+
+ final EntityTable attrTable =
+ this.pageService.entityTableBuilder(
+ Domain.CONFIGURATION_NODE.TYPE_NAME + "_Template",
+ this.restService.getRestCall(GetTemplateAttributePage.class))
+ .withRestCallAdapter(restCall -> restCall.withURIVariable(
+ API.PARAM_PARENT_MODEL_ID,
+ entityKey.modelId))
+ .withPaging(15)
+ .withColumn(new ColumnDefinition<>(
+ Domain.CONFIGURATION_ATTRIBUTE.ATTR_NAME,
+ ATTRIBUTES_LIST_NAME_TEXT_KEY,
+ this::getAttributeName)
+ .withFilter(this.nameFilter)
+ .sortable()
+ .widthProportion(3))
+ .withColumn(new ColumnDefinition(
+ Domain.CONFIGURATION_ATTRIBUTE.ATTR_TYPE,
+ ATTRIBUTES_LIST_TYPE_TEXT_KEY,
+ resourceService::getAttributeTypeName)
+ .withFilter(typeFilter)
+ .sortable()
+ .widthProportion(1))
+ .withColumn(new ColumnDefinition<>(
+ Domain.ORIENTATION.ATTR_VIEW_ID,
+ ATTRIBUTES_LIST_VIEW_TEXT_KEY,
+ resourceService.getViewNameFunction(entityKey.modelId))
+ .withFilter(viewFilter)
+ .sortable()
+ .widthProportion(1))
+ .withColumn(new ColumnDefinition<>(
+ Domain.ORIENTATION.ATTR_GROUP_ID,
+ ATTRIBUTES_LIST_GROUP_TEXT_KEY,
+ TemplateAttribute::getGroupId)
+ .withFilter(this.groupFilter)
+ .sortable()
+ .widthProportion(1))
+ .withDefaultAction(pageActionBuilder
+ .newAction(ActionDefinition.SEB_EXAM_CONFIG_TEMPLATE_ATTR_EDIT)
+ .withParentEntityKey(entityKey)
+ .create())
+
+ .withSelectionListener(this.pageService.getSelectionPublisher(
+ pageContext,
+ ActionDefinition.SEB_EXAM_CONFIG_TEMPLATE_ATTR_EDIT,
+ ActionDefinition.SEB_EXAM_CONFIG_TEMPLATE_ATTR_SET_DEFAULT,
+ ActionDefinition.SEB_EXAM_CONFIG_TEMPLATE_ATTR_LIST_REMOVE_VIEW,
+ ActionDefinition.SEB_EXAM_CONFIG_TEMPLATE_ATTR_LIST_ATTACH_DEFAULT_VIEW))
+
+ .compose(pageContext.copyOf(content));
+
+ pageActionBuilder
+
+ .newAction(ActionDefinition.SEB_EXAM_CONFIG_TEMPLATE_ATTR_EDIT)
+ .withParentEntityKey(entityKey)
+ .withSelect(
+ attrTable::getSelection,
+ PageAction::applySingleSelectionAsEntityKey,
+ EMPTY_ATTRIBUTE_SELECTION_TEXT_KEY)
+ .publishIf(attrTable::hasAnyContent, false)
+
+ .newAction(ActionDefinition.SEB_EXAM_CONFIG_TEMPLATE_ATTR_SET_DEFAULT)
+ .withParentEntityKey(entityKey)
+ .withSelect(
+ attrTable::getSelection,
+ action -> this.resetToDefaults(action, attrTable),
+ EMPTY_ATTRIBUTE_SELECTION_TEXT_KEY)
+ .noEventPropagation()
+ .publishIf(attrTable::hasAnyContent, false)
+
+ .newAction(ActionDefinition.SEB_EXAM_CONFIG_TEMPLATE_ATTR_LIST_REMOVE_VIEW)
+ .withParentEntityKey(entityKey)
+ .withSelect(
+ attrTable::getSelection,
+ action -> this.removeFormView(action, attrTable),
+ EMPTY_ATTRIBUTE_SELECTION_TEXT_KEY)
+ .noEventPropagation()
+ .publishIf(attrTable::hasAnyContent, false)
+
+ .newAction(ActionDefinition.SEB_EXAM_CONFIG_TEMPLATE_ATTR_LIST_ATTACH_DEFAULT_VIEW)
+ .withParentEntityKey(entityKey)
+ .withSelect(
+ attrTable::getSelection,
+ action -> this.attachView(action, attrTable),
+ EMPTY_ATTRIBUTE_SELECTION_TEXT_KEY)
+ .noEventPropagation()
+ .publishIf(attrTable::hasAnyContent, false);
+ }
+
+ pageActionBuilder
+
+ .newAction(ActionDefinition.SEB_EXAM_CONFIG_TEMPLATE_NEW)
+ .publishIf(() -> writeGrant && isReadonly)
+
+ .newAction(ActionDefinition.SEB_EXAM_CONFIG_TEMPLATE_MODIFY)
+ .withEntityKey(entityKey)
+ .publishIf(() -> modifyGrant && isReadonly)
+
+ .newAction(ActionDefinition.SEB_EXAM_CONFIG_TEMPLATE_CREATE_CONFIG)
+ .withEntityKey(entityKey)
+ .withExec(SebExamConfigCreationPopup.configCreationFunction(
+ this.pageService,
+ pageContext
+ .withAttribute(
+ PageContext.AttributeKeys.CREATE_FROM_TEMPLATE,
+ Constants.TRUE_STRING)
+ .withAttribute(
+ PageContext.AttributeKeys.COPY_AS_TEMPLATE,
+ Constants.FALSE_STRING)))
+ .publishIf(() -> modifyGrant && isReadonly)
+
+ .newAction(ActionDefinition.SEB_EXAM_CONFIG_TEMPLATE_SAVE)
+ .withEntityKey(entityKey)
+ .withExec(formHandle::processFormSave)
+ .ignoreMoveAwayFromEdit()
+ .publishIf(() -> !isReadonly)
+
+ .newAction(ActionDefinition.SEB_EXAM_CONFIG_TEMPLATE_CANCEL_MODIFY)
+ .withEntityKey(entityKey)
+ .withExec(this.pageService.backToCurrentFunction())
+ .publishIf(() -> !isReadonly);
+
+ }
+
+ private String getAttributeName(final TemplateAttribute attribute) {
+
+ final String name = this.i18nSupport.getText(
+ ExamConfigurationService.ATTRIBUTE_LABEL_LOC_TEXT_PREFIX + attribute.getName(),
+ "");
+ if (StringUtils.isNotBlank(name)) {
+ return attribute.getName() + " (" + name + ")";
+ } else {
+ return attribute.getName();
+ }
+ }
+
+ private PageAction resetToDefaults(
+ final PageAction action,
+ final EntityTable attrTable) {
+
+ final PageAction resetToDefaults = this.examConfigurationService.resetToDefaults(action);
+ // reload the list
+ attrTable.applyFilter();
+ return resetToDefaults;
+ }
+
+ private PageAction removeFormView(
+ final PageAction action,
+ final EntityTable attrTable) {
+
+ final PageAction removeFormView = this.examConfigurationService.removeFromView(action);
+ // reload the list
+ attrTable.applyFilter();
+ return removeFormView;
+ }
+
+ private PageAction attachView(
+ final PageAction action,
+ final EntityTable attrTable) {
+
+ final PageAction attachView = this.examConfigurationService.attachToDefaultView(action);
+ // reload the list
+ attrTable.applyFilter();
+ return attachView;
+ }
+
+}
diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/content/ConfigTemplateList.java b/src/main/java/ch/ethz/seb/sebserver/gui/content/ConfigTemplateList.java
index 5694776d..674dab8f 100644
--- a/src/main/java/ch/ethz/seb/sebserver/gui/content/ConfigTemplateList.java
+++ b/src/main/java/ch/ethz/seb/sebserver/gui/content/ConfigTemplateList.java
@@ -1,155 +1,159 @@
-/*
- * Copyright (c) 2020 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.content;
-
-import org.eclipse.swt.widgets.Composite;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.context.annotation.Lazy;
-import org.springframework.stereotype.Component;
-
-import ch.ethz.seb.sebserver.gbl.api.EntityType;
-import ch.ethz.seb.sebserver.gbl.model.Domain;
-import ch.ethz.seb.sebserver.gbl.model.Entity;
-import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode;
-import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode.ConfigurationType;
-import ch.ethz.seb.sebserver.gbl.model.user.UserRole;
-import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
-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.LocTextKey;
-import ch.ethz.seb.sebserver.gui.service.page.PageContext;
-import ch.ethz.seb.sebserver.gui.service.page.PageService;
-import ch.ethz.seb.sebserver.gui.service.page.PageService.PageActionBuilder;
-import ch.ethz.seb.sebserver.gui.service.page.TemplateComposer;
-import ch.ethz.seb.sebserver.gui.service.page.impl.PageAction;
-import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestService;
-import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.GetExamConfigNodePage;
-import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.CurrentUser;
-import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.CurrentUser.GrantCheck;
-import ch.ethz.seb.sebserver.gui.table.ColumnDefinition;
-import ch.ethz.seb.sebserver.gui.table.ColumnDefinition.TableFilterAttribute;
-import ch.ethz.seb.sebserver.gui.table.EntityTable;
-import ch.ethz.seb.sebserver.gui.table.TableFilter.CriteriaType;
-import ch.ethz.seb.sebserver.gui.widget.WidgetFactory;
-
-@Lazy
-@Component
-@GuiProfile
-public class ConfigTemplateList implements TemplateComposer {
-
- private static final LocTextKey NO_MODIFY_PRIVILEGE_ON_OTHER_INSTITUION =
- new LocTextKey("sebserver.examconfig.list.action.no.modify.privilege");
- private static final LocTextKey TITLE_TEMPLATE_TEXT_KEY =
- new LocTextKey("sebserver.configtemplate.list.title");
- private static final LocTextKey EMPTY_TEMPLATE_LIST_TEXT_KEY =
- new LocTextKey("sebserver.configtemplate.list.empty");
- private static final LocTextKey INSTITUTION_TEXT_KEY =
- new LocTextKey("sebserver.examconfig.list.column.institution");
- private static final LocTextKey NAME_TEXT_KEY =
- new LocTextKey("sebserver.examconfig.list.column.name");
- private static final LocTextKey DESCRIPTION_TEXT_KEY =
- new LocTextKey("sebserver.examconfig.list.column.description");
- private static final LocTextKey EMPTY_TEMPLATE_SELECTION_TEXT_KEY =
- new LocTextKey("sebserver.configtemplate.info.pleaseSelect");
-
- private final PageService pageService;
- private final RestService restService;
- private final CurrentUser currentUser;
- private final ResourceService resourceService;
- private final int pageSize;
-
- private final TableFilterAttribute institutionFilter;
- private final TableFilterAttribute nameFilter =
- new TableFilterAttribute(CriteriaType.TEXT, Entity.FILTER_ATTR_NAME);
- private final TableFilterAttribute descFilter =
- new TableFilterAttribute(CriteriaType.TEXT, ConfigurationNode.FILTER_ATTR_DESCRIPTION);
-
- protected ConfigTemplateList(
- final PageService pageService,
- final RestService restService,
- final CurrentUser currentUser,
- @Value("${sebserver.gui.list.page.size:20}") final Integer pageSize) {
-
- this.pageService = pageService;
- this.restService = restService;
- this.currentUser = currentUser;
- this.resourceService = pageService.getResourceService();
- this.pageSize = pageSize;
-
- this.institutionFilter = new TableFilterAttribute(
- CriteriaType.SINGLE_SELECTION,
- Entity.FILTER_ATTR_INSTITUTION,
- this.resourceService::institutionResource);
- }
-
- @Override
- public void compose(final PageContext pageContext) {
- final WidgetFactory widgetFactory = this.pageService.getWidgetFactory();
- final Composite content = widgetFactory.defaultPageLayout(
- pageContext.getParent(),
- TITLE_TEMPLATE_TEXT_KEY);
-
- final boolean isSEBAdmin = this.currentUser.get().hasRole(UserRole.SEB_SERVER_ADMIN);
- final PageActionBuilder pageActionBuilder =
- this.pageService.pageActionBuilder(pageContext.clearEntityKeys());
-
- final EntityTable templateTable =
- this.pageService.entityTableBuilder(
- TITLE_TEMPLATE_TEXT_KEY.name,
- this.restService.getRestCall(GetExamConfigNodePage.class))
- .withStaticFilter(
- Domain.CONFIGURATION_NODE.ATTR_TYPE,
- ConfigurationType.TEMPLATE.name())
- .withEmptyMessage(EMPTY_TEMPLATE_LIST_TEXT_KEY)
- .withPaging(this.pageSize)
- .withColumnIf(
- () -> isSEBAdmin,
- () -> new ColumnDefinition<>(
- Domain.LMS_SETUP.ATTR_INSTITUTION_ID,
- INSTITUTION_TEXT_KEY,
- this.resourceService::localizedExamConfigInstitutionName)
- .withFilter(this.institutionFilter)
- .sortable())
- .withColumn(new ColumnDefinition<>(
- Domain.CONFIGURATION_NODE.ATTR_NAME,
- NAME_TEXT_KEY,
- ConfigurationNode::getName)
- .withFilter(this.nameFilter)
- .sortable())
- .withColumn(new ColumnDefinition<>(
- Domain.CONFIGURATION_NODE.ATTR_DESCRIPTION,
- DESCRIPTION_TEXT_KEY,
- ConfigurationNode::getDescription)
- .withFilter(this.descFilter)
- .sortable())
- .withDefaultAction(pageActionBuilder
- .newAction(ActionDefinition.SEB_EXAM_CONFIG_TEMPLATE_VIEW_FROM_LIST)
- .create())
- .compose(pageContext.copyOf(content));
-
- final GrantCheck examConfigGrant = this.currentUser.grantCheck(EntityType.CONFIGURATION_NODE);
- pageActionBuilder
- // Exam Configuration template actions...
- .newAction(ActionDefinition.SEB_EXAM_CONFIG_TEMPLATE_NEW)
- .publishIf(examConfigGrant::iw)
-
- .newAction(ActionDefinition.SEB_EXAM_CONFIG_TEMPLATE_VIEW_FROM_LIST)
- .withSelect(templateTable::getSelection, PageAction::applySingleSelectionAsEntityKey,
- EMPTY_TEMPLATE_SELECTION_TEXT_KEY)
- .publishIf(() -> templateTable.hasAnyContent())
-
- .newAction(ActionDefinition.SEB_EXAM_CONFIG_TEMPLATE_MODIFY_FROM_LIST)
- .withSelect(
- templateTable.getGrantedSelection(this.currentUser, NO_MODIFY_PRIVILEGE_ON_OTHER_INSTITUION),
- PageAction::applySingleSelectionAsEntityKey, EMPTY_TEMPLATE_SELECTION_TEXT_KEY)
- .publishIf(() -> examConfigGrant.im() && templateTable.hasAnyContent());
-
- }
-
-}
+/*
+ * Copyright (c) 2020 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.content;
+
+import org.eclipse.swt.widgets.Composite;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Lazy;
+import org.springframework.stereotype.Component;
+
+import ch.ethz.seb.sebserver.gbl.api.EntityType;
+import ch.ethz.seb.sebserver.gbl.model.Domain;
+import ch.ethz.seb.sebserver.gbl.model.Entity;
+import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode;
+import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode.ConfigurationType;
+import ch.ethz.seb.sebserver.gbl.model.user.UserRole;
+import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
+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.LocTextKey;
+import ch.ethz.seb.sebserver.gui.service.page.PageContext;
+import ch.ethz.seb.sebserver.gui.service.page.PageService;
+import ch.ethz.seb.sebserver.gui.service.page.PageService.PageActionBuilder;
+import ch.ethz.seb.sebserver.gui.service.page.TemplateComposer;
+import ch.ethz.seb.sebserver.gui.service.page.impl.PageAction;
+import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestService;
+import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.GetExamConfigNodePage;
+import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.CurrentUser;
+import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.CurrentUser.GrantCheck;
+import ch.ethz.seb.sebserver.gui.table.ColumnDefinition;
+import ch.ethz.seb.sebserver.gui.table.ColumnDefinition.TableFilterAttribute;
+import ch.ethz.seb.sebserver.gui.table.EntityTable;
+import ch.ethz.seb.sebserver.gui.table.TableFilter.CriteriaType;
+import ch.ethz.seb.sebserver.gui.widget.WidgetFactory;
+
+@Lazy
+@Component
+@GuiProfile
+public class ConfigTemplateList implements TemplateComposer {
+
+ private static final LocTextKey NO_MODIFY_PRIVILEGE_ON_OTHER_INSTITUTION =
+ new LocTextKey("sebserver.examconfig.list.action.no.modify.privilege");
+ private static final LocTextKey TITLE_TEMPLATE_TEXT_KEY =
+ new LocTextKey("sebserver.configtemplate.list.title");
+ private static final LocTextKey EMPTY_TEMPLATE_LIST_TEXT_KEY =
+ new LocTextKey("sebserver.configtemplate.list.empty");
+ private static final LocTextKey INSTITUTION_TEXT_KEY =
+ new LocTextKey("sebserver.examconfig.list.column.institution");
+ private static final LocTextKey NAME_TEXT_KEY =
+ new LocTextKey("sebserver.examconfig.list.column.name");
+ private static final LocTextKey DESCRIPTION_TEXT_KEY =
+ new LocTextKey("sebserver.examconfig.list.column.description");
+ private static final LocTextKey EMPTY_TEMPLATE_SELECTION_TEXT_KEY =
+ new LocTextKey("sebserver.configtemplate.info.pleaseSelect");
+
+ private final PageService pageService;
+ private final RestService restService;
+ private final CurrentUser currentUser;
+ private final ResourceService resourceService;
+ private final int pageSize;
+
+ private final TableFilterAttribute institutionFilter;
+ private final TableFilterAttribute nameFilter =
+ new TableFilterAttribute(CriteriaType.TEXT, Entity.FILTER_ATTR_NAME);
+ private final TableFilterAttribute descFilter =
+ new TableFilterAttribute(CriteriaType.TEXT, ConfigurationNode.FILTER_ATTR_DESCRIPTION);
+
+ protected ConfigTemplateList(
+ final PageService pageService,
+ final RestService restService,
+ final CurrentUser currentUser,
+ @Value("${sebserver.gui.list.page.size:20}") final Integer pageSize) {
+
+ this.pageService = pageService;
+ this.restService = restService;
+ this.currentUser = currentUser;
+ this.resourceService = pageService.getResourceService();
+ this.pageSize = pageSize;
+
+ this.institutionFilter = new TableFilterAttribute(
+ CriteriaType.SINGLE_SELECTION,
+ Entity.FILTER_ATTR_INSTITUTION,
+ this.resourceService::institutionResource);
+ }
+
+ @Override
+ public void compose(final PageContext pageContext) {
+ final WidgetFactory widgetFactory = this.pageService.getWidgetFactory();
+ final Composite content = widgetFactory.defaultPageLayout(
+ pageContext.getParent(),
+ TITLE_TEMPLATE_TEXT_KEY);
+
+ final boolean isSEBAdmin = this.currentUser.get().hasRole(UserRole.SEB_SERVER_ADMIN);
+ final PageActionBuilder pageActionBuilder =
+ this.pageService.pageActionBuilder(pageContext.clearEntityKeys());
+
+ final EntityTable templateTable =
+ this.pageService.entityTableBuilder(
+ TITLE_TEMPLATE_TEXT_KEY.name,
+ this.restService.getRestCall(GetExamConfigNodePage.class))
+ .withStaticFilter(
+ Domain.CONFIGURATION_NODE.ATTR_TYPE,
+ ConfigurationType.TEMPLATE.name())
+ .withEmptyMessage(EMPTY_TEMPLATE_LIST_TEXT_KEY)
+ .withPaging(this.pageSize)
+ .withColumnIf(
+ () -> isSEBAdmin,
+ () -> new ColumnDefinition<>(
+ Domain.LMS_SETUP.ATTR_INSTITUTION_ID,
+ INSTITUTION_TEXT_KEY,
+ this.resourceService::localizedExamConfigInstitutionName)
+ .withFilter(this.institutionFilter)
+ .sortable())
+ .withColumn(new ColumnDefinition<>(
+ Domain.CONFIGURATION_NODE.ATTR_NAME,
+ NAME_TEXT_KEY,
+ ConfigurationNode::getName)
+ .withFilter(this.nameFilter)
+ .sortable())
+ .withColumn(new ColumnDefinition<>(
+ Domain.CONFIGURATION_NODE.ATTR_DESCRIPTION,
+ DESCRIPTION_TEXT_KEY,
+ ConfigurationNode::getDescription)
+ .withFilter(this.descFilter)
+ .sortable())
+ .withDefaultAction(pageActionBuilder
+ .newAction(ActionDefinition.SEB_EXAM_CONFIG_TEMPLATE_VIEW_FROM_LIST)
+ .create())
+
+ .withSelectionListener(this.pageService.getSelectionPublisher(
+ pageContext,
+ ActionDefinition.SEB_EXAM_CONFIG_TEMPLATE_VIEW_FROM_LIST,
+ ActionDefinition.SEB_EXAM_CONFIG_TEMPLATE_MODIFY_FROM_LIST))
+
+ .compose(pageContext.copyOf(content));
+
+ final GrantCheck examConfigGrant = this.currentUser.grantCheck(EntityType.CONFIGURATION_NODE);
+ pageActionBuilder
+ // Exam Configuration template actions...
+ .newAction(ActionDefinition.SEB_EXAM_CONFIG_TEMPLATE_NEW)
+ .publishIf(examConfigGrant::iw)
+
+ .newAction(ActionDefinition.SEB_EXAM_CONFIG_TEMPLATE_VIEW_FROM_LIST)
+ .withSelect(templateTable::getSelection, PageAction::applySingleSelectionAsEntityKey,
+ EMPTY_TEMPLATE_SELECTION_TEXT_KEY)
+ .publishIf(templateTable::hasAnyContent, false)
+
+ .newAction(ActionDefinition.SEB_EXAM_CONFIG_TEMPLATE_MODIFY_FROM_LIST)
+ .withSelect(
+ templateTable.getGrantedSelection(this.currentUser, NO_MODIFY_PRIVILEGE_ON_OTHER_INSTITUTION),
+ PageAction::applySingleSelectionAsEntityKey, EMPTY_TEMPLATE_SELECTION_TEXT_KEY)
+ .publishIf(() -> examConfigGrant.im() && templateTable.hasAnyContent(), false);
+ }
+}
diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/content/ExamForm.java b/src/main/java/ch/ethz/seb/sebserver/gui/content/ExamForm.java
index c84df4ef..583c1213 100644
--- a/src/main/java/ch/ethz/seb/sebserver/gui/content/ExamForm.java
+++ b/src/main/java/ch/ethz/seb/sebserver/gui/content/ExamForm.java
@@ -1,762 +1,762 @@
-/*
- * 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.content;
-
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-import java.util.function.BooleanSupplier;
-import java.util.function.Function;
-import java.util.function.Supplier;
-
-import org.apache.commons.lang3.BooleanUtils;
-import org.apache.tomcat.util.buf.StringUtils;
-import org.eclipse.rap.rwt.RWT;
-import org.eclipse.rap.rwt.client.service.UrlLauncher;
-import org.eclipse.swt.widgets.Composite;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.context.annotation.Lazy;
-import org.springframework.stereotype.Component;
-
-import ch.ethz.seb.sebserver.gbl.Constants;
-import ch.ethz.seb.sebserver.gbl.api.API;
-import ch.ethz.seb.sebserver.gbl.api.APIMessage;
-import ch.ethz.seb.sebserver.gbl.api.EntityType;
-import ch.ethz.seb.sebserver.gbl.model.Domain;
-import ch.ethz.seb.sebserver.gbl.model.EntityKey;
-import ch.ethz.seb.sebserver.gbl.model.exam.Exam;
-import ch.ethz.seb.sebserver.gbl.model.exam.Exam.ExamStatus;
-import ch.ethz.seb.sebserver.gbl.model.exam.ExamConfigurationMap;
-import ch.ethz.seb.sebserver.gbl.model.exam.Indicator;
-import ch.ethz.seb.sebserver.gbl.model.exam.QuizData;
-import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetup.Features;
-import ch.ethz.seb.sebserver.gbl.model.user.UserRole;
-import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
-import ch.ethz.seb.sebserver.gbl.util.Result;
-import ch.ethz.seb.sebserver.gbl.util.Utils;
-import ch.ethz.seb.sebserver.gui.content.action.ActionDefinition;
-import ch.ethz.seb.sebserver.gui.form.FormBuilder;
-import ch.ethz.seb.sebserver.gui.form.FormHandle;
-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.PageContext;
-import ch.ethz.seb.sebserver.gui.service.page.PageContext.AttributeKeys;
-import ch.ethz.seb.sebserver.gui.service.page.PageService;
-import ch.ethz.seb.sebserver.gui.service.page.PageService.PageActionBuilder;
-import ch.ethz.seb.sebserver.gui.service.page.TemplateComposer;
-import ch.ethz.seb.sebserver.gui.service.page.event.ActionEvent;
-import ch.ethz.seb.sebserver.gui.service.page.impl.PageAction;
-import ch.ethz.seb.sebserver.gui.service.remote.download.DownloadService;
-import ch.ethz.seb.sebserver.gui.service.remote.download.SebExamConfigDownload;
-import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestService;
-import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.CheckExamConsistency;
-import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.DeleteExamConfigMapping;
-import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.DeleteIndicator;
-import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.GetExam;
-import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.GetExamConfigMappingsPage;
-import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.GetIndicatorPage;
-import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.SaveExam;
-import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.lmssetup.GetLmsSetup;
-import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.quiz.GetQuizData;
-import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.quiz.ImportAsExam;
-import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.CurrentUser;
-import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.CurrentUser.EntityGrantCheck;
-import ch.ethz.seb.sebserver.gui.table.ColumnDefinition;
-import ch.ethz.seb.sebserver.gui.table.EntityTable;
-import ch.ethz.seb.sebserver.gui.widget.WidgetFactory;
-import ch.ethz.seb.sebserver.gui.widget.WidgetFactory.CustomVariant;
-
-@Lazy
-@Component
-@GuiProfile
-public class ExamForm implements TemplateComposer {
-
- private static final Logger log = LoggerFactory.getLogger(ExamForm.class);
-
- public static final LocTextKey EXAM_FORM_TITLE_KEY =
- new LocTextKey("sebserver.exam.form.title");
- public static final LocTextKey EXAM_FORM_TITLE_IMPORT_KEY =
- new LocTextKey("sebserver.exam.form.title.import");
- private static final LocTextKey CONFIG_EMPTY_LIST_MESSAGE =
- new LocTextKey("sebserver.exam.configuration.list.empty");
- private static final LocTextKey INDICATOR_EMPTY_LIST_MESSAGE =
- new LocTextKey("sebserver.exam.indicator.list.empty");
- private static final LocTextKey FORM_SUPPORTER_TEXT_KEY =
- new LocTextKey("sebserver.exam.form.supporter");
- private static final LocTextKey FORM_STATUS_TEXT_KEY =
- new LocTextKey("sebserver.exam.form.status");
- private static final LocTextKey FORM_TYPE_TEXT_KEY =
- new LocTextKey("sebserver.exam.form.type");
- private static final LocTextKey FORM_ENDTIME_TEXT_KEY =
- new LocTextKey("sebserver.exam.form.endtime");
- private static final LocTextKey FORM_STARTTIME_TEXT_KEY =
- new LocTextKey("sebserver.exam.form.starttime");
- private static final LocTextKey FORM_DESCRIPTION_TEXT_KEY =
- new LocTextKey("sebserver.exam.form.description");
- private static final LocTextKey FORM_NAME_TEXT_KEY =
- new LocTextKey("sebserver.exam.form.name");
- private static final LocTextKey FORM_QUIZID_TEXT_KEY =
- new LocTextKey("sebserver.exam.form.quizid");
- private static final LocTextKey FORM_QUIZ_URL_TEXT_KEY =
- new LocTextKey("sebserver.exam.form.quizurl");
- private static final LocTextKey FORM_LMSSETUP_TEXT_KEY =
- new LocTextKey("sebserver.exam.form.lmssetup");
-
- private final static LocTextKey CONFIG_LIST_TITLE_KEY =
- new LocTextKey("sebserver.exam.configuration.list.title");
- private final static LocTextKey CONFIG_NAME_COLUMN_KEY =
- new LocTextKey("sebserver.exam.configuration.list.column.name");
- private final static LocTextKey CONFIG_DESCRIPTION_COLUMN_KEY =
- new LocTextKey("sebserver.exam.configuration.list.column.description");
- private final static LocTextKey CONFIG_STATUS_COLUMN_KEY =
- new LocTextKey("sebserver.exam.configuration.list.column.status");
- private final static LocTextKey CONFIG_EMPTY_SELECTION_TEXT_KEY =
- new LocTextKey("sebserver.exam.configuration.list.pleaseSelect");
-
- private final static LocTextKey INDICATOR_LIST_TITLE_KEY =
- new LocTextKey("sebserver.exam.indicator.list.title");
- private final static LocTextKey INDICATOR_TYPE_COLUMN_KEY =
- new LocTextKey("sebserver.exam.indicator.list.column.type");
- private final static LocTextKey INDICATOR_NAME_COLUMN_KEY =
- new LocTextKey("sebserver.exam.indicator.list.column.name");
- private final static LocTextKey INDICATOR_THRESHOLD_COLUMN_KEY =
- new LocTextKey("sebserver.exam.indicator.list.column.thresholds");
- private final static LocTextKey INDICATOR_EMPTY_SELECTION_TEXT_KEY =
- new LocTextKey("sebserver.exam.indicator.list.pleaseSelect");
-
- private final static LocTextKey CONSISTENCY_MESSAGE_TITLE =
- new LocTextKey("sebserver.exam.consistency.title");
- private final static LocTextKey CONSISTENCY_MESSAGE_MISSING_SUPPORTER =
- new LocTextKey("sebserver.exam.consistency.missing-supporter");
- private final static LocTextKey CONSISTENCY_MESSAGE_MISSING_INDICATOR =
- new LocTextKey("sebserver.exam.consistency.missing-indicator");
- private final static LocTextKey CONSISTENCY_MESSAGE_MISSING_CONFIG =
- new LocTextKey("sebserver.exam.consistency.missing-config");
- private final static LocTextKey CONSISTENCY_MESSAGE_MISSING_SEB_RESTRICTION =
- new LocTextKey("sebserver.exam.consistency.missing-seb-restriction");
-
- private final Map consistencyMessageMapping;
-
- private final static LocTextKey CONFIRM_MESSAGE_REMOVE_CONFIG =
- new LocTextKey("sebserver.exam.confirm.remove-config");
-
- private final PageService pageService;
- private final ResourceService resourceService;
- private final DownloadService downloadService;
- private final String downloadFileName;
- private final WidgetFactory widgetFactory;
- private final RestService restService;
-
- protected ExamForm(
- final PageService pageService,
- final ResourceService resourceService,
- final DownloadService downloadService,
- @Value("${sebserver.gui.seb.exam.config.download.filename}") final String downloadFileName) {
-
- this.pageService = pageService;
- this.resourceService = resourceService;
- this.downloadService = downloadService;
- this.downloadFileName = downloadFileName;
- this.widgetFactory = pageService.getWidgetFactory();
- this.restService = this.resourceService.getRestService();
-
- this.consistencyMessageMapping = new HashMap<>();
- this.consistencyMessageMapping.put(
- APIMessage.ErrorMessage.EXAM_CONSISTANCY_VALIDATION_SUPPORTER.messageCode,
- CONSISTENCY_MESSAGE_MISSING_SUPPORTER);
- this.consistencyMessageMapping.put(
- APIMessage.ErrorMessage.EXAM_CONSISTANCY_VALIDATION_INDICATOR.messageCode,
- CONSISTENCY_MESSAGE_MISSING_INDICATOR);
- this.consistencyMessageMapping.put(
- APIMessage.ErrorMessage.EXAM_CONSISTANCY_VALIDATION_CONFIG.messageCode,
- CONSISTENCY_MESSAGE_MISSING_CONFIG);
- this.consistencyMessageMapping.put(
- APIMessage.ErrorMessage.EXAM_CONSISTANCY_VALIDATION_SEB_RESTRICTION.messageCode,
- CONSISTENCY_MESSAGE_MISSING_SEB_RESTRICTION);
- }
-
- @Override
- public void compose(final PageContext pageContext) {
- final CurrentUser currentUser = this.resourceService.getCurrentUser();
-
- final I18nSupport i18nSupport = this.resourceService.getI18nSupport();
- final EntityKey entityKey = pageContext.getEntityKey();
- final boolean readonly = pageContext.isReadonly();
- final boolean importFromQuizData = BooleanUtils.toBoolean(
- pageContext.getAttribute(AttributeKeys.IMPORT_FROM_QUIZ_DATA));
-
- // get or create model data
- final Exam exam = (importFromQuizData
- ? createExamFromQuizData(pageContext)
- : getExistingExam(pageContext))
- .onError(error -> pageContext.notifyLoadError(EntityType.EXAM, error))
- .getOrThrow();
-
- // new PageContext with actual EntityKey
- final PageContext formContext = pageContext.withEntityKey(exam.getEntityKey());
-
- // check exam consistency and inform the user if needed
- if (readonly) {
- this.restService.getBuilder(CheckExamConsistency.class)
- .withURIVariable(API.PARAM_MODEL_ID, entityKey.modelId)
- .call()
- .ifPresent(result -> showConsistencyChecks(result, formContext.getParent()));
- }
-
- // the default page layout with title
- final LocTextKey titleKey = importFromQuizData
- ? EXAM_FORM_TITLE_IMPORT_KEY
- : EXAM_FORM_TITLE_KEY;
- final Composite content = this.widgetFactory.defaultPageLayout(
- formContext.getParent(),
- titleKey);
-
- final BooleanSupplier isNew = () -> importFromQuizData;
- final BooleanSupplier isNotNew = () -> !isNew.getAsBoolean();
- final EntityGrantCheck userGrantCheck = currentUser.entityGrantCheck(exam);
- final boolean modifyGrant = userGrantCheck.m();
- final ExamStatus examStatus = exam.getStatus();
- final boolean isExamRunning = examStatus == ExamStatus.RUNNING;
- final boolean editable = examStatus == ExamStatus.UP_COMING
- || examStatus == ExamStatus.RUNNING
- && currentUser.get().hasRole(UserRole.EXAM_ADMIN);
- final boolean sebRestrictionAvailable = testSebRestrictionAPI(exam);
-
- // The Exam form
- final FormHandle formHandle = this.pageService.formBuilder(
- formContext.copyOf(content), 8)
- .withDefaultSpanLabel(1)
- .withDefaultSpanInput(4)
- .withDefaultSpanEmptyCell(3)
- .readonly(readonly)
- .putStaticValueIf(isNotNew,
- Domain.EXAM.ATTR_ID,
- exam.getModelId())
- .putStaticValue(
- Domain.EXAM.ATTR_INSTITUTION_ID,
- String.valueOf(exam.getInstitutionId()))
- .putStaticValueIf(isNotNew,
- Domain.EXAM.ATTR_LMS_SETUP_ID,
- String.valueOf(exam.lmsSetupId))
- .putStaticValueIf(isNew,
- QuizData.QUIZ_ATTR_LMS_SETUP_ID,
- String.valueOf(exam.lmsSetupId))
- .putStaticValueIf(isNotNew,
- Domain.EXAM.ATTR_EXTERNAL_ID,
- exam.externalId)
- .putStaticValueIf(isNew,
- QuizData.QUIZ_ATTR_ID,
- exam.externalId)
-
- .addField(FormBuilder.text(
- QuizData.QUIZ_ATTR_NAME,
- FORM_NAME_TEXT_KEY,
- exam.name)
- .readonly(true)
- .withInputSpan(3)
- .withEmptyCellSeparation(false))
-
- .addField(FormBuilder.singleSelection(
- Domain.EXAM.ATTR_LMS_SETUP_ID,
- FORM_LMSSETUP_TEXT_KEY,
- String.valueOf(exam.lmsSetupId),
- this.resourceService::lmsSetupResource)
- .readonly(true)
- .withInputSpan(3)
- .withEmptyCellSeparation(false))
-
- .addField(FormBuilder.text(
- QuizData.QUIZ_ATTR_START_TIME,
- FORM_STARTTIME_TEXT_KEY,
- i18nSupport.formatDisplayDateWithTimeZone(exam.startTime))
- .readonly(true)
- .withInputSpan(3)
- .withEmptyCellSeparation(false))
- .addField(FormBuilder.text(
- QuizData.QUIZ_ATTR_END_TIME,
- FORM_ENDTIME_TEXT_KEY,
- i18nSupport.formatDisplayDateWithTimeZone(exam.endTime))
- .readonly(true)
- .withInputSpan(3)
- .withEmptyCellSeparation(false))
-
- .addField(FormBuilder.text(
- Domain.EXAM.ATTR_EXTERNAL_ID,
- FORM_QUIZID_TEXT_KEY,
- exam.externalId)
- .readonly(true)
- .withEmptyCellSeparation(false))
- .addField(FormBuilder.text(
- QuizData.QUIZ_ATTR_START_URL,
- FORM_QUIZ_URL_TEXT_KEY,
- exam.startURL)
- .readonly(true)
- .withInputSpan(7))
-
- .addField(FormBuilder.text(
- QuizData.QUIZ_ATTR_DESCRIPTION,
- FORM_DESCRIPTION_TEXT_KEY,
- exam.description)
- .asHTML()
- .readonly(true)
- .withInputSpan(6)
- .withEmptyCellSeparation(false))
-
- .addField(FormBuilder.text(
- Domain.EXAM.ATTR_STATUS + "_display",
- FORM_STATUS_TEXT_KEY,
- i18nSupport.getText(new LocTextKey("sebserver.exam.status." + examStatus.name())))
- .readonly(true)
- .withLabelSpan(2)
- .withInputSpan(4)
- .withEmptyCellSpan(1))
- .addField(FormBuilder.singleSelection(
- Domain.EXAM.ATTR_TYPE,
- FORM_TYPE_TEXT_KEY,
- String.valueOf(exam.type),
- this.resourceService::examTypeResources)
- .withLabelSpan(2)
- .withInputSpan(4)
- .withEmptyCellSpan(2))
-
- .addField(FormBuilder.multiComboSelection(
- Domain.EXAM.ATTR_SUPPORTER,
- FORM_SUPPORTER_TEXT_KEY,
- StringUtils.join(exam.supporter, Constants.LIST_SEPARATOR_CHAR),
- this.resourceService::examSupporterResources)
- .withLabelSpan(2)
- .withInputSpan(4)
- .withEmptyCellSpan(2))
-
- .buildFor(importFromQuizData
- ? this.restService.getRestCall(ImportAsExam.class)
- : this.restService.getRestCall(SaveExam.class));
-
- final PageActionBuilder actionBuilder = this.pageService.pageActionBuilder(formContext
- .clearEntityKeys()
- .removeAttribute(AttributeKeys.IMPORT_FROM_QUIZ_DATA));
- // propagate content actions to action-pane
- actionBuilder
-
- .newAction(ActionDefinition.EXAM_MODIFY)
- .withEntityKey(entityKey)
- .publishIf(() -> modifyGrant && readonly && editable)
-
- .newAction(ActionDefinition.EXAM_SAVE)
- .withExec(action -> (importFromQuizData)
- ? importExam(action, formHandle, sebRestrictionAvailable && exam.status == ExamStatus.RUNNING)
- : formHandle.processFormSave(action))
- .ignoreMoveAwayFromEdit()
- .publishIf(() -> !readonly && modifyGrant)
-
- .newAction(ActionDefinition.EXAM_CANCEL_MODIFY)
- .withEntityKey(entityKey)
- .withAttribute(AttributeKeys.IMPORT_FROM_QUIZ_DATA, String.valueOf(importFromQuizData))
- .withExec(this.cancelModifyFunction())
- .publishIf(() -> !readonly)
-
- .newAction(ActionDefinition.EXAM_MODIFY_SEB_RESTRICTION_DETAILS)
- .withEntityKey(entityKey)
- .withExec(ExamSebRestrictionSettings.settingsFunction(this.pageService))
- .withAttribute(
- ExamSebRestrictionSettings.PAGE_CONTEXT_ATTR_LMS_TYPE,
- this.restService.getBuilder(GetLmsSetup.class)
- .withURIVariable(API.PARAM_MODEL_ID, String.valueOf(exam.lmsSetupId))
- .call()
- .getOrThrow().lmsType.name())
- .noEventPropagation()
- .publishIf(() -> sebRestrictionAvailable && readonly)
-
- .newAction(ActionDefinition.EXAM_ENABLE_SEB_RESTRICTION)
- .withEntityKey(entityKey)
- .withExec(action -> ExamSebRestrictionSettings.setSebRestriction(action, true, this.restService))
- .publishIf(() -> sebRestrictionAvailable && readonly && BooleanUtils.isFalse(exam.lmsSebRestriction))
-
- .newAction(ActionDefinition.EXAM_DISABLE_SEB_RESTRICTION)
- .withEntityKey(entityKey)
- .withExec(action -> ExamSebRestrictionSettings.setSebRestriction(action, false, this.restService))
- .publishIf(() -> sebRestrictionAvailable && readonly && BooleanUtils.isTrue(exam.lmsSebRestriction));
-
- // additional data in read-only view
- if (readonly && !importFromQuizData) {
-
- // List of SEB Configuration
- this.widgetFactory.label(content, "");
- this.widgetFactory.labelLocalized(
- content,
- CustomVariant.TEXT_H3,
- CONFIG_LIST_TITLE_KEY);
- this.widgetFactory.labelSeparator(content);
-
- final EntityTable configurationTable =
- this.pageService.entityTableBuilder(this.restService.getRestCall(GetExamConfigMappingsPage.class))
- .withRestCallAdapter(builder -> builder.withQueryParam(
- ExamConfigurationMap.FILTER_ATTR_EXAM_ID,
- entityKey.modelId))
- .withEmptyMessage(CONFIG_EMPTY_LIST_MESSAGE)
- .withPaging(1)
- .hideNavigation()
- .withColumn(new ColumnDefinition<>(
- Domain.CONFIGURATION_NODE.ATTR_NAME,
- CONFIG_NAME_COLUMN_KEY,
- ExamConfigurationMap::getConfigName)
- .widthProportion(2))
- .withColumn(new ColumnDefinition<>(
- Domain.CONFIGURATION_NODE.ATTR_DESCRIPTION,
- CONFIG_DESCRIPTION_COLUMN_KEY,
- ExamConfigurationMap::getConfigDescription)
- .widthProportion(4))
- .withColumn(new ColumnDefinition(
- Domain.CONFIGURATION_NODE.ATTR_STATUS,
- CONFIG_STATUS_COLUMN_KEY,
- this.resourceService::localizedExamConfigStatusName)
- .widthProportion(1))
- .withDefaultActionIf(
- () -> modifyGrant,
- this::viewExamConfigPageAction)
-
- .compose(pageContext.copyOf(content));
-
- final EntityKey configMapKey = (configurationTable.hasAnyContent())
- ? new EntityKey(
- configurationTable.getFirstRowData().configurationNodeId,
- EntityType.CONFIGURATION_NODE)
- : null;
-
- actionBuilder
-
- .newAction(ActionDefinition.EXAM_CONFIGURATION_NEW)
- .withParentEntityKey(entityKey)
- .withExec(ExamToConfigBindingForm.bindFunction(this.pageService))
- .noEventPropagation()
- .publishIf(() -> modifyGrant && editable && !configurationTable.hasAnyContent())
-
- .newAction(ActionDefinition.EXAM_CONFIGURATION_EXAM_CONFIG_VIEW_PROP)
- .withParentEntityKey(entityKey)
- .withEntityKey(configMapKey)
- .publishIf(() -> modifyGrant && configurationTable.hasAnyContent())
-
- .newAction(ActionDefinition.EXAM_CONFIGURATION_DELETE_FROM_LIST)
- .withEntityKey(entityKey)
- .withSelect(
- getConfigMappingSelection(configurationTable),
- this::deleteExamConfigMapping,
- CONFIG_EMPTY_SELECTION_TEXT_KEY)
- .withConfirm(() -> {
- if (isExamRunning) {
- return CONFIRM_MESSAGE_REMOVE_CONFIG;
- }
- return null;
- })
- .publishIf(() -> modifyGrant && configurationTable.hasAnyContent() && editable)
-
- .newAction(ActionDefinition.EXAM_CONFIGURATION_EXPORT)
- .withParentEntityKey(entityKey)
- .withSelect(
- getConfigSelection(configurationTable),
- this::downloadExamConfigAction,
- CONFIG_EMPTY_SELECTION_TEXT_KEY)
- .noEventPropagation()
- .publishIf(() -> userGrantCheck.r() && configurationTable.hasAnyContent())
-
- .newAction(ActionDefinition.EXAM_CONFIGURATION_GET_CONFIG_KEY)
- .withSelect(
- getConfigSelection(configurationTable),
- this::getExamConfigKey,
- CONFIG_EMPTY_SELECTION_TEXT_KEY)
- .noEventPropagation()
- .publishIf(() -> userGrantCheck.r() && configurationTable.hasAnyContent());
-
- // List of Indicators
- this.widgetFactory.label(content, "");
- this.widgetFactory.labelLocalized(
- content,
- CustomVariant.TEXT_H3,
- INDICATOR_LIST_TITLE_KEY);
- this.widgetFactory.labelSeparator(content);
-
- final EntityTable indicatorTable =
- this.pageService.entityTableBuilder(this.restService.getRestCall(GetIndicatorPage.class))
- .withRestCallAdapter(builder -> builder.withQueryParam(
- Indicator.FILTER_ATTR_EXAM_ID,
- entityKey.modelId))
- .withEmptyMessage(INDICATOR_EMPTY_LIST_MESSAGE)
- .withMarkup()
- .withPaging(5)
- .hideNavigation()
- .withColumn(new ColumnDefinition<>(
- Domain.INDICATOR.ATTR_NAME,
- INDICATOR_NAME_COLUMN_KEY,
- Indicator::getName)
- .widthProportion(2))
- .withColumn(new ColumnDefinition<>(
- Domain.INDICATOR.ATTR_TYPE,
- INDICATOR_TYPE_COLUMN_KEY,
- this::indicatorTypeName)
- .widthProportion(1))
- .withColumn(new ColumnDefinition<>(
- Domain.THRESHOLD.REFERENCE_NAME,
- INDICATOR_THRESHOLD_COLUMN_KEY,
- ExamForm::thresholdsValue)
- .asMarkup()
- .widthProportion(4))
- .withDefaultActionIf(
- () -> modifyGrant,
- () -> actionBuilder
- .newAction(ActionDefinition.EXAM_INDICATOR_MODIFY_FROM_LIST)
- .withParentEntityKey(entityKey)
- .create())
-
- .compose(pageContext.copyOf(content));
-
- actionBuilder
-
- .newAction(ActionDefinition.EXAM_INDICATOR_NEW)
- .withParentEntityKey(entityKey)
- .publishIf(() -> modifyGrant)
-
- .newAction(ActionDefinition.EXAM_INDICATOR_MODIFY_FROM_LIST)
- .withParentEntityKey(entityKey)
- .withSelect(
- indicatorTable::getSelection,
- PageAction::applySingleSelectionAsEntityKey,
- INDICATOR_EMPTY_SELECTION_TEXT_KEY)
- .publishIf(() -> modifyGrant && indicatorTable.hasAnyContent())
-
- .newAction(ActionDefinition.EXAM_INDICATOR_DELETE_FROM_LIST)
- .withEntityKey(entityKey)
- .withSelect(
- indicatorTable::getSelection,
- this::deleteSelectedIndicator,
- INDICATOR_EMPTY_SELECTION_TEXT_KEY)
- .publishIf(() -> modifyGrant && indicatorTable.hasAnyContent());
- }
- }
-
- private PageAction importExam(
- final PageAction action,
- final FormHandle formHandle,
- final boolean applySebRestriction) {
-
- // process normal save first
- final PageAction processFormSave = formHandle.processFormSave(action);
-
- // when okay and the exam sebRestriction is true
- if (applySebRestriction) {
- ExamSebRestrictionSettings.setSebRestriction(
- processFormSave,
- true,
- this.restService,
- t -> log.error("Failed to intially restrict the course for SEB on LMS: {}", t.getMessage()));
- }
-
- return processFormSave;
- }
-
- private boolean testSebRestrictionAPI(final Exam exam) {
- return this.restService.getBuilder(GetLmsSetup.class)
- .withURIVariable(API.PARAM_MODEL_ID, String.valueOf(exam.lmsSetupId))
- .call()
- .onError(t -> log.error("Failed to check SEB restriction API: ", t))
- .map(lmsSetup -> lmsSetup.lmsType.features.contains(Features.SEB_RESTICTION))
- .getOr(false);
- }
-
- private void showConsistencyChecks(final Collection result, final Composite parent) {
- if (result == null || result.isEmpty()) {
- return;
- }
-
- final Composite warningPanel = this.widgetFactory.createWarningPanel(parent);
- this.widgetFactory.labelLocalized(
- warningPanel,
- CustomVariant.TITLE_LABEL,
- CONSISTENCY_MESSAGE_TITLE);
-
- result
- .stream()
- .map(message -> this.consistencyMessageMapping.get(message.messageCode))
- .filter(message -> message != null)
- .forEach(message -> this.widgetFactory.labelLocalized(
- warningPanel,
- CustomVariant.MESSAGE,
- message));
- }
-
- private PageAction viewExamConfigPageAction(final EntityTable table) {
-
- return this.pageService.pageActionBuilder(table.getPageContext()
- .clearEntityKeys()
- .removeAttribute(AttributeKeys.IMPORT_FROM_QUIZ_DATA))
- .newAction(ActionDefinition.EXAM_CONFIGURATION_EXAM_CONFIG_VIEW_PROP)
- .withSelectionSupplier(() -> {
- final ExamConfigurationMap selectedROWData = table.getSingleSelectedROWData();
- final HashSet result = new HashSet<>();
- if (selectedROWData != null) {
- result.add(new EntityKey(
- selectedROWData.configurationNodeId,
- EntityType.CONFIGURATION_NODE));
- }
- return result;
- })
- .create();
- }
-
- private PageAction downloadExamConfigAction(final PageAction action) {
- final UrlLauncher urlLauncher = RWT.getClient().getService(UrlLauncher.class);
- final EntityKey selection = action.getSingleSelection();
- if (selection != null) {
- final String downloadURL = this.downloadService.createDownloadURL(
- selection.modelId,
- action.pageContext().getParentEntityKey().modelId,
- SebExamConfigDownload.class,
- this.downloadFileName);
- urlLauncher.openURL(downloadURL);
- }
- return action;
- }
-
- private Supplier> getConfigMappingSelection(
- final EntityTable configurationTable) {
- return () -> {
- final ExamConfigurationMap firstRowData = configurationTable.getFirstRowData();
- if (firstRowData == null) {
- return Collections.emptySet();
- } else {
- return new HashSet<>(Arrays.asList(firstRowData.getEntityKey()));
- }
- };
- }
-
- private Supplier> getConfigSelection(final EntityTable configurationTable) {
- return () -> {
- final ExamConfigurationMap firstRowData = configurationTable.getFirstRowData();
- if (firstRowData == null) {
- return Collections.emptySet();
- } else {
- return new HashSet<>(Arrays.asList(new EntityKey(
- firstRowData.configurationNodeId,
- EntityType.CONFIGURATION_NODE)));
- }
- };
- }
-
- private PageAction deleteSelectedIndicator(final PageAction action) {
- final EntityKey indicatorKey = action.getSingleSelection();
- this.resourceService.getRestService()
- .getBuilder(DeleteIndicator.class)
- .withURIVariable(API.PARAM_MODEL_ID, indicatorKey.modelId)
- .call();
- return action;
- }
-
- private PageAction getExamConfigKey(final PageAction action) {
- final EntityKey examConfigMappingKey = action.getSingleSelection();
- if (examConfigMappingKey != null) {
- action.withEntityKey(examConfigMappingKey);
- return SebExamConfigPropForm
- .getConfigKeyFunction(this.pageService)
- .apply(action);
- }
-
- return action;
- }
-
- private PageAction deleteExamConfigMapping(final PageAction action) {
- final EntityKey examConfigMappingKey = action.getSingleSelection();
- this.resourceService.getRestService()
- .getBuilder(DeleteExamConfigMapping.class)
- .withURIVariable(API.PARAM_MODEL_ID, examConfigMappingKey.modelId)
- .call()
- .onError(error -> action.pageContext().notifyRemoveError(EntityType.EXAM_CONFIGURATION_MAP, error));
- return action;
- }
-
- private Result getExistingExam(final PageContext pageContext) {
- final EntityKey entityKey = pageContext.getEntityKey();
- return this.restService.getBuilder(GetExam.class)
- .withURIVariable(API.PARAM_MODEL_ID, entityKey.modelId)
- .call();
- }
-
- private Result createExamFromQuizData(final PageContext pageContext) {
- final EntityKey entityKey = pageContext.getEntityKey();
- final EntityKey parentEntityKey = pageContext.getParentEntityKey();
- return this.restService.getBuilder(GetQuizData.class)
- .withURIVariable(API.PARAM_MODEL_ID, entityKey.modelId)
- .withQueryParam(QuizData.QUIZ_ATTR_LMS_SETUP_ID, parentEntityKey.modelId)
- .call()
- .map(quizzData -> new Exam(quizzData))
- .onError(error -> pageContext.notifyLoadError(EntityType.EXAM, error));
- }
-
- private String indicatorTypeName(final Indicator indicator) {
- if (indicator.type == null) {
- return Constants.EMPTY_NOTE;
- }
-
- return this.resourceService.getI18nSupport()
- .getText(ResourceService.EXAM_INDICATOR_TYPE_PREFIX + indicator.type.name());
- }
-
- private static String thresholdsValue(final Indicator indicator) {
- if (indicator.thresholds.isEmpty()) {
- return Constants.EMPTY_NOTE;
- }
-
- final StringBuilder builder = indicator.thresholds
- .stream()
- .reduce(
- new StringBuilder(),
- (sb, threshold) -> sb
- .append("")
- .append(Indicator.getDisplayValue(indicator.type, threshold.value))
- .append(" (")
- .append(threshold.color)
- .append(")")
- .append("")
- .append(" | "),
- (sb1, sb2) -> sb1.append(sb2));
- builder.delete(builder.length() - 3, builder.length() - 1);
- return builder.toString();
- }
-
- private Function cancelModifyFunction() {
- final Function backToCurrentFunction = this.pageService.backToCurrentFunction();
- return action -> {
- final boolean importFromQuizData = BooleanUtils.toBoolean(
-
- action.pageContext().getAttribute(AttributeKeys.IMPORT_FROM_QUIZ_DATA));
- if (importFromQuizData) {
- final PageActionBuilder actionBuilder = this.pageService.pageActionBuilder(action.pageContext());
- final PageAction activityHomeAction = actionBuilder
- .newAction(ActionDefinition.QUIZ_DISCOVERY_VIEW_LIST)
- .create();
- this.pageService.firePageEvent(new ActionEvent(activityHomeAction), action.pageContext());
- return activityHomeAction;
- }
-
- return backToCurrentFunction.apply(action);
- };
- }
-
-}
+/*
+ * 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.content;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.function.BooleanSupplier;
+import java.util.function.Function;
+import java.util.function.Supplier;
+
+import org.apache.commons.lang3.BooleanUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.eclipse.rap.rwt.RWT;
+import org.eclipse.rap.rwt.client.service.UrlLauncher;
+import org.eclipse.swt.widgets.Composite;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Lazy;
+import org.springframework.stereotype.Component;
+
+import ch.ethz.seb.sebserver.gbl.Constants;
+import ch.ethz.seb.sebserver.gbl.api.API;
+import ch.ethz.seb.sebserver.gbl.api.APIMessage;
+import ch.ethz.seb.sebserver.gbl.api.EntityType;
+import ch.ethz.seb.sebserver.gbl.model.Domain;
+import ch.ethz.seb.sebserver.gbl.model.EntityKey;
+import ch.ethz.seb.sebserver.gbl.model.exam.Exam;
+import ch.ethz.seb.sebserver.gbl.model.exam.Exam.ExamStatus;
+import ch.ethz.seb.sebserver.gbl.model.exam.ExamConfigurationMap;
+import ch.ethz.seb.sebserver.gbl.model.exam.Indicator;
+import ch.ethz.seb.sebserver.gbl.model.exam.QuizData;
+import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetup.Features;
+import ch.ethz.seb.sebserver.gbl.model.user.UserRole;
+import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
+import ch.ethz.seb.sebserver.gbl.util.Result;
+import ch.ethz.seb.sebserver.gbl.util.Utils;
+import ch.ethz.seb.sebserver.gui.content.action.ActionDefinition;
+import ch.ethz.seb.sebserver.gui.form.FormBuilder;
+import ch.ethz.seb.sebserver.gui.form.FormHandle;
+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.PageContext;
+import ch.ethz.seb.sebserver.gui.service.page.PageContext.AttributeKeys;
+import ch.ethz.seb.sebserver.gui.service.page.PageService;
+import ch.ethz.seb.sebserver.gui.service.page.PageService.PageActionBuilder;
+import ch.ethz.seb.sebserver.gui.service.page.TemplateComposer;
+import ch.ethz.seb.sebserver.gui.service.page.event.ActionEvent;
+import ch.ethz.seb.sebserver.gui.service.page.impl.PageAction;
+import ch.ethz.seb.sebserver.gui.service.remote.download.DownloadService;
+import ch.ethz.seb.sebserver.gui.service.remote.download.SebExamConfigDownload;
+import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestService;
+import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.CheckExamConsistency;
+import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.DeleteExamConfigMapping;
+import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.DeleteIndicator;
+import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.GetExam;
+import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.GetExamConfigMappingsPage;
+import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.GetIndicatorPage;
+import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.SaveExam;
+import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.lmssetup.GetLmsSetup;
+import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.quiz.GetQuizData;
+import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.quiz.ImportAsExam;
+import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.CurrentUser;
+import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.CurrentUser.EntityGrantCheck;
+import ch.ethz.seb.sebserver.gui.table.ColumnDefinition;
+import ch.ethz.seb.sebserver.gui.table.EntityTable;
+import ch.ethz.seb.sebserver.gui.widget.WidgetFactory;
+import ch.ethz.seb.sebserver.gui.widget.WidgetFactory.CustomVariant;
+
+@Lazy
+@Component
+@GuiProfile
+public class ExamForm implements TemplateComposer {
+
+ private static final Logger log = LoggerFactory.getLogger(ExamForm.class);
+
+ public static final LocTextKey EXAM_FORM_TITLE_KEY =
+ new LocTextKey("sebserver.exam.form.title");
+ public static final LocTextKey EXAM_FORM_TITLE_IMPORT_KEY =
+ new LocTextKey("sebserver.exam.form.title.import");
+ private static final LocTextKey CONFIG_EMPTY_LIST_MESSAGE =
+ new LocTextKey("sebserver.exam.configuration.list.empty");
+ private static final LocTextKey INDICATOR_EMPTY_LIST_MESSAGE =
+ new LocTextKey("sebserver.exam.indicator.list.empty");
+ private static final LocTextKey FORM_SUPPORTER_TEXT_KEY =
+ new LocTextKey("sebserver.exam.form.supporter");
+ private static final LocTextKey FORM_STATUS_TEXT_KEY =
+ new LocTextKey("sebserver.exam.form.status");
+ private static final LocTextKey FORM_TYPE_TEXT_KEY =
+ new LocTextKey("sebserver.exam.form.type");
+ private static final LocTextKey FORM_ENDTIME_TEXT_KEY =
+ new LocTextKey("sebserver.exam.form.endtime");
+ private static final LocTextKey FORM_STARTTIME_TEXT_KEY =
+ new LocTextKey("sebserver.exam.form.starttime");
+ private static final LocTextKey FORM_DESCRIPTION_TEXT_KEY =
+ new LocTextKey("sebserver.exam.form.description");
+ private static final LocTextKey FORM_NAME_TEXT_KEY =
+ new LocTextKey("sebserver.exam.form.name");
+ private static final LocTextKey FORM_QUIZID_TEXT_KEY =
+ new LocTextKey("sebserver.exam.form.quizid");
+ private static final LocTextKey FORM_QUIZ_URL_TEXT_KEY =
+ new LocTextKey("sebserver.exam.form.quizurl");
+ private static final LocTextKey FORM_LMSSETUP_TEXT_KEY =
+ new LocTextKey("sebserver.exam.form.lmssetup");
+
+ private final static LocTextKey CONFIG_LIST_TITLE_KEY =
+ new LocTextKey("sebserver.exam.configuration.list.title");
+ private final static LocTextKey CONFIG_NAME_COLUMN_KEY =
+ new LocTextKey("sebserver.exam.configuration.list.column.name");
+ private final static LocTextKey CONFIG_DESCRIPTION_COLUMN_KEY =
+ new LocTextKey("sebserver.exam.configuration.list.column.description");
+ private final static LocTextKey CONFIG_STATUS_COLUMN_KEY =
+ new LocTextKey("sebserver.exam.configuration.list.column.status");
+ private final static LocTextKey CONFIG_EMPTY_SELECTION_TEXT_KEY =
+ new LocTextKey("sebserver.exam.configuration.list.pleaseSelect");
+
+ private final static LocTextKey INDICATOR_LIST_TITLE_KEY =
+ new LocTextKey("sebserver.exam.indicator.list.title");
+ private final static LocTextKey INDICATOR_TYPE_COLUMN_KEY =
+ new LocTextKey("sebserver.exam.indicator.list.column.type");
+ private final static LocTextKey INDICATOR_NAME_COLUMN_KEY =
+ new LocTextKey("sebserver.exam.indicator.list.column.name");
+ private final static LocTextKey INDICATOR_THRESHOLD_COLUMN_KEY =
+ new LocTextKey("sebserver.exam.indicator.list.column.thresholds");
+ private final static LocTextKey INDICATOR_EMPTY_SELECTION_TEXT_KEY =
+ new LocTextKey("sebserver.exam.indicator.list.pleaseSelect");
+
+ private final static LocTextKey CONSISTENCY_MESSAGE_TITLE =
+ new LocTextKey("sebserver.exam.consistency.title");
+ private final static LocTextKey CONSISTENCY_MESSAGE_MISSING_SUPPORTER =
+ new LocTextKey("sebserver.exam.consistency.missing-supporter");
+ private final static LocTextKey CONSISTENCY_MESSAGE_MISSING_INDICATOR =
+ new LocTextKey("sebserver.exam.consistency.missing-indicator");
+ private final static LocTextKey CONSISTENCY_MESSAGE_MISSING_CONFIG =
+ new LocTextKey("sebserver.exam.consistency.missing-config");
+ private final static LocTextKey CONSISTENCY_MESSAGE_MISSING_SEB_RESTRICTION =
+ new LocTextKey("sebserver.exam.consistency.missing-seb-restriction");
+
+ private final Map consistencyMessageMapping;
+
+ private final static LocTextKey CONFIRM_MESSAGE_REMOVE_CONFIG =
+ new LocTextKey("sebserver.exam.confirm.remove-config");
+
+ private final PageService pageService;
+ private final ResourceService resourceService;
+ private final DownloadService downloadService;
+ private final String downloadFileName;
+ private final WidgetFactory widgetFactory;
+ private final RestService restService;
+
+ protected ExamForm(
+ final PageService pageService,
+ final ResourceService resourceService,
+ final DownloadService downloadService,
+ @Value("${sebserver.gui.seb.exam.config.download.filename}") final String downloadFileName) {
+
+ this.pageService = pageService;
+ this.resourceService = resourceService;
+ this.downloadService = downloadService;
+ this.downloadFileName = downloadFileName;
+ this.widgetFactory = pageService.getWidgetFactory();
+ this.restService = this.resourceService.getRestService();
+
+ this.consistencyMessageMapping = new HashMap<>();
+ this.consistencyMessageMapping.put(
+ APIMessage.ErrorMessage.EXAM_CONSISTANCY_VALIDATION_SUPPORTER.messageCode,
+ CONSISTENCY_MESSAGE_MISSING_SUPPORTER);
+ this.consistencyMessageMapping.put(
+ APIMessage.ErrorMessage.EXAM_CONSISTANCY_VALIDATION_INDICATOR.messageCode,
+ CONSISTENCY_MESSAGE_MISSING_INDICATOR);
+ this.consistencyMessageMapping.put(
+ APIMessage.ErrorMessage.EXAM_CONSISTANCY_VALIDATION_CONFIG.messageCode,
+ CONSISTENCY_MESSAGE_MISSING_CONFIG);
+ this.consistencyMessageMapping.put(
+ APIMessage.ErrorMessage.EXAM_CONSISTANCY_VALIDATION_SEB_RESTRICTION.messageCode,
+ CONSISTENCY_MESSAGE_MISSING_SEB_RESTRICTION);
+ }
+
+ @Override
+ public void compose(final PageContext pageContext) {
+ final CurrentUser currentUser = this.resourceService.getCurrentUser();
+
+ final I18nSupport i18nSupport = this.resourceService.getI18nSupport();
+ final EntityKey entityKey = pageContext.getEntityKey();
+ final boolean readonly = pageContext.isReadonly();
+ final boolean importFromQuizData = BooleanUtils.toBoolean(
+ pageContext.getAttribute(AttributeKeys.IMPORT_FROM_QUIZ_DATA));
+
+ // get or create model data
+ final Exam exam = (importFromQuizData
+ ? createExamFromQuizData(pageContext)
+ : getExistingExam(pageContext))
+ .onError(error -> pageContext.notifyLoadError(EntityType.EXAM, error))
+ .getOrThrow();
+
+ // new PageContext with actual EntityKey
+ final PageContext formContext = pageContext.withEntityKey(exam.getEntityKey());
+
+ // check exam consistency and inform the user if needed
+ if (readonly) {
+ this.restService.getBuilder(CheckExamConsistency.class)
+ .withURIVariable(API.PARAM_MODEL_ID, entityKey.modelId)
+ .call()
+ .ifPresent(result -> showConsistencyChecks(result, formContext.getParent()));
+ }
+
+ // the default page layout with title
+ final LocTextKey titleKey = importFromQuizData
+ ? EXAM_FORM_TITLE_IMPORT_KEY
+ : EXAM_FORM_TITLE_KEY;
+ final Composite content = this.widgetFactory.defaultPageLayout(
+ formContext.getParent(),
+ titleKey);
+
+ final BooleanSupplier isNew = () -> importFromQuizData;
+ final BooleanSupplier isNotNew = () -> !isNew.getAsBoolean();
+ final EntityGrantCheck userGrantCheck = currentUser.entityGrantCheck(exam);
+ final boolean modifyGrant = userGrantCheck.m();
+ final ExamStatus examStatus = exam.getStatus();
+ final boolean isExamRunning = examStatus == ExamStatus.RUNNING;
+ final boolean editable = examStatus == ExamStatus.UP_COMING
+ || examStatus == ExamStatus.RUNNING
+ && currentUser.get().hasRole(UserRole.EXAM_ADMIN);
+ final boolean sebRestrictionAvailable = testSebRestrictionAPI(exam);
+
+ // The Exam form
+ final FormHandle formHandle = this.pageService.formBuilder(
+ formContext.copyOf(content), 8)
+ .withDefaultSpanLabel(1)
+ .withDefaultSpanInput(4)
+ .withDefaultSpanEmptyCell(3)
+ .readonly(readonly)
+ .putStaticValueIf(isNotNew,
+ Domain.EXAM.ATTR_ID,
+ exam.getModelId())
+ .putStaticValue(
+ Domain.EXAM.ATTR_INSTITUTION_ID,
+ String.valueOf(exam.getInstitutionId()))
+ .putStaticValueIf(isNotNew,
+ Domain.EXAM.ATTR_LMS_SETUP_ID,
+ String.valueOf(exam.lmsSetupId))
+ .putStaticValueIf(isNew,
+ QuizData.QUIZ_ATTR_LMS_SETUP_ID,
+ String.valueOf(exam.lmsSetupId))
+ .putStaticValueIf(isNotNew,
+ Domain.EXAM.ATTR_EXTERNAL_ID,
+ exam.externalId)
+ .putStaticValueIf(isNew,
+ QuizData.QUIZ_ATTR_ID,
+ exam.externalId)
+
+ .addField(FormBuilder.text(
+ QuizData.QUIZ_ATTR_NAME,
+ FORM_NAME_TEXT_KEY,
+ exam.name)
+ .readonly(true)
+ .withInputSpan(3)
+ .withEmptyCellSeparation(false))
+
+ .addField(FormBuilder.singleSelection(
+ Domain.EXAM.ATTR_LMS_SETUP_ID,
+ FORM_LMSSETUP_TEXT_KEY,
+ String.valueOf(exam.lmsSetupId),
+ this.resourceService::lmsSetupResource)
+ .readonly(true)
+ .withInputSpan(3)
+ .withEmptyCellSeparation(false))
+
+ .addField(FormBuilder.text(
+ QuizData.QUIZ_ATTR_START_TIME,
+ FORM_STARTTIME_TEXT_KEY,
+ i18nSupport.formatDisplayDateWithTimeZone(exam.startTime))
+ .readonly(true)
+ .withInputSpan(3)
+ .withEmptyCellSeparation(false))
+ .addField(FormBuilder.text(
+ QuizData.QUIZ_ATTR_END_TIME,
+ FORM_ENDTIME_TEXT_KEY,
+ i18nSupport.formatDisplayDateWithTimeZone(exam.endTime))
+ .readonly(true)
+ .withInputSpan(3)
+ .withEmptyCellSeparation(false))
+
+ .addField(FormBuilder.text(
+ Domain.EXAM.ATTR_EXTERNAL_ID,
+ FORM_QUIZID_TEXT_KEY,
+ exam.externalId)
+ .readonly(true)
+ .withEmptyCellSeparation(false))
+ .addField(FormBuilder.text(
+ QuizData.QUIZ_ATTR_START_URL,
+ FORM_QUIZ_URL_TEXT_KEY,
+ exam.startURL)
+ .readonly(true)
+ .withInputSpan(7))
+
+ .addField(FormBuilder.text(
+ QuizData.QUIZ_ATTR_DESCRIPTION,
+ FORM_DESCRIPTION_TEXT_KEY,
+ exam.description)
+ .asHTML()
+ .readonly(true)
+ .withInputSpan(6)
+ .withEmptyCellSeparation(false))
+
+ .addField(FormBuilder.text(
+ Domain.EXAM.ATTR_STATUS + "_display",
+ FORM_STATUS_TEXT_KEY,
+ i18nSupport.getText(new LocTextKey("sebserver.exam.status." + examStatus.name())))
+ .readonly(true)
+ .withLabelSpan(2)
+ .withInputSpan(4)
+ .withEmptyCellSpan(1))
+ .addField(FormBuilder.singleSelection(
+ Domain.EXAM.ATTR_TYPE,
+ FORM_TYPE_TEXT_KEY,
+ String.valueOf(exam.type),
+ this.resourceService::examTypeResources)
+ .withLabelSpan(2)
+ .withInputSpan(4)
+ .withEmptyCellSpan(2))
+
+ .addField(FormBuilder.multiComboSelection(
+ Domain.EXAM.ATTR_SUPPORTER,
+ FORM_SUPPORTER_TEXT_KEY,
+ StringUtils.join(exam.supporter, Constants.LIST_SEPARATOR_CHAR),
+ this.resourceService::examSupporterResources)
+ .withLabelSpan(2)
+ .withInputSpan(4)
+ .withEmptyCellSpan(2))
+
+ .buildFor(importFromQuizData
+ ? this.restService.getRestCall(ImportAsExam.class)
+ : this.restService.getRestCall(SaveExam.class));
+
+ final PageActionBuilder actionBuilder = this.pageService.pageActionBuilder(formContext
+ .clearEntityKeys()
+ .removeAttribute(AttributeKeys.IMPORT_FROM_QUIZ_DATA));
+ // propagate content actions to action-pane
+ actionBuilder
+
+ .newAction(ActionDefinition.EXAM_MODIFY)
+ .withEntityKey(entityKey)
+ .publishIf(() -> modifyGrant && readonly && editable)
+
+ .newAction(ActionDefinition.EXAM_SAVE)
+ .withExec(action -> (importFromQuizData)
+ ? importExam(action, formHandle, sebRestrictionAvailable && exam.status == ExamStatus.RUNNING)
+ : formHandle.processFormSave(action))
+ .ignoreMoveAwayFromEdit()
+ .publishIf(() -> !readonly && modifyGrant)
+
+ .newAction(ActionDefinition.EXAM_CANCEL_MODIFY)
+ .withEntityKey(entityKey)
+ .withAttribute(AttributeKeys.IMPORT_FROM_QUIZ_DATA, String.valueOf(importFromQuizData))
+ .withExec(this.cancelModifyFunction())
+ .publishIf(() -> !readonly)
+
+ .newAction(ActionDefinition.EXAM_MODIFY_SEB_RESTRICTION_DETAILS)
+ .withEntityKey(entityKey)
+ .withExec(ExamSebRestrictionSettings.settingsFunction(this.pageService))
+ .withAttribute(
+ ExamSebRestrictionSettings.PAGE_CONTEXT_ATTR_LMS_TYPE,
+ this.restService.getBuilder(GetLmsSetup.class)
+ .withURIVariable(API.PARAM_MODEL_ID, String.valueOf(exam.lmsSetupId))
+ .call()
+ .getOrThrow().lmsType.name())
+ .noEventPropagation()
+ .publishIf(() -> sebRestrictionAvailable && readonly)
+
+ .newAction(ActionDefinition.EXAM_ENABLE_SEB_RESTRICTION)
+ .withEntityKey(entityKey)
+ .withExec(action -> ExamSebRestrictionSettings.setSebRestriction(action, true, this.restService))
+ .publishIf(() -> sebRestrictionAvailable && readonly && BooleanUtils.isFalse(exam.lmsSebRestriction))
+
+ .newAction(ActionDefinition.EXAM_DISABLE_SEB_RESTRICTION)
+ .withEntityKey(entityKey)
+ .withExec(action -> ExamSebRestrictionSettings.setSebRestriction(action, false, this.restService))
+ .publishIf(() -> sebRestrictionAvailable && readonly && BooleanUtils.isTrue(exam.lmsSebRestriction));
+
+ // additional data in read-only view
+ if (readonly && !importFromQuizData) {
+
+ // List of SEB Configuration
+ this.widgetFactory.label(content, StringUtils.EMPTY);
+ this.widgetFactory.labelLocalized(
+ content,
+ CustomVariant.TEXT_H3,
+ CONFIG_LIST_TITLE_KEY);
+ this.widgetFactory.labelSeparator(content);
+
+ final EntityTable configurationTable =
+ this.pageService.entityTableBuilder(this.restService.getRestCall(GetExamConfigMappingsPage.class))
+ .withRestCallAdapter(builder -> builder.withQueryParam(
+ ExamConfigurationMap.FILTER_ATTR_EXAM_ID,
+ entityKey.modelId))
+ .withEmptyMessage(CONFIG_EMPTY_LIST_MESSAGE)
+ .withPaging(1)
+ .hideNavigation()
+ .withColumn(new ColumnDefinition<>(
+ Domain.CONFIGURATION_NODE.ATTR_NAME,
+ CONFIG_NAME_COLUMN_KEY,
+ ExamConfigurationMap::getConfigName)
+ .widthProportion(2))
+ .withColumn(new ColumnDefinition<>(
+ Domain.CONFIGURATION_NODE.ATTR_DESCRIPTION,
+ CONFIG_DESCRIPTION_COLUMN_KEY,
+ ExamConfigurationMap::getConfigDescription)
+ .widthProportion(4))
+ .withColumn(new ColumnDefinition(
+ Domain.CONFIGURATION_NODE.ATTR_STATUS,
+ CONFIG_STATUS_COLUMN_KEY,
+ this.resourceService::localizedExamConfigStatusName)
+ .widthProportion(1))
+ .withDefaultActionIf(
+ () -> modifyGrant,
+ this::viewExamConfigPageAction)
+
+ .compose(pageContext.copyOf(content));
+
+ final EntityKey configMapKey = (configurationTable.hasAnyContent())
+ ? new EntityKey(
+ configurationTable.getFirstRowData().configurationNodeId,
+ EntityType.CONFIGURATION_NODE)
+ : null;
+
+ actionBuilder
+
+ .newAction(ActionDefinition.EXAM_CONFIGURATION_NEW)
+ .withParentEntityKey(entityKey)
+ .withExec(ExamToConfigBindingForm.bindFunction(this.pageService))
+ .noEventPropagation()
+ .publishIf(() -> modifyGrant && editable && !configurationTable.hasAnyContent())
+
+ .newAction(ActionDefinition.EXAM_CONFIGURATION_EXAM_CONFIG_VIEW_PROP)
+ .withParentEntityKey(entityKey)
+ .withEntityKey(configMapKey)
+ .publishIf(() -> modifyGrant && configurationTable.hasAnyContent())
+
+ .newAction(ActionDefinition.EXAM_CONFIGURATION_DELETE_FROM_LIST)
+ .withEntityKey(entityKey)
+ .withSelect(
+ getConfigMappingSelection(configurationTable),
+ this::deleteExamConfigMapping,
+ CONFIG_EMPTY_SELECTION_TEXT_KEY)
+ .withConfirm(() -> {
+ if (isExamRunning) {
+ return CONFIRM_MESSAGE_REMOVE_CONFIG;
+ }
+ return null;
+ })
+ .publishIf(() -> modifyGrant && configurationTable.hasAnyContent() && editable)
+
+ .newAction(ActionDefinition.EXAM_CONFIGURATION_EXPORT)
+ .withParentEntityKey(entityKey)
+ .withSelect(
+ getConfigSelection(configurationTable),
+ this::downloadExamConfigAction,
+ CONFIG_EMPTY_SELECTION_TEXT_KEY)
+ .noEventPropagation()
+ .publishIf(() -> userGrantCheck.r() && configurationTable.hasAnyContent())
+
+ .newAction(ActionDefinition.EXAM_CONFIGURATION_GET_CONFIG_KEY)
+ .withSelect(
+ getConfigSelection(configurationTable),
+ this::getExamConfigKey,
+ CONFIG_EMPTY_SELECTION_TEXT_KEY)
+ .noEventPropagation()
+ .publishIf(() -> userGrantCheck.r() && configurationTable.hasAnyContent());
+
+ // List of Indicators
+ this.widgetFactory.label(content, "");
+ this.widgetFactory.labelLocalized(
+ content,
+ CustomVariant.TEXT_H3,
+ INDICATOR_LIST_TITLE_KEY);
+ this.widgetFactory.labelSeparator(content);
+
+ final EntityTable indicatorTable =
+ this.pageService.entityTableBuilder(this.restService.getRestCall(GetIndicatorPage.class))
+ .withRestCallAdapter(builder -> builder.withQueryParam(
+ Indicator.FILTER_ATTR_EXAM_ID,
+ entityKey.modelId))
+ .withEmptyMessage(INDICATOR_EMPTY_LIST_MESSAGE)
+ .withMarkup()
+ .withPaging(5)
+ .hideNavigation()
+ .withColumn(new ColumnDefinition<>(
+ Domain.INDICATOR.ATTR_NAME,
+ INDICATOR_NAME_COLUMN_KEY,
+ Indicator::getName)
+ .widthProportion(2))
+ .withColumn(new ColumnDefinition<>(
+ Domain.INDICATOR.ATTR_TYPE,
+ INDICATOR_TYPE_COLUMN_KEY,
+ this::indicatorTypeName)
+ .widthProportion(1))
+ .withColumn(new ColumnDefinition<>(
+ Domain.THRESHOLD.REFERENCE_NAME,
+ INDICATOR_THRESHOLD_COLUMN_KEY,
+ ExamForm::thresholdsValue)
+ .asMarkup()
+ .widthProportion(4))
+ .withDefaultActionIf(
+ () -> modifyGrant,
+ () -> actionBuilder
+ .newAction(ActionDefinition.EXAM_INDICATOR_MODIFY_FROM_LIST)
+ .withParentEntityKey(entityKey)
+ .create())
+
+ .compose(pageContext.copyOf(content));
+
+ actionBuilder
+
+ .newAction(ActionDefinition.EXAM_INDICATOR_NEW)
+ .withParentEntityKey(entityKey)
+ .publishIf(() -> modifyGrant)
+
+ .newAction(ActionDefinition.EXAM_INDICATOR_MODIFY_FROM_LIST)
+ .withParentEntityKey(entityKey)
+ .withSelect(
+ indicatorTable::getSelection,
+ PageAction::applySingleSelectionAsEntityKey,
+ INDICATOR_EMPTY_SELECTION_TEXT_KEY)
+ .publishIf(() -> modifyGrant && indicatorTable.hasAnyContent())
+
+ .newAction(ActionDefinition.EXAM_INDICATOR_DELETE_FROM_LIST)
+ .withEntityKey(entityKey)
+ .withSelect(
+ indicatorTable::getSelection,
+ this::deleteSelectedIndicator,
+ INDICATOR_EMPTY_SELECTION_TEXT_KEY)
+ .publishIf(() -> modifyGrant && indicatorTable.hasAnyContent());
+ }
+ }
+
+ private PageAction importExam(
+ final PageAction action,
+ final FormHandle formHandle,
+ final boolean applySebRestriction) {
+
+ // process normal save first
+ final PageAction processFormSave = formHandle.processFormSave(action);
+
+ // when okay and the exam sebRestriction is true
+ if (applySebRestriction) {
+ ExamSebRestrictionSettings.setSebRestriction(
+ processFormSave,
+ true,
+ this.restService,
+ t -> log.error("Failed to intially restrict the course for SEB on LMS: {}", t.getMessage()));
+ }
+
+ return processFormSave;
+ }
+
+ private boolean testSebRestrictionAPI(final Exam exam) {
+ return this.restService.getBuilder(GetLmsSetup.class)
+ .withURIVariable(API.PARAM_MODEL_ID, String.valueOf(exam.lmsSetupId))
+ .call()
+ .onError(t -> log.error("Failed to check SEB restriction API: ", t))
+ .map(lmsSetup -> lmsSetup.lmsType.features.contains(Features.SEB_RESTICTION))
+ .getOr(false);
+ }
+
+ private void showConsistencyChecks(final Collection result, final Composite parent) {
+ if (result == null || result.isEmpty()) {
+ return;
+ }
+
+ final Composite warningPanel = this.widgetFactory.createWarningPanel(parent);
+ this.widgetFactory.labelLocalized(
+ warningPanel,
+ CustomVariant.TITLE_LABEL,
+ CONSISTENCY_MESSAGE_TITLE);
+
+ result
+ .stream()
+ .map(message -> this.consistencyMessageMapping.get(message.messageCode))
+ .filter(message -> message != null)
+ .forEach(message -> this.widgetFactory.labelLocalized(
+ warningPanel,
+ CustomVariant.MESSAGE,
+ message));
+ }
+
+ private PageAction viewExamConfigPageAction(final EntityTable table) {
+
+ return this.pageService.pageActionBuilder(table.getPageContext()
+ .clearEntityKeys()
+ .removeAttribute(AttributeKeys.IMPORT_FROM_QUIZ_DATA))
+ .newAction(ActionDefinition.EXAM_CONFIGURATION_EXAM_CONFIG_VIEW_PROP)
+ .withSelectionSupplier(() -> {
+ final ExamConfigurationMap selectedROWData = table.getSingleSelectedROWData();
+ final HashSet result = new HashSet<>();
+ if (selectedROWData != null) {
+ result.add(new EntityKey(
+ selectedROWData.configurationNodeId,
+ EntityType.CONFIGURATION_NODE));
+ }
+ return result;
+ })
+ .create();
+ }
+
+ private PageAction downloadExamConfigAction(final PageAction action) {
+ final UrlLauncher urlLauncher = RWT.getClient().getService(UrlLauncher.class);
+ final EntityKey selection = action.getSingleSelection();
+ if (selection != null) {
+ final String downloadURL = this.downloadService.createDownloadURL(
+ selection.modelId,
+ action.pageContext().getParentEntityKey().modelId,
+ SebExamConfigDownload.class,
+ this.downloadFileName);
+ urlLauncher.openURL(downloadURL);
+ }
+ return action;
+ }
+
+ private Supplier> getConfigMappingSelection(
+ final EntityTable configurationTable) {
+ return () -> {
+ final ExamConfigurationMap firstRowData = configurationTable.getFirstRowData();
+ if (firstRowData == null) {
+ return Collections.emptySet();
+ } else {
+ return new HashSet<>(Arrays.asList(firstRowData.getEntityKey()));
+ }
+ };
+ }
+
+ private Supplier> getConfigSelection(final EntityTable configurationTable) {
+ return () -> {
+ final ExamConfigurationMap firstRowData = configurationTable.getFirstRowData();
+ if (firstRowData == null) {
+ return Collections.emptySet();
+ } else {
+ return new HashSet<>(Arrays.asList(new EntityKey(
+ firstRowData.configurationNodeId,
+ EntityType.CONFIGURATION_NODE)));
+ }
+ };
+ }
+
+ private PageAction deleteSelectedIndicator(final PageAction action) {
+ final EntityKey indicatorKey = action.getSingleSelection();
+ this.resourceService.getRestService()
+ .getBuilder(DeleteIndicator.class)
+ .withURIVariable(API.PARAM_MODEL_ID, indicatorKey.modelId)
+ .call();
+ return action;
+ }
+
+ private PageAction getExamConfigKey(final PageAction action) {
+ final EntityKey examConfigMappingKey = action.getSingleSelection();
+ if (examConfigMappingKey != null) {
+ action.withEntityKey(examConfigMappingKey);
+ return SebExamConfigPropForm
+ .getConfigKeyFunction(this.pageService)
+ .apply(action);
+ }
+
+ return action;
+ }
+
+ private PageAction deleteExamConfigMapping(final PageAction action) {
+ final EntityKey examConfigMappingKey = action.getSingleSelection();
+ this.resourceService.getRestService()
+ .getBuilder(DeleteExamConfigMapping.class)
+ .withURIVariable(API.PARAM_MODEL_ID, examConfigMappingKey.modelId)
+ .call()
+ .onError(error -> action.pageContext().notifyRemoveError(EntityType.EXAM_CONFIGURATION_MAP, error));
+ return action;
+ }
+
+ private Result getExistingExam(final PageContext pageContext) {
+ final EntityKey entityKey = pageContext.getEntityKey();
+ return this.restService.getBuilder(GetExam.class)
+ .withURIVariable(API.PARAM_MODEL_ID, entityKey.modelId)
+ .call();
+ }
+
+ private Result createExamFromQuizData(final PageContext pageContext) {
+ final EntityKey entityKey = pageContext.getEntityKey();
+ final EntityKey parentEntityKey = pageContext.getParentEntityKey();
+ return this.restService.getBuilder(GetQuizData.class)
+ .withURIVariable(API.PARAM_MODEL_ID, entityKey.modelId)
+ .withQueryParam(QuizData.QUIZ_ATTR_LMS_SETUP_ID, parentEntityKey.modelId)
+ .call()
+ .map(quizzData -> new Exam(quizzData))
+ .onError(error -> pageContext.notifyLoadError(EntityType.EXAM, error));
+ }
+
+ private String indicatorTypeName(final Indicator indicator) {
+ if (indicator.type == null) {
+ return Constants.EMPTY_NOTE;
+ }
+
+ return this.resourceService.getI18nSupport()
+ .getText(ResourceService.EXAM_INDICATOR_TYPE_PREFIX + indicator.type.name());
+ }
+
+ private static String thresholdsValue(final Indicator indicator) {
+ if (indicator.thresholds.isEmpty()) {
+ return Constants.EMPTY_NOTE;
+ }
+
+ final StringBuilder builder = indicator.thresholds
+ .stream()
+ .reduce(
+ new StringBuilder(),
+ (sb, threshold) -> sb
+ .append("")
+ .append(Indicator.getDisplayValue(indicator.type, threshold.value))
+ .append(" (")
+ .append(threshold.color)
+ .append(")")
+ .append("")
+ .append(" | "),
+ (sb1, sb2) -> sb1.append(sb2));
+ builder.delete(builder.length() - 3, builder.length() - 1);
+ return builder.toString();
+ }
+
+ private Function cancelModifyFunction() {
+ final Function backToCurrentFunction = this.pageService.backToCurrentFunction();
+ return action -> {
+ final boolean importFromQuizData = BooleanUtils.toBoolean(
+
+ action.pageContext().getAttribute(AttributeKeys.IMPORT_FROM_QUIZ_DATA));
+ if (importFromQuizData) {
+ final PageActionBuilder actionBuilder = this.pageService.pageActionBuilder(action.pageContext());
+ final PageAction activityHomeAction = actionBuilder
+ .newAction(ActionDefinition.QUIZ_DISCOVERY_VIEW_LIST)
+ .create();
+ this.pageService.firePageEvent(new ActionEvent(activityHomeAction), action.pageContext());
+ return activityHomeAction;
+ }
+
+ return backToCurrentFunction.apply(action);
+ };
+ }
+
+}
diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/content/InstitutionForm.java b/src/main/java/ch/ethz/seb/sebserver/gui/content/InstitutionForm.java
index ff4412e7..2fd79940 100644
--- a/src/main/java/ch/ethz/seb/sebserver/gui/content/InstitutionForm.java
+++ b/src/main/java/ch/ethz/seb/sebserver/gui/content/InstitutionForm.java
@@ -1,172 +1,167 @@
-/*
- * 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.content;
-
-import org.eclipse.swt.widgets.Composite;
-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.EntityType;
-import ch.ethz.seb.sebserver.gbl.model.Domain;
-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.content.action.ActionDefinition;
-import ch.ethz.seb.sebserver.gui.form.FormBuilder;
-import ch.ethz.seb.sebserver.gui.form.FormHandle;
-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.PageService;
-import ch.ethz.seb.sebserver.gui.service.page.TemplateComposer;
-import ch.ethz.seb.sebserver.gui.service.page.impl.DefaultPageLayout;
-import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestService;
-import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.institution.ActivateInstitution;
-import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.institution.DeactivateInstitution;
-import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.institution.GetInstitution;
-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;
-import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.CurrentUser.EntityGrantCheck;
-import ch.ethz.seb.sebserver.gui.widget.WidgetFactory;
-
-@Lazy
-@Component
-@GuiProfile
-public class InstitutionForm implements TemplateComposer {
-
- private static final LocTextKey TITLE_TEXT_KEY =
- new LocTextKey("sebserver.institution.form.title");
- private static final LocTextKey NEW_TITLE_TEXT_KEY =
- new LocTextKey("sebserver.institution.form.title.new");
-
- private static final LocTextKey FORM_LOGO_IMAGE_TEXT_KEY =
- new LocTextKey("sebserver.institution.form.logoImage");
- private static final LocTextKey FORM_URL_SUFFIX_TEXT_KEY =
- new LocTextKey("sebserver.institution.form.urlSuffix");
- private static final LocTextKey FORM_NAME_TEXT_KEY =
- new LocTextKey("sebserver.institution.form.name");
-
- private final PageService pageService;
- private final RestService restService;
- private final CurrentUser currentUser;
-
- protected InstitutionForm(
- final PageService pageService,
- final RestService restService,
- final CurrentUser currentUser) {
-
- this.pageService = pageService;
- this.restService = restService;
- this.currentUser = currentUser;
- }
-
- @Override
- public void compose(final PageContext pageContext) {
-
- final WidgetFactory widgetFactory = this.pageService.getWidgetFactory();
- final EntityKey entityKey = pageContext.getEntityKey();
- final boolean isNew = entityKey == null;
- // get data or create new. Handle error if happen
- final Institution institution = (isNew)
- ? Institution.createNew()
- : this.restService
- .getBuilder(GetInstitution.class)
- .withURIVariable(API.PARAM_MODEL_ID, entityKey.modelId)
- .call()
- .onError(error -> pageContext.notifyLoadError(EntityType.INSTITUTION, error))
- .getOrThrow();
-
- final EntityGrantCheck instGrant = this.currentUser.entityGrantCheck(institution);
- final boolean writeGrant = instGrant.w();
- final boolean modifyGrant = instGrant.m();
- final boolean isReadonly = pageContext.isReadonly();
-
- // new PageContext with actual EntityKey
- final PageContext formContext = pageContext.withEntityKey(institution.getEntityKey());
-
- // the default page layout with interactive title
- final LocTextKey titleKey = isNew
- ? NEW_TITLE_TEXT_KEY
- : TITLE_TEXT_KEY;
- final Composite content = widgetFactory.defaultPageLayout(
- formContext.getParent(),
- titleKey);
-
- // The Institution form
- final FormHandle formHandle = this.pageService.formBuilder(
- formContext.copyOf(content))
- .readonly(isReadonly)
- .putStaticValueIf(() -> !isNew,
- Domain.INSTITUTION.ATTR_ID,
- institution.getModelId())
- .addField(FormBuilder.text(
- Domain.INSTITUTION.ATTR_NAME,
- FORM_NAME_TEXT_KEY,
- institution.name)
- .mandatory(!isReadonly))
- .addField(FormBuilder.text(
- Domain.INSTITUTION.ATTR_URL_SUFFIX,
- FORM_URL_SUFFIX_TEXT_KEY,
- institution.urlSuffix))
- .addField(FormBuilder.imageUpload(
- Domain.INSTITUTION.ATTR_LOGO_IMAGE,
- FORM_LOGO_IMAGE_TEXT_KEY,
- institution.logoImage)
- .withMaxWidth(DefaultPageLayout.LOGO_IMAGE_MAX_WIDTH)
- .withMaxHeight(DefaultPageLayout.LOGO_IMAGE_MAX_HEIGHT))
- .buildFor((isNew)
- ? this.restService.getRestCall(NewInstitution.class)
- : this.restService.getRestCall(SaveInstitution.class));
-
- // propagate content actions to action-pane
- this.pageService.pageActionBuilder(formContext.clearEntityKeys())
-
- .newAction(ActionDefinition.INSTITUTION_NEW)
- .publishIf(() -> writeGrant && isReadonly)
-
-// Removed as discussed in SEBSERV-52
-// .newAction(ActionDefinition.USER_ACCOUNT_NEW)
-// .withParentEntityKey(entityKey)
-// .publishIf(() -> userWriteGrant && isReadonly && institution.isActive())
-
- .newAction(ActionDefinition.INSTITUTION_MODIFY)
- .withEntityKey(entityKey)
- .publishIf(() -> modifyGrant && isReadonly)
-
- .newAction(ActionDefinition.INSTITUTION_DEACTIVATE)
- .withEntityKey(entityKey)
- .withSimpleRestCall(this.restService, DeactivateInstitution.class)
- .withConfirm(this.pageService.confirmDeactivation(institution))
- .publishIf(() -> writeGrant && isReadonly && institution.isActive())
-
- .newAction(ActionDefinition.INSTITUTION_ACTIVATE)
- .withEntityKey(entityKey)
- .withSimpleRestCall(this.restService, ActivateInstitution.class)
- .publishIf(() -> writeGrant && isReadonly && !institution.isActive())
-
- .newAction(ActionDefinition.INSTITUTION_SAVE)
- .withEntityKey(entityKey)
- .withExec(formHandle::processFormSave)
- .ignoreMoveAwayFromEdit()
- .publishIf(() -> !isReadonly)
-
- .newAction(ActionDefinition.INSTITUTION_SAVE_AND_ACTIVATE)
- .withEntityKey(entityKey)
- .withExec(formHandle::saveAndActivate)
- .ignoreMoveAwayFromEdit()
- .publishIf(() -> !isReadonly && !institution.isActive())
-
- .newAction(ActionDefinition.INSTITUTION_CANCEL_MODIFY)
- .withEntityKey(entityKey)
- .withExec(this.pageService.backToCurrentFunction())
- .publishIf(() -> !isReadonly);
- }
-
-}
+/*
+ * 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.content;
+
+import org.eclipse.swt.widgets.Composite;
+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.EntityType;
+import ch.ethz.seb.sebserver.gbl.model.Domain;
+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.content.action.ActionDefinition;
+import ch.ethz.seb.sebserver.gui.form.FormBuilder;
+import ch.ethz.seb.sebserver.gui.form.FormHandle;
+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.PageService;
+import ch.ethz.seb.sebserver.gui.service.page.TemplateComposer;
+import ch.ethz.seb.sebserver.gui.service.page.impl.DefaultPageLayout;
+import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestService;
+import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.institution.ActivateInstitution;
+import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.institution.DeactivateInstitution;
+import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.institution.GetInstitution;
+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;
+import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.CurrentUser.EntityGrantCheck;
+import ch.ethz.seb.sebserver.gui.widget.WidgetFactory;
+
+@Lazy
+@Component
+@GuiProfile
+public class InstitutionForm implements TemplateComposer {
+
+ private static final LocTextKey TITLE_TEXT_KEY =
+ new LocTextKey("sebserver.institution.form.title");
+ private static final LocTextKey NEW_TITLE_TEXT_KEY =
+ new LocTextKey("sebserver.institution.form.title.new");
+
+ private static final LocTextKey FORM_LOGO_IMAGE_TEXT_KEY =
+ new LocTextKey("sebserver.institution.form.logoImage");
+ private static final LocTextKey FORM_URL_SUFFIX_TEXT_KEY =
+ new LocTextKey("sebserver.institution.form.urlSuffix");
+ private static final LocTextKey FORM_NAME_TEXT_KEY =
+ new LocTextKey("sebserver.institution.form.name");
+
+ private final PageService pageService;
+ private final RestService restService;
+ private final CurrentUser currentUser;
+
+ protected InstitutionForm(
+ final PageService pageService,
+ final RestService restService,
+ final CurrentUser currentUser) {
+
+ this.pageService = pageService;
+ this.restService = restService;
+ this.currentUser = currentUser;
+ }
+
+ @Override
+ public void compose(final PageContext pageContext) {
+
+ final WidgetFactory widgetFactory = this.pageService.getWidgetFactory();
+ final EntityKey entityKey = pageContext.getEntityKey();
+ final boolean isNew = entityKey == null;
+ // get data or create new. Handle error if happen
+ final Institution institution = (isNew)
+ ? Institution.createNew()
+ : this.restService
+ .getBuilder(GetInstitution.class)
+ .withURIVariable(API.PARAM_MODEL_ID, entityKey.modelId)
+ .call()
+ .onError(error -> pageContext.notifyLoadError(EntityType.INSTITUTION, error))
+ .getOrThrow();
+
+ final EntityGrantCheck instGrant = this.currentUser.entityGrantCheck(institution);
+ final boolean writeGrant = instGrant.w();
+ final boolean modifyGrant = instGrant.m();
+ final boolean isReadonly = pageContext.isReadonly();
+
+ // new PageContext with actual EntityKey
+ final PageContext formContext = pageContext.withEntityKey(institution.getEntityKey());
+
+ // the default page layout with interactive title
+ final LocTextKey titleKey = isNew
+ ? NEW_TITLE_TEXT_KEY
+ : TITLE_TEXT_KEY;
+ final Composite content = widgetFactory.defaultPageLayout(
+ formContext.getParent(),
+ titleKey);
+
+ // The Institution form
+ final FormHandle formHandle = this.pageService.formBuilder(
+ formContext.copyOf(content))
+ .readonly(isReadonly)
+ .putStaticValueIf(() -> !isNew,
+ Domain.INSTITUTION.ATTR_ID,
+ institution.getModelId())
+ .addField(FormBuilder.text(
+ Domain.INSTITUTION.ATTR_NAME,
+ FORM_NAME_TEXT_KEY,
+ institution.name)
+ .mandatory(!isReadonly))
+ .addField(FormBuilder.text(
+ Domain.INSTITUTION.ATTR_URL_SUFFIX,
+ FORM_URL_SUFFIX_TEXT_KEY,
+ institution.urlSuffix))
+ .addField(FormBuilder.imageUpload(
+ Domain.INSTITUTION.ATTR_LOGO_IMAGE,
+ FORM_LOGO_IMAGE_TEXT_KEY,
+ institution.logoImage)
+ .withMaxWidth(DefaultPageLayout.LOGO_IMAGE_MAX_WIDTH)
+ .withMaxHeight(DefaultPageLayout.LOGO_IMAGE_MAX_HEIGHT))
+ .buildFor((isNew)
+ ? this.restService.getRestCall(NewInstitution.class)
+ : this.restService.getRestCall(SaveInstitution.class));
+
+ // propagate content actions to action-pane
+ this.pageService.pageActionBuilder(formContext.clearEntityKeys())
+
+ .newAction(ActionDefinition.INSTITUTION_NEW)
+ .publishIf(() -> writeGrant && isReadonly)
+
+ .newAction(ActionDefinition.INSTITUTION_MODIFY)
+ .withEntityKey(entityKey)
+ .publishIf(() -> modifyGrant && isReadonly)
+
+ .newAction(ActionDefinition.INSTITUTION_DEACTIVATE)
+ .withEntityKey(entityKey)
+ .withSimpleRestCall(this.restService, DeactivateInstitution.class)
+ .withConfirm(this.pageService.confirmDeactivation(institution))
+ .publishIf(() -> writeGrant && isReadonly && institution.isActive())
+
+ .newAction(ActionDefinition.INSTITUTION_ACTIVATE)
+ .withEntityKey(entityKey)
+ .withSimpleRestCall(this.restService, ActivateInstitution.class)
+ .publishIf(() -> writeGrant && isReadonly && !institution.isActive())
+
+ .newAction(ActionDefinition.INSTITUTION_SAVE)
+ .withEntityKey(entityKey)
+ .withExec(formHandle::processFormSave)
+ .ignoreMoveAwayFromEdit()
+ .publishIf(() -> !isReadonly)
+
+ .newAction(ActionDefinition.INSTITUTION_SAVE_AND_ACTIVATE)
+ .withEntityKey(entityKey)
+ .withExec(formHandle::saveAndActivate)
+ .ignoreMoveAwayFromEdit()
+ .publishIf(() -> !isReadonly && !institution.isActive())
+
+ .newAction(ActionDefinition.INSTITUTION_CANCEL_MODIFY)
+ .withEntityKey(entityKey)
+ .withExec(this.pageService.backToCurrentFunction())
+ .publishIf(() -> !isReadonly);
+ }
+
+}
diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/content/InstitutionList.java b/src/main/java/ch/ethz/seb/sebserver/gui/content/InstitutionList.java
index 096ba1cc..3399b1ec 100644
--- a/src/main/java/ch/ethz/seb/sebserver/gui/content/InstitutionList.java
+++ b/src/main/java/ch/ethz/seb/sebserver/gui/content/InstitutionList.java
@@ -1,158 +1,158 @@
-/*
- * 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.content;
-
-import org.apache.commons.lang3.StringUtils;
-import org.eclipse.swt.widgets.Composite;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.context.annotation.Lazy;
-import org.springframework.stereotype.Component;
-
-import ch.ethz.seb.sebserver.gbl.api.EntityType;
-import ch.ethz.seb.sebserver.gbl.model.Domain;
-import ch.ethz.seb.sebserver.gbl.model.Entity;
-import ch.ethz.seb.sebserver.gbl.model.institution.Institution;
-import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
-import ch.ethz.seb.sebserver.gui.content.action.ActionDefinition;
-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.PageService;
-import ch.ethz.seb.sebserver.gui.service.page.PageService.PageActionBuilder;
-import ch.ethz.seb.sebserver.gui.service.page.TemplateComposer;
-import ch.ethz.seb.sebserver.gui.service.page.impl.PageAction;
-import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestService;
-import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.institution.GetInstitutionPage;
-import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.CurrentUser;
-import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.CurrentUser.GrantCheck;
-import ch.ethz.seb.sebserver.gui.table.ColumnDefinition;
-import ch.ethz.seb.sebserver.gui.table.ColumnDefinition.TableFilterAttribute;
-import ch.ethz.seb.sebserver.gui.table.EntityTable;
-import ch.ethz.seb.sebserver.gui.table.TableFilter.CriteriaType;
-
-@Lazy
-@Component
-@GuiProfile
-public class InstitutionList implements TemplateComposer {
-
- private static final LocTextKey EMPTY_LIST_TEXT_KEY =
- new LocTextKey("sebserver.institution.list.empty");
- private static final LocTextKey TITLE_TEXT_KEY =
- new LocTextKey("sebserver.institution.list.title");
- private static final LocTextKey NAME_TEXT_KEY =
- new LocTextKey("sebserver.institution.list.column.name");
- private static final LocTextKey URL_TEXT_KEY =
- new LocTextKey("sebserver.institution.list.column.urlSuffix");
- private static final LocTextKey ACTIVE_TEXT_KEY =
- new LocTextKey("sebserver.institution.list.column.active");
- private static final LocTextKey EMPTY_SELECTION_TEXT_KEY =
- new LocTextKey("sebserver.institution.info.pleaseSelect");
-
- private final TableFilterAttribute nameFilter =
- new TableFilterAttribute(CriteriaType.TEXT, Entity.FILTER_ATTR_NAME);
- private final TableFilterAttribute urlSuffixFilter =
- new TableFilterAttribute(CriteriaType.TEXT, Institution.FILTER_ATTR_URL_SUFFIX);
- private final TableFilterAttribute activityFilter;
-
- private final PageService pageService;
- private final RestService restService;
- private final CurrentUser currentUser;
- private final int pageSize;
-
- protected InstitutionList(
- final PageService pageService,
- final RestService restService,
- final CurrentUser currentUser,
- @Value("${sebserver.gui.list.page.size:20}") final Integer pageSize) {
-
- this.pageService = pageService;
- this.restService = restService;
- this.currentUser = currentUser;
- this.pageSize = pageSize;
-
- this.activityFilter = new TableFilterAttribute(
- CriteriaType.SINGLE_SELECTION,
- Institution.FILTER_ATTR_ACTIVE,
- StringUtils.EMPTY,
- this.pageService.getResourceService()::activityResources);
- }
-
- @Override
- public void compose(final PageContext pageContext) {
- final Composite content = this.pageService.getWidgetFactory().defaultPageLayout(
- pageContext.getParent(),
- TITLE_TEXT_KEY);
-
- final PageActionBuilder pageActionBuilder =
- this.pageService.pageActionBuilder(pageContext.clearEntityKeys());
-
- // table
- final EntityTable table =
- this.pageService.entityTableBuilder(this.restService.getRestCall(GetInstitutionPage.class))
- .withEmptyMessage(EMPTY_LIST_TEXT_KEY)
- .withPaging(this.pageSize)
- .withColumn(new ColumnDefinition<>(
- Domain.INSTITUTION.ATTR_NAME,
- NAME_TEXT_KEY,
- Institution::getName)
- .sortable()
- .withFilter(this.nameFilter))
- .withColumn(new ColumnDefinition<>(
- Domain.INSTITUTION.ATTR_URL_SUFFIX,
- URL_TEXT_KEY,
- Institution::getUrlSuffix)
- .sortable()
- .withFilter(this.urlSuffixFilter))
- .withColumn(new ColumnDefinition<>(
- Domain.INSTITUTION.ATTR_ACTIVE,
- ACTIVE_TEXT_KEY,
- this.pageService.getResourceService(). localizedActivityFunction())
- .sortable()
- .withFilter(this.activityFilter))
- .withDefaultAction(pageActionBuilder
- .newAction(ActionDefinition.INSTITUTION_VIEW_FROM_LIST)
- .create())
- .withSelectionListener(this.pageService.getSelectionPublisher(
- ActionDefinition.INSTITUTION_TOGGLE_ACTIVITY,
- ActionDefinition.INSTITUTION_ACTIVATE,
- ActionDefinition.INSTITUTION_DEACTIVATE,
- pageContext,
- ActionDefinition.INSTITUTION_VIEW_FROM_LIST,
- ActionDefinition.INSTITUTION_MODIFY_FROM_LIST,
- ActionDefinition.INSTITUTION_TOGGLE_ACTIVITY))
- .compose(pageContext.copyOf(content));
-
- // propagate content actions to action-pane
- final GrantCheck instGrant = this.currentUser.grantCheck(EntityType.INSTITUTION);
-
- pageActionBuilder
-
- .newAction(ActionDefinition.INSTITUTION_NEW)
- .publishIf(instGrant::w)
-
- .newAction(ActionDefinition.INSTITUTION_VIEW_FROM_LIST)
- .withSelect(
- table::getSelection,
- PageAction::applySingleSelectionAsEntityKey,
- EMPTY_SELECTION_TEXT_KEY)
- .publishIf(() -> table.hasAnyContent(), false)
-
- .newAction(ActionDefinition.INSTITUTION_MODIFY_FROM_LIST)
- .withSelect(
- table::getSelection,
- PageAction::applySingleSelectionAsEntityKey,
- EMPTY_SELECTION_TEXT_KEY)
- .publishIf(() -> instGrant.m() && table.hasAnyContent(), false)
-
- .newAction(ActionDefinition.INSTITUTION_TOGGLE_ACTIVITY)
- .withExec(this.pageService.activationToggleActionFunction(table, EMPTY_SELECTION_TEXT_KEY))
- .withConfirm(this.pageService.confirmDeactivation(table))
- .publishIf(() -> instGrant.m() && table.hasAnyContent(), false);
- }
-
-}
+/*
+ * 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.content;
+
+import org.apache.commons.lang3.StringUtils;
+import org.eclipse.swt.widgets.Composite;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Lazy;
+import org.springframework.stereotype.Component;
+
+import ch.ethz.seb.sebserver.gbl.api.EntityType;
+import ch.ethz.seb.sebserver.gbl.model.Domain;
+import ch.ethz.seb.sebserver.gbl.model.Entity;
+import ch.ethz.seb.sebserver.gbl.model.institution.Institution;
+import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
+import ch.ethz.seb.sebserver.gui.content.action.ActionDefinition;
+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.PageService;
+import ch.ethz.seb.sebserver.gui.service.page.PageService.PageActionBuilder;
+import ch.ethz.seb.sebserver.gui.service.page.TemplateComposer;
+import ch.ethz.seb.sebserver.gui.service.page.impl.PageAction;
+import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestService;
+import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.institution.GetInstitutionPage;
+import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.CurrentUser;
+import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.CurrentUser.GrantCheck;
+import ch.ethz.seb.sebserver.gui.table.ColumnDefinition;
+import ch.ethz.seb.sebserver.gui.table.ColumnDefinition.TableFilterAttribute;
+import ch.ethz.seb.sebserver.gui.table.EntityTable;
+import ch.ethz.seb.sebserver.gui.table.TableFilter.CriteriaType;
+
+@Lazy
+@Component
+@GuiProfile
+public class InstitutionList implements TemplateComposer {
+
+ private static final LocTextKey EMPTY_LIST_TEXT_KEY =
+ new LocTextKey("sebserver.institution.list.empty");
+ private static final LocTextKey TITLE_TEXT_KEY =
+ new LocTextKey("sebserver.institution.list.title");
+ private static final LocTextKey NAME_TEXT_KEY =
+ new LocTextKey("sebserver.institution.list.column.name");
+ private static final LocTextKey URL_TEXT_KEY =
+ new LocTextKey("sebserver.institution.list.column.urlSuffix");
+ private static final LocTextKey ACTIVE_TEXT_KEY =
+ new LocTextKey("sebserver.institution.list.column.active");
+ private static final LocTextKey EMPTY_SELECTION_TEXT_KEY =
+ new LocTextKey("sebserver.institution.info.pleaseSelect");
+
+ private final TableFilterAttribute nameFilter =
+ new TableFilterAttribute(CriteriaType.TEXT, Entity.FILTER_ATTR_NAME);
+ private final TableFilterAttribute urlSuffixFilter =
+ new TableFilterAttribute(CriteriaType.TEXT, Institution.FILTER_ATTR_URL_SUFFIX);
+ private final TableFilterAttribute activityFilter;
+
+ private final PageService pageService;
+ private final RestService restService;
+ private final CurrentUser currentUser;
+ private final int pageSize;
+
+ protected InstitutionList(
+ final PageService pageService,
+ final RestService restService,
+ final CurrentUser currentUser,
+ @Value("${sebserver.gui.list.page.size:20}") final Integer pageSize) {
+
+ this.pageService = pageService;
+ this.restService = restService;
+ this.currentUser = currentUser;
+ this.pageSize = pageSize;
+
+ this.activityFilter = new TableFilterAttribute(
+ CriteriaType.SINGLE_SELECTION,
+ Institution.FILTER_ATTR_ACTIVE,
+ StringUtils.EMPTY,
+ this.pageService.getResourceService()::activityResources);
+ }
+
+ @Override
+ public void compose(final PageContext pageContext) {
+ final Composite content = this.pageService.getWidgetFactory().defaultPageLayout(
+ pageContext.getParent(),
+ TITLE_TEXT_KEY);
+
+ final PageActionBuilder pageActionBuilder =
+ this.pageService.pageActionBuilder(pageContext.clearEntityKeys());
+
+ // table
+ final EntityTable table =
+ this.pageService.entityTableBuilder(this.restService.getRestCall(GetInstitutionPage.class))
+ .withEmptyMessage(EMPTY_LIST_TEXT_KEY)
+ .withPaging(this.pageSize)
+ .withColumn(new ColumnDefinition<>(
+ Domain.INSTITUTION.ATTR_NAME,
+ NAME_TEXT_KEY,
+ Institution::getName)
+ .sortable()
+ .withFilter(this.nameFilter))
+ .withColumn(new ColumnDefinition<>(
+ Domain.INSTITUTION.ATTR_URL_SUFFIX,
+ URL_TEXT_KEY,
+ Institution::getUrlSuffix)
+ .sortable()
+ .withFilter(this.urlSuffixFilter))
+ .withColumn(new ColumnDefinition<>(
+ Domain.INSTITUTION.ATTR_ACTIVE,
+ ACTIVE_TEXT_KEY,
+ this.pageService.getResourceService(). localizedActivityFunction())
+ .sortable()
+ .withFilter(this.activityFilter))
+ .withDefaultAction(pageActionBuilder
+ .newAction(ActionDefinition.INSTITUTION_VIEW_FROM_LIST)
+ .create())
+ .withSelectionListener(this.pageService.getSelectionPublisher(
+ ActionDefinition.INSTITUTION_TOGGLE_ACTIVITY,
+ ActionDefinition.INSTITUTION_ACTIVATE,
+ ActionDefinition.INSTITUTION_DEACTIVATE,
+ pageContext,
+ ActionDefinition.INSTITUTION_VIEW_FROM_LIST,
+ ActionDefinition.INSTITUTION_MODIFY_FROM_LIST,
+ ActionDefinition.INSTITUTION_TOGGLE_ACTIVITY))
+ .compose(pageContext.copyOf(content));
+
+ // propagate content actions to action-pane
+ final GrantCheck instGrant = this.currentUser.grantCheck(EntityType.INSTITUTION);
+
+ pageActionBuilder
+
+ .newAction(ActionDefinition.INSTITUTION_NEW)
+ .publishIf(instGrant::w)
+
+ .newAction(ActionDefinition.INSTITUTION_VIEW_FROM_LIST)
+ .withSelect(
+ table::getSelection,
+ PageAction::applySingleSelectionAsEntityKey,
+ EMPTY_SELECTION_TEXT_KEY)
+ .publishIf(table::hasAnyContent, false)
+
+ .newAction(ActionDefinition.INSTITUTION_MODIFY_FROM_LIST)
+ .withSelect(
+ table::getSelection,
+ PageAction::applySingleSelectionAsEntityKey,
+ EMPTY_SELECTION_TEXT_KEY)
+ .publishIf(() -> instGrant.m() && table.hasAnyContent(), false)
+
+ .newAction(ActionDefinition.INSTITUTION_TOGGLE_ACTIVITY)
+ .withExec(this.pageService.activationToggleActionFunction(table, EMPTY_SELECTION_TEXT_KEY))
+ .withConfirm(this.pageService.confirmDeactivation(table))
+ .publishIf(() -> instGrant.m() && table.hasAnyContent(), false);
+ }
+
+}
diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/content/SebClientConfigForm.java b/src/main/java/ch/ethz/seb/sebserver/gui/content/SebClientConfigForm.java
index e8b6d317..16704734 100644
--- a/src/main/java/ch/ethz/seb/sebserver/gui/content/SebClientConfigForm.java
+++ b/src/main/java/ch/ethz/seb/sebserver/gui/content/SebClientConfigForm.java
@@ -1,205 +1,211 @@
-/*
- * 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.content;
-
-import org.eclipse.rap.rwt.RWT;
-import org.eclipse.rap.rwt.client.service.UrlLauncher;
-import org.eclipse.swt.widgets.Composite;
-import org.springframework.beans.factory.annotation.Value;
-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.EntityType;
-import ch.ethz.seb.sebserver.gbl.model.Domain;
-import ch.ethz.seb.sebserver.gbl.model.EntityKey;
-import ch.ethz.seb.sebserver.gbl.model.sebconfig.SebClientConfig;
-import ch.ethz.seb.sebserver.gbl.model.user.UserInfo;
-import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
-import ch.ethz.seb.sebserver.gui.content.action.ActionDefinition;
-import ch.ethz.seb.sebserver.gui.form.FormBuilder;
-import ch.ethz.seb.sebserver.gui.form.FormHandle;
-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.PageContext;
-import ch.ethz.seb.sebserver.gui.service.page.PageService;
-import ch.ethz.seb.sebserver.gui.service.page.TemplateComposer;
-import ch.ethz.seb.sebserver.gui.service.remote.download.DownloadService;
-import ch.ethz.seb.sebserver.gui.service.remote.download.SebClientConfigDownload;
-import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestService;
-import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.clientconfig.ActivateClientConfig;
-import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.clientconfig.DeactivateClientConfig;
-import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.clientconfig.GetClientConfig;
-import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.clientconfig.NewClientConfig;
-import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.clientconfig.SaveClientConfig;
-import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.CurrentUser;
-import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.CurrentUser.EntityGrantCheck;
-import ch.ethz.seb.sebserver.gui.widget.WidgetFactory;
-
-@Lazy
-@Component
-@GuiProfile
-public class SebClientConfigForm implements TemplateComposer {
-
- private static final LocTextKey FORM_TITLE_NEW =
- new LocTextKey("sebserver.clientconfig.form.title.new");
- private static final LocTextKey FORM_TITLE =
- new LocTextKey("sebserver.clientconfig.form.title");
- private static final LocTextKey FORM_NAME_TEXT_KEY =
- new LocTextKey("sebserver.clientconfig.form.name");
- private static final LocTextKey FORM_FALLBACK_URL_TEXT_KEY =
- new LocTextKey("sebserver.clientconfig.form.fallback-url");
- private static final LocTextKey FORM_DATE_TEXT_KEY =
- new LocTextKey("sebserver.clientconfig.form.date");
- private static final LocTextKey FORM_ENCRYPT_SECRET_TEXT_KEY =
- new LocTextKey("sebserver.clientconfig.form.encryptSecret");
- private static final LocTextKey FORM_CONFIRM_ENCRYPT_SECRET_TEXT_KEY =
- new LocTextKey("sebserver.clientconfig.form.encryptSecret.confirm");
-
- private final PageService pageService;
- private final RestService restService;
- private final CurrentUser currentUser;
- private final DownloadService downloadService;
- private final String downloadFileName;
-
- protected SebClientConfigForm(
- final PageService pageService,
- final RestService restService,
- final CurrentUser currentUser,
- final DownloadService downloadService,
- @Value("${sebserver.gui.seb.client.config.download.filename}") final String downloadFileName) {
-
- this.pageService = pageService;
- this.restService = restService;
- this.currentUser = currentUser;
- this.downloadService = downloadService;
- this.downloadFileName = downloadFileName;
- }
-
- @Override
- public void compose(final PageContext pageContext) {
- final WidgetFactory widgetFactory = this.pageService.getWidgetFactory();
- final I18nSupport i18nSupport = this.pageService.getI18nSupport();
-
- final UserInfo user = this.currentUser.get();
- final EntityKey entityKey = pageContext.getEntityKey();
- final EntityKey parentEntityKey = pageContext.getParentEntityKey();
-
- final boolean isNew = entityKey == null;
-
- // get data or create new. Handle error if happen
- final SebClientConfig clientConfig = (isNew)
- ? SebClientConfig.createNew((parentEntityKey != null)
- ? Long.valueOf(parentEntityKey.modelId)
- : user.institutionId)
- : this.restService
- .getBuilder(GetClientConfig.class)
- .withURIVariable(API.PARAM_MODEL_ID, entityKey.modelId)
- .call()
- .onError(error -> pageContext.notifyLoadError(EntityType.SEB_CLIENT_CONFIGURATION, error))
- .getOrThrow();
-
- final EntityGrantCheck entityGrant = this.currentUser.entityGrantCheck(clientConfig);
- final boolean writeGrant = entityGrant.w();
- final boolean modifyGrant = entityGrant.m();
- final boolean isReadonly = pageContext.isReadonly();
-
- // new PageContext with actual EntityKey
- final PageContext formContext = pageContext.withEntityKey(clientConfig.getEntityKey());
-
- // the default page layout with interactive title
- final LocTextKey titleKey = (isNew)
- ? FORM_TITLE_NEW
- : FORM_TITLE;
- final Composite content = widgetFactory.defaultPageLayout(
- formContext.getParent(),
- titleKey);
-
- // The SebClientConfig form
- final FormHandle formHandle = this.pageService.formBuilder(
- formContext.copyOf(content))
- .readonly(isReadonly)
- .putStaticValueIf(() -> !isNew,
- Domain.SEB_CLIENT_CONFIGURATION.ATTR_ID,
- clientConfig.getModelId())
- .putStaticValue(
- Domain.SEB_CLIENT_CONFIGURATION.ATTR_INSTITUTION_ID,
- String.valueOf(clientConfig.getInstitutionId()))
- .addField(FormBuilder.text(
- Domain.SEB_CLIENT_CONFIGURATION.ATTR_NAME,
- FORM_NAME_TEXT_KEY,
- clientConfig.name))
- .addField(FormBuilder.text(
- SebClientConfig.ATTR_FALLBACK_START_URL,
- FORM_FALLBACK_URL_TEXT_KEY,
- clientConfig.fallbackStartURL))
- .addFieldIf(() -> !isNew,
- () -> FormBuilder.text(
- Domain.SEB_CLIENT_CONFIGURATION.ATTR_DATE,
- FORM_DATE_TEXT_KEY,
- i18nSupport.formatDisplayDateWithTimeZone(clientConfig.date))
- .readonly(true))
- .addField(FormBuilder.text(
- Domain.SEB_CLIENT_CONFIGURATION.ATTR_ENCRYPT_SECRET,
- FORM_ENCRYPT_SECRET_TEXT_KEY)
- .asPasswordField())
- .addField(FormBuilder.text(
- SebClientConfig.ATTR_CONFIRM_ENCRYPT_SECRET,
- FORM_CONFIRM_ENCRYPT_SECRET_TEXT_KEY)
- .asPasswordField())
- .buildFor((isNew)
- ? this.restService.getRestCall(NewClientConfig.class)
- : this.restService.getRestCall(SaveClientConfig.class));
-
- final UrlLauncher urlLauncher = RWT.getClient().getService(UrlLauncher.class);
- this.pageService.pageActionBuilder(formContext.clearEntityKeys())
-
- .newAction(ActionDefinition.SEB_CLIENT_CONFIG_NEW)
- .publishIf(() -> writeGrant && isReadonly)
-
- .newAction(ActionDefinition.SEB_CLIENT_CONFIG_MODIFY)
- .withEntityKey(entityKey)
- .publishIf(() -> modifyGrant && isReadonly)
-
- .newAction(ActionDefinition.SEB_CLIENT_CONFIG_EXPORT)
- .withEntityKey(entityKey)
- .withExec(action -> {
- final String downloadURL = this.downloadService.createDownloadURL(
- entityKey.modelId,
- SebClientConfigDownload.class,
- this.downloadFileName);
- urlLauncher.openURL(downloadURL);
- return action;
- })
- .publishIf(() -> writeGrant && isReadonly && clientConfig.isActive())
-
- .newAction(ActionDefinition.SEB_CLIENT_CONFIG_DEACTIVATE)
- .withEntityKey(entityKey)
- .withSimpleRestCall(this.restService, DeactivateClientConfig.class)
- .withConfirm(this.pageService.confirmDeactivation(clientConfig))
- .publishIf(() -> writeGrant && isReadonly && clientConfig.isActive())
-
- .newAction(ActionDefinition.SEB_CLIENT_CONFIG_ACTIVATE)
- .withEntityKey(entityKey)
- .withSimpleRestCall(this.restService, ActivateClientConfig.class)
- .publishIf(() -> writeGrant && isReadonly && !clientConfig.isActive())
-
- .newAction(ActionDefinition.SEB_CLIENT_CONFIG_SAVE)
- .withEntityKey(entityKey)
- .withExec(formHandle::processFormSave)
- .ignoreMoveAwayFromEdit()
- .publishIf(() -> !isReadonly)
-
- .newAction(ActionDefinition.SEB_CLIENT_CONFIG_CANCEL_MODIFY)
- .withEntityKey(entityKey)
- .withExec(this.pageService.backToCurrentFunction())
- .publishIf(() -> !isReadonly);
- }
-
-}
+/*
+ * 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.content;
+
+import org.eclipse.rap.rwt.RWT;
+import org.eclipse.rap.rwt.client.service.UrlLauncher;
+import org.eclipse.swt.widgets.Composite;
+import org.springframework.beans.factory.annotation.Value;
+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.EntityType;
+import ch.ethz.seb.sebserver.gbl.model.Domain;
+import ch.ethz.seb.sebserver.gbl.model.EntityKey;
+import ch.ethz.seb.sebserver.gbl.model.sebconfig.SebClientConfig;
+import ch.ethz.seb.sebserver.gbl.model.user.UserInfo;
+import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
+import ch.ethz.seb.sebserver.gui.content.action.ActionDefinition;
+import ch.ethz.seb.sebserver.gui.form.FormBuilder;
+import ch.ethz.seb.sebserver.gui.form.FormHandle;
+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.PageContext;
+import ch.ethz.seb.sebserver.gui.service.page.PageService;
+import ch.ethz.seb.sebserver.gui.service.page.TemplateComposer;
+import ch.ethz.seb.sebserver.gui.service.remote.download.DownloadService;
+import ch.ethz.seb.sebserver.gui.service.remote.download.SebClientConfigDownload;
+import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestService;
+import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.clientconfig.ActivateClientConfig;
+import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.clientconfig.DeactivateClientConfig;
+import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.clientconfig.GetClientConfig;
+import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.clientconfig.NewClientConfig;
+import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.clientconfig.SaveClientConfig;
+import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.CurrentUser;
+import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.CurrentUser.EntityGrantCheck;
+import ch.ethz.seb.sebserver.gui.widget.WidgetFactory;
+
+@Lazy
+@Component
+@GuiProfile
+public class SebClientConfigForm implements TemplateComposer {
+
+ private static final LocTextKey FORM_TITLE_NEW =
+ new LocTextKey("sebserver.clientconfig.form.title.new");
+ private static final LocTextKey FORM_TITLE =
+ new LocTextKey("sebserver.clientconfig.form.title");
+ private static final LocTextKey FORM_NAME_TEXT_KEY =
+ new LocTextKey("sebserver.clientconfig.form.name");
+ private static final LocTextKey FORM_FALLBACK_URL_TEXT_KEY =
+ new LocTextKey("sebserver.clientconfig.form.fallback-url");
+ private static final LocTextKey FORM_DATE_TEXT_KEY =
+ new LocTextKey("sebserver.clientconfig.form.date");
+ private static final LocTextKey FORM_ENCRYPT_SECRET_TEXT_KEY =
+ new LocTextKey("sebserver.clientconfig.form.encryptSecret");
+ private static final LocTextKey FORM_CONFIRM_ENCRYPT_SECRET_TEXT_KEY =
+ new LocTextKey("sebserver.clientconfig.form.encryptSecret.confirm");
+
+ private final PageService pageService;
+ private final RestService restService;
+ private final CurrentUser currentUser;
+ private final DownloadService downloadService;
+ private final String downloadFileName;
+
+ protected SebClientConfigForm(
+ final PageService pageService,
+ final RestService restService,
+ final CurrentUser currentUser,
+ final DownloadService downloadService,
+ @Value("${sebserver.gui.seb.client.config.download.filename}") final String downloadFileName) {
+
+ this.pageService = pageService;
+ this.restService = restService;
+ this.currentUser = currentUser;
+ this.downloadService = downloadService;
+ this.downloadFileName = downloadFileName;
+ }
+
+ @Override
+ public void compose(final PageContext pageContext) {
+ final WidgetFactory widgetFactory = this.pageService.getWidgetFactory();
+ final I18nSupport i18nSupport = this.pageService.getI18nSupport();
+
+ final UserInfo user = this.currentUser.get();
+ final EntityKey entityKey = pageContext.getEntityKey();
+ final EntityKey parentEntityKey = pageContext.getParentEntityKey();
+
+ final boolean isNew = entityKey == null;
+
+ // get data or create new. Handle error if happen
+ final SebClientConfig clientConfig = (isNew)
+ ? SebClientConfig.createNew((parentEntityKey != null)
+ ? Long.valueOf(parentEntityKey.modelId)
+ : user.institutionId)
+ : this.restService
+ .getBuilder(GetClientConfig.class)
+ .withURIVariable(API.PARAM_MODEL_ID, entityKey.modelId)
+ .call()
+ .onError(error -> pageContext.notifyLoadError(EntityType.SEB_CLIENT_CONFIGURATION, error))
+ .getOrThrow();
+
+ final EntityGrantCheck entityGrant = this.currentUser.entityGrantCheck(clientConfig);
+ final boolean writeGrant = entityGrant.w();
+ final boolean modifyGrant = entityGrant.m();
+ final boolean isReadonly = pageContext.isReadonly();
+
+ // new PageContext with actual EntityKey
+ final PageContext formContext = pageContext.withEntityKey(clientConfig.getEntityKey());
+
+ // the default page layout with interactive title
+ final LocTextKey titleKey = (isNew)
+ ? FORM_TITLE_NEW
+ : FORM_TITLE;
+ final Composite content = widgetFactory.defaultPageLayout(
+ formContext.getParent(),
+ titleKey);
+
+ // The SebClientConfig form
+ final FormHandle formHandle = this.pageService.formBuilder(
+ formContext.copyOf(content))
+ .readonly(isReadonly)
+ .putStaticValueIf(() -> !isNew,
+ Domain.SEB_CLIENT_CONFIGURATION.ATTR_ID,
+ clientConfig.getModelId())
+ .putStaticValue(
+ Domain.SEB_CLIENT_CONFIGURATION.ATTR_INSTITUTION_ID,
+ String.valueOf(clientConfig.getInstitutionId()))
+ .addField(FormBuilder.text(
+ Domain.SEB_CLIENT_CONFIGURATION.ATTR_NAME,
+ FORM_NAME_TEXT_KEY,
+ clientConfig.name))
+ .addField(FormBuilder.text(
+ SebClientConfig.ATTR_FALLBACK_START_URL,
+ FORM_FALLBACK_URL_TEXT_KEY,
+ clientConfig.fallbackStartURL))
+ .addFieldIf(() -> !isNew,
+ () -> FormBuilder.text(
+ Domain.SEB_CLIENT_CONFIGURATION.ATTR_DATE,
+ FORM_DATE_TEXT_KEY,
+ i18nSupport.formatDisplayDateWithTimeZone(clientConfig.date))
+ .readonly(true))
+ .addField(FormBuilder.text(
+ Domain.SEB_CLIENT_CONFIGURATION.ATTR_ENCRYPT_SECRET,
+ FORM_ENCRYPT_SECRET_TEXT_KEY)
+ .asPasswordField())
+ .addField(FormBuilder.text(
+ SebClientConfig.ATTR_CONFIRM_ENCRYPT_SECRET,
+ FORM_CONFIRM_ENCRYPT_SECRET_TEXT_KEY)
+ .asPasswordField())
+ .buildFor((isNew)
+ ? this.restService.getRestCall(NewClientConfig.class)
+ : this.restService.getRestCall(SaveClientConfig.class));
+
+ final UrlLauncher urlLauncher = RWT.getClient().getService(UrlLauncher.class);
+ this.pageService.pageActionBuilder(formContext.clearEntityKeys())
+
+ .newAction(ActionDefinition.SEB_CLIENT_CONFIG_NEW)
+ .publishIf(() -> writeGrant && isReadonly)
+
+ .newAction(ActionDefinition.SEB_CLIENT_CONFIG_MODIFY)
+ .withEntityKey(entityKey)
+ .publishIf(() -> modifyGrant && isReadonly)
+
+ .newAction(ActionDefinition.SEB_CLIENT_CONFIG_EXPORT)
+ .withEntityKey(entityKey)
+ .withExec(action -> {
+ final String downloadURL = this.downloadService.createDownloadURL(
+ entityKey.modelId,
+ SebClientConfigDownload.class,
+ this.downloadFileName);
+ urlLauncher.openURL(downloadURL);
+ return action;
+ })
+ .publishIf(() -> writeGrant && isReadonly && clientConfig.isActive())
+
+ .newAction(ActionDefinition.SEB_CLIENT_CONFIG_DEACTIVATE)
+ .withEntityKey(entityKey)
+ .withSimpleRestCall(this.restService, DeactivateClientConfig.class)
+ .withConfirm(this.pageService.confirmDeactivation(clientConfig))
+ .publishIf(() -> writeGrant && isReadonly && clientConfig.isActive())
+
+ .newAction(ActionDefinition.SEB_CLIENT_CONFIG_ACTIVATE)
+ .withEntityKey(entityKey)
+ .withSimpleRestCall(this.restService, ActivateClientConfig.class)
+ .publishIf(() -> writeGrant && isReadonly && !clientConfig.isActive())
+
+ .newAction(ActionDefinition.SEB_CLIENT_CONFIG_SAVE)
+ .withEntityKey(entityKey)
+ .withExec(formHandle::processFormSave)
+ .ignoreMoveAwayFromEdit()
+ .publishIf(() -> !isReadonly)
+
+ .newAction(ActionDefinition.SEB_CLIENT_CONFIG_SAVE_AND_ACTIVATE)
+ .withEntityKey(entityKey)
+ .withExec(formHandle::saveAndActivate)
+ .ignoreMoveAwayFromEdit()
+ .publishIf(() -> !isReadonly && !clientConfig.isActive())
+
+ .newAction(ActionDefinition.SEB_CLIENT_CONFIG_CANCEL_MODIFY)
+ .withEntityKey(entityKey)
+ .withExec(this.pageService.backToCurrentFunction())
+ .publishIf(() -> !isReadonly);
+ }
+
+}
diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/content/SebClientConfigList.java b/src/main/java/ch/ethz/seb/sebserver/gui/content/SebClientConfigList.java
index 5de41fcf..c1d55c51 100644
--- a/src/main/java/ch/ethz/seb/sebserver/gui/content/SebClientConfigList.java
+++ b/src/main/java/ch/ethz/seb/sebserver/gui/content/SebClientConfigList.java
@@ -1,182 +1,199 @@
-/*
- * 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.content;
-
-import java.util.function.Function;
-
-import org.eclipse.swt.widgets.Composite;
-import org.joda.time.DateTime;
-import org.joda.time.DateTimeZone;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.context.annotation.Lazy;
-import org.springframework.stereotype.Component;
-
-import ch.ethz.seb.sebserver.gbl.Constants;
-import ch.ethz.seb.sebserver.gbl.api.EntityType;
-import ch.ethz.seb.sebserver.gbl.model.Domain;
-import ch.ethz.seb.sebserver.gbl.model.Entity;
-import ch.ethz.seb.sebserver.gbl.model.sebconfig.SebClientConfig;
-import ch.ethz.seb.sebserver.gbl.model.user.UserInfo;
-import ch.ethz.seb.sebserver.gbl.model.user.UserRole;
-import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
-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.PageContext;
-import ch.ethz.seb.sebserver.gui.service.page.PageService;
-import ch.ethz.seb.sebserver.gui.service.page.PageService.PageActionBuilder;
-import ch.ethz.seb.sebserver.gui.service.page.TemplateComposer;
-import ch.ethz.seb.sebserver.gui.service.page.impl.PageAction;
-import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestService;
-import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.clientconfig.GetClientConfigPage;
-import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.CurrentUser;
-import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.CurrentUser.GrantCheck;
-import ch.ethz.seb.sebserver.gui.table.ColumnDefinition;
-import ch.ethz.seb.sebserver.gui.table.ColumnDefinition.TableFilterAttribute;
-import ch.ethz.seb.sebserver.gui.table.EntityTable;
-import ch.ethz.seb.sebserver.gui.table.TableFilter.CriteriaType;
-
-@Lazy
-@Component
-@GuiProfile
-public class SebClientConfigList implements TemplateComposer {
-
- private static final LocTextKey NO_MODIFY_PRIVILEGE_ON_OTHER_INSTITUION =
- new LocTextKey("sebserver.clientconfig.list.action.no.modify.privilege");
- private static final LocTextKey EMPTY_LIST_TEXT_KEY =
- new LocTextKey("sebserver.clientconfig.list.empty");
- private static final LocTextKey TITLE_TEXT_KEY =
- new LocTextKey("sebserver.clientconfig.list.title");
- private static final LocTextKey INSTITUTION_TEXT_KEY =
- new LocTextKey("sebserver.clientconfig.list.column.institution");
- private static final LocTextKey NAME_TEXT_KEY =
- new LocTextKey("sebserver.clientconfig.list.column.name");
- private static final LocTextKey ACTIVE_TEXT_KEY =
- new LocTextKey("sebserver.clientconfig.list.column.active");
- private static final LocTextKey EMPTY_SELECTION_TEXT_KEY =
- new LocTextKey("sebserver.clientconfig.info.pleaseSelect");
-
- private final TableFilterAttribute institutionFilter;
- private final TableFilterAttribute nameFilter =
- new TableFilterAttribute(CriteriaType.TEXT, Entity.FILTER_ATTR_NAME);
- private final TableFilterAttribute dateFilter =
- new TableFilterAttribute(
- CriteriaType.DATE,
- SebClientConfig.FILTER_ATTR_CREATION_DATE,
- DateTime.now(DateTimeZone.UTC)
- .minusYears(1)
- .toString(Constants.DEFAULT_DATE_TIME_FORMAT));
- private final TableFilterAttribute activityFilter;
-
- private final PageService pageService;
- private final RestService restService;
- private final CurrentUser currentUser;
- private final ResourceService resourceService;
- private final int pageSize;
-
- protected SebClientConfigList(
- final PageService pageService,
- final RestService restService,
- final CurrentUser currentUser,
- @Value("${sebserver.gui.list.page.size:20}") final Integer pageSize) {
-
- this.pageService = pageService;
- this.restService = restService;
- this.currentUser = currentUser;
- this.resourceService = pageService.getResourceService();
- this.pageSize = pageSize;
-
- this.institutionFilter = new TableFilterAttribute(
- CriteriaType.SINGLE_SELECTION,
- Entity.FILTER_ATTR_INSTITUTION,
- this.resourceService::institutionResource);
-
- this.activityFilter = new TableFilterAttribute(
- CriteriaType.SINGLE_SELECTION,
- UserInfo.FILTER_ATTR_ACTIVE,
- this.resourceService::activityResources);
- }
-
- @Override
- public void compose(final PageContext pageContext) {
-
- final I18nSupport i18nSupport = this.pageService.getI18nSupport();
- final Composite content = this.pageService.getWidgetFactory().defaultPageLayout(
- pageContext.getParent(),
- TITLE_TEXT_KEY);
-
- final boolean isSEBAdmin = this.currentUser.get().hasRole(UserRole.SEB_SERVER_ADMIN);
- final PageActionBuilder pageActionBuilder =
- this.pageService.pageActionBuilder(pageContext.clearEntityKeys());
-
- // table
- final EntityTable table =
- this.pageService.entityTableBuilder(this.restService.getRestCall(GetClientConfigPage.class))
- .withEmptyMessage(EMPTY_LIST_TEXT_KEY)
- .withPaging(this.pageSize)
- .withColumnIf(
- () -> isSEBAdmin,
- () -> new ColumnDefinition<>(
- Domain.LMS_SETUP.ATTR_INSTITUTION_ID,
- INSTITUTION_TEXT_KEY,
- clientConfigInstitutionNameFunction(this.resourceService))
- .withFilter(this.institutionFilter))
- .withColumn(new ColumnDefinition<>(
- Domain.SEB_CLIENT_CONFIGURATION.ATTR_NAME,
- NAME_TEXT_KEY,
- SebClientConfig::getName)
- .withFilter(this.nameFilter)
- .sortable())
- .withColumn(new ColumnDefinition<>(
- Domain.SEB_CLIENT_CONFIGURATION.ATTR_DATE,
- new LocTextKey(
- "sebserver.clientconfig.list.column.date",
- i18nSupport.getUsersTimeZoneTitleSuffix()),
- SebClientConfig::getDate)
- .withFilter(this.dateFilter)
- .sortable())
- .withColumn(new ColumnDefinition<>(
- Domain.SEB_CLIENT_CONFIGURATION.ATTR_ACTIVE,
- ACTIVE_TEXT_KEY,
- this.pageService.getResourceService(). localizedActivityFunction())
- .withFilter(this.activityFilter)
- .sortable())
- .withDefaultAction(pageActionBuilder
- .newAction(ActionDefinition.SEB_CLIENT_CONFIG_VIEW_FROM_LIST)
- .create())
- .compose(pageContext.copyOf(content));
-
- final GrantCheck clientConfigGrant = this.currentUser.grantCheck(EntityType.SEB_CLIENT_CONFIGURATION);
-
- pageActionBuilder
-
- .newAction(ActionDefinition.SEB_CLIENT_CONFIG_NEW)
- .publishIf(clientConfigGrant::iw)
-
- .newAction(ActionDefinition.SEB_CLIENT_CONFIG_VIEW_FROM_LIST)
- .withSelect(table::getSelection, PageAction::applySingleSelectionAsEntityKey, EMPTY_SELECTION_TEXT_KEY)
- .publishIf(() -> table.hasAnyContent())
-
- .newAction(ActionDefinition.SEB_CLIENT_CONFIG_MODIFY_FROM_LIST)
- .withSelect(
- table.getGrantedSelection(this.currentUser, NO_MODIFY_PRIVILEGE_ON_OTHER_INSTITUION),
- PageAction::applySingleSelectionAsEntityKey, EMPTY_SELECTION_TEXT_KEY)
- .publishIf(() -> clientConfigGrant.im() && table.hasAnyContent());
-
- }
-
- private static Function clientConfigInstitutionNameFunction(
- final ResourceService resourceService) {
-
- return config -> resourceService.getInstitutionNameFunction()
- .apply(String.valueOf(config.institutionId));
- }
-
-}
+/*
+ * 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.content;
+
+import java.util.function.Function;
+
+import org.eclipse.swt.widgets.Composite;
+import org.joda.time.DateTime;
+import org.joda.time.DateTimeZone;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Lazy;
+import org.springframework.stereotype.Component;
+
+import ch.ethz.seb.sebserver.gbl.Constants;
+import ch.ethz.seb.sebserver.gbl.api.EntityType;
+import ch.ethz.seb.sebserver.gbl.model.Domain;
+import ch.ethz.seb.sebserver.gbl.model.Entity;
+import ch.ethz.seb.sebserver.gbl.model.sebconfig.SebClientConfig;
+import ch.ethz.seb.sebserver.gbl.model.user.UserInfo;
+import ch.ethz.seb.sebserver.gbl.model.user.UserRole;
+import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
+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.PageContext;
+import ch.ethz.seb.sebserver.gui.service.page.PageService;
+import ch.ethz.seb.sebserver.gui.service.page.PageService.PageActionBuilder;
+import ch.ethz.seb.sebserver.gui.service.page.TemplateComposer;
+import ch.ethz.seb.sebserver.gui.service.page.impl.PageAction;
+import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestService;
+import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.clientconfig.GetClientConfigPage;
+import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.CurrentUser;
+import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.CurrentUser.GrantCheck;
+import ch.ethz.seb.sebserver.gui.table.ColumnDefinition;
+import ch.ethz.seb.sebserver.gui.table.ColumnDefinition.TableFilterAttribute;
+import ch.ethz.seb.sebserver.gui.table.EntityTable;
+import ch.ethz.seb.sebserver.gui.table.TableFilter.CriteriaType;
+
+@Lazy
+@Component
+@GuiProfile
+public class SebClientConfigList implements TemplateComposer {
+
+ private static final LocTextKey NO_MODIFY_PRIVILEGE_ON_OTHER_INSTITUION =
+ new LocTextKey("sebserver.clientconfig.list.action.no.modify.privilege");
+ private static final LocTextKey EMPTY_LIST_TEXT_KEY =
+ new LocTextKey("sebserver.clientconfig.list.empty");
+ private static final LocTextKey TITLE_TEXT_KEY =
+ new LocTextKey("sebserver.clientconfig.list.title");
+ private static final LocTextKey INSTITUTION_TEXT_KEY =
+ new LocTextKey("sebserver.clientconfig.list.column.institution");
+ private static final LocTextKey NAME_TEXT_KEY =
+ new LocTextKey("sebserver.clientconfig.list.column.name");
+ private static final LocTextKey ACTIVE_TEXT_KEY =
+ new LocTextKey("sebserver.clientconfig.list.column.active");
+ private static final LocTextKey EMPTY_SELECTION_TEXT_KEY =
+ new LocTextKey("sebserver.clientconfig.info.pleaseSelect");
+
+ private final TableFilterAttribute institutionFilter;
+ private final TableFilterAttribute nameFilter =
+ new TableFilterAttribute(CriteriaType.TEXT, Entity.FILTER_ATTR_NAME);
+ private final TableFilterAttribute dateFilter =
+ new TableFilterAttribute(
+ CriteriaType.DATE,
+ SebClientConfig.FILTER_ATTR_CREATION_DATE,
+ DateTime.now(DateTimeZone.UTC)
+ .minusYears(1)
+ .toString(Constants.DEFAULT_DATE_TIME_FORMAT));
+ private final TableFilterAttribute activityFilter;
+
+ private final PageService pageService;
+ private final RestService restService;
+ private final CurrentUser currentUser;
+ private final ResourceService resourceService;
+ private final int pageSize;
+
+ protected SebClientConfigList(
+ final PageService pageService,
+ final RestService restService,
+ final CurrentUser currentUser,
+ @Value("${sebserver.gui.list.page.size:20}") final Integer pageSize) {
+
+ this.pageService = pageService;
+ this.restService = restService;
+ this.currentUser = currentUser;
+ this.resourceService = pageService.getResourceService();
+ this.pageSize = pageSize;
+
+ this.institutionFilter = new TableFilterAttribute(
+ CriteriaType.SINGLE_SELECTION,
+ Entity.FILTER_ATTR_INSTITUTION,
+ this.resourceService::institutionResource);
+
+ this.activityFilter = new TableFilterAttribute(
+ CriteriaType.SINGLE_SELECTION,
+ UserInfo.FILTER_ATTR_ACTIVE,
+ this.resourceService::activityResources);
+ }
+
+ @Override
+ public void compose(final PageContext pageContext) {
+
+ final I18nSupport i18nSupport = this.pageService.getI18nSupport();
+ final Composite content = this.pageService.getWidgetFactory().defaultPageLayout(
+ pageContext.getParent(),
+ TITLE_TEXT_KEY);
+
+ final boolean isSEBAdmin = this.currentUser.get().hasRole(UserRole.SEB_SERVER_ADMIN);
+ final PageActionBuilder pageActionBuilder =
+ this.pageService.pageActionBuilder(pageContext.clearEntityKeys());
+
+ // table
+ final EntityTable table =
+ this.pageService.entityTableBuilder(this.restService.getRestCall(GetClientConfigPage.class))
+ .withEmptyMessage(EMPTY_LIST_TEXT_KEY)
+ .withPaging(this.pageSize)
+ .withColumnIf(
+ () -> isSEBAdmin,
+ () -> new ColumnDefinition<>(
+ Domain.LMS_SETUP.ATTR_INSTITUTION_ID,
+ INSTITUTION_TEXT_KEY,
+ clientConfigInstitutionNameFunction(this.resourceService))
+ .withFilter(this.institutionFilter))
+ .withColumn(new ColumnDefinition<>(
+ Domain.SEB_CLIENT_CONFIGURATION.ATTR_NAME,
+ NAME_TEXT_KEY,
+ SebClientConfig::getName)
+ .withFilter(this.nameFilter)
+ .sortable())
+ .withColumn(new ColumnDefinition<>(
+ Domain.SEB_CLIENT_CONFIGURATION.ATTR_DATE,
+ new LocTextKey(
+ "sebserver.clientconfig.list.column.date",
+ i18nSupport.getUsersTimeZoneTitleSuffix()),
+ SebClientConfig::getDate)
+ .withFilter(this.dateFilter)
+ .sortable())
+ .withColumn(new ColumnDefinition<>(
+ Domain.SEB_CLIENT_CONFIGURATION.ATTR_ACTIVE,
+ ACTIVE_TEXT_KEY,
+ this.pageService.getResourceService(). localizedActivityFunction())
+ .withFilter(this.activityFilter)
+ .sortable())
+ .withDefaultAction(pageActionBuilder
+ .newAction(ActionDefinition.SEB_CLIENT_CONFIG_VIEW_FROM_LIST)
+ .create())
+
+ .withSelectionListener(this.pageService.getSelectionPublisher(
+ ActionDefinition.SEB_CLIENT_CONFIG_TOGGLE_ACTIVITY,
+ ActionDefinition.SEB_CLIENT_CONFIG_ACTIVATE,
+ ActionDefinition.SEB_CLIENT_CONFIG_DEACTIVATE,
+ pageContext,
+ ActionDefinition.SEB_CLIENT_CONFIG_VIEW_FROM_LIST,
+ ActionDefinition.SEB_CLIENT_CONFIG_MODIFY_FROM_LIST,
+ ActionDefinition.SEB_CLIENT_CONFIG_TOGGLE_ACTIVITY))
+
+ .compose(pageContext.copyOf(content));
+
+ final GrantCheck clientConfigGrant = this.currentUser.grantCheck(EntityType.SEB_CLIENT_CONFIGURATION);
+
+ pageActionBuilder
+
+ .newAction(ActionDefinition.SEB_CLIENT_CONFIG_NEW)
+ .publishIf(clientConfigGrant::iw)
+
+ .newAction(ActionDefinition.SEB_CLIENT_CONFIG_VIEW_FROM_LIST)
+ .withSelect(table::getSelection, PageAction::applySingleSelectionAsEntityKey, EMPTY_SELECTION_TEXT_KEY)
+ .publishIf(table::hasAnyContent, false)
+
+ .newAction(ActionDefinition.SEB_CLIENT_CONFIG_MODIFY_FROM_LIST)
+ .withSelect(
+ table.getGrantedSelection(this.currentUser, NO_MODIFY_PRIVILEGE_ON_OTHER_INSTITUION),
+ PageAction::applySingleSelectionAsEntityKey, EMPTY_SELECTION_TEXT_KEY)
+ .publishIf(() -> clientConfigGrant.im() && table.hasAnyContent(), false)
+
+ .newAction(ActionDefinition.SEB_CLIENT_CONFIG_TOGGLE_ACTIVITY)
+ .withExec(this.pageService.activationToggleActionFunction(table, EMPTY_SELECTION_TEXT_KEY))
+ .withConfirm(this.pageService.confirmDeactivation(table))
+ .publishIf(() -> clientConfigGrant.im() && table.hasAnyContent(), false);
+
+
+
+ }
+
+ private static Function clientConfigInstitutionNameFunction(
+ final ResourceService resourceService) {
+
+ return config -> resourceService.getInstitutionNameFunction()
+ .apply(String.valueOf(config.institutionId));
+ }
+
+}
diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/content/SebExamConfigList.java b/src/main/java/ch/ethz/seb/sebserver/gui/content/SebExamConfigList.java
index ec2783b1..6d923b73 100644
--- a/src/main/java/ch/ethz/seb/sebserver/gui/content/SebExamConfigList.java
+++ b/src/main/java/ch/ethz/seb/sebserver/gui/content/SebExamConfigList.java
@@ -1,174 +1,178 @@
-/*
- * 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.content;
-
-import org.eclipse.swt.widgets.Composite;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.context.annotation.Lazy;
-import org.springframework.stereotype.Component;
-
-import ch.ethz.seb.sebserver.gbl.api.EntityType;
-import ch.ethz.seb.sebserver.gbl.model.Domain;
-import ch.ethz.seb.sebserver.gbl.model.Entity;
-import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode;
-import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode.ConfigurationType;
-import ch.ethz.seb.sebserver.gbl.model.user.UserRole;
-import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
-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.LocTextKey;
-import ch.ethz.seb.sebserver.gui.service.page.PageContext;
-import ch.ethz.seb.sebserver.gui.service.page.PageService;
-import ch.ethz.seb.sebserver.gui.service.page.PageService.PageActionBuilder;
-import ch.ethz.seb.sebserver.gui.service.page.TemplateComposer;
-import ch.ethz.seb.sebserver.gui.service.page.impl.PageAction;
-import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestService;
-import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.GetExamConfigNodePage;
-import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.CurrentUser;
-import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.CurrentUser.GrantCheck;
-import ch.ethz.seb.sebserver.gui.table.ColumnDefinition;
-import ch.ethz.seb.sebserver.gui.table.ColumnDefinition.TableFilterAttribute;
-import ch.ethz.seb.sebserver.gui.table.EntityTable;
-import ch.ethz.seb.sebserver.gui.table.TableFilter.CriteriaType;
-import ch.ethz.seb.sebserver.gui.widget.WidgetFactory;
-
-@Lazy
-@Component
-@GuiProfile
-public class SebExamConfigList implements TemplateComposer {
-
- private static final LocTextKey NO_MODIFY_PRIVILEGE_ON_OTHER_INSTITUION =
- new LocTextKey("sebserver.examconfig.list.action.no.modify.privilege");
- private static final LocTextKey EMPTY_CONFIG_LIST_TEXT_KEY =
- new LocTextKey("sebserver.examconfig.list.empty");
- private static final LocTextKey TITLE_CONFIGURATION_TEXT_KEY =
- new LocTextKey("sebserver.examconfig.list.title");
- private static final LocTextKey INSTITUTION_TEXT_KEY =
- new LocTextKey("sebserver.examconfig.list.column.institution");
- private static final LocTextKey NAME_TEXT_KEY =
- new LocTextKey("sebserver.examconfig.list.column.name");
- private static final LocTextKey DESCRIPTION_TEXT_KEY =
- new LocTextKey("sebserver.examconfig.list.column.description");
- private static final LocTextKey STATUS_TEXT_KEY =
- new LocTextKey("sebserver.examconfig.list.column.status");
- private static final LocTextKey EMPTY_SELECTION_TEXT_KEY =
- new LocTextKey("sebserver.examconfig.info.pleaseSelect");
-
- private final TableFilterAttribute institutionFilter;
- private final TableFilterAttribute nameFilter =
- new TableFilterAttribute(CriteriaType.TEXT, Entity.FILTER_ATTR_NAME);
- private final TableFilterAttribute descFilter =
- new TableFilterAttribute(CriteriaType.TEXT, ConfigurationNode.FILTER_ATTR_DESCRIPTION);
- private final TableFilterAttribute statusFilter;
-
- private final PageService pageService;
- private final RestService restService;
- private final CurrentUser currentUser;
- private final ResourceService resourceService;
- private final int pageSize;
-
- protected SebExamConfigList(
- final PageService pageService,
- final RestService restService,
- final CurrentUser currentUser,
- @Value("${sebserver.gui.list.page.size:20}") final Integer pageSize) {
-
- this.pageService = pageService;
- this.restService = restService;
- this.currentUser = currentUser;
- this.resourceService = pageService.getResourceService();
- this.pageSize = pageSize;
-
- this.institutionFilter = new TableFilterAttribute(
- CriteriaType.SINGLE_SELECTION,
- Entity.FILTER_ATTR_INSTITUTION,
- this.resourceService::institutionResource);
-
- this.statusFilter = new TableFilterAttribute(
- CriteriaType.SINGLE_SELECTION,
- ConfigurationNode.FILTER_ATTR_STATUS,
- this.resourceService::examConfigStatusResources);
- }
-
- @Override
- public void compose(final PageContext pageContext) {
- final WidgetFactory widgetFactory = this.pageService.getWidgetFactory();
- final Composite content = widgetFactory.defaultPageLayout(
- pageContext.getParent(),
- TITLE_CONFIGURATION_TEXT_KEY);
-
- final boolean isSEBAdmin = this.currentUser.get().hasRole(UserRole.SEB_SERVER_ADMIN);
- final PageActionBuilder pageActionBuilder =
- this.pageService.pageActionBuilder(pageContext.clearEntityKeys());
-
- // exam configuration table
- final EntityTable configTable =
- this.pageService.entityTableBuilder(this.restService.getRestCall(GetExamConfigNodePage.class))
- .withStaticFilter(
- Domain.CONFIGURATION_NODE.ATTR_TYPE,
- ConfigurationType.EXAM_CONFIG.name())
- .withEmptyMessage(EMPTY_CONFIG_LIST_TEXT_KEY)
- .withPaging(this.pageSize)
- .withColumnIf(
- () -> isSEBAdmin,
- () -> new ColumnDefinition<>(
- Domain.LMS_SETUP.ATTR_INSTITUTION_ID,
- INSTITUTION_TEXT_KEY,
- this.resourceService::localizedExamConfigInstitutionName)
- .withFilter(this.institutionFilter)
- .sortable())
- .withColumn(new ColumnDefinition<>(
- Domain.CONFIGURATION_NODE.ATTR_NAME,
- NAME_TEXT_KEY,
- ConfigurationNode::getName)
- .withFilter(this.nameFilter)
- .sortable())
- .withColumn(new ColumnDefinition<>(
- Domain.CONFIGURATION_NODE.ATTR_DESCRIPTION,
- DESCRIPTION_TEXT_KEY,
- ConfigurationNode::getDescription)
- .withFilter(this.descFilter)
- .sortable())
- .withColumn(new ColumnDefinition(
- Domain.CONFIGURATION_NODE.ATTR_STATUS,
- STATUS_TEXT_KEY,
- this.resourceService::localizedExamConfigStatusName)
- .withFilter(this.statusFilter)
- .sortable())
- .withDefaultAction(pageActionBuilder
- .newAction(ActionDefinition.SEB_EXAM_CONFIG_VIEW_PROP_FROM_LIST)
- .create())
- .compose(pageContext.copyOf(content));
-
- final GrantCheck examConfigGrant = this.currentUser.grantCheck(EntityType.CONFIGURATION_NODE);
- pageActionBuilder
- // Exam Configuration actions...
- .newAction(ActionDefinition.SEB_EXAM_CONFIG_NEW)
- .publishIf(examConfigGrant::iw)
-
- .newAction(ActionDefinition.SEB_EXAM_CONFIG_VIEW_PROP_FROM_LIST)
- .withSelect(configTable::getSelection, PageAction::applySingleSelectionAsEntityKey,
- EMPTY_SELECTION_TEXT_KEY)
- .publishIf(() -> configTable.hasAnyContent())
-
- .newAction(ActionDefinition.SEB_EXAM_CONFIG_MODIFY_PROP_FROM_LIST)
- .withSelect(
- configTable.getGrantedSelection(this.currentUser, NO_MODIFY_PRIVILEGE_ON_OTHER_INSTITUION),
- PageAction::applySingleSelectionAsEntityKey, EMPTY_SELECTION_TEXT_KEY)
- .publishIf(() -> examConfigGrant.im() && configTable.hasAnyContent())
-
- .newAction(ActionDefinition.SEB_EXAM_CONFIG_IMPORT_TO_NEW_CONFIG)
- .withExec(SebExamConfigImportPopup.importFunction(this.pageService, true))
- .noEventPropagation()
- .publishIf(() -> examConfigGrant.im())
-
- ;
- }
-
-}
+/*
+ * 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.content;
+
+import org.eclipse.swt.widgets.Composite;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Lazy;
+import org.springframework.stereotype.Component;
+
+import ch.ethz.seb.sebserver.gbl.api.EntityType;
+import ch.ethz.seb.sebserver.gbl.model.Domain;
+import ch.ethz.seb.sebserver.gbl.model.Entity;
+import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode;
+import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode.ConfigurationType;
+import ch.ethz.seb.sebserver.gbl.model.user.UserRole;
+import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
+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.LocTextKey;
+import ch.ethz.seb.sebserver.gui.service.page.PageContext;
+import ch.ethz.seb.sebserver.gui.service.page.PageService;
+import ch.ethz.seb.sebserver.gui.service.page.PageService.PageActionBuilder;
+import ch.ethz.seb.sebserver.gui.service.page.TemplateComposer;
+import ch.ethz.seb.sebserver.gui.service.page.impl.PageAction;
+import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestService;
+import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.GetExamConfigNodePage;
+import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.CurrentUser;
+import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.CurrentUser.GrantCheck;
+import ch.ethz.seb.sebserver.gui.table.ColumnDefinition;
+import ch.ethz.seb.sebserver.gui.table.ColumnDefinition.TableFilterAttribute;
+import ch.ethz.seb.sebserver.gui.table.EntityTable;
+import ch.ethz.seb.sebserver.gui.table.TableFilter.CriteriaType;
+import ch.ethz.seb.sebserver.gui.widget.WidgetFactory;
+
+@Lazy
+@Component
+@GuiProfile
+public class SebExamConfigList implements TemplateComposer {
+
+ private static final LocTextKey NO_MODIFY_PRIVILEGE_ON_OTHER_INSTITUION =
+ new LocTextKey("sebserver.examconfig.list.action.no.modify.privilege");
+ private static final LocTextKey EMPTY_CONFIG_LIST_TEXT_KEY =
+ new LocTextKey("sebserver.examconfig.list.empty");
+ private static final LocTextKey TITLE_CONFIGURATION_TEXT_KEY =
+ new LocTextKey("sebserver.examconfig.list.title");
+ private static final LocTextKey INSTITUTION_TEXT_KEY =
+ new LocTextKey("sebserver.examconfig.list.column.institution");
+ private static final LocTextKey NAME_TEXT_KEY =
+ new LocTextKey("sebserver.examconfig.list.column.name");
+ private static final LocTextKey DESCRIPTION_TEXT_KEY =
+ new LocTextKey("sebserver.examconfig.list.column.description");
+ private static final LocTextKey STATUS_TEXT_KEY =
+ new LocTextKey("sebserver.examconfig.list.column.status");
+ private static final LocTextKey EMPTY_SELECTION_TEXT_KEY =
+ new LocTextKey("sebserver.examconfig.info.pleaseSelect");
+
+ private final TableFilterAttribute institutionFilter;
+ private final TableFilterAttribute nameFilter =
+ new TableFilterAttribute(CriteriaType.TEXT, Entity.FILTER_ATTR_NAME);
+ private final TableFilterAttribute descFilter =
+ new TableFilterAttribute(CriteriaType.TEXT, ConfigurationNode.FILTER_ATTR_DESCRIPTION);
+ private final TableFilterAttribute statusFilter;
+
+ private final PageService pageService;
+ private final RestService restService;
+ private final CurrentUser currentUser;
+ private final ResourceService resourceService;
+ private final int pageSize;
+
+ protected SebExamConfigList(
+ final PageService pageService,
+ final RestService restService,
+ final CurrentUser currentUser,
+ @Value("${sebserver.gui.list.page.size:20}") final Integer pageSize) {
+
+ this.pageService = pageService;
+ this.restService = restService;
+ this.currentUser = currentUser;
+ this.resourceService = pageService.getResourceService();
+ this.pageSize = pageSize;
+
+ this.institutionFilter = new TableFilterAttribute(
+ CriteriaType.SINGLE_SELECTION,
+ Entity.FILTER_ATTR_INSTITUTION,
+ this.resourceService::institutionResource);
+
+ this.statusFilter = new TableFilterAttribute(
+ CriteriaType.SINGLE_SELECTION,
+ ConfigurationNode.FILTER_ATTR_STATUS,
+ this.resourceService::examConfigStatusResources);
+ }
+
+ @Override
+ public void compose(final PageContext pageContext) {
+ final WidgetFactory widgetFactory = this.pageService.getWidgetFactory();
+ final Composite content = widgetFactory.defaultPageLayout(
+ pageContext.getParent(),
+ TITLE_CONFIGURATION_TEXT_KEY);
+
+ final boolean isSEBAdmin = this.currentUser.get().hasRole(UserRole.SEB_SERVER_ADMIN);
+ final PageActionBuilder pageActionBuilder =
+ this.pageService.pageActionBuilder(pageContext.clearEntityKeys());
+
+ // exam configuration table
+ final EntityTable configTable =
+ this.pageService.entityTableBuilder(this.restService.getRestCall(GetExamConfigNodePage.class))
+ .withStaticFilter(
+ Domain.CONFIGURATION_NODE.ATTR_TYPE,
+ ConfigurationType.EXAM_CONFIG.name())
+ .withEmptyMessage(EMPTY_CONFIG_LIST_TEXT_KEY)
+ .withPaging(this.pageSize)
+ .withColumnIf(
+ () -> isSEBAdmin,
+ () -> new ColumnDefinition<>(
+ Domain.LMS_SETUP.ATTR_INSTITUTION_ID,
+ INSTITUTION_TEXT_KEY,
+ this.resourceService::localizedExamConfigInstitutionName)
+ .withFilter(this.institutionFilter)
+ .sortable())
+ .withColumn(new ColumnDefinition<>(
+ Domain.CONFIGURATION_NODE.ATTR_NAME,
+ NAME_TEXT_KEY,
+ ConfigurationNode::getName)
+ .withFilter(this.nameFilter)
+ .sortable())
+ .withColumn(new ColumnDefinition<>(
+ Domain.CONFIGURATION_NODE.ATTR_DESCRIPTION,
+ DESCRIPTION_TEXT_KEY,
+ ConfigurationNode::getDescription)
+ .withFilter(this.descFilter)
+ .sortable())
+ .withColumn(new ColumnDefinition(
+ Domain.CONFIGURATION_NODE.ATTR_STATUS,
+ STATUS_TEXT_KEY,
+ this.resourceService::localizedExamConfigStatusName)
+ .withFilter(this.statusFilter)
+ .sortable())
+ .withDefaultAction(pageActionBuilder
+ .newAction(ActionDefinition.SEB_EXAM_CONFIG_VIEW_PROP_FROM_LIST)
+ .create())
+
+ .withSelectionListener(this.pageService.getSelectionPublisher(
+ pageContext,
+ ActionDefinition.SEB_EXAM_CONFIG_VIEW_PROP_FROM_LIST,
+ ActionDefinition.SEB_EXAM_CONFIG_MODIFY_PROP_FROM_LIST))
+
+ .compose(pageContext.copyOf(content));
+
+ final GrantCheck examConfigGrant = this.currentUser.grantCheck(EntityType.CONFIGURATION_NODE);
+ pageActionBuilder
+ // Exam Configuration actions...
+ .newAction(ActionDefinition.SEB_EXAM_CONFIG_NEW)
+ .publishIf(examConfigGrant::iw)
+
+ .newAction(ActionDefinition.SEB_EXAM_CONFIG_VIEW_PROP_FROM_LIST)
+ .withSelect(configTable::getSelection, PageAction::applySingleSelectionAsEntityKey,
+ EMPTY_SELECTION_TEXT_KEY)
+ .publishIf(configTable::hasAnyContent, false)
+
+ .newAction(ActionDefinition.SEB_EXAM_CONFIG_MODIFY_PROP_FROM_LIST)
+ .withSelect(
+ configTable.getGrantedSelection(this.currentUser, NO_MODIFY_PRIVILEGE_ON_OTHER_INSTITUION),
+ PageAction::applySingleSelectionAsEntityKey, EMPTY_SELECTION_TEXT_KEY)
+ .publishIf(() -> examConfigGrant.im() && configTable.hasAnyContent(), false)
+
+ .newAction(ActionDefinition.SEB_EXAM_CONFIG_IMPORT_TO_NEW_CONFIG)
+ .withExec(SebExamConfigImportPopup.importFunction(this.pageService, true))
+ .noEventPropagation()
+ .publishIf(examConfigGrant::im);
+ }
+
+}
diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/content/SebExamConfigPropForm.java b/src/main/java/ch/ethz/seb/sebserver/gui/content/SebExamConfigPropForm.java
index f90c31a0..abc15f1a 100644
--- a/src/main/java/ch/ethz/seb/sebserver/gui/content/SebExamConfigPropForm.java
+++ b/src/main/java/ch/ethz/seb/sebserver/gui/content/SebExamConfigPropForm.java
@@ -1,413 +1,423 @@
-/*
- * 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.content;
-
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.List;
-import java.util.function.Function;
-
-import org.eclipse.rap.rwt.RWT;
-import org.eclipse.rap.rwt.client.service.UrlLauncher;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Text;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.context.annotation.Lazy;
-import org.springframework.stereotype.Component;
-
-import ch.ethz.seb.sebserver.gbl.Constants;
-import ch.ethz.seb.sebserver.gbl.api.API;
-import ch.ethz.seb.sebserver.gbl.api.EntityType;
-import ch.ethz.seb.sebserver.gbl.model.Domain;
-import ch.ethz.seb.sebserver.gbl.model.EntityKey;
-import ch.ethz.seb.sebserver.gbl.model.exam.ExamConfigurationMap;
-import ch.ethz.seb.sebserver.gbl.model.exam.QuizData;
-import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigKey;
-import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode;
-import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode.ConfigurationStatus;
-import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode.ConfigurationType;
-import ch.ethz.seb.sebserver.gbl.model.user.UserInfo;
-import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
-import ch.ethz.seb.sebserver.gbl.util.Tuple;
-import ch.ethz.seb.sebserver.gui.content.action.ActionDefinition;
-import ch.ethz.seb.sebserver.gui.form.FormBuilder;
-import ch.ethz.seb.sebserver.gui.form.FormHandle;
-import ch.ethz.seb.sebserver.gui.service.ResourceService;
-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.PageMessageException;
-import ch.ethz.seb.sebserver.gui.service.page.PageService;
-import ch.ethz.seb.sebserver.gui.service.page.PageService.PageActionBuilder;
-import ch.ethz.seb.sebserver.gui.service.page.TemplateComposer;
-import ch.ethz.seb.sebserver.gui.service.page.impl.ModalInputDialog;
-import ch.ethz.seb.sebserver.gui.service.page.impl.PageAction;
-import ch.ethz.seb.sebserver.gui.service.remote.download.DownloadService;
-import ch.ethz.seb.sebserver.gui.service.remote.download.SebExamConfigPlaintextDownload;
-import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestService;
-import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.GetExamConfigMappingNames;
-import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.GetExamConfigMappingsPage;
-import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.ExportConfigKey;
-import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.GetExamConfigNode;
-import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.NewExamConfig;
-import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.SaveExamConfig;
-import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.CurrentUser;
-import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.CurrentUser.EntityGrantCheck;
-import ch.ethz.seb.sebserver.gui.table.ColumnDefinition;
-import ch.ethz.seb.sebserver.gui.table.EntityTable;
-import ch.ethz.seb.sebserver.gui.widget.WidgetFactory;
-import ch.ethz.seb.sebserver.gui.widget.WidgetFactory.CustomVariant;
-
-@Lazy
-@Component
-@GuiProfile
-public class SebExamConfigPropForm implements TemplateComposer {
-
- static final LocTextKey FORM_TITLE_NEW =
- new LocTextKey("sebserver.examconfig.form.title.new");
- static final LocTextKey FORM_TITLE =
- new LocTextKey("sebserver.examconfig.form.title");
- static final LocTextKey FORM_NAME_TEXT_KEY =
- new LocTextKey("sebserver.examconfig.form.name");
- static final LocTextKey FORM_DESCRIPTION_TEXT_KEY =
- new LocTextKey("sebserver.examconfig.form.description");
- static final LocTextKey FORM_HISTORY_TEXT_KEY =
- new LocTextKey("sebserver.examconfig.form.with-history");
- static final LocTextKey FORM_TEMPLATE_TEXT_KEY =
- new LocTextKey("sebserver.examconfig.form.template");
- static final LocTextKey FORM_STATUS_TEXT_KEY =
- new LocTextKey("sebserver.examconfig.form.status");
- static final LocTextKey FORM_IMPORT_TEXT_KEY =
- new LocTextKey("sebserver.examconfig.action.import-config");
- static final LocTextKey FORM_IMPORT_SELECT_TEXT_KEY =
- new LocTextKey("sebserver.examconfig.action.import-file-select");
- static final LocTextKey FORM_IMPORT_PASSWORD_TEXT_KEY =
- new LocTextKey("sebserver.examconfig.action.import-file-password");
- static final LocTextKey CONFIG_KEY_TITLE_TEXT_KEY =
- new LocTextKey("sebserver.examconfig.form.config-key.title");
- static final LocTextKey FORM_IMPORT_CONFIRM_TEXT_KEY =
- new LocTextKey("sebserver.examconfig.action.import-config.confirm");
- static final LocTextKey FORM_ATTACHED_EXAMS_TITLE_TEXT_KEY =
- new LocTextKey("sebserver.examconfig.form.attched-to");
-
- static final LocTextKey SAVE_CONFIRM_STATE_CHANGE_WHILE_ATTACHED =
- new LocTextKey("sebserver.examconfig.action.state-change.confirm");
-
- private final PageService pageService;
- private final RestService restService;
- private final CurrentUser currentUser;
- private final DownloadService downloadService;
- private final String downloadFileName;
-
- protected SebExamConfigPropForm(
- final PageService pageService,
- final CurrentUser currentUser,
- final DownloadService downloadService,
- @Value("${sebserver.gui.seb.exam.config.download.filename}") final String downloadFileName) {
-
- this.pageService = pageService;
- this.restService = pageService.getRestService();
- this.currentUser = currentUser;
- this.downloadService = downloadService;
- this.downloadFileName = downloadFileName;
- }
-
- @Override
- public void compose(final PageContext pageContext) {
- final WidgetFactory widgetFactory = this.pageService.getWidgetFactory();
- final ResourceService resourceService = this.pageService.getResourceService();
-
- final UserInfo user = this.currentUser.get();
- final EntityKey entityKey = pageContext.getEntityKey();
- final EntityKey parentEntityKey = pageContext.getParentEntityKey();
- final boolean isNew = entityKey == null;
-
- // get data or create new. Handle error if happen
- final ConfigurationNode examConfig = (isNew)
- ? ConfigurationNode.createNewExamConfig(user.institutionId)
- : this.restService
- .getBuilder(GetExamConfigNode.class)
- .withURIVariable(API.PARAM_MODEL_ID, entityKey.modelId)
- .call()
- .onError(error -> pageContext.notifyLoadError(EntityType.CONFIGURATION_NODE, error))
- .getOrThrow();
-
- final EntityGrantCheck entityGrant = this.currentUser.entityGrantCheck(examConfig);
- final boolean writeGrant = entityGrant.w();
- final boolean modifyGrant = entityGrant.m();
- final boolean isReadonly = pageContext.isReadonly();
- final boolean isAttachedToExam = !isNew && this.restService
- .getBuilder(GetExamConfigMappingNames.class)
- .withQueryParam(ExamConfigurationMap.FILTER_ATTR_CONFIG_ID, examConfig.getModelId())
- .call()
- .map(names -> names != null && !names.isEmpty())
- .getOr(Boolean.FALSE);
-
- // new PageContext with actual EntityKey
- final PageContext formContext = pageContext.withEntityKey(examConfig.getEntityKey());
-
- // the default page layout with interactive title
- final LocTextKey titleKey = (isNew)
- ? FORM_TITLE_NEW
- : FORM_TITLE;
- final Composite content = widgetFactory.defaultPageLayout(
- formContext.getParent(),
- titleKey);
-
- final List> examConfigTemplateResources = resourceService.getExamConfigTemplateResources();
- final FormHandle formHandle = this.pageService.formBuilder(
- formContext.copyOf(content))
- .readonly(isReadonly)
- .putStaticValueIf(() -> !isNew,
- Domain.CONFIGURATION_NODE.ATTR_ID,
- examConfig.getModelId())
- .putStaticValue(
- Domain.CONFIGURATION_NODE.ATTR_INSTITUTION_ID,
- String.valueOf(examConfig.getInstitutionId()))
- .putStaticValue(
- Domain.CONFIGURATION_NODE.ATTR_TYPE,
- ConfigurationType.EXAM_CONFIG.name())
- .addFieldIf(
- () -> !examConfigTemplateResources.isEmpty(),
- () -> FormBuilder.singleSelection(
- Domain.CONFIGURATION_NODE.ATTR_TEMPLATE_ID,
- FORM_TEMPLATE_TEXT_KEY,
- (parentEntityKey != null)
- ? parentEntityKey.modelId
- : String.valueOf(examConfig.templateId),
- resourceService::getExamConfigTemplateResources)
- .readonly(!isNew))
- .addField(FormBuilder.text(
- Domain.CONFIGURATION_NODE.ATTR_NAME,
- FORM_NAME_TEXT_KEY,
- examConfig.name))
- .addField(FormBuilder.text(
- Domain.CONFIGURATION_NODE.ATTR_DESCRIPTION,
- FORM_DESCRIPTION_TEXT_KEY,
- examConfig.description)
- .asArea())
-
- .addField(FormBuilder.singleSelection(
- Domain.CONFIGURATION_NODE.ATTR_STATUS,
- FORM_STATUS_TEXT_KEY,
- examConfig.status.name(),
- () -> resourceService.examConfigStatusResources(isAttachedToExam))
- .withEmptyCellSeparation((isReadonly) ? false : true))
- .buildFor((isNew)
- ? this.restService.getRestCall(NewExamConfig.class)
- : this.restService.getRestCall(SaveExamConfig.class));
-
- final boolean settingsReadonly = examConfig.status == ConfigurationStatus.IN_USE;
- final UrlLauncher urlLauncher = RWT.getClient().getService(UrlLauncher.class);
- final PageContext actionContext = formContext.clearEntityKeys();
- final PageActionBuilder actionBuilder = this.pageService.pageActionBuilder(actionContext);
- actionBuilder
-
- .newAction(ActionDefinition.SEB_EXAM_CONFIG_NEW)
- .publishIf(() -> writeGrant && isReadonly)
-
- .newAction(ActionDefinition.SEB_EXAM_CONFIG_PROP_MODIFY)
- .withEntityKey(entityKey)
- .publishIf(() -> modifyGrant && isReadonly)
-
- .newAction(ActionDefinition.SEB_EXAM_CONFIG_VIEW)
- .withEntityKey(entityKey)
- .publishIf(() -> isReadonly)
-
- .newAction(ActionDefinition.SEB_EXAM_CONFIG_MODIFY)
- .withEntityKey(entityKey)
- .publishIf(() -> modifyGrant && isReadonly && !settingsReadonly)
-
- .newAction(ActionDefinition.SEB_EXAM_CONFIG_EXPORT_PLAIN_XML)
- .withEntityKey(entityKey)
- .withExec(action -> {
- final String downloadURL = this.downloadService.createDownloadURL(
- entityKey.modelId,
- SebExamConfigPlaintextDownload.class,
- this.downloadFileName);
- urlLauncher.openURL(downloadURL);
- return action;
- })
- .noEventPropagation()
- .publishIf(() -> modifyGrant && isReadonly)
-
- .newAction(ActionDefinition.SEB_EXAM_CONFIG_GET_CONFIG_KEY)
- .withEntityKey(entityKey)
- .withExec(SebExamConfigPropForm.getConfigKeyFunction(this.pageService))
- .noEventPropagation()
- .publishIf(() -> modifyGrant && isReadonly)
-
- .newAction(ActionDefinition.SEB_EXAM_CONFIG_IMPORT_TO_EXISTING_CONFIG)
- .withEntityKey(entityKey)
- .withExec(SebExamConfigImportPopup.importFunction(this.pageService, false))
- .noEventPropagation()
- .publishIf(() -> modifyGrant && isReadonly && !isAttachedToExam)
-
- .newAction(ActionDefinition.SEB_EXAM_CONFIG_COPY_CONFIG)
- .withEntityKey(entityKey)
- .withExec(SebExamConfigCreationPopup.configCreationFunction(
- this.pageService,
- actionContext
- .withEntityKey(entityKey)
- .withAttribute(
- PageContext.AttributeKeys.COPY_AS_TEMPLATE,
- Constants.FALSE_STRING)
- .withAttribute(
- PageContext.AttributeKeys.CREATE_FROM_TEMPLATE,
- Constants.FALSE_STRING)))
- .noEventPropagation()
- .publishIf(() -> modifyGrant && isReadonly)
-
- .newAction(ActionDefinition.SEB_EXAM_CONFIG_COPY_CONFIG_AS_TEMPALTE)
- .withEntityKey(entityKey)
- .withExec(SebExamConfigCreationPopup.configCreationFunction(
- this.pageService,
- pageContext.withAttribute(
- PageContext.AttributeKeys.COPY_AS_TEMPLATE,
- Constants.TRUE_STRING)))
- .noEventPropagation()
- .publishIf(() -> modifyGrant && isReadonly)
-
- .newAction(ActionDefinition.SEB_EXAM_CONFIG_PROP_SAVE)
- .withEntityKey(entityKey)
- .withExec(formHandle::processFormSave)
- .ignoreMoveAwayFromEdit()
- .withConfirm(() -> stateChangeConfirm(isAttachedToExam, formHandle))
- .publishIf(() -> !isReadonly)
-
- .newAction(ActionDefinition.SEB_EXAM_CONFIG_PROP_CANCEL_MODIFY)
- .withEntityKey(entityKey)
- .withExec(this.pageService.backToCurrentFunction())
- .publishIf(() -> !isReadonly);
-
- if (isAttachedToExam && isReadonly) {
-
- widgetFactory.labelSeparator(content);
- widgetFactory.labelLocalized(
- content,
- CustomVariant.TEXT_H3,
- FORM_ATTACHED_EXAMS_TITLE_TEXT_KEY);
-
- final EntityTable table =
- this.pageService.entityTableBuilder(this.restService.getRestCall(GetExamConfigMappingsPage.class))
- .withRestCallAdapter(restCall -> restCall.withQueryParam(
- ExamConfigurationMap.FILTER_ATTR_CONFIG_ID, examConfig.getModelId()))
- .withPaging(1)
- .hideNavigation()
- .withRowDecorator(ExamList.decorateOnExamMapConsistency(this.pageService))
-
- .withColumn(new ColumnDefinition<>(
- QuizData.QUIZ_ATTR_NAME,
- ExamList.COLUMN_TITLE_NAME_KEY,
- ExamConfigurationMap::getExamName))
-
- .withColumn(new ColumnDefinition<>(
- QuizData.QUIZ_ATTR_START_TIME,
- new LocTextKey(
- ExamList.EXAM_LIST_COLUMN_STARTTIME,
- this.pageService.getI18nSupport().getUsersTimeZoneTitleSuffix()),
- ExamConfigurationMap::getExamStartTime))
-
- .withColumn(new ColumnDefinition(
- Domain.EXAM.ATTR_TYPE,
- ExamList.COLUMN_TITLE_TYPE_KEY,
- resourceService::localizedExamTypeName))
-
- .withDefaultAction(this::showExamAction)
-
- .compose(pageContext.copyOf(content));
-
- actionBuilder
-
- .newAction(ActionDefinition.EXAM_VIEW_FROM_LIST)
- .withExec(pageAction -> {
- final ExamConfigurationMap selectedExamMapping = getSelectedExamMapping(table);
- return pageAction.withEntityKey(
- new EntityKey(selectedExamMapping.examId, EntityType.EXAM));
- })
- .publishIf(table::hasAnyContent);
- }
- }
-
- private PageAction showExamAction(final EntityTable table) {
- return this.pageService.pageActionBuilder(table.getPageContext())
- .newAction(ActionDefinition.EXAM_VIEW_FROM_LIST)
- .withSelectionSupplier(() -> {
- final ExamConfigurationMap selectedROWData = getSelectedExamMapping(table);
- return new HashSet<>(Arrays.asList(new EntityKey(selectedROWData.examId, EntityType.EXAM)));
- })
- .withExec(PageAction::applySingleSelectionAsEntityKey)
- .create();
- }
-
- private ExamConfigurationMap getSelectedExamMapping(final EntityTable table) {
- final ExamConfigurationMap selectedROWData = table.getSingleSelectedROWData();
-
- if (selectedROWData == null) {
- throw new PageMessageException(ExamList.EMPTY_SELECTION_TEXT_KEY);
- }
- return selectedROWData;
- }
-
- private LocTextKey stateChangeConfirm(
- final boolean isAttachedToExam,
- final FormHandle formHandle) {
-
- if (isAttachedToExam) {
- final String fieldValue = formHandle
- .getForm()
- .getFieldValue(Domain.CONFIGURATION_NODE.ATTR_STATUS);
-
- if (fieldValue != null) {
- final ConfigurationStatus state = ConfigurationStatus.valueOf(fieldValue);
- if (state != ConfigurationStatus.IN_USE) {
- return SAVE_CONFIRM_STATE_CHANGE_WHILE_ATTACHED;
- }
- }
- }
-
- return null;
- }
-
- public static Function getConfigKeyFunction(final PageService pageService) {
- final RestService restService = pageService.getResourceService().getRestService();
- return action -> {
- final ConfigKey configKey = restService.getBuilder(ExportConfigKey.class)
- .withURIVariable(API.PARAM_MODEL_ID, action.getEntityKey().modelId)
- .call()
- .getOrThrow();
-
- final WidgetFactory widgetFactory = pageService.getWidgetFactory();
- final ModalInputDialog dialog = new ModalInputDialog<>(
- action.pageContext().getParent().getShell(),
- widgetFactory);
-
- dialog.setDialogWidth(500);
-
- dialog.open(
- CONFIG_KEY_TITLE_TEXT_KEY,
- action.pageContext(),
- pc -> {
- final Composite content = widgetFactory.defaultPageLayout(
- pc.getParent());
-
- widgetFactory.labelLocalized(
- content,
- CustomVariant.TEXT_H3,
- CONFIG_KEY_TITLE_TEXT_KEY);
-
- final Text text = new Text(content, SWT.NONE);
- text.setEditable(false);
- text.setText(configKey.key);
- });
- return action;
- };
- }
-
-}
+/*
+ * 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.content;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.function.Function;
+
+import org.apache.commons.lang3.StringUtils;
+import org.eclipse.rap.rwt.RWT;
+import org.eclipse.rap.rwt.client.service.UrlLauncher;
+import org.eclipse.swt.SWT;
+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;
+
+import ch.ethz.seb.sebserver.gbl.Constants;
+import ch.ethz.seb.sebserver.gbl.api.API;
+import ch.ethz.seb.sebserver.gbl.api.EntityType;
+import ch.ethz.seb.sebserver.gbl.model.Domain;
+import ch.ethz.seb.sebserver.gbl.model.EntityKey;
+import ch.ethz.seb.sebserver.gbl.model.exam.ExamConfigurationMap;
+import ch.ethz.seb.sebserver.gbl.model.exam.QuizData;
+import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigKey;
+import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode;
+import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode.ConfigurationStatus;
+import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode.ConfigurationType;
+import ch.ethz.seb.sebserver.gbl.model.user.UserInfo;
+import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
+import ch.ethz.seb.sebserver.gbl.util.Tuple;
+import ch.ethz.seb.sebserver.gui.content.action.ActionDefinition;
+import ch.ethz.seb.sebserver.gui.form.FormBuilder;
+import ch.ethz.seb.sebserver.gui.form.FormHandle;
+import ch.ethz.seb.sebserver.gui.service.ResourceService;
+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.PageMessageException;
+import ch.ethz.seb.sebserver.gui.service.page.PageService;
+import ch.ethz.seb.sebserver.gui.service.page.PageService.PageActionBuilder;
+import ch.ethz.seb.sebserver.gui.service.page.TemplateComposer;
+import ch.ethz.seb.sebserver.gui.service.page.impl.ModalInputDialog;
+import ch.ethz.seb.sebserver.gui.service.page.impl.PageAction;
+import ch.ethz.seb.sebserver.gui.service.remote.download.DownloadService;
+import ch.ethz.seb.sebserver.gui.service.remote.download.SebExamConfigPlaintextDownload;
+import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestService;
+import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.GetExamConfigMappingNames;
+import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.GetExamConfigMappingsPage;
+import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.ExportConfigKey;
+import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.GetExamConfigNode;
+import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.NewExamConfig;
+import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.SaveExamConfig;
+import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.CurrentUser;
+import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.CurrentUser.EntityGrantCheck;
+import ch.ethz.seb.sebserver.gui.table.ColumnDefinition;
+import ch.ethz.seb.sebserver.gui.table.EntityTable;
+import ch.ethz.seb.sebserver.gui.widget.WidgetFactory;
+import ch.ethz.seb.sebserver.gui.widget.WidgetFactory.CustomVariant;
+
+@Lazy
+@Component
+@GuiProfile
+public class SebExamConfigPropForm implements TemplateComposer {
+
+ static final LocTextKey FORM_TITLE_NEW =
+ new LocTextKey("sebserver.examconfig.form.title.new");
+ static final LocTextKey FORM_TITLE =
+ new LocTextKey("sebserver.examconfig.form.title");
+ static final LocTextKey FORM_NAME_TEXT_KEY =
+ new LocTextKey("sebserver.examconfig.form.name");
+ static final LocTextKey FORM_DESCRIPTION_TEXT_KEY =
+ new LocTextKey("sebserver.examconfig.form.description");
+ static final LocTextKey FORM_HISTORY_TEXT_KEY =
+ new LocTextKey("sebserver.examconfig.form.with-history");
+ static final LocTextKey FORM_TEMPLATE_TEXT_KEY =
+ new LocTextKey("sebserver.examconfig.form.template");
+ static final LocTextKey FORM_STATUS_TEXT_KEY =
+ new LocTextKey("sebserver.examconfig.form.status");
+ static final LocTextKey FORM_IMPORT_TEXT_KEY =
+ new LocTextKey("sebserver.examconfig.action.import-config");
+ static final LocTextKey FORM_IMPORT_SELECT_TEXT_KEY =
+ new LocTextKey("sebserver.examconfig.action.import-file-select");
+ static final LocTextKey FORM_IMPORT_PASSWORD_TEXT_KEY =
+ new LocTextKey("sebserver.examconfig.action.import-file-password");
+ static final LocTextKey CONFIG_KEY_TITLE_TEXT_KEY =
+ new LocTextKey("sebserver.examconfig.form.config-key.title");
+ static final LocTextKey FORM_IMPORT_CONFIRM_TEXT_KEY =
+ new LocTextKey("sebserver.examconfig.action.import-config.confirm");
+ static final LocTextKey FORM_ATTACHED_EXAMS_TITLE_TEXT_KEY =
+ new LocTextKey("sebserver.examconfig.form.attached-to");
+ static final LocTextKey FORM_ATTACHED_EXAMS_TITLE_TOOLTIP_TEXT_KEY =
+ new LocTextKey("sebserver.examconfig.form.attached-to" + Constants.TOOLTIP_TEXT_KEY_SUFFIX);
+
+ static final LocTextKey SAVE_CONFIRM_STATE_CHANGE_WHILE_ATTACHED =
+ new LocTextKey("sebserver.examconfig.action.state-change.confirm");
+
+ private final PageService pageService;
+ private final RestService restService;
+ private final CurrentUser currentUser;
+ private final DownloadService downloadService;
+ private final String downloadFileName;
+
+ protected SebExamConfigPropForm(
+ final PageService pageService,
+ final CurrentUser currentUser,
+ final DownloadService downloadService,
+ @Value("${sebserver.gui.seb.exam.config.download.filename}") final String downloadFileName) {
+
+ this.pageService = pageService;
+ this.restService = pageService.getRestService();
+ this.currentUser = currentUser;
+ this.downloadService = downloadService;
+ this.downloadFileName = downloadFileName;
+ }
+
+ @Override
+ public void compose(final PageContext pageContext) {
+ final WidgetFactory widgetFactory = this.pageService.getWidgetFactory();
+ final ResourceService resourceService = this.pageService.getResourceService();
+
+ final UserInfo user = this.currentUser.get();
+ final EntityKey entityKey = pageContext.getEntityKey();
+ final EntityKey parentEntityKey = pageContext.getParentEntityKey();
+ final boolean isNew = entityKey == null;
+
+ // get data or create new. Handle error if happen
+ final ConfigurationNode examConfig = (isNew)
+ ? ConfigurationNode.createNewExamConfig(user.institutionId)
+ : this.restService
+ .getBuilder(GetExamConfigNode.class)
+ .withURIVariable(API.PARAM_MODEL_ID, entityKey.modelId)
+ .call()
+ .onError(error -> pageContext.notifyLoadError(EntityType.CONFIGURATION_NODE, error))
+ .getOrThrow();
+
+ final EntityGrantCheck entityGrant = this.currentUser.entityGrantCheck(examConfig);
+ final boolean writeGrant = entityGrant.w();
+ final boolean modifyGrant = entityGrant.m();
+ final boolean isReadonly = pageContext.isReadonly();
+ final boolean isAttachedToExam = !isNew && this.restService
+ .getBuilder(GetExamConfigMappingNames.class)
+ .withQueryParam(ExamConfigurationMap.FILTER_ATTR_CONFIG_ID, examConfig.getModelId())
+ .call()
+ .map(names -> names != null && !names.isEmpty())
+ .getOr(Boolean.FALSE);
+
+ // new PageContext with actual EntityKey
+ final PageContext formContext = pageContext.withEntityKey(examConfig.getEntityKey());
+
+ // the default page layout with interactive title
+ final LocTextKey titleKey = (isNew)
+ ? FORM_TITLE_NEW
+ : FORM_TITLE;
+ final Composite content = widgetFactory.defaultPageLayout(
+ formContext.getParent(),
+ titleKey);
+
+ final List> examConfigTemplateResources = resourceService.getExamConfigTemplateResources();
+ final FormHandle formHandle = this.pageService.formBuilder(
+ formContext.copyOf(content))
+ .readonly(isReadonly)
+ .putStaticValueIf(() -> !isNew,
+ Domain.CONFIGURATION_NODE.ATTR_ID,
+ examConfig.getModelId())
+ .putStaticValue(
+ Domain.CONFIGURATION_NODE.ATTR_INSTITUTION_ID,
+ String.valueOf(examConfig.getInstitutionId()))
+ .putStaticValue(
+ Domain.CONFIGURATION_NODE.ATTR_TYPE,
+ ConfigurationType.EXAM_CONFIG.name())
+ .addFieldIf(
+ () -> !examConfigTemplateResources.isEmpty(),
+ () -> FormBuilder.singleSelection(
+ Domain.CONFIGURATION_NODE.ATTR_TEMPLATE_ID,
+ FORM_TEMPLATE_TEXT_KEY,
+ (parentEntityKey != null)
+ ? parentEntityKey.modelId
+ : String.valueOf(examConfig.templateId),
+ resourceService::getExamConfigTemplateResources)
+ .readonly(!isNew))
+ .addField(FormBuilder.text(
+ Domain.CONFIGURATION_NODE.ATTR_NAME,
+ FORM_NAME_TEXT_KEY,
+ examConfig.name)
+ .mandatory(!isReadonly))
+ .addField(FormBuilder.text(
+ Domain.CONFIGURATION_NODE.ATTR_DESCRIPTION,
+ FORM_DESCRIPTION_TEXT_KEY,
+ examConfig.description)
+ .asArea())
+
+ .addField(FormBuilder.singleSelection(
+ Domain.CONFIGURATION_NODE.ATTR_STATUS,
+ FORM_STATUS_TEXT_KEY,
+ examConfig.status.name(),
+ () -> resourceService.examConfigStatusResources(isAttachedToExam))
+ .withEmptyCellSeparation(!isReadonly))
+ .buildFor((isNew)
+ ? this.restService.getRestCall(NewExamConfig.class)
+ : this.restService.getRestCall(SaveExamConfig.class));
+
+ final boolean settingsReadonly = examConfig.status == ConfigurationStatus.IN_USE;
+ final UrlLauncher urlLauncher = RWT.getClient().getService(UrlLauncher.class);
+ final PageContext actionContext = formContext.clearEntityKeys();
+ final PageActionBuilder actionBuilder = this.pageService.pageActionBuilder(actionContext);
+ actionBuilder
+
+ .newAction(ActionDefinition.SEB_EXAM_CONFIG_NEW)
+ .publishIf(() -> writeGrant && isReadonly)
+
+ .newAction(ActionDefinition.SEB_EXAM_CONFIG_PROP_MODIFY)
+ .withEntityKey(entityKey)
+
+ .publishIf(() -> modifyGrant && isReadonly)
+
+ .newAction(ActionDefinition.SEB_EXAM_CONFIG_MODIFY)
+ .withEntityKey(entityKey)
+ .withAttribute(PageContext.AttributeKeys.READ_ONLY, String.valueOf(!modifyGrant))
+ .publishIf(() -> modifyGrant && isReadonly)
+
+ .newAction(ActionDefinition.SEB_EXAM_CONFIG_EXPORT_PLAIN_XML)
+ .withEntityKey(entityKey)
+ .withExec(action -> {
+ final String downloadURL = this.downloadService.createDownloadURL(
+ entityKey.modelId,
+ SebExamConfigPlaintextDownload.class,
+ this.downloadFileName);
+ urlLauncher.openURL(downloadURL);
+ return action;
+ })
+ .noEventPropagation()
+ .publishIf(() -> modifyGrant && isReadonly)
+
+ .newAction(ActionDefinition.SEB_EXAM_CONFIG_GET_CONFIG_KEY)
+ .withEntityKey(entityKey)
+ .withExec(SebExamConfigPropForm.getConfigKeyFunction(this.pageService))
+ .noEventPropagation()
+ .publishIf(() -> modifyGrant && isReadonly)
+
+ .newAction(ActionDefinition.SEB_EXAM_CONFIG_IMPORT_TO_EXISTING_CONFIG)
+ .withEntityKey(entityKey)
+ .withExec(SebExamConfigImportPopup.importFunction(this.pageService, false))
+ .noEventPropagation()
+ .publishIf(() -> modifyGrant && isReadonly && !isAttachedToExam)
+
+ .newAction(ActionDefinition.SEB_EXAM_CONFIG_COPY_CONFIG)
+ .withEntityKey(entityKey)
+ .withExec(SebExamConfigCreationPopup.configCreationFunction(
+ this.pageService,
+ actionContext
+ .withEntityKey(entityKey)
+ .withAttribute(
+ PageContext.AttributeKeys.COPY_AS_TEMPLATE,
+ Constants.FALSE_STRING)
+ .withAttribute(
+ PageContext.AttributeKeys.CREATE_FROM_TEMPLATE,
+ Constants.FALSE_STRING)))
+ .noEventPropagation()
+ .publishIf(() -> modifyGrant && isReadonly)
+
+ .newAction(ActionDefinition.SEB_EXAM_CONFIG_COPY_CONFIG_AS_TEMPALTE)
+ .withEntityKey(entityKey)
+ .withExec(SebExamConfigCreationPopup.configCreationFunction(
+ this.pageService,
+ pageContext.withAttribute(
+ PageContext.AttributeKeys.COPY_AS_TEMPLATE,
+ Constants.TRUE_STRING)))
+ .noEventPropagation()
+ .publishIf(() -> modifyGrant && isReadonly)
+
+ .newAction(ActionDefinition.SEB_EXAM_CONFIG_PROP_SAVE)
+ .withEntityKey(entityKey)
+ .withExec(formHandle::processFormSave)
+ .ignoreMoveAwayFromEdit()
+ .withConfirm(() -> stateChangeConfirm(isAttachedToExam, formHandle))
+ .publishIf(() -> !isReadonly)
+
+ .newAction(ActionDefinition.SEB_EXAM_CONFIG_PROP_CANCEL_MODIFY)
+ .withEntityKey(entityKey)
+ .withExec(this.pageService.backToCurrentFunction())
+ .publishIf(() -> !isReadonly);
+
+ if (isAttachedToExam && isReadonly) {
+
+ widgetFactory.label(content, StringUtils.EMPTY);
+ widgetFactory.labelLocalized(
+ content,
+ CustomVariant.TEXT_H3,
+ FORM_ATTACHED_EXAMS_TITLE_TEXT_KEY,
+ FORM_ATTACHED_EXAMS_TITLE_TOOLTIP_TEXT_KEY);
+ widgetFactory.labelSeparator(content);
+
+ final EntityTable table =
+ this.pageService.entityTableBuilder(this.restService.getRestCall(GetExamConfigMappingsPage.class))
+ .withRestCallAdapter(restCall -> restCall.withQueryParam(
+ ExamConfigurationMap.FILTER_ATTR_CONFIG_ID, examConfig.getModelId()))
+ .withPaging(1)
+ .hideNavigation()
+ .withRowDecorator(ExamList.decorateOnExamMapConsistency(this.pageService))
+
+ .withColumn(new ColumnDefinition<>(
+ QuizData.QUIZ_ATTR_NAME,
+ ExamList.COLUMN_TITLE_NAME_KEY,
+ ExamConfigurationMap::getExamName))
+
+ .withColumn(new ColumnDefinition<>(
+ QuizData.QUIZ_ATTR_START_TIME,
+ new LocTextKey(
+ ExamList.EXAM_LIST_COLUMN_STARTTIME,
+ this.pageService.getI18nSupport().getUsersTimeZoneTitleSuffix()),
+ ExamConfigurationMap::getExamStartTime))
+
+ .withColumn(new ColumnDefinition<>(
+ Domain.EXAM.ATTR_TYPE,
+ ExamList.COLUMN_TITLE_TYPE_KEY,
+ resourceService::localizedExamTypeName))
+
+ .withDefaultAction(this::showExamAction)
+
+ .withSelectionListener(this.pageService.getSelectionPublisher(
+ pageContext,
+ ActionDefinition.EXAM_VIEW_FROM_LIST))
+
+ .compose(pageContext.copyOf(content));
+
+ actionBuilder
+
+ .newAction(ActionDefinition.EXAM_VIEW_FROM_LIST)
+ .withExec(pageAction -> {
+ final ExamConfigurationMap selectedExamMapping = getSelectedExamMapping(table);
+ return pageAction.withEntityKey(
+ new EntityKey(selectedExamMapping.examId, EntityType.EXAM));
+ })
+ .publishIf(table::hasAnyContent, false);
+ }
+ }
+
+ private PageAction showExamAction(final EntityTable table) {
+ return this.pageService.pageActionBuilder(table.getPageContext())
+ .newAction(ActionDefinition.EXAM_VIEW_FROM_LIST)
+ .withSelectionSupplier(() -> {
+ final ExamConfigurationMap selectedROWData = getSelectedExamMapping(table);
+ return new HashSet<>(Collections.singletonList(new EntityKey(selectedROWData.examId, EntityType.EXAM)));
+ })
+ .withExec(PageAction::applySingleSelectionAsEntityKey)
+ .create();
+ }
+
+ private ExamConfigurationMap getSelectedExamMapping(final EntityTable table) {
+ final ExamConfigurationMap selectedROWData = table.getSingleSelectedROWData();
+
+ if (selectedROWData == null) {
+ throw new PageMessageException(ExamList.EMPTY_SELECTION_TEXT_KEY);
+ }
+ return selectedROWData;
+ }
+
+ private LocTextKey stateChangeConfirm(
+ final boolean isAttachedToExam,
+ final FormHandle formHandle) {
+
+ if (isAttachedToExam) {
+ final String fieldValue = formHandle
+ .getForm()
+ .getFieldValue(Domain.CONFIGURATION_NODE.ATTR_STATUS);
+
+ if (fieldValue != null) {
+ final ConfigurationStatus state = ConfigurationStatus.valueOf(fieldValue);
+ if (state != ConfigurationStatus.IN_USE) {
+ return SAVE_CONFIRM_STATE_CHANGE_WHILE_ATTACHED;
+ }
+ }
+ }
+
+ return null;
+ }
+
+ public static Function getConfigKeyFunction(final PageService pageService) {
+ final RestService restService = pageService.getResourceService().getRestService();
+ return action -> {
+ final ConfigKey configKey = restService.getBuilder(ExportConfigKey.class)
+ .withURIVariable(API.PARAM_MODEL_ID, action.getEntityKey().modelId)
+ .call()
+ .getOrThrow();
+
+ final WidgetFactory widgetFactory = pageService.getWidgetFactory();
+ final ModalInputDialog dialog = new ModalInputDialog<>(
+ action.pageContext().getParent().getShell(),
+ widgetFactory);
+
+ dialog.setDialogWidth(500);
+
+ dialog.open(
+ CONFIG_KEY_TITLE_TEXT_KEY,
+ action.pageContext(),
+ pc -> {
+ final Composite content = widgetFactory.defaultPageLayout(
+ pc.getParent());
+
+ widgetFactory.labelLocalized(
+ content,
+ CustomVariant.TEXT_H3,
+ CONFIG_KEY_TITLE_TEXT_KEY);
+
+ final Text text = new Text(content, SWT.NONE);
+ text.setEditable(false);
+ text.setText(configKey.key);
+ });
+ return action;
+ };
+ }
+
+}
diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/content/SebExamConfigSettingsForm.java b/src/main/java/ch/ethz/seb/sebserver/gui/content/SebExamConfigSettingsForm.java
index ec77a9af..861c6a0f 100644
--- a/src/main/java/ch/ethz/seb/sebserver/gui/content/SebExamConfigSettingsForm.java
+++ b/src/main/java/ch/ethz/seb/sebserver/gui/content/SebExamConfigSettingsForm.java
@@ -1,239 +1,238 @@
-/*
- * 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.content;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.apache.commons.lang3.StringUtils;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.layout.GridData;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.TabFolder;
-import org.eclipse.swt.widgets.TabItem;
-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.Constants;
-import ch.ethz.seb.sebserver.gbl.api.API;
-import ch.ethz.seb.sebserver.gbl.api.APIMessage;
-import ch.ethz.seb.sebserver.gbl.api.APIMessageError;
-import ch.ethz.seb.sebserver.gbl.api.EntityType;
-import ch.ethz.seb.sebserver.gbl.model.EntityKey;
-import ch.ethz.seb.sebserver.gbl.model.sebconfig.Configuration;
-import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode;
-import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode.ConfigurationStatus;
-import ch.ethz.seb.sebserver.gbl.model.sebconfig.View;
-import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
-import ch.ethz.seb.sebserver.gbl.util.Utils;
-import ch.ethz.seb.sebserver.gui.content.action.ActionDefinition;
-import ch.ethz.seb.sebserver.gui.service.examconfig.ExamConfigurationService;
-import ch.ethz.seb.sebserver.gui.service.examconfig.impl.AttributeMapping;
-import ch.ethz.seb.sebserver.gui.service.examconfig.impl.ViewContext;
-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.PageMessageException;
-import ch.ethz.seb.sebserver.gui.service.page.PageService;
-import ch.ethz.seb.sebserver.gui.service.page.TemplateComposer;
-import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestService;
-import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.GetConfigurations;
-import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.GetExamConfigNode;
-import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.SaveExamConfigHistory;
-import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.SebExamConfigUndo;
-import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.CurrentUser;
-import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.CurrentUser.GrantCheck;
-import ch.ethz.seb.sebserver.gui.widget.WidgetFactory;
-
-@Lazy
-@Component
-@GuiProfile
-public class SebExamConfigSettingsForm implements TemplateComposer {
-
- private static final Logger log = LoggerFactory.getLogger(SebExamConfigSettingsForm.class);
-
- private static final String VIEW_TEXT_KEY_PREFIX =
- "sebserver.examconfig.props.form.views.";
- private static final String KEY_SAVE_TO_HISTORY_SUCCESS =
- "sebserver.examconfig.action.saveToHistory.success";
- private static final String KEY_UNDO_SUCCESS =
- "sebserver.examconfig.action.undo.success";
- private static final LocTextKey TITLE_TEXT_KEY =
- new LocTextKey("sebserver.examconfig.props.from.title");
-
- private static final LocTextKey MESSAGE_SAVE_INTEGRITY_VIOLATION =
- new LocTextKey("sebserver.examconfig.action.saveToHistory.integrity-violation");
-
- private final PageService pageService;
- private final RestService restService;
- private final CurrentUser currentUser;
- private final ExamConfigurationService examConfigurationService;
-
- protected SebExamConfigSettingsForm(
- final PageService pageService,
- final RestService restService,
- final CurrentUser currentUser,
- final ExamConfigurationService examConfigurationService) {
-
- this.pageService = pageService;
- this.restService = restService;
- this.currentUser = currentUser;
- this.examConfigurationService = examConfigurationService;
- }
-
- @Override
- public void compose(final PageContext pageContext) {
- final WidgetFactory widgetFactory = this.pageService.getWidgetFactory();
-
- final EntityKey entityKey = pageContext.getEntityKey();
-
- final Composite content = widgetFactory.defaultPageLayout(
- pageContext.getParent(),
- TITLE_TEXT_KEY);
-
- try {
-
- final ConfigurationNode configNode = this.restService.getBuilder(GetExamConfigNode.class)
- .withURIVariable(API.PARAM_MODEL_ID, entityKey.modelId)
- .call()
- .onError(error -> pageContext.notifyLoadError(EntityType.CONFIGURATION_NODE, error))
- .getOrThrow();
-
- final Configuration configuration = this.restService.getBuilder(GetConfigurations.class)
- .withQueryParam(Configuration.FILTER_ATTR_CONFIGURATION_NODE_ID, configNode.getModelId())
- .withQueryParam(Configuration.FILTER_ATTR_FOLLOWUP, Constants.TRUE_STRING)
- .call()
- .map(Utils::toSingleton)
- .onError(error -> pageContext.notifyLoadError(EntityType.CONFIGURATION, error))
- .getOrThrow();
-
- final AttributeMapping attributes = this.examConfigurationService
- .getAttributes(configNode.templateId)
- .onError(error -> pageContext.notifyLoadError(EntityType.CONFIGURATION_ATTRIBUTE, error))
- .getOrThrow();
-
- final boolean readonly = pageContext.isReadonly() || configNode.status == ConfigurationStatus.IN_USE;
- final List views = this.examConfigurationService.getViews(attributes);
- final TabFolder tabFolder = widgetFactory.tabFolderLocalized(content);
- tabFolder.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
-
- final List viewContexts = new ArrayList<>();
- for (final View view : views) {
- final ViewContext viewContext = this.examConfigurationService.createViewContext(
- pageContext,
- configuration,
- view,
- attributes,
- 20,
- readonly);
- viewContexts.add(viewContext);
-
- final Composite viewGrid = this.examConfigurationService.createViewGrid(
- tabFolder,
- viewContext);
-
- final TabItem tabItem = widgetFactory.tabItemLocalized(
- tabFolder,
- new LocTextKey(VIEW_TEXT_KEY_PREFIX + view.name));
- tabItem.setControl(viewGrid);
- }
-
- // set selection if available
- final String viewIndex = pageContext.getAttribute("VIEW_INDEX");
- if (StringUtils.isNotBlank(viewIndex)) {
- try {
- tabFolder.setSelection(Integer.parseInt(viewIndex));
- } catch (final NumberFormatException e) {
- log.warn("Failed to initialize view selection");
- }
- }
-
- this.examConfigurationService.initInputFieldValues(configuration.id, viewContexts);
-
- final GrantCheck examConfigGrant = this.currentUser.grantCheck(EntityType.CONFIGURATION_NODE);
- this.pageService.pageActionBuilder(pageContext.clearEntityKeys())
-
- .newAction(ActionDefinition.SEB_EXAM_CONFIG_SAVE_TO_HISTORY)
- .withEntityKey(entityKey)
- .withExec(action -> {
- this.restService.getBuilder(SaveExamConfigHistory.class)
- .withURIVariable(API.PARAM_MODEL_ID, configuration.getModelId())
- .call()
- .onError(t -> notifyErrorOnSave(t, pageContext));
- return action.withAttribute(
- "VIEW_INDEX",
- String.valueOf(tabFolder.getSelectionIndex()));
- })
- .withSuccess(KEY_SAVE_TO_HISTORY_SUCCESS)
- .ignoreMoveAwayFromEdit()
- .publishIf(() -> examConfigGrant.iw() && !readonly)
-
- .newAction(ActionDefinition.SEB_EXAM_CONFIG_UNDO)
- .withEntityKey(entityKey)
- .withExec(action -> {
- this.restService.getBuilder(SebExamConfigUndo.class)
- .withURIVariable(API.PARAM_MODEL_ID, configuration.getModelId())
- .call()
- .getOrThrow();
- return action.withAttribute(
- "VIEW_INDEX",
- String.valueOf(tabFolder.getSelectionIndex()));
- })
- .withSuccess(KEY_UNDO_SUCCESS)
- .ignoreMoveAwayFromEdit()
- .publishIf(() -> examConfigGrant.iw() && !readonly)
-
- .newAction(ActionDefinition.SEB_EXAM_CONFIG_COPY_CONFIG_AS_TEMPALTE)
- .withEntityKey(entityKey)
- .withExec(SebExamConfigCreationPopup.configCreationFunction(
- this.pageService,
- pageContext
- .withAttribute(
- PageContext.AttributeKeys.COPY_AS_TEMPLATE,
- Constants.TRUE_STRING)
- .withAttribute(
- PageContext.AttributeKeys.CREATE_FROM_TEMPLATE,
- Constants.FALSE_STRING)))
- .noEventPropagation()
- .publishIf(() -> examConfigGrant.iw())
-
- .newAction(ActionDefinition.SEB_EXAM_CONFIG_VIEW_PROP)
- .withEntityKey(entityKey)
- .ignoreMoveAwayFromEdit()
- .publish();
-
- } catch (final RuntimeException e) {
- pageContext.notifyUnexpectedError(e);
- throw e;
- } catch (final Exception e) {
- log.error("Unexpected error while trying to fetch exam configuration data and create views", e);
- pageContext.notifyError(SebExamConfigPropForm.FORM_TITLE, e);
- }
- }
-
- private void notifyErrorOnSave(final Exception error, final PageContext context) {
- if (error instanceof APIMessageError) {
- try {
- final List errorMessages = ((APIMessageError) error).getErrorMessages();
- final APIMessage apiMessage = errorMessages.get(0);
- if (APIMessage.ErrorMessage.INTEGRITY_VALIDATION.isOf(apiMessage)) {
- throw new PageMessageException(MESSAGE_SAVE_INTEGRITY_VIOLATION);
- } else {
- throw error;
- }
- } catch (final PageMessageException e) {
- throw e;
- } catch (final Exception e) {
- throw new RuntimeException(error);
- }
- }
- }
-
-}
+/*
+ * 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.content;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.commons.lang3.StringUtils;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.TabFolder;
+import org.eclipse.swt.widgets.TabItem;
+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.Constants;
+import ch.ethz.seb.sebserver.gbl.api.API;
+import ch.ethz.seb.sebserver.gbl.api.APIMessage;
+import ch.ethz.seb.sebserver.gbl.api.APIMessageError;
+import ch.ethz.seb.sebserver.gbl.api.EntityType;
+import ch.ethz.seb.sebserver.gbl.model.EntityKey;
+import ch.ethz.seb.sebserver.gbl.model.sebconfig.Configuration;
+import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode;
+import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode.ConfigurationStatus;
+import ch.ethz.seb.sebserver.gbl.model.sebconfig.View;
+import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
+import ch.ethz.seb.sebserver.gbl.util.Utils;
+import ch.ethz.seb.sebserver.gui.content.action.ActionDefinition;
+import ch.ethz.seb.sebserver.gui.service.examconfig.ExamConfigurationService;
+import ch.ethz.seb.sebserver.gui.service.examconfig.impl.AttributeMapping;
+import ch.ethz.seb.sebserver.gui.service.examconfig.impl.ViewContext;
+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.PageMessageException;
+import ch.ethz.seb.sebserver.gui.service.page.PageService;
+import ch.ethz.seb.sebserver.gui.service.page.TemplateComposer;
+import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestService;
+import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.GetConfigurations;
+import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.GetExamConfigNode;
+import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.SaveExamConfigHistory;
+import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.SebExamConfigUndo;
+import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.CurrentUser;
+import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.CurrentUser.GrantCheck;
+import ch.ethz.seb.sebserver.gui.widget.WidgetFactory;
+
+@Lazy
+@Component
+@GuiProfile
+public class SebExamConfigSettingsForm implements TemplateComposer {
+
+ private static final Logger log = LoggerFactory.getLogger(SebExamConfigSettingsForm.class);
+
+ private static final String VIEW_TEXT_KEY_PREFIX =
+ "sebserver.examconfig.props.form.views.";
+ private static final String KEY_SAVE_TO_HISTORY_SUCCESS =
+ "sebserver.examconfig.action.saveToHistory.success";
+ private static final String KEY_UNDO_SUCCESS =
+ "sebserver.examconfig.action.undo.success";
+ private static final LocTextKey TITLE_TEXT_KEY =
+ new LocTextKey("sebserver.examconfig.props.from.title");
+
+ private static final LocTextKey MESSAGE_SAVE_INTEGRITY_VIOLATION =
+ new LocTextKey("sebserver.examconfig.action.saveToHistory.integrity-violation");
+
+ private final PageService pageService;
+ private final RestService restService;
+ private final CurrentUser currentUser;
+ private final ExamConfigurationService examConfigurationService;
+
+ protected SebExamConfigSettingsForm(
+ final PageService pageService,
+ final RestService restService,
+ final CurrentUser currentUser,
+ final ExamConfigurationService examConfigurationService) {
+
+ this.pageService = pageService;
+ this.restService = restService;
+ this.currentUser = currentUser;
+ this.examConfigurationService = examConfigurationService;
+ }
+
+ @Override
+ public void compose(final PageContext pageContext) {
+ final WidgetFactory widgetFactory = this.pageService.getWidgetFactory();
+
+ final EntityKey entityKey = pageContext.getEntityKey();
+
+ final Composite content = widgetFactory.defaultPageLayout(
+ pageContext.getParent(),
+ TITLE_TEXT_KEY);
+
+ try {
+
+ final ConfigurationNode configNode = this.restService.getBuilder(GetExamConfigNode.class)
+ .withURIVariable(API.PARAM_MODEL_ID, entityKey.modelId)
+ .call()
+ .onError(error -> pageContext.notifyLoadError(EntityType.CONFIGURATION_NODE, error))
+ .getOrThrow();
+
+ final Configuration configuration = this.restService.getBuilder(GetConfigurations.class)
+ .withQueryParam(Configuration.FILTER_ATTR_CONFIGURATION_NODE_ID, configNode.getModelId())
+ .withQueryParam(Configuration.FILTER_ATTR_FOLLOWUP, Constants.TRUE_STRING)
+ .call()
+ .map(Utils::toSingleton)
+ .onError(error -> pageContext.notifyLoadError(EntityType.CONFIGURATION, error))
+ .getOrThrow();
+
+ final AttributeMapping attributes = this.examConfigurationService
+ .getAttributes(configNode.templateId)
+ .onError(error -> pageContext.notifyLoadError(EntityType.CONFIGURATION_ATTRIBUTE, error))
+ .getOrThrow();
+
+ final boolean readonly = pageContext.isReadonly() || configNode.status == ConfigurationStatus.IN_USE;
+ final List views = this.examConfigurationService.getViews(attributes);
+ final TabFolder tabFolder = widgetFactory.tabFolderLocalized(content);
+ tabFolder.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
+
+ final List viewContexts = new ArrayList<>();
+ for (final View view : views) {
+ final ViewContext viewContext = this.examConfigurationService.createViewContext(
+ pageContext,
+ configuration,
+ view,
+ attributes,
+ 20,
+ readonly);
+ viewContexts.add(viewContext);
+
+ final Composite viewGrid = this.examConfigurationService.createViewGrid(
+ tabFolder,
+ viewContext);
+
+ final TabItem tabItem = widgetFactory.tabItemLocalized(
+ tabFolder,
+ new LocTextKey(VIEW_TEXT_KEY_PREFIX + view.name));
+ tabItem.setControl(viewGrid);
+ }
+
+ // set selection if available
+ final String viewIndex = pageContext.getAttribute("VIEW_INDEX");
+ if (StringUtils.isNotBlank(viewIndex)) {
+ try {
+ tabFolder.setSelection(Integer.parseInt(viewIndex));
+ } catch (final NumberFormatException e) {
+ log.warn("Failed to initialize view selection");
+ }
+ }
+
+ this.examConfigurationService.initInputFieldValues(configuration.id, viewContexts);
+
+ final GrantCheck examConfigGrant = this.currentUser.grantCheck(EntityType.CONFIGURATION_NODE);
+ this.pageService.pageActionBuilder(pageContext.clearEntityKeys())
+
+ .newAction(ActionDefinition.SEB_EXAM_CONFIG_SAVE_TO_HISTORY)
+ .withEntityKey(entityKey)
+ .withExec(action -> {
+ this.restService.getBuilder(SaveExamConfigHistory.class)
+ .withURIVariable(API.PARAM_MODEL_ID, configuration.getModelId())
+ .call()
+ .onError(t -> notifyErrorOnSave(t, pageContext));
+ return action.withAttribute(
+ "VIEW_INDEX",
+ String.valueOf(tabFolder.getSelectionIndex()));
+ })
+ .withSuccess(KEY_SAVE_TO_HISTORY_SUCCESS)
+ .ignoreMoveAwayFromEdit()
+ .publishIf(() -> examConfigGrant.iw() && !readonly)
+
+ .newAction(ActionDefinition.SEB_EXAM_CONFIG_UNDO)
+ .withEntityKey(entityKey)
+ .withExec(action -> {
+ this.restService.getBuilder(SebExamConfigUndo.class)
+ .withURIVariable(API.PARAM_MODEL_ID, configuration.getModelId())
+ .call()
+ .getOrThrow();
+ return action.withAttribute(
+ "VIEW_INDEX",
+ String.valueOf(tabFolder.getSelectionIndex()));
+ })
+ .withSuccess(KEY_UNDO_SUCCESS)
+ .ignoreMoveAwayFromEdit()
+ .publishIf(() -> examConfigGrant.iw() && !readonly)
+
+ .newAction(ActionDefinition.SEB_EXAM_CONFIG_COPY_CONFIG_AS_TEMPALTE)
+ .withEntityKey(entityKey)
+ .withExec(SebExamConfigCreationPopup.configCreationFunction(
+ this.pageService,
+ pageContext
+ .withAttribute(
+ PageContext.AttributeKeys.COPY_AS_TEMPLATE,
+ Constants.TRUE_STRING)
+ .withAttribute(
+ PageContext.AttributeKeys.CREATE_FROM_TEMPLATE,
+ Constants.FALSE_STRING)))
+ .noEventPropagation()
+ .publishIf(examConfigGrant::iw)
+
+ .newAction(ActionDefinition.SEB_EXAM_CONFIG_VIEW_PROP)
+ .withEntityKey(entityKey)
+ .ignoreMoveAwayFromEdit()
+ .publish();
+
+ } catch (final RuntimeException e) {
+ pageContext.notifyUnexpectedError(e);
+ throw e;
+ } catch (final Exception e) {
+ log.error("Unexpected error while trying to fetch exam configuration data and create views", e);
+ pageContext.notifyError(SebExamConfigPropForm.FORM_TITLE, e);
+ }
+ }
+
+ private void notifyErrorOnSave(final Exception error, final PageContext context) {
+ if (error instanceof APIMessageError) {
+ try {
+ final List errorMessages = ((APIMessageError) error).getErrorMessages();
+ final APIMessage apiMessage = errorMessages.get(0);
+ if (APIMessage.ErrorMessage.INTEGRITY_VALIDATION.isOf(apiMessage)) {
+ throw new PageMessageException(MESSAGE_SAVE_INTEGRITY_VIOLATION);
+ } else {
+ throw error;
+ }
+ } catch (final PageMessageException e) {
+ throw e;
+ } catch (final Exception e) {
+ throw new RuntimeException(error);
+ }
+ }
+ }
+}
diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/content/UserAccountChangePasswordForm.java b/src/main/java/ch/ethz/seb/sebserver/gui/content/UserAccountChangePasswordForm.java
index 2b0598ea..8b939e7e 100644
--- a/src/main/java/ch/ethz/seb/sebserver/gui/content/UserAccountChangePasswordForm.java
+++ b/src/main/java/ch/ethz/seb/sebserver/gui/content/UserAccountChangePasswordForm.java
@@ -1,143 +1,147 @@
-/*
- * 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.content;
-
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.MessageBox;
-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.EntityType;
-import ch.ethz.seb.sebserver.gbl.model.Domain;
-import ch.ethz.seb.sebserver.gbl.model.EntityKey;
-import ch.ethz.seb.sebserver.gbl.model.user.PasswordChange;
-import ch.ethz.seb.sebserver.gbl.model.user.UserInfo;
-import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
-import ch.ethz.seb.sebserver.gui.content.action.ActionDefinition;
-import ch.ethz.seb.sebserver.gui.form.FormBuilder;
-import ch.ethz.seb.sebserver.gui.form.FormHandle;
-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.PageContext;
-import ch.ethz.seb.sebserver.gui.service.page.PageService;
-import ch.ethz.seb.sebserver.gui.service.page.TemplateComposer;
-import ch.ethz.seb.sebserver.gui.service.page.impl.PageAction;
-import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestService;
-import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.useraccount.ChangePassword;
-import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.useraccount.GetUserAccount;
-import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.CurrentUser;
-import ch.ethz.seb.sebserver.gui.widget.Message;
-import ch.ethz.seb.sebserver.gui.widget.WidgetFactory;
-
-@Lazy
-@Component
-@GuiProfile
-/** The form to change an User-Account password.
- * If the current user is the owner of the User-Account the password is required and must
- * match the users current password.
- * If the current user is an administrator that has to reset another users password the
- * password that is also required must match the administrators current password. */
-public class UserAccountChangePasswordForm implements TemplateComposer {
-
- private static final String FORM_TITLE_KEY = "sebserver.useraccount.form.pwchange.title";
- private static final LocTextKey FORM_PASSWORD_NEW_TEXT_KEY =
- new LocTextKey("sebserver.useraccount.form.password.new");
- private static final LocTextKey FORM_PASSWORD_NEW_CONFIRM_TEXT_KEY =
- new LocTextKey("sebserver.useraccount.form.password.new.confirm");
- private static final LocTextKey FORM_PASSWORD_TEXT_KEY =
- new LocTextKey("sebserver.useraccount.form.password");
-
- private final PageService pageService;
- private final RestService restService;
- private final CurrentUser currentUser;
- private final I18nSupport i18nSupport;
-
- protected UserAccountChangePasswordForm(
- final PageService pageService,
- final RestService restService,
- final CurrentUser currentUser) {
-
- this.pageService = pageService;
- this.restService = restService;
- this.currentUser = currentUser;
- this.i18nSupport = pageService.getI18nSupport();
- }
-
- @Override
- public void compose(final PageContext pageContext) {
-
- final WidgetFactory widgetFactory = this.pageService.getWidgetFactory();
- final EntityKey entityKey = pageContext.getEntityKey();
-
- final UserInfo userInfo = this.restService
- .getBuilder(GetUserAccount.class)
- .withURIVariable(API.PARAM_MODEL_ID, entityKey.modelId)
- .call()
- .onError(error -> pageContext.notifyLoadError(EntityType.USER, error))
- .getOrThrow();
-
- final Composite content = widgetFactory.defaultPageLayout(
- pageContext.getParent(),
- new LocTextKey(FORM_TITLE_KEY, userInfo.username));
-
- final boolean ownAccount = this.currentUser.get().uuid.equals(entityKey.getModelId());
-
- // The Password Change form
- final FormHandle formHandle = this.pageService.formBuilder(pageContext.copyOf(content))
- .readonly(false)
- .putStaticValueIf(() -> entityKey != null,
- Domain.USER.ATTR_UUID,
- entityKey.getModelId())
- .addField(FormBuilder.text(
- PasswordChange.ATTR_NAME_PASSWORD,
- FORM_PASSWORD_TEXT_KEY)
- .asPasswordField())
- .addField(FormBuilder.text(
- PasswordChange.ATTR_NAME_NEW_PASSWORD,
- FORM_PASSWORD_NEW_TEXT_KEY)
- .asPasswordField())
- .addFieldIf(
- () -> entityKey != null,
- () -> FormBuilder.text(
- PasswordChange.ATTR_NAME_CONFIRM_NEW_PASSWORD,
- FORM_PASSWORD_NEW_CONFIRM_TEXT_KEY)
- .asPasswordField())
- .buildFor(this.restService.getRestCall(ChangePassword.class));
-
- this.pageService.pageActionBuilder(pageContext)
-
- .newAction(ActionDefinition.USER_ACCOUNT_CHANGE_PASSOWRD_SAVE)
- .withExec(action -> {
- final PageAction saveAction = formHandle.processFormSave(action);
- if (ownAccount) {
- // NOTE: in this case the user changed the password of the own account
- // this should cause an logout with specified message that password change
- // was successful and the pointing the need of re login with the new password
- this.pageService.logout(pageContext);
- final MessageBox error = new Message(
- pageContext.getShell(),
- this.i18nSupport.getText("sebserver.login.password.change"),
- this.i18nSupport.getText("sebserver.login.password.change.success"),
- SWT.ICON_INFORMATION,
- this.i18nSupport);
- error.open(null);
- }
- return saveAction;
- })
- .ignoreMoveAwayFromEdit()
- .publish()
-
- .newAction(ActionDefinition.USER_ACCOUNT_CANCEL_MODIFY)
- .withExec(this.pageService.backToCurrentFunction())
- .publish();
- }
-
-}
+/*
+ * 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.content;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.MessageBox;
+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.EntityType;
+import ch.ethz.seb.sebserver.gbl.model.Domain;
+import ch.ethz.seb.sebserver.gbl.model.EntityKey;
+import ch.ethz.seb.sebserver.gbl.model.user.PasswordChange;
+import ch.ethz.seb.sebserver.gbl.model.user.UserInfo;
+import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
+import ch.ethz.seb.sebserver.gui.content.action.ActionDefinition;
+import ch.ethz.seb.sebserver.gui.form.FormBuilder;
+import ch.ethz.seb.sebserver.gui.form.FormHandle;
+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.PageContext;
+import ch.ethz.seb.sebserver.gui.service.page.PageService;
+import ch.ethz.seb.sebserver.gui.service.page.TemplateComposer;
+import ch.ethz.seb.sebserver.gui.service.page.impl.PageAction;
+import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestService;
+import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.useraccount.ChangePassword;
+import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.useraccount.GetUserAccount;
+import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.CurrentUser;
+import ch.ethz.seb.sebserver.gui.widget.Message;
+import ch.ethz.seb.sebserver.gui.widget.WidgetFactory;
+
+@Lazy
+@Component
+@GuiProfile
+/** The form to change an User-Account password.
+ * If the current user is the owner of the User-Account the password is required and must
+ * match the users current password.
+ * If the current user is an administrator that has to reset another users password the
+ * password that is also required must match the administrators current password.
+ **/
+public class UserAccountChangePasswordForm implements TemplateComposer {
+
+ private static final String FORM_TITLE_KEY = "sebserver.useraccount.form.pwchange.title";
+ private static final LocTextKey FORM_PASSWORD_NEW_TEXT_KEY =
+ new LocTextKey("sebserver.useraccount.form.password.new");
+ private static final LocTextKey FORM_PASSWORD_NEW_CONFIRM_TEXT_KEY =
+ new LocTextKey("sebserver.useraccount.form.password.new.confirm");
+ private static final LocTextKey FORM_PASSWORD_TEXT_KEY =
+ new LocTextKey("sebserver.useraccount.form.password");
+
+ private final PageService pageService;
+ private final RestService restService;
+ private final CurrentUser currentUser;
+ private final I18nSupport i18nSupport;
+
+ protected UserAccountChangePasswordForm(
+ final PageService pageService,
+ final RestService restService,
+ final CurrentUser currentUser) {
+
+ this.pageService = pageService;
+ this.restService = restService;
+ this.currentUser = currentUser;
+ this.i18nSupport = pageService.getI18nSupport();
+ }
+
+ @Override
+ public void compose(final PageContext pageContext) {
+
+ final WidgetFactory widgetFactory = this.pageService.getWidgetFactory();
+ final EntityKey entityKey = pageContext.getEntityKey();
+
+ final UserInfo userInfo = this.restService
+ .getBuilder(GetUserAccount.class)
+ .withURIVariable(API.PARAM_MODEL_ID, entityKey.modelId)
+ .call()
+ .onError(error -> pageContext.notifyLoadError(EntityType.USER, error))
+ .getOrThrow();
+
+ final Composite content = widgetFactory.defaultPageLayout(
+ pageContext.getParent(),
+ new LocTextKey(FORM_TITLE_KEY, userInfo.username));
+
+ final boolean ownAccount = this.currentUser.get().uuid.equals(entityKey.getModelId());
+
+ // The Password Change form
+ final FormHandle formHandle = this.pageService.formBuilder(pageContext.copyOf(content))
+ .readonly(false)
+ .putStaticValueIf(() -> entityKey != null,
+ Domain.USER.ATTR_UUID,
+ entityKey.getModelId())
+ .addField(FormBuilder.text(
+ PasswordChange.ATTR_NAME_PASSWORD,
+ FORM_PASSWORD_TEXT_KEY)
+ .asPasswordField()
+ .mandatory())
+ .addField(FormBuilder.text(
+ PasswordChange.ATTR_NAME_NEW_PASSWORD,
+ FORM_PASSWORD_NEW_TEXT_KEY)
+ .asPasswordField()
+ .mandatory())
+ .addFieldIf(
+ () -> entityKey != null,
+ () -> FormBuilder.text(
+ PasswordChange.ATTR_NAME_CONFIRM_NEW_PASSWORD,
+ FORM_PASSWORD_NEW_CONFIRM_TEXT_KEY)
+ .asPasswordField()
+ .mandatory())
+ .buildFor(this.restService.getRestCall(ChangePassword.class));
+
+ this.pageService.pageActionBuilder(pageContext)
+
+ .newAction(ActionDefinition.USER_ACCOUNT_CHANGE_PASSWORD_SAVE)
+ .withExec(action -> {
+ final PageAction saveAction = formHandle.processFormSave(action);
+ if (ownAccount) {
+ // NOTE: in this case the user changed the password of the own account
+ // this should cause an logout with specified message that password change
+ // was successful and the pointing the need of re login with the new password
+ this.pageService.logout(pageContext);
+ final MessageBox error = new Message(
+ pageContext.getShell(),
+ this.i18nSupport.getText("sebserver.login.password.change"),
+ this.i18nSupport.getText("sebserver.login.password.change.success"),
+ SWT.ICON_INFORMATION,
+ this.i18nSupport);
+ error.open(null);
+ }
+ return saveAction;
+ })
+ .ignoreMoveAwayFromEdit()
+ .publish()
+
+ .newAction(ActionDefinition.USER_ACCOUNT_CANCEL_MODIFY)
+ .withExec(this.pageService.backToCurrentFunction())
+ .publish();
+ }
+
+}
diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/content/UserAccountForm.java b/src/main/java/ch/ethz/seb/sebserver/gui/content/UserAccountForm.java
index caa81a82..708267bf 100644
--- a/src/main/java/ch/ethz/seb/sebserver/gui/content/UserAccountForm.java
+++ b/src/main/java/ch/ethz/seb/sebserver/gui/content/UserAccountForm.java
@@ -1,279 +1,291 @@
-/*
- * 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.content;
-
-import java.util.function.BooleanSupplier;
-
-import org.apache.commons.lang3.BooleanUtils;
-import org.apache.tomcat.util.buf.StringUtils;
-import org.eclipse.swt.widgets.Composite;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.context.annotation.Lazy;
-import org.springframework.stereotype.Component;
-
-import ch.ethz.seb.sebserver.gbl.Constants;
-import ch.ethz.seb.sebserver.gbl.api.API;
-import ch.ethz.seb.sebserver.gbl.api.EntityType;
-import ch.ethz.seb.sebserver.gbl.api.authorization.Privilege;
-import ch.ethz.seb.sebserver.gbl.api.authorization.PrivilegeType;
-import ch.ethz.seb.sebserver.gbl.model.Domain;
-import ch.ethz.seb.sebserver.gbl.model.Domain.USER_ROLE;
-import ch.ethz.seb.sebserver.gbl.model.EntityKey;
-import ch.ethz.seb.sebserver.gbl.model.user.PasswordChange;
-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.content.action.ActionDefinition;
-import ch.ethz.seb.sebserver.gui.form.FormBuilder;
-import ch.ethz.seb.sebserver.gui.form.FormHandle;
-import ch.ethz.seb.sebserver.gui.service.ResourceService;
-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.PageService;
-import ch.ethz.seb.sebserver.gui.service.page.TemplateComposer;
-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.useraccount.ActivateUserAccount;
-import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.useraccount.DeactivateUserAccount;
-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.remote.webservice.auth.CurrentUser.EntityGrantCheck;
-import ch.ethz.seb.sebserver.gui.widget.WidgetFactory;
-
-@Lazy
-@Component
-@GuiProfile
-public class UserAccountForm implements TemplateComposer {
-
- static final LocTextKey TITLE_TEXT_KEY =
- new LocTextKey("sebserver.useraccount.form.title");
- static final LocTextKey NEW_TITLE_TEXT_KEY =
- new LocTextKey("sebserver.useraccount.form.title.new");
-
- static final LocTextKey FORM_PASSWORD_CONFIRM_TEXT_KEY =
- new LocTextKey("sebserver.useraccount.form.password.confirm");
- static final LocTextKey FORM_PASSWORD_TEXT_KEY =
- new LocTextKey("sebserver.useraccount.form.password");
- static final LocTextKey FORM_ROLES_TEXT_KEY =
- new LocTextKey("sebserver.useraccount.form.roles");
- static final LocTextKey FORM_TIMEZONE_TEXT_KEY =
- new LocTextKey("sebserver.useraccount.form.timezone");
- static final LocTextKey FORM_MAIL_TEXT_KEY =
- new LocTextKey("sebserver.useraccount.form.mail");
- static final LocTextKey FORM_USERNAME_TEXT_KEY =
- new LocTextKey("sebserver.useraccount.form.username");
- static final LocTextKey FORM_NAME_TEXT_KEY =
- new LocTextKey("sebserver.useraccount.form.name");
- static final LocTextKey FORM_SURNAME_TEXT_KEY =
- new LocTextKey("sebserver.useraccount.form.surname");
- static final LocTextKey FORM_INSTITUTION_TEXT_KEY =
- new LocTextKey("sebserver.useraccount.form.institution");
- static final LocTextKey FORM_CREATION_DATE_TEXT_KEY =
- new LocTextKey("sebserver.useraccount.form.creationdate");
- static final LocTextKey FORM_LANG_TEXT_KEY =
- new LocTextKey("sebserver.useraccount.form.language");
-
- private final PageService pageService;
- private final ResourceService resourceService;
- private final boolean multilingual;
-
- protected UserAccountForm(
- final PageService pageService,
- final ResourceService resourceService,
- @Value("${sebserver.gui.multilingual:false}") final Boolean multilingual) {
-
- this.pageService = pageService;
- this.resourceService = resourceService;
- this.multilingual = BooleanUtils.toBoolean(multilingual);
- }
-
- @Override
- public void compose(final PageContext pageContext) {
- final CurrentUser currentUser = this.resourceService.getCurrentUser();
- final RestService restService = this.resourceService.getRestService();
- final WidgetFactory widgetFactory = this.pageService.getWidgetFactory();
-
- final UserInfo user = currentUser.get();
- final EntityKey entityKey = pageContext.getEntityKey();
- final EntityKey parentEntityKey = pageContext.getParentEntityKey();
- final boolean readonly = pageContext.isReadonly();
-
- final BooleanSupplier isNew = () -> entityKey == null;
- final BooleanSupplier isNotNew = () -> !isNew.getAsBoolean();
- final BooleanSupplier isSEBAdmin = () -> user.hasRole(UserRole.SEB_SERVER_ADMIN);
-
- // get data or create new. handle error if happen
- final UserAccount userAccount = isNew.getAsBoolean()
- ? UserMod.createNew((parentEntityKey != null)
- ? Long.valueOf(parentEntityKey.modelId)
- : user.institutionId)
- : restService
- .getBuilder(GetUserAccount.class)
- .withURIVariable(API.PARAM_MODEL_ID, entityKey.modelId)
- .call()
- .onError(error -> pageContext.notifyLoadError(EntityType.USER, error))
- .getOrThrow();
-
- final boolean roleBasedEditGrant = Privilege.hasRoleBasedUserAccountEditGrant(userAccount, currentUser.get());
- // new PageContext with actual EntityKey
- final PageContext formContext = pageContext.withEntityKey(userAccount.getEntityKey());
- final boolean ownAccount = user.uuid.equals(userAccount.getModelId());
- final EntityGrantCheck userGrantCheck = currentUser.entityGrantCheck(userAccount);
-
- final boolean writeGrant = roleBasedEditGrant && userGrantCheck.w();
- final boolean modifyGrant = roleBasedEditGrant && userGrantCheck.m();
- final boolean institutionalWriteGrant = currentUser.hasInstitutionalPrivilege(
- PrivilegeType.WRITE,
- EntityType.USER);
-
- final boolean institutionActive = restService.getBuilder(GetInstitution.class)
- .withURIVariable(API.PARAM_MODEL_ID, String.valueOf(userAccount.getInstitutionId()))
- .call()
- .map(inst -> inst.active)
- .getOr(false);
-
- // the default page layout with title
- final LocTextKey titleKey = isNotNew.getAsBoolean()
- ? TITLE_TEXT_KEY
- : NEW_TITLE_TEXT_KEY;
- final Composite content = widgetFactory.defaultPageLayout(
- formContext.getParent(),
- titleKey);
-
- // The UserAccount form
- final FormHandle formHandle = this.pageService.formBuilder(
- formContext.copyOf(content))
- .readonly(readonly)
- .putStaticValueIf(isNotNew,
- Domain.USER.ATTR_UUID,
- userAccount.getModelId())
- .putStaticValueIf(isNotNew,
- Domain.USER.ATTR_INSTITUTION_ID,
- String.valueOf(userAccount.getInstitutionId()))
- .putStaticValueIf(
- () -> !this.multilingual,
- Domain.USER.ATTR_LANGUAGE,
- "en")
- .addFieldIf(
- isSEBAdmin,
- () -> FormBuilder.singleSelection(
- Domain.USER.ATTR_INSTITUTION_ID,
- FORM_INSTITUTION_TEXT_KEY,
- String.valueOf(userAccount.getInstitutionId()),
- () -> this.resourceService.institutionResource())
- .readonlyIf(isNotNew))
- .addFieldIf(
- () -> readonly,
- () -> FormBuilder.text(
- Domain.USER.ATTR_CREATION_DATE,
- FORM_CREATION_DATE_TEXT_KEY,
- this.pageService.getI18nSupport().formatDisplayDate(userAccount.getCreationDate()))
- .readonly(true))
- .addField(FormBuilder.text(
- Domain.USER.ATTR_NAME,
- FORM_NAME_TEXT_KEY,
- userAccount.getName()))
- .addField(FormBuilder.text(
- Domain.USER.ATTR_SURNAME,
- FORM_SURNAME_TEXT_KEY,
- userAccount.getSurname()))
- .addField(FormBuilder.text(
- Domain.USER.ATTR_USERNAME,
- FORM_USERNAME_TEXT_KEY,
- userAccount.getUsername()))
- .addField(FormBuilder.text(
- Domain.USER.ATTR_EMAIL,
- FORM_MAIL_TEXT_KEY,
- userAccount.getEmail()))
- .addFieldIf(
- () -> this.multilingual,
- () -> FormBuilder.singleSelection(
- Domain.USER.ATTR_LANGUAGE,
- FORM_LANG_TEXT_KEY,
- userAccount.getLanguage().getLanguage(),
- this.resourceService::languageResources))
- .addField(FormBuilder.singleSelection(
- Domain.USER.ATTR_TIMEZONE,
- FORM_TIMEZONE_TEXT_KEY,
- userAccount.getTimeZone().getID(),
- this.resourceService::timeZoneResources))
- .addFieldIf(
- () -> modifyGrant,
- () -> FormBuilder.multiCheckboxSelection(
- USER_ROLE.REFERENCE_NAME,
- FORM_ROLES_TEXT_KEY,
- StringUtils.join(userAccount.getRoles(), Constants.LIST_SEPARATOR_CHAR),
- this.resourceService::userRoleResources)
- .visibleIf(writeGrant))
- .addFieldIf(
- isNew,
- () -> FormBuilder.text(
- PasswordChange.ATTR_NAME_NEW_PASSWORD,
- FORM_PASSWORD_TEXT_KEY)
- .asPasswordField())
- .addFieldIf(
- isNew,
- () -> FormBuilder.text(
- PasswordChange.ATTR_NAME_CONFIRM_NEW_PASSWORD,
- FORM_PASSWORD_CONFIRM_TEXT_KEY)
- .asPasswordField())
- .buildFor((entityKey == null)
- ? restService.getRestCall(NewUserAccount.class)
- : restService.getRestCall(SaveUserAccount.class));
-
- // propagate content actions to action-pane
- this.pageService.pageActionBuilder(formContext.clearEntityKeys())
-
- .newAction(ActionDefinition.USER_ACCOUNT_NEW)
- .publishIf(() -> institutionalWriteGrant && readonly && institutionActive)
-
- .newAction(ActionDefinition.USER_ACCOUNT_MODIFY)
- .withEntityKey(entityKey)
- .publishIf(() -> modifyGrant && readonly && institutionActive)
-
- .newAction(ActionDefinition.USER_ACCOUNT_CHANGE_PASSOWRD)
- .withEntityKey(entityKey)
- .publishIf(() -> modifyGrant && readonly && institutionActive && userAccount.isActive())
-
- .newAction(ActionDefinition.USER_ACCOUNT_DEACTIVATE)
- .withEntityKey(entityKey)
- .withSimpleRestCall(restService, DeactivateUserAccount.class)
- .withConfirm(this.pageService.confirmDeactivation(userAccount))
- .publishIf(() -> writeGrant && readonly && institutionActive && userAccount.isActive())
-
- .newAction(ActionDefinition.USER_ACCOUNT_ACTIVATE)
- .withEntityKey(entityKey)
- .withSimpleRestCall(restService, ActivateUserAccount.class)
- .publishIf(() -> writeGrant && readonly && institutionActive && !userAccount.isActive())
-
- .newAction(ActionDefinition.USER_ACCOUNT_SAVE)
- .withEntityKey(entityKey)
- .withExec(action -> {
- return formHandle.handleFormPost(formHandle.doAPIPost()
- .map(userInfo -> {
- if (ownAccount) {
- currentUser.refresh(userInfo);
- }
- return userInfo;
- }),
- action);
- })
- .ignoreMoveAwayFromEdit()
- .publishIf(() -> !readonly)
-
- .newAction(ActionDefinition.USER_ACCOUNT_CANCEL_MODIFY)
- .withExec(this.pageService.backToCurrentFunction())
- .publishIf(() -> !readonly);
- }
-
-}
+/*
+ * 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.content;
+
+import java.util.function.BooleanSupplier;
+
+import org.apache.commons.lang3.BooleanUtils;
+import org.apache.tomcat.util.buf.StringUtils;
+import org.eclipse.swt.widgets.Composite;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Lazy;
+import org.springframework.stereotype.Component;
+
+import ch.ethz.seb.sebserver.gbl.Constants;
+import ch.ethz.seb.sebserver.gbl.api.API;
+import ch.ethz.seb.sebserver.gbl.api.EntityType;
+import ch.ethz.seb.sebserver.gbl.api.authorization.Privilege;
+import ch.ethz.seb.sebserver.gbl.api.authorization.PrivilegeType;
+import ch.ethz.seb.sebserver.gbl.model.Domain;
+import ch.ethz.seb.sebserver.gbl.model.Domain.USER_ROLE;
+import ch.ethz.seb.sebserver.gbl.model.EntityKey;
+import ch.ethz.seb.sebserver.gbl.model.user.PasswordChange;
+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.content.action.ActionDefinition;
+import ch.ethz.seb.sebserver.gui.form.FormBuilder;
+import ch.ethz.seb.sebserver.gui.form.FormHandle;
+import ch.ethz.seb.sebserver.gui.service.ResourceService;
+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.PageService;
+import ch.ethz.seb.sebserver.gui.service.page.TemplateComposer;
+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.useraccount.ActivateUserAccount;
+import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.useraccount.DeactivateUserAccount;
+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.remote.webservice.auth.CurrentUser.EntityGrantCheck;
+import ch.ethz.seb.sebserver.gui.widget.WidgetFactory;
+
+@Lazy
+@Component
+@GuiProfile
+public class UserAccountForm implements TemplateComposer {
+
+ static final LocTextKey TITLE_TEXT_KEY =
+ new LocTextKey("sebserver.useraccount.form.title");
+ static final LocTextKey NEW_TITLE_TEXT_KEY =
+ new LocTextKey("sebserver.useraccount.form.title.new");
+
+ static final LocTextKey FORM_PASSWORD_CONFIRM_TEXT_KEY =
+ new LocTextKey("sebserver.useraccount.form.password.confirm");
+ static final LocTextKey FORM_PASSWORD_TEXT_KEY =
+ new LocTextKey("sebserver.useraccount.form.password");
+ static final LocTextKey FORM_ROLES_TEXT_KEY =
+ new LocTextKey("sebserver.useraccount.form.roles");
+ static final LocTextKey FORM_TIMEZONE_TEXT_KEY =
+ new LocTextKey("sebserver.useraccount.form.timezone");
+ static final LocTextKey FORM_MAIL_TEXT_KEY =
+ new LocTextKey("sebserver.useraccount.form.mail");
+ static final LocTextKey FORM_USERNAME_TEXT_KEY =
+ new LocTextKey("sebserver.useraccount.form.username");
+ static final LocTextKey FORM_NAME_TEXT_KEY =
+ new LocTextKey("sebserver.useraccount.form.name");
+ static final LocTextKey FORM_SURNAME_TEXT_KEY =
+ new LocTextKey("sebserver.useraccount.form.surname");
+ static final LocTextKey FORM_INSTITUTION_TEXT_KEY =
+ new LocTextKey("sebserver.useraccount.form.institution");
+ static final LocTextKey FORM_CREATION_DATE_TEXT_KEY =
+ new LocTextKey("sebserver.useraccount.form.creationdate");
+ static final LocTextKey FORM_LANG_TEXT_KEY =
+ new LocTextKey("sebserver.useraccount.form.language");
+
+ private final PageService pageService;
+ private final ResourceService resourceService;
+ private final boolean multilingual;
+
+ protected UserAccountForm(
+ final PageService pageService,
+ final ResourceService resourceService,
+ @Value("${sebserver.gui.multilingual:false}") final Boolean multilingual) {
+
+ this.pageService = pageService;
+ this.resourceService = resourceService;
+ this.multilingual = BooleanUtils.toBoolean(multilingual);
+ }
+
+ @Override
+ public void compose(final PageContext pageContext) {
+ final CurrentUser currentUser = this.resourceService.getCurrentUser();
+ final RestService restService = this.resourceService.getRestService();
+ final WidgetFactory widgetFactory = this.pageService.getWidgetFactory();
+
+ final UserInfo user = currentUser.get();
+ final EntityKey entityKey = pageContext.getEntityKey();
+ final EntityKey parentEntityKey = pageContext.getParentEntityKey();
+ final boolean readonly = pageContext.isReadonly();
+
+ final BooleanSupplier isNew = () -> entityKey == null;
+ final BooleanSupplier isNotNew = () -> !isNew.getAsBoolean();
+ final BooleanSupplier isSEBAdmin = () -> user.hasRole(UserRole.SEB_SERVER_ADMIN);
+
+ // get data or create new. handle error if happen
+ final UserAccount userAccount = isNew.getAsBoolean()
+ ? UserMod.createNew((parentEntityKey != null)
+ ? Long.valueOf(parentEntityKey.modelId)
+ : currentUser.get().institutionId)
+ : restService
+ .getBuilder(GetUserAccount.class)
+ .withURIVariable(API.PARAM_MODEL_ID, entityKey.modelId)
+ .call()
+ .onError(error -> pageContext.notifyLoadError(EntityType.USER, error))
+ .getOrThrow();
+
+ final boolean roleBasedEditGrant = Privilege.hasRoleBasedUserAccountEditGrant(userAccount, currentUser.get());
+ // new PageContext with actual EntityKey
+ final PageContext formContext = pageContext.withEntityKey(userAccount.getEntityKey());
+ final boolean ownAccount = user.uuid.equals(userAccount.getModelId());
+ final EntityGrantCheck userGrantCheck = currentUser.entityGrantCheck(userAccount);
+
+ final boolean writeGrant = roleBasedEditGrant && userGrantCheck.w();
+ final boolean modifyGrant = roleBasedEditGrant && userGrantCheck.m();
+ final boolean institutionalWriteGrant = currentUser.hasInstitutionalPrivilege(
+ PrivilegeType.WRITE,
+ EntityType.USER);
+
+ final boolean institutionActive = userAccount.getInstitutionId() != null &&
+ restService.getBuilder(GetInstitution.class)
+ .withURIVariable(API.PARAM_MODEL_ID, String.valueOf(userAccount.getInstitutionId()))
+ .call()
+ .map(inst -> inst.active)
+ .getOr(false);
+
+ // the default page layout with title
+ final LocTextKey titleKey = isNotNew.getAsBoolean()
+ ? TITLE_TEXT_KEY
+ : NEW_TITLE_TEXT_KEY;
+ final Composite content = widgetFactory.defaultPageLayout(
+ formContext.getParent(),
+ titleKey);
+
+ // The UserAccount form
+ final FormHandle formHandle = this.pageService.formBuilder(
+ formContext.copyOf(content))
+ .readonly(readonly)
+ .putStaticValueIf(isNotNew,
+ Domain.USER.ATTR_UUID,
+ userAccount.getModelId())
+ .putStaticValueIf(isNotNew,
+ Domain.USER.ATTR_INSTITUTION_ID,
+ String.valueOf(userAccount.getInstitutionId()))
+ .putStaticValueIf(
+ () -> !this.multilingual,
+ Domain.USER.ATTR_LANGUAGE,
+ "en")
+ .addFieldIf(
+ isSEBAdmin,
+ () -> FormBuilder.singleSelection(
+ Domain.USER.ATTR_INSTITUTION_ID,
+ FORM_INSTITUTION_TEXT_KEY,
+ String.valueOf(userAccount.getInstitutionId()),
+ this.resourceService::institutionResource)
+ .readonlyIf(isNotNew)
+ .mandatory(!readonly))
+ .addFieldIf(
+ () -> readonly,
+ () -> FormBuilder.text(
+ Domain.USER.ATTR_CREATION_DATE,
+ FORM_CREATION_DATE_TEXT_KEY,
+ this.pageService.getI18nSupport().formatDisplayDate(userAccount.getCreationDate()))
+ .readonly(true))
+ .addField(FormBuilder.text(
+ Domain.USER.ATTR_NAME,
+ FORM_NAME_TEXT_KEY,
+ userAccount.getName())
+ .mandatory(!readonly))
+ .addField(FormBuilder.text(
+ Domain.USER.ATTR_SURNAME,
+ FORM_SURNAME_TEXT_KEY,
+ userAccount.getSurname())
+ .mandatory(!readonly))
+ .addField(FormBuilder.text(
+ Domain.USER.ATTR_USERNAME,
+ FORM_USERNAME_TEXT_KEY,
+ userAccount.getUsername())
+ .mandatory(!readonly))
+ .addField(FormBuilder.text(
+ Domain.USER.ATTR_EMAIL,
+ FORM_MAIL_TEXT_KEY,
+ userAccount.getEmail()))
+ .addFieldIf(
+ () -> this.multilingual,
+ () -> FormBuilder.singleSelection(
+ Domain.USER.ATTR_LANGUAGE,
+ FORM_LANG_TEXT_KEY,
+ userAccount.getLanguage().getLanguage(),
+ this.resourceService::languageResources))
+ .addField(FormBuilder.singleSelection(
+ Domain.USER.ATTR_TIMEZONE,
+ FORM_TIMEZONE_TEXT_KEY,
+ userAccount.getTimeZone().getID(),
+ this.resourceService::timeZoneResources)
+ .mandatory(!readonly))
+ .addFieldIf(
+ () -> modifyGrant,
+ () -> FormBuilder.multiCheckboxSelection(
+ USER_ROLE.REFERENCE_NAME,
+ FORM_ROLES_TEXT_KEY,
+ StringUtils.join(userAccount.getRoles(), Constants.LIST_SEPARATOR_CHAR),
+ this.resourceService::userRoleResources)
+ .visibleIf(writeGrant)
+ .mandatory(!readonly))
+ .addFieldIf(
+ isNew,
+ () -> FormBuilder.text(
+ PasswordChange.ATTR_NAME_NEW_PASSWORD,
+ FORM_PASSWORD_TEXT_KEY)
+ .asPasswordField()
+ .mandatory(!readonly))
+ .addFieldIf(
+ isNew,
+ () -> FormBuilder.text(
+ PasswordChange.ATTR_NAME_CONFIRM_NEW_PASSWORD,
+ FORM_PASSWORD_CONFIRM_TEXT_KEY)
+ .asPasswordField()
+ .mandatory(!readonly))
+ .buildFor((entityKey == null)
+ ? restService.getRestCall(NewUserAccount.class)
+ : restService.getRestCall(SaveUserAccount.class));
+
+ // propagate content actions to action-pane
+ this.pageService.pageActionBuilder(formContext.clearEntityKeys())
+
+ .newAction(ActionDefinition.USER_ACCOUNT_NEW)
+ .publishIf(() -> institutionalWriteGrant && readonly && institutionActive)
+
+ .newAction(ActionDefinition.USER_ACCOUNT_MODIFY)
+ .withEntityKey(entityKey)
+ .publishIf(() -> modifyGrant && readonly && institutionActive)
+
+ .newAction(ActionDefinition.USER_ACCOUNT_CHANGE_PASSWORD)
+ .withEntityKey(entityKey)
+ .publishIf(() -> modifyGrant && readonly && institutionActive && userAccount.isActive())
+
+ .newAction(ActionDefinition.USER_ACCOUNT_DEACTIVATE)
+ .withEntityKey(entityKey)
+ .withSimpleRestCall(restService, DeactivateUserAccount.class)
+ .withConfirm(this.pageService.confirmDeactivation(userAccount))
+ .publishIf(() -> writeGrant && readonly && institutionActive && userAccount.isActive())
+
+ .newAction(ActionDefinition.USER_ACCOUNT_ACTIVATE)
+ .withEntityKey(entityKey)
+ .withSimpleRestCall(restService, ActivateUserAccount.class)
+ .publishIf(() -> writeGrant && readonly && institutionActive && !userAccount.isActive())
+
+ .newAction(ActionDefinition.USER_ACCOUNT_SAVE)
+ .withEntityKey(entityKey)
+ .withExec(action -> formHandle.handleFormPost(formHandle.doAPIPost()
+ .map(userInfo -> {
+ if (ownAccount) {
+ currentUser.refresh(userInfo);
+ }
+ return userInfo;
+ }),
+ action))
+ .ignoreMoveAwayFromEdit()
+ .publishIf(() -> !readonly)
+
+ .newAction(ActionDefinition.USER_ACCOUNT_SAVE_AND_ACTIVATE)
+ .withEntityKey(entityKey)
+ .withExec(formHandle::saveAndActivate)
+ .ignoreMoveAwayFromEdit()
+ .publishIf(() -> !readonly && !ownAccount && !userAccount.isActive())
+
+ .newAction(ActionDefinition.USER_ACCOUNT_CANCEL_MODIFY)
+ .withExec(this.pageService.backToCurrentFunction())
+ .publishIf(() -> !readonly);
+ }
+}
diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/content/UserAccountList.java b/src/main/java/ch/ethz/seb/sebserver/gui/content/UserAccountList.java
index a8a68cbc..5e4d60e8 100644
--- a/src/main/java/ch/ethz/seb/sebserver/gui/content/UserAccountList.java
+++ b/src/main/java/ch/ethz/seb/sebserver/gui/content/UserAccountList.java
@@ -1,236 +1,250 @@
-/*
- * 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.content;
-
-import java.util.function.BooleanSupplier;
-import java.util.function.Function;
-
-import org.apache.commons.lang3.BooleanUtils;
-import org.eclipse.swt.widgets.Composite;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.context.annotation.Lazy;
-import org.springframework.stereotype.Component;
-
-import ch.ethz.seb.sebserver.gbl.Constants;
-import ch.ethz.seb.sebserver.gbl.api.API;
-import ch.ethz.seb.sebserver.gbl.api.EntityType;
-import ch.ethz.seb.sebserver.gbl.api.authorization.Privilege;
-import ch.ethz.seb.sebserver.gbl.model.Domain;
-import ch.ethz.seb.sebserver.gbl.model.Entity;
-import ch.ethz.seb.sebserver.gbl.model.user.UserInfo;
-import ch.ethz.seb.sebserver.gbl.model.user.UserRole;
-import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
-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.LocTextKey;
-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.PageService;
-import ch.ethz.seb.sebserver.gui.service.page.PageService.PageActionBuilder;
-import ch.ethz.seb.sebserver.gui.service.page.TemplateComposer;
-import ch.ethz.seb.sebserver.gui.service.page.impl.PageAction;
-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.GetUserAccountPage;
-import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.CurrentUser;
-import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.CurrentUser.GrantCheck;
-import ch.ethz.seb.sebserver.gui.table.ColumnDefinition;
-import ch.ethz.seb.sebserver.gui.table.ColumnDefinition.TableFilterAttribute;
-import ch.ethz.seb.sebserver.gui.table.EntityTable;
-import ch.ethz.seb.sebserver.gui.table.TableFilter.CriteriaType;
-import ch.ethz.seb.sebserver.gui.widget.WidgetFactory;
-
-@Lazy
-@Component
-@GuiProfile
-public class UserAccountList implements TemplateComposer {
-
- // localized text keys
- private static final LocTextKey EMPTY_TEXT_KEY =
- new LocTextKey("sebserver.useraccount.list.empty");
- private static final LocTextKey INSTITUTION_TEXT_KEY =
- new LocTextKey("sebserver.useraccount.list.column.institution");
- private static final LocTextKey EMPTY_SELECTION_TEXT_KEY =
- new LocTextKey("sebserver.useraccount.info.pleaseSelect");
- private static final LocTextKey ACTIVE_TEXT_KEY =
- new LocTextKey("sebserver.useraccount.list.column.active");
- private static final LocTextKey LANG_TEXT_KEY =
- new LocTextKey("sebserver.useraccount.list.column.language");
- private static final LocTextKey MAIL_TEXT_KEY =
- new LocTextKey("sebserver.useraccount.list.column.email");
- private static final LocTextKey USER_NAME_TEXT_KEY =
- new LocTextKey("sebserver.useraccount.list.column.username");
- private static final LocTextKey NAME_TEXT_KEY =
- new LocTextKey("sebserver.useraccount.list.column.name");
- private static final LocTextKey TITLE_TEXT_KEY =
- new LocTextKey("sebserver.useraccount.list.title");
- private static final LocTextKey NO_EDIT_RIGHT_MESSAGE =
- new LocTextKey("sebserver.useraccount.info.notEditable");
-
- // filter attribute models
- private final TableFilterAttribute institutionFilter;
- private final TableFilterAttribute nameFilter =
- new TableFilterAttribute(CriteriaType.TEXT, Entity.FILTER_ATTR_NAME);
- private final TableFilterAttribute usernameFilter =
- new TableFilterAttribute(CriteriaType.TEXT, UserInfo.FILTER_ATTR_USER_NAME);
- private final TableFilterAttribute mailFilter =
- new TableFilterAttribute(CriteriaType.TEXT, UserInfo.FILTER_ATTR_EMAIL);
- private final TableFilterAttribute languageFilter;
- private final TableFilterAttribute activityFilter;
-
- // dependencies
- private final PageService pageService;
- private final ResourceService resourceService;
- private final int pageSize;
- private final boolean multilingual;
-
- protected UserAccountList(
- final PageService pageService,
- final ResourceService resourceService,
- @Value("${sebserver.gui.list.page.size:20}") final Integer pageSize,
- @Value("${sebserver.gui.multilingual:false}") final Boolean ml) {
-
- this.pageService = pageService;
- this.resourceService = resourceService;
- this.pageSize = pageSize;
- this.multilingual = BooleanUtils.isTrue(ml);
-
- this.institutionFilter = new TableFilterAttribute(
- CriteriaType.SINGLE_SELECTION,
- Entity.FILTER_ATTR_INSTITUTION,
- this.resourceService::institutionResource);
-
- this.languageFilter = new TableFilterAttribute(
- CriteriaType.SINGLE_SELECTION,
- UserInfo.FILTER_ATTR_LANGUAGE,
- this.resourceService::languageResources);
-
- this.activityFilter = new TableFilterAttribute(
- CriteriaType.SINGLE_SELECTION,
- UserInfo.FILTER_ATTR_ACTIVE,
- this.resourceService::activityResources);
- }
-
- @Override
- public void compose(final PageContext pageContext) {
- final WidgetFactory widgetFactory = this.pageService.getWidgetFactory();
- final CurrentUser currentUser = this.resourceService.getCurrentUser();
- final RestService restService = this.resourceService.getRestService();
- // content page layout with title
- final Composite content = widgetFactory.defaultPageLayout(
- pageContext.getParent(),
- TITLE_TEXT_KEY);
-
- final BooleanSupplier isSEBAdmin = () -> currentUser.get().hasRole(UserRole.SEB_SERVER_ADMIN);
- final PageActionBuilder actionBuilder = this.pageService.pageActionBuilder(pageContext.clearEntityKeys());
-
- // table
- final EntityTable table = this.pageService.entityTableBuilder(
- restService.getRestCall(GetUserAccountPage.class))
- .withEmptyMessage(EMPTY_TEXT_KEY)
- .withPaging(this.pageSize)
-
- .withColumnIf(
- isSEBAdmin,
- () -> new ColumnDefinition<>(
- Domain.USER.ATTR_INSTITUTION_ID,
- INSTITUTION_TEXT_KEY,
- userInstitutionNameFunction(this.resourceService))
- .withFilter(this.institutionFilter)
- .widthProportion(2))
-
- .withColumn(new ColumnDefinition<>(
- Domain.USER.ATTR_NAME,
- NAME_TEXT_KEY,
- UserInfo::getName)
- .withFilter(this.nameFilter)
- .sortable()
- .widthProportion(2))
-
- .withColumn(new ColumnDefinition<>(
- Domain.USER.ATTR_USERNAME,
- USER_NAME_TEXT_KEY,
- UserInfo::getUsername)
- .withFilter(this.usernameFilter)
- .sortable()
- .widthProportion(2))
-
- .withColumn(new ColumnDefinition<>(
- Domain.USER.ATTR_EMAIL,
- MAIL_TEXT_KEY,
- UserInfo::getEmail)
- .withFilter(this.mailFilter)
- .sortable()
- .widthProportion(3))
-
- .withColumnIf(() -> this.multilingual,
- () -> new ColumnDefinition<>(
- Domain.USER.ATTR_LANGUAGE,
- LANG_TEXT_KEY,
- this::getLocaleDisplayText)
- .withFilter(this.languageFilter)
- .localized()
- .sortable()
- .widthProportion(1))
-
- .withColumn(new ColumnDefinition<>(
- Domain.USER.ATTR_ACTIVE,
- ACTIVE_TEXT_KEY,
- this.pageService.getResourceService(). localizedActivityFunction())
- .sortable()
- .withFilter(this.activityFilter)
- .widthProportion(1))
-
- .withDefaultAction(actionBuilder
- .newAction(ActionDefinition.USER_ACCOUNT_VIEW_FROM_LIST)
- .create())
- .compose(pageContext.copyOf(content));
-
- // propagate content actions to action-pane
- final GrantCheck userGrant = currentUser.grantCheck(EntityType.USER);
- actionBuilder
-
- .newAction(ActionDefinition.USER_ACCOUNT_NEW)
- .publishIf(userGrant::iw)
-
- .newAction(ActionDefinition.USER_ACCOUNT_VIEW_FROM_LIST)
- .withSelect(table::getSelection, PageAction::applySingleSelectionAsEntityKey, EMPTY_SELECTION_TEXT_KEY)
- .publishIf(() -> table.hasAnyContent())
-
- .newAction(ActionDefinition.USER_ACCOUNT_MODIFY_FROM_LIST)
- .withSelect(table::getSelection, this::editAction, EMPTY_SELECTION_TEXT_KEY)
- .publishIf(() -> userGrant.im() && table.hasAnyContent());
- }
-
- private PageAction editAction(final PageAction pageAction) {
- if (!this.resourceService.getRestService()
- .getBuilder(GetUserAccount.class)
- .withURIVariable(API.PARAM_MODEL_ID, pageAction.getSingleSelection().modelId)
- .call()
- .map(user -> Privilege.hasRoleBasedUserAccountEditGrant(user,
- this.resourceService.getCurrentUser().get()))
- .getOr(false)) {
- throw new PageMessageException(NO_EDIT_RIGHT_MESSAGE);
- }
-
- return PageAction.applySingleSelectionAsEntityKey(pageAction);
- }
-
- private String getLocaleDisplayText(final UserInfo userInfo) {
- return (userInfo.language != null)
- ? userInfo.language.getDisplayLanguage(this.pageService.getI18nSupport().getUsersLanguageLocale())
- : Constants.EMPTY_NOTE;
- }
-
- private static Function userInstitutionNameFunction(final ResourceService resourceService) {
- final Function institutionNameFunction = resourceService.getInstitutionNameFunction();
- return userInfo -> institutionNameFunction.apply(String.valueOf(userInfo.institutionId));
- }
-
-}
+/*
+ * 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.content;
+
+import ch.ethz.seb.sebserver.gbl.Constants;
+import ch.ethz.seb.sebserver.gbl.api.API;
+import ch.ethz.seb.sebserver.gbl.api.EntityType;
+import ch.ethz.seb.sebserver.gbl.api.authorization.Privilege;
+import ch.ethz.seb.sebserver.gbl.model.Domain;
+import ch.ethz.seb.sebserver.gbl.model.Entity;
+import ch.ethz.seb.sebserver.gbl.model.user.UserInfo;
+import ch.ethz.seb.sebserver.gbl.model.user.UserRole;
+import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
+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.LocTextKey;
+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.PageService;
+import ch.ethz.seb.sebserver.gui.service.page.PageService.PageActionBuilder;
+import ch.ethz.seb.sebserver.gui.service.page.TemplateComposer;
+import ch.ethz.seb.sebserver.gui.service.page.impl.PageAction;
+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.GetUserAccountPage;
+import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.CurrentUser;
+import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.CurrentUser.GrantCheck;
+import ch.ethz.seb.sebserver.gui.table.ColumnDefinition;
+import ch.ethz.seb.sebserver.gui.table.ColumnDefinition.TableFilterAttribute;
+import ch.ethz.seb.sebserver.gui.table.EntityTable;
+import ch.ethz.seb.sebserver.gui.table.TableFilter.CriteriaType;
+import ch.ethz.seb.sebserver.gui.widget.WidgetFactory;
+import org.apache.commons.lang3.BooleanUtils;
+import org.eclipse.swt.widgets.Composite;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Lazy;
+import org.springframework.stereotype.Component;
+
+import java.util.function.BooleanSupplier;
+import java.util.function.Function;
+
+@Lazy
+@Component
+@GuiProfile
+public class UserAccountList implements TemplateComposer {
+
+ // localized text keys
+ private static final LocTextKey EMPTY_TEXT_KEY =
+ new LocTextKey("sebserver.useraccount.list.empty");
+ private static final LocTextKey INSTITUTION_TEXT_KEY =
+ new LocTextKey("sebserver.useraccount.list.column.institution");
+ private static final LocTextKey EMPTY_SELECTION_TEXT_KEY =
+ new LocTextKey("sebserver.useraccount.info.pleaseSelect");
+ private static final LocTextKey ACTIVE_TEXT_KEY =
+ new LocTextKey("sebserver.useraccount.list.column.active");
+ private static final LocTextKey LANG_TEXT_KEY =
+ new LocTextKey("sebserver.useraccount.list.column.language");
+ private static final LocTextKey MAIL_TEXT_KEY =
+ new LocTextKey("sebserver.useraccount.list.column.email");
+ private static final LocTextKey USER_NAME_TEXT_KEY =
+ new LocTextKey("sebserver.useraccount.list.column.username");
+ private static final LocTextKey NAME_TEXT_KEY =
+ new LocTextKey("sebserver.useraccount.list.column.name");
+ private static final LocTextKey TITLE_TEXT_KEY =
+ new LocTextKey("sebserver.useraccount.list.title");
+ private static final LocTextKey NO_EDIT_RIGHT_MESSAGE =
+ new LocTextKey("sebserver.useraccount.info.notEditable");
+
+ // filter attribute models
+ private final TableFilterAttribute institutionFilter;
+ private final TableFilterAttribute nameFilter =
+ new TableFilterAttribute(CriteriaType.TEXT, Entity.FILTER_ATTR_NAME);
+ private final TableFilterAttribute usernameFilter =
+ new TableFilterAttribute(CriteriaType.TEXT, UserInfo.FILTER_ATTR_USER_NAME);
+ private final TableFilterAttribute mailFilter =
+ new TableFilterAttribute(CriteriaType.TEXT, UserInfo.FILTER_ATTR_EMAIL);
+ private final TableFilterAttribute languageFilter;
+ private final TableFilterAttribute activityFilter;
+
+ // dependencies
+ private final PageService pageService;
+ private final ResourceService resourceService;
+ private final int pageSize;
+ private final boolean multilingual;
+
+ protected UserAccountList(
+ final PageService pageService,
+ final ResourceService resourceService,
+ @Value("${sebserver.gui.list.page.size:20}") final Integer pageSize,
+ @Value("${sebserver.gui.multilingual:false}") final Boolean ml) {
+
+ this.pageService = pageService;
+ this.resourceService = resourceService;
+ this.pageSize = pageSize;
+ this.multilingual = BooleanUtils.isTrue(ml);
+
+ this.institutionFilter = new TableFilterAttribute(
+ CriteriaType.SINGLE_SELECTION,
+ Entity.FILTER_ATTR_INSTITUTION,
+ this.resourceService::institutionResource);
+
+ this.languageFilter = new TableFilterAttribute(
+ CriteriaType.SINGLE_SELECTION,
+ UserInfo.FILTER_ATTR_LANGUAGE,
+ this.resourceService::languageResources);
+
+ this.activityFilter = new TableFilterAttribute(
+ CriteriaType.SINGLE_SELECTION,
+ UserInfo.FILTER_ATTR_ACTIVE,
+ this.resourceService::activityResources);
+ }
+
+ @Override
+ public void compose(final PageContext pageContext) {
+ final WidgetFactory widgetFactory = this.pageService.getWidgetFactory();
+ final CurrentUser currentUser = this.resourceService.getCurrentUser();
+ final RestService restService = this.resourceService.getRestService();
+ // content page layout with title
+ final Composite content = widgetFactory.defaultPageLayout(
+ pageContext.getParent(),
+ TITLE_TEXT_KEY);
+
+ final BooleanSupplier isSEBAdmin = () -> currentUser.get().hasRole(UserRole.SEB_SERVER_ADMIN);
+ final PageActionBuilder actionBuilder = this.pageService.pageActionBuilder(pageContext.clearEntityKeys());
+
+ // table
+ final EntityTable table = this.pageService.entityTableBuilder(
+ restService.getRestCall(GetUserAccountPage.class))
+ .withEmptyMessage(EMPTY_TEXT_KEY)
+ .withPaging(this.pageSize)
+
+ .withColumnIf(
+ isSEBAdmin,
+ () -> new ColumnDefinition<>(
+ Domain.USER.ATTR_INSTITUTION_ID,
+ INSTITUTION_TEXT_KEY,
+ userInstitutionNameFunction(this.resourceService))
+ .withFilter(this.institutionFilter)
+ .widthProportion(2))
+
+ .withColumn(new ColumnDefinition<>(
+ Domain.USER.ATTR_NAME,
+ NAME_TEXT_KEY,
+ UserInfo::getName)
+ .withFilter(this.nameFilter)
+ .sortable()
+ .widthProportion(2))
+
+ .withColumn(new ColumnDefinition<>(
+ Domain.USER.ATTR_USERNAME,
+ USER_NAME_TEXT_KEY,
+ UserInfo::getUsername)
+ .withFilter(this.usernameFilter)
+ .sortable()
+ .widthProportion(2))
+
+ .withColumn(new ColumnDefinition<>(
+ Domain.USER.ATTR_EMAIL,
+ MAIL_TEXT_KEY,
+ UserInfo::getEmail)
+ .withFilter(this.mailFilter)
+ .sortable()
+ .widthProportion(3))
+
+ .withColumnIf(() -> this.multilingual,
+ () -> new ColumnDefinition<>(
+ Domain.USER.ATTR_LANGUAGE,
+ LANG_TEXT_KEY,
+ this::getLocaleDisplayText)
+ .withFilter(this.languageFilter)
+ .localized()
+ .sortable()
+ .widthProportion(1))
+
+ .withColumn(new ColumnDefinition<>(
+ Domain.USER.ATTR_ACTIVE,
+ ACTIVE_TEXT_KEY,
+ this.pageService.getResourceService(). localizedActivityFunction())
+ .sortable()
+ .withFilter(this.activityFilter)
+ .widthProportion(1))
+
+ .withDefaultAction(actionBuilder
+ .newAction(ActionDefinition.USER_ACCOUNT_VIEW_FROM_LIST)
+ .create())
+
+ .withSelectionListener(this.pageService.getSelectionPublisher(
+ ActionDefinition.USER_ACCOUNT_TOGGLE_ACTIVITY,
+ ActionDefinition.USER_ACCOUNT_ACTIVATE,
+ ActionDefinition.USER_ACCOUNT_DEACTIVATE,
+ pageContext,
+ ActionDefinition.USER_ACCOUNT_VIEW_FROM_LIST,
+ ActionDefinition.USER_ACCOUNT_MODIFY_FROM_LIST,
+ ActionDefinition.USER_ACCOUNT_TOGGLE_ACTIVITY))
+
+ .compose(pageContext.copyOf(content));
+
+ // propagate content actions to action-pane
+ final GrantCheck userGrant = currentUser.grantCheck(EntityType.USER);
+ actionBuilder
+
+ .newAction(ActionDefinition.USER_ACCOUNT_NEW)
+ .publishIf(userGrant::iw)
+
+ .newAction(ActionDefinition.USER_ACCOUNT_VIEW_FROM_LIST)
+ .withSelect(table::getSelection, PageAction::applySingleSelectionAsEntityKey, EMPTY_SELECTION_TEXT_KEY)
+ .publishIf(table::hasAnyContent, false)
+
+ .newAction(ActionDefinition.USER_ACCOUNT_MODIFY_FROM_LIST)
+ .withSelect(table::getSelection, this::editAction, EMPTY_SELECTION_TEXT_KEY)
+ .publishIf(() -> userGrant.im() && table.hasAnyContent(), false)
+
+ .newAction(ActionDefinition.USER_ACCOUNT_TOGGLE_ACTIVITY)
+ .withExec(this.pageService.activationToggleActionFunction(table, EMPTY_SELECTION_TEXT_KEY))
+ .withConfirm(this.pageService.confirmDeactivation(table))
+ .publishIf(() -> userGrant.m() && table.hasAnyContent(), false);
+ }
+
+ private PageAction editAction(final PageAction pageAction) {
+ if (!this.resourceService.getRestService()
+ .getBuilder(GetUserAccount.class)
+ .withURIVariable(API.PARAM_MODEL_ID, pageAction.getSingleSelection().modelId)
+ .call()
+ .map(user -> Privilege.hasRoleBasedUserAccountEditGrant(user,
+ this.resourceService.getCurrentUser().get()))
+ .getOr(false)) {
+ throw new PageMessageException(NO_EDIT_RIGHT_MESSAGE);
+ }
+
+ return PageAction.applySingleSelectionAsEntityKey(pageAction);
+ }
+
+ private String getLocaleDisplayText(final UserInfo userInfo) {
+ return (userInfo.language != null)
+ ? userInfo.language.getDisplayLanguage(this.pageService.getI18nSupport().getUsersLanguageLocale())
+ : Constants.EMPTY_NOTE;
+ }
+
+ private static Function userInstitutionNameFunction(final ResourceService resourceService) {
+ final Function institutionNameFunction = resourceService.getInstitutionNameFunction();
+ return userInfo -> institutionNameFunction.apply(String.valueOf(userInfo.institutionId));
+ }
+
+}
diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/content/UserActivityLogs.java b/src/main/java/ch/ethz/seb/sebserver/gui/content/UserActivityLogs.java
index 5529e9c7..26d6db09 100644
--- a/src/main/java/ch/ethz/seb/sebserver/gui/content/UserActivityLogs.java
+++ b/src/main/java/ch/ethz/seb/sebserver/gui/content/UserActivityLogs.java
@@ -1,276 +1,279 @@
-/*
- * 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.content;
-
-import java.util.function.BooleanSupplier;
-import java.util.function.Function;
-
-import org.eclipse.swt.widgets.Composite;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.context.annotation.Lazy;
-import org.springframework.stereotype.Component;
-
-import ch.ethz.seb.sebserver.gbl.Constants;
-import ch.ethz.seb.sebserver.gbl.api.API;
-import ch.ethz.seb.sebserver.gbl.model.Domain;
-import ch.ethz.seb.sebserver.gbl.model.Entity;
-import ch.ethz.seb.sebserver.gbl.model.user.UserActivityLog;
-import ch.ethz.seb.sebserver.gbl.model.user.UserInfo;
-import ch.ethz.seb.sebserver.gbl.model.user.UserRole;
-import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
-import ch.ethz.seb.sebserver.gbl.util.Utils;
-import ch.ethz.seb.sebserver.gui.content.action.ActionDefinition;
-import ch.ethz.seb.sebserver.gui.form.FormBuilder;
-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.PageContext;
-import ch.ethz.seb.sebserver.gui.service.page.PageService;
-import ch.ethz.seb.sebserver.gui.service.page.PageService.PageActionBuilder;
-import ch.ethz.seb.sebserver.gui.service.page.TemplateComposer;
-import ch.ethz.seb.sebserver.gui.service.page.impl.ModalInputDialog;
-import ch.ethz.seb.sebserver.gui.service.page.impl.PageAction;
-import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestService;
-import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.logs.GetUserLogPage;
-import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.useraccount.GetUserAccount;
-import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.CurrentUser;
-import ch.ethz.seb.sebserver.gui.table.ColumnDefinition;
-import ch.ethz.seb.sebserver.gui.table.ColumnDefinition.TableFilterAttribute;
-import ch.ethz.seb.sebserver.gui.table.EntityTable;
-import ch.ethz.seb.sebserver.gui.table.TableFilter.CriteriaType;
-import ch.ethz.seb.sebserver.gui.widget.WidgetFactory;
-
-@Lazy
-@Component
-@GuiProfile
-public class UserActivityLogs implements TemplateComposer {
-
- private static final LocTextKey DETAILS_TITLE_TEXT_KEY =
- new LocTextKey("sebserver.userlogs.details.title");
- private static final LocTextKey TITLE_TEXT_KEY =
- new LocTextKey("sebserver.userlogs.list.title");
- private static final LocTextKey EMPTY_TEXT_KEY =
- new LocTextKey("sebserver.userlogs.list.empty");
- private static final LocTextKey INSTITUTION_TEXT_KEY =
- new LocTextKey("sebserver.userlogs.list.column.institution");
- private static final LocTextKey USER_TEXT_KEY =
- new LocTextKey("sebserver.userlogs.list.column.user");
- private static final LocTextKey DATE_TEXT_KEY =
- new LocTextKey("sebserver.userlogs.list.column.dateTime");
- private static final LocTextKey DETAILS_DATE_TEXT_KEY =
- new LocTextKey("sebserver.seblogs.details.dateTime");
- private static final LocTextKey ACTIVITY_TEXT_KEY =
- new LocTextKey("sebserver.userlogs.list.column.activityType");
- private static final LocTextKey ENTITY_TYPE_TEXT_KEY =
- new LocTextKey("sebserver.userlogs.list.column.entityType");
- private static final LocTextKey ENTITY_ID_TEXT_KEY =
- new LocTextKey("sebserver.userlogs.list.column.entityId");
- private static final LocTextKey MESSAGE_TEXT_KEY =
- new LocTextKey("sebserver.userlogs.list.column.message");
- private final static LocTextKey EMPTY_SELECTION_TEXT =
- new LocTextKey("sebserver.userlogs.info.pleaseSelect");
-
- private final TableFilterAttribute institutionFilter;
- private final TableFilterAttribute userNameFilter =
- new TableFilterAttribute(CriteriaType.TEXT, UserActivityLog.FILTER_ATTR_USER_NAME);
- private final TableFilterAttribute activityFilter;
- private final TableFilterAttribute entityFilter;
-
- private final PageService pageService;
- private final ResourceService resourceService;
- private final I18nSupport i18nSupport;
- private final WidgetFactory widgetFactory;
- private final int pageSize;
-
- public UserActivityLogs(
- final PageService pageService,
- @Value("${sebserver.gui.list.page.size:20}") final Integer pageSize) {
-
- this.pageService = pageService;
- this.resourceService = pageService.getResourceService();
- this.i18nSupport = this.resourceService.getI18nSupport();
- this.widgetFactory = pageService.getWidgetFactory();
- this.pageSize = pageSize;
-
- this.institutionFilter = new TableFilterAttribute(
- CriteriaType.SINGLE_SELECTION,
- Entity.FILTER_ATTR_INSTITUTION,
- this.resourceService::institutionResource);
-
- this.activityFilter = new TableFilterAttribute(
- CriteriaType.SINGLE_SELECTION,
- UserActivityLog.FILTER_ATTR_ACTIVITY_TYPES,
- this.resourceService::userActivityTypeResources);
-
- this.entityFilter = new TableFilterAttribute(
- CriteriaType.SINGLE_SELECTION,
- UserActivityLog.FILTER_ATTR_ENTITY_TYPES,
- this.resourceService::entityTypeResources);
- }
-
- @Override
- public void compose(final PageContext pageContext) {
- final CurrentUser currentUser = this.resourceService.getCurrentUser();
- final WidgetFactory widgetFactory = this.pageService.getWidgetFactory();
- final RestService restService = this.resourceService.getRestService();
- // content page layout with title
- final Composite content = widgetFactory.defaultPageLayout(
- pageContext.getParent(),
- TITLE_TEXT_KEY);
-
- final PageActionBuilder actionBuilder = this.pageService.pageActionBuilder(
- pageContext
- .clearEntityKeys()
- .clearAttributes());
-
- final BooleanSupplier isSebAdmin =
- () -> currentUser.get().hasRole(UserRole.SEB_SERVER_ADMIN);
-
- final Function institutionNameFunction =
- this.resourceService.getInstitutionNameFunction()
- .compose(log -> {
- try {
- final UserInfo user = restService.getBuilder(GetUserAccount.class)
- .withURIVariable(API.PARAM_MODEL_ID, log.getUserUuid())
- .call().getOrThrow();
- return String.valueOf(user.getInstitutionId());
- } catch (final Exception e) {
- return Constants.EMPTY_NOTE;
- }
- });
-
- // table
- final EntityTable table = this.pageService.entityTableBuilder(
- restService.getRestCall(GetUserLogPage.class))
- .withEmptyMessage(EMPTY_TEXT_KEY)
- .withPaging(this.pageSize)
-
- .withColumnIf(
- isSebAdmin,
- () -> new ColumnDefinition<>(
- UserActivityLog.FILTER_ATTR_INSTITUTION,
- INSTITUTION_TEXT_KEY,
- institutionNameFunction)
- .withFilter(this.institutionFilter))
-
- .withColumn(new ColumnDefinition<>(
- UserActivityLog.ATTR_USER_NAME,
- USER_TEXT_KEY,
- UserActivityLog::getUsername)
- .withFilter(this.userNameFilter))
-
- .withColumn(new ColumnDefinition(
- Domain.USER_ACTIVITY_LOG.ATTR_ACTIVITY_TYPE,
- ACTIVITY_TEXT_KEY,
- this.resourceService::getUserActivityTypeName)
- .withFilter(this.activityFilter)
- .sortable())
-
- .withColumn(new ColumnDefinition(
- Domain.USER_ACTIVITY_LOG.ATTR_ENTITY_ID,
- ENTITY_TYPE_TEXT_KEY,
- this.resourceService::getEntityTypeName)
- .withFilter(this.entityFilter)
- .sortable())
-
- .withColumn(new ColumnDefinition<>(
- Domain.USER_ACTIVITY_LOG.ATTR_TIMESTAMP,
- new LocTextKey(DATE_TEXT_KEY.name, this.i18nSupport.getUsersTimeZoneTitleSuffix()),
- this::getLogTime)
- .withFilter(new TableFilterAttribute(
- CriteriaType.DATE_RANGE,
- UserActivityLog.FILTER_ATTR_FROM_TO,
- Utils.toDateTimeUTC(Utils.getMillisecondsNow())
- .minusYears(1)
- .toString()))
- .sortable())
-
- .withDefaultAction(t -> actionBuilder
- .newAction(ActionDefinition.LOGS_USER_ACTIVITY_SHOW_DETAILS)
- .withExec(action -> this.showDetails(action, t.getSingleSelectedROWData()))
- .noEventPropagation()
- .create())
-
- .compose(pageContext.copyOf(content));
-
- actionBuilder
- .newAction(ActionDefinition.LOGS_USER_ACTIVITY_SHOW_DETAILS)
- .withSelect(
- table::getSelection,
- action -> this.showDetails(action, table.getSingleSelectedROWData()),
- EMPTY_SELECTION_TEXT)
- .noEventPropagation()
- .publishIf(table::hasAnyContent);
-
- }
-
- private final String getLogTime(final UserActivityLog log) {
- if (log == null || log.timestamp == null) {
- return Constants.EMPTY_NOTE;
- }
-
- return this.i18nSupport
- .formatDisplayDateTime(Utils.toDateTimeUTC(log.timestamp));
- }
-
- private PageAction showDetails(final PageAction action, final UserActivityLog userActivityLog) {
- action.getSingleSelection();
-
- final ModalInputDialog dialog = new ModalInputDialog<>(
- action.pageContext().getParent().getShell(),
- this.widgetFactory);
- dialog.setLargeDialogWidth();
- dialog.open(
- DETAILS_TITLE_TEXT_KEY,
- action.pageContext(),
- pc -> createDetailsForm(userActivityLog, pc));
-
- return action;
- }
-
- private void createDetailsForm(final UserActivityLog userActivityLog, final PageContext pc) {
-
- final Composite parent = pc.getParent();
- final Composite grid = this.widgetFactory.createPopupScrollComposite(parent);
-
- this.pageService.formBuilder(pc.copyOf(grid))
- .withDefaultSpanInput(6)
- .withEmptyCellSeparation(false)
- .readonly(true)
- .addField(FormBuilder.text(
- UserActivityLog.ATTR_USER_NAME,
- USER_TEXT_KEY,
- String.valueOf(userActivityLog.getUsername())))
- .addField(FormBuilder.text(
- Domain.USER_ACTIVITY_LOG.ATTR_ACTIVITY_TYPE,
- ACTIVITY_TEXT_KEY,
- this.resourceService.getUserActivityTypeName(userActivityLog)))
- .addField(FormBuilder.text(
- Domain.USER_ACTIVITY_LOG.ATTR_ENTITY_TYPE,
- ENTITY_TYPE_TEXT_KEY,
- this.resourceService.getEntityTypeName(userActivityLog)))
- .addField(FormBuilder.text(
- Domain.USER_ACTIVITY_LOG.ATTR_ENTITY_ID,
- ENTITY_ID_TEXT_KEY,
- userActivityLog.entityId))
- .addField(FormBuilder.text(
- Domain.USER_ACTIVITY_LOG.ATTR_TIMESTAMP,
- DETAILS_DATE_TEXT_KEY,
- this.widgetFactory.getI18nSupport()
- .formatDisplayDateTime(Utils.toDateTimeUTC(userActivityLog.timestamp)) + " " +
- this.i18nSupport.getUsersTimeZoneTitleSuffix()))
- .addField(FormBuilder.text(
- Domain.USER_ACTIVITY_LOG.ATTR_MESSAGE,
- MESSAGE_TEXT_KEY,
- String.valueOf(userActivityLog.message))
- .asArea())
- .build();
- }
-
-}
+/*
+ * 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.content;
+
+import java.util.function.BooleanSupplier;
+import java.util.function.Function;
+
+import org.eclipse.swt.widgets.Composite;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Lazy;
+import org.springframework.stereotype.Component;
+
+import ch.ethz.seb.sebserver.gbl.Constants;
+import ch.ethz.seb.sebserver.gbl.api.API;
+import ch.ethz.seb.sebserver.gbl.model.Domain;
+import ch.ethz.seb.sebserver.gbl.model.Entity;
+import ch.ethz.seb.sebserver.gbl.model.user.UserActivityLog;
+import ch.ethz.seb.sebserver.gbl.model.user.UserInfo;
+import ch.ethz.seb.sebserver.gbl.model.user.UserRole;
+import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
+import ch.ethz.seb.sebserver.gbl.util.Utils;
+import ch.ethz.seb.sebserver.gui.content.action.ActionDefinition;
+import ch.ethz.seb.sebserver.gui.form.FormBuilder;
+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.PageContext;
+import ch.ethz.seb.sebserver.gui.service.page.PageService;
+import ch.ethz.seb.sebserver.gui.service.page.PageService.PageActionBuilder;
+import ch.ethz.seb.sebserver.gui.service.page.TemplateComposer;
+import ch.ethz.seb.sebserver.gui.service.page.impl.ModalInputDialog;
+import ch.ethz.seb.sebserver.gui.service.page.impl.PageAction;
+import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestService;
+import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.logs.GetUserLogPage;
+import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.useraccount.GetUserAccount;
+import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.CurrentUser;
+import ch.ethz.seb.sebserver.gui.table.ColumnDefinition;
+import ch.ethz.seb.sebserver.gui.table.ColumnDefinition.TableFilterAttribute;
+import ch.ethz.seb.sebserver.gui.table.EntityTable;
+import ch.ethz.seb.sebserver.gui.table.TableFilter.CriteriaType;
+import ch.ethz.seb.sebserver.gui.widget.WidgetFactory;
+
+@Lazy
+@Component
+@GuiProfile
+public class UserActivityLogs implements TemplateComposer {
+
+ private static final LocTextKey DETAILS_TITLE_TEXT_KEY =
+ new LocTextKey("sebserver.userlogs.details.title");
+ private static final LocTextKey TITLE_TEXT_KEY =
+ new LocTextKey("sebserver.userlogs.list.title");
+ private static final LocTextKey EMPTY_TEXT_KEY =
+ new LocTextKey("sebserver.userlogs.list.empty");
+ private static final LocTextKey INSTITUTION_TEXT_KEY =
+ new LocTextKey("sebserver.userlogs.list.column.institution");
+ private static final LocTextKey USER_TEXT_KEY =
+ new LocTextKey("sebserver.userlogs.list.column.user");
+ private static final LocTextKey DATE_TEXT_KEY =
+ new LocTextKey("sebserver.userlogs.list.column.dateTime");
+ private static final LocTextKey DETAILS_DATE_TEXT_KEY =
+ new LocTextKey("sebserver.seblogs.details.dateTime");
+ private static final LocTextKey ACTIVITY_TEXT_KEY =
+ new LocTextKey("sebserver.userlogs.list.column.activityType");
+ private static final LocTextKey ENTITY_TYPE_TEXT_KEY =
+ new LocTextKey("sebserver.userlogs.list.column.entityType");
+ private static final LocTextKey ENTITY_ID_TEXT_KEY =
+ new LocTextKey("sebserver.userlogs.list.column.entityId");
+ private static final LocTextKey MESSAGE_TEXT_KEY =
+ new LocTextKey("sebserver.userlogs.list.column.message");
+ private final static LocTextKey EMPTY_SELECTION_TEXT =
+ new LocTextKey("sebserver.userlogs.info.pleaseSelect");
+
+ private final TableFilterAttribute institutionFilter;
+ private final TableFilterAttribute userNameFilter =
+ new TableFilterAttribute(CriteriaType.TEXT, UserActivityLog.FILTER_ATTR_USER_NAME);
+ private final TableFilterAttribute activityFilter;
+ private final TableFilterAttribute entityFilter;
+
+ private final PageService pageService;
+ private final ResourceService resourceService;
+ private final I18nSupport i18nSupport;
+ private final WidgetFactory widgetFactory;
+ private final int pageSize;
+
+ public UserActivityLogs(
+ final PageService pageService,
+ @Value("${sebserver.gui.list.page.size:20}") final Integer pageSize) {
+
+ this.pageService = pageService;
+ this.resourceService = pageService.getResourceService();
+ this.i18nSupport = this.resourceService.getI18nSupport();
+ this.widgetFactory = pageService.getWidgetFactory();
+ this.pageSize = pageSize;
+
+ this.institutionFilter = new TableFilterAttribute(
+ CriteriaType.SINGLE_SELECTION,
+ Entity.FILTER_ATTR_INSTITUTION,
+ this.resourceService::institutionResource);
+
+ this.activityFilter = new TableFilterAttribute(
+ CriteriaType.SINGLE_SELECTION,
+ UserActivityLog.FILTER_ATTR_ACTIVITY_TYPES,
+ this.resourceService::userActivityTypeResources);
+
+ this.entityFilter = new TableFilterAttribute(
+ CriteriaType.SINGLE_SELECTION,
+ UserActivityLog.FILTER_ATTR_ENTITY_TYPES,
+ this.resourceService::entityTypeResources);
+ }
+
+ @Override
+ public void compose(final PageContext pageContext) {
+ final CurrentUser currentUser = this.resourceService.getCurrentUser();
+ final WidgetFactory widgetFactory = this.pageService.getWidgetFactory();
+ final RestService restService = this.resourceService.getRestService();
+ // content page layout with title
+ final Composite content = widgetFactory.defaultPageLayout(
+ pageContext.getParent(),
+ TITLE_TEXT_KEY);
+
+ final PageActionBuilder actionBuilder = this.pageService.pageActionBuilder(
+ pageContext
+ .clearEntityKeys()
+ .clearAttributes());
+
+ final BooleanSupplier isSebAdmin =
+ () -> currentUser.get().hasRole(UserRole.SEB_SERVER_ADMIN);
+
+ final Function institutionNameFunction =
+ this.resourceService.getInstitutionNameFunction()
+ .compose(log -> {
+ try {
+ final UserInfo user = restService.getBuilder(GetUserAccount.class)
+ .withURIVariable(API.PARAM_MODEL_ID, log.getUserUuid())
+ .call().getOrThrow();
+ return String.valueOf(user.getInstitutionId());
+ } catch (final Exception e) {
+ return Constants.EMPTY_NOTE;
+ }
+ });
+
+ // table
+ final EntityTable table = this.pageService.entityTableBuilder(
+ restService.getRestCall(GetUserLogPage.class))
+ .withEmptyMessage(EMPTY_TEXT_KEY)
+ .withPaging(this.pageSize)
+
+ .withColumnIf(
+ isSebAdmin,
+ () -> new ColumnDefinition<>(
+ UserActivityLog.FILTER_ATTR_INSTITUTION,
+ INSTITUTION_TEXT_KEY,
+ institutionNameFunction)
+ .withFilter(this.institutionFilter))
+
+ .withColumn(new ColumnDefinition<>(
+ UserActivityLog.ATTR_USER_NAME,
+ USER_TEXT_KEY,
+ UserActivityLog::getUsername)
+ .withFilter(this.userNameFilter))
+
+ .withColumn(new ColumnDefinition(
+ Domain.USER_ACTIVITY_LOG.ATTR_ACTIVITY_TYPE,
+ ACTIVITY_TEXT_KEY,
+ this.resourceService::getUserActivityTypeName)
+ .withFilter(this.activityFilter)
+ .sortable())
+
+ .withColumn(new ColumnDefinition(
+ Domain.USER_ACTIVITY_LOG.ATTR_ENTITY_ID,
+ ENTITY_TYPE_TEXT_KEY,
+ this.resourceService::getEntityTypeName)
+ .withFilter(this.entityFilter)
+ .sortable())
+
+ .withColumn(new ColumnDefinition<>(
+ Domain.USER_ACTIVITY_LOG.ATTR_TIMESTAMP,
+ new LocTextKey(DATE_TEXT_KEY.name, this.i18nSupport.getUsersTimeZoneTitleSuffix()),
+ this::getLogTime)
+ .withFilter(new TableFilterAttribute(
+ CriteriaType.DATE_RANGE,
+ UserActivityLog.FILTER_ATTR_FROM_TO,
+ Utils.toDateTimeUTC(Utils.getMillisecondsNow())
+ .minusYears(1)
+ .toString()))
+ .sortable())
+
+ .withDefaultAction(t -> actionBuilder
+ .newAction(ActionDefinition.LOGS_USER_ACTIVITY_SHOW_DETAILS)
+ .withExec(action -> this.showDetails(action, t.getSingleSelectedROWData()))
+ .noEventPropagation()
+ .create())
+
+ .withSelectionListener(this.pageService.getSelectionPublisher(
+ pageContext,
+ ActionDefinition.LOGS_USER_ACTIVITY_SHOW_DETAILS))
+ .compose(pageContext.copyOf(content));
+
+ actionBuilder
+ .newAction(ActionDefinition.LOGS_USER_ACTIVITY_SHOW_DETAILS)
+ .withSelect(
+ table::getSelection,
+ action -> this.showDetails(action, table.getSingleSelectedROWData()),
+ EMPTY_SELECTION_TEXT)
+ .noEventPropagation()
+ .publishIf(table::hasAnyContent, false);
+
+ }
+
+ private String getLogTime(final UserActivityLog log) {
+ if (log == null || log.timestamp == null) {
+ return Constants.EMPTY_NOTE;
+ }
+
+ return this.i18nSupport
+ .formatDisplayDateTime(Utils.toDateTimeUTC(log.timestamp));
+ }
+
+ private PageAction showDetails(final PageAction action, final UserActivityLog userActivityLog) {
+ action.getSingleSelection();
+
+ final ModalInputDialog dialog = new ModalInputDialog<>(
+ action.pageContext().getParent().getShell(),
+ this.widgetFactory);
+ dialog.setLargeDialogWidth();
+ dialog.open(
+ DETAILS_TITLE_TEXT_KEY,
+ action.pageContext(),
+ pc -> createDetailsForm(userActivityLog, pc));
+
+ return action;
+ }
+
+ private void createDetailsForm(final UserActivityLog userActivityLog, final PageContext pc) {
+
+ final Composite parent = pc.getParent();
+ final Composite grid = this.widgetFactory.createPopupScrollComposite(parent);
+
+ this.pageService.formBuilder(pc.copyOf(grid))
+ .withDefaultSpanInput(6)
+ .withEmptyCellSeparation(false)
+ .readonly(true)
+ .addField(FormBuilder.text(
+ UserActivityLog.ATTR_USER_NAME,
+ USER_TEXT_KEY,
+ String.valueOf(userActivityLog.getUsername())))
+ .addField(FormBuilder.text(
+ Domain.USER_ACTIVITY_LOG.ATTR_ACTIVITY_TYPE,
+ ACTIVITY_TEXT_KEY,
+ this.resourceService.getUserActivityTypeName(userActivityLog)))
+ .addField(FormBuilder.text(
+ Domain.USER_ACTIVITY_LOG.ATTR_ENTITY_TYPE,
+ ENTITY_TYPE_TEXT_KEY,
+ this.resourceService.getEntityTypeName(userActivityLog)))
+ .addField(FormBuilder.text(
+ Domain.USER_ACTIVITY_LOG.ATTR_ENTITY_ID,
+ ENTITY_ID_TEXT_KEY,
+ userActivityLog.entityId))
+ .addField(FormBuilder.text(
+ Domain.USER_ACTIVITY_LOG.ATTR_TIMESTAMP,
+ DETAILS_DATE_TEXT_KEY,
+ this.widgetFactory.getI18nSupport()
+ .formatDisplayDateTime(Utils.toDateTimeUTC(userActivityLog.timestamp)) + " " +
+ this.i18nSupport.getUsersTimeZoneTitleSuffix()))
+ .addField(FormBuilder.text(
+ Domain.USER_ACTIVITY_LOG.ATTR_MESSAGE,
+ MESSAGE_TEXT_KEY,
+ String.valueOf(userActivityLog.message))
+ .asArea())
+ .build();
+ }
+
+}
diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/content/action/ActionDefinition.java b/src/main/java/ch/ethz/seb/sebserver/gui/content/action/ActionDefinition.java
index 5af58e3b..d625df8d 100644
--- a/src/main/java/ch/ethz/seb/sebserver/gui/content/action/ActionDefinition.java
+++ b/src/main/java/ch/ethz/seb/sebserver/gui/content/action/ActionDefinition.java
@@ -1,672 +1,690 @@
-/*
- * Copyright (c) 2018 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.content.action;
-
-import ch.ethz.seb.sebserver.gui.content.activity.PageStateDefinitionImpl;
-import ch.ethz.seb.sebserver.gui.service.i18n.LocTextKey;
-import ch.ethz.seb.sebserver.gui.service.page.PageStateDefinition;
-import ch.ethz.seb.sebserver.gui.widget.WidgetFactory.ImageIcon;
-
-/** Enumeration of static action data for each action within the SEB Server GUI */
-public enum ActionDefinition {
-
- INSTITUTION_VIEW_LIST(
- new LocTextKey("sebserver.institution.action.list"),
- PageStateDefinitionImpl.INSTITUTION_LIST),
- INSTITUTION_VIEW_FORM(
- new LocTextKey("sebserver.institution.action.form"),
- PageStateDefinitionImpl.INSTITUTION_VIEW),
- INSTITUTION_NEW(
- new LocTextKey("sebserver.institution.action.new"),
- ImageIcon.INSTITUTION,
- PageStateDefinitionImpl.INSTITUTION_EDIT,
- ActionCategory.FORM),
- INSTITUTION_VIEW_FROM_LIST(
- new LocTextKey("sebserver.institution.action.list.view"),
- ImageIcon.SHOW,
- PageStateDefinitionImpl.INSTITUTION_VIEW,
- ActionCategory.INSTITUTION_LIST),
- INSTITUTION_MODIFY_FROM_LIST(
- new LocTextKey("sebserver.institution.action.list.modify"),
- ImageIcon.EDIT,
- PageStateDefinitionImpl.INSTITUTION_EDIT,
- ActionCategory.INSTITUTION_LIST),
-
- INSTITUTION_MODIFY(
- new LocTextKey("sebserver.institution.action.modify"),
- ImageIcon.EDIT,
- PageStateDefinitionImpl.INSTITUTION_EDIT,
- ActionCategory.FORM),
- INSTITUTION_CANCEL_MODIFY(
- new LocTextKey("sebserver.overall.action.modify.cancel"),
- ImageIcon.CANCEL,
- PageStateDefinitionImpl.INSTITUTION_VIEW,
- ActionCategory.FORM),
- INSTITUTION_SAVE(
- new LocTextKey("sebserver.institution.action.save"),
- ImageIcon.SAVE,
- PageStateDefinitionImpl.INSTITUTION_VIEW,
- ActionCategory.FORM),
- INSTITUTION_SAVE_AND_ACTIVATE(
- new LocTextKey("sebserver.form.action.save.activate"),
- ImageIcon.ACTIVE,
- PageStateDefinitionImpl.INSTITUTION_VIEW,
- ActionCategory.FORM),
- INSTITUTION_ACTIVATE(
- new LocTextKey("sebserver.institution.action.activate"),
- ImageIcon.TOGGLE_OFF,
- PageStateDefinitionImpl.INSTITUTION_VIEW,
- ActionCategory.FORM),
- INSTITUTION_DEACTIVATE(
- new LocTextKey("sebserver.institution.action.deactivate"),
- ImageIcon.TOGGLE_ON,
- PageStateDefinitionImpl.INSTITUTION_VIEW,
- ActionCategory.FORM),
- INSTITUTION_TOGGLE_ACTIVITY(
- new LocTextKey("sebserver.overall.action.toggle-activity"),
- ImageIcon.SWITCH,
- PageStateDefinitionImpl.INSTITUTION_LIST,
- ActionCategory.INSTITUTION_LIST),
-
- USER_ACCOUNT_VIEW_LIST(
- new LocTextKey("sebserver.useraccount.action.list"),
- PageStateDefinitionImpl.USER_ACCOUNT_LIST),
- USER_ACCOUNT_VIEW_FORM(
- new LocTextKey("sebserver.useraccount.action.form"),
- PageStateDefinitionImpl.USER_ACCOUNT_VIEW),
- USER_ACCOUNT_NEW(
- new LocTextKey("sebserver.useraccount.action.new"),
- ImageIcon.USER,
- PageStateDefinitionImpl.USER_ACCOUNT_EDIT),
- USER_ACCOUNT_VIEW_FROM_LIST(
- new LocTextKey("sebserver.useraccount.action.view"),
- ImageIcon.SHOW,
- PageStateDefinitionImpl.USER_ACCOUNT_VIEW,
- ActionCategory.USER_ACCOUNT_LIST),
- USER_ACCOUNT_MODIFY_FROM_LIST(
- new LocTextKey("sebserver.useraccount.action.list.modify"),
- ImageIcon.EDIT,
- PageStateDefinitionImpl.USER_ACCOUNT_EDIT,
- ActionCategory.USER_ACCOUNT_LIST),
- USER_ACCOUNT_MODIFY(
- new LocTextKey("sebserver.useraccount.action.modify"),
- ImageIcon.EDIT,
- PageStateDefinitionImpl.USER_ACCOUNT_EDIT,
- ActionCategory.FORM),
- USER_ACCOUNT_CANCEL_MODIFY(
- new LocTextKey("sebserver.overall.action.modify.cancel"),
- ImageIcon.CANCEL,
- PageStateDefinitionImpl.USER_ACCOUNT_VIEW,
- ActionCategory.FORM),
- USER_ACCOUNT_SAVE(
- new LocTextKey("sebserver.useraccount.action.save"),
- ImageIcon.SAVE,
- PageStateDefinitionImpl.USER_ACCOUNT_VIEW,
- ActionCategory.FORM),
- USER_ACCOUNT_ACTIVATE(
- new LocTextKey("sebserver.useraccount.action.activate"),
- ImageIcon.TOGGLE_OFF,
- PageStateDefinitionImpl.USER_ACCOUNT_VIEW,
- ActionCategory.FORM),
- USER_ACCOUNT_DEACTIVATE(
- new LocTextKey("sebserver.useraccount.action.deactivate"),
- ImageIcon.TOGGLE_ON,
- PageStateDefinitionImpl.USER_ACCOUNT_VIEW,
- ActionCategory.FORM),
- USER_ACCOUNT_CHANGE_PASSOWRD(
- new LocTextKey("sebserver.useraccount.action.change.password"),
- ImageIcon.SECURE,
- PageStateDefinitionImpl.USER_ACCOUNT_PASSWORD_CHANGE,
- ActionCategory.FORM),
- USER_ACCOUNT_CHANGE_PASSOWRD_SAVE(
- new LocTextKey("sebserver.useraccount.action.change.password.save"),
- ImageIcon.SAVE,
- PageStateDefinitionImpl.USER_ACCOUNT_VIEW,
- ActionCategory.FORM),
-
- LMS_SETUP_VIEW_LIST(
- new LocTextKey("sebserver.lmssetup.action.list"),
- PageStateDefinitionImpl.LMS_SETUP_LIST),
- LMS_SETUP_NEW(
- new LocTextKey("sebserver.lmssetup.action.new"),
- ImageIcon.LMS_SETUP,
- PageStateDefinitionImpl.LMS_SETUP_EDIT),
- LMS_SETUP_VIEW_FROM_LIST(
- new LocTextKey("sebserver.lmssetup.action.list.view"),
- ImageIcon.SHOW,
- PageStateDefinitionImpl.LMS_SETUP_VIEW,
- ActionCategory.LMS_SETUP_LIST),
- LMS_SETUP_MODIFY_FROM_LIST(
- new LocTextKey("sebserver.lmssetup.action.list.modify"),
- ImageIcon.EDIT,
- PageStateDefinitionImpl.LMS_SETUP_EDIT,
- ActionCategory.LMS_SETUP_LIST),
- LMS_SETUP_MODIFY(
- new LocTextKey("sebserver.lmssetup.action.modify"),
- ImageIcon.EDIT,
- PageStateDefinitionImpl.LMS_SETUP_EDIT,
- ActionCategory.FORM),
- LMS_SETUP_SAVE_AND_TEST(
- new LocTextKey("sebserver.lmssetup.action.savetest"),
- ImageIcon.TEST,
- PageStateDefinitionImpl.LMS_SETUP_VIEW,
- ActionCategory.FORM),
- LMS_SETUP_TEST_AND_SAVE(
- new LocTextKey("sebserver.lmssetup.action.testsave"),
- ImageIcon.TEST,
- PageStateDefinitionImpl.LMS_SETUP_VIEW,
- ActionCategory.FORM),
- LMS_SETUP_CANCEL_MODIFY(
- new LocTextKey("sebserver.overall.action.modify.cancel"),
- ImageIcon.CANCEL,
- PageStateDefinitionImpl.LMS_SETUP_VIEW,
- ActionCategory.FORM),
- LMS_SETUP_SAVE(
- new LocTextKey("sebserver.lmssetup.action.save"),
- ImageIcon.SAVE,
- PageStateDefinitionImpl.LMS_SETUP_VIEW,
- ActionCategory.FORM),
- LMS_SETUP_ACTIVATE(
- new LocTextKey("sebserver.lmssetup.action.activate"),
- ImageIcon.TOGGLE_OFF,
- PageStateDefinitionImpl.LMS_SETUP_VIEW,
- ActionCategory.FORM),
- LMS_SETUP_DEACTIVATE(
- new LocTextKey("sebserver.lmssetup.action.deactivate"),
- ImageIcon.TOGGLE_ON,
- PageStateDefinitionImpl.LMS_SETUP_VIEW,
- ActionCategory.FORM),
-
- QUIZ_DISCOVERY_VIEW_LIST(
- new LocTextKey("sebserver.quizdiscovery.action.list"),
- PageStateDefinitionImpl.QUIZ_LIST),
- QUIZ_DISCOVERY_SHOW_DETAILS(
- new LocTextKey("sebserver.quizdiscovery.action.details"),
- ImageIcon.SHOW,
- ActionCategory.QUIZ_LIST),
- QUIZ_DISCOVERY_EXAM_IMPORT(
- new LocTextKey("sebserver.quizdiscovery.action.import"),
- ImageIcon.IMPORT,
- PageStateDefinitionImpl.EXAM_EDIT,
- ActionCategory.QUIZ_LIST),
-
- EXAM_VIEW_LIST(
- new LocTextKey("sebserver.exam.action.list"),
- PageStateDefinitionImpl.EXAM_LIST),
- EXAM_IMPORT(
- new LocTextKey("sebserver.exam.action.import"),
- ImageIcon.IMPORT,
- PageStateDefinitionImpl.QUIZ_LIST),
- EXAM_VIEW_FROM_LIST(
- new LocTextKey("sebserver.exam.action.list.view"),
- ImageIcon.SHOW,
- PageStateDefinitionImpl.EXAM_VIEW,
- ActionCategory.EXAM_LIST),
- EXAM_MODIFY_FROM_LIST(
- new LocTextKey("sebserver.exam.action.list.modify"),
- ImageIcon.EDIT,
- PageStateDefinitionImpl.EXAM_EDIT,
- ActionCategory.EXAM_LIST),
- EXAM_MODIFY(
- new LocTextKey("sebserver.exam.action.modify"),
- ImageIcon.EDIT,
- PageStateDefinitionImpl.EXAM_EDIT,
- ActionCategory.FORM),
- EXAM_CANCEL_MODIFY(
- new LocTextKey("sebserver.overall.action.modify.cancel"),
- ImageIcon.CANCEL,
- PageStateDefinitionImpl.EXAM_VIEW,
- ActionCategory.FORM),
- EXAM_SAVE(
- new LocTextKey("sebserver.exam.action.save"),
- ImageIcon.SAVE,
- PageStateDefinitionImpl.EXAM_VIEW,
- ActionCategory.FORM),
- EXAM_ACTIVATE(
- new LocTextKey("sebserver.exam.action.activate"),
- ImageIcon.TOGGLE_OFF,
- PageStateDefinitionImpl.EXAM_VIEW,
- ActionCategory.FORM),
- EXAM_DEACTIVATE(
- new LocTextKey("sebserver.exam.action.deactivate"),
- ImageIcon.TOGGLE_ON,
- PageStateDefinitionImpl.EXAM_VIEW,
- ActionCategory.FORM),
-
- EXAM_MODIFY_SEB_RESTRICTION_DETAILS(
- new LocTextKey("sebserver.exam.action.sebrestriction.details"),
- ImageIcon.RESTRICTION,
- PageStateDefinitionImpl.EXAM_VIEW,
- ActionCategory.FORM),
- EXAM_ENABLE_SEB_RESTRICTION(
- new LocTextKey("sebserver.exam.action.sebrestriction.enable"),
- ImageIcon.UNLOCK,
- PageStateDefinitionImpl.EXAM_VIEW,
- ActionCategory.FORM),
- EXAM_DISABLE_SEB_RESTRICTION(
- new LocTextKey("sebserver.exam.action.sebrestriction.disable"),
- ImageIcon.LOCK,
- PageStateDefinitionImpl.EXAM_VIEW,
- ActionCategory.FORM),
-
- EXAM_CONFIGURATION_NEW(
- new LocTextKey("sebserver.exam.configuration.action.list.new"),
- ImageIcon.NEW,
- PageStateDefinitionImpl.EXAM_VIEW,
- ActionCategory.EXAM_CONFIG_MAPPING_LIST),
- EXAM_CONFIGURATION_MODIFY_FROM_LIST(
- new LocTextKey("sebserver.exam.configuration.action.list.modify"),
- ImageIcon.EDIT,
- PageStateDefinitionImpl.EXAM_VIEW,
- ActionCategory.EXAM_CONFIG_MAPPING_LIST),
- EXAM_CONFIGURATION_EXAM_CONFIG_VIEW_PROP(
- new LocTextKey("sebserver.exam.configuration.action.list.view"),
- ImageIcon.SHOW,
- PageStateDefinitionImpl.SEB_EXAM_CONFIG_PROP_VIEW,
- ActionCategory.EXAM_CONFIG_MAPPING_LIST),
- EXAM_CONFIGURATION_DELETE_FROM_LIST(
- new LocTextKey("sebserver.exam.configuration.action.list.delete"),
- ImageIcon.DELETE,
- PageStateDefinitionImpl.EXAM_VIEW,
- ActionCategory.EXAM_CONFIG_MAPPING_LIST),
- EXAM_CONFIGURATION_EXPORT(
- new LocTextKey("sebserver.exam.configuration.action.export-config"),
- ImageIcon.EXPORT,
- PageStateDefinitionImpl.EXAM_VIEW,
- ActionCategory.EXAM_CONFIG_MAPPING_LIST),
- EXAM_CONFIGURATION_GET_CONFIG_KEY(
- new LocTextKey("sebserver.exam.configuration.action.get-config-key"),
- ImageIcon.SECURE,
- ActionCategory.EXAM_CONFIG_MAPPING_LIST),
- EXAM_CONFIGURATION_SAVE(
- new LocTextKey("sebserver.exam.configuration.action.save"),
- ImageIcon.SAVE,
- PageStateDefinitionImpl.EXAM_VIEW,
- ActionCategory.FORM),
- EXAM_CONFIGURATION_CANCEL_MODIFY(
- new LocTextKey("sebserver.overall.action.modify.cancel"),
- ImageIcon.CANCEL,
- PageStateDefinitionImpl.EXAM_VIEW,
- ActionCategory.FORM),
-
- EXAM_INDICATOR_NEW(
- new LocTextKey("sebserver.exam.indicator.action.list.new"),
- ImageIcon.INDICATOR,
- PageStateDefinitionImpl.INDICATOR_EDIT,
- ActionCategory.INDICATOR_LIST),
- EXAM_INDICATOR_MODIFY_FROM_LIST(
- new LocTextKey("sebserver.exam.indicator.action.list.modify"),
- ImageIcon.EDIT,
- PageStateDefinitionImpl.INDICATOR_EDIT,
- ActionCategory.INDICATOR_LIST),
- EXAM_INDICATOR_DELETE_FROM_LIST(
- new LocTextKey("sebserver.exam.indicator.action.list.delete"),
- ImageIcon.DELETE,
- PageStateDefinitionImpl.EXAM_VIEW,
- ActionCategory.INDICATOR_LIST),
- EXAM_INDICATOR_SAVE(
- new LocTextKey("sebserver.exam.indicator.action.save"),
- ImageIcon.SAVE,
- PageStateDefinitionImpl.EXAM_VIEW,
- ActionCategory.FORM),
- EXAM_INDICATOR_CANCEL_MODIFY(
- new LocTextKey("sebserver.overall.action.modify.cancel"),
- ImageIcon.CANCEL,
- PageStateDefinitionImpl.EXAM_VIEW,
- ActionCategory.FORM),
-
- SEB_CLIENT_CONFIG_LIST(
- new LocTextKey("sebserver.clientconfig.action.list"),
- PageStateDefinitionImpl.SEB_CLIENT_CONFIG_LIST),
- SEB_CLIENT_CONFIG_NEW(
- new LocTextKey("sebserver.clientconfig.action.list.new"),
- ImageIcon.NEW,
- PageStateDefinitionImpl.SEB_CLIENT_CONFIG_EDIT),
- SEB_CLIENT_CONFIG_VIEW_FROM_LIST(
- new LocTextKey("sebserver.clientconfig.action.list.view"),
- ImageIcon.SHOW,
- PageStateDefinitionImpl.SEB_CLIENT_CONFIG_VIEW,
- ActionCategory.SEB_CLIENT_CONFIG_LIST),
- SEB_CLIENT_CONFIG_MODIFY_FROM_LIST(
- new LocTextKey("sebserver.clientconfig.action.list.modify"),
- ImageIcon.EDIT,
- PageStateDefinitionImpl.SEB_CLIENT_CONFIG_EDIT,
- ActionCategory.SEB_CLIENT_CONFIG_LIST),
- SEB_CLIENT_CONFIG_MODIFY(
- new LocTextKey("sebserver.clientconfig.action.modify"),
- ImageIcon.EDIT,
- PageStateDefinitionImpl.SEB_CLIENT_CONFIG_EDIT,
- ActionCategory.FORM),
- SEB_CLIENT_CONFIG_CANCEL_MODIFY(
- new LocTextKey("sebserver.overall.action.modify.cancel"),
- ImageIcon.CANCEL,
- PageStateDefinitionImpl.SEB_CLIENT_CONFIG_VIEW,
- ActionCategory.FORM),
- SEB_CLIENT_CONFIG_SAVE(
- new LocTextKey("sebserver.clientconfig.action.save"),
- ImageIcon.SAVE,
- PageStateDefinitionImpl.SEB_CLIENT_CONFIG_VIEW,
- ActionCategory.FORM),
- SEB_CLIENT_CONFIG_ACTIVATE(
- new LocTextKey("sebserver.clientconfig.action.activate"),
- ImageIcon.TOGGLE_OFF,
- PageStateDefinitionImpl.SEB_CLIENT_CONFIG_VIEW,
- ActionCategory.FORM),
- SEB_CLIENT_CONFIG_DEACTIVATE(
- new LocTextKey("sebserver.clientconfig.action.deactivate"),
- ImageIcon.TOGGLE_ON,
- PageStateDefinitionImpl.SEB_CLIENT_CONFIG_VIEW,
- ActionCategory.FORM),
- SEB_CLIENT_CONFIG_EXPORT(
- new LocTextKey("sebserver.clientconfig.action.export"),
- ImageIcon.EXPORT,
- PageStateDefinitionImpl.SEB_CLIENT_CONFIG_VIEW,
- ActionCategory.FORM),
-
- SEB_EXAM_CONFIG_LIST(
- new LocTextKey("sebserver.examconfig.action.list"),
- PageStateDefinitionImpl.SEB_EXAM_CONFIG_LIST),
- SEB_EXAM_CONFIG_NEW(
- new LocTextKey("sebserver.examconfig.action.list.new"),
- ImageIcon.NEW,
- PageStateDefinitionImpl.SEB_EXAM_CONFIG_PROP_EDIT),
- SEB_EXAM_CONFIG_VIEW_PROP_FROM_LIST(
- new LocTextKey("sebserver.examconfig.action.list.view"),
- ImageIcon.SHOW,
- PageStateDefinitionImpl.SEB_EXAM_CONFIG_PROP_VIEW,
- ActionCategory.SEB_EXAM_CONFIG_LIST),
- SEB_EXAM_CONFIG_VIEW_PROP(
- new LocTextKey("sebserver.examconfig.action.view.properties"),
- ImageIcon.SHOW,
- PageStateDefinitionImpl.SEB_EXAM_CONFIG_PROP_VIEW,
- ActionCategory.FORM),
- SEB_EXAM_CONFIG_IMPORT_TO_NEW_CONFIG(
- new LocTextKey("sebserver.examconfig.action.import-config"),
- ImageIcon.IMPORT,
- PageStateDefinitionImpl.SEB_EXAM_CONFIG_LIST,
- ActionCategory.VARIA),
-
- SEB_EXAM_CONFIG_MODIFY_PROP_FROM_LIST(
- new LocTextKey("sebserver.examconfig.action.list.modify.properties"),
- ImageIcon.EDIT,
- PageStateDefinitionImpl.SEB_EXAM_CONFIG_PROP_EDIT,
- ActionCategory.SEB_EXAM_CONFIG_LIST),
- SEB_EXAM_CONFIG_PROP_MODIFY(
- new LocTextKey("sebserver.examconfig.action.modify.properties"),
- ImageIcon.EDIT,
- PageStateDefinitionImpl.SEB_EXAM_CONFIG_PROP_EDIT,
- ActionCategory.FORM),
- SEB_EXAM_CONFIG_MODIFY(
- new LocTextKey("sebserver.examconfig.action.modify"),
- ImageIcon.EDIT_SETTINGS,
- PageStateDefinitionImpl.SEB_EXAM_CONFIG_EDIT,
- ActionCategory.FORM),
- SEB_EXAM_CONFIG_VIEW(
- new LocTextKey("sebserver.examconfig.action.view"),
- ImageIcon.EDIT_SETTINGS,
- PageStateDefinitionImpl.SEB_EXAM_CONFIG_VIEW,
- ActionCategory.FORM),
- SEB_EXAM_CONFIG_PROP_CANCEL_MODIFY(
- new LocTextKey("sebserver.overall.action.modify.cancel"),
- ImageIcon.CANCEL,
- PageStateDefinitionImpl.SEB_EXAM_CONFIG_PROP_VIEW,
- ActionCategory.FORM),
- SEB_EXAM_CONFIG_PROP_SAVE(
- new LocTextKey("sebserver.examconfig.action.save"),
- ImageIcon.SAVE,
- PageStateDefinitionImpl.SEB_EXAM_CONFIG_PROP_VIEW,
- ActionCategory.FORM),
- SEB_EXAM_CONFIG_EXPORT_PLAIN_XML(
- new LocTextKey("sebserver.examconfig.action.export.plainxml"),
- ImageIcon.EXPORT,
- ActionCategory.FORM),
- SEB_EXAM_CONFIG_GET_CONFIG_KEY(
- new LocTextKey("sebserver.examconfig.action.get-config-key"),
- ImageIcon.SECURE,
- ActionCategory.FORM),
- SEB_EXAM_CONFIG_IMPORT_TO_EXISTING_CONFIG(
- new LocTextKey("sebserver.examconfig.action.import-config"),
- ImageIcon.IMPORT,
- ActionCategory.FORM),
-
- SEB_EXAM_CONFIG_COPY_CONFIG(
- new LocTextKey("sebserver.examconfig.action.copy"),
- ImageIcon.COPY,
- ActionCategory.FORM),
- SEB_EXAM_CONFIG_COPY_CONFIG_AS_TEMPALTE(
- new LocTextKey("sebserver.examconfig.action.copy-as-template"),
- ImageIcon.TEMPLATE,
- ActionCategory.FORM),
-
- SEB_EXAM_CONFIG_MODIFY_FROM_LIST(
- new LocTextKey("sebserver.examconfig.action.list.modify"),
- ImageIcon.EDIT_SETTINGS,
- PageStateDefinitionImpl.SEB_EXAM_CONFIG_EDIT,
- ActionCategory.SEB_EXAM_CONFIG_LIST),
-
- SEB_EXAM_CONFIG_SAVE_TO_HISTORY(
- new LocTextKey("sebserver.examconfig.action.saveToHistory"),
- ImageIcon.SAVE,
- PageStateDefinitionImpl.SEB_EXAM_CONFIG_EDIT,
- ActionCategory.FORM),
- SEB_EXAM_CONFIG_UNDO(
- new LocTextKey("sebserver.examconfig.action.undo"),
- ImageIcon.UNDO,
- PageStateDefinitionImpl.SEB_EXAM_CONFIG_EDIT,
- ActionCategory.FORM),
-
- SEB_EXAM_CONFIG_TEMPLATE_LIST(
- new LocTextKey("sebserver.configtemplate.action.list"),
- PageStateDefinitionImpl.SEB_EXAM_CONFIG_TEMPLATE_LIST),
- SEB_EXAM_CONFIG_TEMPLATE_NEW(
- new LocTextKey("sebserver.configtemplate.action.list.new"),
- ImageIcon.TEMPLATE,
- PageStateDefinitionImpl.SEB_EXAM_CONFIG_TEMPLATE_EDIT,
- ActionCategory.VARIA),
- SEB_EXAM_CONFIG_TEMPLATE_VIEW_FROM_LIST(
- new LocTextKey("sebserver.configtemplate.action.list.view"),
- ImageIcon.SHOW,
- PageStateDefinitionImpl.SEB_EXAM_CONFIG_TEMPLATE_VIEW,
- ActionCategory.SEB_CONFIG_TEMPLATE_LIST),
- SEB_EXAM_CONFIG_TEMPLATE_VIEW(
- new LocTextKey("sebserver.configtemplate.action.view"),
- ImageIcon.SHOW,
- PageStateDefinitionImpl.SEB_EXAM_CONFIG_TEMPLATE_VIEW,
- ActionCategory.FORM),
- SEB_EXAM_CONFIG_TEMPLATE_MODIFY_FROM_LIST(
- new LocTextKey("sebserver.configtemplate.action.list.modify"),
- ImageIcon.EDIT,
- PageStateDefinitionImpl.SEB_EXAM_CONFIG_TEMPLATE_EDIT,
- ActionCategory.SEB_CONFIG_TEMPLATE_LIST),
- SEB_EXAM_CONFIG_TEMPLATE_MODIFY(
- new LocTextKey("sebserver.configtemplate.action.modify"),
- ImageIcon.EDIT,
- PageStateDefinitionImpl.SEB_EXAM_CONFIG_TEMPLATE_EDIT,
- ActionCategory.FORM),
- SEB_EXAM_CONFIG_TEMPLATE_CREATE_CONFIG(
- new LocTextKey("sebserver.configtemplate.action.create-config"),
- ImageIcon.NEW,
- PageStateDefinitionImpl.SEB_EXAM_CONFIG_TEMPLATE_VIEW,
- ActionCategory.FORM),
- SEB_EXAM_CONFIG_TEMPLATE_CANCEL_MODIFY(
- new LocTextKey("sebserver.overall.action.modify.cancel"),
- ImageIcon.CANCEL,
- PageStateDefinitionImpl.SEB_EXAM_CONFIG_TEMPLATE_VIEW,
- ActionCategory.FORM),
- SEB_EXAM_CONFIG_TEMPLATE_SAVE(
- new LocTextKey("sebserver.configtemplate.action.save"),
- ImageIcon.SAVE,
- PageStateDefinitionImpl.SEB_EXAM_CONFIG_TEMPLATE_VIEW,
- ActionCategory.FORM),
-
- SEB_EXAM_CONFIG_TEMPLATE_ATTR_EDIT(
- new LocTextKey("sebserver.configtemplate.attr.list.actions.modify"),
- ImageIcon.EDIT,
- PageStateDefinitionImpl.SEB_EXAM_CONFIG_TEMPLATE_ATTRIBUTE_EDIT,
- ActionCategory.SEB_CONFIG_TEMPLATE_ATTRIBUTE_LIST),
- SEB_EXAM_CONFIG_TEMPLATE_ATTR_SET_DEFAULT(
- new LocTextKey("sebserver.configtemplate.attr.list.actions.setdefault"),
- ImageIcon.SAVE,
- PageStateDefinitionImpl.SEB_EXAM_CONFIG_TEMPLATE_VIEW,
- ActionCategory.SEB_CONFIG_TEMPLATE_ATTRIBUTE_LIST),
- SEB_EXAM_CONFIG_TEMPLATE_ATTR_LIST_REMOVE_VIEW(
- new LocTextKey("sebserver.configtemplate.attr.list.actions.removeview"),
- ImageIcon.REMOVE,
- PageStateDefinitionImpl.SEB_EXAM_CONFIG_TEMPLATE_VIEW,
- ActionCategory.SEB_CONFIG_TEMPLATE_ATTRIBUTE_LIST),
- SEB_EXAM_CONFIG_TEMPLATE_ATTR_LIST_ATTACH_DEFAULT_VIEW(
- new LocTextKey("sebserver.configtemplate.attr.list.actions.attach-default-view"),
- ImageIcon.ADD,
- PageStateDefinitionImpl.SEB_EXAM_CONFIG_TEMPLATE_VIEW,
- ActionCategory.SEB_CONFIG_TEMPLATE_ATTRIBUTE_LIST),
- SEB_EXAM_CONFIG_TEMPLATE_ATTR_REMOVE_VIEW(
- new LocTextKey("sebserver.configtemplate.attr.list.actions.removeview"),
- ImageIcon.REMOVE,
- PageStateDefinitionImpl.SEB_EXAM_CONFIG_TEMPLATE_ATTRIBUTE_EDIT,
- ActionCategory.FORM),
- SEB_EXAM_CONFIG_TEMPLATE_ATTR_ATTACH_DEFAULT_VIEW(
- new LocTextKey("sebserver.configtemplate.attr.list.actions.attach-default-view"),
- ImageIcon.ADD,
- PageStateDefinitionImpl.SEB_EXAM_CONFIG_TEMPLATE_ATTRIBUTE_EDIT,
- ActionCategory.FORM),
-
- SEB_EXAM_CONFIG_TEMPLATE_ATTR_FORM_SET_DEFAULT(
- new LocTextKey("sebserver.configtemplate.attr.action.setdefault"),
- ImageIcon.UNDO,
- PageStateDefinitionImpl.SEB_EXAM_CONFIG_TEMPLATE_ATTRIBUTE_EDIT,
- ActionCategory.FORM),
- SEB_EXAM_CONFIG_TEMPLATE_ATTR_FORM_EDIT_TEMPLATE(
- new LocTextKey("sebserver.configtemplate.attr.action.template"),
- ImageIcon.SHOW,
- PageStateDefinitionImpl.SEB_EXAM_CONFIG_TEMPLATE_VIEW,
- ActionCategory.FORM),
-
- RUNNING_EXAM_VIEW_LIST(
- new LocTextKey("sebserver.monitoring.action.list"),
- PageStateDefinitionImpl.MONITORING_RUNNING_EXAM_LIST),
- MONITOR_EXAM_FROM_LIST(
- new LocTextKey("sebserver.monitoring.exam.action.list.view"),
- ImageIcon.SHOW,
- PageStateDefinitionImpl.MONITORING_RUNNING_EXAM,
- ActionCategory.RUNNING_EXAM_LIST),
- MONITOR_EXAM_CLIENT_CONNECTION(
- new LocTextKey("sebserver.monitoring.exam.connection.action.view"),
- ImageIcon.SHOW,
- PageStateDefinitionImpl.MONITORING_CLIENT_CONNECTION,
- ActionCategory.CLIENT_EVENT_LIST),
- MONITOR_EXAM_CLIENT_CONNECTION_QUIT(
- new LocTextKey("sebserver.monitoring.exam.connection.action.instruction.quit"),
- ImageIcon.SEND_QUIT,
- PageStateDefinitionImpl.MONITORING_CLIENT_CONNECTION,
- ActionCategory.FORM),
- MONITOR_EXAM_QUIT_SELECTED(
- new LocTextKey("sebserver.monitoring.exam.connection.action.instruction.quit"),
- ImageIcon.SEND_QUIT,
- PageStateDefinitionImpl.MONITORING_RUNNING_EXAM,
- ActionCategory.CLIENT_EVENT_LIST),
- MONITOR_EXAM_QUIT_ALL(
- new LocTextKey("sebserver.monitoring.exam.connection.action.instruction.quit.all"),
- ImageIcon.SEND_QUIT,
- PageStateDefinitionImpl.MONITORING_RUNNING_EXAM,
- ActionCategory.FORM),
- MONITOR_EXAM_FROM_DETAILS(
- new LocTextKey("sebserver.monitoring.exam.action.detail.view"),
- ImageIcon.SHOW,
- PageStateDefinitionImpl.MONITORING_RUNNING_EXAM,
- ActionCategory.FORM),
-
- MONITOR_EXAM_DISABLE_SELECTED_CONNECTION(
- new LocTextKey("sebserver.monitoring.exam.connection.action.disable"),
- ImageIcon.DISABLE,
- PageStateDefinitionImpl.MONITORING_RUNNING_EXAM,
- ActionCategory.CLIENT_EVENT_LIST),
-
- MONITOR_EXAM_HIDE_REQUESTED_CONNECTION(
- new LocTextKey("sebserver.monitoring.exam.connection.action.hide.requested"),
- ImageIcon.TOGGLE_OFF,
- PageStateDefinitionImpl.MONITORING_RUNNING_EXAM,
- ActionCategory.FILTER),
- MONITOR_EXAM_SHOW_REQUESTED_CONNECTION(
- new LocTextKey("sebserver.monitoring.exam.connection.action.show.requested"),
- ImageIcon.TOGGLE_ON,
- PageStateDefinitionImpl.MONITORING_RUNNING_EXAM,
- ActionCategory.FILTER),
- MONITOR_EXAM_HIDE_CLOSED_CONNECTION(
- new LocTextKey("sebserver.monitoring.exam.connection.action.hide.closed"),
- ImageIcon.TOGGLE_OFF,
- PageStateDefinitionImpl.MONITORING_RUNNING_EXAM,
- ActionCategory.FILTER),
- MONITOR_EXAM_SHOW_CLOSED_CONNECTION(
- new LocTextKey("sebserver.monitoring.exam.connection.action.show.closed"),
- ImageIcon.TOGGLE_ON,
- PageStateDefinitionImpl.MONITORING_RUNNING_EXAM,
- ActionCategory.FILTER),
- MONITOR_EXAM_HIDE_DISABLED_CONNECTION(
- new LocTextKey("sebserver.monitoring.exam.connection.action.hide.disabled"),
- ImageIcon.TOGGLE_OFF,
- PageStateDefinitionImpl.MONITORING_RUNNING_EXAM,
- ActionCategory.FILTER),
- MONITOR_EXAM_SHOW_DISABLED_CONNECTION(
- new LocTextKey("sebserver.monitoring.exam.connection.action.show.disabled"),
- ImageIcon.TOGGLE_ON,
- PageStateDefinitionImpl.MONITORING_RUNNING_EXAM,
- ActionCategory.FILTER),
-
- LOGS_USER_ACTIVITY_LIST(
- new LocTextKey("sebserver.logs.activity.userlogs"),
- PageStateDefinitionImpl.USER_ACTIVITY_LOGS),
- LOGS_USER_ACTIVITY_SHOW_DETAILS(
- new LocTextKey("sebserver.logs.activity.userlogs.details"),
- ImageIcon.SHOW,
- ActionCategory.LOGS_USER_ACTIVITY_LIST),
-
- LOGS_SEB_CLIENT(
- new LocTextKey("sebserver.logs.activity.seblogs"),
- PageStateDefinitionImpl.SEB_CLIENT_LOGS),
- LOGS_SEB_CLIENT_SHOW_DETAILS(
- new LocTextKey("sebserver.logs.activity.seblogs.details"),
- ImageIcon.SHOW,
- ActionCategory.LOGS_SEB_CLIENT_LIST),
-
- ;
-
- public final LocTextKey title;
- public final ImageIcon icon;
- public final PageStateDefinition targetState;
- public final ActionCategory category;
-
- private ActionDefinition(final LocTextKey title, final PageStateDefinition targetState) {
- this(title, null, targetState, ActionCategory.VARIA);
- }
-
- private ActionDefinition(final LocTextKey title, final ImageIcon icon, final PageStateDefinition targetState) {
- this(title, icon, targetState, ActionCategory.VARIA);
- }
-
- private ActionDefinition(
- final LocTextKey title,
- final ImageIcon icon,
- final ActionCategory category) {
-
- this(title, icon, null, category);
- }
-
- private ActionDefinition(
- final LocTextKey title,
- final ImageIcon icon,
- final PageStateDefinition targetState,
- final ActionCategory category) {
-
- this.title = title;
- this.icon = icon;
- this.targetState = targetState;
- this.category = category;
- }
-
-}
+/*
+ * Copyright (c) 2018 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.content.action;
+
+import ch.ethz.seb.sebserver.gui.content.activity.PageStateDefinitionImpl;
+import ch.ethz.seb.sebserver.gui.service.i18n.LocTextKey;
+import ch.ethz.seb.sebserver.gui.service.page.PageStateDefinition;
+import ch.ethz.seb.sebserver.gui.widget.WidgetFactory.ImageIcon;
+
+/** Enumeration of static action data for each action within the SEB Server GUI */
+public enum ActionDefinition {
+
+ INSTITUTION_VIEW_LIST(
+ new LocTextKey("sebserver.institution.action.list"),
+ PageStateDefinitionImpl.INSTITUTION_LIST),
+ INSTITUTION_VIEW_FORM(
+ new LocTextKey("sebserver.institution.action.form"),
+ PageStateDefinitionImpl.INSTITUTION_VIEW),
+ INSTITUTION_NEW(
+ new LocTextKey("sebserver.institution.action.new"),
+ ImageIcon.INSTITUTION,
+ PageStateDefinitionImpl.INSTITUTION_EDIT,
+ ActionCategory.FORM),
+ INSTITUTION_VIEW_FROM_LIST(
+ new LocTextKey("sebserver.institution.action.list.view"),
+ ImageIcon.SHOW,
+ PageStateDefinitionImpl.INSTITUTION_VIEW,
+ ActionCategory.INSTITUTION_LIST),
+ INSTITUTION_MODIFY_FROM_LIST(
+ new LocTextKey("sebserver.institution.action.list.modify"),
+ ImageIcon.EDIT,
+ PageStateDefinitionImpl.INSTITUTION_EDIT,
+ ActionCategory.INSTITUTION_LIST),
+
+ INSTITUTION_MODIFY(
+ new LocTextKey("sebserver.institution.action.modify"),
+ ImageIcon.EDIT,
+ PageStateDefinitionImpl.INSTITUTION_EDIT,
+ ActionCategory.FORM),
+ INSTITUTION_CANCEL_MODIFY(
+ new LocTextKey("sebserver.overall.action.modify.cancel"),
+ ImageIcon.CANCEL,
+ PageStateDefinitionImpl.INSTITUTION_VIEW,
+ ActionCategory.FORM),
+ INSTITUTION_SAVE(
+ new LocTextKey("sebserver.institution.action.save"),
+ ImageIcon.SAVE,
+ PageStateDefinitionImpl.INSTITUTION_VIEW,
+ ActionCategory.FORM),
+ INSTITUTION_SAVE_AND_ACTIVATE(
+ new LocTextKey("sebserver.form.action.save.activate"),
+ ImageIcon.ACTIVE,
+ PageStateDefinitionImpl.INSTITUTION_VIEW,
+ ActionCategory.FORM),
+ INSTITUTION_ACTIVATE(
+ new LocTextKey("sebserver.institution.action.activate"),
+ ImageIcon.TOGGLE_OFF,
+ PageStateDefinitionImpl.INSTITUTION_VIEW,
+ ActionCategory.FORM),
+ INSTITUTION_DEACTIVATE(
+ new LocTextKey("sebserver.institution.action.deactivate"),
+ ImageIcon.TOGGLE_ON,
+ PageStateDefinitionImpl.INSTITUTION_VIEW,
+ ActionCategory.FORM),
+ INSTITUTION_TOGGLE_ACTIVITY(
+ new LocTextKey("sebserver.overall.action.toggle-activity"),
+ ImageIcon.SWITCH,
+ PageStateDefinitionImpl.INSTITUTION_LIST,
+ ActionCategory.INSTITUTION_LIST),
+
+ USER_ACCOUNT_VIEW_LIST(
+ new LocTextKey("sebserver.useraccount.action.list"),
+ PageStateDefinitionImpl.USER_ACCOUNT_LIST),
+ USER_ACCOUNT_VIEW_FORM(
+ new LocTextKey("sebserver.useraccount.action.form"),
+ PageStateDefinitionImpl.USER_ACCOUNT_VIEW),
+ USER_ACCOUNT_NEW(
+ new LocTextKey("sebserver.useraccount.action.new"),
+ ImageIcon.USER,
+ PageStateDefinitionImpl.USER_ACCOUNT_EDIT),
+ USER_ACCOUNT_VIEW_FROM_LIST(
+ new LocTextKey("sebserver.useraccount.action.view"),
+ ImageIcon.SHOW,
+ PageStateDefinitionImpl.USER_ACCOUNT_VIEW,
+ ActionCategory.USER_ACCOUNT_LIST),
+ USER_ACCOUNT_MODIFY_FROM_LIST(
+ new LocTextKey("sebserver.useraccount.action.list.modify"),
+ ImageIcon.EDIT,
+ PageStateDefinitionImpl.USER_ACCOUNT_EDIT,
+ ActionCategory.USER_ACCOUNT_LIST),
+ USER_ACCOUNT_MODIFY(
+ new LocTextKey("sebserver.useraccount.action.modify"),
+ ImageIcon.EDIT,
+ PageStateDefinitionImpl.USER_ACCOUNT_EDIT,
+ ActionCategory.FORM),
+ USER_ACCOUNT_CANCEL_MODIFY(
+ new LocTextKey("sebserver.overall.action.modify.cancel"),
+ ImageIcon.CANCEL,
+ PageStateDefinitionImpl.USER_ACCOUNT_VIEW,
+ ActionCategory.FORM),
+ USER_ACCOUNT_SAVE(
+ new LocTextKey("sebserver.useraccount.action.save"),
+ ImageIcon.SAVE,
+ PageStateDefinitionImpl.USER_ACCOUNT_VIEW,
+ ActionCategory.FORM),
+ USER_ACCOUNT_SAVE_AND_ACTIVATE(
+ new LocTextKey("sebserver.form.action.save.activate"),
+ ImageIcon.ACTIVE,
+ PageStateDefinitionImpl.USER_ACCOUNT_VIEW,
+ ActionCategory.FORM),
+ USER_ACCOUNT_ACTIVATE(
+ new LocTextKey("sebserver.useraccount.action.activate"),
+ ImageIcon.TOGGLE_OFF,
+ PageStateDefinitionImpl.USER_ACCOUNT_VIEW,
+ ActionCategory.FORM),
+ USER_ACCOUNT_DEACTIVATE(
+ new LocTextKey("sebserver.useraccount.action.deactivate"),
+ ImageIcon.TOGGLE_ON,
+ PageStateDefinitionImpl.USER_ACCOUNT_VIEW,
+ ActionCategory.FORM),
+ USER_ACCOUNT_TOGGLE_ACTIVITY(
+ new LocTextKey("sebserver.overall.action.toggle-activity"),
+ ImageIcon.SWITCH,
+ PageStateDefinitionImpl.USER_ACCOUNT_LIST,
+ ActionCategory.USER_ACCOUNT_LIST),
+
+ USER_ACCOUNT_CHANGE_PASSWORD(
+ new LocTextKey("sebserver.useraccount.action.change.password"),
+ ImageIcon.SECURE,
+ PageStateDefinitionImpl.USER_ACCOUNT_PASSWORD_CHANGE,
+ ActionCategory.FORM),
+ USER_ACCOUNT_CHANGE_PASSWORD_SAVE(
+ new LocTextKey("sebserver.useraccount.action.change.password.save"),
+ ImageIcon.SAVE,
+ PageStateDefinitionImpl.USER_ACCOUNT_VIEW,
+ ActionCategory.FORM),
+
+ LMS_SETUP_VIEW_LIST(
+ new LocTextKey("sebserver.lmssetup.action.list"),
+ PageStateDefinitionImpl.LMS_SETUP_LIST),
+ LMS_SETUP_NEW(
+ new LocTextKey("sebserver.lmssetup.action.new"),
+ ImageIcon.LMS_SETUP,
+ PageStateDefinitionImpl.LMS_SETUP_EDIT),
+ LMS_SETUP_VIEW_FROM_LIST(
+ new LocTextKey("sebserver.lmssetup.action.list.view"),
+ ImageIcon.SHOW,
+ PageStateDefinitionImpl.LMS_SETUP_VIEW,
+ ActionCategory.LMS_SETUP_LIST),
+ LMS_SETUP_MODIFY_FROM_LIST(
+ new LocTextKey("sebserver.lmssetup.action.list.modify"),
+ ImageIcon.EDIT,
+ PageStateDefinitionImpl.LMS_SETUP_EDIT,
+ ActionCategory.LMS_SETUP_LIST),
+ LMS_SETUP_MODIFY(
+ new LocTextKey("sebserver.lmssetup.action.modify"),
+ ImageIcon.EDIT,
+ PageStateDefinitionImpl.LMS_SETUP_EDIT,
+ ActionCategory.FORM),
+ LMS_SETUP_SAVE_AND_TEST(
+ new LocTextKey("sebserver.lmssetup.action.savetest"),
+ ImageIcon.TEST,
+ PageStateDefinitionImpl.LMS_SETUP_VIEW,
+ ActionCategory.FORM),
+ LMS_SETUP_TEST_AND_SAVE(
+ new LocTextKey("sebserver.lmssetup.action.testsave"),
+ ImageIcon.TEST,
+ PageStateDefinitionImpl.LMS_SETUP_VIEW,
+ ActionCategory.FORM),
+ LMS_SETUP_CANCEL_MODIFY(
+ new LocTextKey("sebserver.overall.action.modify.cancel"),
+ ImageIcon.CANCEL,
+ PageStateDefinitionImpl.LMS_SETUP_VIEW,
+ ActionCategory.FORM),
+ LMS_SETUP_SAVE(
+ new LocTextKey("sebserver.lmssetup.action.save"),
+ ImageIcon.SAVE,
+ PageStateDefinitionImpl.LMS_SETUP_VIEW,
+ ActionCategory.FORM),
+ LMS_SETUP_ACTIVATE(
+ new LocTextKey("sebserver.lmssetup.action.activate"),
+ ImageIcon.TOGGLE_OFF,
+ PageStateDefinitionImpl.LMS_SETUP_VIEW,
+ ActionCategory.FORM),
+ LMS_SETUP_DEACTIVATE(
+ new LocTextKey("sebserver.lmssetup.action.deactivate"),
+ ImageIcon.TOGGLE_ON,
+ PageStateDefinitionImpl.LMS_SETUP_VIEW,
+ ActionCategory.FORM),
+
+ QUIZ_DISCOVERY_VIEW_LIST(
+ new LocTextKey("sebserver.quizdiscovery.action.list"),
+ PageStateDefinitionImpl.QUIZ_LIST),
+ QUIZ_DISCOVERY_SHOW_DETAILS(
+ new LocTextKey("sebserver.quizdiscovery.action.details"),
+ ImageIcon.SHOW,
+ ActionCategory.QUIZ_LIST),
+ QUIZ_DISCOVERY_EXAM_IMPORT(
+ new LocTextKey("sebserver.quizdiscovery.action.import"),
+ ImageIcon.IMPORT,
+ PageStateDefinitionImpl.EXAM_EDIT,
+ ActionCategory.QUIZ_LIST),
+
+ EXAM_VIEW_LIST(
+ new LocTextKey("sebserver.exam.action.list"),
+ PageStateDefinitionImpl.EXAM_LIST),
+ EXAM_IMPORT(
+ new LocTextKey("sebserver.exam.action.import"),
+ ImageIcon.IMPORT,
+ PageStateDefinitionImpl.QUIZ_LIST),
+ EXAM_VIEW_FROM_LIST(
+ new LocTextKey("sebserver.exam.action.list.view"),
+ ImageIcon.SHOW,
+ PageStateDefinitionImpl.EXAM_VIEW,
+ ActionCategory.EXAM_LIST),
+ EXAM_MODIFY_FROM_LIST(
+ new LocTextKey("sebserver.exam.action.list.modify"),
+ ImageIcon.EDIT,
+ PageStateDefinitionImpl.EXAM_EDIT,
+ ActionCategory.EXAM_LIST),
+ EXAM_MODIFY(
+ new LocTextKey("sebserver.exam.action.modify"),
+ ImageIcon.EDIT,
+ PageStateDefinitionImpl.EXAM_EDIT,
+ ActionCategory.FORM),
+ EXAM_CANCEL_MODIFY(
+ new LocTextKey("sebserver.overall.action.modify.cancel"),
+ ImageIcon.CANCEL,
+ PageStateDefinitionImpl.EXAM_VIEW,
+ ActionCategory.FORM),
+ EXAM_SAVE(
+ new LocTextKey("sebserver.exam.action.save"),
+ ImageIcon.SAVE,
+ PageStateDefinitionImpl.EXAM_VIEW,
+ ActionCategory.FORM),
+ EXAM_ACTIVATE(
+ new LocTextKey("sebserver.exam.action.activate"),
+ ImageIcon.TOGGLE_OFF,
+ PageStateDefinitionImpl.EXAM_VIEW,
+ ActionCategory.FORM),
+ EXAM_DEACTIVATE(
+ new LocTextKey("sebserver.exam.action.deactivate"),
+ ImageIcon.TOGGLE_ON,
+ PageStateDefinitionImpl.EXAM_VIEW,
+ ActionCategory.FORM),
+
+ EXAM_MODIFY_SEB_RESTRICTION_DETAILS(
+ new LocTextKey("sebserver.exam.action.sebrestriction.details"),
+ ImageIcon.RESTRICTION,
+ PageStateDefinitionImpl.EXAM_VIEW,
+ ActionCategory.FORM),
+ EXAM_ENABLE_SEB_RESTRICTION(
+ new LocTextKey("sebserver.exam.action.sebrestriction.enable"),
+ ImageIcon.UNLOCK,
+ PageStateDefinitionImpl.EXAM_VIEW,
+ ActionCategory.FORM),
+ EXAM_DISABLE_SEB_RESTRICTION(
+ new LocTextKey("sebserver.exam.action.sebrestriction.disable"),
+ ImageIcon.LOCK,
+ PageStateDefinitionImpl.EXAM_VIEW,
+ ActionCategory.FORM),
+
+ EXAM_CONFIGURATION_NEW(
+ new LocTextKey("sebserver.exam.configuration.action.list.new"),
+ ImageIcon.NEW,
+ PageStateDefinitionImpl.EXAM_VIEW,
+ ActionCategory.EXAM_CONFIG_MAPPING_LIST),
+ EXAM_CONFIGURATION_MODIFY_FROM_LIST(
+ new LocTextKey("sebserver.exam.configuration.action.list.modify"),
+ ImageIcon.EDIT,
+ PageStateDefinitionImpl.EXAM_VIEW,
+ ActionCategory.EXAM_CONFIG_MAPPING_LIST),
+ EXAM_CONFIGURATION_EXAM_CONFIG_VIEW_PROP(
+ new LocTextKey("sebserver.exam.configuration.action.list.view"),
+ ImageIcon.SHOW,
+ PageStateDefinitionImpl.SEB_EXAM_CONFIG_PROP_VIEW,
+ ActionCategory.EXAM_CONFIG_MAPPING_LIST),
+ EXAM_CONFIGURATION_DELETE_FROM_LIST(
+ new LocTextKey("sebserver.exam.configuration.action.list.delete"),
+ ImageIcon.DELETE,
+ PageStateDefinitionImpl.EXAM_VIEW,
+ ActionCategory.EXAM_CONFIG_MAPPING_LIST),
+ EXAM_CONFIGURATION_EXPORT(
+ new LocTextKey("sebserver.exam.configuration.action.export-config"),
+ ImageIcon.EXPORT,
+ PageStateDefinitionImpl.EXAM_VIEW,
+ ActionCategory.EXAM_CONFIG_MAPPING_LIST),
+ EXAM_CONFIGURATION_GET_CONFIG_KEY(
+ new LocTextKey("sebserver.exam.configuration.action.get-config-key"),
+ ImageIcon.SECURE,
+ ActionCategory.EXAM_CONFIG_MAPPING_LIST),
+ EXAM_CONFIGURATION_SAVE(
+ new LocTextKey("sebserver.exam.configuration.action.save"),
+ ImageIcon.SAVE,
+ PageStateDefinitionImpl.EXAM_VIEW,
+ ActionCategory.FORM),
+ EXAM_CONFIGURATION_CANCEL_MODIFY(
+ new LocTextKey("sebserver.overall.action.modify.cancel"),
+ ImageIcon.CANCEL,
+ PageStateDefinitionImpl.EXAM_VIEW,
+ ActionCategory.FORM),
+
+ EXAM_INDICATOR_NEW(
+ new LocTextKey("sebserver.exam.indicator.action.list.new"),
+ ImageIcon.INDICATOR,
+ PageStateDefinitionImpl.INDICATOR_EDIT,
+ ActionCategory.INDICATOR_LIST),
+ EXAM_INDICATOR_MODIFY_FROM_LIST(
+ new LocTextKey("sebserver.exam.indicator.action.list.modify"),
+ ImageIcon.EDIT,
+ PageStateDefinitionImpl.INDICATOR_EDIT,
+ ActionCategory.INDICATOR_LIST),
+ EXAM_INDICATOR_DELETE_FROM_LIST(
+ new LocTextKey("sebserver.exam.indicator.action.list.delete"),
+ ImageIcon.DELETE,
+ PageStateDefinitionImpl.EXAM_VIEW,
+ ActionCategory.INDICATOR_LIST),
+ EXAM_INDICATOR_SAVE(
+ new LocTextKey("sebserver.exam.indicator.action.save"),
+ ImageIcon.SAVE,
+ PageStateDefinitionImpl.EXAM_VIEW,
+ ActionCategory.FORM),
+ EXAM_INDICATOR_CANCEL_MODIFY(
+ new LocTextKey("sebserver.overall.action.modify.cancel"),
+ ImageIcon.CANCEL,
+ PageStateDefinitionImpl.EXAM_VIEW,
+ ActionCategory.FORM),
+
+ SEB_CLIENT_CONFIG_LIST(
+ new LocTextKey("sebserver.clientconfig.action.list"),
+ PageStateDefinitionImpl.SEB_CLIENT_CONFIG_LIST),
+ SEB_CLIENT_CONFIG_NEW(
+ new LocTextKey("sebserver.clientconfig.action.list.new"),
+ ImageIcon.NEW,
+ PageStateDefinitionImpl.SEB_CLIENT_CONFIG_EDIT),
+ SEB_CLIENT_CONFIG_VIEW_FROM_LIST(
+ new LocTextKey("sebserver.clientconfig.action.list.view"),
+ ImageIcon.SHOW,
+ PageStateDefinitionImpl.SEB_CLIENT_CONFIG_VIEW,
+ ActionCategory.SEB_CLIENT_CONFIG_LIST),
+ SEB_CLIENT_CONFIG_MODIFY_FROM_LIST(
+ new LocTextKey("sebserver.clientconfig.action.list.modify"),
+ ImageIcon.EDIT,
+ PageStateDefinitionImpl.SEB_CLIENT_CONFIG_EDIT,
+ ActionCategory.SEB_CLIENT_CONFIG_LIST),
+ SEB_CLIENT_CONFIG_MODIFY(
+ new LocTextKey("sebserver.clientconfig.action.modify"),
+ ImageIcon.EDIT,
+ PageStateDefinitionImpl.SEB_CLIENT_CONFIG_EDIT,
+ ActionCategory.FORM),
+ SEB_CLIENT_CONFIG_CANCEL_MODIFY(
+ new LocTextKey("sebserver.overall.action.modify.cancel"),
+ ImageIcon.CANCEL,
+ PageStateDefinitionImpl.SEB_CLIENT_CONFIG_VIEW,
+ ActionCategory.FORM),
+ SEB_CLIENT_CONFIG_SAVE(
+ new LocTextKey("sebserver.clientconfig.action.save"),
+ ImageIcon.SAVE,
+ PageStateDefinitionImpl.SEB_CLIENT_CONFIG_VIEW,
+ ActionCategory.FORM),
+ SEB_CLIENT_CONFIG_SAVE_AND_ACTIVATE(
+ new LocTextKey("sebserver.form.action.save.activate"),
+ ImageIcon.ACTIVE,
+ PageStateDefinitionImpl.SEB_CLIENT_CONFIG_VIEW,
+ ActionCategory.FORM),
+ SEB_CLIENT_CONFIG_ACTIVATE(
+ new LocTextKey("sebserver.clientconfig.action.activate"),
+ ImageIcon.TOGGLE_OFF,
+ PageStateDefinitionImpl.SEB_CLIENT_CONFIG_VIEW,
+ ActionCategory.FORM),
+ SEB_CLIENT_CONFIG_DEACTIVATE(
+ new LocTextKey("sebserver.clientconfig.action.deactivate"),
+ ImageIcon.TOGGLE_ON,
+ PageStateDefinitionImpl.SEB_CLIENT_CONFIG_VIEW,
+ ActionCategory.FORM),
+ SEB_CLIENT_CONFIG_TOGGLE_ACTIVITY(
+ new LocTextKey("sebserver.overall.action.toggle-activity"),
+ ImageIcon.SWITCH,
+ PageStateDefinitionImpl.SEB_CLIENT_CONFIG_LIST,
+ ActionCategory.SEB_CLIENT_CONFIG_LIST),
+ SEB_CLIENT_CONFIG_EXPORT(
+ new LocTextKey("sebserver.clientconfig.action.export"),
+ ImageIcon.EXPORT,
+ PageStateDefinitionImpl.SEB_CLIENT_CONFIG_VIEW,
+ ActionCategory.FORM),
+
+ SEB_EXAM_CONFIG_LIST(
+ new LocTextKey("sebserver.examconfig.action.list"),
+ PageStateDefinitionImpl.SEB_EXAM_CONFIG_LIST),
+ SEB_EXAM_CONFIG_NEW(
+ new LocTextKey("sebserver.examconfig.action.list.new"),
+ ImageIcon.NEW,
+ PageStateDefinitionImpl.SEB_EXAM_CONFIG_PROP_EDIT),
+ SEB_EXAM_CONFIG_VIEW_PROP_FROM_LIST(
+ new LocTextKey("sebserver.examconfig.action.list.view"),
+ ImageIcon.SHOW,
+ PageStateDefinitionImpl.SEB_EXAM_CONFIG_PROP_VIEW,
+ ActionCategory.SEB_EXAM_CONFIG_LIST),
+ SEB_EXAM_CONFIG_VIEW_PROP(
+ new LocTextKey("sebserver.examconfig.action.view.properties"),
+ ImageIcon.SHOW,
+ PageStateDefinitionImpl.SEB_EXAM_CONFIG_PROP_VIEW,
+ ActionCategory.FORM),
+ SEB_EXAM_CONFIG_IMPORT_TO_NEW_CONFIG(
+ new LocTextKey("sebserver.examconfig.action.import-config"),
+ ImageIcon.IMPORT,
+ PageStateDefinitionImpl.SEB_EXAM_CONFIG_LIST,
+ ActionCategory.VARIA),
+
+ SEB_EXAM_CONFIG_MODIFY_PROP_FROM_LIST(
+ new LocTextKey("sebserver.examconfig.action.list.modify.properties"),
+ ImageIcon.EDIT,
+ PageStateDefinitionImpl.SEB_EXAM_CONFIG_PROP_EDIT,
+ ActionCategory.SEB_EXAM_CONFIG_LIST),
+ SEB_EXAM_CONFIG_PROP_MODIFY(
+ new LocTextKey("sebserver.examconfig.action.modify.properties"),
+ ImageIcon.EDIT,
+ PageStateDefinitionImpl.SEB_EXAM_CONFIG_PROP_EDIT,
+ ActionCategory.FORM),
+ SEB_EXAM_CONFIG_MODIFY(
+ new LocTextKey("sebserver.examconfig.action.modify"),
+ ImageIcon.EDIT_SETTINGS,
+ PageStateDefinitionImpl.SEB_EXAM_CONFIG_EDIT,
+ ActionCategory.FORM),
+
+ SEB_EXAM_CONFIG_PROP_CANCEL_MODIFY(
+ new LocTextKey("sebserver.overall.action.modify.cancel"),
+ ImageIcon.CANCEL,
+ PageStateDefinitionImpl.SEB_EXAM_CONFIG_PROP_VIEW,
+ ActionCategory.FORM),
+ SEB_EXAM_CONFIG_PROP_SAVE(
+ new LocTextKey("sebserver.examconfig.action.save"),
+ ImageIcon.SAVE,
+ PageStateDefinitionImpl.SEB_EXAM_CONFIG_PROP_VIEW,
+ ActionCategory.FORM),
+
+ SEB_EXAM_CONFIG_EXPORT_PLAIN_XML(
+ new LocTextKey("sebserver.examconfig.action.export.plainxml"),
+ ImageIcon.EXPORT,
+ ActionCategory.FORM),
+ SEB_EXAM_CONFIG_GET_CONFIG_KEY(
+ new LocTextKey("sebserver.examconfig.action.get-config-key"),
+ ImageIcon.SECURE,
+ ActionCategory.FORM),
+ SEB_EXAM_CONFIG_IMPORT_TO_EXISTING_CONFIG(
+ new LocTextKey("sebserver.examconfig.action.import-config"),
+ ImageIcon.IMPORT,
+ ActionCategory.FORM),
+
+ SEB_EXAM_CONFIG_COPY_CONFIG(
+ new LocTextKey("sebserver.examconfig.action.copy"),
+ ImageIcon.COPY,
+ ActionCategory.FORM),
+ SEB_EXAM_CONFIG_COPY_CONFIG_AS_TEMPALTE(
+ new LocTextKey("sebserver.examconfig.action.copy-as-template"),
+ ImageIcon.TEMPLATE,
+ ActionCategory.FORM),
+
+ SEB_EXAM_CONFIG_MODIFY_FROM_LIST(
+ new LocTextKey("sebserver.examconfig.action.list.modify"),
+ ImageIcon.EDIT_SETTINGS,
+ PageStateDefinitionImpl.SEB_EXAM_CONFIG_EDIT,
+ ActionCategory.SEB_EXAM_CONFIG_LIST),
+
+ SEB_EXAM_CONFIG_SAVE_TO_HISTORY(
+ new LocTextKey("sebserver.examconfig.action.saveToHistory"),
+ ImageIcon.SAVE,
+ PageStateDefinitionImpl.SEB_EXAM_CONFIG_EDIT,
+ ActionCategory.FORM),
+ SEB_EXAM_CONFIG_UNDO(
+ new LocTextKey("sebserver.examconfig.action.undo"),
+ ImageIcon.UNDO,
+ PageStateDefinitionImpl.SEB_EXAM_CONFIG_EDIT,
+ ActionCategory.FORM),
+
+ SEB_EXAM_CONFIG_TEMPLATE_LIST(
+ new LocTextKey("sebserver.configtemplate.action.list"),
+ PageStateDefinitionImpl.SEB_EXAM_CONFIG_TEMPLATE_LIST),
+ SEB_EXAM_CONFIG_TEMPLATE_NEW(
+ new LocTextKey("sebserver.configtemplate.action.list.new"),
+ ImageIcon.TEMPLATE,
+ PageStateDefinitionImpl.SEB_EXAM_CONFIG_TEMPLATE_EDIT,
+ ActionCategory.VARIA),
+ SEB_EXAM_CONFIG_TEMPLATE_VIEW_FROM_LIST(
+ new LocTextKey("sebserver.configtemplate.action.list.view"),
+ ImageIcon.SHOW,
+ PageStateDefinitionImpl.SEB_EXAM_CONFIG_TEMPLATE_VIEW,
+ ActionCategory.SEB_CONFIG_TEMPLATE_LIST),
+ SEB_EXAM_CONFIG_TEMPLATE_VIEW(
+ new LocTextKey("sebserver.configtemplate.action.view"),
+ ImageIcon.SHOW,
+ PageStateDefinitionImpl.SEB_EXAM_CONFIG_TEMPLATE_VIEW,
+ ActionCategory.FORM),
+ SEB_EXAM_CONFIG_TEMPLATE_MODIFY_FROM_LIST(
+ new LocTextKey("sebserver.configtemplate.action.list.modify"),
+ ImageIcon.EDIT,
+ PageStateDefinitionImpl.SEB_EXAM_CONFIG_TEMPLATE_EDIT,
+ ActionCategory.SEB_CONFIG_TEMPLATE_LIST),
+ SEB_EXAM_CONFIG_TEMPLATE_MODIFY(
+ new LocTextKey("sebserver.configtemplate.action.modify"),
+ ImageIcon.EDIT,
+ PageStateDefinitionImpl.SEB_EXAM_CONFIG_TEMPLATE_EDIT,
+ ActionCategory.FORM),
+ SEB_EXAM_CONFIG_TEMPLATE_CREATE_CONFIG(
+ new LocTextKey("sebserver.configtemplate.action.create-config"),
+ ImageIcon.NEW,
+ PageStateDefinitionImpl.SEB_EXAM_CONFIG_TEMPLATE_VIEW,
+ ActionCategory.FORM),
+ SEB_EXAM_CONFIG_TEMPLATE_CANCEL_MODIFY(
+ new LocTextKey("sebserver.overall.action.modify.cancel"),
+ ImageIcon.CANCEL,
+ PageStateDefinitionImpl.SEB_EXAM_CONFIG_TEMPLATE_VIEW,
+ ActionCategory.FORM),
+ SEB_EXAM_CONFIG_TEMPLATE_SAVE(
+ new LocTextKey("sebserver.configtemplate.action.save"),
+ ImageIcon.SAVE,
+ PageStateDefinitionImpl.SEB_EXAM_CONFIG_TEMPLATE_VIEW,
+ ActionCategory.FORM),
+
+ SEB_EXAM_CONFIG_TEMPLATE_ATTR_EDIT(
+ new LocTextKey("sebserver.configtemplate.attr.list.actions.modify"),
+ ImageIcon.EDIT,
+ PageStateDefinitionImpl.SEB_EXAM_CONFIG_TEMPLATE_ATTRIBUTE_EDIT,
+ ActionCategory.SEB_CONFIG_TEMPLATE_ATTRIBUTE_LIST),
+ SEB_EXAM_CONFIG_TEMPLATE_ATTR_SET_DEFAULT(
+ new LocTextKey("sebserver.configtemplate.attr.list.actions.setdefault"),
+ ImageIcon.SAVE,
+ PageStateDefinitionImpl.SEB_EXAM_CONFIG_TEMPLATE_VIEW,
+ ActionCategory.SEB_CONFIG_TEMPLATE_ATTRIBUTE_LIST),
+ SEB_EXAM_CONFIG_TEMPLATE_ATTR_LIST_REMOVE_VIEW(
+ new LocTextKey("sebserver.configtemplate.attr.list.actions.removeview"),
+ ImageIcon.REMOVE,
+ PageStateDefinitionImpl.SEB_EXAM_CONFIG_TEMPLATE_VIEW,
+ ActionCategory.SEB_CONFIG_TEMPLATE_ATTRIBUTE_LIST),
+ SEB_EXAM_CONFIG_TEMPLATE_ATTR_LIST_ATTACH_DEFAULT_VIEW(
+ new LocTextKey("sebserver.configtemplate.attr.list.actions.attach-default-view"),
+ ImageIcon.ADD,
+ PageStateDefinitionImpl.SEB_EXAM_CONFIG_TEMPLATE_VIEW,
+ ActionCategory.SEB_CONFIG_TEMPLATE_ATTRIBUTE_LIST),
+ SEB_EXAM_CONFIG_TEMPLATE_ATTR_REMOVE_VIEW(
+ new LocTextKey("sebserver.configtemplate.attr.list.actions.removeview"),
+ ImageIcon.REMOVE,
+ PageStateDefinitionImpl.SEB_EXAM_CONFIG_TEMPLATE_ATTRIBUTE_EDIT,
+ ActionCategory.FORM),
+ SEB_EXAM_CONFIG_TEMPLATE_ATTR_ATTACH_DEFAULT_VIEW(
+ new LocTextKey("sebserver.configtemplate.attr.list.actions.attach-default-view"),
+ ImageIcon.ADD,
+ PageStateDefinitionImpl.SEB_EXAM_CONFIG_TEMPLATE_ATTRIBUTE_EDIT,
+ ActionCategory.FORM),
+
+ SEB_EXAM_CONFIG_TEMPLATE_ATTR_FORM_SET_DEFAULT(
+ new LocTextKey("sebserver.configtemplate.attr.action.setdefault"),
+ ImageIcon.UNDO,
+ PageStateDefinitionImpl.SEB_EXAM_CONFIG_TEMPLATE_ATTRIBUTE_EDIT,
+ ActionCategory.FORM),
+ SEB_EXAM_CONFIG_TEMPLATE_ATTR_FORM_EDIT_TEMPLATE(
+ new LocTextKey("sebserver.configtemplate.attr.action.template"),
+ ImageIcon.SHOW,
+ PageStateDefinitionImpl.SEB_EXAM_CONFIG_TEMPLATE_VIEW,
+ ActionCategory.FORM),
+
+ RUNNING_EXAM_VIEW_LIST(
+ new LocTextKey("sebserver.monitoring.action.list"),
+ PageStateDefinitionImpl.MONITORING_RUNNING_EXAM_LIST),
+ MONITOR_EXAM_FROM_LIST(
+ new LocTextKey("sebserver.monitoring.exam.action.list.view"),
+ ImageIcon.SHOW,
+ PageStateDefinitionImpl.MONITORING_RUNNING_EXAM,
+ ActionCategory.RUNNING_EXAM_LIST),
+ MONITOR_EXAM_CLIENT_CONNECTION(
+ new LocTextKey("sebserver.monitoring.exam.connection.action.view"),
+ ImageIcon.SHOW,
+ PageStateDefinitionImpl.MONITORING_CLIENT_CONNECTION,
+ ActionCategory.CLIENT_EVENT_LIST),
+ MONITOR_EXAM_CLIENT_CONNECTION_QUIT(
+ new LocTextKey("sebserver.monitoring.exam.connection.action.instruction.quit"),
+ ImageIcon.SEND_QUIT,
+ PageStateDefinitionImpl.MONITORING_CLIENT_CONNECTION,
+ ActionCategory.FORM),
+ MONITOR_EXAM_QUIT_SELECTED(
+ new LocTextKey("sebserver.monitoring.exam.connection.action.instruction.quit"),
+ ImageIcon.SEND_QUIT,
+ PageStateDefinitionImpl.MONITORING_RUNNING_EXAM,
+ ActionCategory.CLIENT_EVENT_LIST),
+ MONITOR_EXAM_QUIT_ALL(
+ new LocTextKey("sebserver.monitoring.exam.connection.action.instruction.quit.all"),
+ ImageIcon.SEND_QUIT,
+ PageStateDefinitionImpl.MONITORING_RUNNING_EXAM,
+ ActionCategory.FORM),
+ MONITOR_EXAM_FROM_DETAILS(
+ new LocTextKey("sebserver.monitoring.exam.action.detail.view"),
+ ImageIcon.SHOW,
+ PageStateDefinitionImpl.MONITORING_RUNNING_EXAM,
+ ActionCategory.FORM),
+
+ MONITOR_EXAM_DISABLE_SELECTED_CONNECTION(
+ new LocTextKey("sebserver.monitoring.exam.connection.action.disable"),
+ ImageIcon.DISABLE,
+ PageStateDefinitionImpl.MONITORING_RUNNING_EXAM,
+ ActionCategory.CLIENT_EVENT_LIST),
+
+ MONITOR_EXAM_HIDE_REQUESTED_CONNECTION(
+ new LocTextKey("sebserver.monitoring.exam.connection.action.hide.requested"),
+ ImageIcon.TOGGLE_OFF,
+ PageStateDefinitionImpl.MONITORING_RUNNING_EXAM,
+ ActionCategory.FILTER),
+ MONITOR_EXAM_SHOW_REQUESTED_CONNECTION(
+ new LocTextKey("sebserver.monitoring.exam.connection.action.show.requested"),
+ ImageIcon.TOGGLE_ON,
+ PageStateDefinitionImpl.MONITORING_RUNNING_EXAM,
+ ActionCategory.FILTER),
+ MONITOR_EXAM_HIDE_CLOSED_CONNECTION(
+ new LocTextKey("sebserver.monitoring.exam.connection.action.hide.closed"),
+ ImageIcon.TOGGLE_OFF,
+ PageStateDefinitionImpl.MONITORING_RUNNING_EXAM,
+ ActionCategory.FILTER),
+ MONITOR_EXAM_SHOW_CLOSED_CONNECTION(
+ new LocTextKey("sebserver.monitoring.exam.connection.action.show.closed"),
+ ImageIcon.TOGGLE_ON,
+ PageStateDefinitionImpl.MONITORING_RUNNING_EXAM,
+ ActionCategory.FILTER),
+ MONITOR_EXAM_HIDE_DISABLED_CONNECTION(
+ new LocTextKey("sebserver.monitoring.exam.connection.action.hide.disabled"),
+ ImageIcon.TOGGLE_OFF,
+ PageStateDefinitionImpl.MONITORING_RUNNING_EXAM,
+ ActionCategory.FILTER),
+ MONITOR_EXAM_SHOW_DISABLED_CONNECTION(
+ new LocTextKey("sebserver.monitoring.exam.connection.action.show.disabled"),
+ ImageIcon.TOGGLE_ON,
+ PageStateDefinitionImpl.MONITORING_RUNNING_EXAM,
+ ActionCategory.FILTER),
+
+ LOGS_USER_ACTIVITY_LIST(
+ new LocTextKey("sebserver.logs.activity.userlogs"),
+ PageStateDefinitionImpl.USER_ACTIVITY_LOGS),
+ LOGS_USER_ACTIVITY_SHOW_DETAILS(
+ new LocTextKey("sebserver.logs.activity.userlogs.details"),
+ ImageIcon.SHOW,
+ ActionCategory.LOGS_USER_ACTIVITY_LIST),
+
+ LOGS_SEB_CLIENT(
+ new LocTextKey("sebserver.logs.activity.seblogs"),
+ PageStateDefinitionImpl.SEB_CLIENT_LOGS),
+ LOGS_SEB_CLIENT_SHOW_DETAILS(
+ new LocTextKey("sebserver.logs.activity.seblogs.details"),
+ ImageIcon.SHOW,
+ ActionCategory.LOGS_SEB_CLIENT_LIST),
+
+ ;
+
+ public final LocTextKey title;
+ public final ImageIcon icon;
+ public final PageStateDefinition targetState;
+ public final ActionCategory category;
+
+ ActionDefinition(final LocTextKey title, final PageStateDefinition targetState) {
+ this(title, null, targetState, ActionCategory.VARIA);
+ }
+
+ ActionDefinition(final LocTextKey title, final ImageIcon icon, final PageStateDefinition targetState) {
+ this(title, icon, targetState, ActionCategory.VARIA);
+ }
+
+ ActionDefinition(
+ final LocTextKey title,
+ final ImageIcon icon,
+ final ActionCategory category) {
+
+ this(title, icon, null, category);
+ }
+
+ ActionDefinition(
+ final LocTextKey title,
+ final ImageIcon icon,
+ final PageStateDefinition targetState,
+ final ActionCategory category) {
+
+ this.title = title;
+ this.icon = icon;
+ this.targetState = targetState;
+ this.category = category;
+ }
+
+}
diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/content/activity/PageStateDefinitionImpl.java b/src/main/java/ch/ethz/seb/sebserver/gui/content/activity/PageStateDefinitionImpl.java
index 493fb22c..c242cf22 100644
--- a/src/main/java/ch/ethz/seb/sebserver/gui/content/activity/PageStateDefinitionImpl.java
+++ b/src/main/java/ch/ethz/seb/sebserver/gui/content/activity/PageStateDefinitionImpl.java
@@ -1,138 +1,137 @@
-/*
- * 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.content.activity;
-
-import ch.ethz.seb.sebserver.gui.content.ConfigTemplateAttributeForm;
-import ch.ethz.seb.sebserver.gui.content.ConfigTemplateForm;
-import ch.ethz.seb.sebserver.gui.content.ConfigTemplateList;
-import ch.ethz.seb.sebserver.gui.content.ExamForm;
-import ch.ethz.seb.sebserver.gui.content.ExamList;
-import ch.ethz.seb.sebserver.gui.content.IndicatorForm;
-import ch.ethz.seb.sebserver.gui.content.InstitutionForm;
-import ch.ethz.seb.sebserver.gui.content.InstitutionList;
-import ch.ethz.seb.sebserver.gui.content.LmsSetupForm;
-import ch.ethz.seb.sebserver.gui.content.LmsSetupList;
-import ch.ethz.seb.sebserver.gui.content.MonitoringClientConnection;
-import ch.ethz.seb.sebserver.gui.content.MonitoringRunningExam;
-import ch.ethz.seb.sebserver.gui.content.MonitoringRunningExamList;
-import ch.ethz.seb.sebserver.gui.content.QuizDiscoveryList;
-import ch.ethz.seb.sebserver.gui.content.SebClientConfigForm;
-import ch.ethz.seb.sebserver.gui.content.SebClientConfigList;
-import ch.ethz.seb.sebserver.gui.content.SebClientLogs;
-import ch.ethz.seb.sebserver.gui.content.SebExamConfigList;
-import ch.ethz.seb.sebserver.gui.content.SebExamConfigPropForm;
-import ch.ethz.seb.sebserver.gui.content.SebExamConfigSettingsForm;
-import ch.ethz.seb.sebserver.gui.content.UserAccountChangePasswordForm;
-import ch.ethz.seb.sebserver.gui.content.UserAccountForm;
-import ch.ethz.seb.sebserver.gui.content.UserAccountList;
-import ch.ethz.seb.sebserver.gui.content.UserActivityLogs;
-import ch.ethz.seb.sebserver.gui.content.action.ActionPane;
-import ch.ethz.seb.sebserver.gui.service.page.Activity;
-import ch.ethz.seb.sebserver.gui.service.page.PageStateDefinition;
-import ch.ethz.seb.sebserver.gui.service.page.TemplateComposer;
-
-public enum PageStateDefinitionImpl implements PageStateDefinition {
-
- INSTITUTION_LIST(Type.LIST_VIEW, InstitutionList.class, ActivityDefinition.INSTITUTION),
- INSTITUTION_VIEW(Type.FORM_VIEW, InstitutionForm.class, ActivityDefinition.INSTITUTION),
- INSTITUTION_EDIT(Type.FORM_EDIT, InstitutionForm.class, ActivityDefinition.INSTITUTION),
-
- USER_ACCOUNT_LIST(Type.LIST_VIEW, UserAccountList.class, ActivityDefinition.USER_ACCOUNT),
- USER_ACCOUNT_VIEW(Type.FORM_VIEW, UserAccountForm.class, ActivityDefinition.USER_ACCOUNT),
- USER_ACCOUNT_EDIT(Type.FORM_EDIT, UserAccountForm.class, ActivityDefinition.USER_ACCOUNT),
- USER_ACCOUNT_PASSWORD_CHANGE(Type.FORM_EDIT, UserAccountChangePasswordForm.class, ActivityDefinition.USER_ACCOUNT),
-
- LMS_SETUP_LIST(Type.LIST_VIEW, LmsSetupList.class, ActivityDefinition.LMS_SETUP),
- LMS_SETUP_VIEW(Type.FORM_VIEW, LmsSetupForm.class, ActivityDefinition.LMS_SETUP),
- LMS_SETUP_EDIT(Type.FORM_EDIT, LmsSetupForm.class, ActivityDefinition.LMS_SETUP),
-
- QUIZ_LIST(Type.LIST_VIEW, QuizDiscoveryList.class, ActivityDefinition.QUIZ_DISCOVERY),
-
- EXAM_LIST(Type.LIST_VIEW, ExamList.class, ActivityDefinition.EXAM),
- EXAM_VIEW(Type.FORM_VIEW, ExamForm.class, ActivityDefinition.EXAM),
- EXAM_EDIT(Type.FORM_EDIT, ExamForm.class, ActivityDefinition.EXAM),
- INDICATOR_EDIT(Type.FORM_EDIT, IndicatorForm.class, ActivityDefinition.EXAM),
-
- SEB_CLIENT_CONFIG_LIST(Type.LIST_VIEW, SebClientConfigList.class, ActivityDefinition.SEB_CLIENT_CONFIG),
- SEB_CLIENT_CONFIG_VIEW(Type.FORM_VIEW, SebClientConfigForm.class, ActivityDefinition.SEB_CLIENT_CONFIG),
- SEB_CLIENT_CONFIG_EDIT(Type.FORM_EDIT, SebClientConfigForm.class, ActivityDefinition.SEB_CLIENT_CONFIG),
-
- SEB_EXAM_CONFIG_LIST(Type.LIST_VIEW, SebExamConfigList.class, ActivityDefinition.SEB_EXAM_CONFIG),
- SEB_EXAM_CONFIG_PROP_VIEW(Type.FORM_VIEW, SebExamConfigPropForm.class, ActivityDefinition.SEB_EXAM_CONFIG),
- SEB_EXAM_CONFIG_PROP_EDIT(Type.FORM_EDIT, SebExamConfigPropForm.class, ActivityDefinition.SEB_EXAM_CONFIG),
- SEB_EXAM_CONFIG_EDIT(Type.FORM_IN_TIME_EDIT, SebExamConfigSettingsForm.class, ActivityDefinition.SEB_EXAM_CONFIG),
- SEB_EXAM_CONFIG_VIEW(Type.FORM_VIEW, SebExamConfigSettingsForm.class, ActivityDefinition.SEB_EXAM_CONFIG),
-
- SEB_EXAM_CONFIG_TEMPLATE_LIST(Type.LIST_VIEW, ConfigTemplateList.class,
- ActivityDefinition.SEB_EXAM_CONFIG_TEMPLATE),
- SEB_EXAM_CONFIG_TEMPLATE_VIEW(Type.FORM_VIEW, ConfigTemplateForm.class,
- ActivityDefinition.SEB_EXAM_CONFIG_TEMPLATE),
- SEB_EXAM_CONFIG_TEMPLATE_EDIT(Type.FORM_EDIT, ConfigTemplateForm.class,
- ActivityDefinition.SEB_EXAM_CONFIG_TEMPLATE),
-
- SEB_EXAM_CONFIG_TEMPLATE_ATTRIBUTE_EDIT(
- Type.FORM_EDIT,
- ConfigTemplateAttributeForm.class,
- ActivityDefinition.SEB_EXAM_CONFIG),
-
- MONITORING_RUNNING_EXAM_LIST(Type.LIST_VIEW, MonitoringRunningExamList.class, ActivityDefinition.MONITORING_EXAMS),
- MONITORING_RUNNING_EXAM(Type.FORM_VIEW, MonitoringRunningExam.class, ActivityDefinition.MONITORING_EXAMS),
- MONITORING_CLIENT_CONNECTION(Type.FORM_VIEW, MonitoringClientConnection.class, ActivityDefinition.MONITORING_EXAMS),
-
- USER_ACTIVITY_LOGS(Type.LIST_VIEW, UserActivityLogs.class, ActivityDefinition.USER_ACTIVITY_LOGS),
- SEB_CLIENT_LOGS(Type.LIST_VIEW, SebClientLogs.class, ActivityDefinition.SEB_CLIENT_LOGS)
-
- ;
-
- public final Type type;
- public final Class extends TemplateComposer> contentPaneComposer;
- public final Class extends TemplateComposer> actionPaneComposer;
- public final Activity activityAnchor;
-
- private PageStateDefinitionImpl(
- final Type type,
- final Class extends TemplateComposer> contentPaneComposer,
- final Activity activityAnchor) {
-
- this(type, contentPaneComposer, ActionPane.class, activityAnchor);
- }
-
- private PageStateDefinitionImpl(
- final Type type,
- final Class extends TemplateComposer> contentPaneComposer,
- final Class extends TemplateComposer> actionPaneComposer,
- final Activity activityAnchor) {
-
- this.type = type;
- this.contentPaneComposer = contentPaneComposer;
- this.actionPaneComposer = actionPaneComposer;
- this.activityAnchor = activityAnchor;
- }
-
- @Override
- public Type type() {
- return this.type;
- }
-
- @Override
- public Class extends TemplateComposer> contentPaneComposer() {
- return this.contentPaneComposer;
- }
-
- @Override
- public Class extends TemplateComposer> actionPaneComposer() {
- return this.actionPaneComposer;
- }
-
- @Override
- public Activity activityAnchor() {
- return this.activityAnchor;
- }
-
-}
+/*
+ * 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.content.activity;
+
+import ch.ethz.seb.sebserver.gui.content.ConfigTemplateAttributeForm;
+import ch.ethz.seb.sebserver.gui.content.ConfigTemplateForm;
+import ch.ethz.seb.sebserver.gui.content.ConfigTemplateList;
+import ch.ethz.seb.sebserver.gui.content.ExamForm;
+import ch.ethz.seb.sebserver.gui.content.ExamList;
+import ch.ethz.seb.sebserver.gui.content.IndicatorForm;
+import ch.ethz.seb.sebserver.gui.content.InstitutionForm;
+import ch.ethz.seb.sebserver.gui.content.InstitutionList;
+import ch.ethz.seb.sebserver.gui.content.LmsSetupForm;
+import ch.ethz.seb.sebserver.gui.content.LmsSetupList;
+import ch.ethz.seb.sebserver.gui.content.MonitoringClientConnection;
+import ch.ethz.seb.sebserver.gui.content.MonitoringRunningExam;
+import ch.ethz.seb.sebserver.gui.content.MonitoringRunningExamList;
+import ch.ethz.seb.sebserver.gui.content.QuizDiscoveryList;
+import ch.ethz.seb.sebserver.gui.content.SebClientConfigForm;
+import ch.ethz.seb.sebserver.gui.content.SebClientConfigList;
+import ch.ethz.seb.sebserver.gui.content.SebClientLogs;
+import ch.ethz.seb.sebserver.gui.content.SebExamConfigList;
+import ch.ethz.seb.sebserver.gui.content.SebExamConfigPropForm;
+import ch.ethz.seb.sebserver.gui.content.SebExamConfigSettingsForm;
+import ch.ethz.seb.sebserver.gui.content.UserAccountChangePasswordForm;
+import ch.ethz.seb.sebserver.gui.content.UserAccountForm;
+import ch.ethz.seb.sebserver.gui.content.UserAccountList;
+import ch.ethz.seb.sebserver.gui.content.UserActivityLogs;
+import ch.ethz.seb.sebserver.gui.content.action.ActionPane;
+import ch.ethz.seb.sebserver.gui.service.page.Activity;
+import ch.ethz.seb.sebserver.gui.service.page.PageStateDefinition;
+import ch.ethz.seb.sebserver.gui.service.page.TemplateComposer;
+
+public enum PageStateDefinitionImpl implements PageStateDefinition {
+
+ INSTITUTION_LIST(Type.LIST_VIEW, InstitutionList.class, ActivityDefinition.INSTITUTION),
+ INSTITUTION_VIEW(Type.FORM_VIEW, InstitutionForm.class, ActivityDefinition.INSTITUTION),
+ INSTITUTION_EDIT(Type.FORM_EDIT, InstitutionForm.class, ActivityDefinition.INSTITUTION),
+
+ USER_ACCOUNT_LIST(Type.LIST_VIEW, UserAccountList.class, ActivityDefinition.USER_ACCOUNT),
+ USER_ACCOUNT_VIEW(Type.FORM_VIEW, UserAccountForm.class, ActivityDefinition.USER_ACCOUNT),
+ USER_ACCOUNT_EDIT(Type.FORM_EDIT, UserAccountForm.class, ActivityDefinition.USER_ACCOUNT),
+ USER_ACCOUNT_PASSWORD_CHANGE(Type.FORM_EDIT, UserAccountChangePasswordForm.class, ActivityDefinition.USER_ACCOUNT),
+
+ LMS_SETUP_LIST(Type.LIST_VIEW, LmsSetupList.class, ActivityDefinition.LMS_SETUP),
+ LMS_SETUP_VIEW(Type.FORM_VIEW, LmsSetupForm.class, ActivityDefinition.LMS_SETUP),
+ LMS_SETUP_EDIT(Type.FORM_EDIT, LmsSetupForm.class, ActivityDefinition.LMS_SETUP),
+
+ QUIZ_LIST(Type.LIST_VIEW, QuizDiscoveryList.class, ActivityDefinition.QUIZ_DISCOVERY),
+
+ EXAM_LIST(Type.LIST_VIEW, ExamList.class, ActivityDefinition.EXAM),
+ EXAM_VIEW(Type.FORM_VIEW, ExamForm.class, ActivityDefinition.EXAM),
+ EXAM_EDIT(Type.FORM_EDIT, ExamForm.class, ActivityDefinition.EXAM),
+ INDICATOR_EDIT(Type.FORM_EDIT, IndicatorForm.class, ActivityDefinition.EXAM),
+
+ SEB_CLIENT_CONFIG_LIST(Type.LIST_VIEW, SebClientConfigList.class, ActivityDefinition.SEB_CLIENT_CONFIG),
+ SEB_CLIENT_CONFIG_VIEW(Type.FORM_VIEW, SebClientConfigForm.class, ActivityDefinition.SEB_CLIENT_CONFIG),
+ SEB_CLIENT_CONFIG_EDIT(Type.FORM_EDIT, SebClientConfigForm.class, ActivityDefinition.SEB_CLIENT_CONFIG),
+
+ SEB_EXAM_CONFIG_LIST(Type.LIST_VIEW, SebExamConfigList.class, ActivityDefinition.SEB_EXAM_CONFIG),
+ SEB_EXAM_CONFIG_PROP_VIEW(Type.FORM_VIEW, SebExamConfigPropForm.class, ActivityDefinition.SEB_EXAM_CONFIG),
+ SEB_EXAM_CONFIG_PROP_EDIT(Type.FORM_EDIT, SebExamConfigPropForm.class, ActivityDefinition.SEB_EXAM_CONFIG),
+ SEB_EXAM_CONFIG_EDIT(Type.FORM_IN_TIME_EDIT, SebExamConfigSettingsForm.class, ActivityDefinition.SEB_EXAM_CONFIG),
+ SEB_EXAM_CONFIG_VIEW(Type.FORM_VIEW, SebExamConfigSettingsForm.class, ActivityDefinition.SEB_EXAM_CONFIG),
+
+ SEB_EXAM_CONFIG_TEMPLATE_LIST(Type.LIST_VIEW, ConfigTemplateList.class,
+ ActivityDefinition.SEB_EXAM_CONFIG_TEMPLATE),
+ SEB_EXAM_CONFIG_TEMPLATE_VIEW(Type.FORM_VIEW, ConfigTemplateForm.class,
+ ActivityDefinition.SEB_EXAM_CONFIG_TEMPLATE),
+ SEB_EXAM_CONFIG_TEMPLATE_EDIT(Type.FORM_EDIT, ConfigTemplateForm.class,
+ ActivityDefinition.SEB_EXAM_CONFIG_TEMPLATE),
+ SEB_EXAM_CONFIG_TEMPLATE_ATTRIBUTE_EDIT(
+ Type.FORM_EDIT,
+ ConfigTemplateAttributeForm.class,
+ ActivityDefinition.SEB_EXAM_CONFIG_TEMPLATE),
+
+ MONITORING_RUNNING_EXAM_LIST(Type.LIST_VIEW, MonitoringRunningExamList.class, ActivityDefinition.MONITORING_EXAMS),
+ MONITORING_RUNNING_EXAM(Type.FORM_VIEW, MonitoringRunningExam.class, ActivityDefinition.MONITORING_EXAMS),
+ MONITORING_CLIENT_CONNECTION(Type.FORM_VIEW, MonitoringClientConnection.class, ActivityDefinition.MONITORING_EXAMS),
+
+ USER_ACTIVITY_LOGS(Type.LIST_VIEW, UserActivityLogs.class, ActivityDefinition.USER_ACTIVITY_LOGS),
+ SEB_CLIENT_LOGS(Type.LIST_VIEW, SebClientLogs.class, ActivityDefinition.SEB_CLIENT_LOGS)
+
+ ;
+
+ public final Type type;
+ public final Class extends TemplateComposer> contentPaneComposer;
+ public final Class extends TemplateComposer> actionPaneComposer;
+ public final Activity activityAnchor;
+
+ private PageStateDefinitionImpl(
+ final Type type,
+ final Class extends TemplateComposer> contentPaneComposer,
+ final Activity activityAnchor) {
+
+ this(type, contentPaneComposer, ActionPane.class, activityAnchor);
+ }
+
+ private PageStateDefinitionImpl(
+ final Type type,
+ final Class extends TemplateComposer> contentPaneComposer,
+ final Class extends TemplateComposer> actionPaneComposer,
+ final Activity activityAnchor) {
+
+ this.type = type;
+ this.contentPaneComposer = contentPaneComposer;
+ this.actionPaneComposer = actionPaneComposer;
+ this.activityAnchor = activityAnchor;
+ }
+
+ @Override
+ public Type type() {
+ return this.type;
+ }
+
+ @Override
+ public Class extends TemplateComposer> contentPaneComposer() {
+ return this.contentPaneComposer;
+ }
+
+ @Override
+ public Class extends TemplateComposer> actionPaneComposer() {
+ return this.actionPaneComposer;
+ }
+
+ @Override
+ public Activity activityAnchor() {
+ return this.activityAnchor;
+ }
+
+}
diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/ResourceService.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/ResourceService.java
index 3cca59d5..432ac387 100644
--- a/src/main/java/ch/ethz/seb/sebserver/gui/service/ResourceService.java
+++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/ResourceService.java
@@ -1,650 +1,665 @@
-/*
- * 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;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.EnumSet;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-import java.util.function.Function;
-import java.util.function.Supplier;
-import java.util.stream.Collectors;
-
-import org.apache.commons.lang3.StringUtils;
-import org.joda.time.DateTimeZone;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.context.annotation.Lazy;
-import org.springframework.stereotype.Service;
-
-import ch.ethz.seb.sebserver.gbl.Constants;
-import ch.ethz.seb.sebserver.gbl.api.API;
-import ch.ethz.seb.sebserver.gbl.api.EntityType;
-import ch.ethz.seb.sebserver.gbl.model.Activatable;
-import ch.ethz.seb.sebserver.gbl.model.Entity;
-import ch.ethz.seb.sebserver.gbl.model.EntityName;
-import ch.ethz.seb.sebserver.gbl.model.exam.Exam;
-import ch.ethz.seb.sebserver.gbl.model.exam.Exam.ExamStatus;
-import ch.ethz.seb.sebserver.gbl.model.exam.Exam.ExamType;
-import ch.ethz.seb.sebserver.gbl.model.exam.ExamConfigurationMap;
-import ch.ethz.seb.sebserver.gbl.model.exam.Indicator.IndicatorType;
-import ch.ethz.seb.sebserver.gbl.model.exam.OpenEdxSebRestriction.PermissionComponent;
-import ch.ethz.seb.sebserver.gbl.model.exam.OpenEdxSebRestriction.WhiteListPath;
-import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetup.LmsType;
-import ch.ethz.seb.sebserver.gbl.model.sebconfig.AttributeType;
-import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode;
-import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode.ConfigurationStatus;
-import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode.ConfigurationType;
-import ch.ethz.seb.sebserver.gbl.model.sebconfig.TemplateAttribute;
-import ch.ethz.seb.sebserver.gbl.model.sebconfig.View;
-import ch.ethz.seb.sebserver.gbl.model.session.ClientConnection.ConnectionStatus;
-import ch.ethz.seb.sebserver.gbl.model.session.ClientConnectionData;
-import ch.ethz.seb.sebserver.gbl.model.session.ClientEvent;
-import ch.ethz.seb.sebserver.gbl.model.session.ClientEvent.EventType;
-import ch.ethz.seb.sebserver.gbl.model.user.UserActivityLog;
-import ch.ethz.seb.sebserver.gbl.model.user.UserInfo;
-import ch.ethz.seb.sebserver.gbl.model.user.UserLogActivityType;
-import ch.ethz.seb.sebserver.gbl.model.user.UserRole;
-import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
-import ch.ethz.seb.sebserver.gbl.util.Result;
-import ch.ethz.seb.sebserver.gbl.util.Tuple;
-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.remote.webservice.api.RestService;
-import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.GetExamNames;
-import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.GetExams;
-import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.institution.GetInstitutionNames;
-import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.lmssetup.GetLmsSetupNames;
-import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.GetExamConfigNodeNames;
-import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.GetExamConfigNodes;
-import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.GetViews;
-import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.useraccount.GetUserAccountNames;
-import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.CurrentUser;
-
-@Lazy
-@Service
-@GuiProfile
-/** Defines functionality to get resources or functions of resources to feed e.g. selection or
- * combo-box content. */
-public class ResourceService {
-
- private static final String MISSING_CLIENT_PING_NAME_KEY = "MISSING";
-
- public static final Comparator> RESOURCE_COMPARATOR = (t1, t2) -> t1._2.compareTo(t2._2);
-
- public static final EnumSet ENTITY_TYPE_EXCLUDE_MAP = EnumSet.of(
- EntityType.ADDITIONAL_ATTRIBUTES,
- EntityType.CLIENT_CONNECTION,
- EntityType.CLIENT_EVENT,
- EntityType.CONFIGURATION_ATTRIBUTE,
- EntityType.CONFIGURATION_VALUE,
- EntityType.CONFIGURATION,
- EntityType.ORIENTATION,
- EntityType.USER_ACTIVITY_LOG,
- EntityType.USER_ROLE,
- EntityType.WEBSERVICE_SERVER_INFO);
-
- public static final EnumSet CLIENT_EVENT_TYPE_EXCLUDE_MAP = EnumSet.of(
- EventType.LAST_PING);
-
- public static final String EXAMCONFIG_STATUS_PREFIX = "sebserver.examconfig.status.";
- public static final String EXAM_TYPE_PREFIX = "sebserver.exam.type.";
- public static final String USERACCOUNT_ROLE_PREFIX = "sebserver.useraccount.role.";
- public static final String EXAM_INDICATOR_TYPE_PREFIX = "sebserver.exam.indicator.type.";
- public static final String LMSSETUP_TYPE_PREFIX = "sebserver.lmssetup.type.";
- public static final String LMSSETUP_PROXY_AUTH_TYPE_PREFIX = "sebserver.lmssetup.form.proxy.auth-type.";
- public static final String CONFIG_ATTRIBUTE_TYPE_PREFIX = "sebserver.configtemplate.attr.type.";
- public static final String SEB_RESTRICTION_WHITE_LIST_PREFIX = "sebserver.exam.form.sebrestriction.whiteListPaths.";
- public static final String SEB_RESTRICTION_PERMISSIONS_PREFIX = "sebserver.exam.form.sebrestriction.permissions.";
-
- public static final EnumSet ATTRIBUTE_TYPES_NOT_DISPLAYED = EnumSet.of(
- AttributeType.LABEL,
- AttributeType.COMPOSITE_TABLE,
- AttributeType.INLINE_TABLE);
-
- public static final String CLIENT_EVENT_TYPE_PREFIX = "sebserver.monitoring.exam.connection.event.type.";
- public static final String USER_ACTIVITY_TYPE_PREFIX = "sebserver.overall.types.activityType.";
- public static final String ENTITY_TYPE_PREFIX = "sebserver.overall.types.entityType.";
- public static final String SEB_CONNECTION_STATUS_KEY_PREFIX = "sebserver.monitoring.exam.connection.status.";
- public static final LocTextKey ACTIVE_TEXT_KEY = new LocTextKey("sebserver.overall.status.active");
- public static final LocTextKey INACTIVE_TEXT_KEY = new LocTextKey("sebserver.overall.status.inactive");
-
- private final I18nSupport i18nSupport;
- private final RestService restService;
- private final CurrentUser currentUser;
- private final boolean mock_lms_enabled;
-
- protected ResourceService(
- final I18nSupport i18nSupport,
- final RestService restService,
- final CurrentUser currentUser,
- @Value("${sebserver.gui.webservice.mock-lms-enabled:true}") final boolean mock_lms_enabled) {
-
- this.i18nSupport = i18nSupport;
- this.restService = restService;
- this.currentUser = currentUser;
- this.mock_lms_enabled = mock_lms_enabled;
- }
-
- public I18nSupport getI18nSupport() {
- return this.i18nSupport;
- }
-
- public RestService getRestService() {
- return this.restService;
- }
-
- public CurrentUser getCurrentUser() {
- return this.currentUser;
- }
-
- public Supplier>> localizedResourceSupplier(final List> source) {
- return () -> source.stream()
- .map(tuple -> new Tuple<>(tuple._1, this.i18nSupport.getText(tuple._2)))
- .collect(Collectors.toList());
- }
-
- public List> activityResources() {
- final List> result = new ArrayList<>();
- result.add(new Tuple<>(Constants.TRUE_STRING, this.i18nSupport.getText("sebserver.overall.status.active")));
- result.add(new Tuple<>(Constants.FALSE_STRING, this.i18nSupport.getText("sebserver.overall.status.inactive")));
- result.add(new Tuple<>(StringUtils.EMPTY, this.i18nSupport.getText("sebserver.overall.status.all")));
- return result;
- }
-
- public List> lmsTypeResources() {
- return Arrays.asList(LmsType.values())
- .stream()
- .filter(lmsType -> lmsType != LmsType.MOCKUP || this.mock_lms_enabled)
- .map(lmsType -> new Tuple<>(
- lmsType.name(),
- this.i18nSupport.getText(LMSSETUP_TYPE_PREFIX + lmsType.name(), lmsType.name())))
- .sorted(RESOURCE_COMPARATOR)
- .collect(Collectors.toList());
- }
-
- public List> clientEventTypeResources() {
- return Arrays.asList(EventType.values())
- .stream()
- .filter(eventType -> !CLIENT_EVENT_TYPE_EXCLUDE_MAP.contains(eventType))
- .map(eventType -> new Tuple<>(
- eventType.name(),
- getEventTypeName(eventType)))
- .sorted(RESOURCE_COMPARATOR)
- .collect(Collectors.toList());
- }
-
- public String getEventTypeName(final ClientEvent event) {
- if (event == null) {
- return getEventTypeName(EventType.UNKNOWN);
- }
- return getEventTypeName(event.eventType);
- }
-
- public String getEventTypeName(final EventType eventType) {
- if (eventType == null) {
- return Constants.EMPTY_NOTE;
- }
- return this.i18nSupport.getText(CLIENT_EVENT_TYPE_PREFIX + eventType.name(), eventType.name());
- }
-
- public List> indicatorTypeResources() {
- return Arrays.asList(IndicatorType.values())
- .stream()
- .map(type -> new Tuple<>(
- type.name(),
- this.i18nSupport.getText(EXAM_INDICATOR_TYPE_PREFIX + type.name(), type.name())))
- .sorted(RESOURCE_COMPARATOR)
- .collect(Collectors.toList());
- }
-
- public List> examConfigurationSelectionResources() {
- return getExamConfigurationSelection()
- .getOr(Collections.emptyList())
- .stream()
- .map(entityName -> new Tuple<>(entityName.modelId, entityName.name))
- .sorted(RESOURCE_COMPARATOR)
- .collect(Collectors.toList());
- }
-
- public List> userRoleResources() {
- return UserRole.publicRolesForUser(this.currentUser.get())
- .stream()
- .map(ur -> new Tuple<>(
- ur.name(),
- this.i18nSupport.getText(USERACCOUNT_ROLE_PREFIX + ur.name())))
- .sorted(RESOURCE_COMPARATOR)
- .collect(Collectors.toList());
- }
-
- public List> institutionResource() {
- return this.restService.getBuilder(GetInstitutionNames.class)
- .withQueryParam(Entity.FILTER_ATTR_ACTIVE, Constants.TRUE_STRING)
- .call()
- .getOr(Collections.emptyList())
- .stream()
- .map(entityName -> new Tuple<>(entityName.modelId, entityName.name))
- .sorted(RESOURCE_COMPARATOR)
- .collect(Collectors.toList());
- }
-
- public Function getInstitutionNameFunction() {
- final Map idNameMap = this.restService.getBuilder(GetInstitutionNames.class)
- .withQueryParam(Entity.FILTER_ATTR_ACTIVE, Constants.TRUE_STRING)
- .call()
- .getOr(Collections.emptyList())
- .stream()
- .collect(Collectors.toMap(e -> e.modelId, e -> e.name));
-
- return id -> {
- if (!idNameMap.containsKey(id)) {
- return Constants.EMPTY_NOTE;
- }
- return idNameMap.get(id);
- };
- }
-
- public List> lmsSetupResource() {
- 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(Entity.FILTER_ATTR_INSTITUTION, institutionId)
- .withQueryParam(Entity.FILTER_ATTR_ACTIVE, Constants.TRUE_STRING)
- .call()
- .getOr(Collections.emptyList())
- .stream()
- .map(entityName -> new Tuple<>(entityName.modelId, entityName.name))
- .sorted(RESOURCE_COMPARATOR)
- .collect(Collectors.toList());
- }
-
- public Function getLmsSetupNameFunction() {
- final boolean isSEBAdmin = this.currentUser.get().hasRole(UserRole.SEB_SERVER_ADMIN);
- final String institutionId = (isSEBAdmin) ? "" : String.valueOf(this.currentUser.get().institutionId);
- final Map idNameMap = this.restService.getBuilder(GetLmsSetupNames.class)
- .withQueryParam(Entity.FILTER_ATTR_INSTITUTION, institutionId)
- .withQueryParam(Entity.FILTER_ATTR_ACTIVE, Constants.TRUE_STRING)
- .call()
- .getOr(Collections.emptyList())
- .stream()
- .collect(Collectors.toMap(e -> e.modelId, e -> e.name));
-
- return id -> {
- if (!idNameMap.containsKey(id)) {
- return Constants.EMPTY_NOTE;
- }
- return idNameMap.get(id);
- };
- }
-
- public List> entityTypeResources() {
- return Arrays.asList(EntityType.values())
- .stream()
- .filter(type -> !ENTITY_TYPE_EXCLUDE_MAP.contains(type))
- .map(type -> new Tuple<>(type.name(), getEntityTypeName(type)))
- .sorted(RESOURCE_COMPARATOR)
- .collect(Collectors.toList());
- }
-
- public static LocTextKey getEntityTypeNameKey(final EntityType type) {
- return new LocTextKey(ENTITY_TYPE_PREFIX + type.name());
- }
-
- public String getEntityTypeName(final EntityType type) {
- if (type == null) {
- return Constants.EMPTY_NOTE;
- }
- return this.i18nSupport.getText(getEntityTypeNameKey(type));
- }
-
- public String getEntityTypeName(final UserActivityLog userLog) {
- return getEntityTypeName(userLog.entityType);
- }
-
- public List> userActivityTypeResources() {
- return Arrays.asList(UserLogActivityType.values())
- .stream()
- .map(type -> new Tuple<>(type.name(), getUserActivityTypeName(type)))
- .sorted(RESOURCE_COMPARATOR)
- .collect(Collectors.toList());
- }
-
- public String getUserActivityTypeName(final UserLogActivityType type) {
- if (type == null) {
- return Constants.EMPTY_NOTE;
- }
- return this.i18nSupport.getText(USER_ACTIVITY_TYPE_PREFIX + type.name());
- }
-
- public String getUserActivityTypeName(final UserActivityLog userLog) {
- return getUserActivityTypeName(userLog.activityType);
- }
-
- /** 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 */
- public List> languageResources() {
- final Locale currentLocale = this.i18nSupport.getUsersLanguageLocale();
- return this.i18nSupport.supportedLanguages()
- .stream()
- .map(locale -> new Tuple<>(locale.toLanguageTag(), locale.getDisplayLanguage(currentLocale)))
- .filter(tuple -> StringUtils.isNotBlank(tuple._2))
- .sorted(RESOURCE_COMPARATOR)
- .collect(Collectors.toList());
- }
-
- public List> timeZoneResources() {
- final Locale currentLocale = this.i18nSupport.getUsersLanguageLocale();
- return DateTimeZone
- .getAvailableIDs()
- .stream()
- .map(id -> new Tuple<>(id, id + " (" + DateTimeZone.forID(id).getName(0, currentLocale) + ")"))
- .sorted(RESOURCE_COMPARATOR)
- .collect(Collectors.toList());
- }
-
- public List> examTypeResources() {
- return Arrays.asList(ExamType.values())
- .stream()
- .filter(type -> type != ExamType.UNDEFINED)
- .map(type -> new Tuple<>(
- type.name(),
- this.i18nSupport.getText(EXAM_TYPE_PREFIX + type.name())))
- .sorted(RESOURCE_COMPARATOR)
- .collect(Collectors.toList());
- }
-
- public List> examConfigStatusResources() {
- return examConfigStatusResources(false);
- }
-
- public List> examConfigStatusResources(final boolean isAttachedToExam) {
- return Arrays.asList(ConfigurationStatus.values())
- .stream()
- .filter(status -> {
- if (isAttachedToExam) {
- return status != ConfigurationStatus.READY_TO_USE;
- } else {
- return status != ConfigurationStatus.IN_USE;
- }
- })
- .map(type -> new Tuple<>(
- type.name(),
- this.i18nSupport.getText(EXAMCONFIG_STATUS_PREFIX + type.name())))
- .sorted(RESOURCE_COMPARATOR)
- .collect(Collectors.toList());
- }
-
- public List> examSupporterResources() {
- final UserInfo userInfo = this.currentUser.get();
- final List selection = 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());
- return selection
- .stream()
- .map(entityName -> new Tuple<>(entityName.modelId, entityName.name))
- .sorted(RESOURCE_COMPARATOR)
- .collect(Collectors.toList());
- }
-
- public List> userResources() {
- 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)
- .call()
- .getOr(Collections.emptyList())
- .stream()
- .map(entityName -> new Tuple<>(entityName.modelId, entityName.name))
- .sorted(RESOURCE_COMPARATOR)
- .collect(Collectors.toList());
- }
-
- public Function localizedActivityFunction() {
- final Function localizedActivityResource = localizedActivityResource();
- return activatable -> localizedActivityResource.apply(activatable.isActive());
- }
-
- public Function localizedActivityResource() {
- return activity -> activity
- ? this.i18nSupport.getText(ACTIVE_TEXT_KEY)
- : this.i18nSupport.getText(INACTIVE_TEXT_KEY);
- }
-
- public String localizedExamConfigInstitutionName(final ConfigurationNode config) {
- return getInstitutionNameFunction()
- .apply(String.valueOf(config.institutionId));
- }
-
- public String localizedExamConfigStatusName(final ConfigurationNode config) {
- if (config.status == null) {
- return Constants.EMPTY_NOTE;
- }
-
- return this.i18nSupport
- .getText(ResourceService.EXAMCONFIG_STATUS_PREFIX + config.status.name());
- }
-
- public String localizedExamConfigStatusName(final ExamConfigurationMap config) {
- if (config.configStatus == null) {
- return Constants.EMPTY_NOTE;
- }
-
- return this.i18nSupport
- .getText(ResourceService.EXAMCONFIG_STATUS_PREFIX + config.configStatus.name());
- }
-
- public String localizedClientConnectionStatusName(final ClientConnectionData connectionData) {
- if (connectionData == null) {
- final String name = ConnectionStatus.UNDEFINED.name();
- return this.i18nSupport.getText(
- SEB_CONNECTION_STATUS_KEY_PREFIX + name,
- name);
- }
- if (connectionData.missingPing) {
- return this.i18nSupport.getText(
- SEB_CONNECTION_STATUS_KEY_PREFIX + MISSING_CLIENT_PING_NAME_KEY,
- MISSING_CLIENT_PING_NAME_KEY);
- } else {
- return localizedClientConnectionStatusName((connectionData.clientConnection != null)
- ? connectionData.clientConnection.status
- : ConnectionStatus.UNDEFINED);
- }
- }
-
- public String localizedClientConnectionStatusName(final ConnectionStatus status) {
- String name;
- if (status != null) {
- name = status.name();
- } else {
- name = ConnectionStatus.UNDEFINED.name();
- }
- return this.i18nSupport
- .getText(SEB_CONNECTION_STATUS_KEY_PREFIX + name, name);
- }
-
- public String localizedExamTypeName(final ExamConfigurationMap examMap) {
- if (examMap.examType == null) {
- return Constants.EMPTY_NOTE;
- }
-
- return this.i18nSupport
- .getText(ResourceService.EXAM_TYPE_PREFIX + examMap.examType.name());
- }
-
- public String localizedExamTypeName(final Exam exam) {
- if (exam.type == null) {
- return Constants.EMPTY_NOTE;
- }
-
- return this.i18nSupport
- .getText(ResourceService.EXAM_TYPE_PREFIX + exam.type.name());
- }
-
- public List> getExamLogSelectionResources() {
- final UserInfo userInfo = this.currentUser.get();
- return this.restService.getBuilder(GetExams.class)
- .withQueryParam(Entity.FILTER_ATTR_INSTITUTION, String.valueOf(userInfo.getInstitutionId()))
- .withQueryParam(Exam.FILTER_CACHED_QUIZZES, Constants.TRUE_STRING)
- .call()
- .getOr(Collections.emptyList())
- .stream()
- .filter(exam -> exam != null
- && (exam.getStatus() == ExamStatus.RUNNING || exam.getStatus() == ExamStatus.FINISHED))
- .map(exam -> new Tuple<>(exam.getModelId(), exam.name))
- .sorted(RESOURCE_COMPARATOR)
- .collect(Collectors.toList());
- }
-
- public List> getExamResources() {
- final UserInfo userInfo = this.currentUser.get();
- return this.restService.getBuilder(GetExamNames.class)
- .withQueryParam(Entity.FILTER_ATTR_INSTITUTION, String.valueOf(userInfo.getInstitutionId()))
- .withQueryParam(Exam.FILTER_CACHED_QUIZZES, Constants.TRUE_STRING)
- .call()
- .getOr(Collections.emptyList())
- .stream()
- .map(entityName -> new Tuple<>(entityName.modelId, entityName.name))
- .sorted(RESOURCE_COMPARATOR)
- .collect(Collectors.toList());
- }
-
- public Map getExamNameMapping() {
- final UserInfo userInfo = this.currentUser.get();
- return this.restService.getBuilder(GetExamNames.class)
- .withQueryParam(Entity.FILTER_ATTR_INSTITUTION, String.valueOf(userInfo.getInstitutionId()))
- .withQueryParam(Exam.FILTER_CACHED_QUIZZES, Constants.TRUE_STRING)
- .call()
- .getOr(Collections.emptyList())
- .stream()
- .filter(k -> StringUtils.isNotBlank(k.modelId))
- .collect(Collectors.toMap(
- k -> Long.valueOf(k.modelId),
- k -> k.name));
- }
-
- public List> getViewResources() {
- return getViewResources(API.DEFAULT_CONFIG_TEMPLATE_ID);
- }
-
- public List> getViewResources(final String templateId) {
- return this.restService.getBuilder(GetViews.class)
- .withQueryParam(
- View.FILTER_ATTR_TEMPLATE,
- templateId)
- .call()
- .getOr(Collections.emptyList())
- .stream()
- .map(view -> new Tuple<>(view.getModelId(), view.name))
- .sorted(RESOURCE_COMPARATOR)
- .collect(Collectors.toList());
- }
-
- public final Function getViewNameFunction(final String templateId) {
- final Map mapping = this.getViewResources(templateId)
- .stream()
- .collect(Collectors.toMap(tuple -> tuple._1, tuple -> tuple._2));
-
- return attr -> mapping.get(attr.getViewModelId());
- }
-
- public List> getAttributeTypeResources() {
- return Arrays.asList(AttributeType.values())
- .stream()
- .filter(type -> !ATTRIBUTE_TYPES_NOT_DISPLAYED.contains(type))
- .map(type -> new Tuple<>(getAttributeTypeFilterName(type), getAttributeTypeName(type)))
- .sorted(RESOURCE_COMPARATOR)
- .collect(Collectors.toList());
- }
-
- public String getAttributeTypeName(final TemplateAttribute attribute) {
- if (attribute != null && attribute.getConfigAttribute() != null) {
- return getAttributeTypeName(attribute.getConfigAttribute().type);
- }
-
- return Constants.EMPTY_NOTE;
- }
-
- private String getAttributeTypeFilterName(final AttributeType type) {
- if (type == AttributeType.TABLE) {
- return type.name()
- + Constants.LIST_SEPARATOR
- + AttributeType.COMPOSITE_TABLE.name()
- + Constants.LIST_SEPARATOR
- + AttributeType.INLINE_TABLE.name();
- } else {
- return type.name();
- }
- }
-
- public String getAttributeTypeName(final AttributeType type) {
- if (type == null) {
- return Constants.EMPTY_NOTE;
- }
- return this.i18nSupport
- .getText(CONFIG_ATTRIBUTE_TYPE_PREFIX + type.name());
- }
-
- public List> getExamConfigTemplateResources() {
- final UserInfo userInfo = this.currentUser.get();
- return this.restService.getBuilder(GetExamConfigNodes.class)
- .withQueryParam(Entity.FILTER_ATTR_INSTITUTION, String.valueOf(userInfo.getInstitutionId()))
- .withQueryParam(ConfigurationNode.FILTER_ATTR_TYPE, ConfigurationType.TEMPLATE.name())
- .call()
- .getOr(Collections.emptyList())
- .stream()
- .map(node -> new Tuple<>(node.getModelId(), node.name))
- .sorted(RESOURCE_COMPARATOR)
- .collect(Collectors.toList());
- }
-
- public List> sebRestrictionWhiteListResources() {
- return Arrays.asList(WhiteListPath.values())
- .stream()
- .map(type -> new Tuple<>(
- type.key,
- this.i18nSupport.getText(SEB_RESTRICTION_WHITE_LIST_PREFIX + type.name(), type.key)))
- .sorted(RESOURCE_COMPARATOR)
- .collect(Collectors.toList());
- }
-
- public List> sebRestrictionPermissionResources() {
- return Arrays.asList(PermissionComponent.values())
- .stream()
- .map(type -> new Tuple<>(
- type.key,
- this.i18nSupport.getText(SEB_RESTRICTION_PERMISSIONS_PREFIX + type.name(), type.key)))
- .sorted(RESOURCE_COMPARATOR)
- .collect(Collectors.toList());
- }
-
- private Result> getExamConfigurationSelection() {
- return this.restService.getBuilder(GetExamConfigNodeNames.class)
- .withQueryParam(
- Entity.FILTER_ATTR_INSTITUTION,
- String.valueOf(this.currentUser.get().institutionId))
- .withQueryParam(
- ConfigurationNode.FILTER_ATTR_TYPE,
- ConfigurationType.EXAM_CONFIG.name())
- .withQueryParam(
- ConfigurationNode.FILTER_ATTR_STATUS,
- ConfigurationStatus.READY_TO_USE.name())
- .call();
- }
-
-}
+/*
+ * 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;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.EnumSet;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.function.Function;
+import java.util.function.Supplier;
+import java.util.stream.Collectors;
+
+import ch.ethz.seb.sebserver.gbl.util.Tuple3;
+import ch.ethz.seb.sebserver.gbl.util.Utils;
+import org.apache.commons.lang3.StringUtils;
+import org.joda.time.DateTimeZone;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Lazy;
+import org.springframework.stereotype.Service;
+
+import ch.ethz.seb.sebserver.gbl.Constants;
+import ch.ethz.seb.sebserver.gbl.api.API;
+import ch.ethz.seb.sebserver.gbl.api.EntityType;
+import ch.ethz.seb.sebserver.gbl.model.Activatable;
+import ch.ethz.seb.sebserver.gbl.model.Entity;
+import ch.ethz.seb.sebserver.gbl.model.EntityName;
+import ch.ethz.seb.sebserver.gbl.model.exam.Exam;
+import ch.ethz.seb.sebserver.gbl.model.exam.Exam.ExamStatus;
+import ch.ethz.seb.sebserver.gbl.model.exam.Exam.ExamType;
+import ch.ethz.seb.sebserver.gbl.model.exam.ExamConfigurationMap;
+import ch.ethz.seb.sebserver.gbl.model.exam.Indicator.IndicatorType;
+import ch.ethz.seb.sebserver.gbl.model.exam.OpenEdxSebRestriction.PermissionComponent;
+import ch.ethz.seb.sebserver.gbl.model.exam.OpenEdxSebRestriction.WhiteListPath;
+import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetup.LmsType;
+import ch.ethz.seb.sebserver.gbl.model.sebconfig.AttributeType;
+import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode;
+import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode.ConfigurationStatus;
+import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode.ConfigurationType;
+import ch.ethz.seb.sebserver.gbl.model.sebconfig.TemplateAttribute;
+import ch.ethz.seb.sebserver.gbl.model.sebconfig.View;
+import ch.ethz.seb.sebserver.gbl.model.session.ClientConnection.ConnectionStatus;
+import ch.ethz.seb.sebserver.gbl.model.session.ClientConnectionData;
+import ch.ethz.seb.sebserver.gbl.model.session.ClientEvent;
+import ch.ethz.seb.sebserver.gbl.model.session.ClientEvent.EventType;
+import ch.ethz.seb.sebserver.gbl.model.user.UserActivityLog;
+import ch.ethz.seb.sebserver.gbl.model.user.UserInfo;
+import ch.ethz.seb.sebserver.gbl.model.user.UserLogActivityType;
+import ch.ethz.seb.sebserver.gbl.model.user.UserRole;
+import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
+import ch.ethz.seb.sebserver.gbl.util.Result;
+import ch.ethz.seb.sebserver.gbl.util.Tuple;
+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.remote.webservice.api.RestService;
+import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.GetExamNames;
+import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.GetExams;
+import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.institution.GetInstitutionNames;
+import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.lmssetup.GetLmsSetupNames;
+import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.GetExamConfigNodeNames;
+import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.GetExamConfigNodes;
+import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.GetViews;
+import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.useraccount.GetUserAccountNames;
+import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.CurrentUser;
+
+@Lazy
+@Service
+@GuiProfile
+/** Defines functionality to get resources or functions of resources to feed e.g. selection or
+ * combo-box content. */
+public class ResourceService {
+
+ private static final String MISSING_CLIENT_PING_NAME_KEY = "MISSING";
+
+ public static final Comparator> RESOURCE_COMPARATOR = (t1, t2) -> t1._2.compareTo(t2._2);
+ public static final Comparator> RESOURCE_COMPARATOR_TUPLE_3 = (t1, t2) -> t1._2.compareTo(t2._2);
+
+ public static final EnumSet ENTITY_TYPE_EXCLUDE_MAP = EnumSet.of(
+ EntityType.ADDITIONAL_ATTRIBUTES,
+ EntityType.CLIENT_CONNECTION,
+ EntityType.CLIENT_EVENT,
+ EntityType.CONFIGURATION_ATTRIBUTE,
+ EntityType.CONFIGURATION_VALUE,
+ EntityType.CONFIGURATION,
+ EntityType.ORIENTATION,
+ EntityType.USER_ACTIVITY_LOG,
+ EntityType.USER_ROLE,
+ EntityType.WEBSERVICE_SERVER_INFO);
+
+ public static final EnumSet CLIENT_EVENT_TYPE_EXCLUDE_MAP = EnumSet.of(
+ EventType.LAST_PING);
+
+ public static final String EXAMCONFIG_STATUS_PREFIX = "sebserver.examconfig.status.";
+ public static final String EXAM_TYPE_PREFIX = "sebserver.exam.type.";
+ public static final String USERACCOUNT_ROLE_PREFIX = "sebserver.useraccount.role.";
+ public static final String EXAM_INDICATOR_TYPE_PREFIX = "sebserver.exam.indicator.type.";
+ public static final String LMSSETUP_TYPE_PREFIX = "sebserver.lmssetup.type.";
+ public static final String CONFIG_ATTRIBUTE_TYPE_PREFIX = "sebserver.configtemplate.attr.type.";
+ public static final String SEB_RESTRICTION_WHITE_LIST_PREFIX = "sebserver.exam.form.sebrestriction.whiteListPaths.";
+ public static final String SEB_RESTRICTION_PERMISSIONS_PREFIX = "sebserver.exam.form.sebrestriction.permissions.";
+
+ public static final EnumSet ATTRIBUTE_TYPES_NOT_DISPLAYED = EnumSet.of(
+ AttributeType.LABEL,
+ AttributeType.COMPOSITE_TABLE,
+ AttributeType.INLINE_TABLE);
+
+ public static final String CLIENT_EVENT_TYPE_PREFIX = "sebserver.monitoring.exam.connection.event.type.";
+ public static final String USER_ACTIVITY_TYPE_PREFIX = "sebserver.overall.types.activityType.";
+ public static final String ENTITY_TYPE_PREFIX = "sebserver.overall.types.entityType.";
+ public static final String SEB_CONNECTION_STATUS_KEY_PREFIX = "sebserver.monitoring.exam.connection.status.";
+ public static final LocTextKey ACTIVE_TEXT_KEY = new LocTextKey("sebserver.overall.status.active");
+ public static final LocTextKey INACTIVE_TEXT_KEY = new LocTextKey("sebserver.overall.status.inactive");
+
+ private final I18nSupport i18nSupport;
+ private final RestService restService;
+ private final CurrentUser currentUser;
+ private final boolean mock_lms_enabled;
+
+ protected ResourceService(
+ final I18nSupport i18nSupport,
+ final RestService restService,
+ final CurrentUser currentUser,
+ @Value("${sebserver.gui.webservice.mock-lms-enabled:true}") final boolean mock_lms_enabled) {
+
+ this.i18nSupport = i18nSupport;
+ this.restService = restService;
+ this.currentUser = currentUser;
+ this.mock_lms_enabled = mock_lms_enabled;
+ }
+
+ public I18nSupport getI18nSupport() {
+ return this.i18nSupport;
+ }
+
+ public RestService getRestService() {
+ return this.restService;
+ }
+
+ public CurrentUser getCurrentUser() {
+ return this.currentUser;
+ }
+
+ public Supplier>> localizedResourceSupplier(final List> source) {
+ return () -> source.stream()
+ .map(tuple -> new Tuple<>(tuple._1, this.i18nSupport.getText(tuple._2)))
+ .collect(Collectors.toList());
+ }
+
+ public List> activityResources() {
+ final List> result = new ArrayList<>();
+ result.add(new Tuple<>(Constants.TRUE_STRING, this.i18nSupport.getText("sebserver.overall.status.active")));
+ result.add(new Tuple<>(Constants.FALSE_STRING, this.i18nSupport.getText("sebserver.overall.status.inactive")));
+ result.add(new Tuple<>(StringUtils.EMPTY, this.i18nSupport.getText("sebserver.overall.status.all")));
+ return result;
+ }
+
+ public List> lmsTypeResources() {
+ return Arrays.asList(LmsType.values())
+ .stream()
+ .filter(lmsType -> lmsType != LmsType.MOCKUP || this.mock_lms_enabled)
+ .map(lmsType -> new Tuple<>(
+ lmsType.name(),
+ this.i18nSupport.getText(LMSSETUP_TYPE_PREFIX + lmsType.name(), lmsType.name())))
+ .sorted(RESOURCE_COMPARATOR)
+ .collect(Collectors.toList());
+ }
+
+ public List> clientEventTypeResources() {
+ return Arrays.asList(EventType.values())
+ .stream()
+ .filter(eventType -> !CLIENT_EVENT_TYPE_EXCLUDE_MAP.contains(eventType))
+ .map(eventType -> new Tuple<>(
+ eventType.name(),
+ getEventTypeName(eventType)))
+ .sorted(RESOURCE_COMPARATOR)
+ .collect(Collectors.toList());
+ }
+
+ public String getEventTypeName(final ClientEvent event) {
+ if (event == null) {
+ return getEventTypeName(EventType.UNKNOWN);
+ }
+ return getEventTypeName(event.eventType);
+ }
+
+ public String getEventTypeName(final EventType eventType) {
+ if (eventType == null) {
+ return Constants.EMPTY_NOTE;
+ }
+ return this.i18nSupport.getText(CLIENT_EVENT_TYPE_PREFIX + eventType.name(), eventType.name());
+ }
+
+ public List> indicatorTypeResources() {
+ return Arrays.asList(IndicatorType.values())
+ .stream()
+ .map(type -> new Tuple3<>(
+ type.name(),
+ this.i18nSupport.getText(EXAM_INDICATOR_TYPE_PREFIX + type.name(), type.name()),
+ Utils.formatLineBreaks(this.i18nSupport.getText(
+ EXAM_INDICATOR_TYPE_PREFIX + type.name() + Constants.TOOLTIP_TEXT_KEY_SUFFIX,
+ StringUtils.EMPTY))))
+ .sorted(RESOURCE_COMPARATOR_TUPLE_3)
+ .collect(Collectors.toList());
+ }
+
+ public List> examConfigurationSelectionResources() {
+ return getExamConfigurationSelection()
+ .getOr(Collections.emptyList())
+ .stream()
+ .map(entityName -> new Tuple<>(entityName.modelId, entityName.name))
+ .sorted(RESOURCE_COMPARATOR)
+ .collect(Collectors.toList());
+ }
+
+ public List> userRoleResources() {
+ return UserRole.publicRolesForUser(this.currentUser.get())
+ .stream()
+ .map(ur -> new Tuple3<>(
+ ur.name(),
+ this.i18nSupport.getText(USERACCOUNT_ROLE_PREFIX + ur.name()),
+ Utils.formatLineBreaks(this.i18nSupport.getText(
+ USERACCOUNT_ROLE_PREFIX + ur.name() + Constants.TOOLTIP_TEXT_KEY_SUFFIX,
+ StringUtils.EMPTY))))
+ .sorted(RESOURCE_COMPARATOR)
+ .collect(Collectors.toList());
+ }
+
+ public List> institutionResource() {
+ return this.restService.getBuilder(GetInstitutionNames.class)
+ .withQueryParam(Entity.FILTER_ATTR_ACTIVE, Constants.TRUE_STRING)
+ .call()
+ .getOr(Collections.emptyList())
+ .stream()
+ .map(entityName -> new Tuple<>(entityName.modelId, entityName.name))
+ .sorted(RESOURCE_COMPARATOR)
+ .collect(Collectors.toList());
+ }
+
+ public Function getInstitutionNameFunction() {
+ final Map idNameMap = this.restService.getBuilder(GetInstitutionNames.class)
+ .withQueryParam(Entity.FILTER_ATTR_ACTIVE, Constants.TRUE_STRING)
+ .call()
+ .getOr(Collections.emptyList())
+ .stream()
+ .collect(Collectors.toMap(e -> e.modelId, e -> e.name));
+
+ return id -> {
+ if (!idNameMap.containsKey(id)) {
+ return Constants.EMPTY_NOTE;
+ }
+ return idNameMap.get(id);
+ };
+ }
+
+ public List> lmsSetupResource() {
+ 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(Entity.FILTER_ATTR_INSTITUTION, institutionId)
+ .withQueryParam(Entity.FILTER_ATTR_ACTIVE, Constants.TRUE_STRING)
+ .call()
+ .getOr(Collections.emptyList())
+ .stream()
+ .map(entityName -> new Tuple<>(entityName.modelId, entityName.name))
+ .sorted(RESOURCE_COMPARATOR)
+ .collect(Collectors.toList());
+ }
+
+ public Function getLmsSetupNameFunction() {
+ final boolean isSEBAdmin = this.currentUser.get().hasRole(UserRole.SEB_SERVER_ADMIN);
+ final String institutionId = (isSEBAdmin) ? "" : String.valueOf(this.currentUser.get().institutionId);
+ final Map idNameMap = this.restService.getBuilder(GetLmsSetupNames.class)
+ .withQueryParam(Entity.FILTER_ATTR_INSTITUTION, institutionId)
+ .withQueryParam(Entity.FILTER_ATTR_ACTIVE, Constants.TRUE_STRING)
+ .call()
+ .getOr(Collections.emptyList())
+ .stream()
+ .collect(Collectors.toMap(e -> e.modelId, e -> e.name));
+
+ return id -> {
+ if (!idNameMap.containsKey(id)) {
+ return Constants.EMPTY_NOTE;
+ }
+ return idNameMap.get(id);
+ };
+ }
+
+ public List> entityTypeResources() {
+ return Arrays.asList(EntityType.values())
+ .stream()
+ .filter(type -> !ENTITY_TYPE_EXCLUDE_MAP.contains(type))
+ .map(type -> new Tuple<>(type.name(), getEntityTypeName(type)))
+ .sorted(RESOURCE_COMPARATOR)
+ .collect(Collectors.toList());
+ }
+
+ public static LocTextKey getEntityTypeNameKey(final EntityType type) {
+ return new LocTextKey(ENTITY_TYPE_PREFIX + type.name());
+ }
+
+ public String getEntityTypeName(final EntityType type) {
+ if (type == null) {
+ return Constants.EMPTY_NOTE;
+ }
+ return this.i18nSupport.getText(getEntityTypeNameKey(type));
+ }
+
+ public String getEntityTypeName(final UserActivityLog userLog) {
+ return getEntityTypeName(userLog.entityType);
+ }
+
+ public List> userActivityTypeResources() {
+ return Arrays.asList(UserLogActivityType.values())
+ .stream()
+ .map(type -> new Tuple<>(type.name(), getUserActivityTypeName(type)))
+ .sorted(RESOURCE_COMPARATOR)
+ .collect(Collectors.toList());
+ }
+
+ public String getUserActivityTypeName(final UserLogActivityType type) {
+ if (type == null) {
+ return Constants.EMPTY_NOTE;
+ }
+ return this.i18nSupport.getText(USER_ACTIVITY_TYPE_PREFIX + type.name());
+ }
+
+ public String getUserActivityTypeName(final UserActivityLog userLog) {
+ return getUserActivityTypeName(userLog.activityType);
+ }
+
+ /** Get a list of language key/name tuples for all supported languages in the
+ * language of the current users locale.
+ *
+ * @return list of language key/name tuples for all supported languages in the language of the current users
+ * locale */
+ public List> languageResources() {
+ final Locale currentLocale = this.i18nSupport.getUsersLanguageLocale();
+ return this.i18nSupport.supportedLanguages()
+ .stream()
+ .map(locale -> new Tuple<>(locale.toLanguageTag(), locale.getDisplayLanguage(currentLocale)))
+ .filter(tuple -> StringUtils.isNotBlank(tuple._2))
+ .sorted(RESOURCE_COMPARATOR)
+ .collect(Collectors.toList());
+ }
+
+ public List> timeZoneResources() {
+ final Locale currentLocale = this.i18nSupport.getUsersLanguageLocale();
+ return DateTimeZone
+ .getAvailableIDs()
+ .stream()
+ .map(id -> new Tuple<>(id, id + " (" + DateTimeZone.forID(id).getName(0, currentLocale) + ")"))
+ .sorted(RESOURCE_COMPARATOR)
+ .collect(Collectors.toList());
+ }
+
+ public List> examTypeResources() {
+ return Arrays.asList(ExamType.values())
+ .stream()
+ .filter(type -> type != ExamType.UNDEFINED)
+ .map(type -> new Tuple3<>(
+ type.name(),
+ this.i18nSupport.getText(EXAM_TYPE_PREFIX + type.name()),
+ Utils.formatLineBreaks(this.i18nSupport.getText(
+ this.i18nSupport.getText(EXAM_TYPE_PREFIX + type.name()) + Constants.TOOLTIP_TEXT_KEY_SUFFIX,
+ StringUtils.EMPTY))
+ ))
+ .sorted(RESOURCE_COMPARATOR)
+ .collect(Collectors.toList());
+ }
+
+ public List> examConfigStatusResources() {
+ return examConfigStatusResources(false);
+ }
+
+ public List> examConfigStatusResources(final boolean isAttachedToExam) {
+ return Arrays.asList(ConfigurationStatus.values())
+ .stream()
+ .filter(status -> {
+ if (isAttachedToExam) {
+ return status != ConfigurationStatus.READY_TO_USE;
+ } else {
+ return status != ConfigurationStatus.IN_USE;
+ }
+ })
+ .map(type -> new Tuple3<>(
+ type.name(),
+ this.i18nSupport.getText(EXAMCONFIG_STATUS_PREFIX + type.name()),
+ Utils.formatLineBreaks(this.i18nSupport.getText(
+ this.i18nSupport.getText(EXAMCONFIG_STATUS_PREFIX + type.name()) + Constants.TOOLTIP_TEXT_KEY_SUFFIX,
+ StringUtils.EMPTY))
+ ))
+ .sorted(RESOURCE_COMPARATOR)
+ .collect(Collectors.toList());
+ }
+
+ public List> examSupporterResources() {
+ final UserInfo userInfo = this.currentUser.get();
+ final List selection = 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());
+ return selection
+ .stream()
+ .map(entityName -> new Tuple<>(entityName.modelId, entityName.name))
+ .sorted(RESOURCE_COMPARATOR)
+ .collect(Collectors.toList());
+ }
+
+ public List> userResources() {
+ 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)
+ .call()
+ .getOr(Collections.emptyList())
+ .stream()
+ .map(entityName -> new Tuple<>(entityName.modelId, entityName.name))
+ .sorted(RESOURCE_COMPARATOR)
+ .collect(Collectors.toList());
+ }
+
+ public Function localizedActivityFunction() {
+ final Function localizedActivityResource = localizedActivityResource();
+ return activatable -> localizedActivityResource.apply(activatable.isActive());
+ }
+
+ public Function localizedActivityResource() {
+ return activity -> activity
+ ? this.i18nSupport.getText(ACTIVE_TEXT_KEY)
+ : this.i18nSupport.getText(INACTIVE_TEXT_KEY);
+ }
+
+ public String localizedExamConfigInstitutionName(final ConfigurationNode config) {
+ return getInstitutionNameFunction()
+ .apply(String.valueOf(config.institutionId));
+ }
+
+ public String localizedExamConfigStatusName(final ConfigurationNode config) {
+ if (config.status == null) {
+ return Constants.EMPTY_NOTE;
+ }
+
+ return this.i18nSupport
+ .getText(ResourceService.EXAMCONFIG_STATUS_PREFIX + config.status.name());
+ }
+
+ public String localizedExamConfigStatusName(final ExamConfigurationMap config) {
+ if (config.configStatus == null) {
+ return Constants.EMPTY_NOTE;
+ }
+
+ return this.i18nSupport
+ .getText(ResourceService.EXAMCONFIG_STATUS_PREFIX + config.configStatus.name());
+ }
+
+ public String localizedClientConnectionStatusName(final ClientConnectionData connectionData) {
+ if (connectionData == null) {
+ final String name = ConnectionStatus.UNDEFINED.name();
+ return this.i18nSupport.getText(
+ SEB_CONNECTION_STATUS_KEY_PREFIX + name,
+ name);
+ }
+ if (connectionData.missingPing) {
+ return this.i18nSupport.getText(
+ SEB_CONNECTION_STATUS_KEY_PREFIX + MISSING_CLIENT_PING_NAME_KEY,
+ MISSING_CLIENT_PING_NAME_KEY);
+ } else {
+ return localizedClientConnectionStatusName((connectionData.clientConnection != null)
+ ? connectionData.clientConnection.status
+ : ConnectionStatus.UNDEFINED);
+ }
+ }
+
+ public String localizedClientConnectionStatusName(final ConnectionStatus status) {
+ String name;
+ if (status != null) {
+ name = status.name();
+ } else {
+ name = ConnectionStatus.UNDEFINED.name();
+ }
+ return this.i18nSupport
+ .getText(SEB_CONNECTION_STATUS_KEY_PREFIX + name, name);
+ }
+
+ public String localizedExamTypeName(final ExamConfigurationMap examMap) {
+ if (examMap.examType == null) {
+ return Constants.EMPTY_NOTE;
+ }
+
+ return this.i18nSupport
+ .getText(ResourceService.EXAM_TYPE_PREFIX + examMap.examType.name());
+ }
+
+ public String localizedExamTypeName(final Exam exam) {
+ if (exam.type == null) {
+ return Constants.EMPTY_NOTE;
+ }
+
+ return this.i18nSupport
+ .getText(ResourceService.EXAM_TYPE_PREFIX + exam.type.name());
+ }
+
+ public List> getExamLogSelectionResources() {
+ final UserInfo userInfo = this.currentUser.get();
+ return this.restService.getBuilder(GetExams.class)
+ .withQueryParam(Entity.FILTER_ATTR_INSTITUTION, String.valueOf(userInfo.getInstitutionId()))
+ .withQueryParam(Exam.FILTER_CACHED_QUIZZES, Constants.TRUE_STRING)
+ .call()
+ .getOr(Collections.emptyList())
+ .stream()
+ .filter(exam -> exam != null
+ && (exam.getStatus() == ExamStatus.RUNNING || exam.getStatus() == ExamStatus.FINISHED))
+ .map(exam -> new Tuple<>(exam.getModelId(), exam.name))
+ .sorted(RESOURCE_COMPARATOR)
+ .collect(Collectors.toList());
+ }
+
+ public List> getExamResources() {
+ final UserInfo userInfo = this.currentUser.get();
+ return this.restService.getBuilder(GetExamNames.class)
+ .withQueryParam(Entity.FILTER_ATTR_INSTITUTION, String.valueOf(userInfo.getInstitutionId()))
+ .withQueryParam(Exam.FILTER_CACHED_QUIZZES, Constants.TRUE_STRING)
+ .call()
+ .getOr(Collections.emptyList())
+ .stream()
+ .map(entityName -> new Tuple<>(entityName.modelId, entityName.name))
+ .sorted(RESOURCE_COMPARATOR)
+ .collect(Collectors.toList());
+ }
+
+ public Map getExamNameMapping() {
+ final UserInfo userInfo = this.currentUser.get();
+ return this.restService.getBuilder(GetExamNames.class)
+ .withQueryParam(Entity.FILTER_ATTR_INSTITUTION, String.valueOf(userInfo.getInstitutionId()))
+ .withQueryParam(Exam.FILTER_CACHED_QUIZZES, Constants.TRUE_STRING)
+ .call()
+ .getOr(Collections.emptyList())
+ .stream()
+ .filter(k -> StringUtils.isNotBlank(k.modelId))
+ .collect(Collectors.toMap(
+ k -> Long.valueOf(k.modelId),
+ k -> k.name));
+ }
+
+ public List> getViewResources() {
+ return getViewResources(API.DEFAULT_CONFIG_TEMPLATE_ID);
+ }
+
+ public List> getViewResources(final String templateId) {
+ return this.restService.getBuilder(GetViews.class)
+ .withQueryParam(
+ View.FILTER_ATTR_TEMPLATE,
+ templateId)
+ .call()
+ .getOr(Collections.emptyList())
+ .stream()
+ .map(view -> new Tuple<>(view.getModelId(), view.name))
+ .sorted(RESOURCE_COMPARATOR)
+ .collect(Collectors.toList());
+ }
+
+ public final Function getViewNameFunction(final String templateId) {
+ final Map mapping = this.getViewResources(templateId)
+ .stream()
+ .collect(Collectors.toMap(tuple -> tuple._1, tuple -> tuple._2));
+
+ return attr -> mapping.get(attr.getViewModelId());
+ }
+
+ public List> getAttributeTypeResources() {
+ return Arrays.asList(AttributeType.values())
+ .stream()
+ .filter(type -> !ATTRIBUTE_TYPES_NOT_DISPLAYED.contains(type))
+ .map(type -> new Tuple<>(getAttributeTypeFilterName(type), getAttributeTypeName(type)))
+ .sorted(RESOURCE_COMPARATOR)
+ .collect(Collectors.toList());
+ }
+
+ public String getAttributeTypeName(final TemplateAttribute attribute) {
+ if (attribute != null && attribute.getConfigAttribute() != null) {
+ return getAttributeTypeName(attribute.getConfigAttribute().type);
+ }
+
+ return Constants.EMPTY_NOTE;
+ }
+
+ private String getAttributeTypeFilterName(final AttributeType type) {
+ if (type == AttributeType.TABLE) {
+ return type.name()
+ + Constants.LIST_SEPARATOR
+ + AttributeType.COMPOSITE_TABLE.name()
+ + Constants.LIST_SEPARATOR
+ + AttributeType.INLINE_TABLE.name();
+ } else {
+ return type.name();
+ }
+ }
+
+ public String getAttributeTypeName(final AttributeType type) {
+ if (type == null) {
+ return Constants.EMPTY_NOTE;
+ }
+ return this.i18nSupport
+ .getText(CONFIG_ATTRIBUTE_TYPE_PREFIX + type.name());
+ }
+
+ public List> getExamConfigTemplateResources() {
+ final UserInfo userInfo = this.currentUser.get();
+ return this.restService.getBuilder(GetExamConfigNodes.class)
+ .withQueryParam(Entity.FILTER_ATTR_INSTITUTION, String.valueOf(userInfo.getInstitutionId()))
+ .withQueryParam(ConfigurationNode.FILTER_ATTR_TYPE, ConfigurationType.TEMPLATE.name())
+ .call()
+ .getOr(Collections.emptyList())
+ .stream()
+ .map(node -> new Tuple<>(node.getModelId(), node.name))
+ .sorted(RESOURCE_COMPARATOR)
+ .collect(Collectors.toList());
+ }
+
+ public List> sebRestrictionWhiteListResources() {
+ return Arrays.asList(WhiteListPath.values())
+ .stream()
+ .map(type -> new Tuple<>(
+ type.key,
+ this.i18nSupport.getText(SEB_RESTRICTION_WHITE_LIST_PREFIX + type.name(), type.key)))
+ .sorted(RESOURCE_COMPARATOR)
+ .collect(Collectors.toList());
+ }
+
+ public List> sebRestrictionPermissionResources() {
+ return Arrays.asList(PermissionComponent.values())
+ .stream()
+ .map(type -> new Tuple<>(
+ type.key,
+ this.i18nSupport.getText(SEB_RESTRICTION_PERMISSIONS_PREFIX + type.name(), type.key)))
+ .sorted(RESOURCE_COMPARATOR)
+ .collect(Collectors.toList());
+ }
+
+ private Result> getExamConfigurationSelection() {
+ return this.restService.getBuilder(GetExamConfigNodeNames.class)
+ .withQueryParam(
+ Entity.FILTER_ATTR_INSTITUTION,
+ String.valueOf(this.currentUser.get().institutionId))
+ .withQueryParam(
+ ConfigurationNode.FILTER_ATTR_TYPE,
+ ConfigurationType.EXAM_CONFIG.name())
+ .withQueryParam(
+ ConfigurationNode.FILTER_ATTR_STATUS,
+ ConfigurationStatus.READY_TO_USE.name())
+ .call();
+ }
+
+}
diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/i18n/I18nSupport.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/i18n/I18nSupport.java
index f94d4f33..1376f307 100644
--- a/src/main/java/ch/ethz/seb/sebserver/gui/service/i18n/I18nSupport.java
+++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/i18n/I18nSupport.java
@@ -1,181 +1,186 @@
-/*
- * Copyright (c) 2018 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.i18n;
-
-import java.util.Collection;
-import java.util.Locale;
-
-import org.joda.time.DateTime;
-
-import ch.ethz.seb.sebserver.gbl.util.Utils;
-
-public interface I18nSupport {
-
- public static final String SUPPORTED_LANGUAGES_KEY = "sebserver.gui.supported.languages";
- public static final String MULTILINGUAL_KEY = "sebserver.gui.multilingual";
- public static final String FORMAL_LOCALE_KEY = "sebserver.gui.date.displayformat";
- public static final String ATTR_CURRENT_SESSION_LOCALE = "CURRENT_SESSION_LOCALE";
-
- /** Get all supported languages as a collection of Locale
- *
- * @return all supported languages as a collection of Locale */
- Collection supportedLanguages();
-
- /** Get the current users language based Locale (from user info language selection)
- * Or the default language Locale if the user has not defined any language
- *
- * @return the current user language Locale to use in context */
- Locale getUsersLanguageLocale();
-
- /** Get the current users format based Locale (from user info format selection)
- * Or the default format Locale if the user has not defined any language
- *
- * @return the current user format Locale to use in context */
- Locale getUsersFormatLocale();
-
- /** Format a DateTime to a text format to display.
- * This uses the date-format defined by either the attribute 'sebserver.gui.date.displayformat'
- * or the Constants.DEFAULT_DISPLAY_DATE_FORMAT
- *
- * Adds time-zone offset information if the currents user time-zone is different form UTC
- *
- * @param date the DateTime instance
- * @return date formatted date String to display */
- String formatDisplayDate(DateTime date);
-
- /** Format a DateTime to a text format to display with additional time zone name at the end.
- * This uses the date-format defined by either the attribute 'sebserver.gui.date.displayformat'
- * or the Constants.DEFAULT_DISPLAY_DATE_FORMAT
- *
- * Adds time-zone offset information if the currents user time-zone is different form UTC
- *
- * @param date the DateTime instance
- * @return date formatted date String to display */
- default String formatDisplayDateWithTimeZone(final DateTime date) {
- return formatDisplayDateTime(date) + " " + this.getUsersTimeZoneTitleSuffix();
- }
-
- /** Format a time-stamp (milliseconds) to a text format to display.
- * This uses the date-format defined by either the attribute 'sebserver.gui.date.displayformat'
- * or the Constants.DEFAULT_DISPLAY_DATE_FORMAT
- *
- * Adds time-zone information if the currents user time-zone is different form UTC
- *
- * @param date the DateTime instance
- * @return date formatted date String to display */
- default String formatDisplayDate(final Long timestamp) {
- return formatDisplayDate(Utils.toDateTimeUTC(timestamp));
- }
-
- /** Format a DateTime to a text format to display.
- * This uses the date-format defined by either the attribute 'sebserver.gui.datetime.displayformat'
- * or the Constants.DEFAULT_DISPLAY_DATE_TIME_FORMAT
- *
- * Adds time-zone information if the currents user time-zone is different form UTC
- *
- * @param date the DateTime instance
- * @return date formatted date time String to display */
- String formatDisplayDateTime(DateTime date);
-
- /** Format a time-stamp (milliseconds) to a text format to display.
- * This uses the date-format defined by either the attribute 'sebserver.gui.datetime.displayformat'
- * or the Constants.DEFAULT_DISPLAY_DATE_TIME_FORMAT
- *
- * Adds time-zone information if the currents user time-zone is different form UTC
- *
- * @param date the DateTime instance
- * @return date formatted date time String to display */
- default String formatDisplayDateTime(final Long timestamp) {
- return formatDisplayDateTime(Utils.toDateTimeUTC(timestamp));
- }
-
- /** Format a DateTime to a text format to display.
- * This uses the date-format defined by either the attribute 'sebserver.gui.time.displayformat'
- * or the Constants.DEFAULT_DISPLAY_TIME_FORMAT
- *
- * Adds time-zone information if the currents user time-zone is different form UTC
- *
- * @param date the DateTime instance
- * @return date formatted time String to display */
- String formatDisplayTime(DateTime date);
-
- /** Format a time-stamp (milliseconds) to a text format to display.
- * This uses the date-format defined by either the attribute 'sebserver.gui.time.displayformat'
- * or the Constants.DEFAULT_DISPLAY_TIME_FORMAT
- *
- * Adds time-zone information if the currents user time-zone is different form UTC
- *
- * @param date the DateTime instance
- * @return date formatted time String to display */
- default String formatDisplayTime(final Long timestamp) {
- return formatDisplayTime(Utils.toDateTimeUTC(timestamp));
- }
-
- /** If the current user has another time zone then UTC this will return a tile suffix that describes
- * a date/time column title with adding (UTC|{usersTimeZone}) that can be added to the title.
- *
- * @return date/time column title suffix for current user */
- String getUsersTimeZoneTitleSuffix();
-
- /** Get localized text of specified key for currently set Locale.
- *
- * @param key LocTextKey instance
- * @param def default text
- * @return the text in current language parsed from localized text */
- default String getText(final LocTextKey key, final String def) {
- return getText(key.name, def, key.args);
- }
-
- /** Get localized text of specified key for currently set Locale.
- *
- * @param key LocTextKey instance
- * @return the text in current language parsed from localized text */
- default String getText(final LocTextKey key) {
- return getText(key.name, key.name, key.args);
- }
-
- /** Get localized text of specified key for currently set Locale.
- *
- * @param key the key name of localized text
- * @param args additional arguments to parse the localized text
- * @return the text in current language parsed from localized text */
- default String getText(final String key, final Object... args) {
- return getText(key, key, args);
- }
-
- /** Get localized text of specified key for currently set Locale.
- *
- * @param key the key name of localized text
- * @param def default text that is returned if no localized test with specified key was found
- * @param args additional arguments to parse the localized text
- * @return the text in current language parsed from localized text */
- String getText(final String key, String def, Object... args);
-
- /** Get localized text of specified key and Locale.
- *
- * @param key the key name of localized text
- * @param locale the Locale
- * @param args additional arguments to parse the localized text
- * @return the text in current language parsed from localized text */
- default String getText(final String key, final Locale locale, final Object... args) {
- return getText(key, locale, key, args);
- }
-
- /** Get localized text of specified key and Locale.
- *
- * @param key the key name of localized text
- * @param locale the Locale
- * @param def default text that is returned if no localized test with specified key was found
- * @param args additional arguments to parse the localized text
- * @return the text in current language parsed from localized text */
- String getText(String key, Locale locale, String def, Object... args);
-
- boolean hasText(LocTextKey locTextKey);
-
-}
+/*
+ * Copyright (c) 2018 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.i18n;
+
+import java.util.Collection;
+import java.util.Locale;
+
+import org.joda.time.DateTime;
+
+import ch.ethz.seb.sebserver.gbl.util.Utils;
+
+public interface I18nSupport {
+
+ public static final String SUPPORTED_LANGUAGES_KEY = "sebserver.gui.supported.languages";
+ public static final String MULTILINGUAL_KEY = "sebserver.gui.multilingual";
+ public static final String FORMAL_LOCALE_KEY = "sebserver.gui.date.displayformat";
+ public static final String ATTR_CURRENT_SESSION_LOCALE = "CURRENT_SESSION_LOCALE";
+
+ /** Get all supported languages as a collection of Locale
+ *
+ * @return all supported languages as a collection of Locale */
+ Collection supportedLanguages();
+
+ /** Get the current users language based Locale (from user info language selection)
+ * Or the default language Locale if the user has not defined any language
+ *
+ * @return the current user language Locale to use in context */
+ Locale getUsersLanguageLocale();
+
+ /** Get the current users format based Locale (from user info format selection)
+ * Or the default format Locale if the user has not defined any language
+ *
+ * @return the current user format Locale to use in context */
+ Locale getUsersFormatLocale();
+
+ /** Format a DateTime to a text format to display.
+ * This uses the date-format defined by either the attribute 'sebserver.gui.date.displayformat'
+ * or the Constants.DEFAULT_DISPLAY_DATE_FORMAT
+ *
+ * Adds time-zone offset information if the currents user time-zone is different form UTC
+ *
+ * @param date the DateTime instance
+ * @return date formatted date String to display */
+ String formatDisplayDate(DateTime date);
+
+ /** Format a DateTime to a text format to display with additional time zone name at the end.
+ * This uses the date-format defined by either the attribute 'sebserver.gui.date.displayformat'
+ * or the Constants.DEFAULT_DISPLAY_DATE_FORMAT
+ *
+ * Adds time-zone offset information if the currents user time-zone is different form UTC
+ *
+ * @param date the DateTime instance
+ * @return date formatted date String to display */
+ default String formatDisplayDateWithTimeZone(final DateTime date) {
+ return formatDisplayDateTime(date) + " " + this.getUsersTimeZoneTitleSuffix();
+ }
+
+ /** Format a time-stamp (milliseconds) to a text format to display.
+ * This uses the date-format defined by either the attribute 'sebserver.gui.date.displayformat'
+ * or the Constants.DEFAULT_DISPLAY_DATE_FORMAT
+ *
+ * Adds time-zone information if the currents user time-zone is different form UTC
+ *
+ * @param date the DateTime instance
+ * @return date formatted date String to display */
+ default String formatDisplayDate(final Long timestamp) {
+ return formatDisplayDate(Utils.toDateTimeUTC(timestamp));
+ }
+
+ /** Format a DateTime to a text format to display.
+ * This uses the date-format defined by either the attribute 'sebserver.gui.datetime.displayformat'
+ * or the Constants.DEFAULT_DISPLAY_DATE_TIME_FORMAT
+ *
+ * Adds time-zone information if the currents user time-zone is different form UTC
+ *
+ * @param date the DateTime instance
+ * @return date formatted date time String to display */
+ String formatDisplayDateTime(DateTime date);
+
+ /** Format a time-stamp (milliseconds) to a text format to display.
+ * This uses the date-format defined by either the attribute 'sebserver.gui.datetime.displayformat'
+ * or the Constants.DEFAULT_DISPLAY_DATE_TIME_FORMAT
+ *
+ * Adds time-zone information if the currents user time-zone is different form UTC
+ *
+ * @param date the DateTime instance
+ * @return date formatted date time String to display */
+ default String formatDisplayDateTime(final Long timestamp) {
+ return formatDisplayDateTime(Utils.toDateTimeUTC(timestamp));
+ }
+
+ /** Format a DateTime to a text format to display.
+ * This uses the date-format defined by either the attribute 'sebserver.gui.time.displayformat'
+ * or the Constants.DEFAULT_DISPLAY_TIME_FORMAT
+ *
+ * Adds time-zone information if the currents user time-zone is different form UTC
+ *
+ * @param date the DateTime instance
+ * @return date formatted time String to display */
+ String formatDisplayTime(DateTime date);
+
+ /** Format a time-stamp (milliseconds) to a text format to display.
+ * This uses the date-format defined by either the attribute 'sebserver.gui.time.displayformat'
+ * or the Constants.DEFAULT_DISPLAY_TIME_FORMAT
+ *
+ * Adds time-zone information if the currents user time-zone is different form UTC
+ *
+ * @param date the DateTime instance
+ * @return date formatted time String to display */
+ default String formatDisplayTime(final Long timestamp) {
+ return formatDisplayTime(Utils.toDateTimeUTC(timestamp));
+ }
+
+ /** If the current user has another time zone then UTC this will return a tile suffix that describes
+ * a date/time column title with adding (UTC|{usersTimeZone}) that can be added to the title.
+ *
+ * @return date/time column title suffix for current user */
+ String getUsersTimeZoneTitleSuffix();
+
+ /** Get localized text of specified key for currently set Locale.
+ *
+ * @param key LocTextKey instance
+ * @param def default text
+ * @return the text in current language parsed from localized text */
+ default String getText(final LocTextKey key, final String def) {
+ return getText(key.name, def, key.args);
+ }
+
+ /** Get localized text of specified key for currently set Locale.
+ *
+ * @param key LocTextKey instance
+ * @return the text in current language parsed from localized text */
+ default String getText(final LocTextKey key) {
+ return getText(key.name, key.name, key.args);
+ }
+
+ /** Get localized text of specified key for currently set Locale.
+ *
+ * @param key the key name of localized text
+ * @param args additional arguments to parse the localized text
+ * @return the text in current language parsed from localized text */
+ default String getText(final String key, final Object... args) {
+ return getText(key, key, args);
+ }
+
+ /** Get localized text of specified key for currently set Locale.
+ *
+ * @param key the key name of localized text
+ * @param def default text that is returned if no localized test with specified key was found
+ * @param args additional arguments to parse the localized text
+ * @return the text in current language parsed from localized text */
+ String getText(final String key, String def, Object... args);
+
+ /** Get localized text of specified key and Locale.
+ *
+ * @param key the key name of localized text
+ * @param locale the Locale
+ * @param args additional arguments to parse the localized text
+ * @return the text in current language parsed from localized text */
+ default String getText(final String key, final Locale locale, final Object... args) {
+ return getText(key, locale, key, args);
+ }
+
+ /** Get localized text of specified key and Locale.
+ *
+ * @param key the key name of localized text
+ * @param locale the Locale
+ * @param def default text that is returned if no localized test with specified key was found
+ * @param args additional arguments to parse the localized text
+ * @return the text in current language parsed from localized text */
+ String getText(String key, Locale locale, String def, Object... args);
+
+ /** Indicates if there is a localized text defined for a specified LocTextKey
+ *
+ * @param locTextKey the LocTextKey instance
+ * @return true if there is a localized text defined for a specified LocTextKey, false otherwise
+ */
+ boolean hasText(LocTextKey locTextKey);
+
+}
diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/i18n/impl/PolyglotPageServiceImpl.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/i18n/impl/PolyglotPageServiceImpl.java
index b37c1b37..3e3d5a5d 100644
--- a/src/main/java/ch/ethz/seb/sebserver/gui/service/i18n/impl/PolyglotPageServiceImpl.java
+++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/i18n/impl/PolyglotPageServiceImpl.java
@@ -1,296 +1,294 @@
-/*
- * Copyright (c) 2018 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.i18n.impl;
-
-import java.util.Locale;
-import java.util.function.Consumer;
-
-import org.apache.commons.lang3.StringUtils;
-import org.eclipse.rap.rwt.RWT;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.widgets.Button;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Control;
-import org.eclipse.swt.widgets.Group;
-import org.eclipse.swt.widgets.Label;
-import org.eclipse.swt.widgets.TabFolder;
-import org.eclipse.swt.widgets.TabItem;
-import org.eclipse.swt.widgets.Table;
-import org.eclipse.swt.widgets.TableColumn;
-import org.eclipse.swt.widgets.TableItem;
-import org.eclipse.swt.widgets.Tree;
-import org.eclipse.swt.widgets.TreeItem;
-import org.springframework.context.annotation.Lazy;
-import org.springframework.stereotype.Service;
-
-import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
-import ch.ethz.seb.sebserver.gbl.util.Utils;
-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.i18n.PolyglotPageService;
-import ch.ethz.seb.sebserver.gui.service.page.ComposerService;
-import ch.ethz.seb.sebserver.gui.service.page.PageContext;
-import ch.ethz.seb.sebserver.gui.widget.ImageUploadSelection;
-
-/** Service that supports page language change on the fly */
-@Lazy
-@Service
-@GuiProfile
-public final class PolyglotPageServiceImpl implements PolyglotPageService {
-
- private final I18nSupport i18nSupport;
-
- public PolyglotPageServiceImpl(final I18nSupport i18nSupport) {
- this.i18nSupport = i18nSupport;
- }
-
- @Override
- public I18nSupport getI18nSupport() {
- return this.i18nSupport;
- }
-
- @Override
- public void setDefaultPageLocale(final Composite root) {
- setPageLocale(root, this.i18nSupport.getUsersLanguageLocale());
- }
-
- @Override
- @SuppressWarnings("unchecked")
- public void setPageLocale(final Composite root, final Locale locale) {
- RWT.getUISession()
- .getHttpSession()
- .setAttribute(I18nSupport.ATTR_CURRENT_SESSION_LOCALE, locale);
-
- ComposerService.traversePageTree(
- root,
- comp -> comp.getData(POLYGLOT_WIDGET_FUNCTION_KEY) != null,
- comp -> ((Consumer) comp.getData(POLYGLOT_WIDGET_FUNCTION_KEY)).accept(comp));
-
- root.layout(true, true);
- }
-
- @Override
- public void injectI18n(final ImageUploadSelection imageUpload, final LocTextKey locTextKey) {
- final Consumer imageUploadFunction = iu -> {
- if (locTextKey != null) {
- iu.setSelectionText(this.i18nSupport.getText(locTextKey));
- }
- };
- imageUpload.setData(POLYGLOT_WIDGET_FUNCTION_KEY, imageUploadFunction);
- imageUploadFunction.accept(imageUpload);
- }
-
- @Override
- public void injectI18n(final Label label, final LocTextKey locTextKey) {
- injectI18n(label, locTextKey, null);
- }
-
- @Override
- public void injectI18n(final Label label, final LocTextKey locTextKey, final LocTextKey locToolTipKey) {
- final Consumer