Skip to content

Commit

Permalink
fix(ui): filter limiting now working properly
Browse files Browse the repository at this point in the history
  • Loading branch information
MauritsioRK authored May 18, 2020
1 parent 639c74c commit e139aef
Show file tree
Hide file tree
Showing 6 changed files with 143 additions and 25 deletions.
28 changes: 28 additions & 0 deletions lib/database/seeders/20200517151947-more-tags.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/**
* @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.
*/

module.exports = {
up: (queryInterface, _Sequelize) => queryInterface.bulkInsert('tags', [
{
text: 'GLOBAL',
},
{
text: 'TEST',
},
{
text: 'OTHER',
},
]),

down: (queryInterface, _Sequelize) => queryInterface.bulkDelete('tags', null, {}),
};
35 changes: 35 additions & 0 deletions lib/database/seeders/20200517152010-link-more-tags.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/**
* @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.
*/

module.exports = {
up: (queryInterface, _Sequelize) => queryInterface.bulkInsert('log_tags', [
{
log_id: 1,
tag_id: 3,
},
{
log_id: 3,
tag_id: 4,
},
{
log_id: 2,
tag_id: 5,
},
{
log_id: 3,
tag_id: 6,
},
]),

down: (queryInterface, _Sequelize) => queryInterface.bulkDelete('log_tags', null, {}),
};
42 changes: 22 additions & 20 deletions lib/public/components/Filters/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@
* or submit itself to any jurisdiction.
*/
import { h } from '/js/src/index.js';
import { iconMinus, iconPlus } from '/js/src/icons.js';

const FILTERS_LIMITS = 5;
const FILTERS_LIMIT = 5;

/**
* Checkbox filter
Expand All @@ -21,33 +22,34 @@ const FILTERS_LIMITS = 5;
* @return {vnode} Return the form to be shown
*/
const checkboxFilter = (model, tags) => {
const checkboxes = Object.entries(tags).map(([tag, count], index) =>
h('.form-check', [
const checkboxes = Object.entries(tags).map(([tag, count], index) => {
const isChecked = model.logs.isTagInFilterCriteria(tag);
return h('.form-check', [
h('input.form-check-input', {
onclick: (e) => {
const isChecked = e.target.checked;
!isChecked
? model.logs.removeFilter(tag)
: model.logs.addFilter(tag);
},
onclick: () => isChecked ? model.logs.removeFilter(tag) : model.logs.addFilter(tag),
id: `filtersCheckbox${index + 1}`,
type: 'checkbox',
checked: isChecked,
}),
h('label.flex-row.items-center.form-check-label', {
for: `filtersCheckbox${index + 1}`,
}, tag, h('.f7.mh1.gray-darker', `(${count})`)),
]));
]);
});

return checkboxes.length > FILTERS_LIMITS
? h('.form-group', [
...checkboxes.slice(0, FILTERS_LIMITS),
h('button.btn.btn-primary.mv1', {
// eslint-disable-next-line no-console
onclick: () => console.log('TODO'),
}, 'Meer opties'),
...checkboxes.slice(FILTERS_LIMITS),
])
: h('.form-group', checkboxes);
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;
}
};

/**
Expand Down
2 changes: 1 addition & 1 deletion lib/public/views/Logs/Details/page.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import PostBox from '../../../components/Post/index.js';
*/
const logDetailScreen = (model) => {
const data = model.logs.getData();
const error = model.logs.didErrorOccur();
const error = model.logs.hasErrorOccured();

if (data && data.length !== 0) {
const id = parseInt(model.router.params.id, 10);
Expand Down
35 changes: 31 additions & 4 deletions lib/public/views/Logs/Logs.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export default class Overview extends Observable {
this.filterCriteria = [];
this.data = [];
this.filteredData = [];
this.moreFilters = false;
this.error = false;
}

Expand Down Expand Up @@ -81,10 +82,18 @@ export default class Overview extends Observable {
}

/**
* Indicates if there was an error during log fetching
* Getter for filter criteria
* @returns {Boolean} Returns if more filters should be shown above the predefined limit
*/
shouldShowMoreFilters() {
return this.moreFilters;
}

/**
* Getter for error occurence
* @returns {Boolean} Returns if an error occured during log fetching
*/
didErrorOccur() {
hasErrorOccured() {
return this.error;
}

Expand Down Expand Up @@ -125,15 +134,15 @@ export default class Overview extends Observable {
* @returns {Array} Sets the filtered data on the criteria applied by the user
*/
filterByTags() {
this.filteredData = this.data.filter((entry) => this.checkExistingTag(entry));
this.filteredData = this.data.filter((entry) => this.hasExistingTag(entry));
}

/**
* Check for an existing tag
* @param {Object} entry The entry in the total array of the data
* @return {Boolean} Returns the status of the existence of a tag in the data entry
*/
checkExistingTag(entry) {
hasExistingTag(entry) {
return this.filterCriteria.filter((tag) => entry.tags.filter(({ text }) => tag === text).length > 0).length > 0;
}

Expand All @@ -149,4 +158,22 @@ export default class Overview extends Observable {
return accumulator;
}, {});
}

/**
* Checks if a tag is already defined within the user's filter criteria
* @param {String} tag The tag to check on
* @return {Boolean} Whether the tag is in the user's filter criteria
*/
isTagInFilterCriteria(tag) {
return this.filterCriteria.includes(tag);
}

/**
* Toggles the visibility of tag filters above the predefined limit
* @return {Boolean} Whether the extra filters should be shown
*/
toggleMoreFilters() {
this.moreFilters = !this.moreFilters;
this.notify();
}
}
26 changes: 26 additions & 0 deletions test/public/logs/overview.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,32 @@ module.exports = function () {
expect(unfilteredRows.length - 1).to.equal(numberOfRows);
});

it('can show and hide extra filters if available', async () => {
const FILTERS_LIMIT = 5;
const buttonId = '#toggleMoreFilters';

// Expect the page to have a button allowing for showing more filters
const toggleFiltersButton = await page.$(buttonId);
let buttonText = await page.evaluate((element) => element.innerText, toggleFiltersButton);
expect(buttonText.trim()).to.equal('More filters');

// Expect the button to show at least one extra filter when clicked
await page.click(buttonId);
await page.waitFor(100);
let extraFilter = await page.$(`#filtersCheckbox${FILTERS_LIMIT + 1}`);
expect(Boolean(extraFilter)).to.be.true;

// Expect the text to change to reflect the newly shown filters
buttonText = await page.evaluate((element) => element.innerText, toggleFiltersButton);
expect(buttonText.trim()).to.equal('Less filters');

// Expect the button to remove the extra filter when clicked again
await page.click(buttonId);
await page.waitFor(100);
extraFilter = await page.$(`#filtersCheckbox${FILTERS_LIMIT + 1}`);
expect(Boolean(extraFilter)).to.be.false;
});

it('shows correct datatypes in respective columns', async () => {
table = await page.$$('tr');
firstRowId = await findRowById(table, page);
Expand Down

0 comments on commit e139aef

Please sign in to comment.