Skip to content

Commit

Permalink
feat(admin-ui): Add data table filter presets functionality
Browse files Browse the repository at this point in the history
  • Loading branch information
michaelbromley committed Aug 25, 2023
1 parent 39832bd commit a656ef2
Show file tree
Hide file tree
Showing 10 changed files with 251 additions and 30 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ export class DataTableFilterCollection<FilterInput extends Record<string, any> =
)
.subscribe(value => {
this.#activeFilters = [];
if (value === '') {
if (value === '' || value === null) {
this.#valueChanges$.next(this.#activeFilters);
return;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import { Location } from '@angular/common';
import { Injectable, Injector } from '@angular/core';
import { Injectable } from '@angular/core';

import { LanguageCode } from '../../common/generated-types';
import { DataService } from '../../data/providers/data.service';
import { WidgetLayoutDefinition } from '../dashboard-widget/dashboard-widget-types';

export type DataTableConfig = {
[id: string]: {
visibility: string[];
order: { [id: string]: number };
showSearchFilterRow: boolean;
filterPresets: Array<{ name: string; value: string }>;
};
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,31 @@
<ng-content select="vdr-bulk-action-menu"></ng-content>
</div>
<div class="table-wrapper">
<table
class=""
[class.no-select]="disableSelect"
>
<div class="preset-tabs" *ngIf="filters && filterPresets.length">
<div
*ngFor="let preset of filterPresets"
class="preset-tab"
[class.active]="preset.value === serializedActiveFilters"
>
<a
[routerLink]="['./']"
[queryParams]="preset.value === serializedActiveFilters ? {} : { filters: preset.value }"
>
<div>{{ preset.name }}</div>
</a>
<vdr-dropdown>
<button class="icon-button" vdrDropdownTrigger>
<clr-icon shape="ellipsis-vertical" size="12" />
</button>
<vdr-dropdown-menu vdrPosition="bottom-left">
<button vdrDropdownItem (click)="deleteFilterPreset(preset.name)">
<clr-icon shape="trash" class="is-danger"></clr-icon>{{ 'common.delete' | translate }}
</button>
</vdr-dropdown-menu>
</vdr-dropdown>
</div>
</div>
<table class="" [class.no-select]="disableSelect">
<thead [class.items-selected]="selectionManager?.selection.length">
<tr class="heading-row">
<th *ngIf="selectionManager" class="selection-col">
Expand Down Expand Up @@ -60,6 +81,7 @@
<div class="filter-row-wrapper" [class.hidden]="!showSearchFilterRow">
<ng-container *ngTemplateOutlet="searchComponent?.template"></ng-container>
<ng-container *ngTemplateOutlet="customSearchTemplate"></ng-container>
<div *ngIf="filterPresets.length"></div>
<ng-container *ngIf="filters">
<div class="filters">
<vdr-data-table-filters
Expand All @@ -73,6 +95,37 @@
[filters]="filters"
class="mt-1"
></vdr-data-table-filters>
<vdr-dropdown #addPresetDropdown>
<button
class="add-preset-button mt-1"
vdrDropdownTrigger
[class.visible]="filters.activeFilters.length > 0 && !selectedFilterPreset"
[disabled]="filters.activeFilters.length === 0 || !!selectedFilterPreset"
>
<clr-icon shape="floppy"/>
<div>{{ 'common.save-filter-preset' | translate }}</div>
</button>
<vdr-dropdown-menu
vdrPosition="bottom-left"
[cdkTrapFocus]="true"
[cdkTrapFocusAutoCapture]="true"
>
<form class="mx-1">
<div>
<input
type="text"
[placeholder]="'common.filter-preset-name' | translate"
[formControl]="filterPresetName"
/>
</div>
<div class="preset-create-row">
<button class="button mt-2" (click)="saveFilterPreset()">
{{ 'common.create' | translate }}
</button>
</div>
</form>
</vdr-dropdown-menu>
</vdr-dropdown>
</div>
</ng-container>
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
@import 'variables';
@import "mixins";
@import 'mixins';

:host {
display: block;
Expand All @@ -26,16 +26,19 @@
top: 5px;
height: 40px;
}

.table-wrapper {
display: block;
overflow-y: hidden;
overflow-x: auto;
width: 100%;
max-width: var(--surface-width);
}

table {
width: 100%;
}

table.no-select {
user-select: none;
}
Expand All @@ -57,37 +60,43 @@ table.no-select {
display: flex;
align-items: center;
margin-inline-start: calc(var(--space-unit) * 0.5);

button {
border: 0;
border-radius: var(--border-radius-lg);
color: var(--color-weight-500);
padding: 0 2px;
cursor: pointer;
background-color: transparent;

&.active {
color: var(--color-primary-700);
}
}

.sort-label {
margin-inline-start: calc(var(--space-unit) * 0.5);
font-size: 10px;
color: var(--color-primary-600);
font-weight: 400;
}
}

.toggle-search-filter-row {
position: absolute;
top: -12px;
left: 4px;
@media screen and (min-width: $breakpoint-large) {
left: 8px;
}

&.active {
background-color: var(--color-primary-700);
color: var(--color-primary-100);
border-color: var(--color-primary-700);
}
}

th.filter-row {
position: relative;
font-size: var(--font-size-base);
Expand Down Expand Up @@ -115,11 +124,76 @@ th.filter-row {
gap: calc(var(--space-unit) * 0.5);
}
}

.preset-tabs {
padding-inline-start: var(--surface-margin-left);
margin: var(--space-unit) 0;
display: flex;
overflow-x: auto;
overflow-y: hidden;
border-bottom: 1px solid var(--color-component-border-100);
}

.preset-tab {
display: flex;
align-items: center;
gap: calc(var(--space-unit) * 0.5);
font-size: var(--font-size-sm);
cursor: pointer;
white-space: nowrap;
text-transform: none;
padding-inline-end: calc(var(--space-unit) * 1);
border-bottom: 1px solid var(--color-weight-300);
margin-bottom: -1px;
cursor: pointer;

> a {
padding: calc(var(--space-unit) * 1) calc(var(--space-unit) * 2);
padding-inline-end: 0;
color: var(--color-weight-600);
}

&.active {
border-bottom-color: var(--color-text-active);

> a {
color: var(--color-text-active);
}
}
}

.preset-tab-link {
display: flex;
align-items: center;
gap: calc(var(--space-unit) * 0.5);
}

.add-preset-button {
display: flex;
flex-direction: row;
cursor: pointer;
gap: 6px;
align-items: center;
border: none;
padding: 0 var(--space-unit);
height: calc(var(--space-unit) * 3);
font-size: var(--font-size-xs);
border-radius: var(--border-radius-lg);
background-color: var(--color-button-small-bg);
color: var(--color-button-small-text);
opacity: 0;
transition: opacity 0.2s;
&.visible {
opacity: 1;
}
}

.filter-row-wrapper {
padding: calc(var(--space-unit) * 4);
padding-inline-start: 0;
max-height: 150px;
transition: max-height 0.2s, padding 0.2s, opacity 0.2s;

&.hidden {
max-height: 0px;
padding-top: 0;
Expand All @@ -129,7 +203,6 @@ th.filter-row {
}
}


.cell-link {
display: block;
width: 100%;
Expand All @@ -145,12 +218,15 @@ td.active {
align-items: center;
line-height: var(--font-size-sm);
color: var(--color-weight-700);

&.left {
justify-content: flex-start;
}

&.center {
justify-content: center;
}

&.right {
justify-content: flex-end;
}
Expand All @@ -172,11 +248,18 @@ vdr-empty-placeholder {
margin-inline-start: var(--surface-margin-left);
margin-inline-end: var(--space-unit);
}

.total-items-count {
font-size: var(--font-size-xs);
}

@container (max-width: 500px) {
.total-items-count {
display: none;
}
}

.preset-create-row {
display: flex;
justify-content: flex-end;
}
Loading

0 comments on commit a656ef2

Please sign in to comment.