Skip to content

Commit 5c204e2

Browse files
[O2B-1560] Add filter is active indicator to the UI (#2147)
Notable changes for users: - An indicator has been added to the toolbar next to the filter button/dropdown - - When filters are active, this indicator turns green and starts 'glowing' - - The indicator has a red 'x' icon next to it that glows red. When pressed, the filters are cleared Notable changes for developers: - A fix that was missed in previous branches is that the mcReproducable toggle filter is now considered inactive when untoggled, yet still not 'empty' so it is added to requests
1 parent 9d7bf56 commit 5c204e2

3 files changed

Lines changed: 98 additions & 7 deletions

File tree

lib/public/app.css

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -718,6 +718,68 @@ label {
718718
opacity: 0.5;
719719
}
720720

721+
.active-filters-indicator {
722+
position: relative;
723+
z-index: 10;
724+
background-color: white;
725+
border-radius: .25rem;
726+
padding: var(--space-xs) var(--space-s) var(--space-xs) var(--space-s);
727+
margin: 0 0 0 var(--space-s);
728+
}
729+
730+
.active-filters-indicator:has(+ .clear-filter-icon-container) {
731+
border-right: 0;
732+
border-radius: .25rem 0 0 .25rem
733+
}
734+
735+
.clear-filter-icon-container {
736+
background-color: white;
737+
border-radius: 0 .25rem .25rem 0;
738+
font-weight: 700;
739+
cursor: pointer;
740+
}
741+
742+
.clear-filter-icon {
743+
padding: var(--space-xs);
744+
background-color: white;
745+
color: var(--color-danger);
746+
position: relative;
747+
border-radius: 0 .25rem .25rem 0;
748+
z-index: 10;
749+
}
750+
751+
.clear-filter-icon:hover {
752+
background-color: var(--color-danger);
753+
color: white;
754+
}
755+
756+
.inactive {
757+
opacity: 0.5;
758+
pointer-events: none;
759+
}
760+
761+
.pulse-green {
762+
--pulse-color: 102, 255, 7;
763+
animation: pulse 2s infinite;
764+
}
765+
766+
.pulse-red {
767+
--pulse-color: 206, 42, 42;
768+
animation: pulse 2s infinite;
769+
}
770+
771+
@keyframes pulse {
772+
0% {
773+
box-shadow: 0 0 0px rgba(var(--pulse-color), 0.6);
774+
}
775+
50% {
776+
box-shadow: 0 0 10px rgba(var(--pulse-color), 0.9);
777+
}
778+
100% {
779+
box-shadow: 0 0 0px rgba(var(--pulse-color), 0.6);
780+
}
781+
}
782+
721783
/**
722784
* Breakpoints :
723785
* small : x < 600 (default styles)

lib/public/components/Filters/common/filtersPanelPopover.js

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -42,18 +42,21 @@ const filtersToggleTrigger = () => h('button#openFilterToggle.btn.btn.btn-primar
4242
* Button component that resets all filters upon click
4343
*
4444
* @param {FilteringModel|OverviewPageModel} filteringModel the FilteringModel
45+
* @param {bool} [isIcon=false] if the component is rendered as a regular button with text or as a component with an 'X' icon
4546
* @returns {Component} the reset button component
4647
*/
47-
const resetFiltersButton = (filteringModel) => h(
48-
'button#reset-filters.btn.btn-danger',
49-
{
48+
const resetFiltersButton = (filteringModel, isIcon = false) => {
49+
const attributes = {
5050
disabled: !filteringModel.isAnyFilterActive(),
5151
onclick: () => filteringModel.resetFiltering
5252
? filteringModel.resetFiltering(true, true)
5353
: filteringModel.reset(true, true),
54-
},
55-
'Reset all filters',
56-
);
54+
};
55+
56+
return isIcon
57+
? h('.clear-filter-icon-container.btn-group-item.last-item.pulse-red', attributes, h('.clear-filter-icon.b1.b-danger', 'X'))
58+
: h('button#reset-filters.btn.btn-danger', attributes, 'Reset all filters');
59+
};
5760

5861
/**
5962
* Create main header of the filters panel
@@ -168,6 +171,31 @@ const pasteButtonOption = (model) => {
168171
}, 'Paste filters');
169172
};
170173

174+
/**
175+
* A indicates if any filters are currently active on the page
176+
*
177+
* @param {FilteringModel} model the filtering model
178+
* @returns {Component} the active filters indicator
179+
*/
180+
const activeFilterIndicator = (model) => {
181+
// Sometimes, the overview model is passed to filterPanelPopover instead of the filteringmodel (e.g. envirionments)
182+
const { filteringModel = model } = model;
183+
184+
const hasActiveFilters = filteringModel.isAnyFilterActive();
185+
const innerText = `Filters ${hasActiveFilters ? 'Active' : 'Inactive'}`;
186+
187+
let indicator = '.active-filters-indicator.b1';
188+
indicator += hasActiveFilters ? '.b-success.success.pulse-green' : '.inactive';
189+
190+
const children = [h(indicator, innerText)];
191+
192+
if (hasActiveFilters) {
193+
children.push(resetFiltersButton(filteringModel, true));
194+
}
195+
196+
return h('.flex-row.items-center', children);
197+
};
198+
171199
/**
172200
* Return component composed of the filter popover button and a dropdown trigger
173201
*
@@ -195,6 +223,7 @@ export const filtersPanelPopover = (filteringModel, filtersConfiguration, config
195223
],
196224
),
197225
),
226+
activeFilterIndicator(filteringModel),
198227
],
199228
);
200229
};

lib/public/views/Runs/Overview/RunsWithQcModel.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ export class RunsWithQcModel extends RunsOverviewModel {
7878

7979
this._observablesQcFlagsSummaryDependsOn$ = null;
8080
// This filter instance will be added as a sub-filter for a MultiCompositionFilter and a GaqFilter later.
81-
this._mcReproducibleAsNotBad = new ToggleFilterModel();
81+
this._mcReproducibleAsNotBad = new ToggleFilterModel(false, true);
8282

8383
this._runDetectorsSelectionModel = new RunDetectorsSelectionModel();
8484
this._runDetectorsSelectionModel.bubbleTo(this);

0 commit comments

Comments
 (0)