Skip to content

Commit

Permalink
Merge pull request #158 from AliceO2Group/feat/new-frontend-filters
Browse files Browse the repository at this point in the history
New frontend filters
  • Loading branch information
Patrick Hendriks authored Jul 10, 2020
2 parents 0519404 + 6ee1a3b commit 7267d8d
Show file tree
Hide file tree
Showing 15 changed files with 312 additions and 187 deletions.
22 changes: 22 additions & 0 deletions lib/public/components/Filters/author.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.
*/

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

/**
* TODO
* @return {vnode} TODO
*/
const authorFilter = () => h('', 'TODO');

export default authorFilter;
22 changes: 22 additions & 0 deletions lib/public/components/Filters/created.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.
*/

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

/**
* TODO
* @return {vnode} TODO
*/
const createdFilter = () => h('', 'TODO');

export default createdFilter;
91 changes: 22 additions & 69 deletions lib/public/components/Filters/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,80 +12,33 @@
*/

import { h } from '/js/src/index.js';
import { iconMinus, iconPlus } from '/js/src/icons.js';

const FILTERS_LIMIT = 5;

/**
* Radio button to toggle the filter operation
* @param {Object} model Pass the model to access the defined functions
* @return {vnode} Return the form to be shown
*/
const filterOperationRadioButtons = (model) => h('.form-group-header.flex-row', ['AND', 'OR'].map((operation) =>
h('.form-check', {
style: 'margin-right: 0.5rem',
}, [
h('input.form-check-input', {
onclick: () => model.logs.setFilterOperation(operation),
id: `filterOperationRadioButton${operation}`,
checked: operation === model.logs.getFilterOperation(),
type: 'radio',
name: 'operationRadioButtons',
}),
h('label.form-check-label', {
for: `filterOperationRadioButton${operation}`,
}, operation),
])));

/**
* Checkbox filter for a tag
* @param {Object} model Pass the model to access the defined functions
* @param {Array} tags Pass the tags to load in the view
* @return {vnode} Return the form to be shown
*/
const tagCheckboxes = (model, tags) => {
const checkboxes = tags.map((tag, index) => {
const isChecked = model.logs.isTagInFilter(tag.id);
return h('.form-check', [
h('input.form-check-input', {
onclick: () => isChecked ? model.logs.removeFilter(tag.id) : model.logs.addFilter(tag.id),
id: `tagCheckbox${index + 1}`,
type: 'checkbox',
checked: isChecked,
}),
h('label.flex-row.items-center.form-check-label', {
for: `tagCheckbox${index + 1}`,
}, tag.text),
]);
});

if (checkboxes.length <= FILTERS_LIMIT) {
return checkboxes;
} else {
const showMoreFilters = model.logs.shouldShowMoreFilters();
const toggleFilters = h('button.btn.btn-primary.mv1#toggleMoreFilters', {
onclick: () => model.logs.toggleMoreFilters(),
}, ...showMoreFilters ? [iconMinus(), ' Less filters'] : [iconPlus(), ' More filters']);

const slicedCheckboxes = showMoreFilters ? checkboxes : checkboxes.slice(0, FILTERS_LIMIT);
slicedCheckboxes.splice(FILTERS_LIMIT, 0, toggleFilters);

return slicedCheckboxes;
}
};
import { iconChevronBottom, iconChevronRight } from '/js/src/icons.js';

/**
* Render the filters
* @param {Object} model Pass the model to access the defined functions
* @param {Array} tags Pass the tags to load in the view
* @return {vnode} Return final view of the filtering form
* Render a complete filter collection
* @param {Object} model The global model object
* @param {Object} columns The columns representing the table
* @return {vnode} The full collection of filters accessible through dropdowns
*/
const filters = (model, tags) =>
const filters = (model, columns) =>
h('.w-100.shadow-level1.p2', [
h('.f3', 'Filters'),
h('.f4', 'Tags'),
filterOperationRadioButtons(model),
tagCheckboxes(model, tags),
Object.entries(columns).reduce((accumulator, [key, column]) => {
if (column.filter) {
accumulator.push([
h('.flex-row.items-center', {
onclick: () => model.logs.toggleFilterExpanded(key),
id: `${key}FilterToggle`,
style: 'cursor: pointer;',
}, [
h('', model.logs.isFilterExpanded(key) ? iconChevronBottom() : iconChevronRight()),
h('.f4.mh1', column.name),
]),
model.logs.isFilterExpanded(key) && column.filter,
]);
}
return accumulator;
}, []),
]);

export default filters;
82 changes: 82 additions & 0 deletions lib/public/components/Filters/tags.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
/**
* @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 { h } from '/js/src/index.js';
import { iconMinus, iconPlus } from '/js/src/icons.js';

const TAGS_LIMIT = 5;

/**
* Radio button to toggle the filter operation
* @param {Object} model The global model object
* @return {vnode} The filter operation radio button elements
*/
const tagFilterOperationRadioButtons = (model) => h('.form-group-header.flex-row', ['AND', 'OR'].map((operation) =>
h('.form-check', {
style: 'margin-right: 0.5rem',
}, [
h('input.form-check-input', {
onclick: () => model.logs.setTagFilterOperation(operation),
id: `tagFilterOperationRadioButton${operation}`,
checked: operation === model.logs.getTagFilterOperation(),
type: 'radio',
name: 'operationRadioButtons',
}),
h('label.form-check-label', {
for: `tagFilterOperationRadioButton${operation}`,
}, operation),
])));

/**
* Creates checkboxes for the tag filter subcomponent
* @param {Object} model The global model object
* @return {vnode} A collection of checkboxes to toggle table rows by tags
*/
const tagsFilter = (model) => {
const tags = model.tags.getTags().payload;

if (tags) {
const checkboxes = tags.map((tag, index) => {
const isChecked = model.logs.isTagInFilter(tag.id);
return h('.form-check', [
h('input.form-check-input', {
onclick: () => isChecked ? model.logs
.removeTagFromFilter(tag.id) : model.logs.addTagToFilter(tag.id),
id: `tagCheckbox${index + 1}`,
type: 'checkbox',
checked: isChecked,
}),
h('label.flex-row.items-center.form-check-label', {
for: `tagCheckbox${index + 1}`,
}, tag.text),
]);
});

if (checkboxes.length <= TAGS_LIMIT) {
return [tagFilterOperationRadioButtons(model), ...checkboxes];
} else {
const showMoreFilters = model.logs.shouldShowMoreTags();
const toggleFilters = h('button.btn.btn-primary.mv1#toggleMoreTags', {
onclick: () => model.logs.toggleMoreTags(),
}, ...showMoreFilters ? [iconMinus(), ' Less tags'] : [iconPlus(), ' More tags']);

const slicedCheckboxes = showMoreFilters ? checkboxes : checkboxes.slice(0, TAGS_LIMIT);
slicedCheckboxes.splice(TAGS_LIMIT, 0, toggleFilters);

return [tagFilterOperationRadioButtons(model), ...slicedCheckboxes];
}
}
return null;
};

export default tagsFilter;
22 changes: 22 additions & 0 deletions lib/public/components/Filters/title.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.
*/

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

/**
* TODO
* @return {vnode} TODO
*/
const titleFilter = () => h('', 'TODO');

export default titleFilter;
2 changes: 1 addition & 1 deletion lib/public/components/Pagination/amountSelector.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ const mapAmounts = (onclick, amounts) =>
*/
const amountSelector = (onclickDropdown, onclickAmount, dropdownVisible, amounts, itemsPerPage) =>
h(`.dropdown${dropdownVisible ? '.dropdown-open' : ''}#amountSelector`, [
h('button.btn', { onclick: onclickDropdown }, `Amount per page: ${itemsPerPage} `, iconCaretBottom()),
h('button.btn', { onclick: onclickDropdown }, `Rows per page: ${itemsPerPage} `, iconCaretBottom()),
h('.dropdown-menu', mapAmounts(onclickAmount, amounts)),
]);

Expand Down
10 changes: 7 additions & 3 deletions lib/public/components/Table/content.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ const row = (value, text, rowId, model) => {
h(`#${columnId}-${!isExpanded ? 'plus' : 'minus'}.${isExpanded ? 'danger' : 'primary'}`, {
onclick: (e) => {
e.stopPropagation();
model.logs.toggleCollapse(rowId, value.name);
model.logs.toggleColumnCollapse(rowId, value.name);
},
}, isExpanded
? h('.collapse-button', iconMinus())
Expand All @@ -73,8 +73,12 @@ const content = (data, keys, params, model) => {

return h('tbody', data.map((entry) => {
const rowId = `row${entry[idKey]}`;
return h(`tr#${rowId}`, params(entry), Object.entries(keys)
.map(([key, value]) => row(value, entry[key], rowId, model)));
return h(`tr#${rowId}`, params(entry), Object.entries(keys).reduce((accumulator, [key, value]) => {
if (value.visible) {
accumulator.push(row(value, entry[key], rowId, model));
}
return accumulator;
}, []));
}));
};

Expand Down
11 changes: 7 additions & 4 deletions lib/public/components/Table/headers.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,12 @@ import { h } from '/js/src/index.js';
* @param {Object} keys The full collection of API keys and their corresponding header values
* @return {vnode} An array of rows containing all given header values with specific cell sizes
*/
const headers = (keys) => h('thead', h('tr', Object.values(keys).map((value) => {
const size = value.size || 'cell-m';
return h(`th.${size}`, { scope: 'col' }, value.name);
})));
const headers = (keys) => h('thead', h('tr', Object.values(keys).reduce((accumulator, value) => {
if (value.visible) {
const size = value.size || 'cell-m';
accumulator.push(h(`th.${size}`, { scope: 'col' }, value.name));
}
return accumulator;
}, [])));

export default headers;
24 changes: 4 additions & 20 deletions lib/public/components/Table/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,19 +15,6 @@ import { h } from '/js/src/index.js';
import headers from './headers.js';
import content from './content.js';

/**
* Selectively removes the API keys based on their visibility value
* @param {Object} keys The full collection of API keys and their corresponding header values
* @returns {Object} A filtered collection of keys based on visibility
*/
const filterKeysByVisibility = (keys) => {
Object.entries(keys).forEach(([key, value]) => {
if (!value.visible) {
delete keys[key];
}
});
};

/**
* Renders the table
* @param {Array} data An object array, with every object representing a to be rendered row
Expand All @@ -36,12 +23,9 @@ const filterKeysByVisibility = (keys) => {
* @param {Object} model The global model object
* @returns {vnode} Return the total view of the table to rendered
*/
const table = (data, keys, params = () => null, model) => {
filterKeysByVisibility(keys);
return h('table.table.table-hover.shadow-level1', [
headers(keys),
content(data, keys, params, model),
]);
};
const table = (data, keys, params = () => null, model) => h('table.table.table-hover.shadow-level1', [
headers(keys),
content(data, keys, params, model),
]);

export default table;
Loading

0 comments on commit 7267d8d

Please sign in to comment.