Browse Source

refactor(admin-ui): Extract filter preset components

Michael Bromley 2 years ago
parent
commit
cfe257f4ef

+ 31 - 0
packages/admin-ui/src/lib/core/src/shared/components/data-table-2/add-filter-preset-button.component.html

@@ -0,0 +1,31 @@
+<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>

+ 25 - 0
packages/admin-ui/src/lib/core/src/shared/components/data-table-2/add-filter-preset-button.component.scss

@@ -0,0 +1,25 @@
+
+.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;
+    }
+}
+
+.preset-create-row {
+    display: flex;
+    justify-content: flex-end;
+}

+ 77 - 0
packages/admin-ui/src/lib/core/src/shared/components/data-table-2/add-filter-preset-button.component.ts

@@ -0,0 +1,77 @@
+import {
+    ChangeDetectionStrategy,
+    ChangeDetectorRef,
+    Component,
+    Input,
+    OnDestroy,
+    OnInit,
+    ViewChild,
+} from '@angular/core';
+import { FormControl } from '@angular/forms';
+import { ActivatedRoute } from '@angular/router';
+import { merge, Subject } from 'rxjs';
+import { distinctUntilChanged, map, takeUntil } from 'rxjs/operators';
+import { DataTableFilterCollection } from '../../../providers/data-table/data-table-filter-collection';
+import { DropdownComponent } from '../dropdown/dropdown.component';
+import { FilterPresetService } from './filter-preset.service';
+
+@Component({
+    selector: 'vdr-add-filter-preset-button',
+    templateUrl: './add-filter-preset-button.component.html',
+    styleUrls: ['./add-filter-preset-button.component.scss'],
+    changeDetection: ChangeDetectionStrategy.OnPush,
+})
+export class AddFilterPresetButtonComponent implements OnInit, OnDestroy {
+    @Input({ required: true }) dataTableId: string;
+    @Input({ required: true }) filters: DataTableFilterCollection;
+    @ViewChild('addPresetDropdown') addPresetDropdown: DropdownComponent;
+    selectedFilterPreset: string | undefined;
+    filterPresetName = new FormControl('');
+    private destroy$ = new Subject<void>();
+
+    constructor(
+        private filterPresetService: FilterPresetService,
+        private changeDetector: ChangeDetectorRef,
+        private route: ActivatedRoute,
+    ) {}
+
+    ngOnInit() {
+        merge(
+            this.route.queryParamMap.pipe(
+                map(qpm => qpm.get('filters')),
+                distinctUntilChanged(),
+                takeUntil(this.destroy$),
+            ),
+            this.filterPresetService.presetChanges$,
+        ).subscribe(() => {
+            this.changeDetector.markForCheck();
+            this.updateSelectedFilterPreset();
+        });
+    }
+
+    ngOnDestroy() {
+        this.destroy$.next();
+        this.destroy$.complete();
+    }
+
+    saveFilterPreset() {
+        const name = this.filterPresetName.value;
+        if (this.filters && name) {
+            const value = this.filters.serialize();
+            this.filterPresetService.saveFilterPreset({
+                dataTableId: this.dataTableId,
+                name,
+                value,
+            });
+            this.filterPresetName.setValue('');
+            this.addPresetDropdown.toggleOpen();
+        }
+        this.updateSelectedFilterPreset();
+    }
+
+    private updateSelectedFilterPreset() {
+        this.selectedFilterPreset = this.filterPresetService
+            .getFilterPresets(this.dataTableId)
+            .find(p => p.value === this.filters.serialize())?.name;
+    }
+}

+ 26 - 0
packages/admin-ui/src/lib/core/src/shared/components/data-table-2/data-table-filter-presets.component.html

@@ -0,0 +1,26 @@
+<ng-container *ngIf="filterPresets$ | async as filterPresets">
+    <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>
+</ng-container>

+ 43 - 0
packages/admin-ui/src/lib/core/src/shared/components/data-table-2/data-table-filter-presets.component.scss

@@ -0,0 +1,43 @@
+
+.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);
+}

+ 52 - 0
packages/admin-ui/src/lib/core/src/shared/components/data-table-2/data-table-filter-presets.component.ts

@@ -0,0 +1,52 @@
+import { ChangeDetectionStrategy, Component, Input, OnDestroy, OnInit } from '@angular/core';
+import { ActivatedRoute } from '@angular/router';
+import { Observable, Subject } from 'rxjs';
+import { distinctUntilChanged, map, startWith, takeUntil } from 'rxjs/operators';
+import { DataTableFilterCollection } from '../../../providers/data-table/data-table-filter-collection';
+import { FilterPresetService } from './filter-preset.service';
+
+@Component({
+    selector: 'vdr-data-table-filter-presets',
+    templateUrl: './data-table-filter-presets.component.html',
+    styleUrls: ['./data-table-filter-presets.component.scss'],
+    changeDetection: ChangeDetectionStrategy.OnPush,
+})
+export class DataTableFilterPresetsComponent implements OnInit, OnDestroy {
+    @Input({ required: true }) dataTableId: string;
+    @Input({ required: true }) filters: DataTableFilterCollection;
+    serializedActiveFilters: string;
+    filterPresets$: Observable<Array<{ name: string; value: string }>>;
+
+    private destroy$ = new Subject<void>();
+
+    constructor(private route: ActivatedRoute, private filterPresetService: FilterPresetService) {}
+    ngOnInit() {
+        this.route.queryParamMap
+            .pipe(
+                map(qpm => qpm.get('filters')),
+                distinctUntilChanged(),
+                takeUntil(this.destroy$),
+            )
+            .subscribe(() => {
+                this.serializedActiveFilters = this.filters.serialize();
+            });
+        this.serializedActiveFilters = this.filters.serialize();
+
+        this.filterPresets$ = this.filterPresetService.presetChanges$.pipe(
+            startWith(this.filterPresetService.getFilterPresets(this.dataTableId)),
+        );
+    }
+
+    ngOnDestroy() {
+        this.destroy$.next();
+        this.destroy$.complete();
+    }
+
+    deleteFilterPreset(name: string) {
+        this.filterPresetService.deleteFilterPreset({
+            dataTableId: this.dataTableId,
+            name,
+        });
+        this.serializedActiveFilters = this.filters.serialize();
+    }
+}

+ 5 - 56
packages/admin-ui/src/lib/core/src/shared/components/data-table-2/data-table2.component.html

@@ -2,30 +2,7 @@
     <ng-content select="vdr-bulk-action-menu"></ng-content>
 </div>
 <div class="table-wrapper">
-    <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>
+    <vdr-data-table-filter-presets [filters]="filters" [dataTableId]="id"></vdr-data-table-filter-presets>
     <table class="" [class.no-select]="disableSelect">
         <thead [class.items-selected]="selectionManager?.selection.length">
             <tr class="heading-row">
@@ -81,7 +58,6 @@
                     <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
@@ -95,37 +71,10 @@
                                     [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>
+                                <vdr-add-filter-preset-button
+                                    [filters]="filters"
+                                    [dataTableId]="id"
+                                ></vdr-add-filter-preset-button>
                             </div>
                         </ng-container>
                     </div>

+ 0 - 68
packages/admin-ui/src/lib/core/src/shared/components/data-table-2/data-table2.component.scss

@@ -125,69 +125,6 @@ th.filter-row {
     }
 }
 
-.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;
@@ -258,8 +195,3 @@ vdr-empty-placeholder {
         display: none;
     }
 }
-
-.preset-create-row {
-    display: flex;
-    justify-content: flex-end;
-}

+ 6 - 74
packages/admin-ui/src/lib/core/src/shared/components/data-table-2/data-table2.component.ts

@@ -10,28 +10,25 @@ import {
     Input,
     OnChanges,
     OnDestroy,
-    OnInit,
     Output,
     QueryList,
     SimpleChanges,
     TemplateRef,
-    ViewChild,
 } from '@angular/core';
-import { FormControl } from '@angular/forms';
 import { ActivatedRoute } from '@angular/router';
 import { PaginationService } from 'ngx-pagination';
-import { Observable, Subject, Subscription } from 'rxjs';
+import { Observable, Subject } from 'rxjs';
 import { distinctUntilChanged, map, takeUntil } from 'rxjs/operators';
 import { LanguageCode } from '../../../common/generated-types';
 import { DataService } from '../../../data/providers/data.service';
 import { DataTableFilterCollection } from '../../../providers/data-table/data-table-filter-collection';
 import { DataTableConfig, LocalStorageService } from '../../../providers/local-storage/local-storage.service';
 import { BulkActionMenuComponent } from '../bulk-action-menu/bulk-action-menu.component';
-import { DropdownComponent } from '../dropdown/dropdown.component';
 
 import { DataTable2ColumnComponent } from './data-table-column.component';
 import { DataTableCustomFieldColumnComponent } from './data-table-custom-field-column.component';
 import { DataTable2SearchComponent } from './data-table-search.component';
+import { FilterPresetService } from './filter-preset.service';
 
 /**
  * @description
@@ -100,9 +97,9 @@ import { DataTable2SearchComponent } from './data-table-search.component';
     templateUrl: 'data-table2.component.html',
     styleUrls: ['data-table2.component.scss'],
     changeDetection: ChangeDetectionStrategy.OnPush,
-    providers: [PaginationService],
+    providers: [PaginationService, FilterPresetService],
 })
-export class DataTable2Component<T> implements OnInit, AfterContentInit, OnChanges, OnDestroy {
+export class DataTable2Component<T> implements AfterContentInit, OnChanges, OnDestroy {
     @Input() id: string;
     @Input() items: T[];
     @Input() itemsPerPage: number;
@@ -120,10 +117,10 @@ export class DataTable2Component<T> implements OnInit, AfterContentInit, OnChang
     @ContentChild(DataTable2SearchComponent) searchComponent: DataTable2SearchComponent;
     @ContentChild(BulkActionMenuComponent) bulkActionMenuComponent: BulkActionMenuComponent;
     @ContentChild('vdrDt2CustomSearch') customSearchTemplate: TemplateRef<any>;
-    @ViewChild('addPresetDropdown') addPresetDropdown: DropdownComponent;
     @ContentChildren(TemplateRef) templateRefs: QueryList<TemplateRef<any>>;
 
     route = inject(ActivatedRoute);
+    filterPresetService = inject(FilterPresetService);
 
     rowTemplate: TemplateRef<any>;
     currentStart: number;
@@ -132,10 +129,7 @@ export class DataTable2Component<T> implements OnInit, AfterContentInit, OnChang
     // which allows shift-click multi-row selection
     disableSelect = false;
     showSearchFilterRow = false;
-    filterPresetName = new FormControl('');
-    filterPresets: Array<{ name: string; value: string }> = [];
-    serializedActiveFilters: string;
-    selectedFilterPreset: string | undefined;
+
     protected uiLanguage$: Observable<LanguageCode>;
     protected destroy$ = new Subject<void>();
 
@@ -189,19 +183,6 @@ export class DataTable2Component<T> implements OnInit, AfterContentInit, OnChang
         }
     };
 
-    ngOnInit() {
-        this.filterPresets = this.getFilterPreset();
-        this.route.queryParamMap
-            .pipe(
-                map(qpm => qpm.get('filters')),
-                distinctUntilChanged(),
-                takeUntil(this.destroy$),
-            )
-            .subscribe(() => {
-                this.getSerializedActiveFilters();
-            });
-    }
-
     ngOnChanges(changes: SimpleChanges) {
         if (changes.items) {
             this.currentStart = this.itemsPerPage * (this.currentPage - 1);
@@ -311,50 +292,6 @@ export class DataTable2Component<T> implements OnInit, AfterContentInit, OnChang
         this.selectionManager?.toggleSelection(item, event);
     }
 
-    saveFilterPreset() {
-        const name = this.filterPresetName.value;
-        if (this.filters && name) {
-            const value = this.filters.serialize();
-            const dataTableConfig = this.getDataTableConfig();
-            if (!dataTableConfig[this.id].filterPresets) {
-                dataTableConfig[this.id].filterPresets = [];
-            }
-            const existingName = dataTableConfig[this.id].filterPresets.find(p => p.name === name);
-            if (existingName) {
-                existingName.value = value;
-            } else {
-                dataTableConfig[this.id].filterPresets.push({
-                    name,
-                    value: this.filters.serialize(),
-                });
-            }
-            this.localStorageService.set('dataTableConfig', dataTableConfig);
-            this.filterPresetName.setValue('');
-            this.filterPresets = this.getFilterPreset();
-            this.addPresetDropdown.toggleOpen();
-            this.getSerializedActiveFilters();
-        }
-    }
-
-    deleteFilterPreset(name: string) {
-        const dataTableConfig = this.getDataTableConfig();
-        dataTableConfig[this.id].filterPresets = dataTableConfig[this.id].filterPresets.filter(
-            p => p.name !== name,
-        );
-        this.localStorageService.set('dataTableConfig', dataTableConfig);
-        this.filterPresets = this.getFilterPreset();
-        this.getSerializedActiveFilters();
-    }
-
-    private getSerializedActiveFilters(): void {
-        const dataTableConfig = this.getDataTableConfig();
-        this.serializedActiveFilters = this.filters.serialize();
-        this.selectedFilterPreset = dataTableConfig[this.id].filterPresets.find(
-            p => p.value === this.serializedActiveFilters,
-        )?.name;
-        this.changeDetectorRef.markForCheck();
-    }
-
     protected getDataTableConfig(): DataTableConfig {
         const dataTableConfig = this.localStorageService.get('dataTableConfig') ?? {};
         if (!dataTableConfig[this.id]) {
@@ -367,9 +304,4 @@ export class DataTable2Component<T> implements OnInit, AfterContentInit, OnChang
         }
         return dataTableConfig;
     }
-
-    private getFilterPreset(): Array<{ name: string; value: string }> {
-        const dataTableConfig = this.getDataTableConfig();
-        return dataTableConfig[this.id].filterPresets ?? [];
-    }
 }

+ 59 - 0
packages/admin-ui/src/lib/core/src/shared/components/data-table-2/filter-preset.service.ts

@@ -0,0 +1,59 @@
+import { Injectable } from '@angular/core';
+import { Observable, Subject } from 'rxjs';
+import { DataTableConfig, LocalStorageService } from '../../../providers/local-storage/local-storage.service';
+
+@Injectable({
+    providedIn: 'root',
+})
+export class FilterPresetService {
+    presetChanges$: Observable<Array<{ name: string; value: string }>>;
+    private _presetChanges = new Subject<Array<{ name: string; value: string }>>();
+
+    constructor(private localStorageService: LocalStorageService) {
+        this.presetChanges$ = this._presetChanges.asObservable();
+    }
+
+    protected getDataTableConfig(dataTableId: string): DataTableConfig {
+        const dataTableConfig = this.localStorageService.get('dataTableConfig') ?? {};
+        if (!dataTableConfig[dataTableId]) {
+            dataTableConfig[dataTableId] = {
+                visibility: [],
+                order: {},
+                showSearchFilterRow: false,
+                filterPresets: [],
+            };
+        }
+        return dataTableConfig;
+    }
+
+    getFilterPresets(dataTableId: string): Array<{ name: string; value: string }> {
+        const dataTableConfig = this.getDataTableConfig(dataTableId);
+        return dataTableConfig[dataTableId].filterPresets ?? [];
+    }
+
+    saveFilterPreset(config: { dataTableId: string; name: string; value: string }) {
+        const dataTableConfig = this.getDataTableConfig(config.dataTableId);
+        const filterPresets = dataTableConfig[config.dataTableId].filterPresets ?? [];
+        const existingName = filterPresets.find(p => p.name === config.name);
+        if (existingName) {
+            existingName.value = config.value;
+        } else {
+            filterPresets.push({
+                name: config.name,
+                value: config.value,
+            });
+        }
+        dataTableConfig[config.dataTableId].filterPresets = filterPresets;
+        this.localStorageService.set('dataTableConfig', dataTableConfig);
+        this._presetChanges.next(filterPresets);
+    }
+
+    deleteFilterPreset(config: { dataTableId: string; name: string }) {
+        const dataTableConfig = this.getDataTableConfig(config.dataTableId);
+        dataTableConfig[config.dataTableId].filterPresets = dataTableConfig[
+            config.dataTableId
+        ].filterPresets.filter(p => p.name !== config.name);
+        this.localStorageService.set('dataTableConfig', dataTableConfig);
+        this._presetChanges.next(dataTableConfig[config.dataTableId].filterPresets);
+    }
+}

+ 8 - 1
packages/admin-ui/src/lib/core/src/shared/shared.module.ts

@@ -171,6 +171,8 @@ import { ZoneSelectorComponent } from './components/zone-selector/zone-selector.
 import { ChartComponent } from './components/chart/chart.component';
 import { CurrencyCodeSelectorComponent } from './components/currency-code-selector/currency-code-selector.component';
 import { LanguageCodeSelectorComponent } from './components/language-code-selector/language-code-selector.component';
+import { DataTableFilterPresetsComponent } from './components/data-table-2/data-table-filter-presets.component';
+import { AddFilterPresetButtonComponent } from './components/data-table-2/add-filter-preset-button.component';
 
 const IMPORTS = [
     ClarityModule,
@@ -346,7 +348,12 @@ const DYNAMIC_FORM_INPUTS = [
 @NgModule({
     imports: [IMPORTS],
     exports: [...IMPORTS, ...DECLARATIONS, ...DYNAMIC_FORM_INPUTS],
-    declarations: [...DECLARATIONS, ...DYNAMIC_FORM_INPUTS],
+    declarations: [
+        ...DECLARATIONS,
+        ...DYNAMIC_FORM_INPUTS,
+        DataTableFilterPresetsComponent,
+        AddFilterPresetButtonComponent,
+    ],
     providers: [
         // This needs to be shared, since lazy-loaded
         // modules have their own entryComponents which