diff --git a/app/config/public.js b/app/config/public.js index 871078a50..3aa00d24f 100644 --- a/app/config/public.js +++ b/app/config/public.js @@ -43,13 +43,13 @@ module.exports = { // Properties that will be provided to frontend in the public dataReqParams: { countRecords: 'count-records', - site: 'site', - rowsOnSite: 'rows-on-site', + pageNumber: 'page-number', + itemsPerPage: 'items-per-page', }, defaultDataReqParams: { - site: 1, - rowsOnSite: 50, + pageNumber: 1, + itemsPerPage: 50, }, dataResponseFields: { diff --git a/app/lib/database/DatabaseService.js b/app/lib/database/DatabaseService.js index f9bbe1304..66063ec4e 100644 --- a/app/lib/database/DatabaseService.js +++ b/app/lib/database/DatabaseService.js @@ -127,8 +127,8 @@ class DatabaseService { if (req.query[DRP.countRecords] === 'true') { data[DRF.totalRowsCount] = rows.length; - const offset = params[DRP.rowsOnSite] * (params[DRP.site] - 1); - const limit = params[DRP.rowsOnSite]; + const offset = params[DRP.itemsPerPage] * (params[DRP.pageNumber] - 1); + const limit = params[DRP.itemsPerPage]; rows = rows.slice(offset, offset + limit); } diff --git a/app/lib/database/utilities/PGQueryBuilder.js b/app/lib/database/utilities/PGQueryBuilder.js index 986d6d979..a6f0ee0d0 100644 --- a/app/lib/database/utilities/PGQueryBuilder.js +++ b/app/lib/database/utilities/PGQueryBuilder.js @@ -113,7 +113,7 @@ class PGQueryBuilder { static buildSelect(params) { const dataSubsetQueryPart = (params) => params[DRP.countRecords] === 'true' ? '' : - `LIMIT ${params[DRP.rowsOnSite]} OFFSET ${params[DRP.rowsOnSite] * (params[DRP.site] - 1)}`; + `LIMIT ${params[DRP.itemsPerPage]} OFFSET ${params[DRP.itemsPerPage] * (params[DRP.pageNumber] - 1)}`; const orderingPart = (params) => { if (!params['sorting']) { diff --git a/app/public/components/table/obsoletePager.js b/app/public/components/table/obsoletePager.js index 34f94815a..0c14dc657 100644 --- a/app/public/components/table/obsoletePager.js +++ b/app/public/components/table/obsoletePager.js @@ -15,8 +15,9 @@ import { h, iconChevronBottom } from '/js/src/index.js'; import obsoleteItemsCounter from '../../views/userView/data/table/obsoleteItemsCounter.js'; import { RCT } from '../../config.js'; +import { pageButtonStyle, pagerButtonConditions } from './pagerUtils.js'; -const { site } = RCT.dataReqParams; +const { pageNumber } = RCT.dataReqParams; /** * Uses obsolete model. @@ -28,20 +29,19 @@ const { site } = RCT.dataReqParams; * @returns {obsoletePager} row with pager and table display properties controllers */ export default function obsoletePager(model, data, pagerOnly = true) { - const sitesNumber = Math.ceil(data.totalRecordsNumber / data.rowsOnSite); - const currentSite = Number(Object.fromEntries(data.url.searchParams.entries())[site]); + const pagesCount = Math.ceil(data.totalRecordsNumber / data.itemsPerPage); + const currentPageNumber = Number(Object.fromEntries(data.url.searchParams.entries())[pageNumber]); const columnOptionsSelectId = 'columns-option-select-id'; - const pageButton = (targetSite) => h(`button.btn${targetSite === currentSite ? '.btn-primary' : '.btn-secondary'}.no-text-decoration`, { - onclick: () => model.fetchedData.changePage(targetSite), - }, targetSite); + const buttonConditions = pagerButtonConditions(currentPageNumber, pagesCount); - const siteChangingController = (targetSite, content) => h('button.btn.btn-secondary.site-changing-controller', { - onclick: () => model.fetchedData.changePage(targetSite), - }, content); + const pageButton = (targetPage) => h(`button.btn${pageButtonStyle(targetPage, currentPageNumber)}.no-text-decoration`, { + onclick: () => model.fetchedData.changePage(targetPage), + }, targetPage); - const moreSitesLeft = currentSite > 2; - const moreSitesRight = currentSite < sitesNumber - 1; + const pageChangingController = (targetPage, content) => h('button.btn.btn-secondary.page-changing-controller', { + onclick: () => model.fetchedData.changePage(targetPage), + }, content); function handleOptionChange() { const columnsOptionsSelect = document.getElementById(columnOptionsSelectId); @@ -95,43 +95,36 @@ export default function obsoletePager(model, data, pagerOnly = true) { ], h('.flex.m-right-0-3-rem', - // Move to the first site - currentSite > 1 ? siteChangingController(1, h('.double-left-15-primary')) : ' ', - // Move one site back - currentSite > 1 ? siteChangingController(currentSite - 1, h('.back-15-primary')) : ' ', - - // Move to the middle of sites range [first, current] - moreSitesLeft - ? siteChangingController( - Math.floor(currentSite / 2), + buttonConditions.goToFirstPage ? pageChangingController(1, h('.double-left-15-primary')) : '', + buttonConditions.goOnePageBack ? pageChangingController(currentPageNumber - 1, h('.back-15-primary')) : '', + buttonConditions.goMiddleBack + ? pageChangingController( + Math.floor(currentPageNumber / 2), h('.more-15-primary'), ) : '', - currentSite > 1 ? pageButton(currentSite - 1) : '', - pageButton(currentSite), - currentSite < sitesNumber ? pageButton(currentSite + 1) : '', + buttonConditions.goOnePageBack ? pageButton(currentPageNumber - 1) : '', + pageButton(currentPageNumber), + buttonConditions.goOnePageForward ? pageButton(currentPageNumber + 1) : '', - // Move to the middle of sites range [current, last] - moreSitesRight - ? siteChangingController( - currentSite + Math.floor((sitesNumber - currentSite) / 2), + buttonConditions.goMiddleForward + ? pageChangingController( + currentPageNumber + Math.floor((pagesCount - currentPageNumber) / 2), h('.more-15-primary'), ) : '', - // Move one site forward - currentSite < sitesNumber - ? siteChangingController( - currentSite + 1, + buttonConditions.goOnePageForward + ? pageChangingController( + currentPageNumber + 1, h('.forward-15-primary'), ) : '', - // Move to the last site - currentSite < sitesNumber - ? siteChangingController( - sitesNumber, + buttonConditions.goToLastPage + ? pageChangingController( + pagesCount, h('.double-right-15-primary'), ) : ''), diff --git a/app/public/components/table/pageSelector.js b/app/public/components/table/pageSelector.js index 061a03788..5aa73a9e5 100644 --- a/app/public/components/table/pageSelector.js +++ b/app/public/components/table/pageSelector.js @@ -12,62 +12,49 @@ * or submit itself to any jurisdiction. */ +import { pageButtonStyle, pagerButtonConditions } from './pagerUtils.js'; import { h } from '/js/src/index.js'; export default function pageSelector(currentPage, pagesCount, onPageChange) { - const pageButtonStyle = (targetPage) => targetPage === currentPage - ? '.btn-primary' - : '.btn-secondary'; - - const pageNumberButton = (targetPage) => h(`button.btn${pageButtonStyle(targetPage)}.no-text-decoration`, { + const buttonConditions = pagerButtonConditions(currentPage, pagesCount); + const pageNumberButton = (targetPage) => h(`button.btn${pageButtonStyle(targetPage, currentPage)}.no-text-decoration`, { onclick: () => onPageChange(targetPage), }, targetPage); - const pageIconButton = (targetPage, content) => h('button.btn.btn-secondary.site-changing-controller', { + const pageIconButton = (targetPage, content) => h('button.btn.btn-secondary.page-changing-controller', { onclick: () => onPageChange(targetPage), }, content); - const morePagesLeft = currentPage > 2; - const morePagesRight = currentPage < pagesCount - 1; - const isFirstPage = currentPage > 1; - const isLastPage = currentPage < pagesCount; - return h('.flex.m-right-0-3-rem', - // Move to the first page - isFirstPage ? pageIconButton(1, h('.double-left-15-primary')) : '', - // Move one page back - isFirstPage ? pageIconButton(currentPage - 1, h('.back-15-primary')) : '', + buttonConditions.goToFirstPage ? pageIconButton(1, h('.double-left-15-primary')) : '', + buttonConditions.goOnePageBack ? pageIconButton(currentPage - 1, h('.back-15-primary')) : '', - // Move to the middle of pages range [first, current] - morePagesLeft + buttonConditions.goMiddleBack ? pageIconButton( Math.floor(currentPage / 2), h('.more-15-primary'), ) : '', - isFirstPage ? pageNumberButton(currentPage - 1) : '', + buttonConditions.goOnePageBack ? pageNumberButton(currentPage - 1) : '', pageNumberButton(currentPage), - isLastPage ? pageNumberButton(currentPage + 1) : '', + buttonConditions.goOnePageForward ? pageNumberButton(currentPage + 1) : '', - // Move to the middle of pages range [current, last] - morePagesRight + buttonConditions.goMiddleForward ? pageIconButton( currentPage + Math.floor((pagesCount - currentPage) / 2), h('.more-15-primary'), ) : '', - // Move one page forward - isLastPage + buttonConditions.goOnePageForward ? pageIconButton( currentPage + 1, h('.forward-15-primary'), ) : '', - // Move to the last page - isLastPage + buttonConditions.goToLastPage ? pageIconButton( pagesCount, h('.double-right-15-primary'), diff --git a/app/public/components/table/pagerUtils.js b/app/public/components/table/pagerUtils.js new file mode 100644 index 000000000..49d0e0ead --- /dev/null +++ b/app/public/components/table/pagerUtils.js @@ -0,0 +1,31 @@ +/** + * @license + * Copyright 2019-2020 CERN and copyright holders of ALICE O2. + * See http://alice-o2.web.cern.ch/copyright for details of the copyright holders. + * All rights not expressly granted are reserved. + * + * This software is distributed under the terms of the GNU General Public + * License v3 (GPL Version 3), copied verbatim in the file "COPYING". + * + * In applying this license CERN does not waive the privileges and immunities + * granted to it by virtue of its status as an Intergovernmental Organization + * or submit itself to any jurisdiction. + */ + +export const buttonClasses = { + primary: '.btn-primary', + secondary: '.btn-secondary', +}; + +export const pageButtonStyle = (targetPage, currentPage) => targetPage === currentPage + ? buttonClasses.primary + : buttonClasses.secondary; + +export const pagerButtonConditions = (currentPage, pagesCount) => ({ + goToFirstPage: currentPage > 1, + goOnePageBack: currentPage > 1, + goMiddleBack: currentPage > 2, + goMiddleForward: currentPage < pagesCount - 1, + goOnePageForward: currentPage !== pagesCount, + goToLastPage: currentPage !== pagesCount, +}); diff --git a/app/public/components/table/pagination/PaginationModel.js b/app/public/components/table/pagination/PaginationModel.js index 77704b29e..05747aff4 100644 --- a/app/public/components/table/pagination/PaginationModel.js +++ b/app/public/components/table/pagination/PaginationModel.js @@ -27,13 +27,13 @@ export class PaginationModel extends Observable { super(); this._userPreferences = userPreferences; - this._itemsPerPage = userPreferences.rowsOnSite; + this._itemsPerPage = userPreferences.itemsPerPage; this._currentPage = DEFAULT_CURRENT_PAGE; this._currentPageItemsCount = DEFAULT_ITEMS_COUNT; this._itemsCount = DEFAULT_ITEMS_COUNT; this._userPreferences.observe(() => { - this._itemsPerPage = this._userPreferences.rowsOnSite; + this._itemsPerPage = this._userPreferences.itemsPerPage; this.notify(); }); } diff --git a/app/public/model/UserPreferences.js b/app/public/model/UserPreferences.js index 5b35462ad..aa7d9bfaa 100644 --- a/app/public/model/UserPreferences.js +++ b/app/public/model/UserPreferences.js @@ -17,7 +17,7 @@ import { replaceUrlParams } from '../utils/url/urlUtils.js'; import { RCT } from '../config.js'; const { dataReqParams } = RCT; -const defaultRowsOnSite = 50; +const defaultItemsPerPage = 50; export const sidebarPreferences = { visible: 'visible', @@ -26,24 +26,24 @@ export const sidebarPreferences = { /** * Observable responsible for handling and providing user preferences: - * number of rows on site, UI theme, sidebar preferenes, detector list and predefined filters + * number of items per page, UI theme, sidebar preferenes, detector list and predefined filters */ export default class UserPreferences extends Observable { constructor(parent) { super(); this.parent = parent; - this.rowsOnSite = defaultRowsOnSite; + this.itemsPerPage = defaultItemsPerPage; this.uiTheme = RCT.themes.rct; this.sidebarPreference = sidebarPreferences.collapsible; this.detectorList = RCT.detectors.reduce((acc, detector) => ({ ...acc, [detector]: true }), {}); } setItemsPerPage(itemsPerPage) { - this.rowsOnSite = itemsPerPage; + this.itemsPerPage = itemsPerPage; this.notify(); const url = this.parent.router.getUrl(); - const newUrl = replaceUrlParams(url, { [dataReqParams.rowsOnSite]: this.rowsOnSite }); + const newUrl = replaceUrlParams(url, { [dataReqParams.itemsPerPage]: this.itemsPerPage }); this.parent.router.go(newUrl); } diff --git a/app/public/model/data/FetchedData.js b/app/public/model/data/FetchedData.js index a5ff36821..659a01ec9 100644 --- a/app/public/model/data/FetchedData.js +++ b/app/public/model/data/FetchedData.js @@ -12,7 +12,7 @@ * or submit itself to any jurisdiction. */ -const defaultSite = 1; +const defaultPageNumber = 1; import { RCT } from '../../../config.js'; import { shouldDisplayDetectorField } from '../../utils/dataProcessing/dataProcessingUtils.js'; @@ -29,7 +29,7 @@ const DRF = RCT.dataResponseFields; export default class FetchedData { constructor(url, content, userPreferences, totalRecordsNumber = null) { this.url = url; - this.rowsOnSite = userPreferences.rowsOnSite; + this.itemsPerPage = userPreferences.itemsPerPage; this.detectorList = userPreferences.detectorList; this.sorting = { @@ -51,8 +51,8 @@ export default class FetchedData { useUrlParams(url) { const params = Object.fromEntries(url.searchParams.entries()); const DRP = RCT.dataReqParams; - this.rowsOnSite = params['rows-on-site'] ?? this.rowsOnSite; - this.site = params[DRP.site] ? params[DRP.site] : defaultSite; + this.itemsPerPage = params['items-per-page'] ?? this.itemsPerPage; + this.pageNumber = params[DRP.pageNumber] ? params[DRP.pageNumber] : defaultPageNumber; if (params['sorting']) { const { sorting } = params; if (sorting.startsWith('-')) { diff --git a/app/public/model/data/FetchedDataManager.js b/app/public/model/data/FetchedDataManager.js index c0a78fb4c..68ce8d96b 100644 --- a/app/public/model/data/FetchedDataManager.js +++ b/app/public/model/data/FetchedDataManager.js @@ -48,17 +48,17 @@ export default class FetchedDataManager { * when first after creating object request is performed, * to url is added additional param 'count-records', * which inform backend to calculate the total number of rows in target view - * this information is used to create site navigation + * this information is used to create page navigation */ async reqForData(force = false, url = null) { if (url === null) { url = this.router.getUrl(); - if (!url.searchParams.has(dataReqParams.rowsOnSite)) { - url = new URL(`${url.href}&${dataReqParams.rowsOnSite}=${this.model.parent.userPreferences.rowsOnSite}`); + if (!url.searchParams.has(dataReqParams.itemsPerPage)) { + url = new URL(`${url.href}&${dataReqParams.itemsPerPage}=${this.model.parent.userPreferences.itemsPerPage}`); } - if (!url.searchParams.has(dataReqParams.site)) { - url = new URL(`${url.href}&${dataReqParams.site}=1`); + if (!url.searchParams.has(dataReqParams.pageNumber)) { + url = new URL(`${url.href}&${dataReqParams.pageNumber}=1`); } } const { page, index } = this.model.getDataPointerFromUrl(url); @@ -66,7 +66,7 @@ export default class FetchedDataManager { if (!data || force) { await this.req(true, url); } else if (data.payload.url.href !== url.href) { - if (this.diffOnlyBySiteAndSorting(url, data.payload.url)) { + if (this.diffOnlyByPageNumberAndSorting(url, data.payload.url)) { await this.req(false, url); } else { await this.req(true, url); @@ -74,13 +74,13 @@ export default class FetchedDataManager { } } - diffOnlyBySiteAndSorting(url1, url2) { + diffOnlyByPageNumberAndSorting(url1, url2) { const p1 = Object.fromEntries(new URLSearchParams(url1.search)); const p2 = Object.fromEntries(new URLSearchParams(url2.search)); - p1['site'] = undefined; - p1['sorting'] = undefined; - p2['site'] = undefined; - p2['sorting'] = undefined; + p1[dataReqParams.pageNumber] = undefined; + p1[dataReqParams.sorting] = undefined; + p2[dataReqParams.pageNumber] = undefined; + p2[dataReqParams.sorting] = undefined; return JSON.stringify(p1) == JSON.stringify(p2); } @@ -131,7 +131,7 @@ export default class FetchedDataManager { changePage(pageNumber) { const url = this.router.getUrl(); - const newUrl = replaceUrlParams(url, { [dataReqParams.site]: pageNumber }); + const newUrl = replaceUrlParams(url, { [dataReqParams.pageNumber]: pageNumber }); this.router.go(newUrl); } @@ -142,12 +142,6 @@ export default class FetchedDataManager { this.router.go(newUrl); } - changeRowsOnSite() { - const url = this.router.getUrl(); - const newUrl = replaceUrlParams(url, { [dataReqParams.rowsOnSite]: this.model.parent.userPreferences.rowsOnSite }); - this.router.go(newUrl); - } - changeItemStatus(item) { item.marked = arguments[1] !== undefined ? arguments[1] diff --git a/app/public/model/navigation/Navigation.js b/app/public/model/navigation/Navigation.js index 61d505ee8..f816d0f5c 100644 --- a/app/public/model/navigation/Navigation.js +++ b/app/public/model/navigation/Navigation.js @@ -37,7 +37,7 @@ export default class Navigation extends Observable { this.router.observe(this.routerCallback); this.router.bubbleTo(this); - this.site = defaultDataReqParams.site; + this.pageNumber = defaultDataReqParams.pageNumber; this.handleLocationChange(); } @@ -48,7 +48,7 @@ export default class Navigation extends Observable { switch (url.pathname) { case '/': { if (! page) { - this.router.go(`/?page=${pageNames.periods}${this.siteReqParamsPhrase()}&sorting=-name`); + this.router.go(`/?page=${pageNames.periods}${this.pageNumberReqParamsPhrase()}&sorting=-name`); } else { await this.pageNavigation(url, page); this.parent.fetchedData.reqForData() @@ -70,7 +70,7 @@ export default class Navigation extends Observable { await this.model.runs.fetchRunsPerDataPass(dataPassName).then(() => {}).catch(() => {}); const dpSearchParams = `?page=${pageNames.runsPerDataPass}&index=${dataPassName}`; - const dpUrl = new URL(url.origin + url.pathname + dpSearchParams + this.siteReqParamsPhrase()); + const dpUrl = new URL(url.origin + url.pathname + dpSearchParams + this.pageNumberReqParamsPhrase()); this.parent.fetchedData.reqForData(true, dpUrl).then(() => { const runNumbers = this.model.runs.getRunsPerDataPass(dataPassName).map((row) => row.run_number); this.model.runs.fetchFlagsSummary(dataPassName, runNumbers).then(() => { @@ -91,19 +91,19 @@ export default class Navigation extends Observable { goToDefaultPageUrl(page) { const url = page === pageNames.flags - ? `/?page=${page}&run_numbers=${noRunNumbers}${this.siteReqParamsPhrase()}` - : `/?page=${page}${this.siteReqParamsPhrase()}`; + ? `/?page=${page}&run_numbers=${noRunNumbers}${this.pageNumberReqParamsPhrase()}` + : `/?page=${page}${this.pageNumberReqParamsPhrase()}`; this.router.go(url); } - siteReqParamsPhrase() { - return `&${dataReqParams.rowsOnSite}=${this.model.userPreferences.rowsOnSite}&${dataReqParams.site}=${this.site}`; + pageNumberReqParamsPhrase() { + return `&${dataReqParams.itemsPerPage}=${this.model.userPreferences.itemsPerPage}&${dataReqParams.pageNumber}=${this.pageNumber}`; } - siteReqParams() { + pageNumberReqParams() { return { - [dataReqParams.rowsOnSite]: this.model.userPreferences.rowsOnSite, - [dataReqParams.site]: this.site, + [dataReqParams.itemsPerPage]: this.model.userPreferences.itemsPerPage, + [dataReqParams.pageNumber]: this.pageNumber, }; } @@ -119,6 +119,6 @@ export default class Navigation extends Observable { * @returns {void} */ go(targetPage, targetIndex) { - this.router.go(`/?page=${targetPage}&index=${targetIndex}${this.siteReqParamsPhrase()}`); + this.router.go(`/?page=${targetPage}&index=${targetIndex}${this.pageNumberReqParamsPhrase()}`); } } diff --git a/app/public/styles/rct/custom/components/pager.css b/app/public/styles/rct/custom/components/pager.css index e29cc11fc..1e7cc7705 100644 --- a/app/public/styles/rct/custom/components/pager.css +++ b/app/public/styles/rct/custom/components/pager.css @@ -36,7 +36,7 @@ border: none !important; } -.rct .site-changing-controller { +.rct .page-changing-controller { padding: 5px; margin: 3px; cursor: pointer; diff --git a/app/public/views/runs/Runs.js b/app/public/views/runs/Runs.js index 56c182c92..dc96f82f6 100644 --- a/app/public/views/runs/Runs.js +++ b/app/public/views/runs/Runs.js @@ -34,7 +34,7 @@ export default class Runs extends Observable { async fetchFlagsSummary(dataPass, runNumbers) { const url = this.model.router.getUrl(); - const search = `?page=${PN.flags}&data_pass_name=${dataPass}&run_numbers=${runNumbers}&${DRP.rowsOnSite}=50&${DRP.site}=1`; + const search = `?page=${PN.flags}&data_pass_name=${dataPass}&run_numbers=${runNumbers}&${DRP.itemsPerPage}=50&${DRP.pageNumber}=1`; const flagsUrl = new URL(url.origin + url.pathname + search); await this.model.dataAccess.fetchedData.reqForData(true, flagsUrl); } @@ -43,7 +43,7 @@ export default class Runs extends Observable { const page = this.model.dataAccess.fetchedData[PN.dataPasses]; const [pIndex] = Object.keys(page); const { url } = page[pIndex].payload; - const dpSearchParams = `?page=${PN.runsPerDataPass}&index=${dataPass}&${DRP.rowsOnSite}=50&${DRP.site}=1`; + const dpSearchParams = `?page=${PN.runsPerDataPass}&index=${dataPass}&${DRP.itemsPerPage}=50&${DRP.pageNumber}=1`; await this.model.dataAccess.fetchedData.reqForData(true, new URL(url.origin + url.pathname + dpSearchParams)); const runNumbers = this.model.dataAccess.fetchedData[PN.runsPerDataPass][dataPass].payload.rows.map((row) => row.run_number); diff --git a/app/public/views/runs/runsPerDataPass/overview/qcTypeSelection.js b/app/public/views/runs/runsPerDataPass/overview/qcTypeSelection.js index a8f301f59..3af4ae160 100644 --- a/app/public/views/runs/runsPerDataPass/overview/qcTypeSelection.js +++ b/app/public/views/runs/runsPerDataPass/overview/qcTypeSelection.js @@ -17,7 +17,8 @@ import { RCT } from '../../../../config.js'; const { runBasedQuality } = RCT.quality; export default function qcTypeSelection(navigation, close, item, index, detectorName, runDetectorId, timeBased) { - const flagsUrl = `/?page=flags&data_pass_name=${index}&run_numbers=${item.run_number}&detector=${detectorName}&rows-on-site=50&site=1`; + const baseUrl = `/?page=flags&data_pass_name=${index}&run_numbers=${item.run_number}&detector=${detectorName}`; + const flagsUrl = `${baseUrl}${navigation.pageNumberReqParamsPhrase()}`; const runQualitySelectId = 'run-quality-select'; function handleRunQualityChange() { diff --git a/app/public/views/userView/data/pageSettings/pageSettings.js b/app/public/views/userView/data/pageSettings/pageSettings.js index da46236db..71254e3da 100644 --- a/app/public/views/userView/data/pageSettings/pageSettings.js +++ b/app/public/views/userView/data/pageSettings/pageSettings.js @@ -17,7 +17,7 @@ import quantityInput from '../../../../components/common/quantityInput.js'; import { RCT } from '../../../../config.js'; export default function pageSettings(userPreferences, close) { - const rowsOnSiteInputId = 'rows-per-page-input-id-modal'; + const itemsPerPageInputId = 'rows-per-page-input-id-modal'; const themeSelectId = 'theme-selection'; const sidebarPreferenceSelectId = 'sidebar-selection'; const sidebarPreferences = { @@ -27,11 +27,11 @@ export default function pageSettings(userPreferences, close) { const title = h('h3.text-primary', 'Page settings'); const onclickApply = (userPreferences) => { - const input = document.getElementById(rowsOnSiteInputId); + const input = document.getElementById(itemsPerPageInputId); const inputValue = input.value === '' ? input.placeholder : input.value; if (inputValue < 1 || inputValue > 200) { alert('incorrect number of rows on page: must be in range of [1, 200]'); - input.value = userPreferences.rowsOnSite; + input.value = userPreferences.itemsPerPage; } else { userPreferences.setItemsPerPage(inputValue); } @@ -97,9 +97,9 @@ export default function pageSettings(userPreferences, close) { h('.p-left-1rem', title)), h('.flex-wrap.justify-between.items-center', - h('.text-dark-blue', 'Rows on site'), - quantityInput(rowsOnSiteInputId, - userPreferences.rowsOnSite)), + h('.text-dark-blue', 'Items per page'), + quantityInput(itemsPerPageInputId, + userPreferences.itemsPerPage)), h('.flex-wrap.justify-between.items-center', h('.text-dark-blue', 'UI theme'), diff --git a/app/public/views/userView/data/pagesCellsSpecials.js b/app/public/views/userView/data/pagesCellsSpecials.js index 0f95f3964..f574f70a9 100644 --- a/app/public/views/userView/data/pagesCellsSpecials.js +++ b/app/public/views/userView/data/pagesCellsSpecials.js @@ -34,7 +34,7 @@ const acceptableEnergyMargin = RCT.mapping.energy.acceptableMargin; * return viewButton(model, item.period, (e) => * handleClick(model, e), '', * TODO : this pattern is deprecated - * `/?page=runsPerPeriod&index=${item.period}&period=${item.period}&rowsOnSite=50&site=1`); + * `/?page=runsPerPeriod&index=${item.period}&period=${item.period}&itemsPerPage=50&page-number=1`); * }, * }, * // ..., @@ -54,19 +54,20 @@ pagesCellsSpecials[PN.periods] = { model.navigation, 'runs', // eslint-disable-next-line max-len - `/?page=${PN.runsPerPeriod}&index=${item.name}&${DRP.rowsOnSite}=${model.parent.userPreferences.rowsOnSite}&${DRP.site}=1&sorting=-run_number`, + `/?page=${PN.runsPerPeriod}&index=${item.name}&${DRP.itemsPerPage}=${model.parent.userPreferences.itemsPerPage}&${DRP.pageNumber}=1&sorting=-run_number`, ), linkChip( model.navigation, 'data passes', - `/?page=${PN.dataPasses}&index=${item.name}&${DRP.rowsOnSite}=${model.parent.userPreferences.rowsOnSite}&${DRP.site}=1`, + // eslint-disable-next-line max-len + `/?page=${PN.dataPasses}&index=${item.name}&${DRP.itemsPerPage}=${model.parent.userPreferences.itemsPerPage}&${DRP.pageNumber}=1`, ), linkChip( model.navigation, 'MC', - `/?page=${PN.mc}&index=${item.name}&${DRP.rowsOnSite}=${model.parent.userPreferences.rowsOnSite}&${DRP.site}=1`, + `/?page=${PN.mc}&index=${item.name}&${DRP.itemsPerPage}=${model.parent.userPreferences.itemsPerPage}&${DRP.pageNumber}=1`, )), ], @@ -86,14 +87,14 @@ pagesCellsSpecials[PN.dataPasses] = { onclick: async () => { await runs.fetchRunsPerDataPass(item.name); // eslint-disable-next-line max-len - model.router.go(`/?page=${PN.runsPerDataPass}&index=${item.name}&${DRP.rowsOnSite}=${model.parent.userPreferences.rowsOnSite}&${DRP.site}=1&sorting=-run_number`); + model.router.go(`/?page=${PN.runsPerDataPass}&index=${item.name}&${DRP.itemsPerPage}=${model.parent.userPreferences.itemsPerPage}&${DRP.pageNumber}=1&sorting=-run_number`); }, }, 'runs'), linkChip( model.navigation, 'anchorage', // eslint-disable-next-line max-len - `/?page=${PN.anchoragePerDatapass}&index=${item.name}&${DRP.rowsOnSite}=${model.parent.userPreferences.rowsOnSite}&${DRP.site}=1&sorting=-name`, + `/?page=${PN.anchoragePerDatapass}&index=${item.name}&${DRP.itemsPerPage}=${model.parent.userPreferences.itemsPerPage}&${DRP.pageNumber}=1&sorting=-name`, )), ], size: (model, runs, item) => getReadableFileSizeString(Number(item.size)), @@ -106,7 +107,7 @@ pagesCellsSpecials[PN.mc] = { model.navigation, 'anchored', // eslint-disable-next-line max-len - `/?page=${PN.anchoredPerMC}&index=${item.name}&${DRP.rowsOnSite}=${model.parent.userPreferences.rowsOnSite}&${DRP.site}=1&sorting=-name`, + `/?page=${PN.anchoredPerMC}&index=${item.name}&${DRP.itemsPerPage}=${model.parent.userPreferences.itemsPerPage}&${DRP.pageNumber}=1&sorting=-name`, )), ], }; diff --git a/app/public/views/userView/data/table/obsoleteItemsCounter.js b/app/public/views/userView/data/table/obsoleteItemsCounter.js index 6da6609a6..78ecaf57b 100644 --- a/app/public/views/userView/data/table/obsoleteItemsCounter.js +++ b/app/public/views/userView/data/table/obsoleteItemsCounter.js @@ -14,7 +14,7 @@ import { RCT } from '../../../../config.js'; -const siteParamName = RCT.dataReqParams.site; +const { pageNumber } = RCT.dataReqParams; /** * Please use the new items counter instead that uses the paginationModel @@ -23,12 +23,12 @@ const siteParamName = RCT.dataReqParams.site; * @returns {string} range of items diplayed on the given page and the total number of fetched records */ export default function obsoleteItemsCounter(data) { - const currentSite = Number(Object.fromEntries(data.url.searchParams.entries())[siteParamName]); + const currentPageNumber = Number(Object.fromEntries(data.url.searchParams.entries())[pageNumber]); - const firstRowIdx = (currentSite - 1) * data.rowsOnSite + 1; - const lastRowIdx = currentSite * data.rowsOnSite > data.totalRecordsNumber + const firstRowIdx = (currentPageNumber - 1) * data.itemsPerPage + 1; + const lastRowIdx = currentPageNumber * data.itemsPerPage > data.totalRecordsNumber ? data.totalRecordsNumber - : currentSite * data.rowsOnSite; + : currentPageNumber * data.itemsPerPage; return `${firstRowIdx}-${lastRowIdx} of ${data.totalRecordsNumber}`; } diff --git a/test/database/utilities/PGQueryBuilder.test.js b/test/database/utilities/PGQueryBuilder.test.js index 04fc1a5a4..1be6bc216 100644 --- a/test/database/utilities/PGQueryBuilder.test.js +++ b/test/database/utilities/PGQueryBuilder.test.js @@ -41,8 +41,8 @@ module.exports = () => { const filteringParams = { page: 'periods', - 'rows-on-site': '50', - site: '1', + 'items-per-page': '50', + 'page-number': '1', sorting: '-name', 'name-match': ['%c%,%a', '%C%C'], 'beam-match': 'p-p', @@ -59,8 +59,8 @@ module.exports = () => { const filteringParams = { page: 'periods', - 'rows-on-site': '2', - site: '2', + 'items-per-page': '2', + 'page-number': '2', sorting: '-name', 'name-match': '%c%', 'beam-match': 'p-p,Pb-Pb', @@ -79,8 +79,8 @@ module.exports = () => { const filteringParams = { page: 'periods', - 'rows-on-site': '2', - site: '2', + 'items-per-page': '2', + 'page-number': '2', sorting: '-name', 'name-match': '%c%', 'name-exclude': ['%cccASDF%,', '%asdf,,,%asdf'], @@ -100,8 +100,8 @@ module.exports = () => { const filteringParams = { page: 'periods', - 'rows-on-site': '2', - site: '2', + 'items-per-page': '2', + 'page-number': '2', sorting: '-name', 'year-between': [',,2022,'], }; diff --git a/test/public/components/index.js b/test/public/components/index.js index 617065b51..8e343e10a 100644 --- a/test/public/components/index.js +++ b/test/public/components/index.js @@ -13,8 +13,10 @@ const itemsCounterSuite = require('./itemsCounter.test'); const pageTitleSuite = require('./pageTitle.test'); +const pagerUtils = require('./pagerUtils.test'); module.exports = () => { describe('Items counter', itemsCounterSuite); describe('Page title', pageTitleSuite); + describe('Pager utils', pagerUtils); }; diff --git a/test/public/components/pagerUtils.test.js b/test/public/components/pagerUtils.test.js new file mode 100644 index 000000000..b140d4c69 --- /dev/null +++ b/test/public/components/pagerUtils.test.js @@ -0,0 +1,48 @@ +/** + * @license + * Copyright CERN and copyright holders of ALICE O2. This software is + * distributed under the terms of the GNU General Public License v3 (GPL + * Version 3), copied verbatim in the file "COPYING". + * + * See http://alice-o2.web.cern.ch/license for full licensing information. + * + * In applying this license CERN does not waive the privileges and immunities + * granted to it by virtue of its status as an Intergovernmental Organization + * or submit itself to any jurisdiction. + */ + +const req = require('esm')(module); + +const { buttonClasses, pageButtonStyle, pagerButtonConditions } = req('../../../app/public/components/table/pagerUtils'); +const assert = require('assert'); + +module.exports = () => { + describe('Page button style', () => { + it('should return primary style when the target page is the current page', () => { + assert.equal(pageButtonStyle(6, 6), buttonClasses.primary); + }); + + it('should return secondary style when the target page is the current page', () => { + assert.equal(pageButtonStyle(3, 35), buttonClasses.secondary); + }); + }); + + describe('Page buttons', () => { + it('should not display go back buttons when the user is on the first page', () => { + assert(!pagerButtonConditions(1, 6).goToFirstPage && + !pagerButtonConditions(1, 4).goMiddleBack && + !pagerButtonConditions(1, 3).goOnePageBack); + }); + + it('should not display any pagination buttons when there is only one page', () => { + const buttonConditions = pagerButtonConditions(1, 1); + assert(!Object.keys(buttonConditions).reduce((acc, curr) => acc || buttonConditions[curr], false)); + }); + + it('should not display go forward buttons when the user is on the last page', () => { + assert(!pagerButtonConditions(6, 6).goToLastPage && + !pagerButtonConditions(4, 4).goMiddleForward && + !pagerButtonConditions(3, 3).goOnePageForward); + }); + }); +}; diff --git a/test/public/utils/url/urlUtils.test.js b/test/public/utils/url/urlUtils.test.js index 468ba4e68..cbe776ecc 100644 --- a/test/public/utils/url/urlUtils.test.js +++ b/test/public/utils/url/urlUtils.test.js @@ -17,11 +17,11 @@ const assert = require('assert'); const { replaceUrlParams } = req('../../../../app/public/utils/url/urlUtils'); module.exports = () => { - const url = new URL('http://localhost:8081/?page=periods&index=_0&rows-on-site=50&site=1'); - const targetUrl = new URL('http://localhost:8081/?page=periods&index=_0&rows-on-site=50&site=2'); + const url = new URL('http://localhost:8081/?page=periods&index=_0&items-per-page=50&page-number=1'); + const targetUrl = new URL('http://localhost:8081/?page=periods&index=_0&items-per-page=50&page-number=2'); describe('Replace URL params', () => { it('should return correct value', () => { - assert(replaceUrlParams(url, { site: 2 }).href === targetUrl.href); + assert(replaceUrlParams(url, { 'page-number': 2 }).href === targetUrl.href); }); }); };