mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2026-09-09 18:03:21 +00:00
AAE-49653 Making filter key mandatory string
This commit is contained in:
@@ -15,9 +15,6 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Entity types accepted by the `POST /query/v1/count` endpoint.
|
||||
*/
|
||||
export const FilterCounterEntityType = {
|
||||
TASK: 'TASK',
|
||||
PROCESS_INSTANCE: 'PROCESS_INSTANCE'
|
||||
@@ -31,7 +28,6 @@ export interface FilterCountersQuerySort {
|
||||
isProcessVariable: boolean;
|
||||
}
|
||||
|
||||
/** A single query of the batched count request, holding the criteria of one filter. */
|
||||
export interface FilterCountersQuery {
|
||||
/** Identifies the query, so its counter can be read back from the response. */
|
||||
requestId: string;
|
||||
@@ -41,28 +37,19 @@ export interface FilterCountersQuery {
|
||||
[criteria: string]: unknown;
|
||||
}
|
||||
|
||||
/**
|
||||
* Payload of the batched count request, one entry per counter to be resolved.
|
||||
*/
|
||||
export type FilterCountersRequest = {
|
||||
[entityType in FilterCounterEntityType]?: FilterCountersQuery[];
|
||||
};
|
||||
|
||||
/** Shape of a task or process filter the counters are resolved for. Its key is the `requestId`. */
|
||||
export interface FilterCounterCandidate {
|
||||
key?: string | null;
|
||||
key: string;
|
||||
showCounter?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Counts returned by the batched count request, keyed by entity type and then by `requestId`.
|
||||
* e.g. `{ TASK: { 'my-tasks': 5 }, PROCESS_INSTANCE: { 'running-processes': 5 } }`
|
||||
*/
|
||||
export type FilterCounters = {
|
||||
[entityType in FilterCounterEntityType]?: { [requestId: string]: number };
|
||||
};
|
||||
|
||||
/** Counters of the filters of one entity type, keyed by filter key. */
|
||||
export interface FilterCountersResult {
|
||||
[filterKey: string]: number;
|
||||
}
|
||||
|
||||
+11
-22
@@ -133,7 +133,6 @@ export class ProcessFiltersCloudComponent implements OnInit, OnChanges {
|
||||
}
|
||||
});
|
||||
|
||||
/* Read along with the filters, not once they arrive, so both components share one request. */
|
||||
this.loadFilterCounters(appName, filters$);
|
||||
}
|
||||
|
||||
@@ -141,11 +140,7 @@ export class ProcessFiltersCloudComponent implements OnInit, OnChanges {
|
||||
* Initialize counter collection for filters
|
||||
*/
|
||||
initFilterCounters(): void {
|
||||
this.filters.forEach((filter) => {
|
||||
if (filter.key) {
|
||||
this.counters[filter.key] = 0;
|
||||
}
|
||||
});
|
||||
this.filters.forEach((filter) => (this.counters[filter.key] = 0));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -283,7 +278,6 @@ export class ProcessFiltersCloudComponent implements OnInit, OnChanges {
|
||||
|
||||
private loadFilterCounters(appName: string, filters$: Observable<ProcessFilterCloudModel[]>): void {
|
||||
this.countersSubscription?.unsubscribe();
|
||||
/* Counters are keyed by filter key, so they are applied once the filters are known. */
|
||||
this.countersSubscription = combineLatest([
|
||||
filters$.pipe(catchError(() => EMPTY)),
|
||||
this.filterCountersCloudService.getFilterCounters(appName, FilterCounterEntityType.PROCESS_INSTANCE)
|
||||
@@ -293,21 +287,16 @@ export class ProcessFiltersCloudComponent implements OnInit, OnChanges {
|
||||
}
|
||||
|
||||
private applyFilterCounters(counters: FilterCountersResult): void {
|
||||
this.filters.forEach((filter) => {
|
||||
/* A filter without a key holds no request id. */
|
||||
const filterKey = filter?.showCounter ? filter.key : undefined;
|
||||
if (!filterKey) {
|
||||
return;
|
||||
}
|
||||
this.filters
|
||||
.filter((filter) => filter?.showCounter)
|
||||
.forEach((filter) => {
|
||||
const counter = counters[filter.key];
|
||||
if (counter === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
const counter = counters[filterKey];
|
||||
/* A filter the request left out keeps the counter it holds, rather than showing a wrong one. */
|
||||
if (counter === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.checkIfFilterValuesHasBeenUpdated(filterKey, counter);
|
||||
this.counters = { ...this.counters, [filterKey]: counter };
|
||||
});
|
||||
this.checkIfFilterValuesHasBeenUpdated(filter.key, counter);
|
||||
this.counters = { ...this.counters, [filter.key]: counter };
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -25,7 +25,7 @@ import { ProcessVariableFilterModel } from '../../../models/process-variable-fil
|
||||
export class ProcessFilterCloudModel {
|
||||
id: string;
|
||||
name: string | null;
|
||||
key: string | null;
|
||||
key: string;
|
||||
icon: string | null;
|
||||
index: number | null;
|
||||
appName: string | null;
|
||||
@@ -79,7 +79,7 @@ export class ProcessFilterCloudModel {
|
||||
|
||||
this.id = obj.id || Math.random().toString(36).substring(2, 9);
|
||||
this.name = obj.name || null;
|
||||
this.key = obj.key || null;
|
||||
this.key = obj.key;
|
||||
this.environmentId = obj.environmentId || null;
|
||||
this.showCounter = obj.showCounter || false;
|
||||
this.icon = obj.icon || null;
|
||||
|
||||
@@ -88,7 +88,6 @@ describe('FilterCountersCloudService', () => {
|
||||
const counters = (entityType: FilterCounterEntityType, appName = 'mock-app') => firstValueFrom(service.getFilterCounters(appName, entityType));
|
||||
const taskCounters = (appName = 'mock-app') => counters(FilterCounterEntityType.TASK, appName);
|
||||
const processCounters = (appName = 'mock-app') => counters(FilterCounterEntityType.PROCESS_INSTANCE, appName);
|
||||
/** As read when both filter components are on screen. */
|
||||
const bothCounters = (appName = 'mock-app') =>
|
||||
firstValueFrom(
|
||||
combineLatest([
|
||||
@@ -114,7 +113,6 @@ describe('FilterCountersCloudService', () => {
|
||||
taskEvents$ = new Subject<EngineEventsResult>();
|
||||
processEvents$ = new Subject<EngineEventsResult>();
|
||||
makeGQLQuerySpy = spyOn(notificationCloudService, 'makeGQLQuery');
|
||||
/* Every entity type holds its own subscription. */
|
||||
makeGQLQuerySpy.and.callFake((_appName: string, query: string) =>
|
||||
(query.includes('TASK_CREATED') ? taskEvents$ : processEvents$).asObservable()
|
||||
);
|
||||
@@ -146,7 +144,6 @@ describe('FilterCountersCloudService', () => {
|
||||
});
|
||||
|
||||
it('should share the filters with the batched count request', async () => {
|
||||
/* The filter component holds its subscription while the counters are resolved. */
|
||||
const subscription = service.getTaskFilters('mock-app').subscribe();
|
||||
await taskCounters();
|
||||
subscription.unsubscribe();
|
||||
@@ -232,13 +229,6 @@ describe('FilterCountersCloudService', () => {
|
||||
expect(countRequestIds(FilterCounterEntityType.TASK)).toEqual(['queued-tasks']);
|
||||
});
|
||||
|
||||
it('should leave out a filter without a key, since it holds no request id', async () => {
|
||||
getProcessFiltersSpy.and.returnValue(of([processFilter({ key: null, status: 'RUNNING', showCounter: true })]));
|
||||
|
||||
expect(await processCounters()).toEqual({});
|
||||
expect(postSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should resolve the counters of an entity type when the filters of the other one fail to load', async () => {
|
||||
getProcessFiltersSpy.and.returnValue(throwError(() => new Error('filters failed')));
|
||||
|
||||
@@ -330,7 +320,6 @@ describe('FilterCountersCloudService', () => {
|
||||
service.getFilterCounters('mock-app', FilterCounterEntityType.TASK).subscribe();
|
||||
tick(0);
|
||||
|
||||
/* Opened again, so the first subscription was closed rather than left behind. */
|
||||
expect(makeGQLQuerySpy).toHaveBeenCalledTimes(2);
|
||||
}));
|
||||
|
||||
@@ -348,11 +337,9 @@ describe('FilterCountersCloudService', () => {
|
||||
}));
|
||||
|
||||
it('should release the filters subscription once nothing reads them', fakeAsync(() => {
|
||||
/* `TaskFilterCloudService.filters$` never completes, so a subscription left behind would be held. */
|
||||
const filters$ = new BehaviorSubject(taskFiltersMock);
|
||||
getTaskListFiltersSpy.and.returnValue(filters$.asObservable());
|
||||
|
||||
/* As the filter component does: the filters are held while the counters are read. */
|
||||
const subscriptions = [
|
||||
service.getTaskFilters('mock-app').subscribe(),
|
||||
service.getFilterCounters('mock-app', FilterCounterEntityType.TASK).subscribe()
|
||||
|
||||
@@ -47,7 +47,6 @@ interface EngineEventsData {
|
||||
engineEvents?: TaskCloudEngineEvent[];
|
||||
}
|
||||
|
||||
/** One subscription per entity type, so an app showing one of them is not notified of the other. */
|
||||
const ENGINE_EVENTS_SUBSCRIPTION_QUERIES: Record<FilterCounterEntityType, string> = {
|
||||
[FilterCounterEntityType.TASK]: `
|
||||
subscription {
|
||||
@@ -264,7 +263,6 @@ export class FilterCountersCloudService extends BaseCloudService {
|
||||
this.recountTrigger(appName).next();
|
||||
}
|
||||
|
||||
// The filters of an entity type that fails to load are left out, so the other one is still counted.
|
||||
private getFiltersForCounters(appName: string): Observable<FilterCountersFilters> {
|
||||
const activeEntityTypes = this.activeEntityTypes(appName);
|
||||
|
||||
@@ -305,7 +303,6 @@ export class FilterCountersCloudService extends BaseCloudService {
|
||||
return this.getFiltersForCounters(appName).pipe(
|
||||
take(1),
|
||||
switchMap((filters) => this.fetchFilterCounters(appName, this.buildRequest(filters))),
|
||||
/* A failed count leaves the counters as they are, rather than breaking the stream. */
|
||||
catchError(() => of({}))
|
||||
);
|
||||
}
|
||||
@@ -314,7 +311,6 @@ export class FilterCountersCloudService extends BaseCloudService {
|
||||
return merge(
|
||||
/* Reads landing in the same task are merged, so both filter components share one request. */
|
||||
merge(of(undefined), this.recountTrigger(appName)).pipe(debounceTime(0, asapScheduler)),
|
||||
/* One debounce over every entity type, so a batch of events also results in one request. */
|
||||
this.eventRecountTrigger(appName).pipe(debounceTime(this.notificationDebounceTime))
|
||||
);
|
||||
}
|
||||
@@ -364,12 +360,12 @@ export class FilterCountersCloudService extends BaseCloudService {
|
||||
buildQuery: (filter: T) => Omit<FilterCountersQuery, 'requestId'>
|
||||
): FilterCountersQuery[] {
|
||||
return (filters ?? [])
|
||||
.filter((filter) => filter?.showCounter && this.isCounterBatched(filter))
|
||||
.filter((filter) => filter?.showCounter)
|
||||
.map((filter) => {
|
||||
try {
|
||||
return { ...buildQuery(filter), requestId: filter.key as string };
|
||||
return { ...buildQuery(filter), requestId: filter.key };
|
||||
} catch {
|
||||
/* A malformed filter is left without a counter, so the others still hold one. */
|
||||
/* Left without a counter, so the other filters still hold theirs. */
|
||||
return undefined;
|
||||
}
|
||||
})
|
||||
@@ -385,9 +381,4 @@ export class FilterCountersCloudService extends BaseCloudService {
|
||||
|
||||
return this.post<FilterCountersRequest, FilterCounters>(queryUrl, request).pipe(map((counters) => counters || {}));
|
||||
}
|
||||
|
||||
// A filter without a key holds no `requestId` its counter could be keyed by.
|
||||
private isCounterBatched(filter: FilterCounterCandidate): boolean {
|
||||
return !!filter?.key;
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -108,7 +108,7 @@ export class ServiceTaskFiltersCloudComponent extends BaseTaskFiltersCloudCompon
|
||||
this.filters.find(
|
||||
(filter, index) =>
|
||||
paramFilter.index === index ||
|
||||
paramFilter.key === filter.key ||
|
||||
(!!paramFilter.key && paramFilter.key === filter.key) ||
|
||||
paramFilter.id === filter.id ||
|
||||
(paramFilter.name && paramFilter.name.toLocaleLowerCase() === this.translationService.instant(filter.name).toLocaleLowerCase())
|
||||
); // fallback to preserve the previous behavior
|
||||
|
||||
+11
-18
@@ -118,7 +118,6 @@ export class TaskFiltersCloudComponent extends BaseTaskFiltersCloudComponent imp
|
||||
}
|
||||
});
|
||||
|
||||
/* Read along with the filters, not once they arrive, so both components share one request. */
|
||||
this.loadFilterCounters(appName, filters$);
|
||||
}
|
||||
|
||||
@@ -170,7 +169,7 @@ export class TaskFiltersCloudComponent extends BaseTaskFiltersCloudComponent imp
|
||||
this.filters.find(
|
||||
(filter, index) =>
|
||||
paramFilter.index === index ||
|
||||
paramFilter.key === filter.key ||
|
||||
(!!paramFilter.key && paramFilter.key === filter.key) ||
|
||||
paramFilter.id === filter.id ||
|
||||
(paramFilter.name && paramFilter.name.toLocaleLowerCase() === this.translationService.instant(filter.name).toLocaleLowerCase())
|
||||
); // fallback to preserve the previous behavior
|
||||
@@ -241,7 +240,6 @@ export class TaskFiltersCloudComponent extends BaseTaskFiltersCloudComponent imp
|
||||
|
||||
private loadFilterCounters(appName: string, filters$: Observable<TaskFilterCloudModel[]>): void {
|
||||
this.countersSubscription?.unsubscribe();
|
||||
/* Counters are keyed by filter key, so they are applied once the filters are known. */
|
||||
this.countersSubscription = combineLatest([
|
||||
filters$.pipe(catchError(() => of([]))),
|
||||
this.filterCountersCloudService.getFilterCounters(appName, FilterCounterEntityType.TASK)
|
||||
@@ -251,22 +249,17 @@ export class TaskFiltersCloudComponent extends BaseTaskFiltersCloudComponent imp
|
||||
}
|
||||
|
||||
private applyFilterCounters(counters: FilterCountersResult): void {
|
||||
this.filters.forEach((filter) => {
|
||||
/* A filter without a key holds no request id. */
|
||||
const filterKey = filter?.showCounter ? filter.key : undefined;
|
||||
if (!filterKey) {
|
||||
return;
|
||||
}
|
||||
this.filters
|
||||
.filter((filter) => filter?.showCounter)
|
||||
.forEach((filter) => {
|
||||
const counter = counters[filter.key];
|
||||
if (counter === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
const counter = counters[filterKey];
|
||||
/* A filter the request left out keeps the counter it holds, rather than showing a wrong one. */
|
||||
if (counter === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.checkIfFilterValuesHasBeenUpdated(filterKey, counter);
|
||||
this.counters = { ...this.counters, [filterKey]: counter };
|
||||
});
|
||||
this.checkIfFilterValuesHasBeenUpdated(filter.key, counter);
|
||||
this.counters = { ...this.counters, [filter.key]: counter };
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -84,7 +84,7 @@ export class TaskFilterCloudModel {
|
||||
if (obj) {
|
||||
this.id = obj.id || Math.random().toString(36).substr(2, 9);
|
||||
this.name = obj.name || null;
|
||||
this.key = obj.key || null;
|
||||
this.key = obj.key;
|
||||
this.environmentId = obj.environmentId || null;
|
||||
this.icon = obj.icon || null;
|
||||
this.index = obj.index || null;
|
||||
|
||||
Reference in New Issue
Block a user