From 44bb6f2dc8acfcc75434b870c84441486671d73c Mon Sep 17 00:00:00 2001 From: Ben Stoltz Date: Fri, 11 Oct 2024 11:00:51 -0400 Subject: [PATCH] feat: events processFilters support occurrence && group to sharedToGroup (#1683) --- package-lock.json | 2 +- .../hubEventsHelpers/processFilters.ts | 78 +++++---- .../hubEventsHelpers/processFilters.test.ts | 159 ++++++++---------- 3 files changed, 114 insertions(+), 125 deletions(-) diff --git a/package-lock.json b/package-lock.json index 006486e466d..d3913b0029a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -65017,7 +65017,7 @@ }, "packages/common": { "name": "@esri/hub-common", - "version": "14.204.0", + "version": "14.211.0", "license": "Apache-2.0", "dependencies": { "@terraformer/arcgis": "^2.1.2", diff --git a/packages/common/src/search/_internal/hubEventsHelpers/processFilters.ts b/packages/common/src/search/_internal/hubEventsHelpers/processFilters.ts index a7a042f0ef9..8b4443b3a4d 100644 --- a/packages/common/src/search/_internal/hubEventsHelpers/processFilters.ts +++ b/packages/common/src/search/_internal/hubEventsHelpers/processFilters.ts @@ -56,28 +56,12 @@ export async function processFilters( if (tags?.length) { processedFilters.tags = tags; } - const groupIds = getPredicateValuesByKey(filters, "group"); + const groupIds = getOptionalPredicateStringsByKey(filters, "group"); // if a group was provided, we prioritize that over individual readGroupId or editGroupId // filters to prevent collisions - if (groupIds.length) { - const { results } = await searchGroups({ - q: `id:(${groupIds.join(" OR ")})`, - num: groupIds.length, - ...requestOptions, - }); - const { readGroupIds, editGroupIds } = results.reduce( - (acc, group) => { - const key = isUpdateGroup(group) ? "editGroupIds" : "readGroupIds"; - return { ...acc, [key]: [...acc[key], group.id] }; - }, - { readGroupIds: [], editGroupIds: [] } - ); - if (readGroupIds.length) { - processedFilters.readGroups = readGroupIds.join(","); - } - if (editGroupIds.length) { - processedFilters.editGroups = editGroupIds.join(","); - } + if (groupIds?.length) { + // We are explicitly sending groupIds to sharedToGroups + processedFilters.sharedToGroups = groupIds; } else { // individual readGroupId & editGroupId filters const readGroupIds = getOptionalPredicateStringsByKey( @@ -95,6 +79,8 @@ export async function processFilters( processedFilters.editGroups = editGroupIds; } } + // NOTE: previously notGroup was an inverse of group, but now they are subtly different + // We do not yet have an inverse of sharedToGroups. const notGroupIds = getPredicateValuesByKey(filters, "notGroup"); // if a notGroup was provided, we prioritize that over individual notReadGroupId or notEditGroupId // filters to prevent collisions @@ -159,13 +145,17 @@ export async function processFilters( ); // if a startDateRange was provided, we prioritize that over individual startDateBefore or startDateAfter // filters to prevent collisions + // We are explicitly checking if the to and from values are present + // Because w/ Occurrence, we can have just to or from values if (startDateRange.length) { - processedFilters.startDateTimeBefore = new Date( - startDateRange[0].to - ).toISOString(); - processedFilters.startDateTimeAfter = new Date( - startDateRange[0].from - ).toISOString(); + startDateRange[0].to && + (processedFilters.startDateTimeBefore = new Date( + startDateRange[0].to + ).toISOString()); + startDateRange[0].from && + (processedFilters.startDateTimeAfter = new Date( + startDateRange[0].from + ).toISOString()); } else { // individual startDateBefore & startDateAfter filters const startDateBefore = getPredicateValuesByKey( @@ -193,13 +183,17 @@ export async function processFilters( ); // if a endDateRange was provided, we prioritize that over individual endDateBefore or endDateAfter // filters to prevent collisions + // We are explicitly checking if the to and from values are present + // Because w/ Occurrence, we can have just to or from values if (endDateRange.length) { - processedFilters.endDateTimeBefore = new Date( - endDateRange[0].to - ).toISOString(); - processedFilters.endDateTimeAfter = new Date( - endDateRange[0].from - ).toISOString(); + endDateRange[0].to && + (processedFilters.endDateTimeBefore = new Date( + endDateRange[0].to + ).toISOString()); + endDateRange[0].from && + (processedFilters.endDateTimeAfter = new Date( + endDateRange[0].from + ).toISOString()); } else { // individual endDateBefore & endDateAfter filters const endDateBefore = getPredicateValuesByKey( @@ -221,5 +215,25 @@ export async function processFilters( ).toISOString(); } } + + // If there's an occurrence filter, we need to adjust the startDateTimeBefore, startDateTimeAfter + // Depending on the occurrence. + const occurrence = getPredicateValuesByKey(filters, "occurrence"); + if (occurrence.length) { + occurrence.forEach((o) => { + switch (o) { + case "upcoming": + processedFilters.startDateTimeAfter = new Date().toISOString(); + break; + case "past": + processedFilters.endDateTimeBefore = new Date().toISOString(); + break; + case "inProgress": + processedFilters.startDateTimeBefore = new Date().toISOString(); + processedFilters.endDateTimeAfter = new Date().toISOString(); + break; + } + }); + } return processedFilters; } diff --git a/packages/common/test/search/_internal/hubEventsHelpers/processFilters.test.ts b/packages/common/test/search/_internal/hubEventsHelpers/processFilters.test.ts index dc20c600b3d..e7b841e1d54 100644 --- a/packages/common/test/search/_internal/hubEventsHelpers/processFilters.test.ts +++ b/packages/common/test/search/_internal/hubEventsHelpers/processFilters.test.ts @@ -489,16 +489,9 @@ describe("processFilters", () => { [{ predicates: [] }], hubRequestOptions ); - expect(result.readGroups).toBeUndefined(); - expect(result.editGroups).toBeUndefined(); + expect(result.sharedToGroups).toBeUndefined(); }); - it("should return readGroups and editGroups", async () => { - const searchGroupsSpy = spyOn( - arcgisRestPortal, - "searchGroups" - ).and.returnValue( - Promise.resolve({ results: [editGroup1, readGroup1, editGroup2] }) - ); + it("should return returnToGroups if group has been supplied", async () => { const result = await processFilters( [ { @@ -518,89 +511,8 @@ describe("processFilters", () => { ], hubRequestOptions ); - expect(searchGroupsSpy).toHaveBeenCalledTimes(1); - expect(searchGroupsSpy).toHaveBeenCalledWith({ - q: `id:(${[editGroup1.id, readGroup1.id, editGroup2.id].join(" OR ")})`, - num: 3, - ...hubRequestOptions, - }); - expect(result.readGroups).toEqual(readGroup1.id); - expect(result.editGroups).toEqual( - [editGroup1.id, editGroup2.id].join(",") - ); - }); - it("should filter out inaccessible groups", async () => { - const searchGroupsSpy = spyOn( - arcgisRestPortal, - "searchGroups" - ).and.returnValue(Promise.resolve({ results: [] })); - const result = await processFilters( - [ - { - predicates: [ - { - group: editGroup1.id, - }, - ], - }, - { - predicates: [ - { - group: [readGroup1.id, editGroup2.id], - }, - ], - }, - ], - hubRequestOptions - ); - expect(searchGroupsSpy).toHaveBeenCalledTimes(1); - expect(searchGroupsSpy).toHaveBeenCalledWith({ - q: `id:(${[editGroup1.id, readGroup1.id, editGroup2.id].join(" OR ")})`, - num: 3, - ...hubRequestOptions, - }); - expect(result.readGroups).toBeUndefined(); - expect(result.editGroups).toBeUndefined(); - }); - it("should be prioritized over individual readGroupId and editGroupId", async () => { - const searchGroupsSpy = spyOn( - arcgisRestPortal, - "searchGroups" - ).and.returnValue( - Promise.resolve({ results: [editGroup1, readGroup1, editGroup2] }) - ); - const result = await processFilters( - [ - { - predicates: [ - { - group: editGroup1.id, - }, - { - readGroupId: "some-other-read-group-id", - }, - ], - }, - { - predicates: [ - { - group: [readGroup1.id, editGroup2.id], - editGroupId: ["some-other-edit-group-id"], - }, - ], - }, - ], - hubRequestOptions - ); - expect(searchGroupsSpy).toHaveBeenCalledTimes(1); - expect(searchGroupsSpy).toHaveBeenCalledWith({ - q: `id:(${[editGroup1.id, readGroup1.id, editGroup2.id].join(" OR ")})`, - num: 3, - ...hubRequestOptions, - }); - expect(result.readGroups).toEqual(readGroup1.id); - expect(result.editGroups).toEqual( - [editGroup1.id, editGroup2.id].join(",") + expect(result.sharedToGroups).toEqual( + [editGroup1.id, readGroup1.id, editGroup2.id].join(",") ); }); }); @@ -1101,4 +1013,67 @@ describe("processFilters", () => { expect(result.endDateTimeAfter).toEqual("2024-04-28T04:00:00.000Z"); }); }); + describe("occurrence", () => { + const mockedDate = new Date(1711987200000); + beforeAll(() => { + jasmine.clock().mockDate(mockedDate); + }); + afterAll(() => { + jasmine.clock().uninstall(); + }); + it("should return undefined", async () => { + const result = await processFilters( + [{ predicates: [] }], + hubRequestOptions + ); + expect(result.startDateTimeBefore).toBeUndefined(); + expect(result.startDateTimeAfter).toBeUndefined(); + }); + it("should handle upcoming", async () => { + const result = await processFilters( + [ + { + predicates: [ + { + occurrence: "upcoming", + }, + ], + }, + ], + hubRequestOptions + ); + expect(result.startDateTimeAfter).toEqual(mockedDate.toISOString()); + }); + it("should handle past", async () => { + const result = await processFilters( + [ + { + predicates: [ + { + occurrence: "past", + }, + ], + }, + ], + hubRequestOptions + ); + expect(result.endDateTimeBefore).toEqual(mockedDate.toISOString()); + }); + it("should handle inProgress", async () => { + const result = await processFilters( + [ + { + predicates: [ + { + occurrence: "inProgress", + }, + ], + }, + ], + hubRequestOptions + ); + expect(result.startDateTimeBefore).toEqual(mockedDate.toISOString()); + expect(result.endDateTimeAfter).toEqual(mockedDate.toISOString()); + }); + }); });