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
20 changes: 4 additions & 16 deletions app/config/public.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,11 @@
* or submit itself to any jurisdiction.
*/

const { roles, flags: flagsTypes, detectors } = require('./rct-data');
const { roles, flags: flagsTypes, detectors, pageNames, filterTypes, filterInput } = require('./rct-data');

module.exports = { // Properties that will be provided to frontend in the public folder
filterTypes: {
match: 'match',
exclude: 'exclude',
between: 'between',
},
filterTypes: filterTypes,
filterInput: filterInput,

roles,
flagsTypes,
Expand Down Expand Up @@ -58,16 +55,7 @@ module.exports = { // Properties that will be provided to frontend in the public
fields: 'fields',
},

pageNames: {
periods: 'periods',
dataPasses: 'dataPasses',
mc: 'mc',
anchoredPerMC: 'anchoredPerMC',
anchoragePerDatapass: 'anchoragePerDatapass',
runsPerPeriod: 'runsPerPeriod',
runsPerDataPass: 'runsPerDataPass',
flags: 'flags',
},
pageNames: pageNames,

operationsNames: {
flag_insert: 'flags_insert',
Expand Down
26 changes: 26 additions & 0 deletions app/config/rct-data/filterTypes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/**
* @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.
*/

const filterTypes = {
match: 'match',
exclude: 'exclude',
between: 'between',
};

const filterInput = {
number: 'number',
string: 'string',
};

module.exports = { filterTypes, filterInput };
2 changes: 1 addition & 1 deletion app/config/rct-data/flags.json
Original file line number Diff line number Diff line change
Expand Up @@ -97,4 +97,4 @@
"bad": "1",
"obsolete": "0"
}
]
]
5 changes: 5 additions & 0 deletions app/config/rct-data/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
* or submit itself to any jurisdiction.
*/

const pageNames = require('./pageNames.js');
const { filterTypes, filterInput } = require('./filterTypes.js');
const detectors = require('./detectors.js').sort();
const flags = require('./flags.json');
const roles = require('./roles.js');
Expand All @@ -20,6 +22,9 @@ const beamTypesMappings = require('./beamTypesMappings.js');
const healthcheckQueries = require('./healthcheckQueries.js');

module.exports = {
pageNames,
filterTypes,
filterInput,
detectors,
roles,
flags,
Expand Down
26 changes: 26 additions & 0 deletions app/config/rct-data/pageNames.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/**
* @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.
*/

const pageNames = {
periods: 'periods',
dataPasses: 'dataPasses',
mc: 'mc',
anchoredPerMC: 'anchoredPerMC',
anchoragePerDatapass: 'anchoragePerDatapass',
runsPerPeriod: 'runsPerPeriod',
runsPerDataPass: 'runsPerDataPass',
flags: 'flags',
};

module.exports = pageNames;
15 changes: 15 additions & 0 deletions app/public/utils/filtering/filterUtils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/**
* @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 sqlWildCard = '%';
56 changes: 46 additions & 10 deletions app/public/views/userView/data/table/filtering/activeFilters.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,35 +14,71 @@

import { h } from '/js/src/index.js';
import { RCT } from '../../../../../config.js';
import { sqlWildCard } from '../../../../../utils/filtering/filterUtils.js';

const { dataReqParams } = RCT;
const { defaultDataReqParams } = RCT;
const { dataReqParams, defaultDataReqParams, filterTypes } = RCT;

export default function activeFilters(model) {
export default function activeFilters(model, url) {
const data = model.getCurrentData();
const dataPointer = model.getCurrentDataPointer();
const { fields } = data;
const baseUrl = `/?page=${dataPointer.page}&index=${dataPointer.index}`;
const defaultUrlParams = `${dataReqParams.rowsOnSite}=${defaultDataReqParams.rowsOnSite}&${dataReqParams.site}=${defaultDataReqParams.site}`;

function onClear() {
const isFilterExpression = (item) => Object.values(filterTypes).reduce((acc, curr) => acc || item.includes(curr), false);

const filterField = (filterString) => filterString.split('-')[0];
const filterType = (filterString) => filterString.split('=')[0].split('-')[1];
const filterSearch = (filterString) => {
const rawSearch = decodeURIComponent(filterString.split('=')[1]);
const type = filterType(filterString);
if ((type === filterTypes.exclude || type === filterTypes.match) &&
rawSearch.charAt() === sqlWildCard &&
rawSearch.charAt(rawSearch.length - 1) === sqlWildCard) {
return rawSearch.slice(1, -1);
}
return rawSearch;
};

const filters = url.href.split('&').filter((item) => isFilterExpression(item)).map((item) => ({
field: filterField(item),
type: filterType(item),
search: filterSearch(item),
}));

function onClearAll() {
const firstField = fields.find((f) => f !== undefined && f.name);
const clearUrl = `${baseUrl}&${defaultUrlParams}&sorting=-${firstField.name}`;
model.router.go(clearUrl);
}

function onClearFilter(filter) {
const filterExpressions = url.href.split('&').filter((item) => isFilterExpression(item));
const newUrl = url.href.replace(`&${filterExpressions.filter((item) =>
filterField(item) === filter.field &&
filterType(item) === filter.type &&
filterSearch(item) === filter.search)}`, '');
model.router.go(newUrl);
}

return [
h('div.flex-wrap.justify-between.items-center',
h('div.flex-wrap.justify-between.items-center',
h('h5', 'Active filters'),
h('button.btn.btn-secondary.font-size-small', {
onclick: () => onClear(),
onclick: () => onClearAll(),
}, 'Clear all'))),
h('.flex-wrap.items-center.chips',
h('div.chip.filter-chip.inline',
h('.filter-field.inline', 'name'),
h('.filter-type.inline', 'match'),
h('.filter-input.inline', 'LHC'),
h('.close-10'))),
filters.map((filter) => [
h('div.chip.filter-chip.inline',
h('.filter-field.inline', filter.field),
h('.filter-type.inline', filter.type),
h('.filter-input.inline', filter.search),
h('button.btn.icon-only-button.transparent', {
onclick: () => {
onClearFilter(filter);
},
}, h('.close-10'))),
])),
];
}
46 changes: 26 additions & 20 deletions app/public/views/userView/data/table/filtering/filter.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ const { filterTypes } = RCT;
export default function filter(model) {
const data = model.getCurrentData();
const { fields } = data;
const url = model.router.getUrl();

function onFilteringTypeChange() {
const filteringTypeSelect = document.getElementById('filters-opts-select');
Expand All @@ -32,6 +33,13 @@ export default function filter(model) {
[leftFilterPlaceholder.innerHTML, rightFilterPlaceholder.innerHTML] = types;
}

function clearUserInput() {
document.getElementById('show-options-field').value = '';
document.getElementById('filters-opts-select').value = '';
document.getElementById('left-filter-input').value = '';
document.getElementById('right-filter-input').value = '';
}

function onFilterSubmit() {
const filteringTypeSelect = document.getElementById('filters-opts-select');
const selectedType = filteringTypeSelect.options[filteringTypeSelect.selectedIndex].value;
Expand All @@ -45,33 +53,31 @@ export default function filter(model) {
const leftFilterInput = document.getElementById('left-filter-input').value;
const rightFilterInput = document.getElementById('right-filter-input').value;

// eslint-disable-next-line no-console
console.log({
fieldNameValue,

rightFilterType,
rightFilterInput,

leftFilterType,
leftFilterInput,
});

let filterPhrase = '';
if (selectedType == filterTypes.between) {
// eslint-disable-next-line max-len
filterPhrase += `&${encodeURI(fieldNameValue)}-${encodeURI(filterTypes.between)}=${encodeURI(leftFilterInput)},${encodeURI(rightFilterInput)}`;
const betweenPhrase = `${fieldNameValue}-${selectedType}=${leftFilterInput},${rightFilterInput}`;
const betweenFilterPhrase = `&${encodeURI(betweenPhrase)}`;
if (! url.href.includes(betweenFilterPhrase)) {
filterPhrase += betweenFilterPhrase;
}
} else {
// So Match or Exclude filtering type
// eslint-disable-next-line max-len
filterPhrase += leftFilterInput ? `&${encodeURI(fieldNameValue)}-${encodeURI(leftFilterType)}=${encodeURI(leftFilterInput)}` : '';
filterPhrase += rightFilterInput ? `&${encodeURI(fieldNameValue)}-${encodeURI(rightFilterType)}=${encodeURI(rightFilterInput)}` : '';
const matchPhrase = leftFilterInput ? `${fieldNameValue}-${leftFilterType}=%${leftFilterInput}%` : '';
const matchFilterPhrase = `&${encodeURI(matchPhrase)}`;
console.log(filterPhrase);
if (! url.href.includes(matchFilterPhrase)) {
filterPhrase += matchFilterPhrase;
}

const excludePhrase = rightFilterInput ? `${fieldNameValue}-${rightFilterType}=%${rightFilterInput}%` : '';
const excludeFilterPhrase = `&${encodeURI(excludePhrase)}`;
if (! url.href.includes(excludeFilterPhrase)) {
filterPhrase += excludeFilterPhrase;
}
}

const url = model.router.getUrl();
const newUrl = new URL(`${url.href}${filterPhrase}`);
// eslint-disable-next-line no-console
console.log(newUrl);

clearUserInput();
model.router.go(newUrl);
}

Expand Down
50 changes: 32 additions & 18 deletions app/public/views/userView/data/table/noDataView.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,34 +35,37 @@ const modes = {
waiting: 1,
};

export default function noDataView(
model, dataPointer,
) {
export default function noDataView(model, dataPointer, anyFiltersActive) {
const [mode, setMode] = useState(modes.waiting);

const goBackBtn = h('button.btn.btn-primary.m3', {
onclick: () => model.removeCurrentData(),
}, 'Go back');

const reloadBtn = h('button.btn.btn-primary.m3', {
onclick: async () => {
if (mode() === modes.waiting) {
await model.sync();

/*
* Await model.fetchedData.reqForData(true);
* model.notify();
* document.location.reload(true);
*/
} else {
model.fetchedData.reqForData(true);
}
setMode(modes.requested);
},
}, 'Reload');
const noDataMessage = h('h3', 'No data found');

const clearFiltersBtn = h('button.btn.btn-secondary.m3', {
onclick: () => {
model.goToDefaultPageUrl(dataPointer.page);
},
}, 'Clear filters');

const noDataMessage = h('h3', 'Nothing found');
const noDataExplanation = h('h5', `${
dataPointer.page === pageNames.periods
? 'Please synchronize with outer services'
: 'There is no data to be displayed here'
anyFiltersActive
? 'There is no data that matches your request'
: dataPointer.page === pageNames.periods
? 'Please synchronize with outer services'
: 'There is no data to be displayed here'
}`);

const noPeriodsView = h('.loginDiv.top-100', [
Expand All @@ -79,9 +82,20 @@ export default function noDataView(
goBackBtn,
]);

return dataPointer.page === pageNames.periods
? mode() === modes.requested
? 'loading'
: noPeriodsView
: noDataView;
const noMatchingDataView = h('.loginDiv.top-100', [
h('.nothing-found-90'),
noDataMessage,
noDataExplanation,
h('.flex-row',
clearFiltersBtn,
goBackBtn),
]);

return anyFiltersActive
? noMatchingDataView
: dataPointer.page === pageNames.periods
? mode() === modes.requested
? 'loading'
: noPeriodsView
: noDataView;
}
6 changes: 3 additions & 3 deletions app/public/views/userView/data/table/tablePanel.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ export default function tablePanel(model, runs, detectors) {
const page = model.fetchedData[dataPointer.page];
const { url } = page[dataPointer.index].payload;

const anyFiltersActive = url.href.includes('match') || url.href.includes('exclude') || url.href.includes('from') || url.href.includes('to');
const anyFiltersActive = url.href.includes('match') || url.href.includes('exclude') || url.href.includes('between');
const chips = model.getSubPages(dataPointer.page).filter((index) => index !== defaultIndexString).map((index) => indexChip(model, index));

data.rows = data.rows.filter((item) => item.name != 'null');
Expand Down Expand Up @@ -109,7 +109,7 @@ export default function tablePanel(model, runs, detectors) {

h('div', functionalities(model))),
model.searchFieldsVisible ? filter(model) : '',
anyFiltersActive ? activeFilters(model) : '',
anyFiltersActive ? activeFilters(model, url) : '',

data.rows?.length > 0
? visibleFields.length > 0
Expand All @@ -128,7 +128,7 @@ export default function tablePanel(model, runs, detectors) {
]),
data.rows.length > 15 ? pager(model, data) : ''))
: ''
: noDataView(model, dataPointer),
: noDataView(model, dataPointer, anyFiltersActive),
h('.modal', { id: 'pageSettingsModal' },
h('.modal-content.abs-center.p3', {
id: 'pageSettingsModalContent',
Expand Down