#SEBSERV-27 user account list (with filter)

This commit is contained in:
anhefti 2019-02-20 09:41:36 +01:00
parent d24bb080fb
commit 28556afae6
53 changed files with 973 additions and 296 deletions

View file

@ -58,7 +58,7 @@
<profile>
<id>Java 11</id>
<activation>
<activeByDefault>true</activeByDefault>
<activeByDefault>false</activeByDefault>
</activation>
<properties>
<java.version>11</java.version>

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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<Locale> supportedLanguages();
/** Get the current Locale either form a user if this is called from a logged in user context or the

View file

@ -53,11 +53,11 @@ public class I18nSupportImpl implements I18nSupport {
.withZoneUTC();
}
private static final Collection<Locale> SUPPORTED = Arrays.asList(Locale.ENGLISH, Locale.GERMANY);
private static final Collection<Locale> SUPPORTED_LANGUAGES = Arrays.asList(Locale.ENGLISH, Locale.GERMAN);
@Override
public Collection<Locale> supportedLanguages() {
return SUPPORTED;
return SUPPORTED_LANGUAGES;
}
@Override

View file

@ -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;

View file

@ -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;
}

View file

@ -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<Institution, Institution> 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))

View file

@ -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,

View file

@ -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),

View file

@ -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

View file

@ -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
}
}

View file

@ -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<UserInfo> 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;
}
}

View file

@ -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());
}
}

View file

@ -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());
}
}

View file

@ -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;

View file

@ -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,

View file

@ -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;

View file

@ -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<String, String> getAttributes();
}

View file

@ -171,6 +171,13 @@ public abstract class RestCall<T> {
return this;
}
public RestCallBuilder withQueryParams(final MultiValueMap<String, String> 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<T> {
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());

View file

@ -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<String, RestCall<?>> 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 <T> RestCall<T> getRestCall(final Class<? extends RestCall<T>> type) {
public final <T> RestCall<T> getRestCall(final Class<? extends RestCall<T>> type) {
return (RestCall<T>) this.calls.get(type.getName());
}
public <T> RestCall<T>.RestCallBuilder getBuilder(final Class<? extends RestCall<T>> type) {
public final <T> RestCall<T>.RestCallBuilder getBuilder(final Class<? extends RestCall<T>> type) {
@SuppressWarnings("unchecked")
final RestCall<T> restCall = (RestCall<T>) this.calls.get(type.getName());
if (restCall == null) {
@ -72,4 +80,19 @@ public class RestService {
return restCall.newBuilder();
}
public final List<Tuple<String>> 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();
}
}
}

View file

@ -36,10 +36,4 @@ public class GetInstitutionNames extends RestCall<List<EntityName>> {
API.INSTITUTION_ENDPOINT + API.NAMES_PATH_SEGMENT);
}
@Override
public RestCall<List<EntityName>>.RestCallBuilder newBuilder() {
return super.newBuilder()
.onlyActive(true);
}
}

View file

@ -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<UserInfo> {
protected GetUserAccount() {
super(
new TypeReference<UserInfo>() {
},
HttpMethod.GET,
MediaType.APPLICATION_FORM_URLENCODED,
API.USER_ACCOUNT_ENDPOINT + API.MODEL_ID_VAR_PATH_SEGMENT);
}
}

View file

@ -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<Page<UserInfo>> {
protected GetUserAccounts() {
super(
new TypeReference<Page<UserInfo>>() {
},
HttpMethod.GET,
MediaType.APPLICATION_FORM_URLENCODED,
API.USER_ACCOUNT_ENDPOINT);
}
}

View file

@ -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<ROW extends Entity> {
@ -20,8 +23,13 @@ public final class ColumnDefinition<ROW extends Entity> {
final LocTextKey tooltip;
final int widthPercent;
final Function<ROW, Object> 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<ROW extends Entity> {
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<ROW extends Entity> {
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<ROW extends Entity> {
final Function<ROW, Object> 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<ROW, Object> 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<ROW, Object> 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<ROW, Object> 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<ROW extends Entity> {
final LocTextKey tooltip,
final int widthPercent,
final Function<ROW, Object> 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<Tuple<String>> 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<Tuple<String>> selectionResource) {
this.type = type;
this.columnName = columnName;
this.initValue = initValue;
this.selectionResource = selectionResource;
}
}
}

View file

@ -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 {
}

View file

@ -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<ROW extends Entity> 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<Page<ROW>> restCall;
private transient final List<ColumnDefinition<ROW>> columns;
private transient final List<TableRowAction> actions;
transient final WidgetFactory widgetFactory;
transient final RestCall<Page<ROW>> restCall;
transient final List<ColumnDefinition<ROW>> columns;
transient final List<TableRowAction> actions;
private transient final TableFilter<ROW> filter;
private transient final Table table;
@ -65,8 +72,7 @@ public class EntityTable<ROW extends Entity> extends Composite {
final WidgetFactory widgetFactory,
final List<ColumnDefinition<ROW>> columns,
final List<TableRowAction> actions,
final int pageSize,
final boolean withFilter) {
final int pageSize) {
super(parent, type);
this.widgetFactory = widgetFactory;
@ -75,22 +81,34 @@ public class EntityTable<ROW extends Entity> 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<Table> locFunction = (Consumer<Table>) this.table.getData(POLYGLOT_WIDGET_FUNCTION_KEY);
final Consumer<Table> 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<ROW extends Entity> 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<ROW extends Entity> 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<ROW extends Entity> 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<ROW extends Entity> extends Composite {
// TODO error handling
});
this.layout();
this.layout(true, true);
}
private Page<ROW> createTableRowsFromPage(final Page<ROW> page) {
@ -223,31 +248,55 @@ public class EntityTable<ROW extends Entity> extends Composite {
item.setData(TABLE_ROW_DATA, row);
int index = 0;
for (final ColumnDefinition<ROW> 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<ROW> 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<ROW> column : this.columns) {
@ -256,16 +305,37 @@ public class EntityTable<ROW extends Entity> 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);

View file

@ -22,14 +22,14 @@ import ch.ethz.seb.sebserver.gui.service.widget.WidgetFactory;
/** <code>
* new TableBuilder<T>(RestCall)
* .withPaging(pageSize)
* .withFilterAttribute(attribute.TableFilterAttribute)
* .withColumn(new ColumnDefinition(
* columnName:String,
* displayName:LocTextKey,
* tooltip:LocTextKey,
* width:int,
* valueSupplier:Function<ROW, String>,
* sortable:boolean,
* columnFilter:TableColumnFilter))
* sortable:boolean
* .withAction(action:TableRowAction)
* .withSelectableRows(boolean)
* .compose(parent:Composit, group:Composite);
@ -38,6 +38,7 @@ public class TableBuilder<ROW extends Entity> {
private final WidgetFactory widgetFactory;
final RestCall<Page<ROW>> restCall;
// final List<TableFilterAttribute> filter = new ArrayList<>();
final List<ColumnDefinition<ROW>> columns = new ArrayList<>();
final List<TableRowAction> actions = new ArrayList<>();
@ -57,8 +58,8 @@ public class TableBuilder<ROW extends Entity> {
return this;
}
public TableBuilder<ROW> withColumn(final ColumnDefinition<ROW> columnDef) {
this.columns.add(columnDef);
public TableBuilder<ROW> withColumn(final ColumnDefinition<ROW> columnDefinition) {
this.columns.add(columnDefinition);
return this;
}
@ -73,12 +74,6 @@ public class TableBuilder<ROW extends Entity> {
}
public EntityTable<ROW> 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<ROW extends Entity> {
this.widgetFactory,
this.columns,
this.actions,
this.pageSize,
withFilter);
this.pageSize);
}
}

View file

@ -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<ROW extends Entity> extends Composite implements FilterAttributeSupplier {
public class TableFilter<ROW extends Entity> extends Composite {
private static final long serialVersionUID = -2460403977147440766L;
TableFilter(final EntityTable<ROW> parent) {
super(parent, SWT.NONE);
public static enum CriteriaType {
TEXT,
SINGLE_SELECTION,
COUNTRY_SELECTION,
DATE
}
@Override
public MultiValueMap<String, String> getAttributes() {
// TODO Auto-generated method stub
return null;
private final EntityTable<ROW> entityTable;
private final List<FilterComponent> components;
TableFilter(final EntityTable<ROW> 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<String, String> getFilterParameter() {
return this.components
.stream()
.reduce(new LinkedMultiValueMap<String, String>(),
(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<String, String> putFilterParameter(
final LinkedMultiValueMap<String, String> 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();
}
}
}

View file

@ -68,8 +68,6 @@ public class TableNavigator extends Composite {
}
}
this.layout();
return pageData;
}

View file

@ -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);

View file

@ -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<LanguageSelector> updateFunction;
public LanguageSelector(final Composite parent, final I18nSupport i18nSupport) {
super(parent, getLanguages(i18nSupport));
this.updateFunction = updateFunction(i18nSupport);
this.setData(POLYGLOT_WIDGET_FUNCTION_KEY, this.updateFunction);
}
private static final Consumer<LanguageSelector> updateFunction(final I18nSupport i18nSupport) {
return selection -> selection.applyNewMapping(getLanguages(i18nSupport));
}
public static final List<Tuple<String>> getLanguages(final I18nSupport i18nSupport) {
final Locale currentLocale = i18nSupport.getCurrentLocale();
return i18nSupport.supportedLanguages()
.stream()
.map(locale -> new Tuple<>(locale.toLanguageTag(), locale.getDisplayLanguage(currentLocale)))
.filter(tuple -> StringUtils.isNoneBlank(tuple._2))
.sorted((t1, t2) -> t1._2.compareTo(t2._2))
.collect(Collectors.toList());
}
public void clear() {
super.clearSelection();
this.updateFunction.accept(this);
}
}

View file

@ -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<Tuple<String>> 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<Tuple<String>> 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()]));
}

View file

@ -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<Label, Consumer<ActionEvent>> 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);
// });
}
};
}

View file

@ -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<T extends GrantEntity, M extends GrantEnt
@RequestParam(name = Page.ATTR_SORT, required = false) final String sort,
@RequestParam final MultiValueMap<String, String> 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<T extends GrantEntity, M extends GrantEnt
defaultValue = UserService.USERS_INSTITUTION_AS_DEFAULT) final Long institutionId,
@RequestParam final MultiValueMap<String, String> 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()

View file

@ -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

View file

@ -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

View file

@ -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.<br/>Those will also be deactivated by deactivating this Institution.<br/><br/>Are You sure to deactivate this Institution?
sebserver.institution.form.confirm.deactivation.noDependencies=Are You sure to deactivate this Institution?
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}
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

View file

@ -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 {

View file

Before

Width:  |  Height:  |  Size: 246 B

After

Width:  |  Height:  |  Size: 246 B

View file

Before

Width:  |  Height:  |  Size: 168 B

After

Width:  |  Height:  |  Size: 168 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 186 B

After

Width:  |  Height:  |  Size: 148 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 148 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 186 B

View file

Before

Width:  |  Height:  |  Size: 165 B

After

Width:  |  Height:  |  Size: 165 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 220 B

View file

Before

Width:  |  Height:  |  Size: 121 B

After

Width:  |  Height:  |  Size: 121 B

View file

Before

Width:  |  Height:  |  Size: 165 B

After

Width:  |  Height:  |  Size: 165 B

View file

Before

Width:  |  Height:  |  Size: 211 B

After

Width:  |  Height:  |  Size: 211 B

View file

@ -31,8 +31,8 @@ import org.springframework.test.context.jdbc.Sql;
import com.fasterxml.jackson.core.type.TypeReference;
import ch.ethz.seb.sebserver.gbl.Constants;
import ch.ethz.seb.sebserver.gbl.api.APIMessage;
import ch.ethz.seb.sebserver.gbl.api.API;
import ch.ethz.seb.sebserver.gbl.api.APIMessage;
import ch.ethz.seb.sebserver.gbl.model.Domain;
import ch.ethz.seb.sebserver.gbl.model.Entity;
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
@ -138,7 +138,7 @@ public class UserAPITest extends AdministrationAPIIntegrationTester {
public void getAllUserInfoNoFilter() throws Exception {
Page<UserInfo> userInfos = new RestAPITestHelper()
.withAccessToken(getSebAdminAccess())
.withPath(API.USER_ACCOUNT_ENDPOINT)
.withPath(API.USER_ACCOUNT_ENDPOINT + "?institutionId=1")
.withExpectedStatus(HttpStatus.OK)
.getAsObject(new TypeReference<Page<UserInfo>>() {
});
@ -205,7 +205,7 @@ public class UserAPITest extends AdministrationAPIIntegrationTester {
final String token = getSebAdminAccess();
final Page<UserInfo> 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<UserInfo> 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<UserInfo> 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<UserInfo> 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<UserInfo> 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<EntityName> 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())