From 28556afae6976b914ef7e0ca0f3dfe6d5fbd9f57 Mon Sep 17 00:00:00 2001 From: anhefti Date: Wed, 20 Feb 2019 09:41:36 +0100 Subject: [PATCH] #SEBSERV-27 user account list (with filter) --- docker/demo/{DOCKERFILE => Dockerfile} | 0 pom.xml | 2 +- .../gui/service/{page => }/form/Form.java | 2 +- .../service/{page => }/form/FormBuilder.java | 2 +- .../service/{page => }/form/FormHandle.java | 6 +- .../{page => }/form/PageFormService.java | 2 +- .../gui/service/i18n/I18nSupport.java | 3 + .../service/i18n/impl/I18nSupportImpl.java | 4 +- .../FieldValidationError.java | 2 +- .../service/page/action/ActionDefinition.java | 62 +---- .../page/action/InstitutionActions.java | 6 +- .../service/page/activity/ActivitiesPane.java | 19 +- .../page/activity/ActivitySelection.java | 21 +- .../service/page/content/InstitutionForm.java | 35 +-- .../service/page/content/UserAccountForm.java | 42 +++ .../service/page/content/UserAccountList.java | 98 +++++++ .../service/page/impl/DefaultLoginPage.java | 2 +- .../service/page/impl/DefaultMainPage.java | 2 +- .../impl/{SEBLogin.java => LoginPage.java} | 16 +- .../impl/{SEBMainPage.java => MainPage.java} | 18 +- .../gui/service/page/impl/MainPageState.java | 6 +- .../api/FilterAttributeSupplier.java | 17 -- .../remote/webservice/api/RestCall.java | 14 +- .../remote/webservice/api/RestService.java | 31 ++- .../api/institution/GetInstitutionNames.java | 6 - .../api/useraccount/GetUserAccount.java | 37 +++ .../api/useraccount/GetUserAccounts.java | 38 +++ .../gui/service/table/ColumnDefinition.java | 86 ++++++- .../service/table/ColumnFilterDefinition.java | 13 - .../gui/service/table/EntityTable.java | 132 +++++++--- .../gui/service/table/TableBuilder.java | 18 +- .../gui/service/table/TableFilter.java | 242 +++++++++++++++++- .../gui/service/table/TableNavigator.java | 2 - .../gui/service/widget/ImageUpload.java | 5 +- .../gui/service/widget/LanguageSelector.java | 55 ++++ .../gui/service/widget/SingleSelection.java | 17 +- .../gui/service/widget/WidgetFactory.java | 119 ++++++--- .../weblayer/api/EntityController.java | 24 +- .../config/application-dev-gui.properties | 2 + .../resources/config/application.properties | 1 + src/main/resources/messages.properties | 32 ++- src/main/resources/static/css/sebserver.css | 8 +- .../images/{cancelAction.png => cancel.png} | Bin .../{cancelEditAction.png => cancelEdit.png} | Bin src/main/resources/static/images/delete.png | Bin 186 -> 148 bytes .../resources/static/images/deleteAction.png | Bin 148 -> 0 bytes .../static/images/deletePermanent.png | Bin 0 -> 186 bytes .../images/{editAction.png => edit.png} | Bin src/main/resources/static/images/lens.png | Bin 0 -> 220 bytes .../static/images/{newAction.png => new.png} | Bin .../images/{saveAction.png => save.png} | Bin .../images/{viewAction.png => show.png} | Bin .../integration/api/admin/UserAPITest.java | 20 +- 53 files changed, 973 insertions(+), 296 deletions(-) rename docker/demo/{DOCKERFILE => Dockerfile} (100%) rename src/main/java/ch/ethz/seb/sebserver/gui/service/{page => }/form/Form.java (96%) rename src/main/java/ch/ethz/seb/sebserver/gui/service/{page => }/form/FormBuilder.java (96%) rename src/main/java/ch/ethz/seb/sebserver/gui/service/{page => }/form/FormHandle.java (92%) rename src/main/java/ch/ethz/seb/sebserver/gui/service/{page => }/form/PageFormService.java (94%) rename src/main/java/ch/ethz/seb/sebserver/gui/service/page/{validation => }/FieldValidationError.java (92%) create mode 100644 src/main/java/ch/ethz/seb/sebserver/gui/service/page/content/UserAccountForm.java create mode 100644 src/main/java/ch/ethz/seb/sebserver/gui/service/page/content/UserAccountList.java rename src/main/java/ch/ethz/seb/sebserver/gui/service/page/impl/{SEBLogin.java => LoginPage.java} (87%) rename src/main/java/ch/ethz/seb/sebserver/gui/service/page/impl/{SEBMainPage.java => MainPage.java} (89%) delete mode 100644 src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/FilterAttributeSupplier.java create mode 100644 src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/useraccount/GetUserAccount.java create mode 100644 src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/useraccount/GetUserAccounts.java delete mode 100644 src/main/java/ch/ethz/seb/sebserver/gui/service/table/ColumnFilterDefinition.java create mode 100644 src/main/java/ch/ethz/seb/sebserver/gui/service/widget/LanguageSelector.java rename src/main/resources/static/images/{cancelAction.png => cancel.png} (100%) rename src/main/resources/static/images/{cancelEditAction.png => cancelEdit.png} (100%) delete mode 100644 src/main/resources/static/images/deleteAction.png create mode 100644 src/main/resources/static/images/deletePermanent.png rename src/main/resources/static/images/{editAction.png => edit.png} (100%) create mode 100644 src/main/resources/static/images/lens.png rename src/main/resources/static/images/{newAction.png => new.png} (100%) rename src/main/resources/static/images/{saveAction.png => save.png} (100%) rename src/main/resources/static/images/{viewAction.png => show.png} (100%) diff --git a/docker/demo/DOCKERFILE b/docker/demo/Dockerfile similarity index 100% rename from docker/demo/DOCKERFILE rename to docker/demo/Dockerfile diff --git a/pom.xml b/pom.xml index de4569e5..51b05d7d 100644 --- a/pom.xml +++ b/pom.xml @@ -58,7 +58,7 @@ Java 11 - true + false 11 diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/page/form/Form.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/form/Form.java similarity index 96% rename from src/main/java/ch/ethz/seb/sebserver/gui/service/page/form/Form.java rename to src/main/java/ch/ethz/seb/sebserver/gui/service/form/Form.java index 7d07f9c3..38def3a0 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/service/page/form/Form.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/form/Form.java @@ -6,7 +6,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -package ch.ethz.seb.sebserver.gui.service.page.form; +package ch.ethz.seb.sebserver.gui.service.form; import java.util.ArrayList; import java.util.HashSet; diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/page/form/FormBuilder.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/form/FormBuilder.java similarity index 96% rename from src/main/java/ch/ethz/seb/sebserver/gui/service/page/form/FormBuilder.java rename to src/main/java/ch/ethz/seb/sebserver/gui/service/form/FormBuilder.java index 21d9bf3a..ce6b0c17 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/service/page/form/FormBuilder.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/form/FormBuilder.java @@ -6,7 +6,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -package ch.ethz.seb.sebserver.gui.service.page.form; +package ch.ethz.seb.sebserver.gui.service.form; import java.util.List; import java.util.function.Consumer; diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/page/form/FormHandle.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/form/FormHandle.java similarity index 92% rename from src/main/java/ch/ethz/seb/sebserver/gui/service/page/form/FormHandle.java rename to src/main/java/ch/ethz/seb/sebserver/gui/service/form/FormHandle.java index 92ec7804..cda4f2dd 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/service/page/form/FormHandle.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/form/FormHandle.java @@ -6,7 +6,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -package ch.ethz.seb.sebserver.gui.service.page.form; +package ch.ethz.seb.sebserver.gui.service.form; import java.util.function.Consumer; import java.util.function.Function; @@ -15,14 +15,14 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import ch.ethz.seb.sebserver.gbl.util.Result; +import ch.ethz.seb.sebserver.gui.service.form.Form.FormFieldAccessor; 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.FieldValidationError; 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; -import ch.ethz.seb.sebserver.gui.service.page.validation.FieldValidationError; import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCall; import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCallError; diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/page/form/PageFormService.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/form/PageFormService.java similarity index 94% rename from src/main/java/ch/ethz/seb/sebserver/gui/service/page/form/PageFormService.java rename to src/main/java/ch/ethz/seb/sebserver/gui/service/form/PageFormService.java index 718ad67a..d967908f 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/service/page/form/PageFormService.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/form/PageFormService.java @@ -6,7 +6,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -package ch.ethz.seb.sebserver.gui.service.page.form; +package ch.ethz.seb.sebserver.gui.service.form; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Component; diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/i18n/I18nSupport.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/i18n/I18nSupport.java index 15995416..940d7722 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/service/i18n/I18nSupport.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/i18n/I18nSupport.java @@ -15,6 +15,9 @@ import org.joda.time.DateTime; public interface I18nSupport { + /** Get all supported languages as a collection of Locale + * + * @return all supported languages as a collection of Locale */ Collection supportedLanguages(); /** Get the current Locale either form a user if this is called from a logged in user context or the diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/i18n/impl/I18nSupportImpl.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/i18n/impl/I18nSupportImpl.java index 2c65d65a..d879074c 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/service/i18n/impl/I18nSupportImpl.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/i18n/impl/I18nSupportImpl.java @@ -53,11 +53,11 @@ public class I18nSupportImpl implements I18nSupport { .withZoneUTC(); } - private static final Collection SUPPORTED = Arrays.asList(Locale.ENGLISH, Locale.GERMANY); + private static final Collection SUPPORTED_LANGUAGES = Arrays.asList(Locale.ENGLISH, Locale.GERMAN); @Override public Collection supportedLanguages() { - return SUPPORTED; + return SUPPORTED_LANGUAGES; } @Override diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/page/validation/FieldValidationError.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/page/FieldValidationError.java similarity index 92% rename from src/main/java/ch/ethz/seb/sebserver/gui/service/page/validation/FieldValidationError.java rename to src/main/java/ch/ethz/seb/sebserver/gui/service/page/FieldValidationError.java index 1163d0d8..079a0b0c 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/service/page/validation/FieldValidationError.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/page/FieldValidationError.java @@ -6,7 +6,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -package ch.ethz.seb.sebserver.gui.service.page.validation; +package ch.ethz.seb.sebserver.gui.service.page; import ch.ethz.seb.sebserver.gbl.api.APIMessage; diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/page/action/ActionDefinition.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/page/action/ActionDefinition.java index 3d43e4f1..68ba4386 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/service/page/action/ActionDefinition.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/page/action/ActionDefinition.java @@ -8,88 +8,48 @@ package ch.ethz.seb.sebserver.gui.service.page.action; -import ch.ethz.seb.sebserver.gui.service.widget.WidgetFactory.IconButtonType; +import ch.ethz.seb.sebserver.gui.service.widget.WidgetFactory.ImageIcon; public enum ActionDefinition { INSTITUTION_NEW( "sebserver.institution.action.new", - IconButtonType.NEW_ACTION), + ImageIcon.NEW), INSTITUTION_VIEW( "sebserver.institution.action.view", - IconButtonType.VIEW_ACTION), + ImageIcon.SHOW), INSTITUTION_MODIFY( "sebserver.institution.action.modify", - IconButtonType.MODIFY_ACTION), + ImageIcon.EDIT), INSTITUTION_CANCEL_MODIFY( "sebserver.overall.action.modify.cancel", - IconButtonType.CANCEL_ACTION), + ImageIcon.CANCEL), INSTITUTION_SAVE( "sebserver.institution.action.save", - IconButtonType.SAVE_ACTION), + ImageIcon.SAVE), INSTITUTION_ACTIVATE( "sebserver.institution.action.activate", - IconButtonType.ACTIVATE_ACTION), + ImageIcon.INACTIVE), INSTITUTION_DEACTIVATE( "sebserver.institution.action.deactivate", - IconButtonType.DEACTIVATE_ACTION), + ImageIcon.ACTIVE), INSTITUTION_DELETE( "sebserver.institution.action.modify", - IconButtonType.DELETE_ACTION), - - LMS_SETUP_NEW( - "New LMS Setup", - IconButtonType.NEW_ACTION), - - LMS_SETUP_MODIFY( - "Save LMS Setup", - IconButtonType.SAVE_ACTION), - - LMS_SETUP_DELETE( - "Delete LMS Setup", - IconButtonType.DELETE_ACTION), - - LMS_SETUP_TEST( - "Test LMS Setup", - IconButtonType.SAVE_ACTION), - - SEB_CONFIG_NEW( - "New Configuration", - IconButtonType.NEW_ACTION), - - SEB_CONFIG_MODIFY( - "Save Configuration", - IconButtonType.SAVE_ACTION), - - SEB_CONFIG_DELETE( - "Delete Configuration", - IconButtonType.DELETE_ACTION), - - EXAM_IMPORT( - "Import Exam", - IconButtonType.SAVE_ACTION), - - EXAM_EDIT( - "Edit Selected Exam", - IconButtonType.NEW_ACTION), - - EXAM_DELETE( - "Delete Selected Exam", - IconButtonType.DELETE_ACTION), + ImageIcon.DELETE), ; public final String name; - public final IconButtonType icon; + public final ImageIcon icon; - private ActionDefinition(final String name, final IconButtonType icon) { + private ActionDefinition(final String name, final ImageIcon icon) { this.name = name; this.icon = icon; } diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/page/action/InstitutionActions.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/page/action/InstitutionActions.java index aa281d51..8da1c6ea 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/service/page/action/InstitutionActions.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/page/action/InstitutionActions.java @@ -8,8 +8,6 @@ package ch.ethz.seb.sebserver.gui.service.page.action; -import static ch.ethz.seb.sebserver.gui.service.page.activity.ActivitySelection.Activity.INSTITUTION_NODE; - import java.util.Collection; import java.util.function.Function; @@ -22,10 +20,12 @@ 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.activity.ActivitySelection.Activity; import ch.ethz.seb.sebserver.gui.service.page.event.ActivitySelectionEvent; import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.institution.ActivateInstitution; import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.institution.DeactivateInstitution; +/** Defines the action execution functions for all Institution action. */ public final class InstitutionActions { public static Function postSaveAdapter(final PageContext pageContext) { @@ -92,7 +92,7 @@ public final class InstitutionActions { private static ActivitySelection goToInstitution(final PageContext pageContext, final String modelId, final boolean edit) { - final ActivitySelection activitySelection = INSTITUTION_NODE + final ActivitySelection activitySelection = Activity.INSTITUTION_FORM .createSelection() .withEntity(new EntityKey(modelId, EntityType.INSTITUTION)) .withAttribute(AttributeKeys.READ_ONLY, String.valueOf(!edit)) diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/page/activity/ActivitiesPane.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/page/activity/ActivitiesPane.java index c9769baa..3df94d6c 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/service/page/activity/ActivitiesPane.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/page/activity/ActivitiesPane.java @@ -90,30 +90,31 @@ public class ActivitiesPane implements TemplateComposer { navigationGridData.horizontalIndent = 10; navigation.setLayoutData(navigationGridData); - // institution + // Institution if (userInfo.hasRole(UserRole.SEB_SERVER_ADMIN)) { // institutions (list) as root final TreeItem institutions = this.widgetFactory.treeItemLocalized( navigation, - Activity.INSTITUTION_ROOT.title); - injectActivitySelection(institutions, Activity.INSTITUTION_ROOT.createSelection()); + Activity.INSTITUTION_LIST.title); + injectActivitySelection(institutions, Activity.INSTITUTION_LIST.createSelection()); } else { // institution node as none root final TreeItem institutions = this.widgetFactory.treeItemLocalized( navigation, - Activity.INSTITUTION_NODE.title); + Activity.INSTITUTION_FORM.title); injectActivitySelection( institutions, - Activity.INSTITUTION_NODE.createSelection() + Activity.INSTITUTION_FORM.createSelection() .withEntity(new EntityKey(userInfo.institutionId, EntityType.INSTITUTION)) .withAttribute(AttributeKeys.READ_ONLY, "true")); } -// final TreeItem user = this.widgetFactory.treeItemLocalized( -// navigation, -// "org.sebserver.activities.user"); -// ActivitySelection.set(user, Activity.USERS.createSelection()); + // User Account + final TreeItem userAccounts = this.widgetFactory.treeItemLocalized( + navigation, + Activity.USER_ACCOUNT_LIST.title); + injectActivitySelection(userAccounts, Activity.USER_ACCOUNT_LIST.createSelection()); // // final TreeItem configs = this.widgetFactory.treeItemLocalized( // navigation, diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/page/activity/ActivitySelection.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/page/activity/ActivitySelection.java index 03eabe17..7e216349 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/service/page/activity/ActivitySelection.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/page/activity/ActivitySelection.java @@ -22,6 +22,7 @@ import ch.ethz.seb.sebserver.gui.service.page.TemplateComposer; import ch.ethz.seb.sebserver.gui.service.page.action.ActionPane; import ch.ethz.seb.sebserver.gui.service.page.content.InstitutionForm; import ch.ethz.seb.sebserver.gui.service.page.content.InstitutionList; +import ch.ethz.seb.sebserver.gui.service.page.content.UserAccountList; import ch.ethz.seb.sebserver.gui.service.page.impl.TODOTemplate; public class ActivitySelection { @@ -35,15 +36,25 @@ public class ActivitySelection { public enum Activity { NONE(TODOTemplate.class, TODOTemplate.class), - INSTITUTION_ROOT( + INSTITUTION_LIST( InstitutionList.class, ActionPane.class, - new LocTextKey("sebserver.activities.inst")), - INSTITUTION_NODE( + new LocTextKey("sebserver.activities.institution")), + INSTITUTION_FORM( InstitutionForm.class, ActionPane.class, - new LocTextKey("sebserver.activities.inst")), -// + new LocTextKey("sebserver.activities.institution")), + + USER_ACCOUNT_LIST( + UserAccountList.class, + ActionPane.class, + new LocTextKey("sebserver.activities.useraccount")), + + USER_ACCOUNT_FORM( + UserAccountList.class, + ActionPane.class, + new LocTextKey("sebserver.activities.useraccount")), + // USERS(UserAccountsForm.class, ActionPane.class), // // EXAMS(ExamsListPage.class, ActionPane.class), diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/page/content/InstitutionForm.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/page/content/InstitutionForm.java index fcfcf8fc..791e0b24 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/service/page/content/InstitutionForm.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/page/content/InstitutionForm.java @@ -13,11 +13,7 @@ import java.util.UUID; import java.util.function.Supplier; 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.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.context.annotation.Lazy; @@ -31,15 +27,14 @@ import ch.ethz.seb.sebserver.gbl.model.Entity; import ch.ethz.seb.sebserver.gbl.model.EntityKey; import ch.ethz.seb.sebserver.gbl.model.institution.Institution; import ch.ethz.seb.sebserver.gbl.profile.GuiProfile; +import ch.ethz.seb.sebserver.gui.service.form.FormHandle; +import ch.ethz.seb.sebserver.gui.service.form.PageFormService; import ch.ethz.seb.sebserver.gui.service.i18n.LocTextKey; import ch.ethz.seb.sebserver.gui.service.page.PageContext; import ch.ethz.seb.sebserver.gui.service.page.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.GetInstitutionDependency; @@ -107,29 +102,17 @@ public class InstitutionForm implements TemplateComposer { 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 (interactive9 - 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, + // the default page layout with interactive title + final Composite content = widgetFactory.defaultPageLayout( + formContext.getParent(), + new LocTextKey("sebserver.institution.form.title", institution.name), ActionDefinition.INSTITUTION_SAVE, - event -> { + title -> event -> { final Entity entity = (Entity) event.source; - widgetFactory.injectI18n(pageTitle, new LocTextKey( + widgetFactory.injectI18n(title, new LocTextKey( "sebserver.institution.form.title", entity.getName())); - content.layout(); + title.getParent().layout(); }); // The Institution form diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/page/content/UserAccountForm.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/page/content/UserAccountForm.java new file mode 100644 index 00000000..6662772c --- /dev/null +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/page/content/UserAccountForm.java @@ -0,0 +1,42 @@ +/* + * 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 org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Component; + +import ch.ethz.seb.sebserver.gbl.profile.GuiProfile; +import ch.ethz.seb.sebserver.gui.service.page.PageContext; +import ch.ethz.seb.sebserver.gui.service.page.TemplateComposer; +import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestService; +import ch.ethz.seb.sebserver.gui.service.widget.WidgetFactory; + +@Lazy +@Component +@GuiProfile +public class UserAccountForm implements TemplateComposer { + + private final WidgetFactory widgetFactory; + private final RestService restService; + + protected UserAccountForm( + final WidgetFactory widgetFactory, + final RestService restService) { + + this.widgetFactory = widgetFactory; + this.restService = restService; + } + + @Override + public void compose(final PageContext pageContext) { + // TODO Auto-generated method stub + + } + +} diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/page/content/UserAccountList.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/page/content/UserAccountList.java new file mode 100644 index 00000000..d733253c --- /dev/null +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/page/content/UserAccountList.java @@ -0,0 +1,98 @@ +/* + * 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 org.eclipse.swt.widgets.Composite; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Component; + +import ch.ethz.seb.sebserver.gbl.model.Domain; +import ch.ethz.seb.sebserver.gbl.model.user.UserInfo; +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.TemplateComposer; +import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestService; +import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.useraccount.GetUserAccounts; +import ch.ethz.seb.sebserver.gui.service.table.ColumnDefinition; +import ch.ethz.seb.sebserver.gui.service.table.ColumnDefinition.TableFilterAttribute; +import ch.ethz.seb.sebserver.gui.service.table.EntityTable; +import ch.ethz.seb.sebserver.gui.service.table.TableFilter.CriteriaType; +import ch.ethz.seb.sebserver.gui.service.widget.WidgetFactory; + +@Lazy +@Component +@GuiProfile +public class UserAccountList implements TemplateComposer { + + private final WidgetFactory widgetFactory; + private final RestService restService; + private final int pageSize; + + protected UserAccountList( + final WidgetFactory widgetFactory, + final RestService restService, + @Value("${sebserver.gui.list.page.size}") final Integer pageSize) { + + this.widgetFactory = widgetFactory; + this.restService = restService; + this.pageSize = (pageSize != null) ? pageSize : 20; + } + + @Override + public void compose(final PageContext pageContext) { + final Composite content = this.widgetFactory.defaultPageLayout( + pageContext.getParent(), + new LocTextKey("sebserver.useraccount.list.title")); + + // table + final EntityTable table = + this.widgetFactory.entityTableBuilder(this.restService.getRestCall(GetUserAccounts.class)) + .withPaging(this.pageSize) + .withColumn(new ColumnDefinition<>( + Domain.USER.ATTR_NAME, + new LocTextKey("sebserver.useraccount.list.column.name"), + entity -> entity.name, + new TableFilterAttribute(CriteriaType.TEXT, Domain.USER.ATTR_NAME), + true)) + .withColumn(new ColumnDefinition<>( + Domain.USER.ATTR_USERNAME, + new LocTextKey("sebserver.useraccount.list.column.username"), + entity -> entity.username, + new TableFilterAttribute(CriteriaType.TEXT, Domain.USER.ATTR_USERNAME), + true)) + .withColumn(new ColumnDefinition<>( + Domain.USER.ATTR_EMAIL, + new LocTextKey("sebserver.useraccount.list.column.email"), + entity -> entity.email, + new TableFilterAttribute(CriteriaType.TEXT, Domain.USER.ATTR_EMAIL), + true)) + .withColumn(new ColumnDefinition<>( + Domain.USER.ATTR_LOCALE, + new LocTextKey("sebserver.useraccount.list.column.language"), + this::getLocaleDisplayText, + new TableFilterAttribute(CriteriaType.COUNTRY_SELECTION, Domain.USER.ATTR_LOCALE), + true, true)) + .withColumn(new ColumnDefinition<>( + Domain.USER.ATTR_ACTIVE, + new LocTextKey("sebserver.useraccount.list.column.active"), + entity -> entity.active, + true)) + .compose(content); + + } + + private String getLocaleDisplayText(final UserInfo userInfo) { + return (userInfo.locale != null) + ? userInfo.locale.getDisplayLanguage(this.widgetFactory.getI18nSupport().getCurrentLocale()) + : null; + } + +} diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/page/impl/DefaultLoginPage.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/page/impl/DefaultLoginPage.java index 1ab66970..d7e29da8 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/service/page/impl/DefaultLoginPage.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/page/impl/DefaultLoginPage.java @@ -31,7 +31,7 @@ public class DefaultLoginPage implements PageDefinition { public PageContext applyPageContext(final PageContext pageContext) { return pageContext.withAttribute( AttributeKeys.PAGE_TEMPLATE_COMPOSER_NAME, - SEBLogin.class.getName()); + LoginPage.class.getName()); } } diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/page/impl/DefaultMainPage.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/page/impl/DefaultMainPage.java index 20428438..a7c92fd0 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/service/page/impl/DefaultMainPage.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/page/impl/DefaultMainPage.java @@ -31,7 +31,7 @@ public class DefaultMainPage implements PageDefinition { public PageContext applyPageContext(final PageContext pageContext) { return pageContext.withAttribute( AttributeKeys.PAGE_TEMPLATE_COMPOSER_NAME, - SEBMainPage.class.getName()); + MainPage.class.getName()); } } diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/page/impl/SEBLogin.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/page/impl/LoginPage.java similarity index 87% rename from src/main/java/ch/ethz/seb/sebserver/gui/service/page/impl/SEBLogin.java rename to src/main/java/ch/ethz/seb/sebserver/gui/service/page/impl/LoginPage.java index 4468ff5d..062b8962 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/service/page/impl/SEBLogin.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/page/impl/LoginPage.java @@ -34,15 +34,15 @@ import ch.ethz.seb.sebserver.gui.service.widget.WidgetFactory; @Lazy @Component @GuiProfile -public class SEBLogin implements TemplateComposer { +public class LoginPage implements TemplateComposer { - private static final Logger log = LoggerFactory.getLogger(SEBLogin.class); + private static final Logger log = LoggerFactory.getLogger(LoginPage.class); private final AuthorizationContextHolder authorizationContextHolder; private final WidgetFactory widgetFactory; private final I18nSupport i18nSupport; - public SEBLogin( + public LoginPage( final AuthorizationContextHolder authorizationContextHolder, final WidgetFactory widgetFactory, final I18nSupport i18nSupport) { @@ -56,16 +56,6 @@ 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); -// pageContext = pageContext.removeAttribute(AttributeKeys.LGOUT_SUCCESS); -// } - final Composite loginGroup = new Composite(parent, SWT.NONE); final GridLayout rowLayout = new GridLayout(); rowLayout.marginWidth = 20; diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/page/impl/SEBMainPage.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/page/impl/MainPage.java similarity index 89% rename from src/main/java/ch/ethz/seb/sebserver/gui/service/page/impl/SEBMainPage.java rename to src/main/java/ch/ethz/seb/sebserver/gui/service/page/impl/MainPage.java index 8d3f59ef..0dd9f14e 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/service/page/impl/SEBMainPage.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/page/impl/MainPage.java @@ -29,20 +29,20 @@ import ch.ethz.seb.sebserver.gui.service.page.event.ActivitySelectionEvent; import ch.ethz.seb.sebserver.gui.service.page.event.ActivitySelectionListener; import ch.ethz.seb.sebserver.gui.service.page.event.PageEventListener; import ch.ethz.seb.sebserver.gui.service.widget.WidgetFactory; -import ch.ethz.seb.sebserver.gui.service.widget.WidgetFactory.IconButtonType; +import ch.ethz.seb.sebserver.gui.service.widget.WidgetFactory.ImageIcon; @Lazy @Component @GuiProfile -public class SEBMainPage implements TemplateComposer { +public class MainPage implements TemplateComposer { - static final Logger log = LoggerFactory.getLogger(SEBMainPage.class); + static final Logger log = LoggerFactory.getLogger(MainPage.class); public static final String ATTR_MAIN_PAGE_STATE = "MAIN_PAGE_STATE"; - private static final int ACTIVITY_PANE_WEIGHT = 20; + private static final int ACTIVITY_PANE_WEIGHT = 15; private static final int CONTENT_PANE_WEIGHT = 65; - private static final int ACTION_PANE_WEIGHT = 15; + private static final int ACTION_PANE_WEIGHT = 20; private static final int[] DEFAULT_SASH_WEIGHTS = new int[] { ACTIVITY_PANE_WEIGHT, CONTENT_PANE_WEIGHT, @@ -52,7 +52,7 @@ public class SEBMainPage implements TemplateComposer { private final WidgetFactory widgetFactory; - public SEBMainPage(final WidgetFactory widgetFactory) { + public MainPage(final WidgetFactory widgetFactory) { this.widgetFactory = widgetFactory; } @@ -84,7 +84,7 @@ public class SEBMainPage implements TemplateComposer { content.setLayout(contentOuterlayout); final Label toggleView = this.widgetFactory.imageButton( - IconButtonType.MAXIMIZE, + ImageIcon.MAXIMIZE, content, new LocTextKey("sebserver.mainpage.maximize.tooltip"), event -> { @@ -92,7 +92,7 @@ public class SEBMainPage implements TemplateComposer { if ((Boolean) ib.getData("fullScreen")) { mainSash.setWeights(DEFAULT_SASH_WEIGHTS); ib.setData("fullScreen", false); - ib.setImage(WidgetFactory.IconButtonType.MAXIMIZE.getImage(ib.getDisplay())); + ib.setImage(WidgetFactory.ImageIcon.MAXIMIZE.getImage(ib.getDisplay())); this.widgetFactory.injectI18n( ib, null, @@ -100,7 +100,7 @@ public class SEBMainPage implements TemplateComposer { } else { mainSash.setWeights(OPENED_SASH_WEIGHTS); ib.setData("fullScreen", true); - ib.setImage(WidgetFactory.IconButtonType.MINIMIZE.getImage(ib.getDisplay())); + ib.setImage(WidgetFactory.ImageIcon.MINIMIZE.getImage(ib.getDisplay())); this.widgetFactory.injectI18n( ib, null, diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/page/impl/MainPageState.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/page/impl/MainPageState.java index ba00cb21..665a8f00 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/service/page/impl/MainPageState.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/page/impl/MainPageState.java @@ -28,15 +28,15 @@ public final class MainPageState { .getUISession() .getHttpSession(); - MainPageState mainPageState = (MainPageState) httpSession.getAttribute(SEBMainPage.ATTR_MAIN_PAGE_STATE); + MainPageState mainPageState = (MainPageState) httpSession.getAttribute(MainPage.ATTR_MAIN_PAGE_STATE); if (mainPageState == null) { mainPageState = new MainPageState(); - httpSession.setAttribute(SEBMainPage.ATTR_MAIN_PAGE_STATE, mainPageState); + httpSession.setAttribute(MainPage.ATTR_MAIN_PAGE_STATE, mainPageState); } return mainPageState; } catch (final Exception e) { - SEBMainPage.log.error("Unexpected error while trying to get MainPageState from user-session"); + MainPage.log.error("Unexpected error while trying to get MainPageState from user-session"); } return null; diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/FilterAttributeSupplier.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/FilterAttributeSupplier.java deleted file mode 100644 index 33f1057b..00000000 --- a/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/FilterAttributeSupplier.java +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright (c) 2019 ETH Zürich, Educational Development and Technology (LET) - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -package ch.ethz.seb.sebserver.gui.service.remote.webservice.api; - -import org.springframework.util.MultiValueMap; - -public interface FilterAttributeSupplier { - - MultiValueMap getAttributes(); - -} diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/RestCall.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/RestCall.java index 3e73716a..252a72fa 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/RestCall.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/RestCall.java @@ -171,6 +171,13 @@ public abstract class RestCall { return this; } + public RestCallBuilder withQueryParams(final MultiValueMap params) { + if (params != null) { + this.queryParams.putAll(params); + } + return this; + } + public RestCallBuilder withPaging(final int pageNumber, final int pageSize) { this.queryParams.put(Page.ATTR_PAGE_NUMBER, Arrays.asList(String.valueOf(pageNumber))); this.queryParams.put(Page.ATTR_PAGE_SIZE, Arrays.asList(String.valueOf(pageSize))); @@ -184,13 +191,6 @@ public abstract class RestCall { return this; } - public RestCallBuilder withFilterAttributes(final FilterAttributeSupplier filterAttributes) { - if (filterAttributes != null) { - this.queryParams.putAll(filterAttributes.getAttributes()); - } - return this; - } - public RestCallBuilder withFormBinding(final FormBinding formBinding) { return withURIVariable(API.PARAM_MODEL_ID, formBinding.entityKey().modelId) .withBody(formBinding.getFormAsJson()); diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/RestService.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/RestService.java index 26ffeb3b..ab33b8b6 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/RestService.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/RestService.java @@ -9,9 +9,13 @@ package ch.ethz.seb.sebserver.gui.service.remote.webservice.api; import java.util.Collection; +import java.util.Collections; +import java.util.List; import java.util.Map; import java.util.stream.Collectors; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import org.springframework.web.client.RestTemplate; @@ -19,6 +23,8 @@ import org.springframework.web.util.UriComponentsBuilder; import ch.ethz.seb.sebserver.gbl.api.JSONMapper; import ch.ethz.seb.sebserver.gbl.profile.GuiProfile; +import ch.ethz.seb.sebserver.gbl.util.Tuple; +import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.institution.GetInstitutionNames; import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.AuthorizationContextHolder; import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.WebserviceURIService; @@ -27,6 +33,8 @@ import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.WebserviceURISer @GuiProfile public class RestService { + private static final Logger log = LoggerFactory.getLogger(RestService.class); + private final AuthorizationContextHolder authorizationContextHolder; private final WebserviceURIService webserviceURIBuilderSupplier; private final Map> calls; @@ -47,22 +55,22 @@ public class RestService { call -> call.init(this, jsonMapper))); } - public RestTemplate getWebserviceAPIRestTemplate() { + public final RestTemplate getWebserviceAPIRestTemplate() { return this.authorizationContextHolder .getAuthorizationContext() .getRestTemplate(); } - public UriComponentsBuilder getWebserviceURIBuilder() { + public final UriComponentsBuilder getWebserviceURIBuilder() { return this.webserviceURIBuilderSupplier.getURIBuilder(); } @SuppressWarnings("unchecked") - public RestCall getRestCall(final Class> type) { + public final RestCall getRestCall(final Class> type) { return (RestCall) this.calls.get(type.getName()); } - public RestCall.RestCallBuilder getBuilder(final Class> type) { + public final RestCall.RestCallBuilder getBuilder(final Class> type) { @SuppressWarnings("unchecked") final RestCall restCall = (RestCall) this.calls.get(type.getName()); if (restCall == null) { @@ -72,4 +80,19 @@ public class RestService { return restCall.newBuilder(); } + public final List> getInstitutionSelection() { + try { + return getBuilder(GetInstitutionNames.class) + .call() + .map(list -> list + .stream() + .map(entityName -> new Tuple<>(entityName.modelId, entityName.name)) + .collect(Collectors.toList())) + .getOrThrow(); + } catch (final Exception e) { + log.error("Failed to get selection resource for Institution selection", e); + return Collections.emptyList(); + } + } + } diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/institution/GetInstitutionNames.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/institution/GetInstitutionNames.java index 03d3ec6e..cbbd54ee 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/institution/GetInstitutionNames.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/institution/GetInstitutionNames.java @@ -36,10 +36,4 @@ public class GetInstitutionNames extends RestCall> { API.INSTITUTION_ENDPOINT + API.NAMES_PATH_SEGMENT); } - @Override - public RestCall>.RestCallBuilder newBuilder() { - return super.newBuilder() - .onlyActive(true); - } - } diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/useraccount/GetUserAccount.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/useraccount/GetUserAccount.java new file mode 100644 index 00000000..f9c5aa0d --- /dev/null +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/useraccount/GetUserAccount.java @@ -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.useraccount; + +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.user.UserInfo; +import ch.ethz.seb.sebserver.gbl.profile.GuiProfile; +import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCall; + +@Lazy +@Component +@GuiProfile +public class GetUserAccount extends RestCall { + + protected GetUserAccount() { + super( + new TypeReference() { + }, + HttpMethod.GET, + MediaType.APPLICATION_FORM_URLENCODED, + API.USER_ACCOUNT_ENDPOINT + API.MODEL_ID_VAR_PATH_SEGMENT); + } + +} diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/useraccount/GetUserAccounts.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/useraccount/GetUserAccounts.java new file mode 100644 index 00000000..66a3b535 --- /dev/null +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/useraccount/GetUserAccounts.java @@ -0,0 +1,38 @@ +/* + * 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.useraccount; + +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.Page; +import ch.ethz.seb.sebserver.gbl.model.user.UserInfo; +import ch.ethz.seb.sebserver.gbl.profile.GuiProfile; +import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCall; + +@Lazy +@Component +@GuiProfile +public class GetUserAccounts extends RestCall> { + + protected GetUserAccounts() { + super( + new TypeReference>() { + }, + HttpMethod.GET, + MediaType.APPLICATION_FORM_URLENCODED, + API.USER_ACCOUNT_ENDPOINT); + } + +} diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/table/ColumnDefinition.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/table/ColumnDefinition.java index fa9e4b88..72dbb973 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/service/table/ColumnDefinition.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/table/ColumnDefinition.java @@ -8,10 +8,13 @@ package ch.ethz.seb.sebserver.gui.service.table; +import java.util.List; import java.util.function.Function; import ch.ethz.seb.sebserver.gbl.model.Entity; +import ch.ethz.seb.sebserver.gbl.util.Tuple; import ch.ethz.seb.sebserver.gui.service.i18n.LocTextKey; +import ch.ethz.seb.sebserver.gui.service.table.TableFilter.CriteriaType; public final class ColumnDefinition { @@ -20,8 +23,13 @@ public final class ColumnDefinition { final LocTextKey tooltip; final int widthPercent; final Function valueSupplier; - final ColumnFilterDefinition filter; final boolean sortable; + final TableFilterAttribute filterAttribute; + final boolean localized; + + public ColumnDefinition(final String columnName, final LocTextKey displayName) { + this(columnName, displayName, null, -1); + } public ColumnDefinition( final String columnName, @@ -29,7 +37,7 @@ public final class ColumnDefinition { final LocTextKey tooltip, final int widthPercent) { - this(columnName, displayName, tooltip, widthPercent, null, null, false); + this(columnName, displayName, tooltip, widthPercent, null, null, false, false); } public ColumnDefinition( @@ -37,7 +45,7 @@ public final class ColumnDefinition { final LocTextKey displayName, final int widthPercent) { - this(columnName, displayName, null, widthPercent, null, null, false); + this(columnName, displayName, null, widthPercent, null, null, false, false); } public ColumnDefinition( @@ -46,7 +54,38 @@ public final class ColumnDefinition { final Function valueSupplier, final boolean sortable) { - this(columnName, displayName, null, -1, valueSupplier, null, sortable); + this(columnName, displayName, null, -1, valueSupplier, null, sortable, false); + } + + public ColumnDefinition( + final String columnName, + final LocTextKey displayName, + final Function valueSupplier, + final boolean sortable, + final boolean localized) { + + this(columnName, displayName, null, -1, valueSupplier, null, sortable, localized); + } + + public ColumnDefinition( + final String columnName, + final LocTextKey displayName, + final Function valueSupplier, + final TableFilterAttribute tableFilterAttribute, + final boolean sortable) { + + this(columnName, displayName, null, -1, valueSupplier, tableFilterAttribute, sortable, false); + } + + public ColumnDefinition( + final String columnName, + final LocTextKey displayName, + final Function valueSupplier, + final TableFilterAttribute tableFilterAttribute, + final boolean sortable, + final boolean localized) { + + this(columnName, displayName, null, -1, valueSupplier, tableFilterAttribute, sortable, localized); } public ColumnDefinition( @@ -55,15 +94,48 @@ public final class ColumnDefinition { final LocTextKey tooltip, final int widthPercent, final Function valueSupplier, - final ColumnFilterDefinition filter, - final boolean sortable) { + final TableFilterAttribute filterAttribute, + final boolean sortable, + final boolean localized) { this.columnName = columnName; this.displayName = displayName; this.tooltip = tooltip; this.widthPercent = widthPercent; this.valueSupplier = valueSupplier; - this.filter = filter; + this.filterAttribute = filterAttribute; this.sortable = sortable; + this.localized = localized; + } + + public static final class TableFilterAttribute { + + public final CriteriaType type; + public final String columnName; + public final String initValue; + public final List> selectionResource; + + public TableFilterAttribute( + final CriteriaType type, + final String columnName) { + + this.type = type; + this.columnName = columnName; + this.initValue = ""; + this.selectionResource = null; + } + + public TableFilterAttribute( + final CriteriaType type, + final String columnName, + final String initValue, + final List> selectionResource) { + + this.type = type; + this.columnName = columnName; + this.initValue = initValue; + this.selectionResource = selectionResource; + } + } } diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/table/ColumnFilterDefinition.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/table/ColumnFilterDefinition.java deleted file mode 100644 index e89743e8..00000000 --- a/src/main/java/ch/ethz/seb/sebserver/gui/service/table/ColumnFilterDefinition.java +++ /dev/null @@ -1,13 +0,0 @@ -/* - * Copyright (c) 2019 ETH Zürich, Educational Development and Technology (LET) - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -package ch.ethz.seb.sebserver.gui.service.table; - -public class ColumnFilterDefinition { - -} diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/table/EntityTable.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/table/EntityTable.java index fe7d258e..aeefd83b 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/service/table/EntityTable.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/table/EntityTable.java @@ -8,10 +8,14 @@ package ch.ethz.seb.sebserver.gui.service.table; +import static ch.ethz.seb.sebserver.gui.service.i18n.PolyglotPageService.POLYGLOT_WIDGET_FUNCTION_KEY; + import java.util.Arrays; import java.util.Collections; import java.util.List; +import java.util.Objects; import java.util.Set; +import java.util.function.Consumer; import java.util.stream.Collectors; import org.eclipse.swt.SWT; @@ -22,6 +26,7 @@ import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Table; import org.eclipse.swt.widgets.TableColumn; import org.eclipse.swt.widgets.TableItem; +import org.eclipse.swt.widgets.Widget; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -31,21 +36,23 @@ import ch.ethz.seb.sebserver.gbl.model.Page; import ch.ethz.seb.sebserver.gbl.util.Utils; import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCall; import ch.ethz.seb.sebserver.gui.service.widget.WidgetFactory; +import ch.ethz.seb.sebserver.gui.service.widget.WidgetFactory.ImageIcon; import ch.ethz.seb.sebserver.webservice.servicelayer.PaginationService.SortOrder; public class EntityTable extends Composite { - private static final Logger log = LoggerFactory.getLogger(EntityTable.class); - private static final long serialVersionUID = -4931198225547108993L; - public static final String TABLE_ROW_DATA = "TABLE_ROW_DATA"; + private static final Logger log = LoggerFactory.getLogger(EntityTable.class); - private transient final WidgetFactory widgetFactory; + static final String COLUMN_DEFINITION = "COLUMN_DEFINITION"; + static final String TABLE_ROW_DATA = "TABLE_ROW_DATA"; - private transient final RestCall> restCall; - private transient final List> columns; - private transient final List actions; + transient final WidgetFactory widgetFactory; + + transient final RestCall> restCall; + transient final List> columns; + transient final List actions; private transient final TableFilter filter; private transient final Table table; @@ -65,8 +72,7 @@ public class EntityTable extends Composite { final WidgetFactory widgetFactory, final List> columns, final List actions, - final int pageSize, - final boolean withFilter) { + final int pageSize) { super(parent, type); this.widgetFactory = widgetFactory; @@ -75,22 +81,34 @@ public class EntityTable extends Composite { this.actions = Utils.immutableListOf(actions); super.setLayout(new GridLayout()); - GridData gridData = new GridData(SWT.FILL, SWT.TOP, true, false); + GridData gridData = new GridData(SWT.FILL, SWT.TOP, true, true); gridData.heightHint = (pageSize + 1) * 40; super.setLayoutData(gridData); this.pageSize = pageSize; - this.filter = (withFilter) ? new TableFilter<>(this) : null; + this.filter = columns + .stream() + .map(column -> column.filterAttribute) + .filter(Objects::nonNull) + .findFirst() + .isPresent() ? new TableFilter<>(this) : null; this.table = widgetFactory.tableLocalized(this); - this.table.setLayout(new GridLayout(columns.size(), true)); + final GridLayout gridLayout = new GridLayout(columns.size(), true); + this.table.setLayout(gridLayout); gridData = new GridData(SWT.FILL, SWT.CENTER, true, false); - gridData.heightHint = (pageSize + 1) * 25; + gridData.heightHint = (pageSize + 1) * 27; this.table.setLayoutData(gridData); this.table.addListener(SWT.Resize, this::adaptColumnWidth); + @SuppressWarnings("unchecked") + final Consumer locFunction = (Consumer
) this.table.getData(POLYGLOT_WIDGET_FUNCTION_KEY); + final Consumer
newLocFunction = t -> { + updateValues(); + locFunction.accept(t); + }; + this.table.setData(POLYGLOT_WIDGET_FUNCTION_KEY, newLocFunction); - //this.table.setLayoutData(new GridData(GridData.FILL_BOTH)); this.table.setHeaderVisible(true); this.table.setLinesVisible(true); @@ -128,7 +146,11 @@ public class EntityTable extends Composite { } public void applyFilter() { - // TODO remove all rows, set current page to 0, call rest to get entities and build rows and navigation again + updateTableRows( + this.pageNumber, + this.pageSize, + this.sortColumn, + this.sortOrder); } public void applySort(final String columnName) { @@ -173,6 +195,9 @@ public class EntityTable extends Composite { column.displayName, column.tooltip); + tableColumn.addListener(SWT.Resize, this::adaptColumnWidthChange); + tableColumn.setData(COLUMN_DEFINITION, column); + if (column.sortable) { tableColumn.addListener(SWT.Selection, event -> { if (!column.columnName.equals(this.sortColumn)) { @@ -206,7 +231,7 @@ public class EntityTable extends Composite { this.restCall.newBuilder() .withPaging(pageNumber, pageSize) .withSorting(sortColumn, sortOrder) - .withFilterAttributes(this.filter) + .withQueryParams((this.filter != null) ? this.filter.getFilterParameter() : null) .call() .map(this::createTableRowsFromPage) .map(this.navigator::update) @@ -214,7 +239,7 @@ public class EntityTable extends Composite { // TODO error handling }); - this.layout(); + this.layout(true, true); } private Page createTableRowsFromPage(final Page page) { @@ -223,31 +248,55 @@ public class EntityTable extends Composite { item.setData(TABLE_ROW_DATA, row); int index = 0; for (final ColumnDefinition column : this.columns) { - final Object value = column.valueSupplier.apply(row); - if (value instanceof Boolean) { - // TODO set an image or HTML with checkbox - item.setText(index, String.valueOf(value)); - } else { - if (value != null) { - item.setText(index, String.valueOf(value)); - } else { - item.setText(index, Constants.EMPTY_NOTE); - } - } + setValueToCell(item, index, column.valueSupplier.apply(row)); index++; } if (this.actions != null) { - // TODO + // TODO?? } } return page; } + private void updateValues() { + final TableItem[] items = this.table.getItems(); + final TableColumn[] columns = this.table.getColumns(); + for (int i = 0; i < columns.length; i++) { + final ColumnDefinition columnDefinition = this.columns.get(i); + if (columnDefinition.localized) { + for (int j = 0; j < items.length; j++) { + @SuppressWarnings("unchecked") + final ROW rowData = (ROW) items[j].getData(TABLE_ROW_DATA); + setValueToCell(items[j], i, columnDefinition.valueSupplier.apply(rowData)); + } + } + } + } + + private void setValueToCell(final TableItem item, final int index, final Object value) { + if (value instanceof Boolean) { + addBooleanCell(item, index, value); + } else { + if (value != null) { + item.setText(index, String.valueOf(value)); + } else { + item.setText(index, Constants.EMPTY_NOTE); + } + } + } + + private void addBooleanCell(final TableItem item, final int index, final Object value) { + if ((Boolean) value) { + item.setImage(index, ImageIcon.ACTIVE.getImage(item.getDisplay())); + } else { + item.setImage(index, ImageIcon.INACTIVE.getImage(item.getDisplay())); + } + } + private void adaptColumnWidth(final Event event) { try { final int currentTableWidth = this.table.getParent().getClientArea().width; - int index = 0; for (final ColumnDefinition column : this.columns) { @@ -256,16 +305,37 @@ public class EntityTable extends Composite { : column.widthPercent; final TableColumn tableColumn = this.table.getColumn(index); - tableColumn.setWidth(currentTableWidth / 100 * percentage); + final int newWidth = currentTableWidth / 100 * percentage; + tableColumn.setWidth(newWidth); + if (this.filter != null) { + this.filter.adaptColumnWidth(this.table.indexOf(tableColumn), newWidth); + } index++; } + // NOTE this.layout() triggers the navigation to disappear unexpectedly!? + this.table.layout(true, true); + } catch (final Exception e) { log.warn("Failed to adaptColumnWidth: ", e); } } + private void adaptColumnWidthChange(final Event event) { + final Widget widget = event.widget; + if (widget instanceof TableColumn) { + final TableColumn tableColumn = ((TableColumn) widget); + if (this.filter != null && + this.filter.adaptColumnWidth( + this.table.indexOf(tableColumn), + tableColumn.getWidth())) { + + this.layout(true, true); + } + } + } + @SuppressWarnings("unchecked") private ROW getRowData(final TableItem item) { return (ROW) item.getData(TABLE_ROW_DATA); diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/table/TableBuilder.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/table/TableBuilder.java index 34a0cd8a..002fbf21 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/service/table/TableBuilder.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/table/TableBuilder.java @@ -22,14 +22,14 @@ import ch.ethz.seb.sebserver.gui.service.widget.WidgetFactory; /** * new TableBuilder(RestCall) * .withPaging(pageSize) + * .withFilterAttribute(attribute.TableFilterAttribute) * .withColumn(new ColumnDefinition( * columnName:String, * displayName:LocTextKey, * tooltip:LocTextKey, * width:int, * valueSupplier:Function, - * sortable:boolean, - * columnFilter:TableColumnFilter)) + * sortable:boolean * .withAction(action:TableRowAction) * .withSelectableRows(boolean) * .compose(parent:Composit, group:Composite); @@ -38,6 +38,7 @@ public class TableBuilder { private final WidgetFactory widgetFactory; final RestCall> restCall; +// final List filter = new ArrayList<>(); final List> columns = new ArrayList<>(); final List actions = new ArrayList<>(); @@ -57,8 +58,8 @@ public class TableBuilder { return this; } - public TableBuilder withColumn(final ColumnDefinition columnDef) { - this.columns.add(columnDef); + public TableBuilder withColumn(final ColumnDefinition columnDefinition) { + this.columns.add(columnDefinition); return this; } @@ -73,12 +74,6 @@ public class TableBuilder { } public EntityTable compose(final Composite parent) { - final boolean withFilter = this.columns - .stream() - .filter(c -> c.filter != null) - .findFirst() - .isPresent(); - return new EntityTable<>( this.type, parent, @@ -86,8 +81,7 @@ public class TableBuilder { this.widgetFactory, this.columns, this.actions, - this.pageSize, - withFilter); + this.pageSize); } } diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/table/TableFilter.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/table/TableFilter.java index 22ecd9ae..f2d9643f 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/service/table/TableFilter.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/table/TableFilter.java @@ -8,24 +8,250 @@ package ch.ethz.seb.sebserver.gui.service.table; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +import org.apache.commons.lang3.StringUtils; import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.RowData; +import org.eclipse.swt.layout.RowLayout; import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Text; +import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; import ch.ethz.seb.sebserver.gbl.model.Entity; -import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.FilterAttributeSupplier; +import ch.ethz.seb.sebserver.gui.service.i18n.LocTextKey; +import ch.ethz.seb.sebserver.gui.service.table.ColumnDefinition.TableFilterAttribute; +import ch.ethz.seb.sebserver.gui.service.widget.LanguageSelector; +import ch.ethz.seb.sebserver.gui.service.widget.WidgetFactory.ImageIcon; -public class TableFilter extends Composite implements FilterAttributeSupplier { +public class TableFilter extends Composite { private static final long serialVersionUID = -2460403977147440766L; - TableFilter(final EntityTable parent) { - super(parent, SWT.NONE); + public static enum CriteriaType { + TEXT, + SINGLE_SELECTION, + COUNTRY_SELECTION, + DATE } - @Override - public MultiValueMap getAttributes() { - // TODO Auto-generated method stub - return null; + private final EntityTable entityTable; + private final List components; + + TableFilter(final EntityTable entityTable) { + super(entityTable, SWT.NONE); + final GridData gridData = new GridData(SWT.FILL, SWT.TOP, true, false); + super.setLayoutData(gridData); + final RowLayout layout = new RowLayout(SWT.HORIZONTAL); + layout.spacing = 5; + layout.wrap = false; + super.setLayout(layout); + + this.entityTable = entityTable; + this.components = entityTable.columns + .stream() + .map(column -> column.filterAttribute) + //.filter(Objects::nonNull) + .map(this::createFilterComponent) + .map(comp -> comp.build(this)) + .map(comp -> comp.reset()) + .collect(Collectors.toList()); + + final FilterComponent lastComp = this.components.get(this.components.size() - 1); + if (lastComp instanceof TableFilter.NullFilter) { + this.components.remove(lastComp); + } + + addActions(); + } + + public MultiValueMap getFilterParameter() { + return this.components + .stream() + .reduce(new LinkedMultiValueMap(), + (map, comp) -> comp.putFilterParameter(map), + (map1, map2) -> { + map1.putAll(map2); + return map1; + }); + } + + public void reset() { + this.components + .stream() + .forEach(comp -> comp.reset()); + } + + private FilterComponent createFilterComponent(final TableFilterAttribute attribute) { + if (attribute == null) { + return new NullFilter(); + } + + switch (attribute.type) { + case TEXT: + return new TextFilter(attribute); + case COUNTRY_SELECTION: + return new LanguageFilter(attribute); + default: + throw new IllegalArgumentException("Unsupported FilterAttributeType: " + attribute.type); + } + } + + boolean adaptColumnWidth(final int columnIndex, final int width) { + if (columnIndex < this.components.size()) { + return this.components.get(columnIndex).adaptWidth(width); + } + + return false; + } + + private void addActions() { + this.entityTable.widgetFactory.imageButton( + ImageIcon.SEARCH, + this, + new LocTextKey("sebserver.overall.action.filter"), + event -> { + this.entityTable.applyFilter(); + }); + this.entityTable.widgetFactory.imageButton( + ImageIcon.CANCEL, + this, + new LocTextKey("sebserver.overall.action.filter.clear"), + event -> { + reset(); + }); + } + + private static abstract class FilterComponent { + + static final int CELL_WIDTH_ADJUSTMENT = -30; + + protected RowData rowData; + final TableFilterAttribute attribute; + + FilterComponent(final TableFilterAttribute attribute) { + this.attribute = attribute; + } + + LinkedMultiValueMap putFilterParameter( + final LinkedMultiValueMap filterParameter) { + + final String value = getValue(); + if (StringUtils.isNotBlank(value)) { + filterParameter.put(this.attribute.columnName, Arrays.asList(value)); + } + return filterParameter; + } + + abstract FilterComponent build(Composite parent); + + abstract FilterComponent reset(); + + abstract String getValue(); + + boolean adaptWidth(final int width) { + final int _width = width + CELL_WIDTH_ADJUSTMENT; + if (_width != this.rowData.width) { + this.rowData.width = _width; + return true; + } + + return false; + } + } + + private class NullFilter extends FilterComponent { + + private Label label; + + NullFilter() { + super(null); + } + + @Override + FilterComponent build(final Composite parent) { + this.label = new Label(parent, SWT.NONE); + this.rowData = new RowData(); + this.label.setLayoutData(this.rowData); + return this; + } + + @Override + boolean adaptWidth(final int width) { + return super.adaptWidth(width - CELL_WIDTH_ADJUSTMENT); + } + + @Override + FilterComponent reset() { + return this; + } + + @Override + String getValue() { + return null; + } + } + + private class TextFilter extends FilterComponent { + + private Text textInput; + + TextFilter(final TableFilterAttribute attribute) { + super(attribute); + } + + @Override + FilterComponent reset() { + this.textInput.setText(super.attribute.initValue); + return this; + } + + @Override + FilterComponent build(final Composite parent) { + this.textInput = new Text(parent, SWT.LEFT | SWT.BORDER); + this.rowData = new RowData(); + this.textInput.setLayoutData(this.rowData); + return this; + } + + @Override + String getValue() { + return this.textInput.getText(); + } + + } + + private class LanguageFilter extends FilterComponent { + + private LanguageSelector selector; + + LanguageFilter(final TableFilterAttribute attribute) { + super(attribute); + } + + @Override + FilterComponent build(final Composite parent) { + this.selector = TableFilter.this.entityTable.widgetFactory.countrySelector(parent); + this.rowData = new RowData(); + this.selector.setLayoutData(this.rowData); + return this; + } + + @Override + FilterComponent reset() { + this.selector.clear(); + this.selector.layout(); + return this; + } + + @Override + String getValue() { + return this.selector.getSelectionValue(); + } } } diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/table/TableNavigator.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/table/TableNavigator.java index b2e455b4..6ea0aff2 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/service/table/TableNavigator.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/table/TableNavigator.java @@ -68,8 +68,6 @@ public class TableNavigator extends Composite { } } - this.layout(); - return pageData; } diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/widget/ImageUpload.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/widget/ImageUpload.java index 0493ef2d..4ecae8d0 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/service/widget/ImageUpload.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/widget/ImageUpload.java @@ -29,6 +29,7 @@ import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.util.StreamUtils; import ch.ethz.seb.sebserver.gui.service.push.ServerPushContext; import ch.ethz.seb.sebserver.gui.service.push.ServerPushService; @@ -62,10 +63,12 @@ public class ImageUpload extends Composite { @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()); + ImageUpload.this.imageBase64 = Base64.getEncoder() + .encodeToString(StreamUtils.copyToByteArray(stream)); } } catch (final Exception e) { log.error("Error while trying to upload image", e); diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/widget/LanguageSelector.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/widget/LanguageSelector.java new file mode 100644 index 00000000..b67fc331 --- /dev/null +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/widget/LanguageSelector.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2019 ETH Zürich, Educational Development and Technology (LET) + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +package ch.ethz.seb.sebserver.gui.service.widget; + +import static ch.ethz.seb.sebserver.gui.service.i18n.PolyglotPageService.POLYGLOT_WIDGET_FUNCTION_KEY; + +import java.util.List; +import java.util.Locale; +import java.util.function.Consumer; +import java.util.stream.Collectors; + +import org.apache.commons.lang3.StringUtils; +import org.eclipse.swt.widgets.Composite; + +import ch.ethz.seb.sebserver.gbl.util.Tuple; +import ch.ethz.seb.sebserver.gui.service.i18n.I18nSupport; + +public class LanguageSelector extends SingleSelection { + + private static final long serialVersionUID = -8590909580787576722L; + + private final Consumer updateFunction; + + public LanguageSelector(final Composite parent, final I18nSupport i18nSupport) { + super(parent, getLanguages(i18nSupport)); + this.updateFunction = updateFunction(i18nSupport); + this.setData(POLYGLOT_WIDGET_FUNCTION_KEY, this.updateFunction); + } + + private static final Consumer updateFunction(final I18nSupport i18nSupport) { + return selection -> selection.applyNewMapping(getLanguages(i18nSupport)); + } + + public static final List> getLanguages(final I18nSupport i18nSupport) { + final Locale currentLocale = i18nSupport.getCurrentLocale(); + return i18nSupport.supportedLanguages() + .stream() + .map(locale -> new Tuple<>(locale.toLanguageTag(), locale.getDisplayLanguage(currentLocale))) + .filter(tuple -> StringUtils.isNoneBlank(tuple._2)) + .sorted((t1, t2) -> t1._2.compareTo(t2._2)) + .collect(Collectors.toList()); + } + + public void clear() { + super.clearSelection(); + this.updateFunction.accept(this); + } + +} diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/widget/SingleSelection.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/widget/SingleSelection.java index e9dc70bf..8404e8e6 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/service/widget/SingleSelection.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/widget/SingleSelection.java @@ -8,6 +8,7 @@ package ch.ethz.seb.sebserver.gui.service.widget; +import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; @@ -26,12 +27,20 @@ public class SingleSelection extends Combo { public SingleSelection(final Composite parent, final List> mapping) { super(parent, SWT.READ_ONLY); - this.valueMapping = mapping.stream() + this.valueMapping = new ArrayList<>(); + this.keyMapping = new ArrayList<>(); + applyNewMapping(mapping); + } + + protected void applyNewMapping(final List> mapping) { + this.valueMapping.clear(); + this.keyMapping.clear(); + this.valueMapping.addAll(mapping.stream() .map(t -> t._2) - .collect(Collectors.toList()); - this.keyMapping = mapping.stream() + .collect(Collectors.toList())); + this.keyMapping.addAll(mapping.stream() .map(t -> t._1) - .collect(Collectors.toList()); + .collect(Collectors.toList())); super.setItems(this.valueMapping.toArray(new String[mapping.size()])); } diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/widget/WidgetFactory.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/widget/WidgetFactory.java index a13a5dc8..892c8486 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/service/widget/WidgetFactory.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/widget/WidgetFactory.java @@ -15,6 +15,7 @@ import java.util.Iterator; import java.util.List; import java.util.Locale; import java.util.function.Consumer; +import java.util.function.Function; import org.apache.commons.lang3.StringUtils; import org.eclipse.rap.rwt.RWT; @@ -23,6 +24,7 @@ import org.eclipse.swt.graphics.Device; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.ImageData; import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Combo; import org.eclipse.swt.widgets.Composite; @@ -49,6 +51,9 @@ 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.page.action.ActionDefinition; +import ch.ethz.seb.sebserver.gui.service.page.event.ActionEvent; +import ch.ethz.seb.sebserver.gui.service.page.event.ActionEventListener; 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; @@ -60,40 +65,24 @@ public class WidgetFactory { private static final Logger log = LoggerFactory.getLogger(WidgetFactory.class); - public enum CustomVariant { - TEXT_H1("h1"), - TEXT_H2("h2"), - TEXT_H3("h3"), - TEXT_ACTION("action"), - - FOOTER("footer"), - - ; - - public final String key; - - private CustomVariant(final String key) { - this.key = key; - } - } - - public enum IconButtonType { + public enum ImageIcon { 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"), - ; + EDIT("edit.png"), + CANCEL("cancel.png"), + CANCEL_EDIT("cancelEdit.png"), + SHOW("show.png"), + ACTIVE("active.png"), + INACTIVE("inactive.png"), + SAVE("save.png"), + NEW("new.png"), + DELETE("delete.png"), + SEARCH("lens.png"); private String fileName; private ImageData image = null; - private IconButtonType(final String fileName) { + private ImageIcon(final String fileName) { this.fileName = fileName; } @@ -113,6 +102,24 @@ public class WidgetFactory { } + public enum CustomVariant { + TEXT_H1("h1"), + TEXT_H2("h2"), + TEXT_H3("h3"), + IMAGE_BUTTON("imageButton"), + TEXT_ACTION("action"), + + FOOTER("footer"), + + ; + + public final String key; + + private CustomVariant(final String key) { + this.key = key; + } + } + private final PolyglotPageService polyglotPageService; private final I18nSupport i18nSupport; private final ServerPushService serverPushService; @@ -126,6 +133,42 @@ public class WidgetFactory { this.serverPushService = serverPushService; } + public I18nSupport getI18nSupport() { + return this.i18nSupport; + } + + public Composite defaultPageLayout(final Composite parent) { + final Composite content = new Composite(parent, SWT.NONE); + final GridLayout contentLayout = new GridLayout(); + contentLayout.marginLeft = 10; + content.setLayout(contentLayout); + content.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + return content; + } + + public Composite defaultPageLayout(final Composite parent, final LocTextKey title) { + final Composite defaultPageLayout = defaultPageLayout(parent); + final Label labelLocalizedTitle = labelLocalizedTitle(defaultPageLayout, title); + labelLocalizedTitle.setLayoutData(new GridData(SWT.TOP, SWT.LEFT, true, false)); + return defaultPageLayout; + } + + public Composite defaultPageLayout( + final Composite parent, + final LocTextKey title, + final ActionDefinition actionDefinition, + final Function> eventFunction) { + + final Composite defaultPageLayout = defaultPageLayout(parent); + final Label labelLocalizedTitle = labelLocalizedTitle(defaultPageLayout, title); + labelLocalizedTitle.setLayoutData(new GridData(SWT.TOP, SWT.LEFT, true, false)); + ActionEventListener.injectListener( + labelLocalizedTitle, + actionDefinition, + eventFunction.apply(labelLocalizedTitle)); + return defaultPageLayout; + } + public Button buttonLocalized(final Composite parent, final String locTextKey) { final Button button = new Button(parent, SWT.NONE); this.injectI18n(button, new LocTextKey(locTextKey)); @@ -254,13 +297,13 @@ public class WidgetFactory { } public Label imageButton( - final IconButtonType type, + final ImageIcon type, final Composite parent, final LocTextKey toolTip, final Listener listener) { final Label imageButton = labelLocalized(parent, (LocTextKey) null, toolTip); - imageButton.setData(RWT.CUSTOM_VARIANT, "imageButton"); + imageButton.setData(RWT.CUSTOM_VARIANT, CustomVariant.IMAGE_BUTTON.name()); imageButton.setImage(type.getImage(parent.getDisplay())); if (listener != null) { imageButton.addListener(SWT.MouseDown, listener); @@ -339,6 +382,10 @@ public class WidgetFactory { return combo; } + public LanguageSelector countrySelector(final Composite parent) { + return new LanguageSelector(parent, this.i18nSupport); + } + public ImageUpload formImageUpload( final Composite parent, final String value, @@ -497,6 +544,18 @@ public class WidgetFactory { } if (locToolTipKey != null) { label.setToolTipText(i18nSupport.getText(locToolTipKey)); + // TODO managing a tool-tip delay is not working as expected + // is there another way to achieve this? +// label.addListener(SWT.MouseEnter, event -> { +// System.out.println("*************** set tooltip delay"); +// label.getDisplay().timerExec(1000, () -> { +// System.out.println("*************** set tooltip"); +// label.setToolTipText(i18nSupport.getText(locToolTipKey)); +// }); +// }); +// label.addListener(SWT.MouseExit, event -> { +// label.setToolTipText(null); +// }); } }; } diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/EntityController.java b/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/EntityController.java index 69777a5c..03050fb0 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/EntityController.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/EntityController.java @@ -28,8 +28,8 @@ import org.springframework.web.bind.annotation.RequestParam; import ch.ethz.seb.sebserver.gbl.Constants; import ch.ethz.seb.sebserver.gbl.api.API; -import ch.ethz.seb.sebserver.gbl.api.EntityType; import ch.ethz.seb.sebserver.gbl.api.API.BulkActionType; +import ch.ethz.seb.sebserver.gbl.api.EntityType; import ch.ethz.seb.sebserver.gbl.api.POSTMapper; import ch.ethz.seb.sebserver.gbl.authorization.PrivilegeType; import ch.ethz.seb.sebserver.gbl.model.Entity; @@ -100,9 +100,16 @@ public abstract class EntityController allRequestParams) { + // at least current user must have read access for specified entity type within its own institution checkReadPrivilege(institutionId); - final FilterMap filterMap = new FilterMap(allRequestParams) - .putIfAbsent(API.PARAM_INSTITUTION_ID, String.valueOf(institutionId)); + + final FilterMap filterMap = new FilterMap(allRequestParams); + + // if current user has no read access for specified entity type within other institution then its own institution, + // then the current users institutionId is put as a SQL filter criteria attribute to extends query performance + if (!this.authorization.hasGrant(PrivilegeType.READ_ONLY, this.entityDAO.entityType())) { + filterMap.putIfAbsent(API.PARAM_INSTITUTION_ID, String.valueOf(institutionId)); + } return this.paginationService.getPage( pageNumber, @@ -128,9 +135,16 @@ public abstract class EntityController allRequestParams) { + // at least current user must have read access for specified entity type within its own institution checkReadPrivilege(institutionId); - final FilterMap filterMap = new FilterMap(allRequestParams) - .putIfAbsent(API.PARAM_INSTITUTION_ID, String.valueOf(institutionId)); + + final FilterMap filterMap = new FilterMap(allRequestParams); + + // if current user has no read access for specified entity type within other institution then its own institution, + // then the current users institutionId is put as a SQL filter criteria attribute to extends query performance + if (!this.authorization.hasGrant(PrivilegeType.READ_ONLY, this.entityDAO.entityType())) { + filterMap.putIfAbsent(API.PARAM_INSTITUTION_ID, String.valueOf(institutionId)); + } return getAll(filterMap) .getOrThrow() diff --git a/src/main/resources/config/application-dev-gui.properties b/src/main/resources/config/application-dev-gui.properties index 91c249da..262ad9f2 100644 --- a/src/main/resources/config/application-dev-gui.properties +++ b/src/main/resources/config/application-dev-gui.properties @@ -13,4 +13,6 @@ sebserver.gui.webservice.apipath=/admin-api/v1 sebserver.gui.theme=css/sebserver.css +sebserver.gui.list.page.size=20 sebserver.gui.date.displayformat=EEEE, dd MMMM yyyy - HH:mm + diff --git a/src/main/resources/config/application.properties b/src/main/resources/config/application.properties index ecfd9338..66a6cda8 100644 --- a/src/main/resources/config/application.properties +++ b/src/main/resources/config/application.properties @@ -2,6 +2,7 @@ spring.application.name=SEB Server spring.profiles.active=dev sebserver.version=1.0 beta +sebserver.supported.languages=en,de # comma separated list of known possible OpenEdX API access token request endpoints sebserver.lms.openedix.api.token.request.paths=/oauth2/access_token \ No newline at end of file diff --git a/src/main/resources/messages.properties b/src/main/resources/messages.properties index aeea2ddd..95b28926 100644 --- a/src/main/resources/messages.properties +++ b/src/main/resources/messages.properties @@ -10,6 +10,8 @@ sebserver.overall.message.leave.without.save=You are leaving this page without s 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. +sebserver.overall.action.filter=Apply Filter +sebserver.overall.action.filter.clear=Clear Filter Criteria ################################ # Login Page @@ -32,10 +34,11 @@ sebserver.mainpage.maximize.tooltip=Maximize sebserver.mainpage.minimize.tooltip=Minimize sebserver.activitiespane.title=Activities sebserver.actionpane.title=Actions -sebserver.activities.inst=Institution -sebserver.error.unexpected=Unexpected Error -sebserver.page.message=Information +# Activities +sebserver.activities.institution=Institution +sebserver.activities.useraccount=User Account + ################################ @@ -64,10 +67,25 @@ sebserver.institution.form.logoImage=Logo Image sebserver.institution.form.confirm.deactivation=Note that there are {0} other entities that belongs to this Institution.
Those will also be deactivated by deactivating this Institution.

Are You sure to deactivate this Institution? sebserver.institution.form.confirm.deactivation.noDependencies=Are You sure to deactivate this Institution? -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 +# User Account ################################ -sebserver.form.validation.fieldError.size=The size must be between {3} and {4} \ No newline at end of file +sebserver.useraccount.list.title=User Accounts +sebserver.useraccount.list.column.name=Name +sebserver.useraccount.list.column.username=User Name +sebserver.useraccount.list.column.email=Mail +sebserver.useraccount.list.column.language=Language +sebserver.useraccount.list.column.active=Active + + + +################################ +# Form validation and messages +################################ + +sebserver.form.validation.fieldError.size=The size must be between {3} and {4} +sebserver.form.validation.fieldError.name=Name is mandatory and must have a size between 3 and 255 character +sebserver.form.validation.fieldError.urlSuffix=URL Suffix must have a size between 3 and 255 character +sebserver.error.unexpected=Unexpected Error +sebserver.page.message=Information \ No newline at end of file diff --git a/src/main/resources/static/css/sebserver.css b/src/main/resources/static/css/sebserver.css index acfd6ba1..60fe40b7 100644 --- a/src/main/resources/static/css/sebserver.css +++ b/src/main/resources/static/css/sebserver.css @@ -62,10 +62,16 @@ Label.h3 { color: #1f407a; } +/* Label:hover.imageButton { background-color: #82BE1E; background-gradient-color: #82BE1E; background-image: gradient( linear, left top, left bottom, from( #82BE1E ), to( #82BE1E ) ); +}*/ + +Label:hover.imageButton { + background-color: transparent; + background-repeat: no-repeat; } Composite.bordered { @@ -661,7 +667,7 @@ Table-RowOverlay:selected:unfocused { Table-RowOverlay:linesvisible:even:hover { color: #4a4a4a; background-color: #b5b5b5; - background-image: gradient(linear, left top, left bottom, from(#b5b5b5),to(#d5d5d5)); + background-image: gradient(linear, left top, left bottom, from(#b5b5b5),to(#b5b5b5)); } Table-RowOverlay:linesvisible:even:selected { diff --git a/src/main/resources/static/images/cancelAction.png b/src/main/resources/static/images/cancel.png similarity index 100% rename from src/main/resources/static/images/cancelAction.png rename to src/main/resources/static/images/cancel.png diff --git a/src/main/resources/static/images/cancelEditAction.png b/src/main/resources/static/images/cancelEdit.png similarity index 100% rename from src/main/resources/static/images/cancelEditAction.png rename to src/main/resources/static/images/cancelEdit.png diff --git a/src/main/resources/static/images/delete.png b/src/main/resources/static/images/delete.png index faddb41049cbaf709ae52aad9c546dbd1c7c5283..3ddfaf8a2774ce17e993742f19b2d707fc57aa34 100644 GIT binary patch delta 130 zcmV-|0Db?u0h9rd8G8l*0036bj#mHx09#2!K~#7FV;EULfEsG}f%qN}_v2C14^_iY z$gp-G{*S}3eyChKZta9Mw4;lWYFGmhH^N;>CYS~?fFeT>u0j|@sUeL7y+(OpQy%?| k)J%}P)W{-&3?l~s0BB+*JYg;KZ~y=R07*qoM6N<$f|WTi!~g&Q delta 169 zcmV;a09OB$0lEQ@8Gi%-008{QM%(}Z0D(zFK~#7FW1tZ*V%W!U00{RnXk(LhVEB&( zI-n|2U}(Ss70}H}U^svV6EH1oz_6?Vm!gkg@)I6KKr2KUZUCVu!x7wyE;0x($TCPV z2m@JotXmCcuf=EGMW7k7K#13*BMc%?HytDFyN|f6%fSez93o6boD3^b!h0o9gz5kQ XV7T&TEpP!>gTe~DWM4f2a7RT diff --git a/src/main/resources/static/images/deletePermanent.png b/src/main/resources/static/images/deletePermanent.png new file mode 100644 index 0000000000000000000000000000000000000000..faddb41049cbaf709ae52aad9c546dbd1c7c5283 GIT binary patch literal 186 zcmeAS@N?(olHy`uVBq!ia0vp^LLkh+0wn(&ce?|m8a-VcLn;`P7YG_8-8f#r!13KM zBYARJ!jFDds|8v?2^j~NL@%86O0Z~P6E@JzIj~_3@JTphGsB=Z;+Y8)24 z)1_y`VQ|98!;phHvSLj%Z`%5!>33ZhNN#fIxV}W0M=8KuR{72D{vB&hALLjrOXZUDGG<+jTtDWWgIdL<;=`a7&=b4*4c*mS)rr6?$wIYtjz!Ry_hhmr6Ul z6>4%95Fzx=PNIbZiQ;q!4TyBkPQL39n%3g8D4|5>?CX-U!?g2~57USjc userInfos = new RestAPITestHelper() .withAccessToken(getSebAdminAccess()) - .withPath(API.USER_ACCOUNT_ENDPOINT) + .withPath(API.USER_ACCOUNT_ENDPOINT + "?institutionId=1") .withExpectedStatus(HttpStatus.OK) .getAsObject(new TypeReference>() { }); @@ -205,7 +205,7 @@ public class UserAPITest extends AdministrationAPIIntegrationTester { final String token = getSebAdminAccess(); final Page userInfos = this.jsonMapper.readValue( - this.mockMvc.perform(get(this.endpoint + API.USER_ACCOUNT_ENDPOINT) + this.mockMvc.perform(get(this.endpoint + API.USER_ACCOUNT_ENDPOINT + "?institutionId=1") .contentType(MediaType.APPLICATION_FORM_URLENCODED) .header("Authorization", "Bearer " + token)) .andExpect(status().isOk()) @@ -247,7 +247,7 @@ public class UserAPITest extends AdministrationAPIIntegrationTester { public void getPageNoFilterNoPageAttributesDescendingOrder() throws Exception { final String token = getSebAdminAccess(); final Page userInfos = this.jsonMapper.readValue( - this.mockMvc.perform(get(this.endpoint + API.USER_ACCOUNT_ENDPOINT + "?sort=-") + this.mockMvc.perform(get(this.endpoint + API.USER_ACCOUNT_ENDPOINT + "?sort=-&institutionId=1") .contentType(MediaType.APPLICATION_FORM_URLENCODED) .header("Authorization", "Bearer " + token)) .andExpect(status().isOk()) @@ -345,7 +345,7 @@ public class UserAPITest extends AdministrationAPIIntegrationTester { public void getAllUserInfo() throws Exception { final String token = getSebAdminAccess(); final Page userInfos = this.jsonMapper.readValue( - this.mockMvc.perform(get(this.endpoint + API.USER_ACCOUNT_ENDPOINT) + this.mockMvc.perform(get(this.endpoint + API.USER_ACCOUNT_ENDPOINT + "?institutionId=1") .contentType(MediaType.APPLICATION_FORM_URLENCODED) .header("Authorization", "Bearer " + token)) .andExpect(status().isOk()) @@ -382,7 +382,7 @@ public class UserAPITest extends AdministrationAPIIntegrationTester { // expecting none for SEBAdmins institution final String token = getSebAdminAccess(); Page userInfos = this.jsonMapper.readValue( - this.mockMvc.perform(get(this.endpoint + API.USER_ACCOUNT_ENDPOINT + "?active=false") + this.mockMvc.perform(get(this.endpoint + API.USER_ACCOUNT_ENDPOINT + "?active=false&institutionId=1") .contentType(MediaType.APPLICATION_FORM_URLENCODED) .header("Authorization", "Bearer " + token)) .andExpect(status().isOk()) @@ -415,7 +415,7 @@ public class UserAPITest extends AdministrationAPIIntegrationTester { final String token = getSebAdminAccess(); final Page userInfos = this.jsonMapper.readValue( this.mockMvc - .perform(get(this.endpoint + API.USER_ACCOUNT_ENDPOINT + "?username=exam") + .perform(get(this.endpoint + API.USER_ACCOUNT_ENDPOINT + "?username=exam&institutionId=1") .contentType(MediaType.APPLICATION_FORM_URLENCODED) .header("Authorization", "Bearer " + token)) .andExpect(status().isOk()) @@ -1080,7 +1080,7 @@ public class UserAPITest extends AdministrationAPIIntegrationTester { // for SEB Admin Collection names = this.jsonMapper.readValue( this.mockMvc - .perform(get(this.endpoint + API.USER_ACCOUNT_ENDPOINT + "/names") + .perform(get(this.endpoint + API.USER_ACCOUNT_ENDPOINT + "/names" + "?institutionId=1") .contentType(MediaType.APPLICATION_FORM_URLENCODED) .header("Authorization", "Bearer " + sebAdminToken)) .andExpect(status().isOk()) @@ -1098,7 +1098,7 @@ public class UserAPITest extends AdministrationAPIIntegrationTester { final String instAdminToken = getAdminInstitution2Access(); names = this.jsonMapper.readValue( this.mockMvc - .perform(get(this.endpoint + API.USER_ACCOUNT_ENDPOINT + "/names") + .perform(get(this.endpoint + API.USER_ACCOUNT_ENDPOINT + "/names" + "?institutionId=2") .contentType(MediaType.APPLICATION_FORM_URLENCODED) .header("Authorization", "Bearer " + instAdminToken)) .andExpect(status().isOk()) @@ -1117,7 +1117,7 @@ public class UserAPITest extends AdministrationAPIIntegrationTester { names = this.jsonMapper.readValue( this.mockMvc .perform( - get(this.endpoint + API.USER_ACCOUNT_ENDPOINT + "/names?active=true") + get(this.endpoint + API.USER_ACCOUNT_ENDPOINT + "/names?active=true&institutionId=2") .contentType(MediaType.APPLICATION_FORM_URLENCODED) .header("Authorization", "Bearer " + instAdminToken)) .andExpect(status().isOk())