Skip to content

Commit bbd7a8e

Browse files
committed
Factorize checkboxes/radio display
1 parent cba4b81 commit bbd7a8e

File tree

6 files changed

+89
-81
lines changed

6 files changed

+89
-81
lines changed

lib/public/components/Filters/RunsFilter/runDefinitionFilter.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,15 @@
1111
* or submit itself to any jurisdiction.
1212
*/
1313

14-
import { checkboxes } from '../common/filters/checkboxFilter.js';
14+
import { expandedSelectionFilter } from '../common/filters/checkboxFilter.js';
1515

1616
/**
1717
* Renders a list of checkboxes that lets the user look for runs with specific definition
1818
*
1919
* @param {RunDefinitionFilterModel} runDefinitionFilterModel run definition filter model
2020
* @return {Component} the filter
2121
*/
22-
export const runDefinitionFilter = (runDefinitionFilterModel) => checkboxes(
22+
export const runDefinitionFilter = (runDefinitionFilterModel) => expandedSelectionFilter(
2323
runDefinitionFilterModel.selectionModel,
2424
{ selector: 'run-definition' },
2525
);

lib/public/components/Filters/RunsFilter/runQualitiesFilter.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,12 @@
1111
* or submit itself to any jurisdiction.
1212
*/
1313

14-
import { checkboxes } from '../common/filters/checkboxFilter.js';
14+
import { expandedSelectionFilter } from '../common/filters/checkboxFilter.js';
1515

1616
/**
1717
* Renders a list of checkboxes that lets the user look for runs with specific quality
1818
*
1919
* @param {SelectionFilterModel} filterModel run quality filter model
2020
* @return {Component} the filter component
2121
*/
22-
export const runQualitiesFilter = (filterModel) => checkboxes(filterModel.selectionModel);
22+
export const runQualitiesFilter = (filterModel) => expandedSelectionFilter(filterModel.selectionModel);

lib/public/components/Filters/common/filters/checkboxFilter.js

Lines changed: 5 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
*/
1414

1515
import { h } from '/js/src/index.js';
16+
import { selectionOptions } from '../../../common/selection/selectionOptions.js';
1617

1718
/**
1819
* A general component for generating checkboxes.
@@ -47,19 +48,7 @@ export const checkboxFilter = (name, values, isChecked, onChange, additionalProp
4748
* @param {string} [additionalProperties.selector] input identifiers prefix
4849
* @return {Component} filter component
4950
*/
50-
export const checkboxes = (selectionModel, additionalProperties = {}) => {
51-
const { selector = 'checkboxes' } = additionalProperties;
52-
53-
return h('.flex-row.flex-wrap', selectionModel.options.map((option) => h('.form-check.flex-grow', [
54-
h('input.form-check-input', {
55-
id: `${selector}-checkbox-${option.value}`,
56-
type: 'checkbox',
57-
checked: selectionModel.isSelected(option),
58-
onchange: () => selectionModel.isSelected(option) ? selectionModel.deselect(option) : selectionModel.select(option),
59-
...additionalProperties,
60-
}),
61-
h('label.form-check-label', {
62-
for: `${selector}-checkbox-${option.value}`,
63-
}, option.label || option.value),
64-
])));
65-
};
51+
export const expandedSelectionFilter = (selectionModel, additionalProperties = {}) => h(
52+
'.flex-row.flex-wrap.gc3',
53+
selectionOptions(selectionModel, { selectorPrefix: additionalProperties.selector }),
54+
);

lib/public/components/common/selection/dropdown/selectionDropdown.js

Lines changed: 13 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -15,64 +15,7 @@ import { h, Observable } from '/js/src/index.js';
1515
import spinner from '../../spinner.js';
1616
import { cleanPrefix } from '../../../../utilities/cleanPrefix.js';
1717
import { dropdown } from '../../popover/dropdown.js';
18-
import { filterSelectionOptions } from '../filterSelectionOptions.js';
19-
20-
/**
21-
* Display the dropdown options component containing the search input ahd the available options
22-
*
23-
* @param {SelectionModel} selectionModel the selection model
24-
* @param {string} filter eventual filter used to show only a subset of options
25-
* @param {string} selectorPrefix the prefix used to generate DOM selectors
26-
* @return {Component} the dropdown options component
27-
*/
28-
const filteredDropdownOptions = (selectionModel, filter, selectorPrefix) => {
29-
/**
30-
* Display a given option
31-
*
32-
* @param {SelectionOption} option the option to display
33-
* @param {string} [selectorPrefix] prefix used to generate DOM selectors for the component
34-
* @return {Component} the option's view
35-
*/
36-
const displayOption = (option, selectorPrefix) => {
37-
const selector = option.selector ?? option.value;
38-
39-
return h(
40-
'label.dropdown-option.form-check-label.flex-row.g2.ph2.pv1',
41-
{ key: selector },
42-
[
43-
h(
44-
`input#${selectorPrefix}dropdown-option-${selector}`,
45-
{
46-
type: selectionModel.multiple || selectionModel.allowEmpty ? 'checkbox' : 'radio',
47-
name: `${selectorPrefix}dropdown-option-${selectionModel.multiple ? selector : 'group'}`,
48-
checked: selectionModel.isSelected(option),
49-
onchange: (e) => e.target.checked ? selectionModel.select(option) : selectionModel.deselect(option),
50-
},
51-
),
52-
option.label || option.value,
53-
],
54-
);
55-
};
56-
57-
/**
58-
* Displays the list of available options
59-
*
60-
* @param {SelectionOption[]} availableOptions the list of all the available options
61-
* @return {Component} the options list
62-
*/
63-
const optionsList = (availableOptions) => {
64-
if (availableOptions.length === 0) {
65-
return h('.ph2.pv1', h('em', 'No options'));
66-
}
67-
68-
return availableOptions.map((option) => displayOption(
69-
option,
70-
selectorPrefix,
71-
));
72-
};
73-
74-
return h('.dropdown-options', optionsList(filterSelectionOptions(selectionModel.options, filter)));
75-
};
18+
import { selectionOptions } from '../selectionOptions.js';
7619

7720
/**
7821
* Display a selection component composed of a view of current selection plus a dropdown displaying available options
@@ -151,7 +94,18 @@ export const selectionDropdown = (selectionDropdownModel, configuration) => {
15194
selectionDropdownModel.selectionModel.match({
15295
NotAsked: () => null,
15396
Loading: () => spinner({ size: 2, absolute: false }),
154-
Success: (selectionModel) => filteredDropdownOptions(selectionModel, selectionDropdownModel.searchInputContent, selectorPrefix),
97+
Success: (selectionModel) => h(
98+
'.dropdown-options',
99+
selectionOptions(
100+
selectionModel,
101+
{
102+
filter: selectionDropdownModel.searchInputContent,
103+
placeholder: h('.ph2.pv1', h('em', 'No options')),
104+
selectorPrefix,
105+
labelClasses: ['dropdown-option', 'ph2', 'pv1'],
106+
},
107+
),
108+
),
155109
Failure: () => null,
156110
}),
157111
],
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
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+
import { cleanPrefix } from '../../../utilities/cleanPrefix.js';
15+
import { filterSelectionOptions } from './filterSelectionOptions.js';
16+
import { h } from '/js/src/index.js';
17+
18+
/**
19+
* Display the options of the given selection model
20+
*
21+
* @param {SelectionModel} selectionModel the selection model
22+
* @param {object} [configuration] eventual configuration
23+
* @param {string} [configuration.filter] if specified, only options with label (or value if no label) including this filter will be displayed
24+
* @param {Component} [configuration.placeholder] if specified, this component will be returned if there is no option to display
25+
* @param {string} [configuration.selectorPrefix] prefix to be used to construct elements selectors
26+
* @param {string[]} [configuration.labelClasses] additional classes applied to label
27+
* @return {Component} filter component
28+
*/
29+
export const selectionOptions = (selectionModel, configuration) => {
30+
const { filter, placeholder = null, selectorPrefix, labelClasses: additionalLabelClasses = [] } = configuration || {};
31+
32+
const options = filterSelectionOptions(selectionModel.options, filter);
33+
34+
if (options.length === 0) {
35+
return placeholder;
36+
}
37+
38+
return options.map((option) => {
39+
const selector = option.selector ?? option.value;
40+
41+
const uniqueSelector = `${cleanPrefix(selectorPrefix)}option-${selector}`;
42+
43+
const labelClasses = ['form-check-label', 'flex-row', 'g2', ...additionalLabelClasses];
44+
45+
return h(
46+
`label.${labelClasses.join('.')}`,
47+
{ key: uniqueSelector },
48+
[
49+
h(
50+
`input#${uniqueSelector}`,
51+
{
52+
id: uniqueSelector,
53+
type: selectionModel.multiple || selectionModel.allowEmpty ? 'checkbox' : 'radio',
54+
name: selectionModel.multiple || selectionModel.allowEmpty
55+
? uniqueSelector
56+
: `${cleanPrefix(selectorPrefix)}option-group`,
57+
checked: selectionModel.isSelected(option),
58+
onchange: () => selectionModel.isSelected(option) ? selectionModel.deselect(option) : selectionModel.select(option),
59+
},
60+
),
61+
option.label || option.value,
62+
],
63+
);
64+
});
65+
};

lib/public/views/QcFlagTypes/ActiveColumns/qcFlagTypesActiveColumns.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
import { h } from '/js/src/index.js';
1515
import { formatTimestamp } from '../../../utilities/formatting/formatTimestamp.js';
1616
import { textFilter } from '../../../components/Filters/common/filters/textFilter.js';
17-
import { checkboxes } from '../../../components/Filters/common/filters/checkboxFilter.js';
17+
import { expandedSelectionFilter } from '../../../components/Filters/common/filters/checkboxFilter.js';
1818
import { qcFlagTypeColoredBadge } from '../../../components/qcFlags/qcFlagTypeColoredBadge.js';
1919

2020
/**
@@ -54,7 +54,7 @@ export const qcFlagTypesActiveColumns = {
5454
name: 'Bad',
5555
visible: true,
5656
sortable: true,
57-
filter: ({ isBadFilterModel }) => checkboxes(
57+
filter: ({ isBadFilterModel }) => expandedSelectionFilter(
5858
isBadFilterModel,
5959
{ class: 'w-75 mt1', selector: 'qc-flag-type-bad-filter' },
6060
),

0 commit comments

Comments
 (0)