From 628d9eed93f3b2c3a85204a16f122d21c4e9936d Mon Sep 17 00:00:00 2001 From: Jeffrey Yasskin Date: Wed, 6 Mar 2024 15:57:46 -0800 Subject: [PATCH] Add "last updated at" times to the index and repo pages. Fixes #31. --- frontend/src/components/local-time.ts | 36 +++++++++++++++++++++++++++ frontend/src/lib/formatTime.ts | 12 +++++++++ frontend/src/pages/[org]/[repo].astro | 13 ++++++++++ frontend/src/pages/index.astro | 33 ++++++++++++++++++++++-- 4 files changed, 92 insertions(+), 2 deletions(-) create mode 100644 frontend/src/components/local-time.ts create mode 100644 frontend/src/lib/formatTime.ts diff --git a/frontend/src/components/local-time.ts b/frontend/src/components/local-time.ts new file mode 100644 index 0000000..516ef06 --- /dev/null +++ b/frontend/src/components/local-time.ts @@ -0,0 +1,36 @@ +import { localFormatter } from '@lib/formatTime.js'; +import { LitElement, html, type PropertyDeclaration } from 'lit'; +import { customElement, property } from 'lit/decorators.js'; + +const dateProperty: PropertyDeclaration = { + type: Object, + converter(date: string | null) { + const result = new Date(date ?? ""); + if (isNaN(result.getTime())) return null; + return result; + }, +} + +@customElement('local-time') +export class LocalTime extends LitElement { + // The single time represented by this element. + @property(dateProperty) + datetime: Date | null = null; + + // The range of time represented by this element. + @property(dateProperty) + from: Date | null = null + @property(dateProperty) + to: Date | null = null + + render() { + if (this.datetime) { + return html`${localFormatter.format(this.datetime)}`; + } else if (this.from && this.to) { + return html`${localFormatter.formatRange(this.from, this.to)}`; + } else { + console.error(this, "should have 'datetime' or 'from' and 'to' attributes."); + return html``; + } + } +} diff --git a/frontend/src/lib/formatTime.ts b/frontend/src/lib/formatTime.ts new file mode 100644 index 0000000..14e4399 --- /dev/null +++ b/frontend/src/lib/formatTime.ts @@ -0,0 +1,12 @@ +// For use in the static site generator. +export const englishUtcFormatter = new Intl.DateTimeFormat("en-US", { + dateStyle: "medium", + timeStyle: "long", + timeZone: "UTC", +}); + +// For use in client-side code. +export const localFormatter = new Intl.DateTimeFormat(undefined, { + dateStyle: "medium", + timeStyle: "long" +}); diff --git a/frontend/src/pages/[org]/[repo].astro b/frontend/src/pages/[org]/[repo].astro index f9b2664..07cc224 100644 --- a/frontend/src/pages/[org]/[repo].astro +++ b/frontend/src/pages/[org]/[repo].astro @@ -3,6 +3,7 @@ import Duration from "@components/Duration.astro"; import GhLabel from "@components/GhLabel.astro"; import Issue from "@components/Issue.astro"; import Layout from "@layouts/Layout.astro"; +import { englishUtcFormatter } from "@lib/formatTime.js"; import { IssueSummary } from "@lib/repo-summaries"; import { agendaLengthSLO, @@ -56,6 +57,10 @@ untriaged.push(...triageViolations); untriaged.sort(cmpByTimeUsed); --- + +

+

+ Last updated { + englishUtcFormatter.format(new Date(details.cachedAt)) + }. +

+ { details.labelsPresent ? null : (

diff --git a/frontend/src/pages/index.astro b/frontend/src/pages/index.astro index 9adef9b..a95c25e 100644 --- a/frontend/src/pages/index.astro +++ b/frontend/src/pages/index.astro @@ -1,13 +1,28 @@ --- import GhLabel from "@components/GhLabel.astro"; +import { englishUtcFormatter } from "@lib/formatTime"; import { IssueSummary } from "@lib/repo-summaries"; import { agendaLengthSLO, groupBySlo } from "@lib/slo"; import * as ghLabels from "@lib/triage-labels"; import { getCollection } from "astro:content"; +import assert from "node:assert"; import Layout from "../layouts/Layout.astro"; const repos = await getCollection("github"); +let oldestCache: Date; +let newestCache = (oldestCache = new Date(repos[0].data.cachedAt)); +for (const repo of repos) { + const repoCachedAt = new Date(repo.data.cachedAt); + if (repoCachedAt < oldestCache) { + oldestCache = repoCachedAt; + } + if (repoCachedAt > newestCache) { + newestCache = repoCachedAt; + } +} +assert(oldestCache <= newestCache); + let totalTriageViolations = 0; let totalUrgentViolations = 0; let totalSoonViolations = 0; @@ -153,10 +168,24 @@ function compareByKey( repoSummaries.sort(compareByKey); --- + +

Browser Spec Maintenance Status

+

+ Last updated { + englishUtcFormatter.formatRange(oldestCache, newestCache) + }. +

+

Across all browser specs, we have:

    { @@ -193,8 +222,8 @@ repoSummaries.sort(compareByKey); { totalGroupsOverAgendaLimit > 0 ? (
  • - {totalGroupsOverAgendaLimit} group(s) with too many issues - on the agenda + {totalGroupsOverAgendaLimit} group(s) with too many + issues on the agenda
  • ) : null }