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()
.withEmptyMessage(EMPTY_LIST_TEXT_KEY)
.withPaging(this.pageSize)
.withDefaultSort(CertificateInfo.ATTR_ALIAS)
.withColumn(new ColumnDefinition<>(
CertificateInfo.ATTR_ALIAS,

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -97,6 +97,9 @@ public class EntityTable<ROW> {
private final Consumer<Set<ROW>> selectionListener;
private final Consumer<Integer> contentChangeListener;
private final String defaultSortColumn;
private final PageSortOrder defaultSortOrder;
int pageNumber;
int pageSize;
String sortColumn = null;
@ -120,7 +123,9 @@ public class EntityTable<ROW> {
final MultiValueMap<String, String> staticQueryParams,
final BiConsumer<TableItem, ROW> rowDecorator,
final Consumer<Set<ROW>> selectionListener,
final Consumer<Integer> contentChangeListener) {
final Consumer<Integer> contentChangeListener,
final String defaultSortColumn,
final PageSortOrder defaultSortOrder) {
this.name = name;
this.filterAttrName = name + "_filter";
@ -129,6 +134,9 @@ public class EntityTable<ROW> {
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<ROW> {
}
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<ROW> {
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<ROW> {
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<ROW> {
.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<ROW> {
.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 {

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.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<ROW> {
private Consumer<Set<ROW>> selectionListener;
private Consumer<Integer> 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<ROW> {
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) {
this.columns.add(columnDefinition);
return this;
@ -209,7 +222,9 @@ public class TableBuilder<ROW> {
this.staticQueryParams,
this.rowDecorator,
this.selectionListener,
this.contentChangeListener);
this.contentChangeListener,
this.defaultSortColumn,
this.defaultSortOrder);
}
}

View file

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

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.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<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_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<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_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<String, String> 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<String, String> 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<String, String> 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<String, String> 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<String, String> userActivityLogTableMap = new HashMap<>();
userActivityLogTableMap.put(
UserActivityLog.FILTER_ATTR_INSTITUTION,
institutionNameRef);
userActivityLogTableMap.put(
Domain.USER.ATTR_USERNAME,
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 */
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);
}

View file

@ -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<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.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<ClientConnection> 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<MyBatis3SelectModelAdapter<List<ClientConnectionRecord>>>.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

View file

@ -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<ConfigurationNode> 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<MyBatis3SelectModelAdapter<List<ConfigurationNodeRecord>>>.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

View file

@ -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<ExamRecord> 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<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(
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<ExamRecord> records = whereClause
.and(
ExamRecordDynamicSqlSupport.institutionId,
isEqualToWhenPresent(filterMap.getInstitutionId()))
@ -750,7 +780,7 @@ public class ExamDAOImpl implements ExamDAO {
final HashMap<Long, Collection<ExamRecord>> lmsSetupToRecordMapping = records
.stream()
.reduce(new HashMap<>(),
.reduce(new LinkedHashMap<>(),
(map, record) -> Utils.mapCollect(map, record.getLmsSetupId(), record),
Utils::mapPutAll);

View file

@ -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<LmsSetup> 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<MyBatis3SelectModelAdapter<List<LmsSetupRecord>>>.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

View file

@ -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<Collection<UserActivityLog>> 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<UserActivityLog> predicate) {
return Result.tryCatch(() -> {
@ -332,15 +335,32 @@ public class UserActivityLogDAOImpl implements UserActivityLogDAO {
? Arrays.asList(StringUtils.split(entityTypes, Constants.LIST_SEPARATOR))
: null;
final List<UserActivityLogRecord> records = this.userLogRecordMapper
.selectByExample()
.leftJoin(UserRecordDynamicSqlSupport.userRecord)
.on(
UserRecordDynamicSqlSupport.uuid,
SqlBuilder.equalTo(UserActivityLogRecordDynamicSqlSupport.userUuid))
.where(
UserRecordDynamicSqlSupport.institutionId,
SqlBuilder.isEqualToWhenPresent(institutionId))
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()
.leftJoin(UserRecordDynamicSqlSupport.userRecord)
.on(
UserRecordDynamicSqlSupport.uuid,
SqlBuilder.equalTo(UserActivityLogRecordDynamicSqlSupport.userUuid))
.where(
UserRecordDynamicSqlSupport.institutionId,
SqlBuilder.isEqualToWhenPresent(institutionId));
final List<UserActivityLogRecord> records = whereClause
.and(
UserRecordDynamicSqlSupport.username,
SqlBuilder.isLikeWhenPresent(userName))

View file

@ -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<MyBatis3SelectModelAdapter<List<UserRecord>>>.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()))

View file

@ -103,12 +103,7 @@ public class ClientEventController extends ReadonlyEntityController<ClientEvent,
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);
try {

View file

@ -148,12 +148,7 @@ public abstract class EntityController<T extends Entity, M extends Entity> {
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<T extends Entity, M extends Entity> {
.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)
// ******************

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.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<Exam, Exam> {
.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<String> examSupporter = this.userDAO.all(
this.authorization.getUserService().getCurrentUser().getUserInfo().institutionId,
@ -555,7 +566,7 @@ public class ExamAdministrationController extends EntityController<Exam, Exam> {
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)) {