SEBSERV-28 # first implementation with sort and navigation
still left : filtering
This commit is contained in:
parent
94a75735ee
commit
8f10dd6163
28 changed files with 876 additions and 59 deletions
|
@ -16,6 +16,7 @@ public final class Constants {
|
|||
|
||||
public static final Character LIST_SEPARATOR_CHAR = ',';
|
||||
public static final String LIST_SEPARATOR = ",";
|
||||
public static final String EMPTY_NOTE = "--";
|
||||
|
||||
/** Date-Time formatter without milliseconds using UTC time-zone. Pattern is yyyy-MM-dd HH:mm:ss */
|
||||
public static final DateTimeFormatter DATE_TIME_PATTERN_UTC_NO_MILLIS = DateTimeFormat
|
||||
|
|
|
@ -22,4 +22,6 @@ public class SEBServerRestEndpoints {
|
|||
|
||||
public static final String ENDPOINT_USER_ACTIVITY_LOG = "/useractivity";
|
||||
|
||||
public static final String NAMES_ENDPOINT_SUFFIX = "/names";
|
||||
|
||||
}
|
||||
|
|
|
@ -51,16 +51,16 @@ public final class Page<T> {
|
|||
this.sort = sort;
|
||||
}
|
||||
|
||||
public Integer getNumberOfPages() {
|
||||
return this.numberOfPages;
|
||||
public int getNumberOfPages() {
|
||||
return (this.numberOfPages != null) ? this.numberOfPages : 1;
|
||||
}
|
||||
|
||||
public Integer getPageNumber() {
|
||||
return this.pageNumber;
|
||||
public int getPageNumber() {
|
||||
return (this.pageNumber != null) ? this.pageNumber : 0;
|
||||
}
|
||||
|
||||
public Integer getPageSize() {
|
||||
return this.pageSize;
|
||||
public int getPageSize() {
|
||||
return (this.pageSize != null) ? this.pageSize : -1;
|
||||
}
|
||||
|
||||
public Collection<T> getContent() {
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* Copyright (c) 2019 ETH Zürich, Educational Development and Technology (LET)
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package ch.ethz.seb.sebserver.gui.service;
|
||||
|
||||
import org.eclipse.swt.widgets.Composite;
|
||||
import org.eclipse.swt.widgets.Control;
|
||||
|
||||
public final class RWTUtils {
|
||||
|
||||
public static final String TEXT_NAME_H2 = "h2";
|
||||
|
||||
public static void clearComposite(final Composite parent) {
|
||||
if (parent == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (final Control control : parent.getChildren()) {
|
||||
control.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -16,21 +16,22 @@ public interface PolyglotPageService {
|
|||
|
||||
String POLYGLOT_WIDGET_FUNCTION_KEY = "POLYGLOT_WIDGET_FUNCTION";
|
||||
String POLYGLOT_TREE_ITEM_TEXT_DATA_KEY = "POLYGLOT_TREE_ITEM_TEXT_DATA";
|
||||
String POLYGLOT_TREE_ITEM_TOOLTIP_DATA_KEY = "POLYGLOT_TREE_ITEM_TOOLTIP_DATA";
|
||||
|
||||
/** Gets the underling I18nSupport
|
||||
*
|
||||
*
|
||||
* @return the underling I18nSupport */
|
||||
I18nSupport getI18nSupport();
|
||||
|
||||
/** The default locale for the page.
|
||||
* Uses I18nSupport.getCurrentLocale to do so.
|
||||
*
|
||||
*
|
||||
* @param root the root Composite of the page to change the language */
|
||||
void setDefaultPageLocale(Composite root);
|
||||
|
||||
/** Sets the given Locale and if needed, updates the page language according to the
|
||||
* given Locale
|
||||
*
|
||||
*
|
||||
* @param root root the root Composite of the page to change the language
|
||||
* @param locale the Locale to set */
|
||||
void setPageLocale(Composite root, Locale locale);
|
||||
|
|
|
@ -10,10 +10,10 @@ package ch.ethz.seb.sebserver.gui.service.page;
|
|||
|
||||
public interface TemplateComposer {
|
||||
|
||||
default boolean validate(final PageContext context) {
|
||||
default boolean validate(final PageContext pageContext) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void compose(PageContext composerCtx);
|
||||
void compose(PageContext pageContext);
|
||||
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ import ch.ethz.seb.sebserver.gui.service.i18n.LocTextKey;
|
|||
import ch.ethz.seb.sebserver.gui.service.page.PageContext.AttributeKeys;
|
||||
import ch.ethz.seb.sebserver.gui.service.page.TemplateComposer;
|
||||
import ch.ethz.seb.sebserver.gui.service.page.action.ActionPane;
|
||||
import ch.ethz.seb.sebserver.gui.service.page.content.InstitutionList;
|
||||
import ch.ethz.seb.sebserver.gui.service.page.impl.TODOTemplate;
|
||||
|
||||
public class ActivitySelection {
|
||||
|
@ -31,7 +32,7 @@ public class ActivitySelection {
|
|||
public enum Activity {
|
||||
NONE(TODOTemplate.class, TODOTemplate.class, (String) null),
|
||||
INSTITUTION_ROOT(
|
||||
TODOTemplate.class,
|
||||
InstitutionList.class,
|
||||
ActionPane.class,
|
||||
new LocTextKey("sebserver.activities.inst")),
|
||||
INSTITUTION_NODE(
|
||||
|
|
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
* 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.SWT;
|
||||
import org.eclipse.swt.layout.GridData;
|
||||
import org.eclipse.swt.layout.GridLayout;
|
||||
import org.eclipse.swt.widgets.Composite;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.model.Domain;
|
||||
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.institution.GetInstitutions;
|
||||
import ch.ethz.seb.sebserver.gui.service.table.ColumnDefinition;
|
||||
import ch.ethz.seb.sebserver.gui.service.widget.WidgetFactory;
|
||||
|
||||
@Lazy
|
||||
@Component
|
||||
@GuiProfile
|
||||
public class InstitutionList implements TemplateComposer {
|
||||
|
||||
private final WidgetFactory widgetFactory;
|
||||
private final RestService restService;
|
||||
|
||||
protected InstitutionList(
|
||||
final WidgetFactory widgetFactory,
|
||||
final RestService restService) {
|
||||
|
||||
this.widgetFactory = widgetFactory;
|
||||
this.restService = restService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void compose(final PageContext pageContext) {
|
||||
final Composite content = new Composite(pageContext.getParent(), SWT.NONE);
|
||||
final GridLayout contentLayout = new GridLayout();
|
||||
contentLayout.marginLeft = 10;
|
||||
content.setLayout(contentLayout);
|
||||
content.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
|
||||
|
||||
this.widgetFactory.labelLocalizedTitle(
|
||||
content,
|
||||
new LocTextKey("sebserver.institution.list.title"));
|
||||
|
||||
this.widgetFactory.entityTableBuilder(this.restService.getRestCall(GetInstitutions.class))
|
||||
.withPaging(3)
|
||||
.withColumn(new ColumnDefinition<>(
|
||||
Domain.INSTITUTION.ATTR_NAME,
|
||||
new LocTextKey("sebserver.institution.list.column.name"),
|
||||
null,
|
||||
0,
|
||||
entity -> entity.name,
|
||||
null,
|
||||
true))
|
||||
.withColumn(new ColumnDefinition<>(
|
||||
Domain.INSTITUTION.ATTR_URL_SUFFIX,
|
||||
new LocTextKey("sebserver.institution.list.column.urlSuffix"),
|
||||
null,
|
||||
0,
|
||||
entity -> entity.urlSuffix,
|
||||
null,
|
||||
true))
|
||||
.withColumn(new ColumnDefinition<>(
|
||||
Domain.INSTITUTION.ATTR_ACTIVE,
|
||||
new LocTextKey("sebserver.institution.list.column.active"),
|
||||
null,
|
||||
0,
|
||||
entity -> entity.active,
|
||||
null,
|
||||
true))
|
||||
.compose(content);
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -14,13 +14,13 @@ import java.util.function.Function;
|
|||
import java.util.stream.Collectors;
|
||||
|
||||
import org.eclipse.swt.widgets.Composite;
|
||||
import org.eclipse.swt.widgets.Control;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
|
||||
import ch.ethz.seb.sebserver.gui.service.RWTUtils;
|
||||
import ch.ethz.seb.sebserver.gui.service.i18n.I18nSupport;
|
||||
import ch.ethz.seb.sebserver.gui.service.page.ComposerService;
|
||||
import ch.ethz.seb.sebserver.gui.service.page.PageContext;
|
||||
|
@ -108,7 +108,7 @@ public class ComposerServiceImpl implements ComposerService {
|
|||
|
||||
if (composer.validate(pageContext)) {
|
||||
|
||||
clear(pageContext.getParent());
|
||||
RWTUtils.clearComposite(pageContext.getParent());
|
||||
|
||||
try {
|
||||
composer.compose(pageContext);
|
||||
|
@ -173,14 +173,4 @@ public class ComposerServiceImpl implements ComposerService {
|
|||
this.i18nSupport, this, root, root, null);
|
||||
}
|
||||
|
||||
private void clear(final Composite parent) {
|
||||
if (parent == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (final Control control : parent.getChildren()) {
|
||||
control.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
/*
|
||||
* 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();
|
||||
|
||||
}
|
|
@ -30,6 +30,7 @@ import com.fasterxml.jackson.core.type.TypeReference;
|
|||
|
||||
import ch.ethz.seb.sebserver.gbl.api.APIMessage;
|
||||
import ch.ethz.seb.sebserver.gbl.api.JSONMapper;
|
||||
import ch.ethz.seb.sebserver.gbl.model.Entity;
|
||||
import ch.ethz.seb.sebserver.gbl.model.Page;
|
||||
import ch.ethz.seb.sebserver.gbl.util.Result;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.PaginationService.SortOrder;
|
||||
|
@ -166,7 +167,21 @@ public abstract class RestCall<T> {
|
|||
}
|
||||
|
||||
public RestCallBuilder withSorting(final String column, final SortOrder order) {
|
||||
this.queryParams.put(Page.ATTR_SORT, Arrays.asList(order.prefix + column));
|
||||
if (column != null) {
|
||||
this.queryParams.put(Page.ATTR_SORT, Arrays.asList(order.encode(column)));
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public RestCallBuilder withFilterAttributes(final FilterAttributeSupplier filterAttributes) {
|
||||
if (filterAttributes != null) {
|
||||
this.queryParams.putAll(filterAttributes.getAttributes());
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public RestCallBuilder onlyActive(final boolean active) {
|
||||
this.queryParams.put(Entity.FILTER_ATTR_ACTIVE, Arrays.asList(String.valueOf(active)));
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -188,6 +203,7 @@ public abstract class RestCall<T> {
|
|||
return new HttpEntity<>(this.httpHeaders);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -33,7 +33,13 @@ public class GetInstitutionNames extends RestCall<List<EntityName>> {
|
|||
},
|
||||
HttpMethod.GET,
|
||||
MediaType.APPLICATION_FORM_URLENCODED,
|
||||
SEBServerRestEndpoints.ENDPOINT_INSTITUTION + "/names");
|
||||
SEBServerRestEndpoints.ENDPOINT_INSTITUTION + SEBServerRestEndpoints.NAMES_ENDPOINT_SUFFIX);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RestCall<List<EntityName>>.RestCallBuilder newBuilder() {
|
||||
return super.newBuilder()
|
||||
.onlyActive(true);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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.institution;
|
||||
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.api.SEBServerRestEndpoints;
|
||||
import ch.ethz.seb.sebserver.gbl.model.Page;
|
||||
import ch.ethz.seb.sebserver.gbl.model.institution.Institution;
|
||||
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCall;
|
||||
|
||||
@Lazy
|
||||
@Component
|
||||
@GuiProfile
|
||||
public class GetInstitutions extends RestCall<Page<Institution>> {
|
||||
|
||||
protected GetInstitutions() {
|
||||
super(
|
||||
new TypeReference<Page<Institution>>() {
|
||||
},
|
||||
HttpMethod.GET,
|
||||
MediaType.APPLICATION_FORM_URLENCODED,
|
||||
SEBServerRestEndpoints.ENDPOINT_INSTITUTION);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
* 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;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.model.Entity;
|
||||
import ch.ethz.seb.sebserver.gui.service.i18n.LocTextKey;
|
||||
|
||||
public final class ColumnDefinition<ROW extends Entity> {
|
||||
|
||||
final String columnName;
|
||||
final LocTextKey displayName;
|
||||
final LocTextKey tooltip;
|
||||
final int widthPercent;
|
||||
final Function<ROW, Object> valueSupplier;
|
||||
final ColumnFilterDefinition filter;
|
||||
final boolean sortable;
|
||||
|
||||
public ColumnDefinition(
|
||||
final String columnName,
|
||||
final LocTextKey displayName,
|
||||
final LocTextKey tooltip,
|
||||
final int widthPercent) {
|
||||
|
||||
this(columnName, displayName, tooltip, widthPercent, null, null, false);
|
||||
}
|
||||
|
||||
public ColumnDefinition(
|
||||
final String columnName,
|
||||
final LocTextKey displayName,
|
||||
final int widthPercent) {
|
||||
|
||||
this(columnName, displayName, null, widthPercent, null, null, false);
|
||||
}
|
||||
|
||||
public ColumnDefinition(
|
||||
final String columnName,
|
||||
final LocTextKey displayName,
|
||||
final LocTextKey tooltip,
|
||||
final int widthPercent,
|
||||
final Function<ROW, Object> valueSupplier,
|
||||
final ColumnFilterDefinition filter,
|
||||
final boolean sortable) {
|
||||
|
||||
this.columnName = columnName;
|
||||
this.displayName = displayName;
|
||||
this.tooltip = tooltip;
|
||||
this.widthPercent = widthPercent;
|
||||
this.valueSupplier = valueSupplier;
|
||||
this.filter = filter;
|
||||
this.sortable = sortable;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
/*
|
||||
* Copyright (c) 2019 ETH Zürich, Educational Development and Technology (LET)
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package ch.ethz.seb.sebserver.gui.service.table;
|
||||
|
||||
public class ColumnFilterDefinition {
|
||||
|
||||
}
|
|
@ -0,0 +1,250 @@
|
|||
/*
|
||||
* Copyright (c) 2019 ETH Zürich, Educational Development and Technology (LET)
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package ch.ethz.seb.sebserver.gui.service.table;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
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.Event;
|
||||
import org.eclipse.swt.widgets.Table;
|
||||
import org.eclipse.swt.widgets.TableColumn;
|
||||
import org.eclipse.swt.widgets.TableItem;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.model.Entity;
|
||||
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.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 final WidgetFactory widgetFactory;
|
||||
|
||||
private final RestCall<Page<ROW>> restCall;
|
||||
private final List<ColumnDefinition<ROW>> columns;
|
||||
private final List<TableRowAction> actions;
|
||||
|
||||
private final TableFilter<ROW> filter;
|
||||
private final Table table;
|
||||
private final TableNavigator navigator;
|
||||
|
||||
private final boolean selectableRows;
|
||||
|
||||
private int pageNumber = 1;
|
||||
private int pageSize;
|
||||
private String sortColumn = null;
|
||||
private SortOrder sortOrder = SortOrder.ASCENDING;
|
||||
|
||||
private boolean columnsWithSameWidth = true;
|
||||
|
||||
EntityTable(
|
||||
final Composite parent,
|
||||
final RestCall<Page<ROW>> restCall,
|
||||
final WidgetFactory widgetFactory,
|
||||
final List<ColumnDefinition<ROW>> columns,
|
||||
final List<TableRowAction> actions,
|
||||
final int pageSize,
|
||||
final boolean withFilter,
|
||||
final boolean selectableRows) {
|
||||
|
||||
super(parent, SWT.NONE);
|
||||
this.widgetFactory = widgetFactory;
|
||||
this.restCall = restCall;
|
||||
this.columns = Utils.immutableListOf(columns);
|
||||
this.actions = Utils.immutableListOf(actions);
|
||||
|
||||
super.setLayout(new GridLayout());
|
||||
super.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
|
||||
|
||||
this.pageSize = pageSize;
|
||||
this.filter = (withFilter) ? new TableFilter<>(this) : null;
|
||||
this.selectableRows = selectableRows;
|
||||
|
||||
this.table = widgetFactory.tableLocalized(this);
|
||||
this.table.setLayout(new GridLayout(columns.size(), true));
|
||||
final GridData gridData = new GridData(SWT.FILL, SWT.CENTER, true, false);
|
||||
this.table.setLayoutData(gridData);
|
||||
this.table.addListener(SWT.Resize, this::adaptColumnWidth);
|
||||
|
||||
//this.table.setLayoutData(new GridData(GridData.FILL_BOTH));
|
||||
this.table.setHeaderVisible(true);
|
||||
this.table.setLinesVisible(true);
|
||||
|
||||
this.navigator = new TableNavigator(this);
|
||||
|
||||
createTableColumns();
|
||||
updateTableRows(
|
||||
this.pageNumber,
|
||||
this.pageSize,
|
||||
this.sortColumn,
|
||||
this.sortOrder);
|
||||
}
|
||||
|
||||
public void setPageSize(final int pageSize) {
|
||||
this.pageSize = pageSize;
|
||||
updateTableRows(
|
||||
this.pageNumber,
|
||||
this.pageSize,
|
||||
this.sortColumn,
|
||||
this.sortOrder);
|
||||
}
|
||||
|
||||
public void selectPage(final int pageSelection) {
|
||||
// verify input
|
||||
this.pageNumber = pageSelection;
|
||||
if (this.pageNumber < 1) {
|
||||
this.pageNumber = 1;
|
||||
}
|
||||
|
||||
updateTableRows(
|
||||
this.pageNumber,
|
||||
this.pageSize,
|
||||
this.sortColumn,
|
||||
this.sortOrder);
|
||||
}
|
||||
|
||||
public void applyFilter() {
|
||||
// TODO remove all rows, set current page to 0, call rest to get entities and build rows and navigation again
|
||||
}
|
||||
|
||||
public void applySort(final String columnName) {
|
||||
this.sortColumn = columnName;
|
||||
this.sortOrder = SortOrder.ASCENDING;
|
||||
|
||||
updateTableRows(
|
||||
this.pageNumber,
|
||||
this.pageSize,
|
||||
this.sortColumn,
|
||||
this.sortOrder);
|
||||
}
|
||||
|
||||
public void changeSortOrder() {
|
||||
this.sortOrder = (this.sortOrder == SortOrder.ASCENDING)
|
||||
? SortOrder.DESCENDING
|
||||
: SortOrder.ASCENDING;
|
||||
|
||||
updateTableRows(
|
||||
this.pageNumber,
|
||||
this.pageSize,
|
||||
this.sortColumn,
|
||||
this.sortOrder);
|
||||
}
|
||||
|
||||
private void createTableColumns() {
|
||||
for (final ColumnDefinition<ROW> column : this.columns) {
|
||||
final TableColumn tableColumn = this.widgetFactory.tableColumnLocalized(
|
||||
this.table,
|
||||
column.displayName,
|
||||
column.tooltip);
|
||||
|
||||
if (column.sortable) {
|
||||
tableColumn.addListener(SWT.Selection, event -> {
|
||||
if (!column.columnName.equals(this.sortColumn)) {
|
||||
applySort(column.columnName);
|
||||
this.table.setSortColumn(tableColumn);
|
||||
this.table.setSortDirection(SWT.UP);
|
||||
} else {
|
||||
changeSortOrder();
|
||||
this.table.setSortDirection(
|
||||
(this.sortOrder == SortOrder.ASCENDING) ? SWT.UP : SWT.DOWN);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (column.widthPercent > 0) {
|
||||
this.columnsWithSameWidth = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void updateTableRows(
|
||||
final int pageNumber,
|
||||
final int pageSize,
|
||||
final String sortColumn,
|
||||
final SortOrder sortOrder) {
|
||||
|
||||
// first remove all rows if there are some
|
||||
this.table.removeAll();
|
||||
|
||||
// get page data and create rows
|
||||
this.restCall.newBuilder()
|
||||
.withPaging(pageNumber, pageSize)
|
||||
.withSorting(sortColumn, sortOrder)
|
||||
.withFilterAttributes(this.filter)
|
||||
.call()
|
||||
.map(this::createTableRowsFromPage)
|
||||
.map(this.navigator::update)
|
||||
.onErrorDo(t -> {
|
||||
// TODO error handling
|
||||
});
|
||||
|
||||
this.layout();
|
||||
}
|
||||
|
||||
private Page<ROW> createTableRowsFromPage(final Page<ROW> page) {
|
||||
for (final ROW row : page.content) {
|
||||
final TableItem item = new TableItem(this.table, SWT.NONE);
|
||||
item.setData(TABLE_ROW_DATA, row);
|
||||
int index = 0;
|
||||
if (this.selectableRows) {
|
||||
// TODO
|
||||
}
|
||||
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 {
|
||||
item.setText(index, String.valueOf(value));
|
||||
}
|
||||
index++;
|
||||
}
|
||||
if (this.actions != null) {
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
|
||||
return page;
|
||||
}
|
||||
|
||||
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) {
|
||||
|
||||
final int percentage = (this.columnsWithSameWidth)
|
||||
? 100 / this.columns.size()
|
||||
: column.widthPercent;
|
||||
|
||||
final TableColumn tableColumn = this.table.getColumn(index);
|
||||
tableColumn.setWidth(currentTableWidth / 100 * percentage);
|
||||
|
||||
index++;
|
||||
}
|
||||
|
||||
} catch (final Exception e) {
|
||||
log.warn("Failed to adaptColumnWidth: ", e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,92 @@
|
|||
/*
|
||||
* 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;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.swt.widgets.Composite;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.model.Entity;
|
||||
import ch.ethz.seb.sebserver.gbl.model.Page;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCall;
|
||||
import ch.ethz.seb.sebserver.gui.service.widget.WidgetFactory;
|
||||
|
||||
/** <code>
|
||||
* new TableBuilder<T>(RestCall)
|
||||
* .withPaging(pageSize)
|
||||
* .withColumn(new ColumnDefinition(
|
||||
* columnName:String,
|
||||
* displayName:LocTextKey,
|
||||
* tooltip:LocTextKey,
|
||||
* width:int,
|
||||
* valueSupplier:Function<ROW, String>,
|
||||
* sortable:boolean,
|
||||
* columnFilter:TableColumnFilter))
|
||||
* .withAction(action:TableRowAction)
|
||||
* .withSelectableRows(boolean)
|
||||
* .compose(parent:Composit, group:Composite);
|
||||
* </code> */
|
||||
public class TableBuilder<ROW extends Entity> {
|
||||
|
||||
private final WidgetFactory widgetFactory;
|
||||
final RestCall<Page<ROW>> restCall;
|
||||
final List<ColumnDefinition<ROW>> columns = new ArrayList<>();
|
||||
final List<TableRowAction> actions = new ArrayList<>();
|
||||
|
||||
private int pageSize = -1;
|
||||
private boolean selectableRows = false;
|
||||
|
||||
public TableBuilder(
|
||||
final WidgetFactory widgetFactory,
|
||||
final RestCall<Page<ROW>> restCall) {
|
||||
|
||||
this.widgetFactory = widgetFactory;
|
||||
this.restCall = restCall;
|
||||
}
|
||||
|
||||
public TableBuilder<ROW> withPaging(final int pageSize) {
|
||||
this.pageSize = pageSize;
|
||||
return this;
|
||||
}
|
||||
|
||||
public TableBuilder<ROW> withColumn(final ColumnDefinition<ROW> columnDef) {
|
||||
this.columns.add(columnDef);
|
||||
return this;
|
||||
}
|
||||
|
||||
public TableBuilder<ROW> withSelectableRows() {
|
||||
this.selectableRows = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public TableBuilder<ROW> withAction(final TableRowAction action) {
|
||||
this.actions.add(action);
|
||||
return this;
|
||||
}
|
||||
|
||||
public EntityTable<ROW> compose(final Composite parent) {
|
||||
final boolean withFilter = this.columns
|
||||
.stream()
|
||||
.filter(c -> c.filter != null)
|
||||
.findFirst()
|
||||
.isPresent();
|
||||
|
||||
return new EntityTable<>(
|
||||
parent,
|
||||
this.restCall,
|
||||
this.widgetFactory,
|
||||
this.columns,
|
||||
this.actions,
|
||||
this.pageSize,
|
||||
withFilter,
|
||||
this.selectableRows);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* 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;
|
||||
|
||||
import org.eclipse.swt.SWT;
|
||||
import org.eclipse.swt.widgets.Composite;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.model.Entity;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.FilterAttributeSupplier;
|
||||
|
||||
public class TableFilter<ROW extends Entity> extends Composite implements FilterAttributeSupplier {
|
||||
|
||||
private static final long serialVersionUID = -2460403977147440766L;
|
||||
|
||||
TableFilter(final EntityTable<ROW> parent) {
|
||||
super(parent, SWT.NONE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MultiValueMap<String, String> getAttributes() {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,112 @@
|
|||
/*
|
||||
* 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;
|
||||
|
||||
import org.eclipse.rap.rwt.RWT;
|
||||
import org.eclipse.swt.SWT;
|
||||
import org.eclipse.swt.layout.GridData;
|
||||
import org.eclipse.swt.layout.GridLayout;
|
||||
import org.eclipse.swt.layout.RowLayout;
|
||||
import org.eclipse.swt.widgets.Composite;
|
||||
import org.eclipse.swt.widgets.Label;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.model.Page;
|
||||
import ch.ethz.seb.sebserver.gui.service.RWTUtils;
|
||||
|
||||
public class TableNavigator extends Composite {
|
||||
|
||||
private static final long serialVersionUID = -7349918232061226192L;
|
||||
|
||||
private final int pageNavSize = 3;
|
||||
private final EntityTable<?> entityTable;
|
||||
|
||||
TableNavigator(final EntityTable<?> entityTable) {
|
||||
super(entityTable, SWT.NONE);
|
||||
super.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
|
||||
|
||||
final GridLayout layout = new GridLayout(3, true);
|
||||
layout.marginLeft = 20;
|
||||
super.setLayout(layout);
|
||||
|
||||
this.entityTable = entityTable;
|
||||
}
|
||||
|
||||
public Page<?> update(final Page<?> pageData) {
|
||||
// clear all
|
||||
RWTUtils.clearComposite(this);
|
||||
|
||||
final int pageNumber = pageData.getPageNumber();
|
||||
final int numberOfPages = pageData.getNumberOfPages();
|
||||
|
||||
createPagingHeader(pageNumber, numberOfPages);
|
||||
|
||||
final Composite numNav = new Composite(this, SWT.NONE);
|
||||
numNav.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
|
||||
final RowLayout rowLayout = new RowLayout(SWT.HORIZONTAL);
|
||||
rowLayout.spacing = 5;
|
||||
numNav.setLayout(rowLayout);
|
||||
|
||||
if (numberOfPages > 1) {
|
||||
if (pageNumber > 1) {
|
||||
createRewardLabel(pageNumber, numNav);
|
||||
}
|
||||
|
||||
for (int i = pageNumber - this.pageNavSize; i < pageNumber + this.pageNavSize; i++) {
|
||||
if (i >= 1 && i <= numberOfPages) {
|
||||
createPageNumberLabel(i, i != pageNumber, numNav);
|
||||
}
|
||||
}
|
||||
|
||||
if (pageNumber < numberOfPages) {
|
||||
createForwardLabel(pageNumber, numNav);
|
||||
}
|
||||
}
|
||||
|
||||
this.layout();
|
||||
|
||||
return pageData;
|
||||
}
|
||||
|
||||
private void createPagingHeader(final int page, final int of) {
|
||||
final Label pageHeader = new Label(this, SWT.NONE);
|
||||
pageHeader.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
|
||||
pageHeader.setText("Page " + page + "/" + of);
|
||||
}
|
||||
|
||||
private void createPageNumberLabel(final int page, final boolean selectable, final Composite parent) {
|
||||
final Label pageLabel = new Label(parent, SWT.NONE);
|
||||
|
||||
pageLabel.setText(" " + String.valueOf(page) + " ");
|
||||
if (selectable) {
|
||||
pageLabel.setData(RWT.CUSTOM_VARIANT, "action");
|
||||
pageLabel.addListener(SWT.MouseDown, event -> {
|
||||
this.entityTable.selectPage(page);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void createForwardLabel(final int pageNumber, final Composite parent) {
|
||||
final Label forward = new Label(parent, SWT.NONE);
|
||||
forward.setText(">");
|
||||
forward.setData(RWT.CUSTOM_VARIANT, "action");
|
||||
forward.addListener(SWT.MouseDown, event -> {
|
||||
this.entityTable.selectPage(pageNumber + 1);
|
||||
});
|
||||
}
|
||||
|
||||
private void createRewardLabel(final int pageNumber, final Composite parent) {
|
||||
final Label reward = new Label(parent, SWT.NONE);
|
||||
reward.setText("<");
|
||||
reward.setData(RWT.CUSTOM_VARIANT, "action");
|
||||
reward.addListener(SWT.MouseDown, event -> {
|
||||
this.entityTable.selectPage(pageNumber - 1);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
/*
|
||||
* Copyright (c) 2019 ETH Zürich, Educational Development and Technology (LET)
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package ch.ethz.seb.sebserver.gui.service.table;
|
||||
|
||||
public class TableRowAction {
|
||||
|
||||
}
|
|
@ -8,8 +8,7 @@
|
|||
|
||||
package ch.ethz.seb.sebserver.gui.service.widget;
|
||||
|
||||
import static ch.ethz.seb.sebserver.gui.service.i18n.PolyglotPageService.POLYGLOT_TREE_ITEM_TEXT_DATA_KEY;
|
||||
import static ch.ethz.seb.sebserver.gui.service.i18n.PolyglotPageService.POLYGLOT_WIDGET_FUNCTION_KEY;
|
||||
import static ch.ethz.seb.sebserver.gui.service.i18n.PolyglotPageService.*;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.Iterator;
|
||||
|
@ -39,12 +38,17 @@ import org.slf4j.LoggerFactory;
|
|||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.model.Entity;
|
||||
import ch.ethz.seb.sebserver.gbl.model.Page;
|
||||
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
|
||||
import ch.ethz.seb.sebserver.gbl.util.Tuple;
|
||||
import ch.ethz.seb.sebserver.gui.service.RWTUtils;
|
||||
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.remote.webservice.api.RestCall;
|
||||
import ch.ethz.seb.sebserver.gui.service.table.TableBuilder;
|
||||
|
||||
@Lazy
|
||||
@Service
|
||||
|
@ -158,6 +162,12 @@ public class WidgetFactory {
|
|||
return label;
|
||||
}
|
||||
|
||||
public Label labelLocalizedTitle(final Composite content, final LocTextKey locTextKey) {
|
||||
final Label labelLocalized = labelLocalized(content, RWTUtils.TEXT_NAME_H2, locTextKey);
|
||||
labelLocalized.setLayoutData(new GridData(SWT.TOP, SWT.LEFT, true, false));
|
||||
return labelLocalized;
|
||||
}
|
||||
|
||||
public Tree treeLocalized(final Composite parent, final int style) {
|
||||
final Tree tree = new Tree(parent, SWT.SINGLE | SWT.FULL_SELECTION);
|
||||
this.injectI18n(tree);
|
||||
|
@ -188,15 +198,23 @@ public class WidgetFactory {
|
|||
return item;
|
||||
}
|
||||
|
||||
public <T extends Entity> TableBuilder<T> entityTableBuilder(final RestCall<Page<T>> apiCall) {
|
||||
return new TableBuilder<>(this, apiCall);
|
||||
}
|
||||
|
||||
public Table tableLocalized(final Composite parent) {
|
||||
final Table table = new Table(parent, SWT.NONE);
|
||||
final Table table = new Table(parent, SWT.SINGLE | SWT.NO_SCROLL);
|
||||
this.injectI18n(table);
|
||||
return table;
|
||||
}
|
||||
|
||||
public TableColumn tableColumnLocalized(final Table table, final String locTextKey) {
|
||||
public TableColumn tableColumnLocalized(
|
||||
final Table table,
|
||||
final LocTextKey locTextKey,
|
||||
final LocTextKey toolTipKey) {
|
||||
|
||||
final TableColumn tableColumn = new TableColumn(table, SWT.NONE);
|
||||
this.injectI18n(tableColumn, new LocTextKey(locTextKey));
|
||||
this.injectI18n(tableColumn, locTextKey, toolTipKey);
|
||||
return tableColumn;
|
||||
}
|
||||
|
||||
|
@ -322,9 +340,14 @@ public class WidgetFactory {
|
|||
table.setData(POLYGLOT_WIDGET_FUNCTION_KEY, tableFunction(this.i18nSupport));
|
||||
}
|
||||
|
||||
public void injectI18n(final TableColumn tableColumn, final LocTextKey locTextKey) {
|
||||
public void injectI18n(final TableColumn tableColumn, final LocTextKey locTextKey, final LocTextKey locTooltipKey) {
|
||||
tableColumn.setData(POLYGLOT_TREE_ITEM_TEXT_DATA_KEY, locTextKey);
|
||||
tableColumn.setText(this.i18nSupport.getText(locTextKey));
|
||||
|
||||
if (locTooltipKey != null) {
|
||||
tableColumn.setData(POLYGLOT_TREE_ITEM_TOOLTIP_DATA_KEY, locTooltipKey);
|
||||
tableColumn.setToolTipText(this.i18nSupport.getText(locTooltipKey));
|
||||
}
|
||||
}
|
||||
|
||||
public void injectI18n(final TableItem tableItem, final LocTextKey... locTextKey) {
|
||||
|
|
|
@ -27,6 +27,7 @@ import ch.ethz.seb.sebserver.gbl.model.Page;
|
|||
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
|
||||
import ch.ethz.seb.sebserver.gbl.util.Result;
|
||||
import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.ExamRecordDynamicSqlSupport;
|
||||
import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.InstitutionRecordDynamicSqlSupport;
|
||||
import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.UserActivityLogRecordDynamicSqlSupport;
|
||||
import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.UserRecordDynamicSqlSupport;
|
||||
|
||||
|
@ -36,29 +37,26 @@ import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.UserRecordDynamic
|
|||
public class PaginationService {
|
||||
|
||||
public enum SortOrder {
|
||||
ASCENDING("+"),
|
||||
DESCENDING("-");
|
||||
ASCENDING,
|
||||
DESCENDING;
|
||||
|
||||
public final String prefix;
|
||||
public final static String DESCENDING_PREFIX = "-";
|
||||
|
||||
private SortOrder(final String prefix) {
|
||||
this.prefix = prefix;
|
||||
public String encode(final String sort) {
|
||||
return (this == DESCENDING) ? DESCENDING_PREFIX + sort : sort;
|
||||
}
|
||||
|
||||
public static SortOrder getSortOrder(final String sort) {
|
||||
return (sort != null && sort.startsWith(DESCENDING.prefix))
|
||||
public static String decode(final String sort) {
|
||||
return (sort != null && sort.startsWith(DESCENDING_PREFIX))
|
||||
? sort.substring(1)
|
||||
: sort;
|
||||
}
|
||||
|
||||
public static SortOrder getSortOrder(final String encoded) {
|
||||
return (encoded != null && encoded.startsWith(DESCENDING_PREFIX))
|
||||
? SortOrder.DESCENDING
|
||||
: SortOrder.ASCENDING;
|
||||
}
|
||||
|
||||
public static String getSortColumn(final String sort) {
|
||||
return (sort == null)
|
||||
? null
|
||||
: (sort.startsWith(SortOrder.ASCENDING.prefix) || sort.startsWith(SortOrder.DESCENDING.prefix))
|
||||
? sort.substring(1)
|
||||
: sort;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private final int defaultPageSize;
|
||||
|
@ -137,10 +135,11 @@ public class PaginationService {
|
|||
final com.github.pagehelper.Page<Object> startPage =
|
||||
PageHelper.startPage(getPageNumber(pageNumber), getPageSize(pageSize), true, true, false);
|
||||
|
||||
if (table != null) {
|
||||
if (table != null && StringUtils.isNoneBlank(sort)) {
|
||||
final SortOrder sortOrder = SortOrder.getSortOrder(sort);
|
||||
final String sortColumnName = verifySortColumnName(sort, table);
|
||||
if (StringUtils.isNoneBlank(sortColumnName)) {
|
||||
switch (SortOrder.getSortOrder(sort)) {
|
||||
switch (sortOrder) {
|
||||
case DESCENDING: {
|
||||
PageHelper.orderBy(sortColumnName + " DESC");
|
||||
break;
|
||||
|
@ -178,7 +177,7 @@ public class PaginationService {
|
|||
|
||||
final Map<String, String> mapping = this.sortColumnMapping.get(table.name());
|
||||
if (mapping != null) {
|
||||
final String sortColumn = SortOrder.getSortColumn(sort);
|
||||
final String sortColumn = SortOrder.decode(sort);
|
||||
if (StringUtils.isBlank(sortColumn)) {
|
||||
return this.defaultSortColumn.get(table.name());
|
||||
}
|
||||
|
@ -191,6 +190,24 @@ public class PaginationService {
|
|||
// TODO is it possible to generate this within MyBatis generator?
|
||||
private void initSortColumnMapping() {
|
||||
|
||||
// Institution Table
|
||||
final Map<String, String> institutionTableMap = new HashMap<>();
|
||||
institutionTableMap.put(
|
||||
Domain.INSTITUTION.ATTR_NAME,
|
||||
InstitutionRecordDynamicSqlSupport.name.name());
|
||||
institutionTableMap.put(
|
||||
Domain.INSTITUTION.ATTR_URL_SUFFIX,
|
||||
InstitutionRecordDynamicSqlSupport.urlSuffix.name());
|
||||
institutionTableMap.put(
|
||||
Domain.INSTITUTION.ATTR_ACTIVE,
|
||||
InstitutionRecordDynamicSqlSupport.active.name());
|
||||
this.sortColumnMapping.put(
|
||||
InstitutionRecordDynamicSqlSupport.institutionRecord.name(),
|
||||
institutionTableMap);
|
||||
this.defaultSortColumn.put(
|
||||
InstitutionRecordDynamicSqlSupport.institutionRecord.name(),
|
||||
Domain.INSTITUTION.ATTR_ID);
|
||||
|
||||
// User Table
|
||||
final Map<String, String> userTableMap = new HashMap<>();
|
||||
userTableMap.put(Domain.USER.ATTR_NAME, UserRecordDynamicSqlSupport.name.name());
|
||||
|
|
|
@ -107,7 +107,7 @@ final class MockupLmsAPITemplate implements LmsAPITemplate {
|
|||
? -1
|
||||
: 1;
|
||||
|
||||
final String _sort = SortOrder.getSortColumn(sort);
|
||||
final String _sort = SortOrder.decode(sort);
|
||||
final Comparator<QuizData> comp = (_sort != null)
|
||||
? (_sort.equals(QuizData.FILTER_ATTR_START_TIME))
|
||||
? (q1, q2) -> q1.startTime.compareTo(q2.startTime) * orderFactor
|
||||
|
|
|
@ -30,9 +30,9 @@ import org.springframework.web.bind.annotation.RequestMethod;
|
|||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.model.Domain.LMS_SETUP;
|
||||
import ch.ethz.seb.sebserver.gbl.api.POSTMapper;
|
||||
import ch.ethz.seb.sebserver.gbl.api.SEBServerRestEndpoints;
|
||||
import ch.ethz.seb.sebserver.gbl.model.Domain.LMS_SETUP;
|
||||
import ch.ethz.seb.sebserver.gbl.model.Entity;
|
||||
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
|
||||
import ch.ethz.seb.sebserver.gbl.model.EntityType;
|
||||
|
@ -137,7 +137,7 @@ public class ExamAdministrationController extends ActivatableEntityController<Ex
|
|||
this.examDAO.allMatching(new FilterMap(allRequestParams)).getOrThrow());
|
||||
|
||||
if (!StringUtils.isBlank(sort)) {
|
||||
final String sortBy = SortOrder.getSortColumn(sort);
|
||||
final String sortBy = SortOrder.decode(sort);
|
||||
if (sortBy.equals(QuizData.QUIZ_ATTR_NAME)) {
|
||||
Collections.sort(exams, (exam1, exam2) -> exam1.name.compareTo(exam2.name));
|
||||
}
|
||||
|
|
|
@ -12,9 +12,7 @@ import java.util.Collection;
|
|||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
|
||||
import org.springframework.context.ApplicationEvent;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.context.event.EventListener;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.security.oauth2.common.OAuth2AccessToken;
|
||||
|
@ -29,7 +27,6 @@ import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
|
|||
|
||||
@Controller
|
||||
@WebServiceProfile
|
||||
@Import(DataSourceAutoConfiguration.class)
|
||||
public class RevokeTokenEndpoint {
|
||||
|
||||
private final ConsumerTokenServices tokenServices;
|
||||
|
|
|
@ -18,8 +18,6 @@ sebserver.webservice.api.exam.accessTokenValiditySeconds=1800
|
|||
sebserver.webservice.api.exam.refreshTokenValiditySeconds=-1
|
||||
sebserver.webservice.api.redirect.unauthorized=http://=0.0.0.0:8080/gui
|
||||
|
||||
sebserver.webservice.api.redirect.unauthorized=none
|
||||
|
||||
server.servlet.session.cookie.http-only=true
|
||||
server.servlet.session.tracking-modes=cookie
|
||||
|
||||
|
|
|
@ -29,3 +29,13 @@ sebserver.actionpane.title=Actions
|
|||
sebserver.activities.inst=Institution
|
||||
|
||||
sebserver.error.unexpected=Unexpected Error
|
||||
|
||||
|
||||
################################
|
||||
# Institution
|
||||
################################
|
||||
|
||||
sebserver.institution.list.title=Institutions
|
||||
sebserver.institution.list.column.name=Name
|
||||
sebserver.institution.list.column.urlSuffix=URL Suffix
|
||||
sebserver.institution.list.column.active=Active
|
|
@ -26,6 +26,21 @@ Label {
|
|||
text-shadow: none;
|
||||
}
|
||||
|
||||
Label.action {
|
||||
font: 12px Verdana, "Lucida Sans", Arial, Helvetica, sans-serif;
|
||||
color: #82BE1E;
|
||||
background-color: transparent;
|
||||
background-image: none;
|
||||
background-repeat: repeat;
|
||||
background-position: left top;
|
||||
border: none;
|
||||
border-radius: 0;
|
||||
text-decoration: none;
|
||||
cursor: default;
|
||||
opacity: 1;
|
||||
text-shadow: none;
|
||||
}
|
||||
|
||||
Label.h1 {
|
||||
font: 25px Arial, Helvetica, sans-serif;
|
||||
height: 28px;
|
||||
|
|
Loading…
Add table
Reference in a new issue