Skip to content

Commit

Permalink
Use ToggleableModel for filter panel visibility
Browse files Browse the repository at this point in the history
  • Loading branch information
martinboulais committed Mar 1, 2023
1 parent f6e1372 commit 559a29f
Show file tree
Hide file tree
Showing 10 changed files with 104 additions and 118 deletions.
44 changes: 18 additions & 26 deletions lib/public/components/Filters/common/filtersPanel.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@
* or submit itself to any jurisdiction.
*/

import { taggedEventRegistry } from '../../../utilities/taggedEventRegistry.js';
import { FILTER_PANEL_CLICK_TAG } from '../filtersConstants.js';
import { h } from '/js/src/index.js';

/**
Expand All @@ -26,27 +24,21 @@ import { h } from '/js/src/index.js';
*
* @return {vnode} the filters panel
*/
export const filtersPanel = (globalModel, filteringModel, columns) => h(
`.w-25.filters${filteringModel.areFiltersVisible ? '.display-block' : '.display-none'}`,
{
onclick: (e) => taggedEventRegistry.tagEvent(e, FILTER_PANEL_CLICK_TAG),
},
h('.w-100.shadow-level1.br2', [
h('.f4.ph2', 'Filters'),
Object.values(columns).reduce((accumulator, column) => {
if (column.filter) {
accumulator.push([
h('.flex-row.items-baseline.ph3.pv1', [
h('.w-30.f5', column.name),
h('.w-70', typeof column.filter === 'function' ? column.filter(filteringModel, globalModel) : column.filter),
]),
]);
}
return accumulator;
}, []),
h('.p2', h('button.btn.btn-danger.mt2', {
disabled: !filteringModel.isAnyFilterActive(),
onclick: () => filteringModel.reset(),
}, 'Reset all filters')),
]),
);
export const filtersPanel = (globalModel, filteringModel, columns) => h('.w-100.shadow-level1.br2', [
h('.f4.ph2', 'Filters'),
Object.values(columns).reduce((accumulator, column) => {
if (column.filter) {
accumulator.push([
h('.flex-row.items-baseline.ph3.pv1', [
h('.w-30.f5', column.name),
h('.w-70', typeof column.filter === 'function' ? column.filter(filteringModel, globalModel) : column.filter),
]),
]);
}
return accumulator;
}, []),
h('.p2', h('button.btn.btn-danger.mt2', {
disabled: !filteringModel.isAnyFilterActive(),
onclick: () => filteringModel.reset(),
}, 'Reset all filters')),
]);
13 changes: 6 additions & 7 deletions lib/public/components/Filters/common/filtersToggleButton.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,18 @@
*/

import { taggedEventRegistry } from '../../../utilities/taggedEventRegistry.js';
import { FILTER_PANEL_CLICK_TAG } from '../filtersConstants.js';
import { h } from '/js/src/index.js';

/**
* Return a button to show/hide a filters panel
*
* @param {Object} filteringModel the model handling the filters state
* @param {ToggleableModel} toggleableModel the model handling the filters visibility
*
* @return {vnode} the component to display
* @return {Component} the component to display
*/
export const filtersToggleButton = (filteringModel) => h('button#openFilterToggle.btn.btn.btn-primary', {
export const filtersToggleButton = (toggleableModel) => h('button#openFilterToggle.btn.btn.btn-primary', {
onclick: (e) => {
filteringModel.toggleFiltersVisibility();
taggedEventRegistry.tagEvent(e, FILTER_PANEL_CLICK_TAG);
toggleableModel.toggle();
taggedEventRegistry.tagEvent(e, toggleableModel.closeEventTag);
},
}, `${filteringModel.areFiltersVisible ? 'Close' : 'Open'} filters`);
}, `${toggleableModel.isVisible ? 'Close' : 'Open'} filters`);
14 changes: 0 additions & 14 deletions lib/public/components/Filters/filtersConstants.js

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export class SelectionDropdownModel extends SelectionModel {
*/
constructor(availableOptions, defaultSelection = []) {
super({ availableOptions, defaultSelection });
this._toggleModel = new ToggleableModel(OPEN_BY_DEFAULT);
this._toggleModel = new ToggleableModel({ isVisible: OPEN_BY_DEFAULT });
this._defaultSelection = defaultSelection;
this._searchInputContent = '';

Expand Down
28 changes: 26 additions & 2 deletions lib/public/components/common/toggle/TogglableModel.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,18 @@ export class ToggleableModel extends Observable {
/**
* Constructor
*
* @param {boolean} [isVisible=false] default visibility of the element
* @param {configuration} [configuration] optionally model configuration
* @param {boolean} [configuration.isVisible=false] default visibility of the element
* @param {boolean} [configuration.hideOnEscape] if true, the visibility must be switched to off when escape key is pressed
*/
constructor(isVisible = false) {
constructor(configuration) {
super();
const { isVisible = false, hideOnEscape = true } = configuration || {};

this._isVisible = isVisible;
this._closeEventTag = OPEN_DROPDOWN_EVENT_TAG + getUniqueId();

this._hideOnEscape = hideOnEscape;
}

/**
Expand All @@ -48,6 +54,24 @@ export class ToggleableModel extends Observable {
this.notify();
}

/**
* States if the toggleable element must be hidden when escape key is pressed
*
* @return {boolean} true to hide the element on escape press
*/
get hideOnEscape() {
return this._hideOnEscape;
}

/**
* Toggle the visibility
* @returns {void }
*/
toggle() {
this._isVisible = !this._isVisible;
this.notify();
}

/**
* Returns the current visibility of the element
*
Expand Down
9 changes: 7 additions & 2 deletions lib/public/components/common/toggle/toggleContainer.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,13 @@ import { h } from '/js/src/index.js';
*/
export const toggleContainer = (toggleModel, content, attributes) => {
attributes = attributes || {};
if (!attributes.class) {
attributes.class = '';
}
attributes.class += ' toggle-container';

return h(
'.toggle-container',
'',
{
...attributes,
// eslint-disable-next-line require-jsdoc
Expand All @@ -39,7 +44,7 @@ export const toggleContainer = (toggleModel, content, attributes) => {
this.hideToggleable();
}, toggleModel.closeEventTag);

this.hideDropdownOnEscape = (e) => e.key === 'Escape' && toggleModel.hide();
this.hideDropdownOnEscape = (e) => toggleModel.hideOnEscape && e.key === 'Escape' && toggleModel.hide();
window.addEventListener('keyup', this.hideDropdownOnEscape);
},
// eslint-disable-next-line require-jsdoc
Expand Down
45 changes: 17 additions & 28 deletions lib/public/views/Logs/Logs.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,12 @@ import { Observable, RemoteData } from '/js/src/index.js';
import { TagFilterModel } from '../../components/Filters/common/TagFilterModel.js';
import { SortModel } from '../../components/common/table/SortModel.js';
import { debounce, INPUT_DEBOUNCE_TIME } from '../../utilities/debounce.js';
import { taggedEventRegistry } from '../../utilities/taggedEventRegistry.js';
import { FILTER_PANEL_CLICK_TAG } from '../../components/Filters/filtersConstants.js';
import { FilterInputModel } from '../../components/Filters/common/filters/FilterInputModel.js';
import { LogCreationModel } from './Create/LogCreationModel.js';
import { PaginationModel } from '../../components/Pagination/PaginationModel.js';
import { getRemoteDataSlice } from '../../utilities/fetch/getRemoteDataSlice.js';
import { LogTreeViewModel } from './Details/LogTreeViewModel.js';
import { ToggleableModel } from '../../components/common/toggle/TogglableModel.js';

/**
* Model representing handlers for log entries page
Expand Down Expand Up @@ -56,15 +55,15 @@ export default class LogModel extends Observable {
this._pagination.itemsPerPageSelector$.observe(() => this.notify());

// Filtering models
this._filtersToggle = new ToggleableModel();
this._filtersToggle.bubbleTo(this);

this._authorFilter = new FilterInputModel();
this._registerFilter(this._authorFilter);

this._titleFilter = new FilterInputModel();
this._registerFilter(this._titleFilter);

// Register tagged event listener to close filter if click outside
taggedEventRegistry.addListenerForAnyExceptTagged(() => this.setShowFilters(false), FILTER_PANEL_CLICK_TAG);

this._logs = RemoteData.NotAsked();

this.reset(false);
Expand Down Expand Up @@ -270,30 +269,11 @@ export default class LogModel extends Observable {
}

/**
* Returns whether the filter should be shown or not
* @returns {Boolean} returns whether the filter should be shown
*/
get areFiltersVisible() {
return this.showFilters || false;
}

/**
* Sets whether the filters are shown or not
* @param {Boolean} showFilters Whether the filter should be shown
* @returns {Boolean} returns boolean
*/
setShowFilters(showFilters) {
this.showFilters = showFilters;
this.notify();
}

/**
* Toggles whether the filters are shown
* @returns {void}
* Sets all data related to the Logs to `NotAsked` and clears pagination settings.
* @returns {undefined}
*/
toggleFiltersVisibility() {
this.setShowFilters(!this.areFiltersVisible);
this.notify();
clearLogs() {
this.logs = RemoteData.NotAsked();
}

/**
Expand Down Expand Up @@ -359,6 +339,15 @@ export default class LogModel extends Observable {
return this._pagination;
}

/**
* Returns the toggle model for filters pane
*
* @return {ToggleableModel} the toggle model
*/
get filtersToggle() {
return this._filtersToggle;
}

/**
* Apply the current filtering and update the remote data list
*
Expand Down
11 changes: 8 additions & 3 deletions lib/public/views/Logs/Overview/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { filtersPanel } from '../../../components/Filters/common/filtersPanel.js
import { filtersToggleButton } from '../../../components/Filters/common/filtersToggleButton.js';
import { estimateDisplayableRowsCount } from '../../../utilities/estimateDisplayableRowsCount.js';
import { paginationComponent } from '../../../components/Pagination/paginationComponent.js';
import { toggleContainer } from '../../../components/common/toggle/toggleContainer.js';

const TABLEROW_HEIGHT = 69;
// Estimate of the navbar and pagination elements height total; Needs to be updated in case of changes;
Expand Down Expand Up @@ -47,10 +48,14 @@ const showLogsTable = (model, logs) => {

return [
h('.flex-row.header-container.pv2', [
filtersToggleButton(model.logs),
filtersPanel(model, model.logs, logsActiveColumns),
filtersToggleButton(model.logs.filtersToggle),
toggleContainer(
model.logs.filtersToggle,
model.logs.filtersToggle.isVisible && filtersPanel(model, model.logs, logsActiveColumns),
model.logs.filtersToggle.isVisible ? { class: 'w-25 filters' } : null,
),
h(
`.w-50.filters${model.logs.isAnyFilterActive() && !model.logs.areFiltersVisible
`.w-50.filters${model.logs.isAnyFilterActive() && !model.logs.filtersToggle.isVisible
? '.display-block'
: '.display-none'}`,
h('.f5'),
Expand Down
11 changes: 8 additions & 3 deletions lib/public/views/Runs/Overview/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { filtersPanel } from '../../../components/Filters/common/filtersPanel.js
import { filtersToggleButton } from '../../../components/Filters/common/filtersToggleButton.js';
import { estimateDisplayableRowsCount } from '../../../utilities/estimateDisplayableRowsCount.js';
import { paginationComponent } from '../../../components/Pagination/paginationComponent.js';
import { toggleContainer } from '../../../components/common/toggle/toggleContainer.js';

const TABLEROW_HEIGHT = 59;
// Estimate of the navbar and pagination elements height total; Needs to be updated in case of changes;
Expand All @@ -45,10 +46,14 @@ const showRunsTable = (model, runs) => {

return [
h('.flex-row.header-container.pv2', [
filtersToggleButton(model.runs),
filtersPanel(model, model.runs, runsActiveColumns),
filtersToggleButton(model.runs.filtersToggle),
toggleContainer(
model.runs.filtersToggle,
model.runs.filtersToggle.isVisible && filtersPanel(model, model.runs, runsActiveColumns),
model.runs.filtersToggle.isVisible ? { class: 'w-25 filters' } : null,
),
h(
`.w-60.filters${model.runs.isAnyFilterActive() && !model.runs.areFiltersVisible ? '.display-block' : '.display-none'}`,
`.w-60.filters${model.runs.isAnyFilterActive() && !model.runs.filtersToggle.isVisible ? '.display-block' : '.display-none'}`,
h('.f5'),
`Active filters: ${model.runs.getActiveFilters().join(', ')}`,
),
Expand Down
45 changes: 13 additions & 32 deletions lib/public/views/Runs/Runs.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,11 @@ import { createCSVExport, createJSONExport } from '../../utilities/export.js';
import { TagFilterModel } from '../../components/Filters/common/TagFilterModel.js';
import { PickerModel } from '../../components/common/selection/picker/PickerModel.js';
import { debounce, INPUT_DEBOUNCE_TIME } from '../../utilities/debounce.js';
import { taggedEventRegistry } from '../../utilities/taggedEventRegistry.js';
import { FILTER_PANEL_CLICK_TAG } from '../../components/Filters/filtersConstants.js';
import { PaginationModel } from '../../components/Pagination/PaginationModel.js';
import { getRemoteDataSlice } from '../../utilities/fetch/getRemoteDataSlice.js';
import { DetectorsFilterModel } from '../../components/Filters/RunsFilter/DetectorsFilterModel.js';
import { RunDetailsModel } from './Details/RunDetailsModel.js';
import { ToggleableModel } from '../../components/common/toggle/TogglableModel.js';

/**
* Model representing handlers for runs page
Expand All @@ -42,6 +41,9 @@ export default class RunModel extends Observable {
this._detailsModel = new RunDetailsModel(model);
this._detailsModel.bubbleTo(this);

this._filtersToggle = new ToggleableModel({ hideOnEscape: false });
this._filtersToggle.bubbleTo(this);

this._listingTagsFilterModel = new TagFilterModel();
this._listingTagsFilterModel.observe(() => this._applyFilters(true));

Expand All @@ -62,9 +64,6 @@ export default class RunModel extends Observable {
this._currentPageRuns = RemoteData.notAsked();
this._allRuns = RemoteData.notAsked();

// Register tagged event listener to close filter if click outside
taggedEventRegistry.addListenerForAnyExceptTagged(() => this.setShowFilters(false), FILTER_PANEL_CLICK_TAG);

this.reset(false);

this._debouncedFetchAllRuns = debounce(this.fetchAllRuns.bind(this), INPUT_DEBOUNCE_TIME);
Expand Down Expand Up @@ -796,33 +795,6 @@ export default class RunModel extends Observable {
this._applyFilters();
}

/**
* Returns whether the filter should be shown or not
* @returns {Boolean} returns whether the filter should be shown
*/
get areFiltersVisible() {
return this.showFilters || false;
}

/**
* Sets whether the filters are shown or not
* @param {Boolean} showFilters Whether the filter should be shown
* @returns {void}
*/
setShowFilters(showFilters) {
this.showFilters = showFilters;
this.notify();
}

/**
* Toggles whether the filters are shown
* @returns {void}
*/
toggleFiltersVisibility() {
this.setShowFilters(!this.areFiltersVisible);
this.notify();
}

/**
* Return the model handling the filtering on tags
*
Expand Down Expand Up @@ -903,6 +875,15 @@ export default class RunModel extends Observable {
return this._detailsModel;
}

/**
* Returns the toggle model for filters pane
*
* @return {ToggleableModel} the toggle model
*/
get filtersToggle() {
return this._filtersToggle;
}

/**
* Returns the list of URL params corresponding to the currently applied filter
*
Expand Down

0 comments on commit 559a29f

Please sign in to comment.