diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/content/exam/ExamList.java b/src/main/java/ch/ethz/seb/sebserver/gui/content/exam/ExamList.java index a30016ef..e36488bf 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/content/exam/ExamList.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/content/exam/ExamList.java @@ -30,7 +30,6 @@ import ch.ethz.seb.sebserver.gbl.model.Entity; import ch.ethz.seb.sebserver.gbl.model.exam.Exam; import ch.ethz.seb.sebserver.gbl.model.exam.Exam.ExamStatus; import ch.ethz.seb.sebserver.gbl.model.exam.ExamConfigurationMap; -import ch.ethz.seb.sebserver.gbl.model.exam.QuizData; import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetup; import ch.ethz.seb.sebserver.gbl.model.user.UserRole; import ch.ethz.seb.sebserver.gbl.profile.GuiProfile; @@ -89,7 +88,7 @@ public class ExamList implements TemplateComposer { private final TableFilterAttribute institutionFilter; private final TableFilterAttribute lmsFilter; private final TableFilterAttribute nameFilter = - new TableFilterAttribute(CriteriaType.TEXT, QuizData.FILTER_ATTR_NAME); + new TableFilterAttribute(CriteriaType.TEXT, Domain.EXAM.ATTR_QUIZ_NAME); private final TableFilterAttribute stateFilter; private final TableFilterAttribute typeFilter; @@ -177,21 +176,21 @@ public class ExamList implements TemplateComposer { .sortable()) .withColumn(new ColumnDefinition<>( - QuizData.QUIZ_ATTR_NAME, + Domain.EXAM.ATTR_QUIZ_NAME, COLUMN_TITLE_NAME_KEY, Exam::getName) .withFilter(this.nameFilter) .sortable()) .withColumn(new ColumnDefinition<>( - QuizData.QUIZ_ATTR_START_TIME, + Domain.EXAM.ATTR_QUIZ_START_TIME, new LocTextKey( EXAM_LIST_COLUMN_START_TIME, i18nSupport.getUsersTimeZoneTitleSuffix()), Exam::getStartTime) .withFilter(new TableFilterAttribute( CriteriaType.DATE, - QuizData.FILTER_ATTR_START_TIME, + Domain.EXAM.ATTR_QUIZ_START_TIME, Utils.toDateTimeUTC(Utils.getMillisecondsNow()) .minusYears(1) .toString())) 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 dc99ebdf..1503ec37 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 @@ -282,10 +282,11 @@ public class PaginationServiceImpl implements PaginationService { final Map examTableMap = new HashMap<>(); examTableMap.put(Entity.FILTER_ATTR_INSTITUTION, institutionNameRef); examTableMap.put(Domain.EXAM.ATTR_LMS_SETUP_ID, lmsSetupNameRef); - - // NOTE: This seems not to work and I was not able to figure out why. - // Now the type sorting is done within secondary sort for exams. - //examTableMap.put(Domain.EXAM.ATTR_TYPE, "'" + ExamRecordDynamicSqlSupport.type.name() + "'"); + examTableMap.put(Domain.EXAM.ATTR_QUIZ_NAME, ExamRecordDynamicSqlSupport.quizName.name()); + examTableMap.put(Domain.EXAM.ATTR_QUIZ_START_TIME, ExamRecordDynamicSqlSupport.quizStartTime.name()); + examTableMap.put(Domain.EXAM.ATTR_QUIZ_END_TIME, ExamRecordDynamicSqlSupport.quizEndTime.name()); + examTableMap.put(Domain.EXAM.ATTR_STATUS, ExamRecordDynamicSqlSupport.status.name()); + 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); 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 8000a979..adaf45e2 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 @@ -19,6 +19,7 @@ import org.springframework.util.MultiValueMap; import ch.ethz.seb.sebserver.gbl.Constants; import ch.ethz.seb.sebserver.gbl.api.POSTMapper; +import ch.ethz.seb.sebserver.gbl.model.Domain; import ch.ethz.seb.sebserver.gbl.model.Entity; import ch.ethz.seb.sebserver.gbl.model.exam.Exam; import ch.ethz.seb.sebserver.gbl.model.exam.ExamConfigurationMap; @@ -108,7 +109,7 @@ public class FilterMap extends POSTMapper { } public DateTime getExamFromTime() { - return Utils.toDateTime(getString(QuizData.FILTER_ATTR_START_TIME)); + return Utils.toDateTime(getString(Domain.EXAM.ATTR_QUIZ_START_TIME)); } public DateTime getSEBClientConfigFromTime() { 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 1049592e..dd17c5ff 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 @@ -25,7 +25,6 @@ import java.util.stream.Collectors; import org.apache.commons.lang3.BooleanUtils; import org.apache.commons.lang3.StringUtils; -import org.joda.time.DateTime; import org.mybatis.dynamic.sql.update.UpdateDSL; import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.annotation.Lazy; @@ -121,42 +120,16 @@ public class ExamDAOImpl implements ExamDAO { return Result.tryCatch(() -> { - final Predicate examDataFilter = createPredicate(filterMap); return this.examRecordDAO .allMatching(filterMap, null) .flatMap(this::toDomainModel) .getOrThrow() .stream() - .filter(examDataFilter.and(predicate)) + .filter(predicate) .collect(Collectors.toList()); }); } - private Predicate createPredicate(final FilterMap filterMap) { - final String name = filterMap.getQuizName(); - final DateTime from = filterMap.getExamFromTime(); - final Predicate quizDataFilter = exam -> { - if (StringUtils.isNotBlank(name)) { - if (!exam.name.contains(name)) { - return false; - } - } - - if (from != null && exam.startTime != null) { - // always show exams that has not ended yet - if (exam.endTime == null || exam.endTime.isAfter(from)) { - return true; - } - if (exam.startTime.isBefore(from)) { - return false; - } - } - - return true; - }; - return quizDataFilter; - } - @Override public Result updateState(final Long examId, final ExamStatus status, final String updateId) { return this.examRecordDAO @@ -268,13 +241,12 @@ public class ExamDAOImpl implements ExamDAO { .stream().map(s -> s.name()) .collect(Collectors.toList()) : null; - final Predicate examDataFilter = createPredicate(filterMap); return this.examRecordDAO .allMatching(filterMap, stateNames) .flatMap(this::toDomainModel) .getOrThrow() .stream() - .filter(examDataFilter.and(predicate)) + .filter(predicate) .collect(Collectors.toList()); }); } diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ExamRecordDAO.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ExamRecordDAO.java index a7aed3cb..5550af7b 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ExamRecordDAO.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ExamRecordDAO.java @@ -172,8 +172,6 @@ public class ExamRecordDAO { ExamRecordDynamicSqlSupport.active, isEqualToWhenPresent(filterMap.getActiveAsInt())); - // - whereClause = whereClause .and( ExamRecordDynamicSqlSupport.institutionId, @@ -209,6 +207,10 @@ public class ExamRecordDAO { .and( ExamRecordDynamicSqlSupport.quizName, isLikeWhenPresent(filterMap.getSQLWildcard(EXAM.ATTR_QUIZ_NAME))) + .and( + ExamRecordDynamicSqlSupport.quizEndTime, + isGreaterThanOrEqualToWhenPresent(filterMap.getExamFromTime()), + or(ExamRecordDynamicSqlSupport.quizEndTime, isNull())) .build() .execute(); @@ -465,20 +467,20 @@ public class ExamRecordDAO { .execute(); // check those in not running state (and not archived) and are within the time-frame or on wrong side of the time-frame - // if finished but up-coming + // if finished but up-coming or running final SqlCriterion finished = or( ExamRecordDynamicSqlSupport.status, isEqualTo(ExamStatus.FINISHED.name()), and( - ExamRecordDynamicSqlSupport.quizStartTime, + ExamRecordDynamicSqlSupport.quizEndTime, SqlBuilder.isGreaterThanOrEqualToWhenPresent(now.plus(leadTime)))); - // if up-coming but finished + // if up-coming but running or finished final SqlCriterion upcoming = or( ExamRecordDynamicSqlSupport.status, isEqualTo(ExamStatus.UP_COMING.name()), and( - ExamRecordDynamicSqlSupport.quizEndTime, + ExamRecordDynamicSqlSupport.quizStartTime, SqlBuilder.isLessThanWhenPresent(now.minus(followupTime))), finished); 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 e87b585b..fb292d8e 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 @@ -17,13 +17,12 @@ import java.util.Set; import java.util.function.Function; import java.util.stream.Collectors; -import javax.servlet.http.HttpServletRequest; import javax.validation.Valid; import org.apache.commons.lang3.StringUtils; +import org.joda.time.DateTime; import org.mybatis.dynamic.sql.SqlTable; import org.springframework.http.MediaType; -import org.springframework.util.MultiValueMap; import org.springframework.validation.FieldError; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; @@ -39,14 +38,13 @@ import ch.ethz.seb.sebserver.gbl.api.APIMessage.APIMessageException; import ch.ethz.seb.sebserver.gbl.api.APIMessage.ErrorMessage; import ch.ethz.seb.sebserver.gbl.api.EntityType; import ch.ethz.seb.sebserver.gbl.api.POSTMapper; -import ch.ethz.seb.sebserver.gbl.api.authorization.PrivilegeType; import ch.ethz.seb.sebserver.gbl.model.Domain; import ch.ethz.seb.sebserver.gbl.model.Domain.EXAM; import ch.ethz.seb.sebserver.gbl.model.EntityKey; -import ch.ethz.seb.sebserver.gbl.model.Page; import ch.ethz.seb.sebserver.gbl.model.PageSortOrder; import ch.ethz.seb.sebserver.gbl.model.exam.Chapters; import ch.ethz.seb.sebserver.gbl.model.exam.Exam; +import ch.ethz.seb.sebserver.gbl.model.exam.Exam.ExamType; import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringServiceSettings; import ch.ethz.seb.sebserver.gbl.model.exam.QuizData; import ch.ethz.seb.sebserver.gbl.model.exam.SEBRestriction; @@ -120,50 +118,56 @@ public class ExamAdministrationController extends EntityController { return ExamRecordDynamicSqlSupport.examRecord; } - @RequestMapping( - method = RequestMethod.GET, - consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE, - produces = MediaType.APPLICATION_JSON_VALUE) - @Override - public Page getPage( - @RequestParam( - name = API.PARAM_INSTITUTION_ID, - required = true, - defaultValue = UserService.USERS_INSTITUTION_AS_DEFAULT) final Long institutionId, - @RequestParam(name = Page.ATTR_PAGE_NUMBER, required = false) final Integer pageNumber, - @RequestParam(name = Page.ATTR_PAGE_SIZE, required = false) final Integer pageSize, - @RequestParam(name = Page.ATTR_SORT, required = false) final String sort, - @RequestParam final MultiValueMap allRequestParams, - final HttpServletRequest request) { - - checkReadPrivilege(institutionId); - this.authorization.check( - PrivilegeType.READ, - EntityType.EXAM, - institutionId); - - if (StringUtils.isBlank(sort) || - (this.paginationService.isNativeSortingSupported(ExamRecordDynamicSqlSupport.examRecord, sort))) { - - return super.getPage(institutionId, pageNumber, pageSize, sort, allRequestParams, request); - - } else { - - final Collection exams = this.examDAO - .allMatching(new FilterMap( - allRequestParams, - request.getQueryString()), - this::hasReadAccess) - .getOrThrow(); - - return this.paginationService.buildPageFromList( - pageNumber, - pageSize, - sort, - exams, - pageSort(sort)); - } - } +// @RequestMapping( +// method = RequestMethod.GET, +// consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE, +// produces = MediaType.APPLICATION_JSON_VALUE) +// @Override +// public Page getPage( +// @RequestParam( +// name = API.PARAM_INSTITUTION_ID, +// required = true, +// defaultValue = UserService.USERS_INSTITUTION_AS_DEFAULT) final Long institutionId, +// @RequestParam(name = Page.ATTR_PAGE_NUMBER, required = false) final Integer pageNumber, +// @RequestParam(name = Page.ATTR_PAGE_SIZE, required = false) final Integer pageSize, +// @RequestParam(name = Page.ATTR_SORT, required = false) final String sort, +// @RequestParam final MultiValueMap allRequestParams, +// final HttpServletRequest request) { +// +// checkReadPrivilege(institutionId); +// this.authorization.check( +// PrivilegeType.READ, +// EntityType.EXAM, +// institutionId); +// +// if (StringUtils.isBlank(sort) || +// (this.paginationService.isNativeSortingSupported(ExamRecordDynamicSqlSupport.examRecord, sort))) { +// +// System.out.println("*********************** sort, filter on DB"); +// +// return super.getPage(institutionId, pageNumber, pageSize, sort, allRequestParams, request); +// +// } else { +// +// System.out.println("*********************** sort, filter on List"); +// +// return super.getPage(institutionId, pageNumber, pageSize, sort, allRequestParams, request); +// +//// final Collection exams = this.examDAO +//// .allMatching(new FilterMap( +//// allRequestParams, +//// request.getQueryString()), +//// this::hasReadAccess) +//// .getOrThrow(); +//// +//// return this.paginationService.buildPageFromList( +//// pageNumber, +//// pageSize, +//// sort, +//// exams, +//// pageSort(sort)); +// } +// } @RequestMapping( path = API.MODEL_ID_VAR_PATH_SEGMENT @@ -586,13 +590,13 @@ public class ExamAdministrationController extends EntityController { } 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 != null) ? exam.name : StringUtils.EMPTY)); } if (sortBy.equals(Exam.FILTER_ATTR_TYPE)) { - list.sort(Comparator.comparing(exam -> exam.type)); + list.sort(Comparator.comparing(exam -> (exam.type != null) ? exam.type : ExamType.UNDEFINED)); } if (sortBy.equals(QuizData.FILTER_ATTR_START_TIME) || sortBy.equals(QuizData.QUIZ_ATTR_START_TIME)) { - list.sort(Comparator.comparing(exam -> exam.startTime)); + list.sort(Comparator.comparing(exam -> (exam.startTime != null) ? exam.startTime : new DateTime(0))); } if (PageSortOrder.DESCENDING == PageSortOrder.getSortOrder(sort)) {