This commit is contained in:
Mathias Beaulieu-Duncan 2024-09-21 05:16:31 -04:00
parent 860d48005e
commit aa4f9b4f8d
Signed by: mathias
GPG Key ID: 1C16CF05BAF9162D
4 changed files with 112 additions and 51 deletions

View File

@ -0,0 +1,58 @@
import {Directive, HostListener, Input} from '@angular/core';
import {FilterType, ICompositeFilter, IDataSource, IFilter, ISimpleFilter} from "@openharbor/data";
type FilterTypeString = `${FilterType}`;
@Directive({
selector: '[duiSearch]',
standalone: true
})
export class SearchDirective<TModel> {
@Input({ required: true }) dataSource!: IDataSource<TModel>;
@Input({ required: true }) filterPaths!: string[];
@Input() filterType: FilterTypeString = FilterType.CONTAINS;
filterValue?: string;
lastUsedFilter?: IFilter;
@HostListener('search', ['$event']) onSearch(event: Event): void {
console.log('Search event triggered', event);
this.filterValue = (event.target as any)?.value ?? '';
this.applySearch();
}
applySearch() {
const existingFilters = this.dataSource.filters;
// adapt current filters to remove the previous one if exist
// and replace with new one.
const finalNewFilters = existingFilters
.filter(t => t !== this.lastUsedFilter);
if (this.filterValue) {
const newFilter: ICompositeFilter = {
and: true,
type: FilterType.COMPOSITE,
filters: this.filterPaths.map(filterPath => (<ISimpleFilter>{
path: filterPath,
type: this.filterType,
value: this.filterValue,
and: false
}))
};
finalNewFilters.push(newFilter);
// update last used filter to replace it if changed.
this.lastUsedFilter = newFilter;
} else {
this.lastUsedFilter = undefined;
}
// execute search.
this.dataSource.query({
page: 1,
filters: finalNewFilters
});
}
}

View File

@ -5,3 +5,4 @@
export * from './lib/command/directives/command.directive'; export * from './lib/command/directives/command.directive';
export * from './lib/command/abstractions/command-directive-service.abstraction'; export * from './lib/command/abstractions/command-directive-service.abstraction';
export * from './lib/command/directives/command-form.directive'; export * from './lib/command/directives/command-form.directive';
export * from './lib/search/directives/search.directive';

View File

@ -1,50 +1,49 @@
<div class="mat-elevation-z8"> @if ($data) {
@if ($data) { <table mat-table [dataSource]="$data" matSort
<table mat-table [dataSource]="$data" matSort (matSortChange)="onSortChanged($event)">
(matSortChange)="onSortChanged($event)"> @for (column of _options.columns; track column.column) {
@for (column of _options.columns; track column.column) { <ng-container [matColumnDef]="column.column">
<ng-container [matColumnDef]="column.column"> <th mat-header-cell *matHeaderCellDef
<th mat-header-cell *matHeaderCellDef [mat-sort-header]="column.sorting && column.sorting.path ? column.sorting.path : column.column"
[mat-sort-header]="column.sorting && column.sorting.path ? column.sorting.path : column.column" [disabled]="!(column.sorting?.enable)"
[disabled]="!(column.sorting?.enable)" [sortActionDescription]="column.sorting && column.sorting.description ? (column.sorting.description(column.column) | async) ?? '' : 'Sort by ' + column.column">
[sortActionDescription]="column.sorting && column.sorting.description ? (column.sorting.description(column.column) | async) ?? '' : 'Sort by ' + column.column"> @if (column.title) {
@if (column.title) { {{ column.title(column.column) | async }}
{{ column.title(column.column) | async }} }
} @else {
@else { {{ column.column | titlecase }}
{{ column.column | titlecase }} }
} </th>
</th>
<td mat-cell *matCellDef="let element"> <td mat-cell *matCellDef="let element">
@if (column.value) { @if (column.value) {
{{ column.value(element[column.column]) | async }} {{ column.value(element[column.column]) | async }}
} }
@else { @else {
{{ element[column.column] }} {{ element[column.column] }}
} }
</td> </td>
</ng-container> </ng-container>
}
<tr mat-header-row *matHeaderRowDef="getColumns()"></tr>
<tr mat-row *matRowDef="let row; columns: getColumns();"></tr>
</table>
@if(_options.pagination.enable) {
<mat-paginator
[disabled]="isLoading"
[hidePageSize]="_options.pagination.hidePageSize"
[pageSizeOptions]="_options.pagination.pageSizeOptions"
(page)="onPaginationEvent($event)"
[length]="totalRecords"
showFirstLastButtons
aria-label="Select page of periodic elements">
</mat-paginator>
} }
@if (isLoading) { <tr mat-header-row *matHeaderRowDef="getColumns()"></tr>
<mat-progress-bar mode="query"></mat-progress-bar> <tr mat-row *matRowDef="let row; columns: getColumns();"></tr>
} </table>
@if(_options.pagination.enable) {
<mat-paginator
[disabled]="isLoading"
[hidePageSize]="_options.pagination.hidePageSize"
[pageSizeOptions]="_options.pagination.pageSizeOptions"
(page)="onPaginationEvent($event)"
[length]="totalRecords"
showFirstLastButtons
aria-label="Select page of periodic elements">
</mat-paginator>
} }
</div>
@if (isLoading) {
<mat-progress-bar mode="query"></mat-progress-bar>
}
}

View File

@ -85,7 +85,7 @@ export class DataGridComponent<TModel extends object> implements OnInit, OnDestr
enable: true, enable: true,
hidePageSize: false, hidePageSize: false,
pageSizeOptions: [10, 25, 50, 100], pageSizeOptions: [10, 25, 50, 100],
pageSize: 25 pageSize: 10
} }
}; };
@ -101,6 +101,12 @@ export class DataGridComponent<TModel extends object> implements OnInit, OnDestr
...this.options ...this.options
}; };
this.setPageSize(this._options.pagination.pageSize);
this.subscriptions.push(this.dataSource.loading$
.subscribe(loading => this.isLoading = loading)
);
this.$data = this.dataSource.data$ this.$data = this.dataSource.data$
.pipe( .pipe(
tap((result => { tap((result => {
@ -110,10 +116,6 @@ export class DataGridComponent<TModel extends object> implements OnInit, OnDestr
return result?.data ?? []; return result?.data ?? [];
}) })
); );
this.subscriptions.push(this.dataSource.loading$
.subscribe(loading => this.isLoading = loading)
);
} }
ngOnDestroy() { ngOnDestroy() {
@ -145,6 +147,7 @@ export class DataGridComponent<TModel extends object> implements OnInit, OnDestr
this.dataSource.sorts = this.dataSource.sorts.filter(sort => sort.path !== state.active); this.dataSource.sorts = this.dataSource.sorts.filter(sort => sort.path !== state.active);
} else { } else {
let field = this.dataSource.sorts.find(field => field.path === state.active); let field = this.dataSource.sorts.find(field => field.path === state.active);
if (field === undefined) { if (field === undefined) {
field = { field = {
path: state.active path: state.active