Skip to content

Commit e139aef

Browse files
authored
fix(ui): filter limiting now working properly
1 parent 639c74c commit e139aef

6 files changed

Lines changed: 143 additions & 25 deletions

File tree

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/**
2+
* @license
3+
* Copyright CERN and copyright holders of ALICE O2. This software is
4+
* distributed under the terms of the GNU General Public License v3 (GPL
5+
* Version 3), copied verbatim in the file "COPYING".
6+
*
7+
* See http://alice-o2.web.cern.ch/license for full licensing information.
8+
*
9+
* In applying this license CERN does not waive the privileges and immunities
10+
* granted to it by virtue of its status as an Intergovernmental Organization
11+
* or submit itself to any jurisdiction.
12+
*/
13+
14+
module.exports = {
15+
up: (queryInterface, _Sequelize) => queryInterface.bulkInsert('tags', [
16+
{
17+
text: 'GLOBAL',
18+
},
19+
{
20+
text: 'TEST',
21+
},
22+
{
23+
text: 'OTHER',
24+
},
25+
]),
26+
27+
down: (queryInterface, _Sequelize) => queryInterface.bulkDelete('tags', null, {}),
28+
};
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/**
2+
* @license
3+
* Copyright CERN and copyright holders of ALICE O2. This software is
4+
* distributed under the terms of the GNU General Public License v3 (GPL
5+
* Version 3), copied verbatim in the file "COPYING".
6+
*
7+
* See http://alice-o2.web.cern.ch/license for full licensing information.
8+
*
9+
* In applying this license CERN does not waive the privileges and immunities
10+
* granted to it by virtue of its status as an Intergovernmental Organization
11+
* or submit itself to any jurisdiction.
12+
*/
13+
14+
module.exports = {
15+
up: (queryInterface, _Sequelize) => queryInterface.bulkInsert('log_tags', [
16+
{
17+
log_id: 1,
18+
tag_id: 3,
19+
},
20+
{
21+
log_id: 3,
22+
tag_id: 4,
23+
},
24+
{
25+
log_id: 2,
26+
tag_id: 5,
27+
},
28+
{
29+
log_id: 3,
30+
tag_id: 6,
31+
},
32+
]),
33+
34+
down: (queryInterface, _Sequelize) => queryInterface.bulkDelete('log_tags', null, {}),
35+
};

lib/public/components/Filters/index.js

Lines changed: 22 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,9 @@
1111
* or submit itself to any jurisdiction.
1212
*/
1313
import { h } from '/js/src/index.js';
14+
import { iconMinus, iconPlus } from '/js/src/icons.js';
1415

15-
const FILTERS_LIMITS = 5;
16+
const FILTERS_LIMIT = 5;
1617

1718
/**
1819
* Checkbox filter
@@ -21,33 +22,34 @@ const FILTERS_LIMITS = 5;
2122
* @return {vnode} Return the form to be shown
2223
*/
2324
const checkboxFilter = (model, tags) => {
24-
const checkboxes = Object.entries(tags).map(([tag, count], index) =>
25-
h('.form-check', [
25+
const checkboxes = Object.entries(tags).map(([tag, count], index) => {
26+
const isChecked = model.logs.isTagInFilterCriteria(tag);
27+
return h('.form-check', [
2628
h('input.form-check-input', {
27-
onclick: (e) => {
28-
const isChecked = e.target.checked;
29-
!isChecked
30-
? model.logs.removeFilter(tag)
31-
: model.logs.addFilter(tag);
32-
},
29+
onclick: () => isChecked ? model.logs.removeFilter(tag) : model.logs.addFilter(tag),
3330
id: `filtersCheckbox${index + 1}`,
3431
type: 'checkbox',
32+
checked: isChecked,
3533
}),
3634
h('label.flex-row.items-center.form-check-label', {
3735
for: `filtersCheckbox${index + 1}`,
3836
}, tag, h('.f7.mh1.gray-darker', `(${count})`)),
39-
]));
37+
]);
38+
});
4039

41-
return checkboxes.length > FILTERS_LIMITS
42-
? h('.form-group', [
43-
...checkboxes.slice(0, FILTERS_LIMITS),
44-
h('button.btn.btn-primary.mv1', {
45-
// eslint-disable-next-line no-console
46-
onclick: () => console.log('TODO'),
47-
}, 'Meer opties'),
48-
...checkboxes.slice(FILTERS_LIMITS),
49-
])
50-
: h('.form-group', checkboxes);
40+
if (checkboxes.length <= FILTERS_LIMIT) {
41+
return checkboxes;
42+
} else {
43+
const showMoreFilters = model.logs.shouldShowMoreFilters();
44+
const toggleFilters = h('button.btn.btn-primary.mv1#toggleMoreFilters', {
45+
onclick: () => model.logs.toggleMoreFilters(),
46+
}, ...showMoreFilters ? [iconMinus(), ' Less filters'] : [iconPlus(), ' More filters']);
47+
48+
const slicedCheckboxes = showMoreFilters ? checkboxes : checkboxes.slice(0, FILTERS_LIMIT);
49+
slicedCheckboxes.splice(FILTERS_LIMIT, 0, toggleFilters);
50+
51+
return slicedCheckboxes;
52+
}
5153
};
5254

5355
/**

lib/public/views/Logs/Details/page.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import PostBox from '../../../components/Post/index.js';
2020
*/
2121
const logDetailScreen = (model) => {
2222
const data = model.logs.getData();
23-
const error = model.logs.didErrorOccur();
23+
const error = model.logs.hasErrorOccured();
2424

2525
if (data && data.length !== 0) {
2626
const id = parseInt(model.router.params.id, 10);

lib/public/views/Logs/Logs.js

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ export default class Overview extends Observable {
2727
this.filterCriteria = [];
2828
this.data = [];
2929
this.filteredData = [];
30+
this.moreFilters = false;
3031
this.error = false;
3132
}
3233

@@ -81,10 +82,18 @@ export default class Overview extends Observable {
8182
}
8283

8384
/**
84-
* Indicates if there was an error during log fetching
85+
* Getter for filter criteria
86+
* @returns {Boolean} Returns if more filters should be shown above the predefined limit
87+
*/
88+
shouldShowMoreFilters() {
89+
return this.moreFilters;
90+
}
91+
92+
/**
93+
* Getter for error occurence
8594
* @returns {Boolean} Returns if an error occured during log fetching
8695
*/
87-
didErrorOccur() {
96+
hasErrorOccured() {
8897
return this.error;
8998
}
9099

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

131140
/**
132141
* Check for an existing tag
133142
* @param {Object} entry The entry in the total array of the data
134143
* @return {Boolean} Returns the status of the existence of a tag in the data entry
135144
*/
136-
checkExistingTag(entry) {
145+
hasExistingTag(entry) {
137146
return this.filterCriteria.filter((tag) => entry.tags.filter(({ text }) => tag === text).length > 0).length > 0;
138147
}
139148

@@ -149,4 +158,22 @@ export default class Overview extends Observable {
149158
return accumulator;
150159
}, {});
151160
}
161+
162+
/**
163+
* Checks if a tag is already defined within the user's filter criteria
164+
* @param {String} tag The tag to check on
165+
* @return {Boolean} Whether the tag is in the user's filter criteria
166+
*/
167+
isTagInFilterCriteria(tag) {
168+
return this.filterCriteria.includes(tag);
169+
}
170+
171+
/**
172+
* Toggles the visibility of tag filters above the predefined limit
173+
* @return {Boolean} Whether the extra filters should be shown
174+
*/
175+
toggleMoreFilters() {
176+
this.moreFilters = !this.moreFilters;
177+
this.notify();
178+
}
152179
}

test/public/logs/overview.test.js

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,32 @@ module.exports = function () {
113113
expect(unfilteredRows.length - 1).to.equal(numberOfRows);
114114
});
115115

116+
it('can show and hide extra filters if available', async () => {
117+
const FILTERS_LIMIT = 5;
118+
const buttonId = '#toggleMoreFilters';
119+
120+
// Expect the page to have a button allowing for showing more filters
121+
const toggleFiltersButton = await page.$(buttonId);
122+
let buttonText = await page.evaluate((element) => element.innerText, toggleFiltersButton);
123+
expect(buttonText.trim()).to.equal('More filters');
124+
125+
// Expect the button to show at least one extra filter when clicked
126+
await page.click(buttonId);
127+
await page.waitFor(100);
128+
let extraFilter = await page.$(`#filtersCheckbox${FILTERS_LIMIT + 1}`);
129+
expect(Boolean(extraFilter)).to.be.true;
130+
131+
// Expect the text to change to reflect the newly shown filters
132+
buttonText = await page.evaluate((element) => element.innerText, toggleFiltersButton);
133+
expect(buttonText.trim()).to.equal('Less filters');
134+
135+
// Expect the button to remove the extra filter when clicked again
136+
await page.click(buttonId);
137+
await page.waitFor(100);
138+
extraFilter = await page.$(`#filtersCheckbox${FILTERS_LIMIT + 1}`);
139+
expect(Boolean(extraFilter)).to.be.false;
140+
});
141+
116142
it('shows correct datatypes in respective columns', async () => {
117143
table = await page.$$('tr');
118144
firstRowId = await findRowById(table, page);

0 commit comments

Comments
 (0)