diff --git a/src/main/java/teammates/common/util/Const.java b/src/main/java/teammates/common/util/Const.java index 6d462bba1e2..e32bd8ad774 100644 --- a/src/main/java/teammates/common/util/Const.java +++ b/src/main/java/teammates/common/util/Const.java @@ -33,6 +33,8 @@ public final class Const { public static final Duration FEEDBACK_SESSIONS_SEARCH_WINDOW = Duration.ofDays(30); public static final Duration LOGS_RETENTION_PERIOD = Duration.ofDays(30); + public static final int SEARCH_QUERY_SIZE_LIMIT = 50; + // These constants are used as variable values to mean that the variable is in a 'special' state. public static final int INT_UNINITIALIZED = -9999; diff --git a/src/main/java/teammates/storage/search/SearchManager.java b/src/main/java/teammates/storage/search/SearchManager.java index 4afde069f04..ee6a26c4c5f 100644 --- a/src/main/java/teammates/storage/search/SearchManager.java +++ b/src/main/java/teammates/storage/search/SearchManager.java @@ -19,6 +19,7 @@ import teammates.common.datatransfer.attributes.EntityAttributes; import teammates.common.exception.SearchServiceException; import teammates.common.util.Config; +import teammates.common.util.Const; import teammates.common.util.Logger; import teammates.common.util.StringHelper; @@ -43,7 +44,7 @@ abstract class SearchManager> { "Failed to reset collections. Root cause: %s "; private static final int START_INDEX = 0; - private static final int NUM_OF_RESULTS = 20; + private static final int NUM_OF_RESULTS = Const.SEARCH_QUERY_SIZE_LIMIT; private final HttpSolrClient client; private final boolean isResetAllowed; diff --git a/src/main/java/teammates/ui/constants/ApiConst.java b/src/main/java/teammates/ui/constants/ApiConst.java index 07b1ea6310e..2ed8a89a966 100644 --- a/src/main/java/teammates/ui/constants/ApiConst.java +++ b/src/main/java/teammates/ui/constants/ApiConst.java @@ -26,7 +26,8 @@ public enum ApiConst { RANK_OPTIONS_ANSWER_NOT_SUBMITTED(Const.POINTS_NOT_SUBMITTED), RANK_RECIPIENTS_ANSWER_NOT_SUBMITTED(Const.POINTS_NOT_SUBMITTED), NO_VALUE(Const.POINTS_NO_VALUE), - LOGS_RETENTION_PERIOD(Const.LOGS_RETENTION_PERIOD.toDays()); + LOGS_RETENTION_PERIOD(Const.LOGS_RETENTION_PERIOD.toDays()), + SEARCH_QUERY_SIZE_LIMIT(Const.SEARCH_QUERY_SIZE_LIMIT); // CHECKSTYLE.ON:JavadocVariable private final Object value; diff --git a/src/web/app/pages-admin/admin-search-page/admin-search-page.component.ts b/src/web/app/pages-admin/admin-search-page/admin-search-page.component.ts index 9f317d419d2..7756126fc00 100755 --- a/src/web/app/pages-admin/admin-search-page/admin-search-page.component.ts +++ b/src/web/app/pages-admin/admin-search-page/admin-search-page.component.ts @@ -15,6 +15,7 @@ import { import { SimpleModalService } from '../../../services/simple-modal.service'; import { StatusMessageService } from '../../../services/status-message.service'; import { StudentService } from '../../../services/student.service'; +import { ApiConst } from '../../../types/api-const'; import { Email, RegenerateKey } from '../../../types/api-output'; import { SimpleModalType } from '../../components/simple-modal/simple-modal-type'; import { collapseAnim } from '../../components/teammates-common/collapse-anim'; @@ -61,12 +62,28 @@ export class AdminSearchPageComponent { this.statusMessageService.showWarningToast('No results found.'); this.instructors = []; this.students = []; - } else { - this.instructors = resp.instructors; - this.students = resp.students; - this.hideAllInstructorsLinks(); - this.hideAllStudentsLinks(); + return; } + + this.instructors = resp.instructors; + this.students = resp.students; + this.hideAllInstructorsLinks(); + this.hideAllStudentsLinks(); + + // prompt user to use more specific terms if search results limit reached + const limit: number = ApiConst.SEARCH_QUERY_SIZE_LIMIT; + const limitsReached: string[] = []; + if (this.students.length >= limit) { + limitsReached.push(`${limit} student results`); + } + if (this.instructors.length >= limit) { + limitsReached.push(`${limit} instructor results`); + } + if (limitsReached.length) { + this.statusMessageService.showWarningToast(`${limitsReached.join(' and ')} have been shown on this page + but there may be more results not shown. Consider searching with more specific terms.`); + } + }, (resp: ErrorMessageOutput) => { this.instructors = []; this.students = []; diff --git a/src/web/app/pages-instructor/instructor-search-page/instructor-search-page.component.ts b/src/web/app/pages-instructor/instructor-search-page/instructor-search-page.component.ts index 2e8fe64a5da..fcc9f33ab02 100644 --- a/src/web/app/pages-instructor/instructor-search-page/instructor-search-page.component.ts +++ b/src/web/app/pages-instructor/instructor-search-page/instructor-search-page.component.ts @@ -4,6 +4,7 @@ import { finalize, map, mergeMap } from 'rxjs/operators'; import { CourseService } from '../../../services/course.service'; import { InstructorSearchResult, SearchService } from '../../../services/search.service'; import { StatusMessageService } from '../../../services/status-message.service'; +import { ApiConst } from '../../../types/api-const'; import { InstructorPrivilege, Student, @@ -64,6 +65,10 @@ export class InstructorSearchPageComponent implements OnInit { if (hasStudents) { this.studentsListRowTables = searchStudentsTable; + if (searchStudentsTable.length >= ApiConst.SEARCH_QUERY_SIZE_LIMIT) { + this.statusMessageService.showWarningToast(`${ApiConst.SEARCH_QUERY_SIZE_LIMIT} results have been shown on this page + but there may be more results not shown. Consider searching with more specific terms.`); + } } else { this.studentsListRowTables = []; }