From a351040b0dba3adc9eebd68091b5fde0b62d0188 Mon Sep 17 00:00:00 2001 From: Matt Yoder Date: Mon, 28 Oct 2024 14:34:43 -0400 Subject: [PATCH] feat(resource-group-events): use announcement data from the Operations API --- src/resource-group-events.jsx | 53 ++++++++++++++++++----------- src/resource-home.jsx | 1 - src/utils.jsx | 63 ++++++++++++++++++++++++----------- 3 files changed, 78 insertions(+), 39 deletions(-) diff --git a/src/resource-group-events.jsx b/src/resource-group-events.jsx index cf0dda6..216a4f5 100644 --- a/src/resource-group-events.jsx +++ b/src/resource-group-events.jsx @@ -1,12 +1,17 @@ -import { useJSON } from "./utils"; +import { useJSON, useResourceGroupJSON, useTransform } from "./utils"; import Alert from "./alert"; import ResourceGroupEvent from "./resource-group-event"; import Section from "./section"; export default function ResourceGroupEvents({ baseUri, infoGroupId }) { - const announcementData = useJSON( - `${baseUri}/api/resource-groups/${infoGroupId}/announcements.json`, + const groupData = useResourceGroupJSON(infoGroupId); + const currentAnnouncementData = useJSON( + "https://operations-api.access-ci.org/wh2/news/v1/affiliation/access-ci.org/current_outages/", + null + ); + const futureAnnouncementData = useJSON( + "https://operations-api.access-ci.org/wh2/news/v1/affiliation/access-ci.org/future_outages/", null ); const eventData = useJSON( @@ -14,24 +19,34 @@ export default function ResourceGroupEvents({ baseUri, infoGroupId }) { null, { corsProxy: true } ); - const filteredEvents = - eventData && !eventData.error - ? eventData.filter((event) => new Date(event.date__start) >= new Date()) - : []; - if (!announcementData && !filteredEvents.length) return; + const filteredAnnouncements = useTransform( + [groupData, currentAnnouncementData, futureAnnouncementData], + (groups, current, future) => + [...current.results, ...future.results].filter((ann) => + ann.AffectedResources.some((res) => + groups.infoResourceids.includes(res.ResourceID) + ) + ), + [] + ); + const filteredEvents = useTransform( + [eventData], + (events) => + events.filter((event) => new Date(event.date__start) >= new Date()), + [] + ); + + if (!filteredAnnouncements.length && !filteredEvents.length) return; return (
- {announcementData && - announcementData.announcements.map( - ({ description, announcementUri }) => ( - - {description}{" "} - {announcementUri ? ( - Learn more. - ) : null} - - ) - )} + {filteredAnnouncements.map(({ Subject: subject, Content: content }) => ( + + {subject}{" "} + + Learn more. + + + ))} {filteredEvents.map((event) => ResourceGroupEvent(event))}
); diff --git a/src/resource-home.jsx b/src/resource-home.jsx index 755b1ee..200db61 100644 --- a/src/resource-home.jsx +++ b/src/resource-home.jsx @@ -37,7 +37,6 @@ const linkGroupData = ({ groups: resourceGroups }, { results: resources }) => { for (let resourceGroup of resourceGroups) { resourceGroup.infoGroupId = resourceGroup.infoGroupid; - delete resourceGroup.infoGroupid; resourceGroup.tags = []; resourceGroup.tagIds = []; for (let infoResourceId of resourceGroup.infoResourceids) { diff --git a/src/utils.jsx b/src/utils.jsx index 07abd61..5546daa 100644 --- a/src/utils.jsx +++ b/src/utils.jsx @@ -1,5 +1,5 @@ import { render } from "preact"; -import { useEffect, useState } from "preact/hooks"; +import { useEffect, useMemo, useState } from "preact/hooks"; export const getMode = (breakpoint = 900) => document.body.clientWidth >= breakpoint ? "desktop" : "mobile"; @@ -31,33 +31,58 @@ export const useJSON = ( ) => { const [value, setValue] = useState(defaultValue); useEffect(() => { - if (uri) + if (uri) { if (cache && jsonCache[uri]) { setValue(jsonCache[uri]); return; } - (async () => { - const res = await fetch( - corsProxy ? `https://corsproxy.io/?${encodeURIComponent(uri)}` : uri - ); - if (res.status < 200 || res.status > 299) { - setValue({ error: { status: res.status } }); - } else { - let data; - try { - data = await res.json(); - } catch (error) { - data = { error: { message: error } }; - } finally { - setValue(data); - if (cache) jsonCache[uri] = data; + (async () => { + const res = await fetch( + corsProxy ? `https://corsproxy.io/?${encodeURIComponent(uri)}` : uri + ); + if (res.status < 200 || res.status > 299) { + setValue({ error: { status: res.status } }); + } else { + let data; + try { + data = await res.json(); + } catch (error) { + data = { error: { message: error } }; + } finally { + setValue(data); + if (cache) jsonCache[uri] = data; + } } - } - })(); + })(); + } }, [uri]); return value; }; +export const useResourceGroupJSON = (infoGroupId, defaultValue = null) => { + // TODO: Replace this with the individual group endpoint once it is available. + const groupsData = useJSON( + "/access-ci-ui/api/resource-groups.json", + defaultValue + ); + return groupsData + ? groupsData.groups.find((group) => group.infoGroupid == infoGroupId) || + defaultValue + : defaultValue; +}; + +export const useTransform = ( + responseArray, + transformFunction, + defaultValue = null +) => { + return useMemo(() => { + for (let response of responseArray) + if (!response || response.error) return defaultValue; + return transformFunction.apply(null, responseArray); + }, responseArray); +}; + export const sortOn = (prop) => (a, b) => a[prop] < b[prop] ? -1 : 1; export const extractHref = (html) => {