SEBSERV-27 #Institution Form and actions, refactoring
This commit is contained in:
parent
5a9b85ccde
commit
377df32f72
61 changed files with 1222 additions and 190 deletions
13
pom.xml
13
pom.xml
|
@ -152,10 +152,10 @@
|
|||
<includes>
|
||||
<include>ch/ethz/seb/sebserver/*</include>
|
||||
</includes>
|
||||
<!-- <excludes> -->
|
||||
<!-- <exclude>ch/ethz/seb/sebserver/webservice/datalayer/batis/mapper/*</exclude> -->
|
||||
<!-- <exclude>ch/ethz/seb/sebserver/webservice/datalayer/batis/model/*</exclude> -->
|
||||
<!-- </excludes> -->
|
||||
<!-- <excludes> -->
|
||||
<!-- <exclude>ch/ethz/seb/sebserver/webservice/datalayer/batis/mapper/*</exclude> -->
|
||||
<!-- <exclude>ch/ethz/seb/sebserver/webservice/datalayer/batis/model/*</exclude> -->
|
||||
<!-- </excludes> -->
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
|
@ -270,6 +270,11 @@
|
|||
<artifactId>org.eclipse.rap.rwt</artifactId>
|
||||
<version>3.5.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.rap</groupId>
|
||||
<artifactId>org.eclipse.rap.fileupload</artifactId>
|
||||
<version>3.7.0</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Misc -->
|
||||
<dependency>
|
||||
|
|
|
@ -12,6 +12,21 @@ import org.springframework.boot.SpringApplication;
|
|||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.autoconfigure.security.servlet.UserDetailsServiceAutoConfiguration;
|
||||
|
||||
/** SEB-Server (Safe Exam Browser Server) is a server component to maintain and support
|
||||
* Exams running with SEB (Safe Exam Browser). TODO add link(s)
|
||||
*
|
||||
* SEB-Server uses Spring Boot as main framework is divided into two main components,
|
||||
* a webservice component that implements the business logic, persistence management
|
||||
* and defines a REST API to expose the services over HTTP. The second component is a
|
||||
* GUI component built on RAP RWT/SWT that also uses Spring components to connect and use
|
||||
* the webservice over HTTP. The two components are (implementation-wise) completely separated
|
||||
* from each other by the Rest API and the webservice can also be used by another client.
|
||||
* SEB-Server uses Spring's profiles to consequently separate sub-components of the webservice
|
||||
* and GUI and can be used to start the components on separate servers or within the same
|
||||
* server instance. Additional to the usual profiles like dev, prod, test there are combining
|
||||
* profiles like dev-ws, dev-gui and prod-ws, prod-gui
|
||||
*
|
||||
* TODO documentation for presets to start all-in-one server or separated gui- and webservice- server */
|
||||
@SpringBootApplication(exclude = {
|
||||
// OAuth2ResourceServerAutoConfiguration.class,
|
||||
UserDetailsServiceAutoConfiguration.class,
|
||||
|
|
|
@ -34,4 +34,9 @@ public class API {
|
|||
|
||||
public static final String INACTIVE_SUFFIX = "/inactive";
|
||||
|
||||
public static final String PATH_VAR_MODEL_ID_NAME = "modelId";
|
||||
public static final String PATH_VAR_MODEL_ID = "/{" + PATH_VAR_MODEL_ID_NAME + "}";
|
||||
public static final String PATH_VAR_ACTIVE = PATH_VAR_MODEL_ID + ACTIVE_SUFFIX;
|
||||
public static final String PATH_VAR_INACTIVE = PATH_VAR_MODEL_ID + INACTIVE_SUFFIX;
|
||||
|
||||
}
|
||||
|
|
|
@ -8,14 +8,20 @@
|
|||
|
||||
package ch.ethz.seb.sebserver.gbl.api;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLDecoder;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.apache.commons.lang3.BooleanUtils;
|
||||
import org.joda.time.DateTime;
|
||||
import org.joda.time.DateTimeZone;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.util.Utils;
|
||||
|
@ -26,7 +32,23 @@ public class POSTMapper {
|
|||
|
||||
public POSTMapper(final MultiValueMap<String, String> params) {
|
||||
super();
|
||||
this.params = params;
|
||||
this.params = new LinkedMultiValueMap<>();
|
||||
if (params != null) {
|
||||
for (final Map.Entry<String, List<String>> entry : params.entrySet()) {
|
||||
this.params.put(
|
||||
entry.getKey(),
|
||||
entry.getValue()
|
||||
.stream()
|
||||
.map(encoded -> {
|
||||
try {
|
||||
return URLDecoder.decode(encoded, "UTF-8");
|
||||
} catch (final UnsupportedEncodingException e) {
|
||||
return encoded;
|
||||
}
|
||||
})
|
||||
.collect(Collectors.toList()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public String getString(final String name) {
|
||||
|
@ -117,4 +139,10 @@ public class POSTMapper {
|
|||
return Utils.toDateTime(value);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T extends POSTMapper> T putIfAbsent(final String name, final String value) {
|
||||
this.params.putIfAbsent(name, Arrays.asList(value));
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
/*
|
||||
* Copyright (c) 2019 ETH Zürich, Educational Development and Technology (LET)
|
||||
*
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package ch.ethz.seb.sebserver.gui.service.page.content;
|
||||
package ch.ethz.seb.sebserver.gbl.authorization;
|
||||
|
||||
public class Institution {
|
||||
public class EntityPrivileges {
|
||||
|
||||
}
|
|
@ -6,7 +6,7 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package ch.ethz.seb.sebserver.webservice.servicelayer.authorization;
|
||||
package ch.ethz.seb.sebserver.gbl.authorization;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.model.EntityType;
|
||||
import ch.ethz.seb.sebserver.gbl.model.user.UserRole;
|
||||
|
@ -15,6 +15,8 @@ import ch.ethz.seb.sebserver.gbl.model.user.UserRole;
|
|||
* institutional rights and ownershipRights. */
|
||||
public final class Privilege {
|
||||
|
||||
/** The RoleTypeKey defining the UserRole and EntityType for this Privilege */
|
||||
public final RoleTypeKey roleTypeKey;
|
||||
/** Defines a base-privilege type that defines the overall access for an entity-type */
|
||||
public final PrivilegeType privilegeType;
|
||||
/** Defines an institutional privilege type that defines the institutional restricted access for a
|
||||
|
@ -24,10 +26,12 @@ public final class Privilege {
|
|||
public final PrivilegeType ownershipPrivilege;
|
||||
|
||||
public Privilege(
|
||||
final RoleTypeKey roleTypeKey,
|
||||
final PrivilegeType privilegeType,
|
||||
final PrivilegeType institutionalPrivilege,
|
||||
final PrivilegeType ownershipPrivilege) {
|
||||
|
||||
this.roleTypeKey = roleTypeKey;
|
||||
this.privilegeType = privilegeType;
|
||||
this.institutionalPrivilege = institutionalPrivilege;
|
||||
this.ownershipPrivilege = ownershipPrivilege;
|
||||
|
@ -68,7 +72,7 @@ public final class Privilege {
|
|||
}
|
||||
|
||||
/** A key that combines UserRole EntityType identity */
|
||||
static final class RoleTypeKey {
|
||||
public static final class RoleTypeKey {
|
||||
|
||||
public final EntityType entityType;
|
||||
public final UserRole userRole;
|
|
@ -0,0 +1,15 @@
|
|||
/*
|
||||
* 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.gbl.authorization;
|
||||
|
||||
public enum PrivilegeLevel {
|
||||
BASE,
|
||||
INSTITUTIONAL,
|
||||
OWNERSHIP
|
||||
}
|
|
@ -6,7 +6,7 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package ch.ethz.seb.sebserver.webservice.servicelayer.authorization;
|
||||
package ch.ethz.seb.sebserver.gbl.authorization;
|
||||
|
||||
/** Defines SEB-Server internal privilege types **/
|
||||
public enum PrivilegeType {
|
|
@ -22,6 +22,11 @@ public interface Entity extends ModelIdAware {
|
|||
@JsonIgnore
|
||||
String getName();
|
||||
|
||||
@JsonIgnore
|
||||
default EntityKey getEntityKey() {
|
||||
return new EntityKey(getModelId(), entityType());
|
||||
}
|
||||
|
||||
public static EntityName toName(final Entity entity) {
|
||||
return new EntityName(
|
||||
entity.entityType(),
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
|
||||
package ch.ethz.seb.sebserver.gbl.model;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
@ -15,8 +17,10 @@ import com.fasterxml.jackson.annotation.JsonProperty;
|
|||
public class EntityKey {
|
||||
|
||||
@JsonProperty(value = "modelId", required = true)
|
||||
@NotNull
|
||||
public final String modelId;
|
||||
@JsonProperty(value = "entityType", required = true)
|
||||
@NotNull
|
||||
public final EntityType entityType;
|
||||
@JsonIgnore
|
||||
public final boolean isIdPK;
|
||||
|
@ -26,6 +30,9 @@ public class EntityKey {
|
|||
@JsonProperty(value = "modelId", required = true) final String modelId,
|
||||
@JsonProperty(value = "entityType", required = true) final EntityType entityType) {
|
||||
|
||||
assert (modelId != null) : "modelId has null reference";
|
||||
assert (entityType != null) : "entityType has null reference";
|
||||
|
||||
this.modelId = modelId;
|
||||
this.entityType = entityType;
|
||||
this.isIdPK = entityType != EntityType.USER;
|
||||
|
|
|
@ -12,11 +12,14 @@ import java.util.Collection;
|
|||
import java.util.Set;
|
||||
|
||||
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.APIMessage;
|
||||
import ch.ethz.seb.sebserver.gbl.util.Utils;
|
||||
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class EntityProcessingReport {
|
||||
|
||||
@JsonProperty(value = "source", required = true)
|
||||
|
@ -37,6 +40,15 @@ public class EntityProcessingReport {
|
|||
this.errors = Utils.immutableSetOf(errors);
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
public EntityKey getSingleSource() {
|
||||
if (!this.source.isEmpty()) {
|
||||
return this.source.iterator().next();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static final class ErrorEntry {
|
||||
|
||||
public final EntityKey entityKey;
|
||||
|
|
|
@ -9,9 +9,11 @@
|
|||
package ch.ethz.seb.sebserver.gbl.model.institution;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
import javax.validation.constraints.Pattern;
|
||||
import javax.validation.constraints.Size;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.api.POSTMapper;
|
||||
|
@ -21,6 +23,7 @@ import ch.ethz.seb.sebserver.gbl.model.Domain.INSTITUTION;
|
|||
import ch.ethz.seb.sebserver.gbl.model.EntityType;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.GrantEntity;
|
||||
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public final class Institution implements GrantEntity, Activatable {
|
||||
|
||||
@JsonProperty(Domain.ATTR_ID)
|
||||
|
@ -32,7 +35,7 @@ public final class Institution implements GrantEntity, Activatable {
|
|||
public final String name;
|
||||
|
||||
@JsonProperty(INSTITUTION.ATTR_URL_SUFFIX)
|
||||
@Size(min = 3, max = 255, message = "institution:urlSuffix:size:{min}:{max}:${validatedValue}")
|
||||
@Pattern(regexp = "(^$|.{3,255})", message = "institution:urlSuffix:size:{min}:{max}:${validatedValue}")
|
||||
public final String urlSuffix;
|
||||
|
||||
@JsonProperty(INSTITUTION.ATTR_LOGO_IMAGE)
|
||||
|
|
|
@ -11,6 +11,7 @@ package ch.ethz.seb.sebserver.gui.service.page;
|
|||
import org.eclipse.swt.widgets.Composite;
|
||||
import org.eclipse.swt.widgets.Shell;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
|
||||
import ch.ethz.seb.sebserver.gui.service.page.action.Action;
|
||||
import ch.ethz.seb.sebserver.gui.service.page.action.ActionDefinition;
|
||||
import ch.ethz.seb.sebserver.gui.service.page.activity.ActivitySelection;
|
||||
|
@ -33,7 +34,8 @@ public interface PageContext {
|
|||
|
||||
public static final String PAGE_TEMPLATE_COMPOSER_NAME = "ATTR_PAGE_TEMPLATE_COMPOSER_NAME";
|
||||
|
||||
public static final String INSTITUTION_ID = "INSTITUTION_ID";
|
||||
public static final String READ_ONLY = "READ_ONLY";
|
||||
public static final String CREATE_NEW = "CREATE_NEW";
|
||||
|
||||
public static final String ENTITY_ID = "ENTITY_ID";
|
||||
public static final String PARENT_ENTITY_ID = "PARENT_ENTITY_ID";
|
||||
|
@ -55,8 +57,7 @@ public interface PageContext {
|
|||
//
|
||||
// public static final String AUTHORIZATION_CONTEXT = "AUTHORIZATION_CONTEXT";
|
||||
// public static final String AUTHORIZATION_HEADER = "AUTHORIZATION_HEADER";
|
||||
public static final String AUTHORIZATION_FAILURE = "AUTHORIZATION_FAILURE";
|
||||
public static final String LGOUT_SUCCESS = "LGOUT_SUCCESS";
|
||||
// public static final String AUTHORIZATION_FAILURE = "AUTHORIZATION_FAILURE";
|
||||
|
||||
}
|
||||
|
||||
|
@ -92,16 +93,30 @@ public interface PageContext {
|
|||
* @param key the key of the attribute
|
||||
* @param value the value of the attribute
|
||||
* @return this PageContext instance (builder pattern) */
|
||||
PageContext withAttr(String key, String value);
|
||||
PageContext withAttribute(String key, String value);
|
||||
|
||||
PageContext withSelection(ActivitySelection selection);
|
||||
default PageContext withSelection(final ActivitySelection selection) {
|
||||
return withSelection(selection, true);
|
||||
}
|
||||
|
||||
PageContext withSelection(ActivitySelection selection, boolean clearAttributes);
|
||||
|
||||
String getAttribute(String name);
|
||||
|
||||
String getAttribute(String name, String def);
|
||||
|
||||
EntityKey getEntityKey();
|
||||
|
||||
EntityKey getParentEntityKey();
|
||||
|
||||
PageContext withEntityKey(EntityKey entityKey);
|
||||
|
||||
PageContext withParentEntityKey(EntityKey entityKey);
|
||||
|
||||
boolean hasAttribute(String name);
|
||||
|
||||
PageContext removeAttribute(String name);
|
||||
|
||||
/** Publishes a given PageEvent to the current page tree
|
||||
* This goes through the page-tree and collects all listeners the are listen to
|
||||
* the specified page event type.
|
||||
|
@ -133,7 +148,7 @@ public interface PageContext {
|
|||
* @param error the error as Throwable */
|
||||
void notifyError(String errorMessage, Throwable error);
|
||||
|
||||
void notifyError(Throwable error);
|
||||
<T> T notifyError(Throwable error);
|
||||
|
||||
<T> T logoutOnError(Throwable error);
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
package ch.ethz.seb.sebserver.gui.service.page.action;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.function.BooleanSupplier;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
|
@ -23,12 +24,13 @@ import ch.ethz.seb.sebserver.gui.service.page.event.ActionEvent;
|
|||
import ch.ethz.seb.sebserver.gui.service.page.event.ActionPublishEvent;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestService;
|
||||
|
||||
public class Action implements Runnable {
|
||||
public final class Action implements Runnable {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(Action.class);
|
||||
|
||||
public final ActionDefinition definition;
|
||||
String confirmationMessage;
|
||||
BooleanSupplier confirmComdition = () -> true;
|
||||
String successMessage;
|
||||
boolean updateOnSelection;
|
||||
|
||||
|
@ -49,7 +51,7 @@ public class Action implements Runnable {
|
|||
|
||||
@Override
|
||||
public void run() {
|
||||
if (StringUtils.isNotBlank(this.confirmationMessage)) {
|
||||
if (StringUtils.isNotBlank(this.confirmationMessage) && this.confirmComdition.getAsBoolean()) {
|
||||
this.pageContext.applyConfirmDialog(
|
||||
this.confirmationMessage,
|
||||
() -> exec());
|
||||
|
|
|
@ -16,16 +16,32 @@ public enum ActionDefinition {
|
|||
"sebserver.institution.action.new",
|
||||
IconButtonType.NEW_ACTION),
|
||||
|
||||
INSTITUTION_VIEW(
|
||||
"sebserver.institution.action.view",
|
||||
IconButtonType.VIEW_ACTION),
|
||||
|
||||
INSTITUTION_MODIFY(
|
||||
"sebserver.institution.action.modify",
|
||||
IconButtonType.MODIFY_ACTION),
|
||||
|
||||
INSTITUTION_CANCEL_MODIFY(
|
||||
"sebserver.overall.action.modify.cancel",
|
||||
IconButtonType.CANCEL_ACTION),
|
||||
|
||||
INSTITUTION_SAVE(
|
||||
"actions.modify.institution",
|
||||
"sebserver.institution.action.save",
|
||||
IconButtonType.SAVE_ACTION),
|
||||
|
||||
INSTITUTION_ACTIVATE(
|
||||
"sebserver.institution.action.activate",
|
||||
IconButtonType.ACTIVATE_ACTION),
|
||||
|
||||
INSTITUTION_DEACTIVATE(
|
||||
"sebserver.institution.action.deactivate",
|
||||
IconButtonType.DEACTIVATE_ACTION),
|
||||
|
||||
INSTITUTION_DELETE(
|
||||
"actions.delete.institution",
|
||||
"sebserver.institution.action.modify",
|
||||
IconButtonType.DELETE_ACTION),
|
||||
|
||||
LMS_SETUP_NEW(
|
||||
|
|
|
@ -13,67 +13,92 @@ import static ch.ethz.seb.sebserver.gui.service.page.activity.ActivitySelection.
|
|||
import java.util.Collection;
|
||||
import java.util.function.Function;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.api.API;
|
||||
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
|
||||
import ch.ethz.seb.sebserver.gbl.model.EntityType;
|
||||
import ch.ethz.seb.sebserver.gbl.model.institution.Institution;
|
||||
import ch.ethz.seb.sebserver.gbl.util.Result;
|
||||
import ch.ethz.seb.sebserver.gui.service.page.PageContext;
|
||||
import ch.ethz.seb.sebserver.gui.service.page.PageContext.AttributeKeys;
|
||||
import ch.ethz.seb.sebserver.gui.service.page.PageMessageException;
|
||||
import ch.ethz.seb.sebserver.gui.service.page.activity.ActivitySelection;
|
||||
import ch.ethz.seb.sebserver.gui.service.page.event.ActivitySelectionEvent;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.institution.NewInstitution;
|
||||
import ch.ethz.seb.sebserver.gui.service.table.EntityTable;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.institution.ActivateInstitution;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.institution.DeactivateInstitution;
|
||||
|
||||
public final class InstitutionActions {
|
||||
|
||||
public static Result<?> newInstitution(final Action action) {
|
||||
return action.restService
|
||||
.getBuilder(NewInstitution.class)
|
||||
.call();
|
||||
}
|
||||
|
||||
public static Function<Action, Result<?>> editInstitution(final EntityTable<?> fromTable) {
|
||||
return action -> {
|
||||
final Collection<String> selection = fromTable.getSelection();
|
||||
if (selection.isEmpty()) {
|
||||
return Result.ofError(new PageMessageException("sebserver.institution.info.pleaseSelect"));
|
||||
}
|
||||
|
||||
final EntityKey entityKey = new EntityKey(
|
||||
selection.iterator().next(),
|
||||
EntityType.INSTITUTION);
|
||||
action.pageContext.publishPageEvent(new ActivitySelectionEvent(
|
||||
INSTITUTION_NODE
|
||||
.createSelection()
|
||||
.withEntity(entityKey)));
|
||||
|
||||
return Result.of(entityKey);
|
||||
public static Function<Institution, Institution> postSaveAdapter(final PageContext pageContext) {
|
||||
return inst -> {
|
||||
goToInstitution(pageContext, inst.getModelId(), false);
|
||||
return inst;
|
||||
};
|
||||
}
|
||||
|
||||
// /** Use this higher-order function to create a new Institution action function.
|
||||
// *
|
||||
// * @return */
|
||||
// static Runnable newInstitution(final PageContext composerCtx, final RestServices restServices) {
|
||||
// return () -> {
|
||||
// final IdAndName newInstitutionId = restServices
|
||||
// .sebServerAPICall(NewInstitution.class)
|
||||
// .doAPICall()
|
||||
// .onErrorThrow("Unexpected Error");
|
||||
// composerCtx.notify(new ActionEvent(ActionDefinition.INSTITUTION_NEW, newInstitutionId));
|
||||
// };
|
||||
// }
|
||||
//
|
||||
// /** Use this higher-order function to create a delete Institution action function.
|
||||
// *
|
||||
// * @return */
|
||||
// static Runnable deleteInstitution(final PageContext composerCtx, final RestServices restServices,
|
||||
// final String instId) {
|
||||
// return () -> {
|
||||
// restServices
|
||||
// .sebServerAPICall(DeleteInstitution.class)
|
||||
// .attribute(AttributeKeys.INSTITUTION_ID, instId)
|
||||
// .doAPICall()
|
||||
// .onErrorThrow("Unexpected Error");
|
||||
// composerCtx.notify(new ActionEvent(ActionDefinition.INSTITUTION_DELETE, instId));
|
||||
// };
|
||||
// }
|
||||
public static Result<?> newInstitution(final Action action) {
|
||||
return Result.of(goToInstitution(action.pageContext, null, true));
|
||||
}
|
||||
|
||||
public static Result<?> viewInstitution(final Action action) {
|
||||
return fromInstitution(action, false);
|
||||
}
|
||||
|
||||
public static Result<?> editInstitutionFromList(final Action action) {
|
||||
return fromInstitution(action, true);
|
||||
}
|
||||
|
||||
public static Result<?> editInstitution(final Action action) {
|
||||
return Result.of(goToInstitution(
|
||||
action.pageContext,
|
||||
action.pageContext.getAttribute(AttributeKeys.ENTITY_ID),
|
||||
true));
|
||||
}
|
||||
|
||||
public static Result<?> cancelEditInstitution(final Action action) {
|
||||
return Result.of(goToInstitution(
|
||||
action.pageContext,
|
||||
action.pageContext.getAttribute(AttributeKeys.ENTITY_ID),
|
||||
false));
|
||||
}
|
||||
|
||||
public static Result<?> activateInstitution(final Action action) {
|
||||
return action.restService
|
||||
.getBuilder(ActivateInstitution.class)
|
||||
.withURIVariable(
|
||||
API.PATH_VAR_MODEL_ID_NAME,
|
||||
action.pageContext.getAttribute(AttributeKeys.ENTITY_ID))
|
||||
.call()
|
||||
.map(report -> goToInstitution(action.pageContext, report.getSingleSource().modelId, false));
|
||||
}
|
||||
|
||||
public static Result<?> deactivateInstitution(final Action action) {
|
||||
return action.restService
|
||||
.getBuilder(DeactivateInstitution.class)
|
||||
.withURIVariable(
|
||||
API.PATH_VAR_MODEL_ID_NAME,
|
||||
action.pageContext.getAttribute(AttributeKeys.ENTITY_ID))
|
||||
.call()
|
||||
.map(report -> goToInstitution(action.pageContext, report.getSingleSource().modelId, false));
|
||||
}
|
||||
|
||||
private static Result<?> fromInstitution(final Action action, final boolean edit) {
|
||||
final Collection<String> selection = action.selectionSupplier.get();
|
||||
if (selection.isEmpty()) {
|
||||
return Result.ofError(new PageMessageException("sebserver.institution.info.pleaseSelect"));
|
||||
}
|
||||
|
||||
return Result.of(goToInstitution(action.pageContext, selection.iterator().next(), edit));
|
||||
}
|
||||
|
||||
private static ActivitySelection goToInstitution(final PageContext pageContext, final String modelId,
|
||||
final boolean edit) {
|
||||
final ActivitySelection activitySelection = INSTITUTION_NODE
|
||||
.createSelection()
|
||||
.withEntity(new EntityKey(modelId, EntityType.INSTITUTION))
|
||||
.withAttribute(AttributeKeys.READ_ONLY, String.valueOf(!edit))
|
||||
.withAttribute(AttributeKeys.CREATE_NEW, (modelId != null) ? "false" : "true");
|
||||
pageContext.publishPageEvent(new ActivitySelectionEvent(activitySelection));
|
||||
return activitySelection;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -35,7 +35,7 @@ import ch.ethz.seb.sebserver.gui.service.page.event.ActivitySelectionEvent;
|
|||
import ch.ethz.seb.sebserver.gui.service.page.event.PageEventListener;
|
||||
import ch.ethz.seb.sebserver.gui.service.page.impl.MainPageState;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestService;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.AuthorizationContextHolder;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.CurrentUser;
|
||||
import ch.ethz.seb.sebserver.gui.service.widget.WidgetFactory;
|
||||
import ch.ethz.seb.sebserver.gui.service.widget.WidgetFactory.CustomVariant;
|
||||
|
||||
|
@ -43,22 +43,25 @@ import ch.ethz.seb.sebserver.gui.service.widget.WidgetFactory.CustomVariant;
|
|||
@Component
|
||||
public class ActivitiesPane implements TemplateComposer {
|
||||
|
||||
private static final String ATTR_ACTIVITY_SELECTION = "ACTIVITY_SELECTION";
|
||||
|
||||
private final WidgetFactory widgetFactory;
|
||||
private final RestService restService;
|
||||
private final AuthorizationContextHolder authorizationContextHolder;
|
||||
private final CurrentUser currentUser;
|
||||
|
||||
// TODO are those really needed?
|
||||
private final Map<ActionDefinition, ActivityActionHandler> activityActionHandler =
|
||||
new EnumMap<>(ActionDefinition.class);
|
||||
|
||||
public ActivitiesPane(
|
||||
final WidgetFactory widgetFactory,
|
||||
final RestService restService,
|
||||
final AuthorizationContextHolder authorizationContextHolder,
|
||||
final CurrentUser currentUser,
|
||||
final Collection<ActivityActionHandler> activityActionHandler) {
|
||||
|
||||
this.widgetFactory = widgetFactory;
|
||||
this.restService = restService;
|
||||
this.authorizationContextHolder = authorizationContextHolder;
|
||||
this.currentUser = currentUser;
|
||||
|
||||
for (final ActivityActionHandler aah : activityActionHandler) {
|
||||
this.activityActionHandler.put(aah.handlesAction(), aah);
|
||||
|
@ -67,10 +70,8 @@ public class ActivitiesPane implements TemplateComposer {
|
|||
|
||||
@Override
|
||||
public void compose(final PageContext pageContext) {
|
||||
final UserInfo userInfo = this.authorizationContextHolder
|
||||
.getAuthorizationContext()
|
||||
.getLoggedInUser()
|
||||
.get(pageContext::logoutOnError);
|
||||
final UserInfo userInfo = this.currentUser
|
||||
.getOrHandleError(pageContext::logoutOnError);
|
||||
|
||||
final Label activities = this.widgetFactory.labelLocalized(
|
||||
pageContext.getParent(),
|
||||
|
@ -80,8 +81,9 @@ public class ActivitiesPane implements TemplateComposer {
|
|||
activitiesGridData.horizontalIndent = 20;
|
||||
activities.setLayoutData(activitiesGridData);
|
||||
|
||||
final Tree navigation =
|
||||
this.widgetFactory.treeLocalized(pageContext.getParent(), SWT.SINGLE | SWT.FULL_SELECTION);
|
||||
final Tree navigation = this.widgetFactory.treeLocalized(
|
||||
pageContext.getParent(),
|
||||
SWT.SINGLE | SWT.FULL_SELECTION);
|
||||
final GridData navigationGridData = new GridData(SWT.FILL, SWT.FILL, true, true);
|
||||
navigationGridData.horizontalIndent = 10;
|
||||
navigation.setLayoutData(navigationGridData);
|
||||
|
@ -96,7 +98,7 @@ public class ActivitiesPane implements TemplateComposer {
|
|||
final TreeItem institutions = this.widgetFactory.treeItemLocalized(
|
||||
navigation,
|
||||
Activity.INSTITUTION_ROOT.title);
|
||||
ActivitySelection.inject(institutions, Activity.INSTITUTION_ROOT.createSelection());
|
||||
injectActivitySelection(institutions, Activity.INSTITUTION_ROOT.createSelection());
|
||||
|
||||
// for (final EntityName inst : insitutionNames) {
|
||||
// createInstitutionItem(institutions, inst);
|
||||
|
@ -106,7 +108,7 @@ public class ActivitiesPane implements TemplateComposer {
|
|||
final TreeItem institutions = this.widgetFactory.treeItemLocalized(
|
||||
navigation,
|
||||
Activity.INSTITUTION_ROOT.title);
|
||||
ActivitySelection.inject(institutions, Activity.INSTITUTION_NODE.createSelection());
|
||||
injectActivitySelection(institutions, Activity.INSTITUTION_NODE.createSelection());
|
||||
// final EntityName inst = insitutionNames.iterator().next();
|
||||
// createInstitutionItem(navigation, inst);
|
||||
}
|
||||
|
@ -155,16 +157,20 @@ public class ActivitiesPane implements TemplateComposer {
|
|||
|
||||
navigation.addListener(SWT.Expand, this::handleExpand);
|
||||
navigation.addListener(SWT.Selection, event -> handleSelection(pageContext, event));
|
||||
|
||||
navigation.setData(
|
||||
PageEventListener.LISTENER_ATTRIBUTE_KEY,
|
||||
new ActionEventListener() {
|
||||
@Override
|
||||
public void notify(final ActionEvent event) {
|
||||
final ActivityActionHandler aah =
|
||||
ActivitiesPane.this.activityActionHandler.get(event.actionDefinition);
|
||||
if (aah != null) {
|
||||
aah.notifyAction(event, navigation, pageContext);
|
||||
// final ActivityActionHandler aah =
|
||||
// ActivitiesPane.this.activityActionHandler.get(event.actionDefinition);
|
||||
// if (aah != null) {
|
||||
// aah.notifyAction(event, navigation, pageContext);
|
||||
// }
|
||||
// on case of an Action with ActivitySelection, reset the MainPageState
|
||||
if (event.source instanceof ActivitySelection) {
|
||||
final MainPageState mainPageState = MainPageState.get();
|
||||
mainPageState.activitySelection = (ActivitySelection) event.source;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -172,11 +178,13 @@ public class ActivitiesPane implements TemplateComposer {
|
|||
// page-selection on (re)load
|
||||
final MainPageState mainPageState = MainPageState.get();
|
||||
|
||||
if (mainPageState.activitySelection == null) {
|
||||
mainPageState.activitySelection = ActivitySelection.get(navigation.getItem(0));
|
||||
if (mainPageState.activitySelection == null ||
|
||||
mainPageState.activitySelection.activity == ActivitySelection.Activity.NONE) {
|
||||
mainPageState.activitySelection = getActivitySelection(navigation.getItem(0));
|
||||
}
|
||||
pageContext.publishPageEvent(
|
||||
new ActivitySelectionEvent(mainPageState.activitySelection));
|
||||
navigation.select(navigation.getItem(0));
|
||||
}
|
||||
|
||||
// private void runningExamExpand(final TreeItem item) {
|
||||
|
@ -202,7 +210,7 @@ public class ActivitiesPane implements TemplateComposer {
|
|||
|
||||
System.out.println("opened: " + treeItem);
|
||||
|
||||
final ActivitySelection activity = ActivitySelection.get(treeItem);
|
||||
final ActivitySelection activity = getActivitySelection(treeItem);
|
||||
if (activity != null) {
|
||||
activity.processExpand(treeItem);
|
||||
}
|
||||
|
@ -214,7 +222,7 @@ public class ActivitiesPane implements TemplateComposer {
|
|||
System.out.println("selected: " + treeItem);
|
||||
|
||||
final MainPageState mainPageState = MainPageState.get();
|
||||
final ActivitySelection activitySelection = ActivitySelection.get(treeItem);
|
||||
final ActivitySelection activitySelection = getActivitySelection(treeItem);
|
||||
if (mainPageState.activitySelection == null) {
|
||||
mainPageState.activitySelection = Activity.NONE.createSelection();
|
||||
}
|
||||
|
@ -239,7 +247,7 @@ public class ActivitiesPane implements TemplateComposer {
|
|||
|
||||
static void createInstitutionItem(final EntityName entityName, final TreeItem institution) {
|
||||
institution.setText(entityName.name);
|
||||
ActivitySelection.inject(
|
||||
injectActivitySelection(
|
||||
institution,
|
||||
Activity.INSTITUTION_NODE
|
||||
.createSelection()
|
||||
|
@ -256,7 +264,7 @@ public class ActivitiesPane implements TemplateComposer {
|
|||
}
|
||||
|
||||
for (final TreeItem item : items) {
|
||||
final ActivitySelection activitySelection = ActivitySelection.get(item);
|
||||
final ActivitySelection activitySelection = getActivitySelection(item);
|
||||
final String id = activitySelection.getEntityId();
|
||||
if (activitySelection != null && activitySelection.activity == activity &&
|
||||
(id == null || (objectId != null && objectId.equals(id)))) {
|
||||
|
@ -285,4 +293,12 @@ public class ActivitiesPane implements TemplateComposer {
|
|||
expand(item.getParentItem());
|
||||
}
|
||||
|
||||
public static ActivitySelection getActivitySelection(final TreeItem item) {
|
||||
return (ActivitySelection) item.getData(ATTR_ACTIVITY_SELECTION);
|
||||
}
|
||||
|
||||
public static void injectActivitySelection(final TreeItem item, final ActivitySelection selection) {
|
||||
item.setData(ATTR_ACTIVITY_SELECTION, selection);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ import ch.ethz.seb.sebserver.gui.service.i18n.LocTextKey;
|
|||
import ch.ethz.seb.sebserver.gui.service.page.PageContext.AttributeKeys;
|
||||
import ch.ethz.seb.sebserver.gui.service.page.TemplateComposer;
|
||||
import ch.ethz.seb.sebserver.gui.service.page.action.ActionPane;
|
||||
import ch.ethz.seb.sebserver.gui.service.page.content.InstitutionForm;
|
||||
import ch.ethz.seb.sebserver.gui.service.page.content.InstitutionList;
|
||||
import ch.ethz.seb.sebserver.gui.service.page.impl.TODOTemplate;
|
||||
|
||||
|
@ -39,7 +40,7 @@ public class ActivitySelection {
|
|||
ActionPane.class,
|
||||
new LocTextKey("sebserver.activities.inst")),
|
||||
INSTITUTION_NODE(
|
||||
TODOTemplate.class,
|
||||
InstitutionForm.class,
|
||||
ActionPane.class,
|
||||
new LocTextKey("sebserver.activities.inst")),
|
||||
//
|
||||
|
@ -84,8 +85,6 @@ public class ActivitySelection {
|
|||
}
|
||||
}
|
||||
|
||||
private static final String ATTR_ACTIVITY_SELECTION = "ACTIVITY_SELECTION";
|
||||
|
||||
public final Activity activity;
|
||||
final Map<String, String> attributes;
|
||||
Consumer<TreeItem> expandFunction = EMPTY_FUNCTION;
|
||||
|
@ -114,6 +113,11 @@ public class ActivitySelection {
|
|||
return this;
|
||||
}
|
||||
|
||||
public ActivitySelection withAttribute(final String name, final String value) {
|
||||
this.attributes.put(name, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Map<String, String> getAttributes() {
|
||||
return Collections.unmodifiableMap(this.attributes);
|
||||
}
|
||||
|
@ -134,12 +138,4 @@ public class ActivitySelection {
|
|||
return this.attributes.get(AttributeKeys.ENTITY_ID);
|
||||
}
|
||||
|
||||
public static ActivitySelection get(final TreeItem item) {
|
||||
return (ActivitySelection) item.getData(ATTR_ACTIVITY_SELECTION);
|
||||
}
|
||||
|
||||
public static void inject(final TreeItem item, final ActivitySelection selection) {
|
||||
item.setData(ATTR_ACTIVITY_SELECTION, selection);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,172 @@
|
|||
/*
|
||||
* Copyright (c) 2019 ETH Zürich, Educational Development and Technology (LET)
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package ch.ethz.seb.sebserver.gui.service.page.content;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import org.apache.commons.lang3.BooleanUtils;
|
||||
import org.eclipse.swt.SWT;
|
||||
import org.eclipse.swt.layout.GridData;
|
||||
import org.eclipse.swt.layout.GridLayout;
|
||||
import org.eclipse.swt.widgets.Composite;
|
||||
import org.eclipse.swt.widgets.Label;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
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.institution.Institution;
|
||||
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
|
||||
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.TemplateComposer;
|
||||
import ch.ethz.seb.sebserver.gui.service.page.action.ActionDefinition;
|
||||
import ch.ethz.seb.sebserver.gui.service.page.action.InstitutionActions;
|
||||
import ch.ethz.seb.sebserver.gui.service.page.event.ActionEventListener;
|
||||
import ch.ethz.seb.sebserver.gui.service.page.form.FormHandle;
|
||||
import ch.ethz.seb.sebserver.gui.service.page.form.PageFormService;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestService;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.institution.GetInstitution;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.institution.NewInstitution;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.institution.SaveInstitution;
|
||||
import ch.ethz.seb.sebserver.gui.service.widget.WidgetFactory;
|
||||
|
||||
@Lazy
|
||||
@Component
|
||||
@GuiProfile
|
||||
public class InstitutionForm implements TemplateComposer {
|
||||
|
||||
private final PageFormService pageFormService;
|
||||
private final RestService restService;
|
||||
|
||||
protected InstitutionForm(final PageFormService pageFormService, final RestService restService) {
|
||||
this.pageFormService = pageFormService;
|
||||
this.restService = restService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void compose(final PageContext pageContext) {
|
||||
final WidgetFactory widgetFactory = this.pageFormService.getWidgetFactory();
|
||||
|
||||
final boolean readonly = BooleanUtils.toBoolean(
|
||||
pageContext.getAttribute(AttributeKeys.READ_ONLY, "true"));
|
||||
final boolean createNew = BooleanUtils.toBoolean(
|
||||
pageContext.getAttribute(AttributeKeys.CREATE_NEW, "false"));
|
||||
|
||||
// get data or create new and handle error
|
||||
Institution institution = null;
|
||||
PageContext formContext = pageContext;
|
||||
|
||||
if (createNew) {
|
||||
institution = this.restService
|
||||
.getBuilder(NewInstitution.class)
|
||||
.withQueryParam(Domain.INSTITUTION.ATTR_NAME, "[NEW-" + UUID.randomUUID() + "]")
|
||||
.call()
|
||||
.get(pageContext::notifyError);
|
||||
formContext = pageContext.withEntityKey(institution.getEntityKey());
|
||||
} else {
|
||||
final String instId = pageContext.getAttribute(AttributeKeys.ENTITY_ID);
|
||||
institution = this.restService
|
||||
.getBuilder(GetInstitution.class)
|
||||
.withURIVariable(API.PATH_VAR_MODEL_ID_NAME, instId)
|
||||
.call()
|
||||
.get(pageContext::notifyError);
|
||||
}
|
||||
|
||||
if (institution == null) {
|
||||
// TODO should here be a forward to institution list page for SEB Admin?
|
||||
return;
|
||||
}
|
||||
|
||||
// page grid
|
||||
final Composite content = new Composite(formContext.getParent(), SWT.NONE);
|
||||
final GridLayout contentLayout = new GridLayout();
|
||||
contentLayout.marginLeft = 10;
|
||||
content.setLayout(contentLayout);
|
||||
content.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
|
||||
|
||||
// title
|
||||
final Label pageTitle = widgetFactory.labelLocalizedTitle(
|
||||
content, new LocTextKey(
|
||||
"sebserver.institution.form.title",
|
||||
institution.name));
|
||||
|
||||
pageTitle.setLayoutData(new GridData(SWT.TOP, SWT.LEFT, true, false));
|
||||
ActionEventListener.injectListener(
|
||||
pageTitle,
|
||||
ActionDefinition.INSTITUTION_SAVE,
|
||||
event -> {
|
||||
final Entity entity = (Entity) event.source;
|
||||
widgetFactory.injectI18n(pageTitle, new LocTextKey(
|
||||
"sebserver.institution.form.title",
|
||||
entity.getName()));
|
||||
content.layout();
|
||||
});
|
||||
|
||||
// The Institution form
|
||||
final FormHandle<Institution> formHandle = this.pageFormService.getBuilder(
|
||||
formContext.copyOf(content), 4)
|
||||
.readonly(readonly)
|
||||
.putStaticValue("id", institution.getModelId())
|
||||
.addTextField(
|
||||
Domain.INSTITUTION.ATTR_NAME,
|
||||
"sebserver.institution.form.name",
|
||||
institution.name, 2)
|
||||
.addEmptyCell()
|
||||
.addTextField(
|
||||
Domain.INSTITUTION.ATTR_URL_SUFFIX,
|
||||
"sebserver.institution.form.urlSuffix",
|
||||
institution.urlSuffix, 2)
|
||||
.addEmptyCell()
|
||||
.addImageUpload(
|
||||
Domain.INSTITUTION.ATTR_LOGO_IMAGE,
|
||||
"sebserver.institution.form.logoImage",
|
||||
institution.logoImage, 2)
|
||||
.addEmptyCell()
|
||||
.addTextField(
|
||||
Domain.INSTITUTION.ATTR_URL_SUFFIX,
|
||||
"sebserver.institution.form.urlSuffix",
|
||||
institution.urlSuffix, 2)
|
||||
.buildFor(
|
||||
this.restService.getRestCall(SaveInstitution.class),
|
||||
InstitutionActions.postSaveAdapter(pageContext));
|
||||
|
||||
// propagate content actions to action-pane
|
||||
if (readonly) {
|
||||
formContext.createAction(ActionDefinition.INSTITUTION_NEW)
|
||||
.withExec(InstitutionActions::newInstitution)
|
||||
.publish()
|
||||
.createAction(ActionDefinition.INSTITUTION_MODIFY)
|
||||
.withExec(InstitutionActions::editInstitution)
|
||||
.publish();
|
||||
if (!institution.isActive()) {
|
||||
formContext.createAction(ActionDefinition.INSTITUTION_ACTIVATE)
|
||||
.withExec(InstitutionActions::activateInstitution)
|
||||
.publish();
|
||||
} else {
|
||||
formContext.createAction(ActionDefinition.INSTITUTION_DEACTIVATE)
|
||||
.withExec(InstitutionActions::deactivateInstitution)
|
||||
.publish();
|
||||
}
|
||||
} else {
|
||||
formContext.createAction(ActionDefinition.INSTITUTION_SAVE)
|
||||
.withExec(formHandle::postChanges)
|
||||
.publish()
|
||||
.createAction(ActionDefinition.INSTITUTION_CANCEL_MODIFY)
|
||||
.withExec(InstitutionActions::cancelEditInstitution)
|
||||
.withConfirm("sebserver.overall.action.modify.cancel.confirm")
|
||||
.publish();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -83,8 +83,13 @@ public class InstitutionList implements TemplateComposer {
|
|||
pageContext.createAction(ActionDefinition.INSTITUTION_NEW)
|
||||
.withExec(InstitutionActions::newInstitution)
|
||||
.publish()
|
||||
.createAction(ActionDefinition.INSTITUTION_VIEW)
|
||||
.withSelectionSupplier(table::getSelection)
|
||||
.withExec(InstitutionActions::viewInstitution)
|
||||
.publish()
|
||||
.createAction(ActionDefinition.INSTITUTION_MODIFY)
|
||||
.withExec(InstitutionActions.editInstitution(table))
|
||||
.withSelectionSupplier(table::getSelection)
|
||||
.withExec(InstitutionActions::editInstitutionFromList)
|
||||
.publish();
|
||||
|
||||
}
|
||||
|
|
|
@ -22,14 +22,15 @@ public interface ActionEventListener extends PageEventListener<ActionEvent> {
|
|||
return type == ActionEvent.class;
|
||||
}
|
||||
|
||||
static ActionEventListener of(final Consumer<ActionEvent> eventConsumer) {
|
||||
return new ActionEventListener() {
|
||||
@Override
|
||||
public void notify(final ActionEvent event) {
|
||||
eventConsumer.accept(event);
|
||||
}
|
||||
};
|
||||
}
|
||||
// static ActionEventListener of(final Consumer<ActionEvent> eventConsumer) {
|
||||
// return new ActionEventListener() {
|
||||
// @Override
|
||||
// public void notify(final ActionEvent event) {
|
||||
// eventConsumer.accept(event);
|
||||
// }
|
||||
// };
|
||||
// }
|
||||
//
|
||||
|
||||
static ActionEventListener of(
|
||||
final Predicate<ActionEvent> predicate,
|
||||
|
|
|
@ -27,7 +27,9 @@ import com.fasterxml.jackson.databind.node.ArrayNode;
|
|||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.api.JSONMapper;
|
||||
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.FormBinding;
|
||||
import ch.ethz.seb.sebserver.gui.service.widget.ImageUpload;
|
||||
import ch.ethz.seb.sebserver.gui.service.widget.SingleSelection;
|
||||
|
||||
public final class Form implements FormBinding {
|
||||
|
@ -40,9 +42,17 @@ public final class Form implements FormBinding {
|
|||
private final Map<String, List<Form>> subLists = new LinkedHashMap<>();
|
||||
private final Map<String, Set<String>> groups = new LinkedHashMap<>();
|
||||
|
||||
Form(final JSONMapper jsonMapper) {
|
||||
private final EntityKey entityKey;
|
||||
|
||||
Form(final JSONMapper jsonMapper, final EntityKey entityKey) {
|
||||
this.jsonMapper = jsonMapper;
|
||||
this.objectRoot = this.jsonMapper.createObjectNode();
|
||||
this.entityKey = entityKey;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityKey entityKey() {
|
||||
return this.entityKey;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -91,6 +101,10 @@ public final class Form implements FormBinding {
|
|||
}
|
||||
}
|
||||
|
||||
public void putField(final String name, final Label label, final ImageUpload imageUpload) {
|
||||
this.formFields.put(name, createAccessor(label, imageUpload));
|
||||
}
|
||||
|
||||
public void putSubForm(final String name, final Form form) {
|
||||
this.subForms.put(name, form);
|
||||
}
|
||||
|
@ -190,6 +204,13 @@ public final class Form implements FormBinding {
|
|||
@Override public void setValue(final String value) { singleSelection.select(value); }
|
||||
};
|
||||
}
|
||||
|
||||
private FormFieldAccessor createAccessor(final Label label, final ImageUpload imageUpload) {
|
||||
return new FormFieldAccessor(label, imageUpload) {
|
||||
@Override public String getValue() { return imageUpload.getImageBase64(); }
|
||||
@Override public void setValue(final String value) { imageUpload.setImageBase64(value); }
|
||||
};
|
||||
}
|
||||
//@formatter:on
|
||||
|
||||
public static abstract class FormFieldAccessor {
|
||||
|
@ -215,7 +236,6 @@ public final class Form implements FormBinding {
|
|||
public void setError(final String errorTooltip) {
|
||||
if (!this.hasError) {
|
||||
this.control.setData(RWT.CUSTOM_VARIANT, "error");
|
||||
//this.control.setBackground(new Color(this.control.getDisplay(), 255, 0, 0, 50));
|
||||
this.control.setToolTipText(errorTooltip);
|
||||
this.hasError = true;
|
||||
}
|
||||
|
@ -224,7 +244,6 @@ public final class Form implements FormBinding {
|
|||
public void resetError() {
|
||||
if (this.hasError) {
|
||||
this.control.setData(RWT.CUSTOM_VARIANT, null);
|
||||
//this.control.setBackground(new Color(this.control.getDisplay(), 0, 0, 0, 0));
|
||||
this.control.setToolTipText(null);
|
||||
this.hasError = false;
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ package ch.ethz.seb.sebserver.gui.service.page.form;
|
|||
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.eclipse.swt.SWT;
|
||||
|
@ -23,10 +24,13 @@ import org.slf4j.Logger;
|
|||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.api.JSONMapper;
|
||||
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
|
||||
import ch.ethz.seb.sebserver.gbl.util.Tuple;
|
||||
import ch.ethz.seb.sebserver.gui.service.i18n.LocTextKey;
|
||||
import ch.ethz.seb.sebserver.gui.service.i18n.PolyglotPageService;
|
||||
import ch.ethz.seb.sebserver.gui.service.page.PageContext;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCall;
|
||||
import ch.ethz.seb.sebserver.gui.service.widget.ImageUpload;
|
||||
import ch.ethz.seb.sebserver.gui.service.widget.WidgetFactory;
|
||||
|
||||
public class FormBuilder {
|
||||
|
@ -42,6 +46,7 @@ public class FormBuilder {
|
|||
private boolean readonly = false;
|
||||
|
||||
FormBuilder(
|
||||
final EntityKey entityKey,
|
||||
final JSONMapper jsonMapper,
|
||||
final WidgetFactory widgetFactory,
|
||||
final PolyglotPageService polyglotPageService,
|
||||
|
@ -51,7 +56,7 @@ public class FormBuilder {
|
|||
this.widgetFactory = widgetFactory;
|
||||
this.polyglotPageService = polyglotPageService;
|
||||
this.pageContext = pageContext;
|
||||
this.form = new Form(jsonMapper);
|
||||
this.form = new Form(jsonMapper, entityKey);
|
||||
|
||||
this.formParent = new Composite(pageContext.getParent(), SWT.NONE);
|
||||
final GridLayout layout = new GridLayout(rows, true);
|
||||
|
@ -181,8 +186,48 @@ public class FormBuilder {
|
|||
return this;
|
||||
}
|
||||
|
||||
public <T> FormHandle<T> buildFor(final RestCall<T> post) {
|
||||
return new FormHandle<>(this.pageContext, this.form, post, this.polyglotPageService.getI18nSupport());
|
||||
public FormBuilder addImageUpload(
|
||||
final String name,
|
||||
final String label,
|
||||
final String value,
|
||||
final int span) {
|
||||
|
||||
return addImageUpload(name, label, value, span, null);
|
||||
}
|
||||
|
||||
public FormBuilder addImageUpload(
|
||||
final String name,
|
||||
final String label,
|
||||
final String value,
|
||||
final int span,
|
||||
final String group) {
|
||||
|
||||
final Label lab = this.widgetFactory.formLabelLocalized(this.formParent, label);
|
||||
final ImageUpload imageUpload = this.widgetFactory.formImageUpload(
|
||||
this.formParent,
|
||||
value,
|
||||
new LocTextKey("sebserver.overall.upload"),
|
||||
span, 1);
|
||||
if (this.readonly) {
|
||||
imageUpload.setReadonly();
|
||||
this.form.putField(name, lab, imageUpload);
|
||||
} else {
|
||||
this.form.putField(name, lab, imageUpload);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public <T> FormHandle<T> buildFor(
|
||||
final RestCall<T> post,
|
||||
final Function<T, T> postPostHandle) {
|
||||
|
||||
return new FormHandle<>(
|
||||
this.pageContext,
|
||||
this.form,
|
||||
post,
|
||||
(postPostHandle == null) ? Function.identity() : postPostHandle,
|
||||
this.polyglotPageService.getI18nSupport());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -9,13 +9,16 @@
|
|||
package ch.ethz.seb.sebserver.gui.service.page.form;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.util.Result;
|
||||
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.action.Action;
|
||||
import ch.ethz.seb.sebserver.gui.service.page.action.ActionDefinition;
|
||||
import ch.ethz.seb.sebserver.gui.service.page.event.ActionEvent;
|
||||
import ch.ethz.seb.sebserver.gui.service.page.form.Form.FormFieldAccessor;
|
||||
|
@ -27,31 +30,38 @@ public class FormHandle<T> {
|
|||
|
||||
private static final Logger log = LoggerFactory.getLogger(FormHandle.class);
|
||||
|
||||
public static final String FIELD_VALIDATION_LOCTEXT_PREFIX = "org.sebserver.form.validation.fieldError.";
|
||||
public static final String FIELD_VALIDATION_LOCTEXT_PREFIX = "sebserver.form.validation.fieldError.";
|
||||
|
||||
private final PageContext pageContext;
|
||||
private final Form form;
|
||||
private final RestCall<T> post;
|
||||
private final Function<T, T> postPostHandle;
|
||||
private final I18nSupport i18nSupport;
|
||||
|
||||
FormHandle(
|
||||
final PageContext pageContext,
|
||||
final Form form,
|
||||
final RestCall<T> post,
|
||||
final Function<T, T> postPostHandle,
|
||||
final I18nSupport i18nSupport) {
|
||||
|
||||
this.pageContext = pageContext;
|
||||
this.form = form;
|
||||
this.post = post;
|
||||
this.postPostHandle = postPostHandle;
|
||||
this.i18nSupport = i18nSupport;
|
||||
}
|
||||
|
||||
public void doAPIPost(final ActionDefinition action) {
|
||||
public final Result<T> postChanges(final Action action) {
|
||||
return doAPIPost(action.definition);
|
||||
}
|
||||
|
||||
public Result<T> doAPIPost(final ActionDefinition action) {
|
||||
this.form.process(
|
||||
name -> true,
|
||||
fieldAccessor -> fieldAccessor.resetError());
|
||||
|
||||
this.post
|
||||
return this.post
|
||||
.newBuilder()
|
||||
.withFormBinding(this.form)
|
||||
.call()
|
||||
|
@ -71,7 +81,8 @@ public class FormHandle<T> {
|
|||
log.error("Unexpected error while trying to post form: ", error);
|
||||
this.pageContext.notifyError(error);
|
||||
}
|
||||
});
|
||||
})
|
||||
.map(this.postPostHandle);
|
||||
}
|
||||
|
||||
private final void showValidationError(
|
||||
|
|
|
@ -12,12 +12,15 @@ import org.springframework.context.annotation.Lazy;
|
|||
import org.springframework.stereotype.Component;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.api.JSONMapper;
|
||||
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
|
||||
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
|
||||
import ch.ethz.seb.sebserver.gui.service.i18n.PolyglotPageService;
|
||||
import ch.ethz.seb.sebserver.gui.service.page.PageContext;
|
||||
import ch.ethz.seb.sebserver.gui.service.widget.WidgetFactory;
|
||||
|
||||
@Lazy
|
||||
@Component
|
||||
@GuiProfile
|
||||
public class PageFormService {
|
||||
|
||||
private final JSONMapper jsonMapper;
|
||||
|
@ -34,8 +37,26 @@ public class PageFormService {
|
|||
this.polyglotPageService = polyglotPageService;
|
||||
}
|
||||
|
||||
public FormBuilder getBuilder(final PageContext pageContext, final int rows) {
|
||||
public FormBuilder getBuilder(
|
||||
final PageContext pageContext,
|
||||
final int rows) {
|
||||
|
||||
return new FormBuilder(
|
||||
pageContext.getEntityKey(),
|
||||
this.jsonMapper,
|
||||
this.widgetFactory,
|
||||
this.polyglotPageService,
|
||||
pageContext,
|
||||
rows);
|
||||
}
|
||||
|
||||
public FormBuilder getBuilder(
|
||||
final EntityKey entityKey,
|
||||
final PageContext pageContext,
|
||||
final int rows) {
|
||||
|
||||
return new FormBuilder(
|
||||
entityKey,
|
||||
this.jsonMapper,
|
||||
this.widgetFactory,
|
||||
this.polyglotPageService,
|
||||
|
|
|
@ -29,7 +29,7 @@ public class DefaultLoginPage implements PageDefinition {
|
|||
|
||||
@Override
|
||||
public PageContext applyPageContext(final PageContext pageContext) {
|
||||
return pageContext.withAttr(
|
||||
return pageContext.withAttribute(
|
||||
AttributeKeys.PAGE_TEMPLATE_COMPOSER_NAME,
|
||||
SEBLogin.class.getName());
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@ public class DefaultMainPage implements PageDefinition {
|
|||
|
||||
@Override
|
||||
public PageContext applyPageContext(final PageContext pageContext) {
|
||||
return pageContext.withAttr(
|
||||
return pageContext.withAttribute(
|
||||
AttributeKeys.PAGE_TEMPLATE_COMPOSER_NAME,
|
||||
SEBMainPage.class.getName());
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ import org.eclipse.swt.layout.RowLayout;
|
|||
import org.eclipse.swt.widgets.Button;
|
||||
import org.eclipse.swt.widgets.Composite;
|
||||
import org.eclipse.swt.widgets.Label;
|
||||
import org.eclipse.swt.widgets.MessageBox;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
|
@ -37,6 +38,7 @@ import ch.ethz.seb.sebserver.gui.service.page.PageContext.AttributeKeys;
|
|||
import ch.ethz.seb.sebserver.gui.service.page.TemplateComposer;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.AuthorizationContextHolder;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.WebserviceURIService;
|
||||
import ch.ethz.seb.sebserver.gui.service.widget.Message;
|
||||
import ch.ethz.seb.sebserver.gui.service.widget.WidgetFactory;
|
||||
import ch.ethz.seb.sebserver.gui.service.widget.WidgetFactory.CustomVariant;
|
||||
|
||||
|
@ -138,8 +140,15 @@ public class DefaultPageLayout implements TemplateComposer {
|
|||
MainPageState.clear();
|
||||
|
||||
// forward to login page with success message
|
||||
pageContext.forwardToLoginPage(
|
||||
pageContext.withAttr(AttributeKeys.LGOUT_SUCCESS, "true"));
|
||||
pageContext.forwardToLoginPage(pageContext);
|
||||
|
||||
// show successful logout message
|
||||
final MessageBox logoutSuccess = new Message(
|
||||
pageContext.getShell(),
|
||||
this.polyglotPageService.getI18nSupport().getText("sebserver.logout"),
|
||||
this.polyglotPageService.getI18nSupport().getText("sebserver.logout.success.message"),
|
||||
SWT.ICON_INFORMATION);
|
||||
logoutSuccess.open(null);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -184,7 +193,7 @@ public class DefaultPageLayout implements TemplateComposer {
|
|||
logo.setBackgroundImage(new Image(pageContext.getShell().getDisplay(), input));
|
||||
|
||||
} catch (final Exception e) {
|
||||
log.warn("Get institutional logo failed: ", e);
|
||||
log.warn("Get institutional logo failed: {}", e.getMessage());
|
||||
logo.setData(RWT.CUSTOM_VARIANT, "bgLogo");
|
||||
}
|
||||
|
||||
|
|
|
@ -24,6 +24,8 @@ import org.slf4j.LoggerFactory;
|
|||
|
||||
import ch.ethz.seb.sebserver.gbl.api.APIMessage;
|
||||
import ch.ethz.seb.sebserver.gbl.api.APIMessageError;
|
||||
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
|
||||
import ch.ethz.seb.sebserver.gbl.model.EntityType;
|
||||
import ch.ethz.seb.sebserver.gbl.util.Utils;
|
||||
import ch.ethz.seb.sebserver.gui.service.i18n.I18nSupport;
|
||||
import ch.ethz.seb.sebserver.gui.service.page.ComposerService;
|
||||
|
@ -99,7 +101,7 @@ public class PageContextImpl implements PageContext {
|
|||
this.composerService,
|
||||
this.root,
|
||||
parent,
|
||||
this.attributes);
|
||||
new HashMap<>(this.attributes));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -117,7 +119,7 @@ public class PageContextImpl implements PageContext {
|
|||
}
|
||||
|
||||
@Override
|
||||
public PageContext withAttr(final String key, final String value) {
|
||||
public PageContext withAttribute(final String key, final String value) {
|
||||
final Map<String, String> attrs = new HashMap<>();
|
||||
attrs.putAll(this.attributes);
|
||||
attrs.put(key, value);
|
||||
|
@ -131,13 +133,15 @@ public class PageContextImpl implements PageContext {
|
|||
}
|
||||
|
||||
@Override
|
||||
public PageContext withSelection(final ActivitySelection selection) {
|
||||
public PageContext withSelection(final ActivitySelection selection, final boolean clearAttributes) {
|
||||
if (selection == null) {
|
||||
return this;
|
||||
}
|
||||
|
||||
final Map<String, String> attrs = new HashMap<>();
|
||||
attrs.putAll(this.attributes);
|
||||
if (!clearAttributes) {
|
||||
attrs.putAll(this.attributes);
|
||||
}
|
||||
attrs.putAll(selection.getAttributes());
|
||||
|
||||
return new PageContextImpl(
|
||||
|
@ -163,11 +167,59 @@ public class PageContextImpl implements PageContext {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityKey getEntityKey() {
|
||||
if (hasAttribute(AttributeKeys.ENTITY_ID) && hasAttribute(AttributeKeys.ENTITY_TYPE)) {
|
||||
return new EntityKey(
|
||||
getAttribute(AttributeKeys.ENTITY_ID),
|
||||
EntityType.valueOf(getAttribute(AttributeKeys.ENTITY_TYPE)));
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityKey getParentEntityKey() {
|
||||
if (hasAttribute(AttributeKeys.PARENT_ENTITY_ID) && hasAttribute(AttributeKeys.PARENT_ENTITY_TYPE)) {
|
||||
return new EntityKey(
|
||||
getAttribute(AttributeKeys.PARENT_ENTITY_ID),
|
||||
EntityType.valueOf(getAttribute(AttributeKeys.PARENT_ENTITY_TYPE)));
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageContext withEntityKey(final EntityKey entityKey) {
|
||||
return withAttribute(AttributeKeys.ENTITY_ID, entityKey.modelId)
|
||||
.withAttribute(AttributeKeys.ENTITY_TYPE, entityKey.entityType.name());
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageContext withParentEntityKey(final EntityKey entityKey) {
|
||||
return withAttribute(AttributeKeys.PARENT_ENTITY_ID, entityKey.modelId)
|
||||
.withAttribute(AttributeKeys.PARENT_ENTITY_TYPE, entityKey.entityType.name());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasAttribute(final String name) {
|
||||
return this.attributes.containsKey(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageContext removeAttribute(final String name) {
|
||||
final Map<String, String> attrs = new HashMap<>();
|
||||
attrs.putAll(this.attributes);
|
||||
attrs.remove(name);
|
||||
return new PageContextImpl(
|
||||
this.restService,
|
||||
this.i18nSupport,
|
||||
this.composerService,
|
||||
this.root,
|
||||
this.parent,
|
||||
attrs);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T extends PageEvent> void publishPageEvent(final T event) {
|
||||
|
@ -282,8 +334,9 @@ public class PageContextImpl implements PageContext {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void notifyError(final Throwable error) {
|
||||
public <T> T notifyError(final Throwable error) {
|
||||
notifyError(error.getMessage(), error);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -298,9 +351,7 @@ public class PageContextImpl implements PageContext {
|
|||
}
|
||||
|
||||
MainPageState.clear();
|
||||
forwardToLoginPage(this.withAttr(
|
||||
AttributeKeys.AUTHORIZATION_FAILURE,
|
||||
error.getMessage()));
|
||||
forwardToLoginPage(this);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -25,7 +25,6 @@ import org.springframework.stereotype.Component;
|
|||
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
|
||||
import ch.ethz.seb.sebserver.gui.service.i18n.I18nSupport;
|
||||
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.TemplateComposer;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.AuthorizationContextHolder;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.SEBServerAuthorizationContext;
|
||||
|
@ -57,14 +56,15 @@ public class SEBLogin implements TemplateComposer {
|
|||
public void compose(final PageContext pageContext) {
|
||||
final Composite parent = pageContext.getParent();
|
||||
|
||||
if (pageContext.hasAttribute((AttributeKeys.LGOUT_SUCCESS))) {
|
||||
final MessageBox logoutSuccess = new Message(
|
||||
pageContext.getShell(),
|
||||
this.i18nSupport.getText("sebserver.logout"),
|
||||
this.i18nSupport.getText("sebserver.logout.success.message"),
|
||||
SWT.ICON_INFORMATION);
|
||||
logoutSuccess.open(null);
|
||||
}
|
||||
// if (pageContext.hasAttribute((AttributeKeys.LGOUT_SUCCESS))) {
|
||||
// final MessageBox logoutSuccess = new Message(
|
||||
// pageContext.getShell(),
|
||||
// this.i18nSupport.getText("sebserver.logout"),
|
||||
// this.i18nSupport.getText("sebserver.logout.success.message"),
|
||||
// SWT.ICON_INFORMATION);
|
||||
// logoutSuccess.open(null);
|
||||
// pageContext = pageContext.removeAttribute(AttributeKeys.LGOUT_SUCCESS);
|
||||
// }
|
||||
|
||||
final Composite loginGroup = new Composite(parent, SWT.NONE);
|
||||
final GridLayout rowLayout = new GridLayout();
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* 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.push;
|
||||
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import org.eclipse.swt.widgets.Composite;
|
||||
import org.eclipse.swt.widgets.Display;
|
||||
|
||||
/** ServerPushContext defines the state of a server push session.
|
||||
*
|
||||
* @author anhefti */
|
||||
public final class ServerPushContext {
|
||||
|
||||
private final Composite anchor;
|
||||
private final Predicate<ServerPushContext> runAgain;
|
||||
|
||||
public ServerPushContext(final Composite anchor) {
|
||||
this(anchor, context -> false);
|
||||
}
|
||||
|
||||
public ServerPushContext(
|
||||
final Composite anchor,
|
||||
final Predicate<ServerPushContext> runAgain) {
|
||||
|
||||
this.anchor = anchor;
|
||||
this.runAgain = runAgain;
|
||||
}
|
||||
|
||||
public boolean runAgain() {
|
||||
return this.runAgain.test(this);
|
||||
}
|
||||
|
||||
public boolean isDisposed() {
|
||||
return this.anchor.isDisposed();
|
||||
}
|
||||
|
||||
public Display getDisplay() {
|
||||
return this.anchor.getDisplay();
|
||||
}
|
||||
|
||||
public Composite getAnchor() {
|
||||
return this.anchor;
|
||||
}
|
||||
|
||||
public void layout() {
|
||||
this.anchor.pack();
|
||||
this.anchor.layout();
|
||||
this.anchor.getParent().layout(true, true);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,80 @@
|
|||
/*
|
||||
* 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.push;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.eclipse.rap.rwt.service.ServerPushSession;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Lazy
|
||||
@Service
|
||||
public class ServerPushService {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(ServerPushService.class);
|
||||
|
||||
public void runServerPush(
|
||||
final ServerPushContext context,
|
||||
final Consumer<ServerPushContext> business,
|
||||
final Consumer<ServerPushContext> update) {
|
||||
|
||||
final ServerPushSession pushSession = new ServerPushSession();
|
||||
|
||||
pushSession.start();
|
||||
final Thread bgThread = new Thread(() -> {
|
||||
while (!context.isDisposed() && context.runAgain()) {
|
||||
|
||||
try {
|
||||
log.trace("Call business on Server Push Session on: {}", Thread.currentThread().getName());
|
||||
business.accept(context);
|
||||
} catch (final Exception e) {
|
||||
log.error("Unexpected error while do business for server push service", e);
|
||||
if (context.runAgain()) {
|
||||
continue;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!context.isDisposed()) {
|
||||
|
||||
log.trace("Call update on Server Push Session on: {}", Thread.currentThread().getName());
|
||||
|
||||
context.getDisplay().asyncExec(() -> {
|
||||
try {
|
||||
update.accept(context);
|
||||
} catch (final Exception e) {
|
||||
log.warn(
|
||||
"Failed to update on Server Push Session {}. It seems that the UISession is not available anymore. This may source from a connection interruption",
|
||||
Thread.currentThread().getName(), e);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
log.info("Stop Server Push Session on: {}", Thread.currentThread().getName());
|
||||
try {
|
||||
pushSession.stop();
|
||||
} catch (final Exception e) {
|
||||
log.warn(
|
||||
"Failed to stop Server Push Session on: {}. It seems that the UISession is not available anymore. This may source from a connection interruption",
|
||||
Thread.currentThread().getName(), e);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
log.info("Start new Server Push Session on: {}", bgThread.getName());
|
||||
|
||||
bgThread.setDaemon(true);
|
||||
bgThread.start();
|
||||
}
|
||||
}
|
|
@ -8,8 +8,12 @@
|
|||
|
||||
package ch.ethz.seb.sebserver.gui.service.remote.webservice.api;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
|
||||
|
||||
public interface FormBinding {
|
||||
|
||||
EntityKey entityKey();
|
||||
|
||||
String getFormAsJson();
|
||||
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@ import org.springframework.web.client.RestClientResponseException;
|
|||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.api.API;
|
||||
import ch.ethz.seb.sebserver.gbl.api.APIMessage;
|
||||
import ch.ethz.seb.sebserver.gbl.api.JSONMapper;
|
||||
import ch.ethz.seb.sebserver.gbl.model.Entity;
|
||||
|
@ -111,6 +112,7 @@ public abstract class RestCall<T> {
|
|||
}));
|
||||
} catch (final Exception e) {
|
||||
log.error("Unexpected error-response while webservice API call for: {}", builder, e);
|
||||
restCallError.errors.add(APIMessage.ErrorMessage.UNEXPECTED.of(e));
|
||||
}
|
||||
|
||||
return Result.ofError(restCallError);
|
||||
|
@ -147,6 +149,7 @@ public abstract class RestCall<T> {
|
|||
public RestCallBuilder withBody(final Object body) {
|
||||
if (body instanceof String) {
|
||||
this.body = String.valueOf(body);
|
||||
return this;
|
||||
}
|
||||
|
||||
try {
|
||||
|
@ -189,8 +192,8 @@ public abstract class RestCall<T> {
|
|||
}
|
||||
|
||||
public RestCallBuilder withFormBinding(final FormBinding formBinding) {
|
||||
// TODO Auto-generated method stub
|
||||
return this;
|
||||
return withURIVariable(API.PATH_VAR_MODEL_ID_NAME, formBinding.entityKey().modelId)
|
||||
.withBody(formBinding.getFormAsJson());
|
||||
}
|
||||
|
||||
public RestCallBuilder onlyActive(final boolean active) {
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* 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.remote.webservice.api.institution;
|
||||
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.api.API;
|
||||
import ch.ethz.seb.sebserver.gbl.model.EntityProcessingReport;
|
||||
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCall;
|
||||
|
||||
@Lazy
|
||||
@Component
|
||||
@GuiProfile
|
||||
public class ActivateInstitution extends RestCall<EntityProcessingReport> {
|
||||
|
||||
protected ActivateInstitution() {
|
||||
super(
|
||||
new TypeReference<EntityProcessingReport>() {
|
||||
},
|
||||
HttpMethod.POST,
|
||||
MediaType.APPLICATION_FORM_URLENCODED,
|
||||
API.INSTITUTION_ENDPOINT + API.PATH_VAR_ACTIVE);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* 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.remote.webservice.api.institution;
|
||||
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.api.API;
|
||||
import ch.ethz.seb.sebserver.gbl.model.EntityProcessingReport;
|
||||
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCall;
|
||||
|
||||
@Lazy
|
||||
@Component
|
||||
@GuiProfile
|
||||
public class DeactivateInstitution extends RestCall<EntityProcessingReport> {
|
||||
|
||||
protected DeactivateInstitution() {
|
||||
super(
|
||||
new TypeReference<EntityProcessingReport>() {
|
||||
},
|
||||
HttpMethod.POST,
|
||||
MediaType.APPLICATION_FORM_URLENCODED,
|
||||
API.INSTITUTION_ENDPOINT + API.PATH_VAR_INACTIVE);
|
||||
}
|
||||
|
||||
}
|
|
@ -31,7 +31,7 @@ public class GetInstitution extends RestCall<Institution> {
|
|||
},
|
||||
HttpMethod.GET,
|
||||
MediaType.APPLICATION_FORM_URLENCODED,
|
||||
API.INSTITUTION_ENDPOINT);
|
||||
API.INSTITUTION_ENDPOINT + API.PATH_VAR_MODEL_ID);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* 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.remote.webservice.api.institution;
|
||||
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.api.API;
|
||||
import ch.ethz.seb.sebserver.gbl.model.institution.Institution;
|
||||
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCall;
|
||||
|
||||
@Lazy
|
||||
@Component
|
||||
@GuiProfile
|
||||
public class SaveInstitution extends RestCall<Institution> {
|
||||
|
||||
protected SaveInstitution() {
|
||||
super(
|
||||
new TypeReference<Institution>() {
|
||||
},
|
||||
HttpMethod.PUT,
|
||||
MediaType.APPLICATION_JSON_UTF8,
|
||||
API.INSTITUTION_ENDPOINT + API.PATH_VAR_MODEL_ID);
|
||||
}
|
||||
|
||||
}
|
|
@ -8,6 +8,8 @@
|
|||
|
||||
package ch.ethz.seb.sebserver.gui.service.remote.webservice.auth;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
|
@ -44,6 +46,18 @@ public class CurrentUser {
|
|||
return null;
|
||||
}
|
||||
|
||||
public UserInfo getOrHandleError(final Function<Throwable, UserInfo> errorHandler) {
|
||||
if (isAvailable()) {
|
||||
return this.authContext
|
||||
.getLoggedInUser()
|
||||
.get(errorHandler);
|
||||
}
|
||||
|
||||
log.warn("Current user requested but no user is currently logged in");
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean isAvailable() {
|
||||
updateContext();
|
||||
return this.authContext != null && this.authContext.isLoggedIn();
|
||||
|
|
|
@ -9,9 +9,9 @@
|
|||
package ch.ethz.seb.sebserver.gui.service.table;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.eclipse.swt.SWT;
|
||||
|
@ -25,6 +25,7 @@ import org.eclipse.swt.widgets.TableItem;
|
|||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.Constants;
|
||||
import ch.ethz.seb.sebserver.gbl.model.Entity;
|
||||
import ch.ethz.seb.sebserver.gbl.model.Page;
|
||||
import ch.ethz.seb.sebserver.gbl.util.Utils;
|
||||
|
@ -153,16 +154,16 @@ public class EntityTable<ROW extends Entity> extends Composite {
|
|||
this.sortOrder);
|
||||
}
|
||||
|
||||
public Collection<String> getSelection() {
|
||||
public Set<String> getSelection() {
|
||||
final TableItem[] selection = this.table.getSelection();
|
||||
if (selection == null) {
|
||||
return Collections.emptyList();
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
return Arrays.asList(selection)
|
||||
.stream()
|
||||
.map(this::getRowDataId)
|
||||
.collect(Collectors.toList());
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
private void createTableColumns() {
|
||||
|
@ -227,7 +228,11 @@ public class EntityTable<ROW extends Entity> extends Composite {
|
|||
// TODO set an image or HTML with checkbox
|
||||
item.setText(index, String.valueOf(value));
|
||||
} else {
|
||||
item.setText(index, String.valueOf(value));
|
||||
if (value != null) {
|
||||
item.setText(index, String.valueOf(value));
|
||||
} else {
|
||||
item.setText(index, Constants.EMPTY_NOTE);
|
||||
}
|
||||
}
|
||||
index++;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,149 @@
|
|||
/*
|
||||
* Copyright (c) 2019 ETH Zürich, Educational Development and Technology (LET)
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package ch.ethz.seb.sebserver.gui.service.widget;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Base64;
|
||||
|
||||
import org.apache.commons.codec.binary.Base64InputStream;
|
||||
import org.eclipse.rap.fileupload.FileDetails;
|
||||
import org.eclipse.rap.fileupload.FileUploadHandler;
|
||||
import org.eclipse.rap.fileupload.FileUploadReceiver;
|
||||
import org.eclipse.rap.rwt.RWT;
|
||||
import org.eclipse.rap.rwt.widgets.FileUpload;
|
||||
import org.eclipse.swt.SWT;
|
||||
import org.eclipse.swt.events.SelectionAdapter;
|
||||
import org.eclipse.swt.events.SelectionEvent;
|
||||
import org.eclipse.swt.graphics.Image;
|
||||
import org.eclipse.swt.layout.GridData;
|
||||
import org.eclipse.swt.layout.GridLayout;
|
||||
import org.eclipse.swt.widgets.Composite;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import ch.ethz.seb.sebserver.gui.service.push.ServerPushContext;
|
||||
import ch.ethz.seb.sebserver.gui.service.push.ServerPushService;
|
||||
|
||||
public class ImageUpload extends Composite {
|
||||
|
||||
private static final long serialVersionUID = 368264811155804533L;
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(ImageUpload.class);
|
||||
|
||||
private final ServerPushService serverPushService;
|
||||
|
||||
final Composite imageCanvas;
|
||||
final FileUpload fileUpload;
|
||||
private String imageBase64 = null;
|
||||
private boolean loadNewImage = false;
|
||||
private boolean imageLoaded = false;
|
||||
|
||||
ImageUpload(final Composite parent, final ServerPushService serverPushService) {
|
||||
super(parent, SWT.NONE);
|
||||
super.setLayout(new GridLayout(2, false));
|
||||
|
||||
this.serverPushService = serverPushService;
|
||||
|
||||
this.fileUpload = new FileUpload(this, SWT.NONE);
|
||||
this.fileUpload.setText("Select File");
|
||||
this.fileUpload.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, false, false));
|
||||
|
||||
this.imageCanvas = new Composite(this, SWT.NONE);
|
||||
final GridData canvas = new GridData(SWT.FILL, SWT.FILL, true, true);
|
||||
this.imageCanvas.setLayoutData(canvas);
|
||||
|
||||
final FileUploadHandler uploadHandler = new FileUploadHandler(new FileUploadReceiver() {
|
||||
|
||||
@Override
|
||||
public void receive(final InputStream stream, final FileDetails details) throws IOException {
|
||||
try {
|
||||
final String contentType = details.getContentType();
|
||||
if (contentType != null && contentType.startsWith("image")) {
|
||||
ImageUpload.this.imageBase64 = Base64.getEncoder().encodeToString(stream.readAllBytes());
|
||||
}
|
||||
} catch (final Exception e) {
|
||||
log.error("Error while trying to upload image", e);
|
||||
} finally {
|
||||
ImageUpload.this.imageLoaded = true;
|
||||
stream.close();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
this.fileUpload.addSelectionListener(new SelectionAdapter() {
|
||||
|
||||
private static final long serialVersionUID = -6776734104137568801L;
|
||||
|
||||
@Override
|
||||
public void widgetSelected(final SelectionEvent event) {
|
||||
ImageUpload.this.loadNewImage = true;
|
||||
ImageUpload.this.imageLoaded = false;
|
||||
ImageUpload.this.fileUpload.submit(uploadHandler.getUploadUrl());
|
||||
|
||||
ImageUpload.this.serverPushService.runServerPush(
|
||||
new ServerPushContext(
|
||||
ImageUpload.this,
|
||||
runAgainContext -> {
|
||||
final ImageUpload imageUpload = (ImageUpload) runAgainContext.getAnchor();
|
||||
return imageUpload.loadNewImage && !imageUpload.imageLoaded;
|
||||
}),
|
||||
context -> {
|
||||
try {
|
||||
Thread.sleep(200);
|
||||
} catch (final Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
},
|
||||
context -> {
|
||||
final ImageUpload imageUpload = (ImageUpload) context.getAnchor();
|
||||
if (imageUpload.imageBase64 != null
|
||||
&& imageUpload.loadNewImage
|
||||
&& imageUpload.imageLoaded) {
|
||||
final Base64InputStream input = new Base64InputStream(
|
||||
new ByteArrayInputStream(
|
||||
imageUpload.imageBase64.getBytes(StandardCharsets.UTF_8)),
|
||||
false);
|
||||
|
||||
imageUpload.imageCanvas.setData(RWT.CUSTOM_VARIANT, "bgLogoNoImage");
|
||||
imageUpload.imageCanvas.setBackgroundImage(new Image(context.getDisplay(), input));
|
||||
context.layout();
|
||||
imageUpload.layout();
|
||||
imageUpload.loadNewImage = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
public String getImageBase64() {
|
||||
return this.imageBase64;
|
||||
}
|
||||
|
||||
public void setImageBase64(final String imageBase64) {
|
||||
if (imageBase64 == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.imageBase64 = imageBase64;
|
||||
final Base64InputStream input = new Base64InputStream(
|
||||
new ByteArrayInputStream(imageBase64.getBytes(StandardCharsets.UTF_8)), false);
|
||||
this.imageCanvas.setData(RWT.CUSTOM_VARIANT, "bgLogoNoImage");
|
||||
this.imageCanvas.setBackgroundImage(new Image(super.getDisplay(), input));
|
||||
}
|
||||
|
||||
public void setReadonly() {
|
||||
this.fileUpload.setVisible(false);
|
||||
this.fileUpload.setEnabled(false);
|
||||
}
|
||||
|
||||
}
|
|
@ -16,6 +16,7 @@ import java.util.List;
|
|||
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.graphics.Device;
|
||||
|
@ -39,6 +40,7 @@ import org.slf4j.LoggerFactory;
|
|||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.Constants;
|
||||
import ch.ethz.seb.sebserver.gbl.model.Entity;
|
||||
import ch.ethz.seb.sebserver.gbl.model.Page;
|
||||
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
|
||||
|
@ -47,6 +49,7 @@ 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.PageContext;
|
||||
import ch.ethz.seb.sebserver.gui.service.push.ServerPushService;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCall;
|
||||
import ch.ethz.seb.sebserver.gui.service.table.TableBuilder;
|
||||
|
||||
|
@ -78,6 +81,10 @@ public class WidgetFactory {
|
|||
MAXIMIZE("maximize.png"),
|
||||
MINIMIZE("minimize.png"),
|
||||
MODIFY_ACTION("editAction.png"),
|
||||
CANCEL_ACTION("cancelEditAction.png"),
|
||||
VIEW_ACTION("viewAction.png"),
|
||||
ACTIVATE_ACTION("inactive.png"),
|
||||
DEACTIVATE_ACTION("active.png"),
|
||||
SAVE_ACTION("saveAction.png"),
|
||||
NEW_ACTION("newAction.png"),
|
||||
DELETE_ACTION("deleteAction.png"),
|
||||
|
@ -108,10 +115,15 @@ public class WidgetFactory {
|
|||
|
||||
private final PolyglotPageService polyglotPageService;
|
||||
private final I18nSupport i18nSupport;
|
||||
private final ServerPushService serverPushService;
|
||||
|
||||
public WidgetFactory(
|
||||
final PolyglotPageService polyglotPageService,
|
||||
final ServerPushService serverPushService) {
|
||||
|
||||
public WidgetFactory(final PolyglotPageService polyglotPageService) {
|
||||
this.polyglotPageService = polyglotPageService;
|
||||
this.i18nSupport = polyglotPageService.getI18nSupport();
|
||||
this.serverPushService = serverPushService;
|
||||
}
|
||||
|
||||
public Button buttonLocalized(final Composite parent, final String locTextKey) {
|
||||
|
@ -265,7 +277,7 @@ public class WidgetFactory {
|
|||
|
||||
public Label formValueLabel(final Composite parent, final String value, final int span) {
|
||||
final Label label = new Label(parent, SWT.NONE);
|
||||
label.setText(value);
|
||||
label.setText((StringUtils.isNoneBlank(value)) ? value : Constants.EMPTY_NOTE);
|
||||
final GridData gridData = new GridData(SWT.LEFT, SWT.CENTER, true, false, span, 1);
|
||||
label.setLayoutData(gridData);
|
||||
return label;
|
||||
|
@ -280,7 +292,9 @@ public class WidgetFactory {
|
|||
final GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, false, hspan, vspan);
|
||||
gridData.heightHint = 15;
|
||||
textInput.setLayoutData(gridData);
|
||||
textInput.setText(value);
|
||||
if (value != null) {
|
||||
textInput.setText(value);
|
||||
}
|
||||
return textInput;
|
||||
}
|
||||
|
||||
|
@ -325,6 +339,31 @@ public class WidgetFactory {
|
|||
return combo;
|
||||
}
|
||||
|
||||
public ImageUpload formImageUpload(
|
||||
final Composite parent,
|
||||
final String value,
|
||||
final LocTextKey locTextKey,
|
||||
final int hspan, final int vspan) {
|
||||
|
||||
final ImageUpload imageUpload = imageUploadLocalized(parent, locTextKey);
|
||||
final GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, false, hspan, vspan);
|
||||
imageUpload.setLayoutData(gridData);
|
||||
imageUpload.setImageBase64(value);
|
||||
return imageUpload;
|
||||
}
|
||||
|
||||
public ImageUpload imageUploadLocalized(final Composite parent, final LocTextKey locTextKey) {
|
||||
final ImageUpload imageUpload = new ImageUpload(parent, this.serverPushService);
|
||||
injectI18n(imageUpload, locTextKey);
|
||||
return imageUpload;
|
||||
}
|
||||
|
||||
public void injectI18n(final ImageUpload imageUpload, final LocTextKey locTextKey) {
|
||||
final Consumer<ImageUpload> imageUploadFunction = imageUploadFunction(locTextKey, this.i18nSupport);
|
||||
imageUpload.setData(POLYGLOT_WIDGET_FUNCTION_KEY, imageUploadFunction);
|
||||
imageUploadFunction.accept(imageUpload);
|
||||
}
|
||||
|
||||
public void injectI18n(final Label label, final LocTextKey locTextKey) {
|
||||
injectI18n(label, locTextKey, null);
|
||||
}
|
||||
|
@ -409,6 +448,17 @@ public class WidgetFactory {
|
|||
}
|
||||
}
|
||||
|
||||
private static Consumer<ImageUpload> imageUploadFunction(
|
||||
final LocTextKey locTextKey,
|
||||
final I18nSupport i18nSupport) {
|
||||
|
||||
return imageUpload -> {
|
||||
if (locTextKey != null) {
|
||||
imageUpload.fileUpload.setText(i18nSupport.getText(locTextKey));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static Consumer<Tree> treeFunction(final I18nSupport i18nSupport) {
|
||||
return tree -> updateLocale(tree.getItems(), i18nSupport);
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
package ch.ethz.seb.sebserver.webservice.servicelayer.authorization;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.authorization.PrivilegeType;
|
||||
import ch.ethz.seb.sebserver.gbl.model.EntityType;
|
||||
|
||||
/** Defines a authorization grant rule for a specified EntityType.
|
||||
|
|
|
@ -11,6 +11,7 @@ package ch.ethz.seb.sebserver.webservice.servicelayer.authorization;
|
|||
import java.security.Principal;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.authorization.PrivilegeType;
|
||||
import ch.ethz.seb.sebserver.gbl.model.EntityType;
|
||||
import ch.ethz.seb.sebserver.gbl.util.Result;
|
||||
|
||||
|
|
|
@ -20,11 +20,13 @@ import javax.annotation.PostConstruct;
|
|||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.authorization.Privilege;
|
||||
import ch.ethz.seb.sebserver.gbl.authorization.PrivilegeType;
|
||||
import ch.ethz.seb.sebserver.gbl.authorization.Privilege.RoleTypeKey;
|
||||
import ch.ethz.seb.sebserver.gbl.model.EntityType;
|
||||
import ch.ethz.seb.sebserver.gbl.model.user.UserRole;
|
||||
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
|
||||
import ch.ethz.seb.sebserver.gbl.util.Result;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.Privilege.RoleTypeKey;
|
||||
|
||||
@Lazy
|
||||
@Service
|
||||
|
@ -430,6 +432,7 @@ public class AuthorizationGrantServiceImpl implements AuthorizationGrantService
|
|||
public void create() {
|
||||
final RoleTypeKey roleTypeKey = new RoleTypeKey(this.entityType, this.userRole);
|
||||
final Privilege roleTypeGrant = new Privilege(
|
||||
roleTypeKey,
|
||||
this.basePrivilege,
|
||||
this.institutionalPrivilege,
|
||||
this.ownerPrivilege);
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
package ch.ethz.seb.sebserver.webservice.servicelayer.authorization;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.authorization.PrivilegeType;
|
||||
import ch.ethz.seb.sebserver.gbl.model.EntityType;
|
||||
|
||||
public class PermissionDeniedException extends RuntimeException {
|
||||
|
|
|
@ -15,6 +15,7 @@ import org.springframework.web.bind.annotation.RequestMethod;
|
|||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.api.API;
|
||||
import ch.ethz.seb.sebserver.gbl.authorization.PrivilegeType;
|
||||
import ch.ethz.seb.sebserver.gbl.model.Entity;
|
||||
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
|
||||
import ch.ethz.seb.sebserver.gbl.model.EntityProcessingReport;
|
||||
|
@ -25,7 +26,6 @@ import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.UserRecordDynamic
|
|||
import ch.ethz.seb.sebserver.webservice.servicelayer.PaginationService;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.AuthorizationGrantService;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.GrantEntity;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.PrivilegeType;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.UserService;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.BulkAction;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.BulkAction.Type;
|
||||
|
|
|
@ -28,8 +28,9 @@ import org.springframework.web.bind.annotation.RequestMethod;
|
|||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.Constants;
|
||||
import ch.ethz.seb.sebserver.gbl.api.POSTMapper;
|
||||
import ch.ethz.seb.sebserver.gbl.api.API;
|
||||
import ch.ethz.seb.sebserver.gbl.api.POSTMapper;
|
||||
import ch.ethz.seb.sebserver.gbl.authorization.PrivilegeType;
|
||||
import ch.ethz.seb.sebserver.gbl.model.Domain;
|
||||
import ch.ethz.seb.sebserver.gbl.model.Entity;
|
||||
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
|
||||
|
@ -41,7 +42,6 @@ import ch.ethz.seb.sebserver.gbl.util.Result;
|
|||
import ch.ethz.seb.sebserver.webservice.servicelayer.PaginationService;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.AuthorizationGrantService;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.GrantEntity;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.PrivilegeType;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.UserService;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.BulkAction;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.BulkAction.Type;
|
||||
|
@ -103,10 +103,8 @@ public abstract class EntityController<T extends GrantEntity, M extends GrantEnt
|
|||
@RequestParam final MultiValueMap<String, String> allRequestParams) {
|
||||
|
||||
checkReadPrivilege(institutionId);
|
||||
final FilterMap filterMap = new FilterMap(allRequestParams);
|
||||
allRequestParams.putIfAbsent(
|
||||
Entity.FILTER_ATTR_INSTITUTION,
|
||||
Arrays.asList(String.valueOf(institutionId)));
|
||||
final FilterMap filterMap = new FilterMap(allRequestParams)
|
||||
.putIfAbsent(Entity.FILTER_ATTR_INSTITUTION, String.valueOf(institutionId));
|
||||
|
||||
return this.paginationService.getPage(
|
||||
pageNumber,
|
||||
|
@ -133,10 +131,8 @@ public abstract class EntityController<T extends GrantEntity, M extends GrantEnt
|
|||
@RequestParam final MultiValueMap<String, String> allRequestParams) {
|
||||
|
||||
checkReadPrivilege(institutionId);
|
||||
final FilterMap filterMap = new FilterMap(allRequestParams);
|
||||
allRequestParams.putIfAbsent(
|
||||
Entity.FILTER_ATTR_INSTITUTION,
|
||||
Arrays.asList(String.valueOf(institutionId)));
|
||||
final FilterMap filterMap = new FilterMap(allRequestParams)
|
||||
.putIfAbsent(Entity.FILTER_ATTR_INSTITUTION, String.valueOf(institutionId));
|
||||
|
||||
return getAll(filterMap)
|
||||
.getOrThrow()
|
||||
|
@ -211,10 +207,10 @@ public abstract class EntityController<T extends GrantEntity, M extends GrantEnt
|
|||
PrivilegeType.WRITE,
|
||||
institutionId);
|
||||
|
||||
allRequestParams.putIfAbsent(
|
||||
Domain.ATTR_INSTITUTION_ID,
|
||||
Arrays.asList(String.valueOf(institutionId)));
|
||||
final M requestModel = this.createNew(new POSTMapper(allRequestParams));
|
||||
final POSTMapper postMap = new POSTMapper(allRequestParams)
|
||||
.putIfAbsent(Domain.ATTR_INSTITUTION_ID, String.valueOf(institutionId));
|
||||
|
||||
final M requestModel = this.createNew(postMap);
|
||||
|
||||
return this.beanValidationService.validateBean(requestModel)
|
||||
.flatMap(this.entityDAO::createNew)
|
||||
|
|
|
@ -31,6 +31,7 @@ import org.springframework.web.bind.annotation.RequestParam;
|
|||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.api.POSTMapper;
|
||||
import ch.ethz.seb.sebserver.gbl.authorization.PrivilegeType;
|
||||
import ch.ethz.seb.sebserver.gbl.api.API;
|
||||
import ch.ethz.seb.sebserver.gbl.model.Domain.LMS_SETUP;
|
||||
import ch.ethz.seb.sebserver.gbl.model.Entity;
|
||||
|
@ -46,7 +47,6 @@ import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.ExamRecordDynamic
|
|||
import ch.ethz.seb.sebserver.webservice.servicelayer.PaginationService;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.PaginationService.SortOrder;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.AuthorizationGrantService;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.PrivilegeType;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.UserService;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.BulkActionService;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ExamDAO;
|
||||
|
|
|
@ -22,6 +22,7 @@ import org.springframework.web.bind.annotation.RequestMethod;
|
|||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.api.POSTMapper;
|
||||
import ch.ethz.seb.sebserver.gbl.authorization.PrivilegeType;
|
||||
import ch.ethz.seb.sebserver.gbl.api.API;
|
||||
import ch.ethz.seb.sebserver.gbl.model.EntityType;
|
||||
import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetup;
|
||||
|
@ -30,7 +31,6 @@ import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
|
|||
import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.LmsSetupRecordDynamicSqlSupport;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.PaginationService;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.AuthorizationGrantService;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.PrivilegeType;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.BulkActionService;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.LmsSetupDAO;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.UserActivityLogDAO;
|
||||
|
|
|
@ -15,6 +15,7 @@ import org.springframework.web.bind.annotation.RequestParam;
|
|||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.api.API;
|
||||
import ch.ethz.seb.sebserver.gbl.authorization.PrivilegeType;
|
||||
import ch.ethz.seb.sebserver.gbl.model.Domain.LMS_SETUP;
|
||||
import ch.ethz.seb.sebserver.gbl.model.Entity;
|
||||
import ch.ethz.seb.sebserver.gbl.model.EntityType;
|
||||
|
@ -23,7 +24,6 @@ import ch.ethz.seb.sebserver.gbl.model.exam.QuizData;
|
|||
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
|
||||
import ch.ethz.seb.sebserver.gbl.util.Utils;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.AuthorizationGrantService;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.PrivilegeType;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.UserService;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.lms.LmsAPIService;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.lms.LmsAPITemplate;
|
||||
|
|
|
@ -18,6 +18,7 @@ import org.springframework.web.bind.annotation.RequestParam;
|
|||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.api.API;
|
||||
import ch.ethz.seb.sebserver.gbl.authorization.PrivilegeType;
|
||||
import ch.ethz.seb.sebserver.gbl.model.EntityType;
|
||||
import ch.ethz.seb.sebserver.gbl.model.Page;
|
||||
import ch.ethz.seb.sebserver.gbl.model.user.UserActivityLog;
|
||||
|
@ -27,7 +28,6 @@ import ch.ethz.seb.sebserver.gbl.util.Utils;
|
|||
import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.UserRecordDynamicSqlSupport;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.PaginationService;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.AuthorizationGrantService;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.PrivilegeType;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.UserService;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.UserActivityLogDAO;
|
||||
|
||||
|
|
|
@ -6,6 +6,10 @@ sebserver.overall.version=SEB Server Version : {0}
|
|||
sebserver.overall.imprint=Imprint
|
||||
sebserver.overall.about=About
|
||||
|
||||
sebserver.overall.message.leave.without.save=You are leaving this page without saved changes!\nThe unsaved changes will be lost.\Are you sure to leave the page?
|
||||
sebserver.overall.upload=Please Select
|
||||
sebserver.overall.action.modify.cancel=Cancel
|
||||
sebserver.overall.action.modify.cancel.confirm=Are you sure to cancel? Modifications will be lost.
|
||||
|
||||
################################
|
||||
# Login Page
|
||||
|
@ -42,11 +46,24 @@ sebserver.institution.list.title=Institutions
|
|||
sebserver.institution.list.column.name=Name
|
||||
sebserver.institution.list.column.urlSuffix=URL Suffix
|
||||
sebserver.institution.list.column.active=Active
|
||||
sebserver.institution.action.new=New Institution
|
||||
sebserver.institution.action.modify=Edit Institution
|
||||
sebserver.institution.action.delete=Delete Institution
|
||||
sebserver.institution.info.pleaseSelect=Please Select an Institution from the Table first.
|
||||
|
||||
sebserver.institution.action.new=New Institution
|
||||
sebserver.institution.action.view=View Institution
|
||||
sebserver.institution.action.modify=Edit Institution
|
||||
sebserver.institution.action.save=Save Institution
|
||||
sebserver.institution.action.activate=Active
|
||||
sebserver.institution.action.deactivate=Active
|
||||
sebserver.institution.action.delete=Delete Institution
|
||||
|
||||
sebserver.institution.info.pleaseSelect=Please Select an Institution from the Table first.
|
||||
sebserver.institution.form.title=Institution ({0})
|
||||
|
||||
sebserver.institution.form.name=Name
|
||||
sebserver.institution.form.urlSuffix=URL Suffix
|
||||
sebserver.institution.form.logoImage=Logo Image
|
||||
|
||||
sebserver.form.validation.fieldError.name=Name is mandatory and must have a size between 3 and 255 character
|
||||
sebserver.form.validation.fieldError.urlSuffix=URL Suffix must have a size between 3 and 255 character
|
||||
################################
|
||||
# Form validation
|
||||
################################
|
||||
|
|
|
@ -163,7 +163,7 @@ Text.error {
|
|||
color: #4a4a4a;
|
||||
background-repeat: repeat;
|
||||
background-position: left top;
|
||||
background-color: #ff0000;
|
||||
background-color: #A8322D;
|
||||
background-image: none;
|
||||
text-shadow: none;
|
||||
box-shadow: none;
|
||||
|
@ -258,7 +258,9 @@ Button {
|
|||
|
||||
/* Push Buttons */
|
||||
Button[PUSH],
|
||||
Button[PUSH]:default {
|
||||
Button[PUSH]:default,
|
||||
FileUpload,
|
||||
FileUpload:default {
|
||||
font: bold 12px Arial, Helvetica, sans-serif;
|
||||
background-color: #0069B4;
|
||||
background-gradient-color: #0069B4;
|
||||
|
@ -270,14 +272,16 @@ Button[PUSH]:default {
|
|||
text-shadow: none;
|
||||
}
|
||||
|
||||
Button[PUSH]:pressed {
|
||||
Button[PUSH]:pressed,
|
||||
FileUpload:pressed {
|
||||
background-color: #444;
|
||||
color: #fff;
|
||||
background-gradient-color: #444;
|
||||
background-image: gradient( linear, left top, left bottom, from( #444 ), to( #444 ) );
|
||||
}
|
||||
|
||||
Button[PUSH]:hover {
|
||||
Button[PUSH]:hover,
|
||||
FileUpload:hover {
|
||||
background-color: #82BE1E;
|
||||
background-gradient-color: #82BE1E;
|
||||
background-image: gradient( linear, left top, left bottom, from( #82BE1E ), to( #82BE1E ) );
|
||||
|
@ -285,7 +289,8 @@ Button[PUSH]:hover {
|
|||
cursor: pointer;
|
||||
}
|
||||
|
||||
Button[PUSH]:disabled {
|
||||
Button[PUSH]:disabled,
|
||||
FileUpload:disabled {
|
||||
background-color: transparent;
|
||||
border: 1px solid #EAECEE;
|
||||
color: #c0c0c0;
|
||||
|
@ -293,7 +298,7 @@ Button[PUSH]:disabled {
|
|||
background-position: right;
|
||||
}
|
||||
|
||||
Button-FocusIndicator[PUSH] {
|
||||
Button-FocusIndicator[PUSH][BORDER] {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
|
|
BIN
src/main/resources/static/images/active.png
Normal file
BIN
src/main/resources/static/images/active.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 169 B |
BIN
src/main/resources/static/images/cancelAction.png
Normal file
BIN
src/main/resources/static/images/cancelAction.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 246 B |
BIN
src/main/resources/static/images/cancelEditAction.png
Normal file
BIN
src/main/resources/static/images/cancelEditAction.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 168 B |
BIN
src/main/resources/static/images/inactive.png
Normal file
BIN
src/main/resources/static/images/inactive.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 117 B |
BIN
src/main/resources/static/images/viewAction.png
Normal file
BIN
src/main/resources/static/images/viewAction.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 211 B |
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* 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.gbl.model.institution;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonParseException;
|
||||
import com.fasterxml.jackson.databind.JsonMappingException;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.api.JSONMapper;
|
||||
|
||||
public class InstitutionTest {
|
||||
|
||||
@Test
|
||||
public void test() throws JsonParseException, JsonMappingException, IOException {
|
||||
final String testJson = "{\"id\":\"1\",\"name\":\"ETH Zürichrgerg\",\"urlSuffix\":\"\"}";
|
||||
|
||||
final JSONMapper mapper = new JSONMapper();
|
||||
final Institution inst = mapper.readValue(testJson, Institution.class);
|
||||
}
|
||||
|
||||
}
|
|
@ -23,6 +23,7 @@ import org.junit.Test;
|
|||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.authorization.PrivilegeType;
|
||||
import ch.ethz.seb.sebserver.gbl.model.EntityType;
|
||||
import ch.ethz.seb.sebserver.gbl.model.user.UserInfo;
|
||||
import ch.ethz.seb.sebserver.gbl.model.user.UserRole;
|
||||
|
|
Loading…
Add table
Reference in a new issue