From 23b1bcf3de17f7b0c79a8faba82acc4d3ef592a2 Mon Sep 17 00:00:00 2001 From: Anders Wulff Kringelbach Date: Thu, 27 Jul 2023 17:38:32 +0200 Subject: [PATCH] Add agencies endpoint --- .../schematransform.test.js.snap | 104 ++++++++++ src/datasources/agencies.datasource.js | 91 +++++++++ src/datasources/library.datasource.js | 1 + src/schema/agencies.js | 183 ++++++++++++++++++ src/schema/root.js | 14 ++ 5 files changed, 393 insertions(+) create mode 100644 src/datasources/agencies.datasource.js create mode 100644 src/schema/agencies.js diff --git a/src/__tests__/__snapshots__/schematransform.test.js.snap b/src/__tests__/__snapshots__/schematransform.test.js.snap index b5e1a7c8..fe58b065 100644 --- a/src/__tests__/__snapshots__/schematransform.test.js.snap +++ b/src/__tests__/__snapshots__/schematransform.test.js.snap @@ -275,6 +275,105 @@ type AdminData { requestButton: Boolean } +type LatitudeLongitude { + \\"\\"\\"Geolocation latitude\\"\\"\\" + latitude: Float! + + \\"\\"\\"Geolocation longitude\\"\\"\\" + longitude: Float! +} + +type AgencyList { + \\"\\"\\"Total number of agencies with branches that match query\\"\\"\\" + agencyCount: Int! + + \\"\\"\\"List of agencyIds with branches that match query\\"\\"\\" + agencyIds: [String!]! + + \\"\\"\\" + Total number of branches that match query (across all resulting agencies) + \\"\\"\\" + branchCount: Int! + + \\"\\"\\" + List of branchIds of branches that match query (across all resulting agencies) + \\"\\"\\" + branchIds: [String!]! + + \\"\\"\\"Agencies with branches that match query\\"\\"\\" + agencies: [Agency!]! +} + +type Agency { + \\"\\"\\"Id of the agency (queryable)\\"\\"\\" + agencyId: String! + + \\"\\"\\"Name of the agency (queryable)\\"\\"\\" + agencyName: String! + + \\"\\"\\"Agency phonenumber (likely the main branch's number or null)\\"\\"\\" + agencyPhone: String + + \\"\\"\\"Agency email (likely the main branch's number or null)\\"\\"\\" + agencyEmail: String + + \\"\\"\\"Number of branches that match query within agency\\"\\"\\" + branchCount: Int! + + \\"\\"\\"List of branchIds of branches that match query within agency\\"\\"\\" + branchIds: [String!]! + + \\"\\"\\"Highlights specific to the agency\\"\\"\\" + highlights: [Highlight!]! + + \\"\\"\\"Branches that match query within agency\\"\\"\\" + agencyBranches: [AgencyBranch!]! +} + +type AgencyBranch { + \\"\\"\\"Id of the branch's agency (queryable)\\"\\"\\" + agencyId: String! + + \\"\\"\\"Name of the branch's agency (queryable)\\"\\"\\" + agencyName: String! + + \\"\\"\\"Id of the branch (queryable)\\"\\"\\" + branchId: String! + + \\"\\"\\"Name of the branch (queryable)\\"\\"\\" + branchName: [String!]! + + \\"\\"\\"Shortname of the branch (queryable)\\"\\"\\" + branchShortName: [String!]! + + \\"\\"\\"Branch's phonenumber\\"\\"\\" + branchPhone: String + + \\"\\"\\"Branch's email\\"\\"\\" + branchEmail: String + + \\"\\"\\"Branch's InterLibraryLoan email\\"\\"\\" + branchIllEmail: String + + \\"\\"\\"The city the branch is located in (queryable)\\"\\"\\" + city: String + + \\"\\"\\"The geolocation of the branch\\"\\"\\" + geolocation: LatitudeLongitude + + \\"\\"\\"Highlights specific to the branch and its agency\\"\\"\\" + highlights: [Highlight!]! + + \\"\\"\\"Opening hours of the branch (can be a html-element)\\"\\"\\" + openingHours: [String!]! + + \\"\\"\\"Address of the branch (queryable)\\"\\"\\" + postalAddress: String + + \\"\\"\\"PostalCode of the branch (queryable)\\"\\"\\" + postalCode: Int +} + enum BorchkRequestStatus { ok service_not_licensed @@ -2235,6 +2334,11 @@ type Query { session: Session howru: String localizations(pids: [String!]!): Localizations + + \\"\\"\\" + Agencies with branches that match query (queries on branch's: agencyId, agencyName, branchId, branchName, postalAddress, postalCode, city) + \\"\\"\\" + agencies(q: String!, status: String, limit: Int, offset: Int, language: LanguageCode, bibdkExcludeBranches: Boolean): AgencyList! refWorks(pid: String!): String! ris(pid: String!): String! relatedSubjects(q: [String!]!, limit: Int): [String!] diff --git a/src/datasources/agencies.datasource.js b/src/datasources/agencies.datasource.js new file mode 100644 index 00000000..f1fee1d9 --- /dev/null +++ b/src/datasources/agencies.datasource.js @@ -0,0 +1,91 @@ +import groupBy from "lodash/groupBy"; +import sum from "lodash/sum"; + +function parseAgencyList(agencyList) { + return agencyList.map((agency) => { + return { + agencyId: agency.agencyId, + agencyName: agency.agencyName, + agencyPhone: agency.agencyPhone, + agencyEmail: agency.agencyEmail, + highlights: agency.highlights || [], + branchCount: agency.branchCount, + branchIds: agency.branchIds, + agencyBranches: + agency?.branches?.map((branch) => { + return { + agencyId: agency.agencyId, + agencyName: agency.agencyName, + branchId: branch.branchId, + branchName: branch.branchName || [], + branchShortName: branch.branchShortName || [], + branchPhone: branch.branchPhone, + branchEmail: branch.branchEmail, + branchIllEmail: branch.branchIllEmail, + city: branch.city, + geolocation: branch.geolocation, + highlights: branch.highlights || [], + openingHours: branch.openingHours || [], + postalAddress: branch.postalAddress, + postalCode: branch.postalCode, + }; + }) || [], + }; + }); +} + +export async function load( + { + q, + status = "ALLE", + limit = 10, + offset = 0, + language = "da", + bibdkExcludeBranches = true, + }, + context +) { + const librariesFound = await context.getLoader("library").load({ + q: q, + status: status, + limit: limit, + offset: offset, + language: language, + bibdkExcludeBranches: bibdkExcludeBranches, + }); + + const groupedByAgency = groupBy(librariesFound?.result, "agencyId"); + + const agenciesFlat = Object.values(groupedByAgency)?.map((branches) => { + return { + agencyId: branches?.map((e) => e.agencyId)?.[0], + agencyName: branches?.map((e) => e.agencyName)?.[0], + agencyPhone: branches?.map((e) => e.agencyPhone)?.[0], + agencyEmail: branches?.map((e) => e.agencyEmail)?.[0], + highlights: branches?.map((e) => e.highlights)?.[0], + branchCount: branches?.length, + branchIds: branches?.map((e) => e.branchId) || [], + branches: branches, + }; + }); + + return { + agencyCount: agenciesFlat.length, + agencyIds: + (groupedByAgency && + Object.keys(groupedByAgency).filter( + (agencyId) => typeof agencyId !== "undefined" + )) || + [], + branchCount: sum(agenciesFlat.map((agency) => agency.branchCount)), + branchIds: agenciesFlat?.flatMap((agency) => agency.branchIds), + agencies: parseAgencyList(agenciesFlat), + }; +} + +export const options = { + redis: { + prefix: "agencyList", + ttl: 60 * 15, + }, +}; diff --git a/src/datasources/library.datasource.js b/src/datasources/library.datasource.js index 965eb739..1ffa4048 100644 --- a/src/datasources/library.datasource.js +++ b/src/datasources/library.datasource.js @@ -19,6 +19,7 @@ const fields = [ "name", "agencyName", "agencyId", + "branchName", "branchId", "city", "postalCode", diff --git a/src/schema/agencies.js b/src/schema/agencies.js new file mode 100644 index 00000000..5e806b4d --- /dev/null +++ b/src/schema/agencies.js @@ -0,0 +1,183 @@ +export const typeDef = ` +type LatitudeLongitude { + """ + Geolocation latitude + """ + latitude: Float! + + """ + Geolocation longitude + """ + longitude: Float! +} + +type AgencyList { + """ + Total number of agencies with branches that match query + """ + agencyCount: Int! + + """ + List of agencyIds with branches that match query + """ + agencyIds: [String!]! + + """ + Total number of branches that match query (across all resulting agencies) + """ + branchCount: Int! + + """ + List of branchIds of branches that match query (across all resulting agencies) + """ + branchIds: [String!]! + + """ + Agencies with branches that match query + """ + agencies: [Agency!]! +} + +type Agency { + """ + Id of the agency (queryable) + """ + agencyId: String! + + """ + Name of the agency (queryable) + """ + agencyName: String! + + """ + Agency phonenumber (likely the main branch's number or null) + """ + agencyPhone: String + + """ + Agency email (likely the main branch's number or null) + """ + agencyEmail: String + + """ + Number of branches that match query within agency + """ + branchCount: Int! + + """ + List of branchIds of branches that match query within agency + """ + branchIds: [String!]! + + """ + Highlights specific to the agency + """ + highlights: [Highlight!]! + + """ + Branches that match query within agency + """ + agencyBranches: [AgencyBranch!]! +} + +type AgencyBranch { + """ + Id of the branch's agency (queryable) + """ + agencyId: String! + + """ + Name of the branch's agency (queryable) + """ + agencyName: String! + + """ + Id of the branch (queryable) + """ + branchId: String! + + """ + Name of the branch (queryable) + """ + branchName: [String!]! + + """ + Shortname of the branch (queryable) + """ + branchShortName: [String!]! + + """ + Branch's phonenumber + """ + branchPhone: String + + """ + Branch's email + """ + branchEmail: String + + """ + Branch's InterLibraryLoan email + """ + branchIllEmail: String + + """ + The city the branch is located in (queryable) + """ + city: String + + """ + The geolocation of the branch + """ + geolocation: LatitudeLongitude + + """ + Highlights specific to the branch and its agency + """ + highlights: [Highlight!]! + + """ + Opening hours of the branch (can be a html-element) + """ + openingHours: [String!]! + + """ + Address of the branch (queryable) + """ + postalAddress: String + + """ + PostalCode of the branch (queryable) + """ + postalCode: Int +} +`; + +function highlightResolver(parent, includedFields = null) { + if (!parent.highlights) { + return []; + } + + return Object.entries(parent.highlights) + .map(([key, value]) => ({ + key, + value, + })) + .filter((highlight) => highlight.value.includes("")) + .filter((highlight) => + includedFields === null ? true : includedFields.includes(highlight.key) + ); +} + +export const resolvers = { + Agency: { + highlights(parent, args, context, info) { + return highlightResolver(parent, ["agencyName", "agencyId"]); + }, + }, + AgencyBranch: { + highlights(parent, args, context, info) { + return highlightResolver(parent); + }, + }, +}; diff --git a/src/schema/root.js b/src/schema/root.js index dd3dae30..5daa8dc1 100644 --- a/src/schema/root.js +++ b/src/schema/root.js @@ -87,6 +87,10 @@ type Query { session: Session howru:String localizations(pids:[String!]!): Localizations @complexity(value: 35, multipliers: ["pids"]) + """ + Agencies with branches that match query (queries on branch's: agencyId, agencyName, branchId, branchName, postalAddress, postalCode, city) + """ + agencies(q: String!, status: String, limit: Int, offset: Int, language: LanguageCode, bibdkExcludeBranches: Boolean): AgencyList! @complexity(value: 1, multipliers: ["limit"]) refWorks(pid:String!):String! ris(pid:String!):String! relatedSubjects(q:[String!]!, limit:Int ): [String!] @complexity(value: 3, multipliers: ["q", "limit"]) @@ -208,6 +212,16 @@ export const resolvers = { return localizations; }, + async agencies(parent, args, context, info) { + return await context.datasources.getLoader("agencies").load({ + q: args.q, + status: args.status, + limit: args.limit, + offset: args.offset, + language: args.language, + bibdkExcludeBranches: args.language, + }); + }, howru(parent, args, context, info) { return "gr8"; },