From 99ca6623987957b3597a7de76281a8550a3f1e24 Mon Sep 17 00:00:00 2001 From: mchouliara Date: Thu, 29 Aug 2024 17:57:03 +0300 Subject: [PATCH] refactor plan listing filters, add css styles for buttons (WIP), add typing to base-criteria --- .../filtering/description-filter.component.ts | 2 +- .../misc/criteria/base-criteria.component.ts | 6 +- .../plan-filter-dialog.component.html | 3 +- .../plan-filter-dialog.component.ts | 30 ++-- .../filtering/plan-filter.component.html | 14 +- .../filtering/plan-filter.component.ts | 148 +++++++++--------- .../ui/plan/listing/plan-listing.component.ts | 17 +- frontend/src/styles.scss | 98 ++++++++++++ 8 files changed, 214 insertions(+), 104 deletions(-) diff --git a/frontend/src/app/ui/description/listing/filtering/description-filter.component.ts b/frontend/src/app/ui/description/listing/filtering/description-filter.component.ts index b738f5911..04596f99b 100644 --- a/frontend/src/app/ui/description/listing/filtering/description-filter.component.ts +++ b/frontend/src/app/ui/description/listing/filtering/description-filter.component.ts @@ -29,7 +29,7 @@ import { nameof } from 'ts-simple-nameof'; templateUrl: './description-filter.component.html', styleUrls: ['./description-filter.component.scss'] }) -export class DescriptionFilterComponent extends BaseCriteriaComponent implements OnInit, OnChanges { +export class DescriptionFilterComponent extends BaseCriteriaComponent implements OnInit, OnChanges { @Input() status; @Input() isPublic: boolean; diff --git a/frontend/src/app/ui/misc/criteria/base-criteria.component.ts b/frontend/src/app/ui/misc/criteria/base-criteria.component.ts index 15a1bcf78..fec4f24cd 100644 --- a/frontend/src/app/ui/misc/criteria/base-criteria.component.ts +++ b/frontend/src/app/ui/misc/criteria/base-criteria.component.ts @@ -1,13 +1,13 @@ import { OnInit, Directive } from '@angular/core'; -import { AbstractControl, UntypedFormArray, UntypedFormControl, UntypedFormGroup } from '@angular/forms'; +import { AbstractControl, FormGroup, UntypedFormArray, UntypedFormControl, UntypedFormGroup } from '@angular/forms'; import { BaseComponent } from '@common/base/base.component'; import { ValidationErrorModel } from '@common/forms/validation/error-model/validation-error-model'; @Directive() -export class BaseCriteriaComponent extends BaseComponent implements OnInit { +export class BaseCriteriaComponent; }> extends BaseComponent implements OnInit { public refreshCallback: Function = null; - public formGroup: UntypedFormGroup = null; + public formGroup: FormGroup = null; constructor( public validationErrorModel: ValidationErrorModel, diff --git a/frontend/src/app/ui/plan/listing/filtering/plan-filter-dialog/plan-filter-dialog.component.html b/frontend/src/app/ui/plan/listing/filtering/plan-filter-dialog/plan-filter-dialog.component.html index 85632c994..67ac5e6a2 100644 --- a/frontend/src/app/ui/plan/listing/filtering/plan-filter-dialog/plan-filter-dialog.component.html +++ b/frontend/src/app/ui/plan/listing/filtering/plan-filter-dialog/plan-filter-dialog.component.html @@ -1,7 +1,6 @@ clear ; + filters: PlanListingFilters; constructor( public dialogRef: MatDialogRef, @@ -27,21 +26,22 @@ export class PlanFilterDialogComponent implements OnInit { lookup: PlanLookup, referencesWithTypeItems: ReferencesWithType[], }) { - this.formGroup = this._buildFormFromLookup(data?.lookup) + this.filters = this._buildPlanFilters(data?.lookup, data?.referencesWithTypeItems) } ngOnInit() { this.analyticsService.trackPageView(AnalyticsService.PlanFilterDialog); } - private _buildFormFromLookup(lookup: PlanLookup): FormGroup { - return (new UntypedFormBuilder()).group({ - status: [lookup.statuses?.length > 0 ? lookup.statuses[0] : null], - viewOnlyTenant: [lookup.tenantSubQuery?.codes?.length > 0 ? true : false], - descriptionTemplates: lookup.planDescriptionTemplateSubQuery?.descriptionTemplateGroupIds ? [lookup.planDescriptionTemplateSubQuery?.descriptionTemplateGroupIds] : [], - planBlueprints: lookup.planBlueprintSubQuery?.ids ? [lookup.planBlueprintSubQuery?.ids]: [], - role: lookup.planUserSubQuery?.userRoles ? lookup.planUserSubQuery?.userRoles[0] : null, - }); + private _buildPlanFilters(lookup: PlanLookup, references: ReferencesWithType[]): PlanListingFilters { + return { + status: lookup.statuses?.[0] ?? null, + viewOnlyTenant: lookup.tenantSubQuery?.codes?.length > 0, + descriptionTemplates: lookup.planDescriptionTemplateSubQuery?.descriptionTemplateGroupIds ? lookup.planDescriptionTemplateSubQuery?.descriptionTemplateGroupIds : [], + planBlueprints: lookup.planBlueprintSubQuery?.ids ?? [], + role: lookup.planUserSubQuery?.userRoles?.[0] ?? null, + references: references ?? [] + } } onNoClick(): void { @@ -52,8 +52,8 @@ export class PlanFilterDialogComponent implements OnInit { this.dialogRef.close(); } - onFilterChanged(formGroup: UntypedFormGroup) { - this.dialogRef.close(formGroup.value as PlanListingFilters); + onFilterChanged(filters: PlanListingFilters) { + this.dialogRef.close(filters); } } diff --git a/frontend/src/app/ui/plan/listing/filtering/plan-filter.component.html b/frontend/src/app/ui/plan/listing/filtering/plan-filter.component.html index 729f194d7..209329ec4 100644 --- a/frontend/src/app/ui/plan/listing/filtering/plan-filter.component.html +++ b/frontend/src/app/ui/plan/listing/filtering/plan-filter.component.html @@ -65,7 +65,7 @@
{{'DESCRIPTION-LISTING.FILTERS.REFERENCE-TYPES.NAME' | translate }}
- +
@@ -103,12 +103,22 @@
-
+ + +
+
diff --git a/frontend/src/app/ui/plan/listing/filtering/plan-filter.component.ts b/frontend/src/app/ui/plan/listing/filtering/plan-filter.component.ts index e1b551503..e69638444 100644 --- a/frontend/src/app/ui/plan/listing/filtering/plan-filter.component.ts +++ b/frontend/src/app/ui/plan/listing/filtering/plan-filter.component.ts @@ -12,7 +12,7 @@ import { PlanUserRole } from '@app/core/common/enum/plan-user-role'; import { SingleAutoCompleteConfiguration } from '@app/library/auto-complete/single/single-auto-complete-configuration'; import { Guid } from '@common/types/guid'; import { ReferenceTypeService } from '@app/core/services/reference-type/reference-type.service'; -import { takeUntil } from 'rxjs'; +import { filter, map, Observable, takeUntil } from 'rxjs'; import { ReferenceService } from '@app/core/services/reference/reference.service'; import { ReferenceLookup } from '@app/core/query/reference.lookup'; import { IsActive } from '@notification-service/core/enum/is-active.enum'; @@ -27,13 +27,24 @@ import { ReferencesWithType } from '@app/core/query/description.lookup'; templateUrl: './plan-filter.component.html', styleUrls: ['./plan-filter.component.scss'], }) -export class PlanFilterComponent extends BaseCriteriaComponent implements OnInit, OnChanges { +export class PlanFilterComponent extends BaseCriteriaComponent implements OnInit { @Input() isPublic: boolean; @Input() hasSelectedTenant: boolean; - @Input() referencesWithTypeItems: ReferencesWithType[]; - @Input() filterFormGroup: FormGroup; - @Output() filterChanged: EventEmitter = new EventEmitter(); + + private _filters: PlanListingFilters; + @Input() set filters(v: PlanListingFilters){ + if(v){ + this._filters = v; + this.buildForm(v); + } + } + get filters(){ + return this._filters; + } + + @Output() filterChanged: EventEmitter = new EventEmitter(); + status = PlanStatusEnum; role = PlanUserRole; @@ -41,10 +52,10 @@ export class PlanFilterComponent extends BaseCriteriaComponent implements OnInit sizeError = false; maxFileSize: number = 1048576; - descriptionTemplateAutoCompleteConfiguration: MultipleAutoCompleteConfiguration; - planBlueprintAutoCompleteConfiguration: MultipleAutoCompleteConfiguration; - referenceTypeAutocompleteConfiguration: SingleAutoCompleteConfiguration; - referenceAutocompleteConfiguration: Map; + descriptionTemplateAutoCompleteConfiguration: MultipleAutoCompleteConfiguration = this.descriptionTemplateService.buildDescriptionTempalteGroupMultipleAutocompleteConfiguration(); + planBlueprintAutoCompleteConfiguration: MultipleAutoCompleteConfiguration = this.planBlueprintService.multipleAutocompleteConfiguration; + referenceTypeAutocompleteConfiguration: SingleAutoCompleteConfiguration = this.getReferenceTypeAutocompleteConfiguration(); + referenceAutocompleteConfiguration: Map; constructor( public language: TranslateService, @@ -62,40 +73,39 @@ export class PlanFilterComponent extends BaseCriteriaComponent implements OnInit super.ngOnInit(); } - ngOnChanges(changes: SimpleChanges): void { - if (changes['filterFormGroup']) { + buildForm(filters: PlanListingFilters){ + this.formGroup = new FormGroup({ + status: new FormControl(filters?.status), + descriptionTemplates: new FormControl(filters?.descriptionTemplates), + planBlueprints: new FormControl(filters?.planBlueprints), + role: new FormControl(filters?.role), + viewOnlyTenant: new FormControl(filters?.viewOnlyTenant ?? false), + references: new FormArray([]) + }); - this.descriptionTemplateAutoCompleteConfiguration = this.descriptionTemplateService.buildDescriptionTempalteGroupMultipleAutocompleteConfiguration(); - this.planBlueprintAutoCompleteConfiguration = this.planBlueprintService.multipleAutocompleteConfiguration; - this.referenceTypeAutocompleteConfiguration = this.getReferenceTypeAutocompleteConfiguration(); - this.referenceAutocompleteConfiguration = new Map(); + this.referenceAutocompleteConfiguration = new Map(); - this.formGroup = this.filterFormGroup; + filters?.references?.forEach((item: ReferencesWithType) => { + if (item.referenceTypeId) { + this.addReferenceType(item.referenceTypeId, item.referenceIds); + } + else if (item.referenceIds && item.referenceIds?.length > 0) { + this.referenceService.query(this._referenceLookup(item.referenceIds)).pipe(takeUntil(this._destroyed), map((x) => x.items)) + .subscribe((references: Reference[]) => { + const types = new Set(references.map((x) => x.type.id)); - this.referencesWithTypeItems.forEach((referencesWithType: ReferencesWithType) => { - if (referencesWithType.referenceTypeId) { - this.addReferenceType(referencesWithType.referenceTypeId.toString(), referencesWithType.referenceIds.map(x => x.toString())); - } - else if (referencesWithType.referenceIds && referencesWithType.referenceIds?.length > 0) { - this.referenceService.query(this._referenceLookup(referencesWithType.referenceIds)).pipe(takeUntil(this._destroyed)) - .subscribe((result: QueryResult) => { - const references: Reference[] = result.items; + types.forEach((typeId) => { + const referenceIds = references.filter((x) => x.type.id === typeId).map((x) => x.id) ?? [] + this.addReferenceType(typeId, referenceIds); + }) + }); + } + }); + } - const groupedReferencesByTypeIds = new Map(); - references.forEach(reference => { - if (!groupedReferencesByTypeIds.has(reference.type.id.toString())) groupedReferencesByTypeIds.set(reference.type.id.toString(), []); - - groupedReferencesByTypeIds.get(reference.type.id.toString()).push(reference.id.toString()); - }); - - groupedReferencesByTypeIds.forEach((referenceIds: string[], referenceId: string) => { - this.addReferenceType(referenceId, referenceIds); - }); - }); - } - }); - } - } + resetFilters(){ + this.buildForm(null); + } onCallbackError(error: any) { this.setErrorModel(error.error); @@ -103,37 +113,28 @@ export class PlanFilterComponent extends BaseCriteriaComponent implements OnInit controlModified(): void { this.clearErrorModel(); - this.filterChanged.emit(this.formGroup); - if (this.refreshCallback != null && - (this.formGroup.get('like').value == null || this.formGroup.get('like').value.length === 0 || this.formGroup.get('like').value.length > 2) - ) { - setTimeout(() => this.refreshCallback(true)); - } + this.filterChanged.emit(this.formGroup.value as PlanListingFilters); } - addReferenceType(referenceTypeId: string = null, referenceIds: string[] = null): void { - if (!this.formGroup.get('references')) this.formGroup.addControl('references', this.formBuilder.array([])); - - const formArray = this.formGroup.get('references') as UntypedFormArray; - - const referenceForm: UntypedFormGroup = this.formBuilder.group({ - referenceTypeId: referenceTypeId, - referenceIds: referenceIds ? [referenceIds] : null, + addReferenceType(referenceTypeId: Guid = null, referenceIds: Guid[] = null): void { + const referenceForm = new FormGroup({ + referenceTypeId: new FormControl(referenceTypeId), + referenceIds: new FormControl(referenceIds ? referenceIds : []), }); - if (referenceTypeId && referenceTypeId != '' && referenceIds && referenceIds.length > 0) { - let referenceAutocomplete = this.getReferenceAutocompleteConfiguration(Guid.parse(referenceTypeId)); - this.referenceAutocompleteConfiguration.set(referenceTypeId, referenceAutocomplete); + if (referenceTypeId && referenceIds?.length) { + let referenceAutocomplete = this.getReferenceAutocompleteConfiguration(referenceTypeId); + this.referenceAutocompleteConfiguration.set(referenceTypeId, referenceAutocomplete); } this._registerReferenceTypeListener(referenceForm); this._registerReferencesListener(referenceForm); - formArray.push(referenceForm); + this.formGroup.controls.references.push(referenceForm); } deleteRow(index: number): void { - const formArray = this.formGroup.get('references') as UntypedFormArray; + const formArray = this.formGroup.controls.references; formArray.removeAt(index); } @@ -142,7 +143,7 @@ export class PlanFilterComponent extends BaseCriteriaComponent implements OnInit return this.authentication.currentAccountIsAuthenticated(); } - selectReferenceAutocompleteConfiguration(referenceTypeId: string): MultipleAutoCompleteConfiguration { + selectReferenceAutocompleteConfiguration(referenceTypeId: Guid): MultipleAutoCompleteConfiguration { return this.referenceAutocompleteConfiguration.get(referenceTypeId); }; @@ -172,26 +173,26 @@ export class PlanFilterComponent extends BaseCriteriaComponent implements OnInit return lookup; } - private _registerReferenceTypeListener(control: AbstractControl) { - control.get('referenceTypeId')?.valueChanges.pipe(takeUntil(this._destroyed)) - .subscribe((referenceTypeId: string) => { + private _registerReferenceTypeListener(formGroup: FormGroup) { + formGroup.controls.referenceTypeId?.valueChanges.pipe(takeUntil(this._destroyed)) + .subscribe((referenceTypeId: Guid) => { this.referenceTypeAutocompleteConfiguration = this.getReferenceTypeAutocompleteConfiguration(); - control.get('referenceIds')?.reset(); + formGroup.controls.referenceIds?.reset(); - if (referenceTypeId && referenceTypeId != '') { - let referenceAutocomplete = this.getReferenceAutocompleteConfiguration(Guid.parse(referenceTypeId)); + if (referenceTypeId) { + let referenceAutocomplete = this.getReferenceAutocompleteConfiguration(referenceTypeId); this.referenceAutocompleteConfiguration.set(referenceTypeId, referenceAutocomplete); } }); } - private _registerReferencesListener(control: AbstractControl) { - control.get('referenceIds')?.valueChanges.pipe(takeUntil(this._destroyed)) + private _registerReferencesListener(formGroup: FormGroup) { + formGroup.controls.referenceIds?.valueChanges.pipe(takeUntil(this._destroyed)) .subscribe(references => { - let referenceTypeId = control.get('referenceTypeId').value; + let referenceTypeId = formGroup.controls.referenceTypeId.value; if (!referenceTypeId) return; - let referenceAutocomplete = this.getReferenceAutocompleteConfiguration(Guid.parse(referenceTypeId)); + let referenceAutocomplete = this.getReferenceAutocompleteConfiguration(referenceTypeId); this.referenceAutocompleteConfiguration.set(referenceTypeId, referenceAutocomplete); }); } @@ -206,11 +207,16 @@ export interface PlanListingFilters { references: ReferencesWithType[] } -export interface PlanListingFilterForm { +interface PlanListingFilterForm { status: FormControl, viewOnlyTenant: FormControl, descriptionTemplates: FormControl, planBlueprints: FormControl, role: FormControl, - references: FormArray + references: FormArray> } + +interface PlanListingFilterReferencesForm { + referenceTypeId: FormControl; + referenceIds: FormControl +} \ No newline at end of file diff --git a/frontend/src/app/ui/plan/listing/plan-listing.component.ts b/frontend/src/app/ui/plan/listing/plan-listing.component.ts index fd4cd67ca..48ef1627f 100644 --- a/frontend/src/app/ui/plan/listing/plan-listing.component.ts +++ b/frontend/src/app/ui/plan/listing/plan-listing.component.ts @@ -316,9 +316,7 @@ export class PlanListingComponent extends BaseListingComponent { - if (result) { - this.updateDataFn(result); - } + this.updateDataFn(result); }); } @@ -409,12 +407,11 @@ export class PlanListingComponent extends BaseListingComponent t.code && t.code?.toString() == this.authService.selectedTenant()); if (tenant && tenant?.code) { @@ -425,7 +422,7 @@ export class PlanListingComponent extends BaseListingComponent 0) { this.lookup.planDescriptionTemplateSubQuery = PlanFilterService.initializePlanDescriptionTemplateLookup(); this.lookup.planDescriptionTemplateSubQuery.descriptionTemplateGroupIds = descriptionTemplates; @@ -433,20 +430,20 @@ export class PlanListingComponent extends BaseListingComponent 0) { this.lookup.planBlueprintSubQuery = PlanFilterService.initializePlanBlueprintLookup(); this.lookup.planBlueprintSubQuery.ids = planBlueprints; } else this.lookup.planBlueprintSubQuery = null; // plans - let roles = filters.role !== null ? [filters.role] : null; + let roles = filters?.role !== null ? [filters.role] : null; if (roles && roles?.length > 0) { this.lookup.planUserSubQuery = PlanFilterService.initializePlanUserLookup(); this.lookup.planUserSubQuery.userRoles = roles; } else this.lookup.planUserSubQuery = null; - let references: Guid[] = filters.references + let references: Guid[] = filters?.references ?.filter((reference: ReferencesWithType) => reference.referenceTypeId != null && reference.referenceIds?.length > 0) ?.flatMap((referencesWithType: ReferencesWithType) => referencesWithType.referenceIds) as Guid[]; diff --git a/frontend/src/styles.scss b/frontend/src/styles.scss index a3b8aefcc..ba7d1e6ad 100644 --- a/frontend/src/styles.scss +++ b/frontend/src/styles.scss @@ -400,3 +400,101 @@ $mat-dark-theme: mat.m2-define-dark-theme((color: (primary: $mat-dark-theme-prim .dense-10 { @include mat.all-component-densities(-10); } + +.mdc-button,.mat-mdc-button, .mdc-button:has(.material-icons,mat-icon,[matButtonIcon]) { + &.rounded-btn{ + height: 40px; + border-radius: 30px; + border: none; + opacity: 1; + padding-left: 2em; + padding-right: 2em; + box-shadow: 0px 3px 6px #1E202029; + &:hover { + box-shadow: var(--mdc-protected-button-hover-container-elevation-shadow); + } + } + &.neutral { + background: #ffffff 0% 0% no-repeat padding-box; + border: 1px solid #b5b5b5; + } + + &.primary { + background: var(--primary-color) 0% 0% no-repeat padding-box; + color: #ffffff; + } + + &.primary-inverted { + border: 1px solid var(--primary-color); + background: transparent; + color: var(--primary-color); + } + + &.secondary { + background: var(--secondary-color) 0% 0% no-repeat padding-box; + color: #000000; + } + + // &.save-btn { + + // } + + // &.cancel-btn { + + // } + + // &.finalize-btn { + + // } + + &.delete-btn { + background: #ffffff; + color: #ff3d33;; + border: 1px solid #ff3d33; + } + + &.md-button { + padding: 0.62rem 1.87rem; + font-weight: 400; + } +} + +.mat-mdc-button.mat-mdc-button-disabled { + background-color: #CBCBCB; //!important + color: #FFF; //!important + border: 0px; //!important +} + +.status-chip { + border-radius: 20px; + padding-left: 1em; + padding-right: 1em; + padding-top: 0.2em; + font-size: .8em; + &.status-chip-finalized { + color: #568b5a; + background: #9dd1a1 0% 0% no-repeat padding-box; + } + + &.status-chip-draft { + color: #00c4ff; + background: #d3f5ff 0% 0% no-repeat padding-box; + } + + &.status-chip-error { + color: #cf1407; + background: #ffe6e5 0% 0% no-repeat padding-box; + } +} + +.gap-1-rem{ + gap: 1rem; +} + +.gap-2-rem{ + gap: 2rem; +} + +.gap-half-rem { + gap: 0.5rem; +} \ No newline at end of file