diff --git a/CHANGELOG.md b/CHANGELOG.md index e625863b..d4c12bb5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,11 @@ All notable changes to this project will be documented in this file. The format ## [UNRELEASED] +### Added + +- The API endpoints for listing and fetching KPI details now include KPI + description and parent information. + ### Removed - The Google Sheets integration has been completely removed, both for key diff --git a/functions/api/helpers.js b/functions/api/helpers.js index bc0f45ae..34a538f4 100644 --- a/functions/api/helpers.js +++ b/functions/api/helpers.js @@ -2,6 +2,20 @@ import crypto from 'crypto'; import { FieldValue, getFirestore } from 'firebase-admin/firestore'; import { endOfDay, startOfDay, setHours, isWithinInterval, sub } from 'date-fns'; +/** + * Return resolved document by reference. + * + * `documentRef` is the Firestore reference to resolve. + */ +export async function getDocumentDataByRef(documentRef) { + if (typeof documentRef.get === 'function') { + return documentRef.get().then((snapshot) => { + return snapshot.exists ? snapshot.data() : null; + }); + } + return null; +} + /** * Return a user's display name. If the referenced Firestore reference * does not exist, attempt to extract reference suffix (email). @@ -9,18 +23,20 @@ import { endOfDay, startOfDay, setHours, isWithinInterval, sub } from 'date-fns' * `userRef` is the Firestore reference to resolve. */ export async function getUserDisplayName(userRef) { + const userData = await getDocumentDataByRef(userRef); + + if (userData?.displayName) { + return userData.displayName; + } + if (typeof userRef.get === 'function') { - return userRef.get().then((snapshot) => { - if (!snapshot.exists) { - return userRef.path.split('users/')[1]; - } - const userData = snapshot.data(); - return userData.displayName; - }); + return userRef.path.split('users/')[1]; } + if (typeof userRef === 'string') { return userRef.split('users/')[1]; } + return null; } @@ -132,6 +148,8 @@ export async function buildKpiResponse(kpiSnapshot) { edited, editedBy, name, + description, + parent, type, updateFrequency, } = kpiSnapshot.data(); @@ -149,11 +167,21 @@ export async function buildKpiResponse(kpiSnapshot) { return { value, timestamp: timestamp.toDate() }; }); + const parentData = await getDocumentDataByRef(parent); + const parentOut = parentData + ? { + slug: parentData.slug, + name: parentData.name, + } + : null; + return { id: kpiSnapshot.id, currentValue, name, + description, type, + parent: parentOut, lastUpdated: latestMeasurement || null, updateFrequency: updateFrequency || null, isStale: isKPIStale(updateFrequency, latestMeasurement), diff --git a/public/openapi.yaml b/public/openapi.yaml index 0961c51f..3df1264f 100644 --- a/public/openapi.yaml +++ b/public/openapi.yaml @@ -365,12 +365,23 @@ definitions: type: string Kpi: properties: + id: + type: string currentValue: type: number name: type: string + description: + type: string type: type: string + parent: + type: object + properties: + slug: + type: string + name: + type: string created: type: string format: date-time