From 19134fe84cd781e149bf6e9c45b221f6bc7152db Mon Sep 17 00:00:00 2001 From: manelcecs Date: Tue, 30 Jan 2024 15:11:00 +0100 Subject: [PATCH] Allow no sorting from client --- .../flows/flow-search-service.ts | 38 +++---------------- src/domain-services/flows/flow-service.ts | 23 ++++++----- .../search-flow-by-filters-strategy-impl.ts | 17 +++++++-- .../flows/strategy/impl/utils.ts | 31 ++++++++++++--- 4 files changed, 60 insertions(+), 49 deletions(-) diff --git a/src/domain-services/flows/flow-search-service.ts b/src/domain-services/flows/flow-search-service.ts index e6d1e58e..6ad5338a 100644 --- a/src/domain-services/flows/flow-search-service.ts +++ b/src/domain-services/flows/flow-search-service.ts @@ -208,8 +208,8 @@ export class FlowSearchService { // Categories Map follows the structure: // flowID: { versionID: [categories]} // So we need to get the categories for the flow version - const categories = - categoriesMap.get(flow.id)!.get(flow.versionID) ?? []; + const categories = categoriesMap.get(flow.id); + const categoriesByVersion = categories?.get(flow.versionID) ?? []; const organizations = organizationsMap.get(flow.id) ?? []; const locations = locationsMap.get(flow.id) ?? []; const plans = plansMap.get(flow.id) ?? []; @@ -253,7 +253,7 @@ export class FlowSearchService { return this.buildFlowDTO( flow, - categories, + categoriesByVersion, organizations, locations, plans, @@ -267,27 +267,6 @@ export class FlowSearchService { }) ); - // const isOrderByForFlows = orderBy.entity === 'flow'; - // const firstItem = items[0]; - // const prevPageCursorEntity = isOrderByForFlows - // ? firstItem - // : firstItem[orderBy.entity as keyof typeof firstItem]; - // const prevPageCursorValue = prevPageCursorEntity - // ? prevPageCursorEntity[ - // orderBy.column as keyof typeof prevPageCursorEntity - // ] ?? '' - // : ''; - - // const lastItem = items.at(-1); - // const nextPageCursorEntity = isOrderByForFlows - // ? lastItem - // : lastItem![orderBy.entity as keyof typeof lastItem]; - // const nextPageCursorValue = nextPageCursorEntity - // ? nextPageCursorEntity[ - // orderBy.column as keyof typeof nextPageCursorEntity - // ]?.toString() ?? '' - // : ''; - return { flows: items, hasNextPage: limit <= flows.length, @@ -343,7 +322,7 @@ export class FlowSearchService { operation: filter.flag ? Op.IN : Op.NOT_IN, })); - return shortcutFilters; + return shortcutFilters.length > 0 ? shortcutFilters : null; } determineStrategy( @@ -360,7 +339,8 @@ export class FlowSearchService { // If there are no sortByEntity (orderBy.entity === 'flow') // but flowFilters only // use onlyFlowFiltersStrategy - const isOrderByEntityFlow = orderBy?.entity === 'flow'; + const isOrderByEntityFlow = + orderBy === undefined || orderBy?.entity === 'flow'; const isFlowFiltersDefined = flowFilters !== undefined; const isFlowObjectFiltersDefined = flowObjectFilters !== undefined; const isFlowCategoryFiltersDefined = flowCategoryFilters !== undefined; @@ -764,12 +744,6 @@ export class FlowSearchService { } // Validate the shortcut filters - // There must be only one shortcut filter - // if only one is defined - // return an object like - // { category: 'Parked', operation: 'IN' } - // if more than one is defined - // throw an error const shortcutFilter = this.mapShortcutFilters( isPendingFlows, isCommitmentFlows, diff --git a/src/domain-services/flows/flow-service.ts b/src/domain-services/flows/flow-service.ts index 0aeea8be..5ff4f4ac 100644 --- a/src/domain-services/flows/flow-service.ts +++ b/src/domain-services/flows/flow-service.ts @@ -69,15 +69,6 @@ export class FlowService { // Get the entity list const mappedOrderBy = mapFlowOrderBy(orderBy); - const entityList = await dbConnection - .queryBuilder() - .select( - orderBy.subEntity ? `${orderBy.subEntity}Id` : 'id', - 'flowID', - 'versionID' - ) - .from(entity) - .orderBy(mappedOrderBy.column, mappedOrderBy.order); let mapFlowsToUniqueFlowEntities; @@ -89,6 +80,13 @@ export class FlowService { const result = FlowObjectType.decode(entityCondKey); if (result._tag === 'Right') { + const entityList = await dbConnection + .queryBuilder() + .select('id') + .from(entity) + .orderBy(mappedOrderBy.column, mappedOrderBy.order) + .orderBy('id', mappedOrderBy.order); + const entityIDs = entityList.map((entity) => entity.id); const entityCondKeyFlowObjectType = entityCondKey as FlowObjectType; let query = dbConnection @@ -116,6 +114,13 @@ export class FlowService { versionID: flowID.versionID, })); } else { + const entityList = await dbConnection + .queryBuilder() + .select(`${orderBy.subEntity}Id`, 'flowID', 'versionID') + .from(entity) + .orderBy(mappedOrderBy.column, mappedOrderBy.order) + .orderBy('id', mappedOrderBy.order); + mapFlowsToUniqueFlowEntities = entityList.map((entity) => ({ id: entity.flowID, versionID: entity.versionID, diff --git a/src/domain-services/flows/strategy/impl/search-flow-by-filters-strategy-impl.ts b/src/domain-services/flows/strategy/impl/search-flow-by-filters-strategy-impl.ts index 10b24899..d1c6bde8 100644 --- a/src/domain-services/flows/strategy/impl/search-flow-by-filters-strategy-impl.ts +++ b/src/domain-services/flows/strategy/impl/search-flow-by-filters-strategy-impl.ts @@ -1,6 +1,7 @@ import { Cond } from '@unocha/hpc-api-core/src/db/util/conditions'; import { Service } from 'typedi'; import { FlowService } from '../../flow-service'; +import { type SearchFlowsFilters } from '../../graphql/args'; import { type FlowEntity, type UniqueFlowEntity } from '../../model'; import { type FlowSearchArgs, @@ -219,9 +220,9 @@ export class SearchFlowByFiltersStrategy implements FlowSearchStrategy { ); // Once the list of elements is reduced, we need to build the conditions - const searchConditions = this.buildConditions(reducedFlows); + const searchConditions = this.buildConditions(reducedFlows, flowFilters); - const orderByForFlow = mapFlowOrderBy(orderBy); + const orderByForFlow = { column: 'updatedAt', order: 'DESC' }; const flows = await this.flowService.getFlows({ models, @@ -232,11 +233,21 @@ export class SearchFlowByFiltersStrategy implements FlowSearchStrategy { return { flows, count }; } - buildConditions(uniqueFlowEntities: UniqueFlowEntity[]): any { + buildConditions( + uniqueFlowEntities: UniqueFlowEntity[], + flowFilters: SearchFlowsFilters + ): any { const whereClauses = uniqueFlowEntities.map((flow) => ({ [Cond.AND]: [{ id: flow.id }, { versionID: flow.versionID }], })); + if (flowFilters) { + const flowConditions = prepareFlowConditions(flowFilters); + return { + [Cond.AND]: [flowConditions, { [Cond.OR]: whereClauses }], + }; + } + return { [Cond.OR]: whereClauses, }; diff --git a/src/domain-services/flows/strategy/impl/utils.ts b/src/domain-services/flows/strategy/impl/utils.ts index f0a0378e..bdc8db79 100644 --- a/src/domain-services/flows/strategy/impl/utils.ts +++ b/src/domain-services/flows/strategy/impl/utils.ts @@ -142,16 +142,37 @@ export function mergeFlowIDsFromFilteredFlowObjectsAndFlowCategories( ); } -export function mapFlowOrderBy(orderBy: any) { +export const sortingColumnMapping: Map = new Map< + string, + string +>([ + ['reporterRefCode', 'refCode'], + ['sourceID', 'sourceID'], +]); + +export function mapFlowOrderBy(orderBy: any): { + column: string; + order: string; +} { if (!orderBy) { return { column: 'updatedAt', order: 'DESC' }; } - let orderByForFlow = { column: orderBy.column, order: orderBy.order }; - if (orderBy.entity !== 'flow') { - orderByForFlow = { column: 'updatedAt', order: 'DESC' }; + + if (orderBy.entity === 'flow') { + return { column: orderBy.column, order: orderBy.order }; + } + + let columnToSort: string; + if (sortingColumnMapping.has(orderBy.column)) { + // I don't like this but the compiler is complaining + // that columnToSort might be undefined if I don't do this + // but it's already checked that the column exists in the map + columnToSort = sortingColumnMapping.get(orderBy.column) ?? 'updatedAt'; + } else { + columnToSort = orderBy.column; } - return orderByForFlow; + return { column: columnToSort, order: orderBy.order }; } export function prepareFlowConditions(flowFilters: SearchFlowsFilters): any {