diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/content/CertificateList.java b/src/main/java/ch/ethz/seb/sebserver/gui/content/CertificateList.java index d525d258..0c47202b 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/content/CertificateList.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/content/CertificateList.java @@ -112,6 +112,7 @@ public class CertificateList implements TemplateComposer { .withMultiSelection() .withEmptyMessage(EMPTY_LIST_TEXT_KEY) .withPaging(this.pageSize) + .withDefaultSort(CertificateInfo.ATTR_ALIAS) .withColumn(new ColumnDefinition<>( CertificateInfo.ATTR_ALIAS, diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/content/ConfigTemplateList.java b/src/main/java/ch/ethz/seb/sebserver/gui/content/ConfigTemplateList.java index 5576b2c8..08602b96 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/content/ConfigTemplateList.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/content/ConfigTemplateList.java @@ -106,6 +106,9 @@ public class ConfigTemplateList implements TemplateComposer { ConfigurationType.TEMPLATE.name()) .withEmptyMessage(EMPTY_TEMPLATE_LIST_TEXT_KEY) .withPaging(this.pageSize) + .withDefaultSort(isSEBAdmin + ? Domain.LMS_SETUP.ATTR_INSTITUTION_ID + : Domain.CONFIGURATION_NODE.ATTR_NAME) .withColumnIf( () -> isSEBAdmin, () -> new ColumnDefinition<>( diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/content/ExamList.java b/src/main/java/ch/ethz/seb/sebserver/gui/content/ExamList.java index 4b066b8c..339b3fc0 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/content/ExamList.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/content/ExamList.java @@ -145,8 +145,10 @@ public class ExamList implements TemplateComposer { .withEmptyMessage(EMPTY_LIST_TEXT_KEY) .withPaging(this.pageSize) .withRowDecorator(decorateOnExamConsistency(this.pageService)) - .withStaticFilter(Exam.FILTER_ATTR_ACTIVE, Constants.TRUE_STRING) + .withDefaultSort(isSEBAdmin.getAsBoolean() + ? Domain.EXAM.ATTR_INSTITUTION_ID + : Domain.EXAM.ATTR_LMS_SETUP_ID) .withColumnIf( isSEBAdmin, @@ -155,7 +157,8 @@ public class ExamList implements TemplateComposer { COLUMN_TITLE_INSTITUTION_KEY, exam -> institutionNameFunction .apply(String.valueOf(exam.getInstitutionId()))) - .withFilter(this.institutionFilter)) + .withFilter(this.institutionFilter) + .sortable()) .withColumn(new ColumnDefinition<>( Domain.EXAM.ATTR_LMS_SETUP_ID, diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/content/InstitutionList.java b/src/main/java/ch/ethz/seb/sebserver/gui/content/InstitutionList.java index bf763abd..41303cee 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/content/InstitutionList.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/content/InstitutionList.java @@ -96,6 +96,7 @@ public class InstitutionList implements TemplateComposer { this.pageService.entityTableBuilder(this.restService.getRestCall(GetInstitutionPage.class)) .withEmptyMessage(EMPTY_LIST_TEXT_KEY) .withPaging(this.pageSize) + .withDefaultSort(Domain.INSTITUTION.ATTR_NAME) .withColumn(new ColumnDefinition<>( Domain.INSTITUTION.ATTR_NAME, NAME_TEXT_KEY, diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/content/LmsSetupList.java b/src/main/java/ch/ethz/seb/sebserver/gui/content/LmsSetupList.java index 82ee213f..90e5bc28 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/content/LmsSetupList.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/content/LmsSetupList.java @@ -116,13 +116,15 @@ public class LmsSetupList implements TemplateComposer { this.pageService.entityTableBuilder(restService.getRestCall(GetLmsSetupPage.class)) .withEmptyMessage(EMPTY_LIST_TEXT_KEY) .withPaging(this.pageSize) + .withDefaultSort(isSEBAdmin ? Domain.LMS_SETUP.ATTR_INSTITUTION_ID : Domain.LMS_SETUP.ATTR_NAME) .withColumnIf( () -> isSEBAdmin, () -> new ColumnDefinition<>( Domain.LMS_SETUP.ATTR_INSTITUTION_ID, INSTITUTION_TEXT_KEY, lmsSetupInstitutionNameFunction(this.resourceService)) - .withFilter(this.institutionFilter)) + .withFilter(this.institutionFilter) + .sortable()) .withColumn(new ColumnDefinition<>( Domain.LMS_SETUP.ATTR_NAME, NAME_TEXT_KEY, diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/content/MonitoringRunningExamList.java b/src/main/java/ch/ethz/seb/sebserver/gui/content/MonitoringRunningExamList.java index a090c425..7dfe663e 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/content/MonitoringRunningExamList.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/content/MonitoringRunningExamList.java @@ -95,6 +95,7 @@ public class MonitoringRunningExamList implements TemplateComposer { .withEmptyMessage(EMPTY_LIST_TEXT_KEY) .withPaging(this.pageSize) .withRowDecorator(ExamList.decorateOnExamConsistency(this.pageService)) + .withDefaultSort(QuizData.QUIZ_ATTR_NAME) .withColumn(new ColumnDefinition<>( QuizData.QUIZ_ATTR_NAME, diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/content/SEBClientConfigList.java b/src/main/java/ch/ethz/seb/sebserver/gui/content/SEBClientConfigList.java index 35d0b0d9..184bc98b 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/content/SEBClientConfigList.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/content/SEBClientConfigList.java @@ -119,13 +119,17 @@ public class SEBClientConfigList implements TemplateComposer { this.pageService.entityTableBuilder(this.restService.getRestCall(GetClientConfigPage.class)) .withEmptyMessage(EMPTY_LIST_TEXT_KEY) .withPaging(this.pageSize) + .withDefaultSort(isSEBAdmin + ? Domain.LMS_SETUP.ATTR_INSTITUTION_ID + : Domain.SEB_CLIENT_CONFIGURATION.ATTR_NAME) .withColumnIf( () -> isSEBAdmin, () -> new ColumnDefinition<>( Domain.LMS_SETUP.ATTR_INSTITUTION_ID, INSTITUTION_TEXT_KEY, clientConfigInstitutionNameFunction(this.resourceService)) - .withFilter(this.institutionFilter)) + .withFilter(this.institutionFilter) + .sortable()) .withColumn(new ColumnDefinition<>( Domain.SEB_CLIENT_CONFIGURATION.ATTR_NAME, NAME_TEXT_KEY, diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/content/SEBClientEvents.java b/src/main/java/ch/ethz/seb/sebserver/gui/content/SEBClientEvents.java index e3aa051c..bc303c35 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/content/SEBClientEvents.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/content/SEBClientEvents.java @@ -149,6 +149,7 @@ public class SEBClientEvents implements TemplateComposer { this.restService.getRestCall(GetExtendedClientEventPage.class)) .withEmptyMessage(EMPTY_TEXT_KEY) .withPaging(this.pageSize) + .withDefaultSort(Domain.CLIENT_CONNECTION.ATTR_EXAM_USER_SESSION_ID) .withColumn(new ColumnDefinition<>( Domain.CLIENT_CONNECTION.ATTR_EXAM_ID, diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/content/SEBExamConfigList.java b/src/main/java/ch/ethz/seb/sebserver/gui/content/SEBExamConfigList.java index a549a49e..bad37515 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/content/SEBExamConfigList.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/content/SEBExamConfigList.java @@ -113,6 +113,9 @@ public class SEBExamConfigList implements TemplateComposer { ConfigurationType.EXAM_CONFIG.name()) .withEmptyMessage(EMPTY_CONFIG_LIST_TEXT_KEY) .withPaging(this.pageSize) + .withDefaultSort(isSEBAdmin + ? Domain.LMS_SETUP.ATTR_INSTITUTION_ID + : Domain.CONFIGURATION_NODE.ATTR_NAME) .withColumnIf( () -> isSEBAdmin, () -> new ColumnDefinition<>( diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/content/UserAccountList.java b/src/main/java/ch/ethz/seb/sebserver/gui/content/UserAccountList.java index 9766af20..5a4dbb67 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/content/UserAccountList.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/content/UserAccountList.java @@ -138,7 +138,7 @@ public class UserAccountList implements TemplateComposer { restService.getRestCall(GetUserAccountPage.class)) .withEmptyMessage(EMPTY_TEXT_KEY) .withPaging(this.pageSize) - + .withDefaultSort(isSEBAdmin.getAsBoolean() ? Domain.USER.ATTR_INSTITUTION_ID : Domain.USER.ATTR_NAME) .withColumnIf( isSEBAdmin, () -> new ColumnDefinition<>( @@ -146,7 +146,8 @@ public class UserAccountList implements TemplateComposer { INSTITUTION_TEXT_KEY, userInstitutionNameFunction(this.resourceService)) .withFilter(this.institutionFilter) - .widthProportion(2)) + .widthProportion(2) + .sortable()) .withColumn(new ColumnDefinition<>( Domain.USER.ATTR_NAME, diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/content/UserActivityLogs.java b/src/main/java/ch/ethz/seb/sebserver/gui/content/UserActivityLogs.java index 766d5837..283a8e12 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/content/UserActivityLogs.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/content/UserActivityLogs.java @@ -183,14 +183,17 @@ public class UserActivityLogs implements TemplateComposer { restService.getRestCall(GetUserLogPage.class)) .withEmptyMessage(EMPTY_TEXT_KEY) .withPaging(this.pageSize) - + .withDefaultSort(isSEBAdmin.getAsBoolean() + ? UserActivityLog.FILTER_ATTR_INSTITUTION + : UserActivityLog.ATTR_USER_NAME) .withColumnIf( isSEBAdmin, () -> new ColumnDefinition<>( UserActivityLog.FILTER_ATTR_INSTITUTION, INSTITUTION_TEXT_KEY, institutionNameFunction) - .withFilter(this.institutionFilter)) + .withFilter(this.institutionFilter) + .sortable()) .withColumn(new ColumnDefinition<>( UserActivityLog.ATTR_USER_NAME, diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/table/EntityTable.java b/src/main/java/ch/ethz/seb/sebserver/gui/table/EntityTable.java index a910207e..613e4b39 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/table/EntityTable.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/table/EntityTable.java @@ -97,6 +97,9 @@ public class EntityTable { private final Consumer> selectionListener; private final Consumer contentChangeListener; + private final String defaultSortColumn; + private final PageSortOrder defaultSortOrder; + int pageNumber; int pageSize; String sortColumn = null; @@ -120,7 +123,9 @@ public class EntityTable { final MultiValueMap staticQueryParams, final BiConsumer rowDecorator, final Consumer> selectionListener, - final Consumer contentChangeListener) { + final Consumer contentChangeListener, + final String defaultSortColumn, + final PageSortOrder defaultSortOrder) { this.name = name; this.filterAttrName = name + "_filter"; @@ -129,6 +134,9 @@ public class EntityTable { this.currentPageAttrName = name + "_currentPage"; this.markupEnabled = markupEnabled; + this.defaultSortColumn = defaultSortColumn; + this.defaultSortOrder = defaultSortOrder; + this.composite = new Composite(pageContext.getParent(), SWT.NONE); this.pageService = pageService; this.i18nSupport = pageService.getI18nSupport(); @@ -281,9 +289,10 @@ public class EntityTable { } public void reset() { - this.applySort(null); - this.table.setSortColumn(null); - this.table.setSortDirection(SWT.NONE); + this.sortColumn = this.defaultSortColumn; + this.sortOrder = this.defaultSortOrder; + updateSortUserAttr(); + setTableSort(); applyFilter(); } @@ -306,10 +315,10 @@ public class EntityTable { return this.filter.getFilterParameter(); } - public void applySort(final String columnName) { + public void applySort(final String columnName, final PageSortOrder order) { try { this.sortColumn = columnName; - this.sortOrder = PageSortOrder.ASCENDING; + this.sortOrder = order; if (columnName != null) { updateTableRows( @@ -455,7 +464,7 @@ public class EntityTable { if (column.isSortable()) { tableColumn.addListener(SWT.Selection, event -> { if (!column.columnName.equals(this.sortColumn)) { - applySort(column.columnName); + applySort(column.columnName, PageSortOrder.ASCENDING); this.table.setSortColumn(tableColumn); this.table.setSortDirection(SWT.UP); } else { @@ -713,10 +722,8 @@ public class EntityTable { .getAttribute(this.sortAttrName); if (StringUtils.isNotBlank(sort)) { this.sortColumn = sort; - final TableColumn tableColumn = getTableColumn(sort); - if (tableColumn != null) { - this.table.setSortColumn(tableColumn); - } + } else { + this.sortColumn = this.defaultSortColumn; } final String sortOrder = this.pageService @@ -724,14 +731,30 @@ public class EntityTable { .getAttribute(this.sortOrderAttrName); if (StringUtils.isNotBlank(sortOrder)) { this.sortOrder = PageSortOrder.valueOf(sortOrder); - this.table.setSortDirection(this.sortOrder == PageSortOrder.ASCENDING ? SWT.UP : SWT.DOWN); + } else { + this.sortOrder = this.defaultSortOrder; } + setTableSort(); + } catch (final Exception e) { log.error("Failed to get sort attribute form current user attributes", e); } } + private void setTableSort() { + if (this.sortColumn != null) { + final TableColumn tableColumn = getTableColumn(this.sortColumn); + if (tableColumn != null) { + this.table.setSortColumn(tableColumn); + } + this.table.setSortDirection(this.sortOrder == PageSortOrder.ASCENDING ? SWT.UP : SWT.DOWN); + } else { + this.table.setSortColumn(null); + this.table.setSortDirection(SWT.NONE); + } + } + private void updateFilterUserAttrs() { if (this.filter != null) { try { diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/table/TableBuilder.java b/src/main/java/ch/ethz/seb/sebserver/gui/table/TableBuilder.java index 77ce5917..6275ad97 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/table/TableBuilder.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/table/TableBuilder.java @@ -24,6 +24,7 @@ import org.springframework.util.MultiValueMap; import ch.ethz.seb.sebserver.gbl.api.EntityType; import ch.ethz.seb.sebserver.gbl.model.Page; +import ch.ethz.seb.sebserver.gbl.model.PageSortOrder; import ch.ethz.seb.sebserver.gui.service.i18n.LocTextKey; import ch.ethz.seb.sebserver.gui.service.page.PageContext; import ch.ethz.seb.sebserver.gui.service.page.PageService; @@ -49,6 +50,8 @@ public class TableBuilder { private Consumer> selectionListener; private Consumer contentChangeListener; private boolean markupEnabled = false; + private String defaultSortColumn = null; + private PageSortOrder defaultSortOrder = PageSortOrder.ASCENDING; public TableBuilder( final String name, @@ -106,6 +109,16 @@ public class TableBuilder { return this; } + public TableBuilder withDefaultSort(final String defaultSortColumn) { + this.defaultSortColumn = defaultSortColumn; + return this; + } + + public TableBuilder withDefaultSortOrder(final PageSortOrder defaultSortOrder) { + this.defaultSortOrder = defaultSortOrder; + return this; + } + public TableBuilder withColumn(final ColumnDefinition columnDefinition) { this.columns.add(columnDefinition); return this; @@ -209,7 +222,9 @@ public class TableBuilder { this.staticQueryParams, this.rowDecorator, this.selectionListener, - this.contentChangeListener); + this.contentChangeListener, + this.defaultSortColumn, + this.defaultSortOrder); } } diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/PaginationService.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/PaginationService.java index 1993dfa7..e01725aa 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/PaginationService.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/PaginationService.java @@ -101,9 +101,10 @@ public interface PaginationService { if (sorted.size() < end) { end = sorted.size(); } + final int numberOfPages = sorted.size() / _pageSize; return new Page<>( - sorted.size() / _pageSize, + (numberOfPages > 0) ? numberOfPages : 1, _pageNumber, sort, sorted.subList(start, end)); diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/PaginationServiceImpl.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/PaginationServiceImpl.java index 372f9f9a..8e26546d 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/PaginationServiceImpl.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/PaginationServiceImpl.java @@ -25,8 +25,10 @@ import ch.ethz.seb.sebserver.gbl.model.Domain; import ch.ethz.seb.sebserver.gbl.model.Entity; import ch.ethz.seb.sebserver.gbl.model.Page; import ch.ethz.seb.sebserver.gbl.model.PageSortOrder; +import ch.ethz.seb.sebserver.gbl.model.user.UserActivityLog; 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.ClientConnectionRecordDynamicSqlSupport; import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.ClientEventRecordDynamicSqlSupport; import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.ConfigurationNodeRecordDynamicSqlSupport; import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.ExamRecordDynamicSqlSupport; @@ -75,7 +77,7 @@ public class PaginationServiceImpl implements PaginationService { return false; } - return tableMap.containsKey(orderBy); + return tableMap.containsKey(PageSortOrder.decode(orderBy)); } /** Use this to set a page limitation on SQL level. This checks first if there is @@ -194,6 +196,11 @@ public class PaginationServiceImpl implements PaginationService { private void initSortColumnMapping() { + final String institutionNameRef = "institution." + InstitutionRecordDynamicSqlSupport.name.name(); + final String lmsSetupNameRef = "lms_setup." + LmsSetupRecordDynamicSqlSupport.name.name(); + final String clientConnectionNameRef = + "client_connection." + ClientConnectionRecordDynamicSqlSupport.examUserSessionId.name(); + // define and initialize sort column mapping for... // Institution Table @@ -216,6 +223,7 @@ public class PaginationServiceImpl implements PaginationService { // User Table final Map userTableMap = new HashMap<>(); + userTableMap.put(Domain.USER.ATTR_INSTITUTION_ID, institutionNameRef); userTableMap.put(Domain.USER.ATTR_NAME, UserRecordDynamicSqlSupport.name.name()); userTableMap.put(Domain.USER.ATTR_SURNAME, UserRecordDynamicSqlSupport.surname.name()); userTableMap.put(Domain.USER.ATTR_USERNAME, UserRecordDynamicSqlSupport.username.name()); @@ -226,6 +234,7 @@ public class PaginationServiceImpl implements PaginationService { // LMS Setup Table final Map lmsSetupTableMap = new HashMap<>(); + lmsSetupTableMap.put(Domain.LMS_SETUP.ATTR_INSTITUTION_ID, institutionNameRef); lmsSetupTableMap.put(Domain.LMS_SETUP.ATTR_NAME, LmsSetupRecordDynamicSqlSupport.name.name()); lmsSetupTableMap.put(Domain.LMS_SETUP.ATTR_LMS_TYPE, LmsSetupRecordDynamicSqlSupport.lmsType.name()); this.sortColumnMapping.put(LmsSetupRecordDynamicSqlSupport.lmsSetupRecord.name(), lmsSetupTableMap); @@ -233,18 +242,15 @@ public class PaginationServiceImpl implements PaginationService { // Exam Table final Map examTableMap = new HashMap<>(); - examTableMap.put( - Domain.EXAM.ATTR_TYPE, - ExamRecordDynamicSqlSupport.type.name()); - this.sortColumnMapping.put( - ExamRecordDynamicSqlSupport.examRecord.name(), - examTableMap); - this.defaultSortColumn.put( - ExamRecordDynamicSqlSupport.examRecord.name(), - Domain.EXAM.ATTR_ID); + examTableMap.put(Entity.FILTER_ATTR_INSTITUTION, institutionNameRef); + examTableMap.put(Domain.EXAM.ATTR_LMS_SETUP_ID, lmsSetupNameRef); + examTableMap.put(Domain.EXAM.ATTR_TYPE, ExamRecordDynamicSqlSupport.type.name()); + this.sortColumnMapping.put(ExamRecordDynamicSqlSupport.examRecord.name(), examTableMap); + this.defaultSortColumn.put(ExamRecordDynamicSqlSupport.examRecord.name(), Domain.EXAM.ATTR_ID); // SEB Client Configuration Table final Map sebClientConfigTableMap = new HashMap<>(); + lmsSetupTableMap.put(Domain.SEB_CLIENT_CONFIGURATION.ATTR_INSTITUTION_ID, institutionNameRef); sebClientConfigTableMap.put( Domain.SEB_CLIENT_CONFIGURATION.ATTR_INSTITUTION_ID, SebClientConfigRecordDynamicSqlSupport.institutionId.name()); @@ -265,7 +271,7 @@ public class PaginationServiceImpl implements PaginationService { final Map configurationNodeTableMap = new HashMap<>(); configurationNodeTableMap.put( Domain.CONFIGURATION_NODE.ATTR_INSTITUTION_ID, - ConfigurationNodeRecordDynamicSqlSupport.institutionId.name()); + institutionNameRef); configurationNodeTableMap.put( Domain.CONFIGURATION_NODE.ATTR_NAME, ConfigurationNodeRecordDynamicSqlSupport.name.name()); @@ -284,6 +290,9 @@ public class PaginationServiceImpl implements PaginationService { // ClientEvent table final Map clientEventTableMap = new HashMap<>(); + clientEventTableMap.put( + Domain.CLIENT_CONNECTION.ATTR_EXAM_USER_SESSION_ID, + clientConnectionNameRef); clientEventTableMap.put( Domain.CLIENT_EVENT.ATTR_TYPE, ClientEventRecordDynamicSqlSupport.type.name()); @@ -296,6 +305,9 @@ public class PaginationServiceImpl implements PaginationService { clientEventTableMap.put( Domain.CLIENT_EVENT.ATTR_TEXT, ClientEventRecordDynamicSqlSupport.text.name()); + clientEventTableMap.put( + Domain.CLIENT_EVENT.ATTR_NUMERIC_VALUE, + ClientEventRecordDynamicSqlSupport.numericValue.name()); this.sortColumnMapping.put( ClientEventRecordDynamicSqlSupport.clientEventRecord.name(), clientEventTableMap); @@ -305,6 +317,9 @@ public class PaginationServiceImpl implements PaginationService { // User Activity Log Table final Map userActivityLogTableMap = new HashMap<>(); + userActivityLogTableMap.put( + UserActivityLog.FILTER_ATTR_INSTITUTION, + institutionNameRef); userActivityLogTableMap.put( Domain.USER.ATTR_USERNAME, UserRecordDynamicSqlSupport.username.name()); diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/FilterMap.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/FilterMap.java index bd57f548..9b0922bd 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/FilterMap.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/FilterMap.java @@ -45,6 +45,9 @@ import ch.ethz.seb.sebserver.gbl.util.Utils; * All text based filter criteria are used as SQL wildcard's */ public class FilterMap extends POSTMapper { + public static final String ATTR_ADD_INSITUTION_JOIN = "ADD_INSITUTION_JOIN"; + public static final String ATTR_ADD_LMS_SETUP_JOIN = "ADD_LMS_SETUP_JOIN"; + public FilterMap() { super(new LinkedMultiValueMap<>(), null); } diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/UserActivityLogDAO.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/UserActivityLogDAO.java index 956fe8d7..66e36654 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/UserActivityLogDAO.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/UserActivityLogDAO.java @@ -8,9 +8,6 @@ package ch.ethz.seb.sebserver.webservice.servicelayer.dao; -import java.util.Collection; -import java.util.function.Predicate; - import ch.ethz.seb.sebserver.gbl.api.EntityType; import ch.ethz.seb.sebserver.gbl.model.Entity; import ch.ethz.seb.sebserver.gbl.model.user.UserAccount; @@ -136,13 +133,4 @@ public interface UserActivityLogDAO extends return log(user, activityType, entity, null); } - Result> all( - Long InstitutionId, - String userId, - Long from, - Long to, - String activityTypes, - String entityTypes, - Predicate predicate); - } diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ClientConnectionDAOImpl.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ClientConnectionDAOImpl.java index e039cc93..c2c60e33 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ClientConnectionDAOImpl.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ClientConnectionDAOImpl.java @@ -21,6 +21,8 @@ import java.util.stream.Collectors; import org.apache.commons.lang3.BooleanUtils; import org.mybatis.dynamic.sql.SqlBuilder; +import org.mybatis.dynamic.sql.select.MyBatis3SelectModelAdapter; +import org.mybatis.dynamic.sql.select.QueryExpressionDSL; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Component; import org.springframework.transaction.annotation.Transactional; @@ -41,6 +43,7 @@ import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.ClientEventRecord import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.ClientInstructionRecordDynamicSqlSupport; import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.ClientInstructionRecordMapper; 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.RemoteProctoringRoomRecordDynamicSqlSupport; import ch.ethz.seb.sebserver.webservice.datalayer.batis.model.ClientConnectionRecord; import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.impl.BulkAction; @@ -88,30 +91,44 @@ public class ClientConnectionDAOImpl implements ClientConnectionDAO { final FilterMap filterMap, final Predicate predicate) { - return Result.tryCatch(() -> this.clientConnectionRecordMapper - .selectByExample() - .where( - ClientConnectionRecordDynamicSqlSupport.institutionId, - isEqualToWhenPresent(filterMap.getInstitutionId())) - .and( - ClientConnectionRecordDynamicSqlSupport.examId, - isEqualToWhenPresent(filterMap.getClientConnectionExamId())) - .and( - ClientConnectionRecordDynamicSqlSupport.status, - isEqualToWhenPresent(filterMap.getClientConnectionStatus())) - .and( - ClientConnectionRecordDynamicSqlSupport.examUserSessionId, - isLikeWhenPresent(filterMap.getClientConnectionUserId())) - .and( - ClientConnectionRecordDynamicSqlSupport.clientAddress, - isLikeWhenPresent(filterMap.getClientConnectionIPAddress())) - .build() - .execute() - .stream() - .map(ClientConnectionDAOImpl::toDomainModel) - .flatMap(DAOLoggingSupport::logAndSkipOnError) - .filter(predicate) - .collect(Collectors.toList())); + return Result.tryCatch(() -> { + final QueryExpressionDSL>>.QueryExpressionWhereBuilder whereClause = + (filterMap.getBoolean(FilterMap.ATTR_ADD_INSITUTION_JOIN)) + ? this.clientConnectionRecordMapper + .selectByExample() + .join(InstitutionRecordDynamicSqlSupport.institutionRecord) + .on(InstitutionRecordDynamicSqlSupport.id, + SqlBuilder.equalTo(ClientConnectionRecordDynamicSqlSupport.institutionId)) + .where( + ClientConnectionRecordDynamicSqlSupport.institutionId, + isEqualToWhenPresent(filterMap.getInstitutionId())) + + : this.clientConnectionRecordMapper + .selectByExample() + .where( + ClientConnectionRecordDynamicSqlSupport.institutionId, + isEqualToWhenPresent(filterMap.getInstitutionId())); + return whereClause + .and( + ClientConnectionRecordDynamicSqlSupport.examId, + isEqualToWhenPresent(filterMap.getClientConnectionExamId())) + .and( + ClientConnectionRecordDynamicSqlSupport.status, + isEqualToWhenPresent(filterMap.getClientConnectionStatus())) + .and( + ClientConnectionRecordDynamicSqlSupport.examUserSessionId, + isLikeWhenPresent(filterMap.getClientConnectionUserId())) + .and( + ClientConnectionRecordDynamicSqlSupport.clientAddress, + isLikeWhenPresent(filterMap.getClientConnectionIPAddress())) + .build() + .execute() + .stream() + .map(ClientConnectionDAOImpl::toDomainModel) + .flatMap(DAOLoggingSupport::logAndSkipOnError) + .filter(predicate) + .collect(Collectors.toList()); + }); } @Override diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ConfigurationNodeDAOImpl.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ConfigurationNodeDAOImpl.java index 84a6a9b8..c78d2425 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ConfigurationNodeDAOImpl.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ConfigurationNodeDAOImpl.java @@ -20,6 +20,8 @@ import java.util.function.Predicate; import java.util.stream.Collectors; import org.mybatis.dynamic.sql.SqlBuilder; +import org.mybatis.dynamic.sql.select.MyBatis3SelectModelAdapter; +import org.mybatis.dynamic.sql.select.QueryExpressionDSL; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Component; import org.springframework.transaction.annotation.Transactional; @@ -42,6 +44,7 @@ import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.ConfigurationReco import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.ConfigurationRecordMapper; import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.ConfigurationValueRecordDynamicSqlSupport; import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.ConfigurationValueRecordMapper; +import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.InstitutionRecordDynamicSqlSupport; import ch.ethz.seb.sebserver.webservice.datalayer.batis.model.ConfigurationNodeRecord; import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.impl.BulkAction; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ConfigurationNodeDAO; @@ -104,33 +107,46 @@ public class ConfigurationNodeDAOImpl implements ConfigurationNodeDAO { final FilterMap filterMap, final Predicate predicate) { - return Result.tryCatch(() -> this.configurationNodeRecordMapper - .selectByExample() - .where( - ConfigurationNodeRecordDynamicSqlSupport.status, - SqlBuilder.isEqualToWhenPresent(filterMap.getConfigNodeStatus())) - .and( - ConfigurationNodeRecordDynamicSqlSupport.institutionId, - SqlBuilder.isEqualToWhenPresent(filterMap.getInstitutionId())) - .and( - ConfigurationNodeRecordDynamicSqlSupport.name, - SqlBuilder.isLikeWhenPresent(filterMap.getName())) - .and( - ConfigurationNodeRecordDynamicSqlSupport.description, - SqlBuilder.isLikeWhenPresent(filterMap.getConfigNodeDesc())) - .and( - ConfigurationNodeRecordDynamicSqlSupport.type, - SqlBuilder.isEqualToWhenPresent(filterMap.getConfigNodeType())) - .and( - ConfigurationNodeRecordDynamicSqlSupport.templateId, - SqlBuilder.isEqualToWhenPresent(filterMap.getConfigNodeTemplateId())) - .build() - .execute() - .stream() - .map(ConfigurationNodeDAOImpl::toDomainModel) - .flatMap(DAOLoggingSupport::logAndSkipOnError) - .filter(predicate) - .collect(Collectors.toList())); + return Result.tryCatch(() -> { + final QueryExpressionDSL>>.QueryExpressionWhereBuilder whereClause = + (filterMap.getBoolean(FilterMap.ATTR_ADD_INSITUTION_JOIN)) + ? this.configurationNodeRecordMapper + .selectByExample() + .join(InstitutionRecordDynamicSqlSupport.institutionRecord) + .on(InstitutionRecordDynamicSqlSupport.id, + SqlBuilder.equalTo(ConfigurationNodeRecordDynamicSqlSupport.institutionId)) + .where( + ConfigurationNodeRecordDynamicSqlSupport.status, + SqlBuilder.isEqualToWhenPresent(filterMap.getConfigNodeStatus())) + : this.configurationNodeRecordMapper + .selectByExample() + .where( + ConfigurationNodeRecordDynamicSqlSupport.status, + SqlBuilder.isEqualToWhenPresent(filterMap.getConfigNodeStatus())); + + return whereClause.and( + ConfigurationNodeRecordDynamicSqlSupport.institutionId, + SqlBuilder.isEqualToWhenPresent(filterMap.getInstitutionId())) + .and( + ConfigurationNodeRecordDynamicSqlSupport.name, + SqlBuilder.isLikeWhenPresent(filterMap.getName())) + .and( + ConfigurationNodeRecordDynamicSqlSupport.description, + SqlBuilder.isLikeWhenPresent(filterMap.getConfigNodeDesc())) + .and( + ConfigurationNodeRecordDynamicSqlSupport.type, + SqlBuilder.isEqualToWhenPresent(filterMap.getConfigNodeType())) + .and( + ConfigurationNodeRecordDynamicSqlSupport.templateId, + SqlBuilder.isEqualToWhenPresent(filterMap.getConfigNodeTemplateId())) + .build() + .execute() + .stream() + .map(ConfigurationNodeDAOImpl::toDomainModel) + .flatMap(DAOLoggingSupport::logAndSkipOnError) + .filter(predicate) + .collect(Collectors.toList()); + }); } @Override diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ExamDAOImpl.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ExamDAOImpl.java index fe65a4a7..0ed5636f 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ExamDAOImpl.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ExamDAOImpl.java @@ -15,6 +15,7 @@ import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Objects; @@ -27,6 +28,8 @@ import org.apache.commons.lang3.BooleanUtils; import org.apache.commons.lang3.StringUtils; import org.joda.time.DateTime; import org.mybatis.dynamic.sql.SqlBuilder; +import org.mybatis.dynamic.sql.select.MyBatis3SelectModelAdapter; +import org.mybatis.dynamic.sql.select.QueryExpressionDSL; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Component; import org.springframework.transaction.annotation.Propagation; @@ -51,6 +54,8 @@ import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.AdditionalAttribu import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.ClientConnectionRecordMapper; import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.ExamRecordDynamicSqlSupport; import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.ExamRecordMapper; +import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.InstitutionRecordDynamicSqlSupport; +import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.LmsSetupRecordDynamicSqlSupport; import ch.ethz.seb.sebserver.webservice.datalayer.batis.model.AdditionalAttributeRecord; import ch.ethz.seb.sebserver.webservice.datalayer.batis.model.ExamRecord; import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.impl.BulkAction; @@ -180,10 +185,35 @@ public class ExamDAOImpl implements ExamDAO { return true; }; - final List records = this.examRecordMapper.selectByExample() - .where( - ExamRecordDynamicSqlSupport.active, - isEqualToWhenPresent(filterMap.getActiveAsInt())) + // If we have a sort on institution name, join the institution table + // If we have a sort on lms setup name, join lms setup table + final QueryExpressionDSL>>.QueryExpressionWhereBuilder whereClause = + (filterMap.getBoolean(FilterMap.ATTR_ADD_INSITUTION_JOIN)) + ? this.examRecordMapper + .selectByExample() + .join(InstitutionRecordDynamicSqlSupport.institutionRecord) + .on( + InstitutionRecordDynamicSqlSupport.id, + SqlBuilder.equalTo(ExamRecordDynamicSqlSupport.institutionId)) + .where( + ExamRecordDynamicSqlSupport.active, + isEqualToWhenPresent(filterMap.getActiveAsInt())) + : (filterMap.getBoolean(FilterMap.ATTR_ADD_LMS_SETUP_JOIN)) + ? this.examRecordMapper + .selectByExample() + .join(LmsSetupRecordDynamicSqlSupport.lmsSetupRecord) + .on( + LmsSetupRecordDynamicSqlSupport.id, + SqlBuilder.equalTo(ExamRecordDynamicSqlSupport.lmsSetupId)) + .where( + ExamRecordDynamicSqlSupport.active, + isEqualToWhenPresent(filterMap.getActiveAsInt())) + : this.examRecordMapper.selectByExample() + .where( + ExamRecordDynamicSqlSupport.active, + isEqualToWhenPresent(filterMap.getActiveAsInt())); + + final List records = whereClause .and( ExamRecordDynamicSqlSupport.institutionId, isEqualToWhenPresent(filterMap.getInstitutionId())) @@ -750,7 +780,7 @@ public class ExamDAOImpl implements ExamDAO { final HashMap> lmsSetupToRecordMapping = records .stream() - .reduce(new HashMap<>(), + .reduce(new LinkedHashMap<>(), (map, record) -> Utils.mapCollect(map, record.getLmsSetupId(), record), Utils::mapPutAll); diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/LmsSetupDAOImpl.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/LmsSetupDAOImpl.java index 5710b6b4..c541751f 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/LmsSetupDAOImpl.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/LmsSetupDAOImpl.java @@ -20,6 +20,9 @@ import java.util.stream.Collectors; import org.apache.commons.lang3.BooleanUtils; import org.apache.commons.lang3.StringUtils; +import org.mybatis.dynamic.sql.SqlBuilder; +import org.mybatis.dynamic.sql.select.MyBatis3SelectModelAdapter; +import org.mybatis.dynamic.sql.select.QueryExpressionDSL; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Component; import org.springframework.transaction.annotation.Transactional; @@ -38,6 +41,7 @@ import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetup.LmsType; import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile; import ch.ethz.seb.sebserver.gbl.util.Result; import ch.ethz.seb.sebserver.gbl.util.Utils; +import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.InstitutionRecordDynamicSqlSupport; import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.LmsSetupRecordDynamicSqlSupport; import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.LmsSetupRecordMapper; import ch.ethz.seb.sebserver.webservice.datalayer.batis.model.LmsSetupRecord; @@ -108,27 +112,41 @@ public class LmsSetupDAOImpl implements LmsSetupDAO { final FilterMap filterMap, final Predicate predicate) { - return Result.tryCatch(() -> this.lmsSetupRecordMapper - .selectByExample() - .where( - LmsSetupRecordDynamicSqlSupport.institutionId, - isEqualToWhenPresent(filterMap.getInstitutionId())) - .and( - LmsSetupRecordDynamicSqlSupport.name, - isLikeWhenPresent(filterMap.getName())) - .and( - LmsSetupRecordDynamicSqlSupport.lmsType, - isEqualToWhenPresent(filterMap.getLmsSetupType())) - .and( - LmsSetupRecordDynamicSqlSupport.active, - isEqualToWhenPresent(filterMap.getActiveAsInt())) - .build() - .execute() - .stream() - .map(this::toDomainModel) - .flatMap(DAOLoggingSupport::logAndSkipOnError) - .filter(predicate) - .collect(Collectors.toList())); + return Result.tryCatch(() -> { + final QueryExpressionDSL>>.QueryExpressionWhereBuilder whereClause = + (filterMap.getBoolean(FilterMap.ATTR_ADD_INSITUTION_JOIN)) + ? this.lmsSetupRecordMapper + .selectByExample() + .join(InstitutionRecordDynamicSqlSupport.institutionRecord) + .on(InstitutionRecordDynamicSqlSupport.id, + SqlBuilder.equalTo(LmsSetupRecordDynamicSqlSupport.institutionId)) + .where( + LmsSetupRecordDynamicSqlSupport.institutionId, + isEqualToWhenPresent(filterMap.getInstitutionId())) + : this.lmsSetupRecordMapper + .selectByExample() + .where( + LmsSetupRecordDynamicSqlSupport.institutionId, + isEqualToWhenPresent(filterMap.getInstitutionId())); + + return whereClause + .and( + LmsSetupRecordDynamicSqlSupport.name, + isLikeWhenPresent(filterMap.getName())) + .and( + LmsSetupRecordDynamicSqlSupport.lmsType, + isEqualToWhenPresent(filterMap.getLmsSetupType())) + .and( + LmsSetupRecordDynamicSqlSupport.active, + isEqualToWhenPresent(filterMap.getActiveAsInt())) + .build() + .execute() + .stream() + .map(this::toDomainModel) + .flatMap(DAOLoggingSupport::logAndSkipOnError) + .filter(predicate) + .collect(Collectors.toList()); + }); } @Override diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/UserActivityLogDAOImpl.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/UserActivityLogDAOImpl.java index 461b4f2f..49dded2a 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/UserActivityLogDAOImpl.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/UserActivityLogDAOImpl.java @@ -22,6 +22,8 @@ import java.util.stream.Collectors; import org.apache.commons.lang3.StringUtils; import org.mybatis.dynamic.sql.SqlBuilder; +import org.mybatis.dynamic.sql.select.MyBatis3SelectModelAdapter; +import org.mybatis.dynamic.sql.select.QueryExpressionDSL; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.context.annotation.Lazy; @@ -42,6 +44,7 @@ import ch.ethz.seb.sebserver.gbl.model.user.UserInfo; import ch.ethz.seb.sebserver.gbl.model.user.UserLogActivityType; 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.InstitutionRecordDynamicSqlSupport; import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.UserActivityLogRecordDynamicSqlSupport; import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.UserActivityLogRecordMapper; import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.UserRecordDynamicSqlSupport; @@ -310,11 +313,10 @@ public class UserActivityLogDAOImpl implements UserActivityLogDAO { filterMap.getUserLofTo(), filterMap.getString(UserActivityLog.FILTER_ATTR_ACTIVITY_TYPES), filterMap.getString(UserActivityLog.FILTER_ATTR_ENTITY_TYPES), + filterMap.getBoolean(FilterMap.ATTR_ADD_INSITUTION_JOIN), predicate); } - @Override - @Transactional(readOnly = true) public Result> all( final Long institutionId, final String userName, @@ -322,6 +324,7 @@ public class UserActivityLogDAOImpl implements UserActivityLogDAO { final Long to, final String activityTypes, final String entityTypes, + final boolean joinInstitution, final Predicate predicate) { return Result.tryCatch(() -> { @@ -332,15 +335,32 @@ public class UserActivityLogDAOImpl implements UserActivityLogDAO { ? Arrays.asList(StringUtils.split(entityTypes, Constants.LIST_SEPARATOR)) : null; - final List records = this.userLogRecordMapper - .selectByExample() - .leftJoin(UserRecordDynamicSqlSupport.userRecord) - .on( - UserRecordDynamicSqlSupport.uuid, - SqlBuilder.equalTo(UserActivityLogRecordDynamicSqlSupport.userUuid)) - .where( - UserRecordDynamicSqlSupport.institutionId, - SqlBuilder.isEqualToWhenPresent(institutionId)) + final QueryExpressionDSL>>.QueryExpressionWhereBuilder whereClause = + joinInstitution + ? this.userLogRecordMapper + .selectByExample() + .leftJoin(UserRecordDynamicSqlSupport.userRecord) + .on( + UserRecordDynamicSqlSupport.uuid, + SqlBuilder.equalTo(UserActivityLogRecordDynamicSqlSupport.userUuid)) + .join(InstitutionRecordDynamicSqlSupport.institutionRecord) + .on(InstitutionRecordDynamicSqlSupport.id, + SqlBuilder.equalTo(UserRecordDynamicSqlSupport.institutionId)) + .where( + UserRecordDynamicSqlSupport.institutionId, + SqlBuilder.isEqualToWhenPresent(institutionId)) + + : this.userLogRecordMapper + .selectByExample() + .leftJoin(UserRecordDynamicSqlSupport.userRecord) + .on( + UserRecordDynamicSqlSupport.uuid, + SqlBuilder.equalTo(UserActivityLogRecordDynamicSqlSupport.userUuid)) + .where( + UserRecordDynamicSqlSupport.institutionId, + SqlBuilder.isEqualToWhenPresent(institutionId)); + + final List records = whereClause .and( UserRecordDynamicSqlSupport.username, SqlBuilder.isLikeWhenPresent(userName)) diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/UserDAOImpl.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/UserDAOImpl.java index 40bef45a..8d1a6ba3 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/UserDAOImpl.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/UserDAOImpl.java @@ -27,6 +27,9 @@ import org.apache.commons.lang3.BooleanUtils; import org.apache.commons.lang3.StringUtils; import org.joda.time.DateTime; import org.joda.time.DateTimeZone; +import org.mybatis.dynamic.sql.SqlBuilder; +import org.mybatis.dynamic.sql.select.MyBatis3SelectModelAdapter; +import org.mybatis.dynamic.sql.select.QueryExpressionDSL; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Qualifier; @@ -162,11 +165,22 @@ public class UserDAOImpl implements UserDAO { ? predicate.and(ui -> ui.roles.contains(userRole)) : predicate; - return this.userRecordMapper - .selectByExample() - .where( - UserRecordDynamicSqlSupport.active, - isEqualToWhenPresent(filterMap.getActiveAsInt())) + final QueryExpressionDSL>>.QueryExpressionWhereBuilder sqlWhereClause = + (filterMap.getBoolean(FilterMap.ATTR_ADD_INSITUTION_JOIN)) + ? this.userRecordMapper + .selectByExample() + .join(InstitutionRecordDynamicSqlSupport.institutionRecord) + .on(InstitutionRecordDynamicSqlSupport.id, + SqlBuilder.equalTo(UserRecordDynamicSqlSupport.institutionId)) + .where( + UserRecordDynamicSqlSupport.active, + isEqualToWhenPresent(filterMap.getActiveAsInt())) + : this.userRecordMapper + .selectByExample() + .where( + UserRecordDynamicSqlSupport.active, + isEqualToWhenPresent(filterMap.getActiveAsInt())); + return sqlWhereClause .and( UserRecordDynamicSqlSupport.institutionId, isEqualToWhenPresent(filterMap.getInstitutionId())) diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ClientEventController.java b/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ClientEventController.java index 9ff17dd4..349c42eb 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ClientEventController.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ClientEventController.java @@ -103,12 +103,7 @@ public class ClientEventController extends ReadonlyEntityController { checkReadPrivilege(institutionId); final FilterMap filterMap = new FilterMap(allRequestParams, request.getQueryString()); - - // if current user has no read access for specified entity type within other institution - // then the current users institutionId is put as a SQL filter criteria attribute to extends query performance - if (!this.authorization.hasGrant(PrivilegeType.READ, getGrantEntityType())) { - filterMap.putIfAbsent(API.PARAM_INSTITUTION_ID, String.valueOf(institutionId)); - } + populateFilterMap(filterMap, institutionId, sort); return this.paginationService.getPage( pageNumber, @@ -164,6 +159,19 @@ public abstract class EntityController { .getOrThrow(); } + protected void populateFilterMap(final FilterMap filterMap, final Long institutionId, final String sort) { + // If current user has no read access for specified entity type within other institution + // then the current users institutionId is put as a SQL filter criteria attribute to extends query performance + if (!this.authorization.hasGrant(PrivilegeType.READ, getGrantEntityType())) { + filterMap.putIfAbsent(API.PARAM_INSTITUTION_ID, String.valueOf(institutionId)); + } + + // If sorting is on institution name we need to join the institution table + if (sort != null && sort.contains(Entity.FILTER_ATTR_INSTITUTION)) { + filterMap.putIfAbsent(FilterMap.ATTR_ADD_INSITUTION_JOIN, Constants.TRUE_STRING); + } + } + // ****************** // * GET (names) // ****************** diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ExamAdministrationController.java b/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ExamAdministrationController.java index f9ff8024..0db2eda3 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ExamAdministrationController.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ExamAdministrationController.java @@ -37,6 +37,7 @@ 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.Constants; import ch.ethz.seb.sebserver.gbl.api.API; import ch.ethz.seb.sebserver.gbl.api.APIMessage; import ch.ethz.seb.sebserver.gbl.api.APIMessage.APIMessageException; @@ -480,6 +481,16 @@ public class ExamAdministrationController extends EntityController { .map(this::checkExamSupporterRole); } + @Override + protected void populateFilterMap(final FilterMap filterMap, final Long institutionId, final String sort) { + super.populateFilterMap(filterMap, institutionId, sort); + + // If sorting is on lms setup name we need to join the lms setup table + if (sort != null && sort.contains(Domain.EXAM.ATTR_LMS_SETUP_ID)) { + filterMap.putIfAbsent(FilterMap.ATTR_ADD_LMS_SETUP_JOIN, Constants.TRUE_STRING); + } + } + private Exam checkExamSupporterRole(final Exam exam) { final Set examSupporter = this.userDAO.all( this.authorization.getUserService().getCurrentUser().getUserInfo().institutionId, @@ -555,7 +566,7 @@ public class ExamAdministrationController extends EntityController { return list; } - if (sortBy.equals(Exam.FILTER_ATTR_NAME)) { + if (sortBy.equals(Exam.FILTER_ATTR_NAME) || sortBy.equals(QuizData.QUIZ_ATTR_NAME)) { list.sort(Comparator.comparing(exam -> exam.name)); } if (sortBy.equals(Exam.FILTER_ATTR_TYPE)) {