refactor description listing

This commit is contained in:
CITE\spapacharalampous 2024-08-29 15:50:42 +03:00
parent a99bf8efac
commit f6453bfe6a
8 changed files with 154 additions and 138 deletions

View File

@ -1,7 +1,7 @@
<div class="main-content listing-main-container h-100"> <div class="main-content listing-main-container h-100">
<div class="container-fluid"> <div class="container-fluid">
<div class="row"> <div class="row">
<div *ngIf="hasLoadedListingItems && !hasListingItems && !hasFilters" class="card mt-0"> <div *ngIf="!isLoading && !hasListingItems && !hasFilters" class="card mt-0">
<div class="card-content info-text mb-0"> <div class="card-content info-text mb-0">
<p>{{'DESCRIPTION-LISTING.TEXT-INFO' | translate}} <u class="pointer" [routerLink]="routerUtils.generateUrl(['/explore-descriptions'])">{{'DESCRIPTION-LISTING.LINK-PUBLIC-DESCRIPTIONS' | translate}}</u> {{'DESCRIPTION-LISTING.TEXT-INFO-REST' | translate}}</p> <p>{{'DESCRIPTION-LISTING.TEXT-INFO' | translate}} <u class="pointer" [routerLink]="routerUtils.generateUrl(['/explore-descriptions'])">{{'DESCRIPTION-LISTING.LINK-PUBLIC-DESCRIPTIONS' | translate}}</u> {{'DESCRIPTION-LISTING.TEXT-INFO-REST' | translate}}</p>
<p class="mt-4 pt-2">{{'DESCRIPTION-LISTING.TEXT-INFO-PAR' | translate}} <p class="mt-4 pt-2">{{'DESCRIPTION-LISTING.TEXT-INFO-PAR' | translate}}
@ -13,29 +13,25 @@
</div> </div>
</div> </div>
</div> </div>
<div class="col-auto"> <div class="col-12">
<div *ngIf="hasLoadedListingItems && (hasListingItems || hasFilters)" class="row"> <app-navigation-breadcrumb />
<div class="col-12">
<app-navigation-breadcrumb />
</div>
</div>
</div> </div>
<div *ngIf="hasLoadedListingItems && !isPublic && (hasListingItems || hasFilters)" class="ml-auto"> <div *ngIf="(isLoading || hasListingItems || hasFilters) && !isPublic" class="ml-auto">
<div class="col-auto"> <div class="col-auto">
<button mat-raised-button class="add-description align-self-center yellow-btn" (click)="addNewDescription()"> <button mat-raised-button class="add-description align-self-center yellow-btn" (click)="addNewDescription()">
{{'DESCRIPTION-LISTING.ACTIONS.ADD-DESCRIPTION' | translate}} {{'DESCRIPTION-LISTING.ACTIONS.ADD-DESCRIPTION' | translate}}
</button> </button>
</div> </div>
</div> </div>
<div *ngIf="hasLoadedListingItems && (hasListingItems || hasFilters) && !isPublic" <div *ngIf="(isLoading || hasListingItems || hasFilters) && !isPublic"
class="filter-btn" [style.right]="dialog.getDialogById('filters') ? '446px' : '0px'" [style.width]="listingItems.length > 2 ? '57px' : '37px'" (click)="openFiltersDialog()"> class="filter-btn" [style.right]="dialog.getDialogById('filters') ? '446px' : '0px'" [style.width]="listingItems.length > 2 ? '57px' : '37px'" (click)="openFiltersDialog()">
<button mat-raised-button class="p-0" [matBadge]="filtersCount" [matBadgeHidden]="!hasFilters" matBadgePosition="before"> <button mat-raised-button class="p-0" [matBadge]="filtersCount" [matBadgeHidden]="filtersCount === 0" matBadgePosition="before">
<mat-icon class="mr-4 filter-icon">filter_alt</mat-icon> <mat-icon class="mr-4 filter-icon">filter_alt</mat-icon>
</button> </button>
</div> </div>
</div> </div>
<div> <div>
<div *ngIf="hasLoadedListingItems" class="listing row pb-2"> <div class="listing row pb-2">
<div *ngIf="hasListingItems || hasFilters" class="col-md-12"> <div *ngIf="hasListingItems || hasFilters" class="col-md-12">
<div class="row pt-4"> <div class="row pt-4">
<!-- Sort by --> <!-- Sort by -->
@ -44,11 +40,11 @@
</div> </div>
<div class="col-12 col-xl-auto order-3 order-xl-2"> <div class="col-12 col-xl-auto order-3 order-xl-2">
<mat-form-field class="sort-form w-100"> <mat-form-field class="sort-form w-100">
<mat-select placeholder="{{'GENERAL.CRITERIA.LIKE'| translate}}" [formControl]="formGroup.get('order')" (selectionChange)="orderByChanged()"> <mat-select placeholder="{{'GENERAL.CRITERIA.LIKE'| translate}}" [(ngModel)]="sortBy" (selectionChange)="orderByChanged($event)">
<mat-option *ngIf="!isPublic" [value]="order.UpdatedAt">{{enumUtils.toRecentActivityOrderString(order.UpdatedAt)}}</mat-option> <mat-option *ngIf="!isPublic" [value]="RecentActivityOrder.UpdatedAt">{{enumUtils.toRecentActivityOrderString(RecentActivityOrder.UpdatedAt)}}</mat-option>
<mat-option *ngIf="isPublic" [value]="order.PublishedAt">{{enumUtils.toRecentActivityOrderString(order.PublishedAt)}}</mat-option> <mat-option *ngIf="isPublic" [value]="RecentActivityOrder.PublishedAt">{{enumUtils.toRecentActivityOrderString(RecentActivityOrder.PublishedAt)}}</mat-option>
<mat-option [value]="order.Label">{{enumUtils.toRecentActivityOrderString(order.Label)}}</mat-option> <mat-option [value]="RecentActivityOrder.Label">{{enumUtils.toRecentActivityOrderString(RecentActivityOrder.Label)}}</mat-option>
<mat-option *ngIf="!isPublic" [value]="order.Status">{{enumUtils.toRecentActivityOrderString(order.Status)}}</mat-option> <mat-option *ngIf="!isPublic" [value]="RecentActivityOrder.Status">{{enumUtils.toRecentActivityOrderString(RecentActivityOrder.Status)}}</mat-option>
</mat-select> </mat-select>
</mat-form-field> </mat-form-field>
</div> </div>
@ -63,38 +59,36 @@
<div class="row"> <div class="row">
<!-- Guided Tour --> <!-- Guided Tour -->
<div class="col-12 col-xl-auto d-flex align-items-center"> <div class="col-12 col-xl-auto d-flex align-items-center">
<span *ngIf="!isPublic" class="center-content mb-1 mb-xl-4" (click)="restartTour()">{{ 'DESCRIPTION-LISTING.ACTIONS.TAKE-A-TOUR'| translate }}</span> <span *ngIf="!isPublic" class="center-content" (click)="restartTour()">{{ 'DESCRIPTION-LISTING.ACTIONS.TAKE-A-TOUR'| translate }}</span>
</div> </div>
<!-- End of Guided Tour --> <!-- End of Guided Tour -->
<!-- Search Filter--> <!-- Search Filter-->
<div class="col-12 col-xl-auto"> <div class="col-12 col-xl-auto">
<mat-form-field class="search-form w-100" floatLabel="never"> <app-text-filter suffixIcon="search" floatLabel="never" placeholder="{{'GENERAL.CRITERIA.LIKE'| translate}}" [(value)]=lookup.like (valueChange)="controlModified()" />
<mat-icon matSuffix>search</mat-icon>
<input matInput placeholder="{{'GENERAL.CRITERIA.LIKE'| translate}}" name="likeCriteria" [formControl]="formGroup.get('like')">
<mat-error *ngIf="formGroup.get('like').hasError('backendError')">{{formGroup.get('like').getError('backendError').message}}</mat-error>
</mat-form-field>
</div> </div>
<!-- End of Search Filter --> <!-- End of Search Filter -->
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<div class="col-md-12 col-sm-12 col-md-9"> @if(!isLoading) {
<div *ngFor="let item of listingItems; let i = index"> <div class="col-md-12 col-sm-12 col-md-9">
<app-description-listing-item-component <div *ngFor="let item of listingItems; let i = index">
[isPublic]="isPublic" <app-description-listing-item-component
[description]="item" [isPublic]="isPublic"
[tenants]="tenants" [description]="item"
[showDivider]="i != (listingItems.length - 1)" [tenants]="tenants"
></app-description-listing-item-component> [showDivider]="i != (listingItems.length - 1)"
></app-description-listing-item-component>
</div>
<div *ngIf="hasListingItems && this.lookup?.page?.offset < this.totalCount - 1 && this.pageSize < this.totalCount - 1" class="d-flex justify-content-center">
<button type="button" class="btn-load-more" (click)="loadMore()">{{'DESCRIPTION-LISTING.ACTIONS.LOAD-MORE' | translate}}</button>
</div>
</div> </div>
<div *ngIf="hasListingItems && this.lookup?.page?.offset < this.totalCount - 1 && this.pageSize < this.totalCount - 1" class="d-flex justify-content-center"> <div *ngIf="!hasListingItems && hasFilters" class="col-md-12 d-flex justify-content-center pt-4 mt-4 mb-4 pb-4">
<button type="button" class="btn-load-more" (click)="loadMore()">{{'DESCRIPTION-LISTING.ACTIONS.LOAD-MORE' | translate}}</button> <span class="empty-list">{{'DESCRIPTION-LISTING.EMPTY-LIST' | translate}}</span>
</div> </div>
</div> }
<div *ngIf="!hasListingItems && hasFilters" class="col-md-12 d-flex justify-content-center pt-4 mt-4 mb-4 pb-4">
<span class="empty-list">{{'DESCRIPTION-LISTING.EMPTY-LIST' | translate}}</span>
</div>
</div> </div>
</div> </div>
</div> </div>

View File

@ -1,6 +1,6 @@
import { Component, OnInit, ViewChild } from '@angular/core'; import { Component, OnInit, ViewChild } from '@angular/core';
import { FormBuilder, UntypedFormBuilder, UntypedFormControl, UntypedFormGroup, Validators } from '@angular/forms'; import { FormBuilder, UntypedFormBuilder, UntypedFormControl, UntypedFormGroup, Validators } from '@angular/forms';
import { MatDialog } from '@angular/material/dialog'; import { MatDialog, MatDialogRef } from '@angular/material/dialog';
import { MatPaginator } from '@angular/material/paginator'; import { MatPaginator } from '@angular/material/paginator';
import { MatSort } from '@angular/material/sort'; import { MatSort } from '@angular/material/sort';
import { ActivatedRoute, Params, Router } from '@angular/router'; import { ActivatedRoute, Params, Router } from '@angular/router';
@ -41,6 +41,8 @@ import { Tenant } from '@app/core/model/tenant/tenant';
import { BaseHttpParams } from '@common/http/base-http-params'; import { BaseHttpParams } from '@common/http/base-http-params';
import { InterceptorType } from '@common/http/interceptors/interceptor-type'; import { InterceptorType } from '@common/http/interceptors/interceptor-type';
import { PrincipalService } from '@app/core/services/http/principal.service'; import { PrincipalService } from '@app/core/services/http/principal.service';
import { DescriptionListingFilters } from './filtering/description-filter.component';
import { MatSelectChange } from '@angular/material/select';
@Component({ @Component({
selector: 'app-description-listing-component', selector: 'app-description-listing-component',
@ -60,7 +62,7 @@ export class DescriptionListingComponent extends BaseListingComponent<BaseDescri
totalCount: number; totalCount: number;
plansearchEnabled = true; plansearchEnabled = true;
listingItems: any[] = []; listingItems: any[] = [];
hasLoadedListingItems: boolean = false; isLoading: boolean = false;
isPublic: boolean = false; isPublic: boolean = false;
public isVisible = true; public isVisible = true;
protected ITEMS_PER_PAGE = 5; protected ITEMS_PER_PAGE = 5;
@ -68,31 +70,24 @@ export class DescriptionListingComponent extends BaseListingComponent<BaseDescri
pageSize: number = 5; pageSize: number = 5;
lookup: DescriptionLookup; lookup: DescriptionLookup;
referenceFilters: ReferencesWithType[]; referenceFilters: ReferencesWithType[];
public formGroup = new UntypedFormBuilder().group({
like: new UntypedFormControl(),
order: new UntypedFormControl()
});
tenants: Tenant[] = []; tenants: Tenant[] = [];
scrollbar: boolean; scrollbar: boolean;
order = RecentActivityOrder;
RecentActivityOrder = RecentActivityOrder;
sortBy: RecentActivityOrder;
planText: string; planText: string;
descriptionText: string; descriptionText: string;
private _sortDirection: SortDirection = SortDirection.Descending;
set sortDirection(sortDirection: SortDirection) {
this._sortDirection = sortDirection;
}
get isAscending(): boolean { get isAscending(): boolean {
return this._sortDirection == SortDirection.Ascending; return this.lookup?.order?.items?.[0].startsWith("-");
} }
get isDescending(): boolean { get isDescending(): boolean {
return this._sortDirection == SortDirection.Descending; return this.lookup?.order?.items?.[0].startsWith("+");
}
get sortingDirectionPrefix(): string {
return this.isAscending ? "+" : "-";
} }
get sortingTooltipText(): string { get sortingTooltipText(): string {
return this.isAscending ? this.language.instant('DESCRIPTION-LISTING.ACTIONS.TOGGLE-ΑSCENDING') : this.language.instant('DESCRIPTION-LISTING.ACTIONS.TOGGLE-DESCENDING'); return this.isAscending ? this.language.instant('DESCRIPTION-LISTING.ACTIONS.TOGGLE-ΑSCENDING') : this.language.instant('DESCRIPTION-LISTING.ACTIONS.TOGGLE-DESCENDING');
} }
@ -150,16 +145,7 @@ export class DescriptionListingComponent extends BaseListingComponent<BaseDescri
} }
else if (!this.lookup) this.lookup = this.initializeLookup(); else if (!this.lookup) this.lookup = this.initializeLookup();
this.sortBy = this._getRecentActivityOrder(this.lookup.order.items[0]?.substring(1));
if ((this.formGroup.get('order')?.value == null || (!this.isAscending && !this.isDescending)) && this.lookup.order.items && this.lookup.order.items.length > 0) {
let ordering = this.lookup.order.items[0];
let sortBy = ordering.substring(1, ordering.length);
this.formGroup.get('order').setValue(this._getRecentActivityOrder(sortBy));
ordering.charAt(0) == '-' ? this.sortDirection = SortDirection.Descending : this.sortDirection = SortDirection.Ascending;
}
this.onPageLoad({ offset: this.lookup.page.offset / this.lookup.page.size } as PageLoadEvent); this.onPageLoad({ offset: this.lookup.page.offset / this.lookup.page.size } as PageLoadEvent);
}); });
@ -168,10 +154,6 @@ export class DescriptionListingComponent extends BaseListingComponent<BaseDescri
this.tenants = tenants; this.tenants = tenants;
}); });
} }
this.formGroup.get('like').valueChanges
.pipe(takeUntil(this._destroyed), debounceTime(500))
.subscribe(x => this.controlModified());
} }
ngAfterContentChecked(): void { ngAfterContentChecked(): void {
@ -179,23 +161,24 @@ export class DescriptionListingComponent extends BaseListingComponent<BaseDescri
} }
protected loadListing(): Observable<QueryResult<BaseDescription>> { protected loadListing(): Observable<QueryResult<BaseDescription>> {
this.isLoading = true;
if (this.isPublic) { if (this.isPublic) {
return this.descriptionService.publicQuery(this.lookup).pipe(takeUntil(this._destroyed)) return this.descriptionService.publicQuery(this.lookup).pipe(takeUntil(this._destroyed))
.pipe(tap(result => { .pipe(tap(result => {
this.isLoading = false;
if (!result) { return []; } if (!result) { return []; }
this.totalCount = result.count; this.totalCount = result.count;
if (this.lookup?.page?.offset === 0) this.listingItems = []; if (this.lookup?.page?.offset === 0) this.listingItems = [];
this.listingItems.push(...result.items); this.listingItems.push(...result.items);
this.hasLoadedListingItems = true;
})); }));
} else { } else {
return this.descriptionService.query(this.lookup).pipe(takeUntil(this._destroyed)) return this.descriptionService.query(this.lookup).pipe(takeUntil(this._destroyed))
.pipe(tap(result => { .pipe(tap(result => {
this.isLoading = false;
if (!result) { return []; } if (!result) { return []; }
this.totalCount = result.count; this.totalCount = result.count;
if (this.lookup?.page?.offset === 0) this.listingItems = []; if (this.lookup?.page?.offset === 0) this.listingItems = [];
this.listingItems.push(...result.items); this.listingItems.push(...result.items);
this.hasLoadedListingItems = true;
})); }));
} }
} }
@ -245,7 +228,6 @@ export class DescriptionListingComponent extends BaseListingComponent<BaseDescri
} }
controlModified(): void { controlModified(): void {
this.lookup.like = this.formGroup.get("like").value;
this.lookup.page = { size: this.pageSize, offset: 0 }; this.lookup.page = { size: this.pageSize, offset: 0 };
this.filterChanged(this.lookup, true); this.filterChanged(this.lookup, true);
} }
@ -256,21 +238,34 @@ export class DescriptionListingComponent extends BaseListingComponent<BaseDescri
this.filterChanged(this.lookup, true); this.filterChanged(this.lookup, true);
} }
orderByChanged() { orderByChanged($event: MatSelectChange) {
if (this.formGroup.get('order').value == RecentActivityOrder.Status) { const value = $event.value as RecentActivityOrder;
this.lookup.order = { items: [this.sortingDirectionPrefix + nameof<Plan>(x => x.status)] }; const directionPrefix = this.isAscending ? '-' : '+';
} else if (this.formGroup.get('order').value == RecentActivityOrder.Label) {
this.lookup.order = { items: [this.sortingDirectionPrefix + nameof<Plan>(x => x.label)] }; switch (value) {
} else if (this.formGroup.get('order').value == RecentActivityOrder.PublishedAt) { case RecentActivityOrder.Status: {
this.lookup.order = { items: [this.sortingDirectionPrefix + nameof<Plan>(x => x.finalizedAt)] }; this.lookup.order = { items: [directionPrefix + nameof<Plan>(x => x.status)] };
}else { break;
this.lookup.order = { items: [this.sortingDirectionPrefix + nameof<Plan>(x => x.updatedAt)] }; }
} case RecentActivityOrder.Label: {
this.lookup.order = { items: [directionPrefix + nameof<Plan>(x => x.label)] };
break;
}
case RecentActivityOrder.PublishedAt: {
this.lookup.order = { items: [directionPrefix + nameof<Plan>(x => x.finalizedAt)] };
break;
}
default: {
this.lookup.order = { items: [directionPrefix + nameof<Plan>(x => x.updatedAt)] };
break;
}
};
this.filterChanged(this.lookup); this.filterChanged(this.lookup);
} }
openFiltersDialog(): void { openFiltersDialog(): void {
const dialogRef = this.dialog.open(DescriptionFilterDialogComponent, { const dialogRef: MatDialogRef<DescriptionFilterDialogComponent, DescriptionListingFilters> = this.dialog.open(DescriptionFilterDialogComponent, {
width: '456px', width: '456px',
height: '100%', height: '100%',
id: 'filters', id: 'filters',
@ -280,7 +275,7 @@ export class DescriptionListingComponent extends BaseListingComponent<BaseDescri
data: { data: {
isPublic: this.isPublic ?? true, isPublic: this.isPublic ?? true,
hasSelectedTenant: this.authService.selectedTenant() != 'default', hasSelectedTenant: this.authService.selectedTenant() != 'default',
filterForm: this._buildFormFromLookup(this.lookup, this.referenceFilters), lookup: this.lookup,
referencesWithTypeItems: this.referenceFilters ?? [], referencesWithTypeItems: this.referenceFilters ?? [],
} }
}); });
@ -292,11 +287,10 @@ export class DescriptionListingComponent extends BaseListingComponent<BaseDescri
}); });
} }
updateDataFn(filterForm: UntypedFormGroup): void { updateDataFn(filters: DescriptionListingFilters): void {
this.referenceFilters = this._patchReferenceFiltersFromForm(filterForm); this.referenceFilters = this._patchReferenceFilters(filters);
this.lookup = this._patchLookupFromForm(this.lookup, filterForm); this.lookup = this._patchLookupFromFilters(filters);
this.filtersCount = this._countFilters(this.lookup); this.filtersCount = this._countFilters(this.lookup);
this.hasLoadedListingItems = false;
this.filterChanged(this.lookup) this.filterChanged(this.lookup)
} }
@ -368,8 +362,10 @@ export class DescriptionListingComponent extends BaseListingComponent<BaseDescri
} }
toggleSortDirection(): void { toggleSortDirection(): void {
this.sortDirection = this.isAscending ? SortDirection.Descending : SortDirection.Ascending; const orderBy = this.lookup?.order?.items[0]?.substring(1) ?? nameof<Description>(x => x.updatedAt);
this.orderByChanged(); const sortDirection = this.isAscending ? '+' : '-';
this.lookup.order.items = [`${sortDirection}${orderBy}`];
this.filterChanged(this.lookup);
} }
@ -385,6 +381,7 @@ export class DescriptionListingComponent extends BaseListingComponent<BaseDescri
let lookup: DescriptionLookup = JSON.parse(params['lookup']); let lookup: DescriptionLookup = JSON.parse(params['lookup']);
if (!lookup) return this.initializeLookup(); if (!lookup) return this.initializeLookup();
lookup.like = lookup.like ?? null;
const queryOffset = 0; const queryOffset = 0;
const querySize = (lookup.page?.offset ?? 0) + this.pageSize; const querySize = (lookup.page?.offset ?? 0) + this.pageSize;
@ -414,76 +411,65 @@ export class DescriptionListingComponent extends BaseListingComponent<BaseDescri
} }
} }
_patchLookupFromForm(lookup: DescriptionLookup, formGroup: UntypedFormGroup): DescriptionLookup { _patchLookupFromFilters(filters: DescriptionListingFilters): DescriptionLookup {
if (!formGroup) return; if (!filters) return;
lookup.statuses = formGroup.get("status")?.value !== null ? [formGroup.get("status")?.value] : null; this.lookup.statuses = filters.status !== null ? [filters.status] : null;
// Tenants // Tenants
let viewOnlyTenant = formGroup.get("viewOnlyTenant")?.value ?? false; let viewOnlyTenant = filters.viewOnlyTenant ?? false;
if (viewOnlyTenant) { if (viewOnlyTenant) {
let tenant = this.tenants?.find(t => t.code && t.code?.toString() == this.authService.selectedTenant()); let tenant = this.tenants?.find(t => t.code && t.code?.toString() == this.authService.selectedTenant());
if (tenant && tenant?.code) { if (tenant && tenant?.code) {
lookup.tenantSubQuery = DescriptionFilterService.initializeTenantLookup(); this.lookup.tenantSubQuery = DescriptionFilterService.initializeTenantLookup();
lookup.tenantSubQuery.codes = [tenant.code] this.lookup.tenantSubQuery.codes = [tenant.code]
} }
else lookup.tenantSubQuery = null; else this.lookup.tenantSubQuery = null;
} else lookup.tenantSubQuery = null; } else this.lookup.tenantSubQuery = null;
// Description Templates // Description Templates
let descriptionTemplates = formGroup.get("descriptionTemplates")?.value ?? null; let descriptionTemplates = filters.descriptionTemplates ?? null;
if (descriptionTemplates && descriptionTemplates?.length > 0) { if (descriptionTemplates && descriptionTemplates?.length > 0) {
lookup.descriptionTemplateSubQuery = DescriptionFilterService.initializeDescriptionTemplateLookup(); this.lookup.descriptionTemplateSubQuery = DescriptionFilterService.initializeDescriptionTemplateLookup();
lookup.descriptionTemplateSubQuery.ids = descriptionTemplates; this.lookup.descriptionTemplateSubQuery.ids = descriptionTemplates;
} else lookup.descriptionTemplateSubQuery = null; } else this.lookup.descriptionTemplateSubQuery = null;
// Plans // Plans
let plans = formGroup.get("associatedPlanIds")?.value ?? null; let addPlans = plans && plans?.length > 0; let plans = filters.associatedPlanIds ?? null; let addPlans = plans && plans?.length > 0;
let roles = formGroup.get("role")?.value !== null ? [formGroup.get("role")?.value] : null; let addRoles = roles && roles?.length > 0; let roles = filters.role !== null ? [filters.role] : null; let addRoles = roles && roles?.length > 0;
if (addPlans || addRoles) { if (addPlans || addRoles) {
lookup.planSubQuery = DescriptionFilterService.initializePlanLookup(); this.lookup.planSubQuery = DescriptionFilterService.initializePlanLookup();
if (addPlans) lookup.planSubQuery.ids = plans?.length > 0 ? plans : null; if (addPlans) this.lookup.planSubQuery.ids = plans?.length > 0 ? plans : null;
if (addRoles) { if (addRoles) {
lookup.planSubQuery.planUserSubQuery = DescriptionFilterService.initializePlanUserLookup(); this.lookup.planSubQuery.planUserSubQuery = DescriptionFilterService.initializePlanUserLookup();
lookup.planSubQuery.planUserSubQuery.userRoles = roles; this.lookup.planSubQuery.planUserSubQuery.userRoles = roles;
} }
} else lookup.planSubQuery = null; } else this.lookup.planSubQuery = null;
// Tags // Tags
let tags = formGroup.get("tags")?.value ?? null; let tags = filters.tags ?? null;
if (tags && tags?.length > 0) { if (tags && tags?.length > 0) {
lookup.descriptionTagSubQuery = DescriptionFilterService.initializeTagLookup(); this.lookup.descriptionTagSubQuery = DescriptionFilterService.initializeTagLookup();
lookup.descriptionTagSubQuery.tagIds = tags; this.lookup.descriptionTagSubQuery.tagIds = tags;
} else lookup.descriptionTagSubQuery = null; } else this.lookup.descriptionTagSubQuery = null;
// References // References
let references: Guid[] = formGroup.get("references")?.value let references: Guid[] = filters.references
?.filter((reference: ReferencesWithType) => reference.referenceTypeId != null && reference.referenceIds?.length > 0) ?.filter((reference: ReferencesWithType) => reference.referenceTypeId != null && reference.referenceIds?.length > 0)
?.flatMap((referencesWithType: ReferencesWithType) => referencesWithType.referenceIds) as Guid[]; ?.flatMap((referencesWithType: ReferencesWithType) => referencesWithType.referenceIds) as Guid[];
if (references && references?.length > 0) { if (references && references?.length > 0) {
lookup.descriptionReferenceSubQuery = DescriptionFilterService.initializeReferenceLookup(); this.lookup.descriptionReferenceSubQuery = DescriptionFilterService.initializeReferenceLookup();
lookup.descriptionReferenceSubQuery.referenceIds = references; this.lookup.descriptionReferenceSubQuery.referenceIds = references;
} else lookup.descriptionReferenceSubQuery = null; } else this.lookup.descriptionReferenceSubQuery = null;
return lookup; return this.lookup;
} }
_patchReferenceFiltersFromForm(formGroup: UntypedFormGroup): ReferencesWithType[] { _patchReferenceFilters(filters: DescriptionListingFilters): ReferencesWithType[] {
return formGroup?.get("references")?.value?.filter(( referencesWithType: ReferencesWithType ) => referencesWithType.referenceTypeId != null && referencesWithType.referenceIds?.length > 0) ?? null; return filters.references?.filter(( referencesWithType: ReferencesWithType ) => referencesWithType.referenceTypeId != null && referencesWithType.referenceIds?.length > 0) ?? null;
}
_buildFormFromLookup(lookup: DescriptionLookup, referenceFilters: ReferencesWithType[]): UntypedFormGroup {
return (new UntypedFormBuilder()).group({
status: [lookup.statuses?.length > 0 ? lookup.statuses[0] : null],
viewOnlyTenant: [lookup.tenantSubQuery?.codes?.length > 0 ? true : false],
role: lookup.planSubQuery?.planUserSubQuery?.userRoles ? lookup.planSubQuery?.planUserSubQuery?.userRoles[0] : [],
descriptionTemplates: lookup.descriptionTemplateSubQuery?.ids ? [lookup.descriptionTemplateSubQuery?.ids] : [],
associatedPlanIds: lookup.planSubQuery?.ids ? [lookup.planSubQuery?.ids] : [],
tags: lookup.descriptionTagSubQuery?.tagIds ? [lookup.descriptionTagSubQuery?.tagIds] : [],
});
} }
private _countFilters(lookup: DescriptionLookup): number { private _countFilters(lookup: DescriptionLookup): number {

View File

@ -11,6 +11,7 @@ import { DescriptionFilterDialogComponent } from './filtering/description-filter
import { DescriptionFilterComponent } from './filtering/description-filter.component'; import { DescriptionFilterComponent } from './filtering/description-filter.component';
import { AutoCompleteModule } from '@app/library/auto-complete/auto-complete.module'; import { AutoCompleteModule } from '@app/library/auto-complete/auto-complete.module';
import { DescriptionFilterService } from './filtering/description-filter.service'; import { DescriptionFilterService } from './filtering/description-filter.service';
import { TextFilterModule } from '@common/modules/text-filter/text-filter.module';
@NgModule({ @NgModule({
imports: [ imports: [
@ -21,6 +22,7 @@ import { DescriptionFilterService } from './filtering/description-filter.service
StartNewDescriptionDialogModule, StartNewDescriptionDialogModule,
DescriptionListingRoutingModule, DescriptionListingRoutingModule,
AutoCompleteModule, AutoCompleteModule,
TextFilterModule,
], ],
declarations: [ declarations: [
DescriptionListingComponent, DescriptionListingComponent,

View File

@ -1,7 +1,7 @@
<a class="col-auto d-flex pointer" (click)="onClose()"><span class="ml-auto mt-3 material-icons clear-icon">clear</span></a> <a class="col-auto d-flex pointer" (click)="onClose()"><span class="ml-auto mt-3 material-icons clear-icon">clear</span></a>
<app-description-filter-component <app-description-filter-component
[filterFormGroup]="data.filterForm" [filterFormGroup]="formGroup"
[referencesWithTypeItems]="data.referencesWithTypeItems" [referencesWithTypeItems]="data.referencesWithTypeItems"
[isPublic]="data.isPublic" [isPublic]="data.isPublic"
[hasSelectedTenant]="data.hasSelectedTenant" [hasSelectedTenant]="data.hasSelectedTenant"

View File

@ -1,9 +1,9 @@
import { Component, Inject, OnInit, ViewChild } from '@angular/core'; import { Component, Inject, OnInit, ViewChild } from '@angular/core';
import { UntypedFormGroup } from '@angular/forms'; import { FormGroup, UntypedFormBuilder, UntypedFormGroup } from '@angular/forms';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { AnalyticsService } from '@app/core/services/matomo/analytics-service'; import { AnalyticsService } from '@app/core/services/matomo/analytics-service';
import { DescriptionFilterComponent } from '../description-filter.component'; import { DescriptionFilterComponent, DescriptionListingFilterForm, DescriptionListingFilters } from '../description-filter.component';
import { ReferencesWithType } from '@app/core/query/description.lookup'; import { DescriptionLookup, ReferencesWithType } from '@app/core/query/description.lookup';
@Component({ @Component({
selector: 'description-filter-dialog-component', selector: 'description-filter-dialog-component',
@ -15,16 +15,20 @@ export class DescriptionFilterDialogComponent implements OnInit {
@ViewChild(DescriptionFilterComponent, { static: true }) filter: DescriptionFilterComponent; @ViewChild(DescriptionFilterComponent, { static: true }) filter: DescriptionFilterComponent;
formGroup: FormGroup<DescriptionListingFilterForm>;
constructor( constructor(
public dialogRef: MatDialogRef<DescriptionFilterComponent>, public dialogRef: MatDialogRef<DescriptionFilterComponent>,
private analyticsService: AnalyticsService, private analyticsService: AnalyticsService,
@Inject(MAT_DIALOG_DATA) public data: { @Inject(MAT_DIALOG_DATA) public data: {
isPublic: boolean, isPublic: boolean,
hasSelectedTenant: boolean, hasSelectedTenant: boolean,
filterForm: UntypedFormGroup, lookup: DescriptionLookup,
referencesWithTypeItems: ReferencesWithType[], referencesWithTypeItems: ReferencesWithType[],
} }
) { } ) {
this.formGroup = this._buildFormFromLookup(data?.lookup);
}
ngOnInit() { ngOnInit() {
this.analyticsService.trackPageView(AnalyticsService.DescriptionFilterDialog); this.analyticsService.trackPageView(AnalyticsService.DescriptionFilterDialog);
@ -39,6 +43,17 @@ export class DescriptionFilterDialogComponent implements OnInit {
} }
onFilterChanged(formGroup: UntypedFormGroup) { onFilterChanged(formGroup: UntypedFormGroup) {
this.dialogRef.close(formGroup); this.dialogRef.close(formGroup.value as DescriptionListingFilters);
}
private _buildFormFromLookup(lookup: DescriptionLookup): FormGroup<DescriptionListingFilterForm> {
return (new UntypedFormBuilder()).group({
status: [lookup.statuses?.length > 0 ? lookup.statuses[0] : null],
viewOnlyTenant: [lookup.tenantSubQuery?.codes?.length > 0 ? true : false],
role: lookup.planSubQuery?.planUserSubQuery?.userRoles ? lookup.planSubQuery?.planUserSubQuery?.userRoles[0] : [],
descriptionTemplates: lookup.descriptionTemplateSubQuery?.ids ? [lookup.descriptionTemplateSubQuery?.ids] : [],
associatedPlanIds: lookup.planSubQuery?.ids ? [lookup.planSubQuery?.ids] : [],
tags: lookup.descriptionTagSubQuery?.tagIds ? [lookup.descriptionTagSubQuery?.tagIds] : [],
});
} }
} }

View File

@ -1,6 +1,6 @@
import { Component, EventEmitter, Input, OnChanges, OnInit, Output, SimpleChanges } from '@angular/core'; import { Component, EventEmitter, Input, OnChanges, OnInit, Output, SimpleChanges } from '@angular/core';
import { AbstractControl, FormBuilder, UntypedFormArray, UntypedFormGroup } from '@angular/forms'; import { AbstractControl, FormArray, FormBuilder, FormControl, UntypedFormArray, UntypedFormGroup } from '@angular/forms';
import { DescriptionStatusEnum } from '@app/core/common/enum/description-status'; import { DescriptionStatusEnum } from '@app/core/common/enum/description-status';
import { PlanUserRole } from '@app/core/common/enum/plan-user-role'; import { PlanUserRole } from '@app/core/common/enum/plan-user-role';
import { ReferenceType } from '@app/core/model/reference-type/reference-type'; import { ReferenceType } from '@app/core/model/reference-type/reference-type';
@ -200,3 +200,23 @@ export class DescriptionFilterComponent extends BaseCriteriaComponent implements
}); });
} }
} }
export interface DescriptionListingFilters {
status: DescriptionStatusEnum,
viewOnlyTenant: boolean,
role: Guid,
descriptionTemplates: Guid[],
associatedPlanIds: Guid[],
tags: Guid[],
references: ReferencesWithType[]
}
export interface DescriptionListingFilterForm {
status: FormControl<DescriptionStatusEnum>,
viewOnlyTenant: FormControl<boolean>,
role: FormControl<Guid>,
descriptionTemplates: FormControl<Guid[]>,
associatedPlanIds: FormControl<Guid[]>,
tags: FormControl<Guid[]>,
references: FormArray<any>
}

View File

@ -25,7 +25,6 @@ export class PlanFilterDialogComponent implements OnInit {
isPublic: boolean, isPublic: boolean,
hasSelectedTenant: boolean, hasSelectedTenant: boolean,
lookup: PlanLookup, lookup: PlanLookup,
//filterForm: UntypedFormGroup,
referencesWithTypeItems: ReferencesWithType[], referencesWithTypeItems: ReferencesWithType[],
}) { }) {
this.formGroup = this._buildFormFromLookup(data?.lookup) this.formGroup = this._buildFormFromLookup(data?.lookup)

View File

@ -202,7 +202,7 @@ export interface PlanListingFilters {
viewOnlyTenant: boolean, viewOnlyTenant: boolean,
descriptionTemplates: Guid[], descriptionTemplates: Guid[],
planBlueprints: Guid[], planBlueprints: Guid[],
role: Guid, role: Guid,
references: ReferencesWithType[] references: ReferencesWithType[]
} }