Skip to content
This repository was archived by the owner on Jan 14, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions app/public/Model.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import Runs from './views/runs/Runs.js';
import PeriodsModel from './views/periods/PeriodsModel.js';
import UserPreferences from './model/UserPreferences.js';
import RunsPerPeriodModel from './views/runs/newRunsPerPeriod/RunsPerPeriodModel.js';
import Navigation from './model/navigation/Navigation.js';
const { roles, dataAccess, pageNames } = RCT;

export default class Model extends Observable {
Expand All @@ -41,6 +42,9 @@ export default class Model extends Observable {
this.router.observe(this.handleLocationChange.bind(this));
this.router.bubbleTo(this);

this.navigation = new Navigation(this);
this.navigation.bubbleTo(this);

this.loader = new Loader();
this.loader.bubbleTo(this);

Expand Down
4 changes: 4 additions & 0 deletions app/public/components/about/about.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@

import { h } from '/js/src/index.js';

/**
* View aimed to display the applicaton details
* @return {vnode} appliaction details presentation
*/
export default function about() {
const title = h('h3.text-primary', 'About');

Expand Down
2 changes: 1 addition & 1 deletion app/public/components/buttons/copyLinkButton.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import snackBar from '../snackBars/snackBar.js';

/**
* @param {string} url - url that will be returned to the user
* @returns a button that once clicked will add the url to the user's clipboard
* @returns {vnode} a button that once clicked will add the url to the user's clipboard
*/

export default function copyLinkButton(url) {
Expand Down
2 changes: 1 addition & 1 deletion app/public/components/chips/indexChip.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ const { pageNames } = RCT;
* @param {Observable} model - provides a set of functions
* @param {string} pageName - name of the page
* @param {string} index - index of the item on page
* @returns - button that navigates user to the related (page, index) view
* @returns {vnode} button that navigates user to the related (page, index) view
*/

export default function indexChip(model, pageName, index) {
Expand Down
10 changes: 10 additions & 0 deletions app/public/components/chips/linkChip.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,16 @@

import { h } from '/js/src/index.js';

/**
* Return a component representing a link in a form of a chip
*
* @param {Navigation} navigation the content of the link displayed to the user
* @param {string} label displayed chip name
* @param {string} href the absolute URL targeted by the link
*
* @return {vnode} the linkChip component
*/

export default function linkChip(navigation, label, href) {
return h('a.btn.chip.m1.no-text-decoration', {
onclick: (e) => navigation.handleLinkEvent(e),
Expand Down
2 changes: 1 addition & 1 deletion app/public/model/DataAccessModel.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
import { Observable, Loader } from '/js/src/index.js';
import FetchedDataManager from './data/FetchedDataManager.js';
import { defaultIndex, defaultIndexString } from '../utils/defaults.js';
import Navigation from './navigation/Navigation.js';
import Navigation from './navigation/ObsoleteNavigation.js';
import ServiceUnavailable from './ServiceUnavailable.js';
import { RCT } from '../config.js';
const { messageTimeout } = RCT;
Expand Down
22 changes: 22 additions & 0 deletions app/public/model/OverviewModel.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/**
* @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.
*/

/**
* Interface of a model representing an overview page state
*
* @interface OverviewModel
*/

/**
* @property {PaginationModel} OverviewModel#pagination pagination model of the overview
*/
97 changes: 4 additions & 93 deletions app/public/model/navigation/Navigation.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,113 +12,24 @@
*/

import { Observable } from '/js/src/index.js';
import { RCT } from '../../config.js';
import { noRunNumbers } from '../../utils/defaults.js';
const { pageNames, dataReqParams, defaultDataReqParams } = RCT;

/**
* Model representing handlers for navigation change
*
* @implements {OverviewModel}
* Model representing navigation - aimed to use for url related tasks
*/
export default class Navigation extends Observable {
/**
* The constructor of the Overview model object
* The constructor of the Navigation object
*
* @param {Model} model main model to access the general functions
* @param {DataAccessModel} parent model to access the data fetching functions
* @param {Model} model main model
*/
constructor(model, parent) {
constructor(model) {
super();
this.parent = parent;
this.model = model;
this.router = model.router;
this.routerCallback = this.handleLocationChange.bind(this);
this.router.observe(this.routerCallback);
this.router.bubbleTo(this);

this.pageNumber = defaultDataReqParams.pageNumber;

this.handleLocationChange();
}

async handleLocationChange() {
const url = this.router.getUrl();
const { page } = this.router.params;
switch (url.pathname) {
case '/': {
if (! page) {
this.router.go(`/?page=${pageNames.periods}${this.pageNumberReqParamsPhrase()}&sorting=-name`);
} else {
await this.pageNavigation(url, page);
this.parent.fetchedData.reqForData()
.then(() => {})
.catch(() => {});
}
break;
}
default:
break;
}
}

async pageNavigation(url, page) {
switch (page) {
case pageNames.flags: {
const dataPassName = this.router.params['data_pass_name'];
if (dataPassName) {
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.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(() => {
this.parent.fetchedData.reqForData();
}).catch(() => {});
});
}
break;
}
default: {
this.parent.fetchedData.reqForData()
.then(() => {})
.catch(() => {});
break;
}
}
}

goToDefaultPageUrl(page) {
const url = page === pageNames.flags
? `/?page=${page}&run_numbers=${noRunNumbers}${this.pageNumberReqParamsPhrase()}`
: `/?page=${page}${this.pageNumberReqParamsPhrase()}`;
this.router.go(url);
}

pageNumberReqParamsPhrase() {
return `&${dataReqParams.itemsPerPage}=${this.model.userPreferences.itemsPerPage}&${dataReqParams.pageNumber}=${this.pageNumber}`;
}

pageNumberReqParams() {
return {
[dataReqParams.itemsPerPage]: this.model.userPreferences.itemsPerPage,
[dataReqParams.pageNumber]: this.pageNumber,
};
}

handleLinkEvent(e) {
this.router.handleLinkEvent(e);
this.notify();
}

/**
* Go to the url specified by the pageName and index
* @param {string} targetPage - pageName that the user will be navigated to
* @param {string} targetIndex - index on the page
* @returns {void}
*/
go(targetPage, targetIndex) {
this.router.go(`/?page=${targetPage}&index=${targetIndex}${this.pageNumberReqParamsPhrase()}`);
}
}
145 changes: 145 additions & 0 deletions app/public/model/navigation/ObsoleteNavigation.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
/**
* @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.
*/

import { Observable } from '/js/src/index.js';
import { RCT } from '../../config.js';
import { noRunNumbers } from '../../utils/defaults.js';
import { buildHref } from '../../utils/url/urlUtils.js';
const { pageNames, dataReqParams, defaultDataReqParams } = RCT;

/**
* Model representing handlers for navigation change
*
* @implements {OverviewModel}
* @deprecated
*/
export default class Navigation extends Observable {
/**
* The constructor of the Overview model object
*
* @param {Model} model main model to access the general functions
* @param {DataAccessModel} parent model to access the data fetching functions
*/
constructor(model, parent) {
super();
this.parent = parent;
this.model = model;
this.router = model.router;
this.routerCallback = this.handleLocationChange.bind(this);
this.router.observe(this.routerCallback);
this.router.bubbleTo(this);

this.pageNumber = defaultDataReqParams.pageNumber;

this.handleLocationChange();
}

async handleLocationChange() {
const url = this.router.getUrl();
const { page } = this.router.params;
switch (url.pathname) {
case '/': {
if (! page) {
this.router.go(
buildHref({
page: pageNames.periods,
sorting: '-name',
...this.pageNumberReqParams(),
}),
);
} else {
await this.pageNavigation(url, page);
this.parent.fetchedData.reqForData()
.then(() => {})
.catch(() => {});
}
break;
}
default:
break;
}
}

async pageNavigation(url, page) {
switch (page) {
case pageNames.flags: {
const dataPassName = this.router.params['data_pass_name'];
if (dataPassName) {
await this.model.runs.fetchRunsPerDataPass(dataPassName).then(() => {}).catch(() => {});

const dpSearchParams = buildHref({
page: pageNames.runsPerDataPass,
index: dataPassName,
...this.pageNumberReqParams(),
});
const dpUrl = new URL(url.origin + url.pathname + dpSearchParams);
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(() => {
this.parent.fetchedData.reqForData();
}).catch(() => {});
});
}
break;
}
default: {
this.parent.fetchedData.reqForData()
.then(() => {})
.catch(() => {});
break;
}
}
}

goToDefaultPageUrl(page) {
const url = page === pageNames.flags
? buildHref({
page: page,
['run_numbers']: noRunNumbers,
...this.pageNumberReqParams(),
})
: buildHref({
page: page,
...this.pageNumberReqParams(),
});
this.router.go(url);
}

pageNumberReqParams() {
return {
[dataReqParams.itemsPerPage]: this.model.userPreferences.itemsPerPage,
[dataReqParams.pageNumber]: this.pageNumber,
};
}

handleLinkEvent(e) {
this.router.handleLinkEvent(e);
this.notify();
}

/**
* Go to the url specified by the pageName and index
* @param {string} targetPage - pageName that the user will be navigated to
* @param {string} targetIndex - index on the page
* @returns {void}
*/
go(targetPage, targetIndex) {
this.router.go(
buildHref({
page: targetPage,
index: targetIndex,
...this.pageNumberReqParams(),
}),
);
}
}
12 changes: 12 additions & 0 deletions app/public/utils/url/urlUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,15 @@ export function urlSearchToParamsObject(search) {
}
return Object.fromEntries(search.slice(2).split('&').map((ent) => ent.split('=')));
}

export const formatParameter = (key, value) => `${key}=${value}`;

/**
* Prepares the href for the link components
* @param {Object} parameters list of query parameters, as an object
* @returns {string} href ready to be used in link components
*/
export const buildHref = (parameters) => {
const paramEntries = Object.entries(parameters);
return `?${paramEntries.map(([key, value]) => formatParameter(key, value)).join('&')}`;
};
5 changes: 5 additions & 0 deletions app/public/view.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@ import dataAccessPanel from './views/dataAccessPanel.js';
import { switchCase } from '/js/src/index.js';
import { serviceUnavailable, sessionError, waiting } from './components/messagePanel/messages.js';

/**
* Main view layout
* @param {Model} model - representing current application state
* @return {vnode} application view to be drawn according to model
*/
export default function view(model) {
const { state } = model.dataAccess;

Expand Down
Loading