SEBSERV-108 addes sort and default sort for all except lms lookup

This commit is contained in:
anhefti 2021-05-07 12:13:13 +02:00
parent c222f4216e
commit 8be642c31c
26 changed files with 348 additions and 151 deletions

View file

@ -112,6 +112,7 @@ public class CertificateList implements TemplateComposer {
.withMultiSelection() .withMultiSelection()
.withEmptyMessage(EMPTY_LIST_TEXT_KEY) .withEmptyMessage(EMPTY_LIST_TEXT_KEY)
.withPaging(this.pageSize) .withPaging(this.pageSize)
.withDefaultSort(CertificateInfo.ATTR_ALIAS)
.withColumn(new ColumnDefinition<>( .withColumn(new ColumnDefinition<>(
CertificateInfo.ATTR_ALIAS, CertificateInfo.ATTR_ALIAS,

View file

@ -106,6 +106,9 @@ public class ConfigTemplateList implements TemplateComposer {
ConfigurationType.TEMPLATE.name()) ConfigurationType.TEMPLATE.name())
.withEmptyMessage(EMPTY_TEMPLATE_LIST_TEXT_KEY) .withEmptyMessage(EMPTY_TEMPLATE_LIST_TEXT_KEY)
.withPaging(this.pageSize) .withPaging(this.pageSize)
.withDefaultSort(isSEBAdmin
? Domain.LMS_SETUP.ATTR_INSTITUTION_ID
: Domain.CONFIGURATION_NODE.ATTR_NAME)
.withColumnIf( .withColumnIf(
() -> isSEBAdmin, () -> isSEBAdmin,
() -> new ColumnDefinition<>( () -> new ColumnDefinition<>(

View file

@ -145,8 +145,10 @@ public class ExamList implements TemplateComposer {
.withEmptyMessage(EMPTY_LIST_TEXT_KEY) .withEmptyMessage(EMPTY_LIST_TEXT_KEY)
.withPaging(this.pageSize) .withPaging(this.pageSize)
.withRowDecorator(decorateOnExamConsistency(this.pageService)) .withRowDecorator(decorateOnExamConsistency(this.pageService))
.withStaticFilter(Exam.FILTER_ATTR_ACTIVE, Constants.TRUE_STRING) .withStaticFilter(Exam.FILTER_ATTR_ACTIVE, Constants.TRUE_STRING)
.withDefaultSort(isSEBAdmin.getAsBoolean()
? Domain.EXAM.ATTR_INSTITUTION_ID
: Domain.EXAM.ATTR_LMS_SETUP_ID)
.withColumnIf( .withColumnIf(
isSEBAdmin, isSEBAdmin,
@ -155,7 +157,8 @@ public class ExamList implements TemplateComposer {
COLUMN_TITLE_INSTITUTION_KEY, COLUMN_TITLE_INSTITUTION_KEY,
exam -> institutionNameFunction exam -> institutionNameFunction
.apply(String.valueOf(exam.getInstitutionId()))) .apply(String.valueOf(exam.getInstitutionId())))
.withFilter(this.institutionFilter)) .withFilter(this.institutionFilter)
.sortable())
.withColumn(new ColumnDefinition<>( .withColumn(new ColumnDefinition<>(
Domain.EXAM.ATTR_LMS_SETUP_ID, Domain.EXAM.ATTR_LMS_SETUP_ID,

View file

@ -96,6 +96,7 @@ public class InstitutionList implements TemplateComposer {
this.pageService.entityTableBuilder(this.restService.getRestCall(GetInstitutionPage.class)) this.pageService.entityTableBuilder(this.restService.getRestCall(GetInstitutionPage.class))
.withEmptyMessage(EMPTY_LIST_TEXT_KEY) .withEmptyMessage(EMPTY_LIST_TEXT_KEY)
.withPaging(this.pageSize) .withPaging(this.pageSize)
.withDefaultSort(Domain.INSTITUTION.ATTR_NAME)
.withColumn(new ColumnDefinition<>( .withColumn(new ColumnDefinition<>(
Domain.INSTITUTION.ATTR_NAME, Domain.INSTITUTION.ATTR_NAME,
NAME_TEXT_KEY, NAME_TEXT_KEY,

View file

@ -116,13 +116,15 @@ public class LmsSetupList implements TemplateComposer {
this.pageService.entityTableBuilder(restService.getRestCall(GetLmsSetupPage.class)) this.pageService.entityTableBuilder(restService.getRestCall(GetLmsSetupPage.class))
.withEmptyMessage(EMPTY_LIST_TEXT_KEY) .withEmptyMessage(EMPTY_LIST_TEXT_KEY)
.withPaging(this.pageSize) .withPaging(this.pageSize)
.withDefaultSort(isSEBAdmin ? Domain.LMS_SETUP.ATTR_INSTITUTION_ID : Domain.LMS_SETUP.ATTR_NAME)
.withColumnIf( .withColumnIf(
() -> isSEBAdmin, () -> isSEBAdmin,
() -> new ColumnDefinition<>( () -> new ColumnDefinition<>(
Domain.LMS_SETUP.ATTR_INSTITUTION_ID, Domain.LMS_SETUP.ATTR_INSTITUTION_ID,
INSTITUTION_TEXT_KEY, INSTITUTION_TEXT_KEY,
lmsSetupInstitutionNameFunction(this.resourceService)) lmsSetupInstitutionNameFunction(this.resourceService))
.withFilter(this.institutionFilter)) .withFilter(this.institutionFilter)
.sortable())
.withColumn(new ColumnDefinition<>( .withColumn(new ColumnDefinition<>(
Domain.LMS_SETUP.ATTR_NAME, Domain.LMS_SETUP.ATTR_NAME,
NAME_TEXT_KEY, NAME_TEXT_KEY,

View file

@ -95,6 +95,7 @@ public class MonitoringRunningExamList implements TemplateComposer {
.withEmptyMessage(EMPTY_LIST_TEXT_KEY) .withEmptyMessage(EMPTY_LIST_TEXT_KEY)
.withPaging(this.pageSize) .withPaging(this.pageSize)
.withRowDecorator(ExamList.decorateOnExamConsistency(this.pageService)) .withRowDecorator(ExamList.decorateOnExamConsistency(this.pageService))
.withDefaultSort(QuizData.QUIZ_ATTR_NAME)
.withColumn(new ColumnDefinition<>( .withColumn(new ColumnDefinition<>(
QuizData.QUIZ_ATTR_NAME, QuizData.QUIZ_ATTR_NAME,

View file

@ -119,13 +119,17 @@ public class SEBClientConfigList implements TemplateComposer {
this.pageService.entityTableBuilder(this.restService.getRestCall(GetClientConfigPage.class)) this.pageService.entityTableBuilder(this.restService.getRestCall(GetClientConfigPage.class))
.withEmptyMessage(EMPTY_LIST_TEXT_KEY) .withEmptyMessage(EMPTY_LIST_TEXT_KEY)
.withPaging(this.pageSize) .withPaging(this.pageSize)
.withDefaultSort(isSEBAdmin
? Domain.LMS_SETUP.ATTR_INSTITUTION_ID
: Domain.SEB_CLIENT_CONFIGURATION.ATTR_NAME)
.withColumnIf( .withColumnIf(
() -> isSEBAdmin, () -> isSEBAdmin,
() -> new ColumnDefinition<>( () -> new ColumnDefinition<>(
Domain.LMS_SETUP.ATTR_INSTITUTION_ID, Domain.LMS_SETUP.ATTR_INSTITUTION_ID,
INSTITUTION_TEXT_KEY, INSTITUTION_TEXT_KEY,
clientConfigInstitutionNameFunction(this.resourceService)) clientConfigInstitutionNameFunction(this.resourceService))
.withFilter(this.institutionFilter)) .withFilter(this.institutionFilter)
.sortable())
.withColumn(new ColumnDefinition<>( .withColumn(new ColumnDefinition<>(
Domain.SEB_CLIENT_CONFIGURATION.ATTR_NAME, Domain.SEB_CLIENT_CONFIGURATION.ATTR_NAME,
NAME_TEXT_KEY, NAME_TEXT_KEY,

View file

@ -149,6 +149,7 @@ public class SEBClientEvents implements TemplateComposer {
this.restService.getRestCall(GetExtendedClientEventPage.class)) this.restService.getRestCall(GetExtendedClientEventPage.class))
.withEmptyMessage(EMPTY_TEXT_KEY) .withEmptyMessage(EMPTY_TEXT_KEY)
.withPaging(this.pageSize) .withPaging(this.pageSize)
.withDefaultSort(Domain.CLIENT_CONNECTION.ATTR_EXAM_USER_SESSION_ID)
.withColumn(new ColumnDefinition<>( .withColumn(new ColumnDefinition<>(
Domain.CLIENT_CONNECTION.ATTR_EXAM_ID, Domain.CLIENT_CONNECTION.ATTR_EXAM_ID,

View file

@ -113,6 +113,9 @@ public class SEBExamConfigList implements TemplateComposer {
ConfigurationType.EXAM_CONFIG.name()) ConfigurationType.EXAM_CONFIG.name())
.withEmptyMessage(EMPTY_CONFIG_LIST_TEXT_KEY) .withEmptyMessage(EMPTY_CONFIG_LIST_TEXT_KEY)
.withPaging(this.pageSize) .withPaging(this.pageSize)
.withDefaultSort(isSEBAdmin
? Domain.LMS_SETUP.ATTR_INSTITUTION_ID
: Domain.CONFIGURATION_NODE.ATTR_NAME)
.withColumnIf( .withColumnIf(
() -> isSEBAdmin, () -> isSEBAdmin,
() -> new ColumnDefinition<>( () -> new ColumnDefinition<>(

View file

@ -138,7 +138,7 @@ public class UserAccountList implements TemplateComposer {
restService.getRestCall(GetUserAccountPage.class)) restService.getRestCall(GetUserAccountPage.class))
.withEmptyMessage(EMPTY_TEXT_KEY) .withEmptyMessage(EMPTY_TEXT_KEY)
.withPaging(this.pageSize) .withPaging(this.pageSize)
.withDefaultSort(isSEBAdmin.getAsBoolean() ? Domain.USER.ATTR_INSTITUTION_ID : Domain.USER.ATTR_NAME)
.withColumnIf( .withColumnIf(
isSEBAdmin, isSEBAdmin,
() -> new ColumnDefinition<>( () -> new ColumnDefinition<>(
@ -146,7 +146,8 @@ public class UserAccountList implements TemplateComposer {
INSTITUTION_TEXT_KEY, INSTITUTION_TEXT_KEY,
userInstitutionNameFunction(this.resourceService)) userInstitutionNameFunction(this.resourceService))
.withFilter(this.institutionFilter) .withFilter(this.institutionFilter)
.widthProportion(2)) .widthProportion(2)
.sortable())
.withColumn(new ColumnDefinition<>( .withColumn(new ColumnDefinition<>(
Domain.USER.ATTR_NAME, Domain.USER.ATTR_NAME,

View file

@ -183,14 +183,17 @@ public class UserActivityLogs implements TemplateComposer {
restService.getRestCall(GetUserLogPage.class)) restService.getRestCall(GetUserLogPage.class))
.withEmptyMessage(EMPTY_TEXT_KEY) .withEmptyMessage(EMPTY_TEXT_KEY)
.withPaging(this.pageSize) .withPaging(this.pageSize)
.withDefaultSort(isSEBAdmin.getAsBoolean()
? UserActivityLog.FILTER_ATTR_INSTITUTION
: UserActivityLog.ATTR_USER_NAME)
.withColumnIf( .withColumnIf(
isSEBAdmin, isSEBAdmin,
() -> new ColumnDefinition<>( () -> new ColumnDefinition<>(
UserActivityLog.FILTER_ATTR_INSTITUTION, UserActivityLog.FILTER_ATTR_INSTITUTION,
INSTITUTION_TEXT_KEY, INSTITUTION_TEXT_KEY,
institutionNameFunction) institutionNameFunction)
.withFilter(this.institutionFilter)) .withFilter(this.institutionFilter)
.sortable())
.withColumn(new ColumnDefinition<>( .withColumn(new ColumnDefinition<>(
UserActivityLog.ATTR_USER_NAME, UserActivityLog.ATTR_USER_NAME,

View file

@ -97,6 +97,9 @@ public class EntityTable<ROW> {
private final Consumer<Set<ROW>> selectionListener; private final Consumer<Set<ROW>> selectionListener;
private final Consumer<Integer> contentChangeListener; private final Consumer<Integer> contentChangeListener;
private final String defaultSortColumn;
private final PageSortOrder defaultSortOrder;
int pageNumber; int pageNumber;
int pageSize; int pageSize;
String sortColumn = null; String sortColumn = null;
@ -120,7 +123,9 @@ public class EntityTable<ROW> {
final MultiValueMap<String, String> staticQueryParams, final MultiValueMap<String, String> staticQueryParams,
final BiConsumer<TableItem, ROW> rowDecorator, final BiConsumer<TableItem, ROW> rowDecorator,
final Consumer<Set<ROW>> selectionListener, final Consumer<Set<ROW>> selectionListener,
final Consumer<Integer> contentChangeListener) { final Consumer<Integer> contentChangeListener,
final String defaultSortColumn,
final PageSortOrder defaultSortOrder) {
this.name = name; this.name = name;
this.filterAttrName = name + "_filter"; this.filterAttrName = name + "_filter";
@ -129,6 +134,9 @@ public class EntityTable<ROW> {
this.currentPageAttrName = name + "_currentPage"; this.currentPageAttrName = name + "_currentPage";
this.markupEnabled = markupEnabled; this.markupEnabled = markupEnabled;
this.defaultSortColumn = defaultSortColumn;
this.defaultSortOrder = defaultSortOrder;
this.composite = new Composite(pageContext.getParent(), SWT.NONE); this.composite = new Composite(pageContext.getParent(), SWT.NONE);
this.pageService = pageService; this.pageService = pageService;
this.i18nSupport = pageService.getI18nSupport(); this.i18nSupport = pageService.getI18nSupport();
@ -281,9 +289,10 @@ public class EntityTable<ROW> {
} }
public void reset() { public void reset() {
this.applySort(null); this.sortColumn = this.defaultSortColumn;
this.table.setSortColumn(null); this.sortOrder = this.defaultSortOrder;
this.table.setSortDirection(SWT.NONE); updateSortUserAttr();
setTableSort();
applyFilter(); applyFilter();
} }
@ -306,10 +315,10 @@ public class EntityTable<ROW> {
return this.filter.getFilterParameter(); return this.filter.getFilterParameter();
} }
public void applySort(final String columnName) { public void applySort(final String columnName, final PageSortOrder order) {
try { try {
this.sortColumn = columnName; this.sortColumn = columnName;
this.sortOrder = PageSortOrder.ASCENDING; this.sortOrder = order;
if (columnName != null) { if (columnName != null) {
updateTableRows( updateTableRows(
@ -455,7 +464,7 @@ public class EntityTable<ROW> {
if (column.isSortable()) { if (column.isSortable()) {
tableColumn.addListener(SWT.Selection, event -> { tableColumn.addListener(SWT.Selection, event -> {
if (!column.columnName.equals(this.sortColumn)) { if (!column.columnName.equals(this.sortColumn)) {
applySort(column.columnName); applySort(column.columnName, PageSortOrder.ASCENDING);
this.table.setSortColumn(tableColumn); this.table.setSortColumn(tableColumn);
this.table.setSortDirection(SWT.UP); this.table.setSortDirection(SWT.UP);
} else { } else {
@ -713,10 +722,8 @@ public class EntityTable<ROW> {
.getAttribute(this.sortAttrName); .getAttribute(this.sortAttrName);
if (StringUtils.isNotBlank(sort)) { if (StringUtils.isNotBlank(sort)) {
this.sortColumn = sort; this.sortColumn = sort;
final TableColumn tableColumn = getTableColumn(sort); } else {
if (tableColumn != null) { this.sortColumn = this.defaultSortColumn;
this.table.setSortColumn(tableColumn);
}
} }
final String sortOrder = this.pageService final String sortOrder = this.pageService
@ -724,14 +731,30 @@ public class EntityTable<ROW> {
.getAttribute(this.sortOrderAttrName); .getAttribute(this.sortOrderAttrName);
if (StringUtils.isNotBlank(sortOrder)) { if (StringUtils.isNotBlank(sortOrder)) {
this.sortOrder = PageSortOrder.valueOf(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) { } catch (final Exception e) {
log.error("Failed to get sort attribute form current user attributes", 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() { private void updateFilterUserAttrs() {
if (this.filter != null) { if (this.filter != null) {
try { try {

View file

@ -24,6 +24,7 @@ import org.springframework.util.MultiValueMap;
import ch.ethz.seb.sebserver.gbl.api.EntityType; import ch.ethz.seb.sebserver.gbl.api.EntityType;
import ch.ethz.seb.sebserver.gbl.model.Page; 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.i18n.LocTextKey;
import ch.ethz.seb.sebserver.gui.service.page.PageContext; import ch.ethz.seb.sebserver.gui.service.page.PageContext;
import ch.ethz.seb.sebserver.gui.service.page.PageService; import ch.ethz.seb.sebserver.gui.service.page.PageService;
@ -49,6 +50,8 @@ public class TableBuilder<ROW> {
private Consumer<Set<ROW>> selectionListener; private Consumer<Set<ROW>> selectionListener;
private Consumer<Integer> contentChangeListener; private Consumer<Integer> contentChangeListener;
private boolean markupEnabled = false; private boolean markupEnabled = false;
private String defaultSortColumn = null;
private PageSortOrder defaultSortOrder = PageSortOrder.ASCENDING;
public TableBuilder( public TableBuilder(
final String name, final String name,
@ -106,6 +109,16 @@ public class TableBuilder<ROW> {
return this; return this;
} }
public TableBuilder<ROW> withDefaultSort(final String defaultSortColumn) {
this.defaultSortColumn = defaultSortColumn;
return this;
}
public TableBuilder<ROW> withDefaultSortOrder(final PageSortOrder defaultSortOrder) {
this.defaultSortOrder = defaultSortOrder;
return this;
}
public TableBuilder<ROW> withColumn(final ColumnDefinition<ROW> columnDefinition) { public TableBuilder<ROW> withColumn(final ColumnDefinition<ROW> columnDefinition) {
this.columns.add(columnDefinition); this.columns.add(columnDefinition);
return this; return this;
@ -209,7 +222,9 @@ public class TableBuilder<ROW> {
this.staticQueryParams, this.staticQueryParams,
this.rowDecorator, this.rowDecorator,
this.selectionListener, this.selectionListener,
this.contentChangeListener); this.contentChangeListener,
this.defaultSortColumn,
this.defaultSortOrder);
} }
} }

View file

@ -101,9 +101,10 @@ public interface PaginationService {
if (sorted.size() < end) { if (sorted.size() < end) {
end = sorted.size(); end = sorted.size();
} }
final int numberOfPages = sorted.size() / _pageSize;
return new Page<>( return new Page<>(
sorted.size() / _pageSize, (numberOfPages > 0) ? numberOfPages : 1,
_pageNumber, _pageNumber,
sort, sort,
sorted.subList(start, end)); sorted.subList(start, end));

View file

@ -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.Entity;
import ch.ethz.seb.sebserver.gbl.model.Page; import ch.ethz.seb.sebserver.gbl.model.Page;
import ch.ethz.seb.sebserver.gbl.model.PageSortOrder; 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.profile.WebServiceProfile;
import ch.ethz.seb.sebserver.gbl.util.Result; 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.ClientEventRecordDynamicSqlSupport;
import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.ConfigurationNodeRecordDynamicSqlSupport; import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.ConfigurationNodeRecordDynamicSqlSupport;
import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.ExamRecordDynamicSqlSupport; import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.ExamRecordDynamicSqlSupport;
@ -75,7 +77,7 @@ public class PaginationServiceImpl implements PaginationService {
return false; 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 /** 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() { 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... // define and initialize sort column mapping for...
// Institution Table // Institution Table
@ -216,6 +223,7 @@ public class PaginationServiceImpl implements PaginationService {
// User Table // User Table
final Map<String, String> userTableMap = new HashMap<>(); final Map<String, String> 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_NAME, UserRecordDynamicSqlSupport.name.name());
userTableMap.put(Domain.USER.ATTR_SURNAME, UserRecordDynamicSqlSupport.surname.name()); userTableMap.put(Domain.USER.ATTR_SURNAME, UserRecordDynamicSqlSupport.surname.name());
userTableMap.put(Domain.USER.ATTR_USERNAME, UserRecordDynamicSqlSupport.username.name()); userTableMap.put(Domain.USER.ATTR_USERNAME, UserRecordDynamicSqlSupport.username.name());
@ -226,6 +234,7 @@ public class PaginationServiceImpl implements PaginationService {
// LMS Setup Table // LMS Setup Table
final Map<String, String> lmsSetupTableMap = new HashMap<>(); final Map<String, String> 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_NAME, LmsSetupRecordDynamicSqlSupport.name.name());
lmsSetupTableMap.put(Domain.LMS_SETUP.ATTR_LMS_TYPE, LmsSetupRecordDynamicSqlSupport.lmsType.name()); lmsSetupTableMap.put(Domain.LMS_SETUP.ATTR_LMS_TYPE, LmsSetupRecordDynamicSqlSupport.lmsType.name());
this.sortColumnMapping.put(LmsSetupRecordDynamicSqlSupport.lmsSetupRecord.name(), lmsSetupTableMap); this.sortColumnMapping.put(LmsSetupRecordDynamicSqlSupport.lmsSetupRecord.name(), lmsSetupTableMap);
@ -233,18 +242,15 @@ public class PaginationServiceImpl implements PaginationService {
// Exam Table // Exam Table
final Map<String, String> examTableMap = new HashMap<>(); final Map<String, String> examTableMap = new HashMap<>();
examTableMap.put( examTableMap.put(Entity.FILTER_ATTR_INSTITUTION, institutionNameRef);
Domain.EXAM.ATTR_TYPE, examTableMap.put(Domain.EXAM.ATTR_LMS_SETUP_ID, lmsSetupNameRef);
ExamRecordDynamicSqlSupport.type.name()); examTableMap.put(Domain.EXAM.ATTR_TYPE, ExamRecordDynamicSqlSupport.type.name());
this.sortColumnMapping.put( this.sortColumnMapping.put(ExamRecordDynamicSqlSupport.examRecord.name(), examTableMap);
ExamRecordDynamicSqlSupport.examRecord.name(), this.defaultSortColumn.put(ExamRecordDynamicSqlSupport.examRecord.name(), Domain.EXAM.ATTR_ID);
examTableMap);
this.defaultSortColumn.put(
ExamRecordDynamicSqlSupport.examRecord.name(),
Domain.EXAM.ATTR_ID);
// SEB Client Configuration Table // SEB Client Configuration Table
final Map<String, String> sebClientConfigTableMap = new HashMap<>(); final Map<String, String> sebClientConfigTableMap = new HashMap<>();
lmsSetupTableMap.put(Domain.SEB_CLIENT_CONFIGURATION.ATTR_INSTITUTION_ID, institutionNameRef);
sebClientConfigTableMap.put( sebClientConfigTableMap.put(
Domain.SEB_CLIENT_CONFIGURATION.ATTR_INSTITUTION_ID, Domain.SEB_CLIENT_CONFIGURATION.ATTR_INSTITUTION_ID,
SebClientConfigRecordDynamicSqlSupport.institutionId.name()); SebClientConfigRecordDynamicSqlSupport.institutionId.name());
@ -265,7 +271,7 @@ public class PaginationServiceImpl implements PaginationService {
final Map<String, String> configurationNodeTableMap = new HashMap<>(); final Map<String, String> configurationNodeTableMap = new HashMap<>();
configurationNodeTableMap.put( configurationNodeTableMap.put(
Domain.CONFIGURATION_NODE.ATTR_INSTITUTION_ID, Domain.CONFIGURATION_NODE.ATTR_INSTITUTION_ID,
ConfigurationNodeRecordDynamicSqlSupport.institutionId.name()); institutionNameRef);
configurationNodeTableMap.put( configurationNodeTableMap.put(
Domain.CONFIGURATION_NODE.ATTR_NAME, Domain.CONFIGURATION_NODE.ATTR_NAME,
ConfigurationNodeRecordDynamicSqlSupport.name.name()); ConfigurationNodeRecordDynamicSqlSupport.name.name());
@ -284,6 +290,9 @@ public class PaginationServiceImpl implements PaginationService {
// ClientEvent table // ClientEvent table
final Map<String, String> clientEventTableMap = new HashMap<>(); final Map<String, String> clientEventTableMap = new HashMap<>();
clientEventTableMap.put(
Domain.CLIENT_CONNECTION.ATTR_EXAM_USER_SESSION_ID,
clientConnectionNameRef);
clientEventTableMap.put( clientEventTableMap.put(
Domain.CLIENT_EVENT.ATTR_TYPE, Domain.CLIENT_EVENT.ATTR_TYPE,
ClientEventRecordDynamicSqlSupport.type.name()); ClientEventRecordDynamicSqlSupport.type.name());
@ -296,6 +305,9 @@ public class PaginationServiceImpl implements PaginationService {
clientEventTableMap.put( clientEventTableMap.put(
Domain.CLIENT_EVENT.ATTR_TEXT, Domain.CLIENT_EVENT.ATTR_TEXT,
ClientEventRecordDynamicSqlSupport.text.name()); ClientEventRecordDynamicSqlSupport.text.name());
clientEventTableMap.put(
Domain.CLIENT_EVENT.ATTR_NUMERIC_VALUE,
ClientEventRecordDynamicSqlSupport.numericValue.name());
this.sortColumnMapping.put( this.sortColumnMapping.put(
ClientEventRecordDynamicSqlSupport.clientEventRecord.name(), ClientEventRecordDynamicSqlSupport.clientEventRecord.name(),
clientEventTableMap); clientEventTableMap);
@ -305,6 +317,9 @@ public class PaginationServiceImpl implements PaginationService {
// User Activity Log Table // User Activity Log Table
final Map<String, String> userActivityLogTableMap = new HashMap<>(); final Map<String, String> userActivityLogTableMap = new HashMap<>();
userActivityLogTableMap.put(
UserActivityLog.FILTER_ATTR_INSTITUTION,
institutionNameRef);
userActivityLogTableMap.put( userActivityLogTableMap.put(
Domain.USER.ATTR_USERNAME, Domain.USER.ATTR_USERNAME,
UserRecordDynamicSqlSupport.username.name()); UserRecordDynamicSqlSupport.username.name());

View file

@ -45,6 +45,9 @@ import ch.ethz.seb.sebserver.gbl.util.Utils;
* All text based filter criteria are used as SQL wildcard's */ * All text based filter criteria are used as SQL wildcard's */
public class FilterMap extends POSTMapper { 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() { public FilterMap() {
super(new LinkedMultiValueMap<>(), null); super(new LinkedMultiValueMap<>(), null);
} }

View file

@ -8,9 +8,6 @@
package ch.ethz.seb.sebserver.webservice.servicelayer.dao; 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.api.EntityType;
import ch.ethz.seb.sebserver.gbl.model.Entity; import ch.ethz.seb.sebserver.gbl.model.Entity;
import ch.ethz.seb.sebserver.gbl.model.user.UserAccount; import ch.ethz.seb.sebserver.gbl.model.user.UserAccount;
@ -136,13 +133,4 @@ public interface UserActivityLogDAO extends
return log(user, activityType, entity, null); return log(user, activityType, entity, null);
} }
Result<Collection<UserActivityLog>> all(
Long InstitutionId,
String userId,
Long from,
Long to,
String activityTypes,
String entityTypes,
Predicate<UserActivityLog> predicate);
} }

View file

@ -21,6 +21,8 @@ import java.util.stream.Collectors;
import org.apache.commons.lang3.BooleanUtils; import org.apache.commons.lang3.BooleanUtils;
import org.mybatis.dynamic.sql.SqlBuilder; 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.context.annotation.Lazy;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional; 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.ClientInstructionRecordDynamicSqlSupport;
import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.ClientInstructionRecordMapper; 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.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.mapper.RemoteProctoringRoomRecordDynamicSqlSupport;
import ch.ethz.seb.sebserver.webservice.datalayer.batis.model.ClientConnectionRecord; import ch.ethz.seb.sebserver.webservice.datalayer.batis.model.ClientConnectionRecord;
import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.impl.BulkAction; import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.impl.BulkAction;
@ -88,11 +91,24 @@ public class ClientConnectionDAOImpl implements ClientConnectionDAO {
final FilterMap filterMap, final FilterMap filterMap,
final Predicate<ClientConnection> predicate) { final Predicate<ClientConnection> predicate) {
return Result.tryCatch(() -> this.clientConnectionRecordMapper return Result.tryCatch(() -> {
final QueryExpressionDSL<MyBatis3SelectModelAdapter<List<ClientConnectionRecord>>>.QueryExpressionWhereBuilder whereClause =
(filterMap.getBoolean(FilterMap.ATTR_ADD_INSITUTION_JOIN))
? this.clientConnectionRecordMapper
.selectByExample() .selectByExample()
.join(InstitutionRecordDynamicSqlSupport.institutionRecord)
.on(InstitutionRecordDynamicSqlSupport.id,
SqlBuilder.equalTo(ClientConnectionRecordDynamicSqlSupport.institutionId))
.where( .where(
ClientConnectionRecordDynamicSqlSupport.institutionId, ClientConnectionRecordDynamicSqlSupport.institutionId,
isEqualToWhenPresent(filterMap.getInstitutionId())) isEqualToWhenPresent(filterMap.getInstitutionId()))
: this.clientConnectionRecordMapper
.selectByExample()
.where(
ClientConnectionRecordDynamicSqlSupport.institutionId,
isEqualToWhenPresent(filterMap.getInstitutionId()));
return whereClause
.and( .and(
ClientConnectionRecordDynamicSqlSupport.examId, ClientConnectionRecordDynamicSqlSupport.examId,
isEqualToWhenPresent(filterMap.getClientConnectionExamId())) isEqualToWhenPresent(filterMap.getClientConnectionExamId()))
@ -111,7 +127,8 @@ public class ClientConnectionDAOImpl implements ClientConnectionDAO {
.map(ClientConnectionDAOImpl::toDomainModel) .map(ClientConnectionDAOImpl::toDomainModel)
.flatMap(DAOLoggingSupport::logAndSkipOnError) .flatMap(DAOLoggingSupport::logAndSkipOnError)
.filter(predicate) .filter(predicate)
.collect(Collectors.toList())); .collect(Collectors.toList());
});
} }
@Override @Override

View file

@ -20,6 +20,8 @@ import java.util.function.Predicate;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import org.mybatis.dynamic.sql.SqlBuilder; 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.context.annotation.Lazy;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional; 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.ConfigurationRecordMapper;
import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.ConfigurationValueRecordDynamicSqlSupport; 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.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.datalayer.batis.model.ConfigurationNodeRecord;
import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.impl.BulkAction; import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.impl.BulkAction;
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ConfigurationNodeDAO; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ConfigurationNodeDAO;
@ -104,12 +107,24 @@ public class ConfigurationNodeDAOImpl implements ConfigurationNodeDAO {
final FilterMap filterMap, final FilterMap filterMap,
final Predicate<ConfigurationNode> predicate) { final Predicate<ConfigurationNode> predicate) {
return Result.tryCatch(() -> this.configurationNodeRecordMapper return Result.tryCatch(() -> {
final QueryExpressionDSL<MyBatis3SelectModelAdapter<List<ConfigurationNodeRecord>>>.QueryExpressionWhereBuilder whereClause =
(filterMap.getBoolean(FilterMap.ATTR_ADD_INSITUTION_JOIN))
? this.configurationNodeRecordMapper
.selectByExample() .selectByExample()
.join(InstitutionRecordDynamicSqlSupport.institutionRecord)
.on(InstitutionRecordDynamicSqlSupport.id,
SqlBuilder.equalTo(ConfigurationNodeRecordDynamicSqlSupport.institutionId))
.where( .where(
ConfigurationNodeRecordDynamicSqlSupport.status, ConfigurationNodeRecordDynamicSqlSupport.status,
SqlBuilder.isEqualToWhenPresent(filterMap.getConfigNodeStatus())) SqlBuilder.isEqualToWhenPresent(filterMap.getConfigNodeStatus()))
.and( : this.configurationNodeRecordMapper
.selectByExample()
.where(
ConfigurationNodeRecordDynamicSqlSupport.status,
SqlBuilder.isEqualToWhenPresent(filterMap.getConfigNodeStatus()));
return whereClause.and(
ConfigurationNodeRecordDynamicSqlSupport.institutionId, ConfigurationNodeRecordDynamicSqlSupport.institutionId,
SqlBuilder.isEqualToWhenPresent(filterMap.getInstitutionId())) SqlBuilder.isEqualToWhenPresent(filterMap.getInstitutionId()))
.and( .and(
@ -130,7 +145,8 @@ public class ConfigurationNodeDAOImpl implements ConfigurationNodeDAO {
.map(ConfigurationNodeDAOImpl::toDomainModel) .map(ConfigurationNodeDAOImpl::toDomainModel)
.flatMap(DAOLoggingSupport::logAndSkipOnError) .flatMap(DAOLoggingSupport::logAndSkipOnError)
.filter(predicate) .filter(predicate)
.collect(Collectors.toList())); .collect(Collectors.toList());
});
} }
@Override @Override

View file

@ -15,6 +15,7 @@ import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects; import java.util.Objects;
@ -27,6 +28,8 @@ import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTime; import org.joda.time.DateTime;
import org.mybatis.dynamic.sql.SqlBuilder; 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.context.annotation.Lazy;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Propagation; 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.ClientConnectionRecordMapper;
import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.ExamRecordDynamicSqlSupport; 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.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.AdditionalAttributeRecord;
import ch.ethz.seb.sebserver.webservice.datalayer.batis.model.ExamRecord; import ch.ethz.seb.sebserver.webservice.datalayer.batis.model.ExamRecord;
import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.impl.BulkAction; import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.impl.BulkAction;
@ -180,10 +185,35 @@ public class ExamDAOImpl implements ExamDAO {
return true; return true;
}; };
final List<ExamRecord> records = this.examRecordMapper.selectByExample() // 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<MyBatis3SelectModelAdapter<List<ExamRecord>>>.QueryExpressionWhereBuilder whereClause =
(filterMap.getBoolean(FilterMap.ATTR_ADD_INSITUTION_JOIN))
? this.examRecordMapper
.selectByExample()
.join(InstitutionRecordDynamicSqlSupport.institutionRecord)
.on(
InstitutionRecordDynamicSqlSupport.id,
SqlBuilder.equalTo(ExamRecordDynamicSqlSupport.institutionId))
.where( .where(
ExamRecordDynamicSqlSupport.active, ExamRecordDynamicSqlSupport.active,
isEqualToWhenPresent(filterMap.getActiveAsInt())) 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<ExamRecord> records = whereClause
.and( .and(
ExamRecordDynamicSqlSupport.institutionId, ExamRecordDynamicSqlSupport.institutionId,
isEqualToWhenPresent(filterMap.getInstitutionId())) isEqualToWhenPresent(filterMap.getInstitutionId()))
@ -750,7 +780,7 @@ public class ExamDAOImpl implements ExamDAO {
final HashMap<Long, Collection<ExamRecord>> lmsSetupToRecordMapping = records final HashMap<Long, Collection<ExamRecord>> lmsSetupToRecordMapping = records
.stream() .stream()
.reduce(new HashMap<>(), .reduce(new LinkedHashMap<>(),
(map, record) -> Utils.mapCollect(map, record.getLmsSetupId(), record), (map, record) -> Utils.mapCollect(map, record.getLmsSetupId(), record),
Utils::mapPutAll); Utils::mapPutAll);

View file

@ -20,6 +20,9 @@ import java.util.stream.Collectors;
import org.apache.commons.lang3.BooleanUtils; import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils; 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.context.annotation.Lazy;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional; 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.profile.WebServiceProfile;
import ch.ethz.seb.sebserver.gbl.util.Result; import ch.ethz.seb.sebserver.gbl.util.Result;
import ch.ethz.seb.sebserver.gbl.util.Utils; 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.LmsSetupRecordDynamicSqlSupport;
import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.LmsSetupRecordMapper; import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.LmsSetupRecordMapper;
import ch.ethz.seb.sebserver.webservice.datalayer.batis.model.LmsSetupRecord; import ch.ethz.seb.sebserver.webservice.datalayer.batis.model.LmsSetupRecord;
@ -108,11 +112,24 @@ public class LmsSetupDAOImpl implements LmsSetupDAO {
final FilterMap filterMap, final FilterMap filterMap,
final Predicate<LmsSetup> predicate) { final Predicate<LmsSetup> predicate) {
return Result.tryCatch(() -> this.lmsSetupRecordMapper return Result.tryCatch(() -> {
final QueryExpressionDSL<MyBatis3SelectModelAdapter<List<LmsSetupRecord>>>.QueryExpressionWhereBuilder whereClause =
(filterMap.getBoolean(FilterMap.ATTR_ADD_INSITUTION_JOIN))
? this.lmsSetupRecordMapper
.selectByExample() .selectByExample()
.join(InstitutionRecordDynamicSqlSupport.institutionRecord)
.on(InstitutionRecordDynamicSqlSupport.id,
SqlBuilder.equalTo(LmsSetupRecordDynamicSqlSupport.institutionId))
.where( .where(
LmsSetupRecordDynamicSqlSupport.institutionId, LmsSetupRecordDynamicSqlSupport.institutionId,
isEqualToWhenPresent(filterMap.getInstitutionId())) isEqualToWhenPresent(filterMap.getInstitutionId()))
: this.lmsSetupRecordMapper
.selectByExample()
.where(
LmsSetupRecordDynamicSqlSupport.institutionId,
isEqualToWhenPresent(filterMap.getInstitutionId()));
return whereClause
.and( .and(
LmsSetupRecordDynamicSqlSupport.name, LmsSetupRecordDynamicSqlSupport.name,
isLikeWhenPresent(filterMap.getName())) isLikeWhenPresent(filterMap.getName()))
@ -128,7 +145,8 @@ public class LmsSetupDAOImpl implements LmsSetupDAO {
.map(this::toDomainModel) .map(this::toDomainModel)
.flatMap(DAOLoggingSupport::logAndSkipOnError) .flatMap(DAOLoggingSupport::logAndSkipOnError)
.filter(predicate) .filter(predicate)
.collect(Collectors.toList())); .collect(Collectors.toList());
});
} }
@Override @Override

View file

@ -22,6 +22,8 @@ import java.util.stream.Collectors;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.mybatis.dynamic.sql.SqlBuilder; 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.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Lazy; 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.model.user.UserLogActivityType;
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile; import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
import ch.ethz.seb.sebserver.gbl.util.Result; 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.UserActivityLogRecordDynamicSqlSupport;
import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.UserActivityLogRecordMapper; import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.UserActivityLogRecordMapper;
import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.UserRecordDynamicSqlSupport; import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.UserRecordDynamicSqlSupport;
@ -310,11 +313,10 @@ public class UserActivityLogDAOImpl implements UserActivityLogDAO {
filterMap.getUserLofTo(), filterMap.getUserLofTo(),
filterMap.getString(UserActivityLog.FILTER_ATTR_ACTIVITY_TYPES), filterMap.getString(UserActivityLog.FILTER_ATTR_ACTIVITY_TYPES),
filterMap.getString(UserActivityLog.FILTER_ATTR_ENTITY_TYPES), filterMap.getString(UserActivityLog.FILTER_ATTR_ENTITY_TYPES),
filterMap.getBoolean(FilterMap.ATTR_ADD_INSITUTION_JOIN),
predicate); predicate);
} }
@Override
@Transactional(readOnly = true)
public Result<Collection<UserActivityLog>> all( public Result<Collection<UserActivityLog>> all(
final Long institutionId, final Long institutionId,
final String userName, final String userName,
@ -322,6 +324,7 @@ public class UserActivityLogDAOImpl implements UserActivityLogDAO {
final Long to, final Long to,
final String activityTypes, final String activityTypes,
final String entityTypes, final String entityTypes,
final boolean joinInstitution,
final Predicate<UserActivityLog> predicate) { final Predicate<UserActivityLog> predicate) {
return Result.tryCatch(() -> { return Result.tryCatch(() -> {
@ -332,7 +335,22 @@ public class UserActivityLogDAOImpl implements UserActivityLogDAO {
? Arrays.asList(StringUtils.split(entityTypes, Constants.LIST_SEPARATOR)) ? Arrays.asList(StringUtils.split(entityTypes, Constants.LIST_SEPARATOR))
: null; : null;
final List<UserActivityLogRecord> records = this.userLogRecordMapper final QueryExpressionDSL<MyBatis3SelectModelAdapter<List<UserActivityLogRecord>>>.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() .selectByExample()
.leftJoin(UserRecordDynamicSqlSupport.userRecord) .leftJoin(UserRecordDynamicSqlSupport.userRecord)
.on( .on(
@ -340,7 +358,9 @@ public class UserActivityLogDAOImpl implements UserActivityLogDAO {
SqlBuilder.equalTo(UserActivityLogRecordDynamicSqlSupport.userUuid)) SqlBuilder.equalTo(UserActivityLogRecordDynamicSqlSupport.userUuid))
.where( .where(
UserRecordDynamicSqlSupport.institutionId, UserRecordDynamicSqlSupport.institutionId,
SqlBuilder.isEqualToWhenPresent(institutionId)) SqlBuilder.isEqualToWhenPresent(institutionId));
final List<UserActivityLogRecord> records = whereClause
.and( .and(
UserRecordDynamicSqlSupport.username, UserRecordDynamicSqlSupport.username,
SqlBuilder.isLikeWhenPresent(userName)) SqlBuilder.isLikeWhenPresent(userName))

View file

@ -27,6 +27,9 @@ import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTime; import org.joda.time.DateTime;
import org.joda.time.DateTimeZone; 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.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Qualifier;
@ -162,11 +165,22 @@ public class UserDAOImpl implements UserDAO {
? predicate.and(ui -> ui.roles.contains(userRole)) ? predicate.and(ui -> ui.roles.contains(userRole))
: predicate; : predicate;
return this.userRecordMapper final QueryExpressionDSL<MyBatis3SelectModelAdapter<List<UserRecord>>>.QueryExpressionWhereBuilder sqlWhereClause =
(filterMap.getBoolean(FilterMap.ATTR_ADD_INSITUTION_JOIN))
? this.userRecordMapper
.selectByExample() .selectByExample()
.join(InstitutionRecordDynamicSqlSupport.institutionRecord)
.on(InstitutionRecordDynamicSqlSupport.id,
SqlBuilder.equalTo(UserRecordDynamicSqlSupport.institutionId))
.where( .where(
UserRecordDynamicSqlSupport.active, UserRecordDynamicSqlSupport.active,
isEqualToWhenPresent(filterMap.getActiveAsInt())) isEqualToWhenPresent(filterMap.getActiveAsInt()))
: this.userRecordMapper
.selectByExample()
.where(
UserRecordDynamicSqlSupport.active,
isEqualToWhenPresent(filterMap.getActiveAsInt()));
return sqlWhereClause
.and( .and(
UserRecordDynamicSqlSupport.institutionId, UserRecordDynamicSqlSupport.institutionId,
isEqualToWhenPresent(filterMap.getInstitutionId())) isEqualToWhenPresent(filterMap.getInstitutionId()))

View file

@ -103,12 +103,7 @@ public class ClientEventController extends ReadonlyEntityController<ClientEvent,
checkReadPrivilege(institutionId); checkReadPrivilege(institutionId);
final FilterMap filterMap = new FilterMap(allRequestParams, request.getQueryString()); final FilterMap filterMap = new FilterMap(allRequestParams, request.getQueryString());
populateFilterMap(filterMap, institutionId, 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));
}
try { try {

View file

@ -148,12 +148,7 @@ public abstract class EntityController<T extends Entity, M extends Entity> {
checkReadPrivilege(institutionId); checkReadPrivilege(institutionId);
final FilterMap filterMap = new FilterMap(allRequestParams, request.getQueryString()); final FilterMap filterMap = new FilterMap(allRequestParams, request.getQueryString());
populateFilterMap(filterMap, institutionId, 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));
}
return this.paginationService.getPage( return this.paginationService.getPage(
pageNumber, pageNumber,
@ -164,6 +159,19 @@ public abstract class EntityController<T extends Entity, M extends Entity> {
.getOrThrow(); .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) // * GET (names)
// ****************** // ******************

View file

@ -37,6 +37,7 @@ import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController; 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.API;
import ch.ethz.seb.sebserver.gbl.api.APIMessage; import ch.ethz.seb.sebserver.gbl.api.APIMessage;
import ch.ethz.seb.sebserver.gbl.api.APIMessage.APIMessageException; import ch.ethz.seb.sebserver.gbl.api.APIMessage.APIMessageException;
@ -480,6 +481,16 @@ public class ExamAdministrationController extends EntityController<Exam, Exam> {
.map(this::checkExamSupporterRole); .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) { private Exam checkExamSupporterRole(final Exam exam) {
final Set<String> examSupporter = this.userDAO.all( final Set<String> examSupporter = this.userDAO.all(
this.authorization.getUserService().getCurrentUser().getUserInfo().institutionId, this.authorization.getUserService().getCurrentUser().getUserInfo().institutionId,
@ -555,7 +566,7 @@ public class ExamAdministrationController extends EntityController<Exam, Exam> {
return list; 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)); list.sort(Comparator.comparing(exam -> exam.name));
} }
if (sortBy.equals(Exam.FILTER_ATTR_TYPE)) { if (sortBy.equals(Exam.FILTER_ATTR_TYPE)) {