From c58431081649045cf05405a407824d924571c446 Mon Sep 17 00:00:00 2001 From: develite98 Date: Sat, 28 Oct 2023 15:52:59 +0700 Subject: [PATCH] feat() update code filter --- .../action-collapse.component.html | 41 ------ .../action-collapse.component.scss | 19 --- .../action-collapse.component.ts | 78 ----------- .../compress-image.component.html | 62 --------- .../compress-image.component.scss | 16 --- .../compress-image.component.ts | 121 ------------------ .../database-select/database-filter.pipe.ts | 20 --- .../database-select.component.html | 37 ------ .../database-select.component.scss | 50 -------- .../database-select.component.ts | 58 --------- .../dynamic-data-display.component.ts | 2 +- .../dynamic-db-list.component.ts | 2 +- .../record-form/record-form.component.html | 25 ---- .../record-form/record-form.component.scss | 0 .../record-form/record-form.component.ts | 92 ------------- .../user-avatar/user-avatar.component.html | 5 - .../user-avatar/user-avatar.component.scss | 5 - .../user-avatar/user-avatar.component.ts | 18 --- .../database-data.component.html | 1 + .../database-data/database-data.component.ts | 21 ++- .../database-detail.component.ts | 2 +- .../database-document.component.ts | 2 +- .../portal/discount/discount.component.ts | 6 +- .../pages/portal/module/module.component.ts | 2 +- .../app/pages/portal/order/order.component.ts | 8 +- .../app/pages/portal/page/page.component.ts | 6 +- .../app/pages/portal/post/post.component.ts | 2 +- .../task-card/task-card.component.ts | 2 +- .../task-filter/task-filter.component.ts | 2 +- .../src/app/stores/database-data.store.ts | 19 +++ .../src/model/pagination-request.model.ts | 2 +- .../database-select.component.scss | 1 + libs/mix-share/src/pipes/index.ts | 1 + libs/mix-share/src/pipes/trackby-prop.pipe.ts | 17 +++ .../dynamic-filter.component.html | 13 +- .../dynamic-filter.component.ts | 28 ++-- .../filter-input/filter-input.component.html | 12 +- .../filter-input/filter-input.component.ts | 51 +++++++- .../filter-item/filter-item.component.html | 5 +- .../filter-item/filter-item.component.scss | 1 + .../filter-item/filter-item.component.ts | 84 ++++++------ 41 files changed, 215 insertions(+), 724 deletions(-) delete mode 100644 apps/mix-cms/src/app/components/action-collapse/action-collapse.component.html delete mode 100644 apps/mix-cms/src/app/components/action-collapse/action-collapse.component.scss delete mode 100644 apps/mix-cms/src/app/components/action-collapse/action-collapse.component.ts delete mode 100644 apps/mix-cms/src/app/components/compress-image/compress-image.component.html delete mode 100644 apps/mix-cms/src/app/components/compress-image/compress-image.component.scss delete mode 100644 apps/mix-cms/src/app/components/compress-image/compress-image.component.ts delete mode 100644 apps/mix-cms/src/app/components/database-select/database-filter.pipe.ts delete mode 100644 apps/mix-cms/src/app/components/database-select/database-select.component.html delete mode 100644 apps/mix-cms/src/app/components/database-select/database-select.component.scss delete mode 100644 apps/mix-cms/src/app/components/database-select/database-select.component.ts delete mode 100644 apps/mix-cms/src/app/components/record-form/record-form.component.html delete mode 100644 apps/mix-cms/src/app/components/record-form/record-form.component.scss delete mode 100644 apps/mix-cms/src/app/components/record-form/record-form.component.ts delete mode 100644 apps/mix-cms/src/app/components/user-avatar/user-avatar.component.html delete mode 100644 apps/mix-cms/src/app/components/user-avatar/user-avatar.component.scss delete mode 100644 apps/mix-cms/src/app/components/user-avatar/user-avatar.component.ts create mode 100644 libs/mix-share/src/pipes/trackby-prop.pipe.ts diff --git a/apps/mix-cms/src/app/components/action-collapse/action-collapse.component.html b/apps/mix-cms/src/app/components/action-collapse/action-collapse.component.html deleted file mode 100644 index ed5962e7..00000000 --- a/apps/mix-cms/src/app/components/action-collapse/action-collapse.component.html +++ /dev/null @@ -1,41 +0,0 @@ - - - - {{ item.icon }}   - {{ item.label }} - - - - - - - more_vert - - - - - - - - - - - diff --git a/apps/mix-cms/src/app/components/action-collapse/action-collapse.component.scss b/apps/mix-cms/src/app/components/action-collapse/action-collapse.component.scss deleted file mode 100644 index bdf97436..00000000 --- a/apps/mix-cms/src/app/components/action-collapse/action-collapse.component.scss +++ /dev/null @@ -1,19 +0,0 @@ -mix-action-collapse { - flex-grow: 1; - width: 100%; - padding-right: 8px; -} - -.action-collapse { - &__item { - margin: 0px 4px; - } -} - -.t-item:has(> .action-collapse__item.right) { - margin-left: auto; -} - -span.t-item { - margin-left: auto; -} diff --git a/apps/mix-cms/src/app/components/action-collapse/action-collapse.component.ts b/apps/mix-cms/src/app/components/action-collapse/action-collapse.component.ts deleted file mode 100644 index 48bd5266..00000000 --- a/apps/mix-cms/src/app/components/action-collapse/action-collapse.component.ts +++ /dev/null @@ -1,78 +0,0 @@ -import { CommonModule } from '@angular/common'; -import { Component, Input, ViewEncapsulation } from '@angular/core'; -import { FormsModule } from '@angular/forms'; -import { MixButtonComponent } from '@mixcore/ui/button'; -import { - TuiDataListModule, - TuiDropdownModule, - TuiGroupModule, - TuiHostedDropdownModule, - TuiSvgModule, -} from '@taiga-ui/core'; -import { - TuiBadgeModule, - TuiCheckboxBlockModule, - TuiItemsWithMoreModule, -} from '@taiga-ui/kit'; - -@Component({ - selector: 'mix-action-collapse', - standalone: true, - imports: [ - CommonModule, - TuiItemsWithMoreModule, - MixButtonComponent, - TuiDropdownModule, - TuiSvgModule, - TuiDataListModule, - TuiBadgeModule, - TuiHostedDropdownModule, - TuiCheckboxBlockModule, - FormsModule, - TuiGroupModule, - ], - templateUrl: './action-collapse.component.html', - styleUrls: ['./action-collapse.component.scss'], - encapsulation: ViewEncapsulation.None, -}) -export class ActionCollapseComponent { - @Input() public actions = [ - { - label: 'Create', - key: 'create', - icon: 'edit', - place: 'left', - type: 'primary', - }, - { - label: 'Delete', - key: 'delete', - icon: 'delete', - place: 'left', - type: 'danger', - }, - { - label: 'Export', - key: 'export', - icon: 'system_update_alt', - place: 'left', - }, - ]; - - @Input() public actionMaps: { [key: string]: () => void } = { - create: () => { - // - }, - delete: () => { - // - }, - export: () => { - // - }, - }; - - public onClick(key: string) { - const action = this.actionMaps[key]; - if (action) action(); - } -} diff --git a/apps/mix-cms/src/app/components/compress-image/compress-image.component.html b/apps/mix-cms/src/app/components/compress-image/compress-image.component.html deleted file mode 100644 index d2c44156..00000000 --- a/apps/mix-cms/src/app/components/compress-image/compress-image.component.html +++ /dev/null @@ -1,62 +0,0 @@ -
- - - - - - - - - - - - - -
- - - - diff --git a/apps/mix-cms/src/app/components/compress-image/compress-image.component.scss b/apps/mix-cms/src/app/components/compress-image/compress-image.component.scss deleted file mode 100644 index ab8e1d30..00000000 --- a/apps/mix-cms/src/app/components/compress-image/compress-image.component.scss +++ /dev/null @@ -1,16 +0,0 @@ -.compress-image { - width: 60px; - height: 30px; - border-radius: 6px; - overflow: hidden; - border: 1px solid var(--border-color-default); - position: relative; - cursor: zoom-in; - - .loading-svg { - width: 60px; - height: 30px; - position: absolute; - top: 0; - } -} diff --git a/apps/mix-cms/src/app/components/compress-image/compress-image.component.ts b/apps/mix-cms/src/app/components/compress-image/compress-image.component.ts deleted file mode 100644 index 95c1bf4e..00000000 --- a/apps/mix-cms/src/app/components/compress-image/compress-image.component.ts +++ /dev/null @@ -1,121 +0,0 @@ -import { CommonModule } from '@angular/common'; -import { HttpClient } from '@angular/common/http'; -import { - AfterViewInit, - Component, - ElementRef, - Input, - ViewChild, - inject, - signal, -} from '@angular/core'; -import { TippyDirective } from '@ngneat/helipopper'; -import { TuiDestroyService } from '@taiga-ui/cdk'; - -@Component({ - selector: 'mix-compress-image', - standalone: true, - imports: [CommonModule, TippyDirective], - templateUrl: './compress-image.component.html', - styleUrls: ['./compress-image.component.scss'], - providers: [TuiDestroyService], -}) -export class CompressImageComponent implements AfterViewInit { - @ViewChild('canvas') canvasEl!: ElementRef; - @ViewChild('canvas2', { static: false }) - canvas2El!: ElementRef; - - @Input() public set src(v: string | null) { - this._src = v || ''; - this.loadData(); - } - - public get src() { - return this._src; - } - - public httpClient = inject(HttpClient); - public destroy$ = inject(TuiDestroyService); - public loading = signal(true); - public image = new Image(); - - private _src!: string; - - async ngAfterViewInit() { - this.loadData(); - } - - public loadData() { - if (!this.canvasEl) return; - - this.loading.set(true); - const canvas = this.canvasEl.nativeElement; - const ctx = this.canvasEl.nativeElement.getContext('2d'); - ctx?.clearRect(0, 0, canvas.width, canvas.height); - - this.image.addEventListener( - 'load', - () => { - this.scaleImage(this.image, this.canvasEl.nativeElement); - this.loading.set(false); - }, - false - ); - - this.image.addEventListener( - 'error', - () => { - this.image.src = 'assets/images/image_placeholder.jpg'; - }, - false - ); - - this.image.src = this.src!; - } - - public scaleImage(image: HTMLImageElement, canvas: HTMLCanvasElement) { - const ctx = canvas.getContext('2d'); - const imageAspectRatio = image.width / image.height; - const canvasAspectRatio = canvas.width / canvas.height; - let sourceX, sourceY, sourceWidth, sourceHeight; - - if (imageAspectRatio > canvasAspectRatio) { - sourceWidth = image.height * canvasAspectRatio; - sourceHeight = image.height; - sourceX = (image.width - sourceWidth) / 2; - sourceY = 0; - } else { - sourceWidth = image.width; - sourceHeight = image.width / canvasAspectRatio; - sourceX = 0; - sourceY = (image.height - sourceHeight) / 2; - } - - const destWidth: number = canvas.width; - const destHeight: number = canvas.height; - - ctx?.drawImage( - image, - sourceX, - sourceY, - sourceWidth, - sourceHeight, - 0, - 0, - destWidth, - destHeight - ); - } - - public showPreview(show: boolean) { - if (this.loading()) return; - - if (show) { - setTimeout(() => { - if (this.canvas2El) { - this.scaleImage(this.image, this.canvas2El.nativeElement); - } - }, 100); - } - } -} diff --git a/apps/mix-cms/src/app/components/database-select/database-filter.pipe.ts b/apps/mix-cms/src/app/components/database-select/database-filter.pipe.ts deleted file mode 100644 index 46f803a8..00000000 --- a/apps/mix-cms/src/app/components/database-select/database-filter.pipe.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { Pipe, PipeTransform } from '@angular/core'; -import { MixDatabase } from '@mixcore/lib/model'; - -@Pipe({ - name: 'filter', - pure: true, - standalone: true, -}) -export class DatabaseFilterPipe implements PipeTransform { - transform(searchText: string | null, list: MixDatabase[]): MixDatabase[] { - if (!searchText) return list; - - return list.filter((d) => - d.displayName - .trim() - .toLowerCase() - .includes(searchText.trim().toLowerCase()) - ); - } -} diff --git a/apps/mix-cms/src/app/components/database-select/database-select.component.html b/apps/mix-cms/src/app/components/database-select/database-select.component.html deleted file mode 100644 index e4c25a0c..00000000 --- a/apps/mix-cms/src/app/components/database-select/database-select.component.html +++ /dev/null @@ -1,37 +0,0 @@ - -
- - add  New Table - - - - -
- {{ prefix }} Tables ({{ vm.data.length || '0' }}) -
- -
- - - - - -
- - {{ table.displayName }} -
-
-
-
-
diff --git a/apps/mix-cms/src/app/components/database-select/database-select.component.scss b/apps/mix-cms/src/app/components/database-select/database-select.component.scss deleted file mode 100644 index 6407fcdb..00000000 --- a/apps/mix-cms/src/app/components/database-select/database-select.component.scss +++ /dev/null @@ -1,50 +0,0 @@ -.database-select { - width: 100%; - height: 100%; - padding: 1rem; - display: flex; - flex-direction: column; - box-shadow: -25px 5px 25px -40px #00000080 inset; - border: 1px solid var(--border-color-default); - - &__add-btn { - width: 100%; - margin-bottom: 6px; - display: block; - } - - &__title { - font-size: var(--text-size-xs); - margin-bottom: 0.5rem; - margin-top: 1rem; - font-weight: 500; - opacity: 0.7; - margin-left: 6px; - } - - &__list { - flex-grow: 1; - overflow: auto; - } - - &__item { - display: flex; - align-items: center; - font-weight: 500; - gap: 0.5rem; - padding: 0.5rem; - border-radius: 4px; - overflow: hidden; - cursor: pointer; - white-space: nowrap; - text-overflow: ellipsis; - font-size: var(--text-size-xs); - - &.--active, - &:hover { - opacity: 1; - background: var(--blue-500); - color: var(--white-0); - } - } -} diff --git a/apps/mix-cms/src/app/components/database-select/database-select.component.ts b/apps/mix-cms/src/app/components/database-select/database-select.component.ts deleted file mode 100644 index 0cbc9da2..00000000 --- a/apps/mix-cms/src/app/components/database-select/database-select.component.ts +++ /dev/null @@ -1,58 +0,0 @@ -import { CommonModule } from '@angular/common'; -import { - ChangeDetectionStrategy, - Component, - EventEmitter, - Input, - Output, - inject, -} from '@angular/core'; -import { FormControl, ReactiveFormsModule } from '@angular/forms'; -import { Router } from '@angular/router'; -import { MixDatabase } from '@mixcore/lib/model'; -import { MixButtonComponent } from '@mixcore/ui/button'; -import { MixInputComponent } from '@mixcore/ui/input'; -import { SkeletonLoadingComponent } from '@mixcore/ui/skeleton'; -import { CMS_ROUTES } from '../../app.routes'; -import { DatabaseStore } from '../../stores/database.store'; -import { DatabaseFilterPipe } from './database-filter.pipe'; - -@Component({ - selector: 'mix-database-select', - standalone: true, - imports: [ - CommonModule, - MixButtonComponent, - MixInputComponent, - DatabaseFilterPipe, - ReactiveFormsModule, - SkeletonLoadingComponent, - ], - templateUrl: './database-select.component.html', - styleUrls: ['./database-select.component.scss'], - changeDetection: ChangeDetectionStrategy.OnPush, -}) -export class DatabaseSelectComponent { - public store = inject(DatabaseStore); - public router = inject(Router); - - public searchText = new FormControl(''); - - @Input() public prefix = ''; - @Input() public isCreate = false; - @Input() public selectedItemId?: number; - @Input() public selectedItemName?: string; - @Output() public selectedItemChange = new EventEmitter(); - - public selectDb(mixDb: MixDatabase) { - this.selectedItemId = mixDb.id; - this.selectedItemChange.emit(mixDb); - } - - public createDb() { - this.isCreate = true; - this.selectedItemId = undefined; - - this.router.navigateByUrl(`${CMS_ROUTES.portal.database.fullPath}/create`); - } -} diff --git a/apps/mix-cms/src/app/components/dynamic-data-display/dynamic-data-display.component.ts b/apps/mix-cms/src/app/components/dynamic-data-display/dynamic-data-display.component.ts index 605cfcea..2febb43f 100644 --- a/apps/mix-cms/src/app/components/dynamic-data-display/dynamic-data-display.component.ts +++ b/apps/mix-cms/src/app/components/dynamic-data-display/dynamic-data-display.component.ts @@ -1,7 +1,7 @@ import { CommonModule } from '@angular/common'; import { Component, Input } from '@angular/core'; import { MixColumn, MixDynamicDataValue } from '@mixcore/lib/model'; -import { CompressImageComponent } from '../compress-image/compress-image.component'; +import { CompressImageComponent } from '@mixcore/share/components'; @Component({ selector: 'mix-dynamic-data-display', diff --git a/apps/mix-cms/src/app/components/dynamic-db-list/dynamic-db-list.component.ts b/apps/mix-cms/src/app/components/dynamic-db-list/dynamic-db-list.component.ts index 9dfec3e3..cb3a4e97 100644 --- a/apps/mix-cms/src/app/components/dynamic-db-list/dynamic-db-list.component.ts +++ b/apps/mix-cms/src/app/components/dynamic-db-list/dynamic-db-list.component.ts @@ -35,6 +35,7 @@ import { TuiFileLike } from '@taiga-ui/kit'; import { forkJoin, take } from 'rxjs'; import { FormlyMixModule } from '../../shares/kits/formly-mix.module'; +import { CompressImageComponent } from '@mixcore/share/components'; import { MixInputComponent } from '@mixcore/ui/input'; import { MixInputNumberComponent } from '@mixcore/ui/input-number'; import { SkeletonLoadingComponent } from '@mixcore/ui/skeleton'; @@ -42,7 +43,6 @@ import { EditableModule } from '@ngneat/edit-in-place'; import { TuiSidebarModule } from '@taiga-ui/addon-mobile'; import { TuiActiveZoneModule } from '@taiga-ui/cdk'; import { TuiDataListModule, TuiHostedDropdownModule } from '@taiga-ui/core'; -import { CompressImageComponent } from '../compress-image/compress-image.component'; import { DynamicDataDisplayComponent } from '../dynamic-data-display/dynamic-data-display.component'; @Component({ diff --git a/apps/mix-cms/src/app/components/record-form/record-form.component.html b/apps/mix-cms/src/app/components/record-form/record-form.component.html deleted file mode 100644 index 507a233f..00000000 --- a/apps/mix-cms/src/app/components/record-form/record-form.component.html +++ /dev/null @@ -1,25 +0,0 @@ -
-
- {{ mode === 'create' ? 'Create' : 'Update'}} record from {{ ref.data.mixDatabase.displayName }} -
- -
-
- -
-
- - -
diff --git a/apps/mix-cms/src/app/components/record-form/record-form.component.scss b/apps/mix-cms/src/app/components/record-form/record-form.component.scss deleted file mode 100644 index e69de29b..00000000 diff --git a/apps/mix-cms/src/app/components/record-form/record-form.component.ts b/apps/mix-cms/src/app/components/record-form/record-form.component.ts deleted file mode 100644 index c342f4a5..00000000 --- a/apps/mix-cms/src/app/components/record-form/record-form.component.ts +++ /dev/null @@ -1,92 +0,0 @@ -import { CommonModule } from '@angular/common'; -import { - ChangeDetectionStrategy, - Component, - OnInit, - inject, -} from '@angular/core'; -import { FormGroup, ReactiveFormsModule } from '@angular/forms'; -import { MixDatabase, MixDynamicData } from '@mixcore/lib/model'; -import { MixApiFacadeService } from '@mixcore/share/api'; -import { BaseComponent } from '@mixcore/share/base'; -import { Utils } from '@mixcore/share/utils'; -import { MixButtonComponent } from '@mixcore/ui/button'; -import { DialogRef } from '@ngneat/dialog'; -import { FormlyFieldConfig } from '@ngx-formly/core'; -import { TuiFileLike } from '@taiga-ui/kit'; -import { FormlyMixModule } from '../../shares/kits/formly-mix.module'; - -@Component({ - selector: 'mix-record-form', - standalone: true, - imports: [ - CommonModule, - ReactiveFormsModule, - FormlyMixModule, - MixButtonComponent, - ], - templateUrl: './record-form.component.html', - styleUrls: ['./record-form.component.scss'], - changeDetection: ChangeDetectionStrategy.OnPush, -}) -export class RecordFormComponent extends BaseComponent implements OnInit { - mixApi = inject(MixApiFacadeService); - ref: DialogRef< - { - mixDatabase: MixDatabase; - data: MixDynamicData | undefined; - }, - MixDynamicData - > = inject(DialogRef); - - public uploadFileFn = (file: TuiFileLike) => { - const formData = new FormData(); - formData.append('file', file as File); - formData.append('folder', 'MixContent/StaticFiles'); - - return this.mixApi.uploadApi.uploadFile(formData); - }; - - public deleteFileFn = (file: string) => { - return this.mixApi.uploadApi.deleteFile(file); - }; - - public modelData: MixDynamicData = {}; - public fields: FormlyFieldConfig[] = []; - public form = new FormGroup({}); - public mode: 'create' | 'update' = 'create'; - - ngOnInit() { - const db = this.ref.data.mixDatabase; - const data = this.ref.data.data ?? {}; - this.mode = data ? 'update' : 'create'; - - const { model, fields } = Utils.BuildDynamicFormField( - db.columns, - data, - this.uploadFileFn, - this.deleteFileFn - ); - - this.fields = fields; - this.modelData = model; - } - - public onSaveData() { - const db = this.ref.data.mixDatabase; - this.mixApi.databaseApi - .saveData( - db.systemName, - this.modelData.id ?? -1, - { - ...this.modelData, - ...this.form.getRawValue(), - }, - db.displayName - ) - .pipe(this.observerLoadingState()) - .subscribe((result) => { - this.ref.close(result); - }); - } -} diff --git a/apps/mix-cms/src/app/components/user-avatar/user-avatar.component.html b/apps/mix-cms/src/app/components/user-avatar/user-avatar.component.html deleted file mode 100644 index 78162708..00000000 --- a/apps/mix-cms/src/app/components/user-avatar/user-avatar.component.html +++ /dev/null @@ -1,5 +0,0 @@ - diff --git a/apps/mix-cms/src/app/components/user-avatar/user-avatar.component.scss b/apps/mix-cms/src/app/components/user-avatar/user-avatar.component.scss deleted file mode 100644 index b1b8aebf..00000000 --- a/apps/mix-cms/src/app/components/user-avatar/user-avatar.component.scss +++ /dev/null @@ -1,5 +0,0 @@ -:host { - display: inline-block; - border-radius: 50%; - z-index: 1; -} diff --git a/apps/mix-cms/src/app/components/user-avatar/user-avatar.component.ts b/apps/mix-cms/src/app/components/user-avatar/user-avatar.component.ts deleted file mode 100644 index 95ce1e0f..00000000 --- a/apps/mix-cms/src/app/components/user-avatar/user-avatar.component.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { ChangeDetectionStrategy, Component, Input } from '@angular/core'; -import { CommonModule } from '@angular/common'; -import { TuiAvatarModule } from '@taiga-ui/kit'; -import { TippyDirective } from '@ngneat/helipopper'; -import { UserListVm } from '@mixcore/lib/model'; - -@Component({ - selector: 'mix-user-avatar', - standalone: true, - imports: [CommonModule, TuiAvatarModule, TippyDirective], - templateUrl: './user-avatar.component.html', - styleUrls: ['./user-avatar.component.scss'], - changeDetection: ChangeDetectionStrategy.OnPush, -}) -export class UserAvatarComponent { - @Input() public userInfo!: UserListVm; - @Input() public size: 'l' | 's' | 'xs' = 'l'; -} diff --git a/apps/mix-cms/src/app/pages/portal/database-data/database-data.component.html b/apps/mix-cms/src/app/pages/portal/database-data/database-data.component.html index ec97052a..f37ac68b 100644 --- a/apps/mix-cms/src/app/pages/portal/database-data/database-data.component.html +++ b/apps/mix-cms/src/app/pages/portal/database-data/database-data.component.html @@ -61,6 +61,7 @@ diff --git a/apps/mix-cms/src/app/pages/portal/database-data/database-data.component.ts b/apps/mix-cms/src/app/pages/portal/database-data/database-data.component.ts index 545a02a6..e7f24ac3 100644 --- a/apps/mix-cms/src/app/pages/portal/database-data/database-data.component.ts +++ b/apps/mix-cms/src/app/pages/portal/database-data/database-data.component.ts @@ -7,9 +7,16 @@ import { } from '@angular/core'; import { FormControl, FormsModule, ReactiveFormsModule } from '@angular/forms'; import { ActivatedRoute } from '@angular/router'; -import { MixDatabase, MixDynamicData } from '@mixcore/lib/model'; +import { MixDatabase, MixDynamicData, MixFilter } from '@mixcore/lib/model'; import { MixApiFacadeService } from '@mixcore/share/api'; -import { BasicMixFilterComponent } from '@mixcore/share/components'; +import { + ActionCollapseComponent, + BasicMixFilterComponent, + DatabaseSelectComponent, + MixStatusIndicatorComponent, + MixSubToolbarComponent, + RecordFormComponent, +} from '@mixcore/share/components'; import { DomHelper, toastObserverProcessing } from '@mixcore/share/helper'; import { RelativeTimeSpanPipe } from '@mixcore/share/pipe'; import { MixButtonComponent } from '@mixcore/ui/button'; @@ -38,11 +45,7 @@ import { tap, } from 'rxjs'; import { CMS_ROUTES } from '../../../app.routes'; -import { ActionCollapseComponent } from '../../../components/action-collapse/action-collapse.component'; -import { DatabaseSelectComponent } from '../../../components/database-select/database-select.component'; -import { RecordFormComponent } from '../../../components/record-form/record-form.component'; -import { MixStatusIndicatorComponent } from '../../../components/status-indicator/mix-status-indicator.component'; -import { MixSubToolbarComponent } from '../../../components/sub-toolbar/sub-toolbar.component'; + import { ListPageKit } from '../../../shares/kits/list-page-kit.component'; import { DatabaseDataStore } from '../../../stores/database-data.store'; import { CustomActionCellComponent } from './components/custom-action-cell/custom-action-cell.component'; @@ -344,6 +347,10 @@ export class DatabaseDataComponent }); } + public onFilterChange(value: MixFilter[]) { + this.store.changeFilters(value); + } + public editData(dataId: number) { this.store.state$.pipe(take(1)).subscribe((state) => { if (!state.db) return; diff --git a/apps/mix-cms/src/app/pages/portal/database/database-detail/database-detail.component.ts b/apps/mix-cms/src/app/pages/portal/database/database-detail/database-detail.component.ts index 19d82a36..0ba90113 100644 --- a/apps/mix-cms/src/app/pages/portal/database/database-detail/database-detail.component.ts +++ b/apps/mix-cms/src/app/pages/portal/database/database-detail/database-detail.component.ts @@ -23,6 +23,7 @@ import { } from '@angular/forms'; import { Router } from '@angular/router'; import { MixColumn, MixDatabase } from '@mixcore/lib/model'; +import { DatabaseSelectComponent } from '@mixcore/share/components'; import { FormHelper, MixFormErrorComponent } from '@mixcore/share/form'; import { toastObserverProcessing } from '@mixcore/share/helper'; import { MixButtonComponent } from '@mixcore/ui/button'; @@ -41,7 +42,6 @@ import { } from '@taiga-ui/kit'; import { debounceTime, takeUntil } from 'rxjs'; import { CMS_ROUTES } from '../../../../app.routes'; -import { DatabaseSelectComponent } from '../../../../components/database-select/database-select.component'; import { EntityFormComponent } from '../../../../components/entity-form/entity-form.component'; import { DetailPageKit } from '../../../../shares/kits/page-detail-base-kit.component'; import { DatabaseStore } from '../../../../stores/database.store'; diff --git a/apps/mix-cms/src/app/pages/portal/database/database-document/database-document.component.ts b/apps/mix-cms/src/app/pages/portal/database/database-document/database-document.component.ts index 8bd0105b..156517d9 100644 --- a/apps/mix-cms/src/app/pages/portal/database/database-document/database-document.component.ts +++ b/apps/mix-cms/src/app/pages/portal/database/database-document/database-document.component.ts @@ -12,8 +12,8 @@ import { import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { ActivatedRoute } from '@angular/router'; import { MixDatabase } from '@mixcore/lib/model'; +import { DatabaseSelectComponent } from '@mixcore/share/components'; import { TuiAccordionModule } from '@taiga-ui/kit'; -import { DatabaseSelectComponent } from '../../../../components/database-select/database-select.component'; import { mixDbDocumentJsonGenerator } from './database-document.generator'; export interface DbDocument { diff --git a/apps/mix-cms/src/app/pages/portal/discount/discount.component.ts b/apps/mix-cms/src/app/pages/portal/discount/discount.component.ts index f84e650f..4a12efa1 100644 --- a/apps/mix-cms/src/app/pages/portal/discount/discount.component.ts +++ b/apps/mix-cms/src/app/pages/portal/discount/discount.component.ts @@ -25,6 +25,10 @@ import { PaginationRequestModel, } from '@mixcore/lib/model'; import { MixApiFacadeService } from '@mixcore/share/api'; +import { + CompressImageComponent, + MixSubToolbarComponent, +} from '@mixcore/share/components'; import { ImageHandleDirective } from '@mixcore/share/directives'; import { FormHelper } from '@mixcore/share/form'; import { MixUtcDatePipe, RelativeTimeSpanPipe } from '@mixcore/share/pipe'; @@ -58,9 +62,7 @@ import { import { debounceTime, forkJoin, takeUntil } from 'rxjs'; import { CMS_ROUTES } from '../../../app.routes'; import { BulkAssignMetadataComponent } from '../../../components/bulk-assign-metadata/bulk-assign-metadata.component'; -import { CompressImageComponent } from '../../../components/compress-image/compress-image.component'; import { MixStatusIndicatorComponent } from '../../../components/status-indicator/mix-status-indicator.component'; -import { MixSubToolbarComponent } from '../../../components/sub-toolbar/sub-toolbar.component'; import { DiscountStore } from '../../../stores/discount.store'; @Component({ diff --git a/apps/mix-cms/src/app/pages/portal/module/module.component.ts b/apps/mix-cms/src/app/pages/portal/module/module.component.ts index 0e37559a..92a4008c 100644 --- a/apps/mix-cms/src/app/pages/portal/module/module.component.ts +++ b/apps/mix-cms/src/app/pages/portal/module/module.component.ts @@ -11,12 +11,12 @@ import { MixSubToolbarComponent } from '../../../components/sub-toolbar/sub-tool import { Router } from '@angular/router'; import { MixModule } from '@mixcore/lib/model'; import { MixApiFacadeService } from '@mixcore/share/api'; +import { CompressImageComponent } from '@mixcore/share/components'; import { ImageHandleDirective } from '@mixcore/share/directives'; import { RelativeTimeSpanPipe } from '@mixcore/share/pipe'; import { MixDataTableModule, TableContextMenu } from '@mixcore/ui/table'; import { HotToastService } from '@ngneat/hot-toast'; import { CMS_ROUTES } from '../../../app.routes'; -import { CompressImageComponent } from '../../../components/compress-image/compress-image.component'; import { MixStatusIndicatorComponent } from '../../../components/status-indicator/mix-status-indicator.component'; import { ModuleStore } from '../../../stores/module.store'; diff --git a/apps/mix-cms/src/app/pages/portal/order/order.component.ts b/apps/mix-cms/src/app/pages/portal/order/order.component.ts index 44b0a4b5..c78d8212 100644 --- a/apps/mix-cms/src/app/pages/portal/order/order.component.ts +++ b/apps/mix-cms/src/app/pages/portal/order/order.component.ts @@ -21,6 +21,11 @@ import { PaymentGateway, } from '@mixcore/lib/model'; import { MixApiFacadeService } from '@mixcore/share/api'; +import { + CompressImageComponent, + MixStatusIndicatorComponent, + MixSubToolbarComponent, +} from '@mixcore/share/components'; import { ImageHandleDirective } from '@mixcore/share/directives'; import { MixUtcDatePipe, @@ -55,12 +60,9 @@ import { import { debounceTime, interval, takeUntil } from 'rxjs'; import { CMS_ROUTES } from '../../../app.routes'; import { BulkAssignMetadataComponent } from '../../../components/bulk-assign-metadata/bulk-assign-metadata.component'; -import { CompressImageComponent } from '../../../components/compress-image/compress-image.component'; import { GatewayIndicatorComponent } from '../../../components/gateway-indicator/gateway-indicator.component'; import { OrderStatisticsComponent } from '../../../components/order-statistics/order-statistics.component'; import { OrderStatusIndicatorComponent } from '../../../components/order-status-indicator/order-status-indicator.component'; -import { MixStatusIndicatorComponent } from '../../../components/status-indicator/mix-status-indicator.component'; -import { MixSubToolbarComponent } from '../../../components/sub-toolbar/sub-toolbar.component'; import { ListPageKit } from '../../../shares/kits/list-page-kit.component'; import { OrderStore } from '../../../stores/order.store'; diff --git a/apps/mix-cms/src/app/pages/portal/page/page.component.ts b/apps/mix-cms/src/app/pages/portal/page/page.component.ts index 56f5796f..af23a62f 100644 --- a/apps/mix-cms/src/app/pages/portal/page/page.component.ts +++ b/apps/mix-cms/src/app/pages/portal/page/page.component.ts @@ -12,13 +12,15 @@ import { PageStore } from '../../../stores/page.store'; import { Router } from '@angular/router'; import { MixPage } from '@mixcore/lib/model'; import { MixApiFacadeService } from '@mixcore/share/api'; +import { + CompressImageComponent, + MixStatusIndicatorComponent, +} from '@mixcore/share/components'; import { ImageHandleDirective } from '@mixcore/share/directives'; import { RelativeTimeSpanPipe } from '@mixcore/share/pipe'; import { MixDataTableModule, TableContextMenu } from '@mixcore/ui/table'; import { HotToastService } from '@ngneat/hot-toast'; import { CMS_ROUTES } from '../../../app.routes'; -import { CompressImageComponent } from '../../../components/compress-image/compress-image.component'; -import { MixStatusIndicatorComponent } from '../../../components/status-indicator/mix-status-indicator.component'; @Component({ selector: 'mix-page', standalone: true, diff --git a/apps/mix-cms/src/app/pages/portal/post/post.component.ts b/apps/mix-cms/src/app/pages/portal/post/post.component.ts index 68f08c5a..9291aba4 100644 --- a/apps/mix-cms/src/app/pages/portal/post/post.component.ts +++ b/apps/mix-cms/src/app/pages/portal/post/post.component.ts @@ -28,6 +28,7 @@ import { ImageHandleDirective } from '@mixcore/share/directives'; import { FormHelper } from '@mixcore/share/form'; import { toastObserverProcessing } from '@mixcore/share/helper'; +import { CompressImageComponent } from '@mixcore/share/components'; import { MixImgLoaderPipe, MixUtcDatePipe, @@ -63,7 +64,6 @@ import { import { debounceTime, forkJoin, takeUntil, tap } from 'rxjs'; import { CMS_ROUTES } from '../../../app.routes'; import { BulkAssignMetadataComponent } from '../../../components/bulk-assign-metadata/bulk-assign-metadata.component'; -import { CompressImageComponent } from '../../../components/compress-image/compress-image.component'; import { MixStatusIndicatorComponent } from '../../../components/status-indicator/mix-status-indicator.component'; import { MixSubToolbarComponent } from '../../../components/sub-toolbar/sub-toolbar.component'; import { PostStore } from '../../../stores/post.store'; diff --git a/apps/mix-cms/src/app/pages/portal/task-manage/components/task-card/task-card.component.ts b/apps/mix-cms/src/app/pages/portal/task-manage/components/task-card/task-card.component.ts index 1e369f7d..94f8626e 100644 --- a/apps/mix-cms/src/app/pages/portal/task-manage/components/task-card/task-card.component.ts +++ b/apps/mix-cms/src/app/pages/portal/task-manage/components/task-card/task-card.component.ts @@ -12,9 +12,9 @@ import { TaskTypeIcons, UserListVm, } from '@mixcore/lib/model'; +import { UserAvatarComponent } from '@mixcore/share/components'; import { DialogService } from '@ngneat/dialog'; import { take } from 'rxjs'; -import { UserAvatarComponent } from '../../../../../components/user-avatar/user-avatar.component'; import { UserInfoStore } from '../../../../../stores/user-info.store'; import { TaskDetailModalComponent } from '../task-detail-modal/task-detail-modal.component'; import { TaskPriorityComponent } from '../task-priority/task-priority.component'; diff --git a/apps/mix-cms/src/app/pages/portal/task-manage/components/task-filter/task-filter.component.ts b/apps/mix-cms/src/app/pages/portal/task-manage/components/task-filter/task-filter.component.ts index e6af562e..77d88d7a 100644 --- a/apps/mix-cms/src/app/pages/portal/task-manage/components/task-filter/task-filter.component.ts +++ b/apps/mix-cms/src/app/pages/portal/task-manage/components/task-filter/task-filter.component.ts @@ -7,13 +7,13 @@ import { inject, } from '@angular/core'; import { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms'; +import { UserAvatarComponent } from '@mixcore/share/components'; import { MixButtonComponent } from '@mixcore/ui/button'; import { MixInputComponent } from '@mixcore/ui/input'; import { SkeletonLoadingComponent } from '@mixcore/ui/skeleton'; import { tuiPure } from '@taiga-ui/cdk'; import { TuiLinkModule } from '@taiga-ui/core'; import { TuiFilterModule } from '@taiga-ui/kit'; -import { UserAvatarComponent } from '../../../../../components/user-avatar/user-avatar.component'; import { UserInfoStore } from '../../../../../stores/user-info.store'; import { TaskFilterStore } from '../../store/filter.store'; import { TaskStore } from '../../store/task.store'; diff --git a/apps/mix-cms/src/app/stores/database-data.store.ts b/apps/mix-cms/src/app/stores/database-data.store.ts index 6340d097..bc407f03 100644 --- a/apps/mix-cms/src/app/stores/database-data.store.ts +++ b/apps/mix-cms/src/app/stores/database-data.store.ts @@ -4,6 +4,7 @@ import { MixColumn, MixDatabase, MixDynamicData, + MixFilter, PaginationRequestModel, STRING_DATA_TYPE, } from '@mixcore/lib/model'; @@ -152,6 +153,24 @@ export class DatabaseDataStore extends ComponentStore { this.loadData(request, state.dbSysName); } + public changeFilters(filters: MixFilter[]) { + const state = this.get(); + if (!state.dbSysName) return; + + const request = { + ...state.request, + queries: filters, + } as PaginationRequestModel; + + this.patchState((s) => ({ + ...s, + loadDataError: false, + request: request, + })); + + this.loadData(request, state.dbSysName); + } + public reloadOnlyData() { const state = this.get(); if (!state.dbSysName) return; diff --git a/libs/mix-lib/src/model/pagination-request.model.ts b/libs/mix-lib/src/model/pagination-request.model.ts index 319bafaf..2070ca09 100644 --- a/libs/mix-lib/src/model/pagination-request.model.ts +++ b/libs/mix-lib/src/model/pagination-request.model.ts @@ -36,7 +36,7 @@ export type CompareOperator = | 'NotContain' | 'InRange'; -export const CompareOperatorDisplay: Record = { +export const OperatorDisplay: Record = { Like: 'Like', InRange: 'In Range', Equal: 'Equal', diff --git a/libs/mix-share/src/components/database-select/database-select.component.scss b/libs/mix-share/src/components/database-select/database-select.component.scss index 6407fcdb..713051ac 100644 --- a/libs/mix-share/src/components/database-select/database-select.component.scss +++ b/libs/mix-share/src/components/database-select/database-select.component.scss @@ -45,6 +45,7 @@ opacity: 1; background: var(--blue-500); color: var(--white-0); + opacity: 0.7; } } } diff --git a/libs/mix-share/src/pipes/index.ts b/libs/mix-share/src/pipes/index.ts index 691c1141..79194a44 100644 --- a/libs/mix-share/src/pipes/index.ts +++ b/libs/mix-share/src/pipes/index.ts @@ -2,3 +2,4 @@ export * from './count-up.pipe'; export * from './image-loader.pipe'; export * from './mix-date.pipe'; export * from './relative-timespan.pipe'; +export * from './trackby-prop.pipe'; diff --git a/libs/mix-share/src/pipes/trackby-prop.pipe.ts b/libs/mix-share/src/pipes/trackby-prop.pipe.ts new file mode 100644 index 00000000..3bdc0b95 --- /dev/null +++ b/libs/mix-share/src/pipes/trackby-prop.pipe.ts @@ -0,0 +1,17 @@ +import { NgForOf } from '@angular/common'; +import { Directive, Input, NgIterable, inject } from '@angular/core'; + +@Directive({ + selector: '[ngForTrackByProp]', + standalone: true, +}) +export class TrackByProp { + @Input() ngForOf!: NgIterable; + private ngFor = inject(NgForOf, { self: true }); + + @Input({ required: true }) + set ngForTrackByProp(trackByProp: keyof T) { + if (!trackByProp) return; + this.ngFor.ngForTrackBy = (index: number, item: T) => item[trackByProp]; + } +} diff --git a/libs/mix-ui/src/dynamic-filter/dynamic-filter.component.html b/libs/mix-ui/src/dynamic-filter/dynamic-filter.component.html index 0bbc13e4..57ff7a67 100644 --- a/libs/mix-ui/src/dynamic-filter/dynamic-filter.component.html +++ b/libs/mix-ui/src/dynamic-filter/dynamic-filter.component.html @@ -7,17 +7,22 @@

Filter Record(s)

- - + +
diff --git a/libs/mix-ui/src/dynamic-filter/dynamic-filter.component.ts b/libs/mix-ui/src/dynamic-filter/dynamic-filter.component.ts index 50f07809..c7e05d57 100644 --- a/libs/mix-ui/src/dynamic-filter/dynamic-filter.component.ts +++ b/libs/mix-ui/src/dynamic-filter/dynamic-filter.component.ts @@ -1,13 +1,16 @@ import { CommonModule } from '@angular/common'; import { Component, + EventEmitter, Input, + Output, TemplateRef, ViewEncapsulation, inject, } from '@angular/core'; -import { FormControl } from '@angular/forms'; -import { MixColumn } from '@mixcore/lib/model'; +import { MixColumn, MixFilter } from '@mixcore/lib/model'; +import { TrackByProp } from '@mixcore/share/pipe'; + import { MixButtonComponent } from '@mixcore/ui/button'; import { DialogService } from '@ngneat/dialog'; import { TippyDirective } from '@ngneat/helipopper'; @@ -25,25 +28,34 @@ export interface DynamicFilterValue { MixButtonComponent, TippyDirective, FilterItemComponent, + TrackByProp, ], templateUrl: './dynamic-filter.component.html', styleUrls: ['./dynamic-filter.component.scss'], encapsulation: ViewEncapsulation.None, }) export class DynamicFilterComponent { - @Input() public size: 's' | 'm' = 's'; - @Input() columns: MixColumn[] = []; - public dialog = inject(DialogService); - public filters: DynamicFilterValue[] = []; - public control = new FormControl(); + @Input() public size: 's' | 'm' = 's'; + @Input() columns: MixColumn[] = []; + @Input() public filters: MixFilter[] = []; + @Output() public filtersChange = new EventEmitter(); public open(tpl: TemplateRef) { this.dialog.open(tpl, { resizable: true, draggable: true }); } public add() { - this.filters.push({}); + this.filters.push({ + fieldName: this.columns[0].systemName, + value: null, + compareOperator: 'Like', + }); + } + + public onFilterValueChange(value: MixFilter, index: number) { + this.filters[index] = value; + this.filtersChange.emit(this.filters); } } diff --git a/libs/mix-ui/src/dynamic-filter/filter-input/filter-input.component.html b/libs/mix-ui/src/dynamic-filter/filter-input/filter-input.component.html index 9e633b41..b3bbb2e3 100644 --- a/libs/mix-ui/src/dynamic-filter/filter-input/filter-input.component.html +++ b/libs/mix-ui/src/dynamic-filter/filter-input/filter-input.component.html @@ -1 +1,11 @@ -

filter-input works!

+ + + + + diff --git a/libs/mix-ui/src/dynamic-filter/filter-input/filter-input.component.ts b/libs/mix-ui/src/dynamic-filter/filter-input/filter-input.component.ts index c310c783..a8749e5e 100644 --- a/libs/mix-ui/src/dynamic-filter/filter-input/filter-input.component.ts +++ b/libs/mix-ui/src/dynamic-filter/filter-input/filter-input.component.ts @@ -1,12 +1,55 @@ import { CommonModule } from '@angular/common'; -import { Component } from '@angular/core'; -import { MixInputComponent } from '../../input/input.component'; +import { Component, EventEmitter, Input, Output } from '@angular/core'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; +import { FormControl, ReactiveFormsModule } from '@angular/forms'; +import { DataType } from '@mixcore/lib/model'; +import { MixDatePickerComponent } from '@mixcore/ui/date-picker'; +import { MixInputComponent } from '@mixcore/ui/input'; +import { MixInputNumberComponent } from '@mixcore/ui/input-number'; +import { debounceTime } from 'rxjs'; @Component({ selector: 'mix-filter-input', standalone: true, - imports: [CommonModule, MixInputComponent], + imports: [ + CommonModule, + MixInputComponent, + MixDatePickerComponent, + MixInputNumberComponent, + ReactiveFormsModule, + ], templateUrl: './filter-input.component.html', styleUrls: ['./filter-input.component.scss'], }) -export class FilterInputComponent {} +export class FilterInputComponent { + @Output() valueChange = new EventEmitter(); + + public inputType: 'Text' | 'DatePicker' | 'Number' = 'Text'; + public control = new FormControl(); + + @Input() public set dataType(v: DataType) { + this._dataType = v; + + switch (v) { + case DataType.DateTime: + this.inputType = 'DatePicker'; + break; + case DataType.Integer: + this.inputType = 'Number'; + break; + default: + this.inputType = 'Text'; + } + } + + public get dataType() { + return this._dataType; + } + private _dataType: DataType = DataType.Text; + + constructor() { + this.control.valueChanges + .pipe(takeUntilDestroyed(), debounceTime(300)) + .subscribe((v) => this.valueChange.emit(v)); + } +} diff --git a/libs/mix-ui/src/dynamic-filter/filter-item/filter-item.component.html b/libs/mix-ui/src/dynamic-filter/filter-item/filter-item.component.html index 5701a8e6..f711a949 100644 --- a/libs/mix-ui/src/dynamic-filter/filter-item/filter-item.component.html +++ b/libs/mix-ui/src/dynamic-filter/filter-item/filter-item.component.html @@ -11,5 +11,8 @@ formControlName="operator" > - + diff --git a/libs/mix-ui/src/dynamic-filter/filter-item/filter-item.component.scss b/libs/mix-ui/src/dynamic-filter/filter-item/filter-item.component.scss index 5ff02f3e..7df9263f 100644 --- a/libs/mix-ui/src/dynamic-filter/filter-item/filter-item.component.scss +++ b/libs/mix-ui/src/dynamic-filter/filter-item/filter-item.component.scss @@ -2,4 +2,5 @@ display: grid; grid-template-columns: 120px 150px auto; grid-gap: 4px; + margin-bottom: 6px; } diff --git a/libs/mix-ui/src/dynamic-filter/filter-item/filter-item.component.ts b/libs/mix-ui/src/dynamic-filter/filter-item/filter-item.component.ts index 44465a60..decf7df9 100644 --- a/libs/mix-ui/src/dynamic-filter/filter-item/filter-item.component.ts +++ b/libs/mix-ui/src/dynamic-filter/filter-item/filter-item.component.ts @@ -1,10 +1,19 @@ import { CommonModule } from '@angular/common'; -import { Component, Input, inject } from '@angular/core'; +import { + Component, + DestroyRef, + EventEmitter, + Input, + Output, + inject, +} from '@angular/core'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { FormBuilder, ReactiveFormsModule } from '@angular/forms'; import { CompareOperator, - CompareOperatorDisplay, MixColumn, + MixFilter, + OperatorDisplay, } from '@mixcore/lib/model'; import { MixInputComponent } from '@mixcore/ui/input'; import { MixSelectComponent } from '@mixcore/ui/select'; @@ -24,46 +33,49 @@ import { FilterInputComponent } from '../filter-input/filter-input.component'; styleUrls: ['./filter-item.component.scss'], }) export class FilterItemComponent { - @Input() columns: MixColumn[] = []; - public columnLabel = (col: MixColumn) => (col ? col.displayName : ''); - - @Input() public operators = Object.keys(CompareOperatorDisplay); - public operatorLabel = (opr: CompareOperator) => - opr ? CompareOperatorDisplay[opr] : ''; + public destroyRef = inject(DestroyRef); - // public valueData = {}; - // public fields: FormlyFieldConfig[] = []; - // public valueForm = inject(FormBuilder).group({ - // value: null, - // }); + @Input() filter!: MixFilter; + @Input() public columns: MixColumn[] = []; + @Input() public operators = Object.keys(OperatorDisplay); + public columnLabel = (col: MixColumn) => col?.displayName ?? ''; + public operatorLabel = (opr: CompareOperator) => OperatorDisplay?.[opr] ?? ''; public form = inject(FormBuilder).group({ column: {}, - operator: {}, + operator: {}, }); - constructor() { - // this.form.controls.column.valueChanges - // .pipe(takeUntilDestroyed()) - // .subscribe((col: MixColumn | null) => { - // if (!col) return; - // this.valueData = Utils.initFormFieldDefaultValue( - // col.dataType, - // this.valueData - // ); - // this.fields = [ - // { - // key: 'value', - // type: col.dataType, - // props: { - // label: 'Value', - // }, - // }, - // ]; - // }); - } + @Output() public filterChange = new EventEmitter(); ngOnInit() { - this.form.controls.column.patchValue(this.columns[0]); - this.form.controls.operator.patchValue(this.operators[0]); + this.form.controls.column.patchValue( + this.columns.find((x) => x.systemName === this.filter.fieldName) ?? + this.columns[0] + ); + + this.form.controls.operator.patchValue( + this.operators.find((x) => x === this.filter.compareOperator) ?? + this.operators[0] + ); + + this.form.controls.column.valueChanges + .pipe(takeUntilDestroyed(this.destroyRef)) + .subscribe((v) => { + this.filter.fieldName = v!.systemName; + this.filter.value = ''; + this.filterChange.emit(this.filter); + }); + + this.form.controls.operator.valueChanges + .pipe(takeUntilDestroyed(this.destroyRef)) + .subscribe((v) => { + this.filter.compareOperator = v as CompareOperator; + this.filterChange.emit(this.filter); + }); + } + + public filterValueChange(value: string) { + this.filter.value = value; + this.filterChange.emit(this.filter); } }