diff --git a/index.njk b/index.njk index d17c1c6..4f6c7a7 100644 --- a/index.njk +++ b/index.njk @@ -75,21 +75,35 @@
  • - {{ dependency.name }} - {% if dependency.version %} - v{{ dependency.version }} - {% endif %} - {% if dependency.tag %} - {{ dependency.tag }} - {% endif %} + {{ dependency.name }} + {% if dependency.version %} + v{{ dependency.version }} + {% endif %} + {% if dependency.tag %} + {{ dependency.tag }} + {% endif %} - {% if dependency.isOutdated %} - - - v{{ dependency.latestVersion }} + + {% if dependency.isOutdated %} + + + {{ dependency.changelog }} + v{{ dependency.latestVersion }} + + {% endif %} + {% if dependency.isEndOfLifeSoon %} + + + Support ends {{ dependency.endOfLifeRelative }} + + {% elif dependency.isOutOfSupport %} + + + Support ended {{ dependency.endOfLifeRelative }} + + {% endif %} - {% endif%}
  • {% endfor %} diff --git a/utils/index.js b/utils/index.js index 9be6d4f..870aa8e 100644 --- a/utils/index.js +++ b/utils/index.js @@ -1,5 +1,6 @@ import { readFile } from "fs/promises"; -import { getDependencyState } from "./endOfLifeDateApi/index.js"; +import { differenceInYears, formatDistance, startOfToday } from "date-fns"; +import { getDependencyEndOfLifeDate, getDependencyState } from "./endOfLifeDateApi/index.js"; /** * @typedef {Object} PersistedData @@ -15,14 +16,47 @@ import { getDependencyState } from "./endOfLifeDateApi/index.js"; * @property {string} org - The name of the Github organisation the repos belong to. */ +/** + * @typedef {"sky"|"amber"|"orange"|"red"} TailwindColor + */ + +/** + * @typedef {"bx-check-circle"|"bx-up-arrow-circle"|"bxs-up-arrow-circle"|"bxs-x-circle"} Boxicon + */ + /** * @typedef {Object} UiDependency * @property {string} name * @property {string?} version * @property {string?} tag - * @property {string} color + * @property {TailwindColor} color + * @property {Boxicon} icon + * @property {string?} latestVersion + * @property {Date?} endOfLifeDate + * @property {string?} endOfLifeRelative + * @property {boolean} isOutdated + * @property {boolean} isOutOfSupport + * @property {boolean} isEndOfLifeSoon */ +const stateColors = { + "upToDate": "sky", + "minorUpdateAvailable": "amber", + "majorUpdateAvailable": "orange", + "endOfLife": "red", +}; + +const defaultColor = "stone"; + +const stateIcons = { + "upToDate": "bx-check-circle", + "minorUpdateAvailable": "bx-up-arrow-circle", + "majorUpdateAvailable": "bxs-up-arrow-circle", + "endOfLife": "bxs-x-circle", +}; + +const defaultIcon = "bx-question-mark"; + /** * Maps the persisted dependency data from storage to a format suitable for the UI * @param {import("../model/Dependency").Dependency} dependency @@ -35,43 +69,15 @@ export const mapDependencyFromStorageToUi = (dependency, persistedLifetimes) => const state = lifetimes === undefined ? "unknown" : getDependencyState(dependency, lifetimes.lifetimes); const latestVersion = lifetimes?.lifetimes[0]?.latest; - let color; - switch (state) { - case "unknown": - color = "stone"; - break; - case "upToDate": - color = "sky"; - break; - case "minorUpdateAvailable": - color = "amber"; - break; - case "majorUpdateAvailable": - color = "orange"; - break; - case "endOfLife": - color = "red"; - break; - } - - let icon; - switch (state) { - case "unknown": - icon = "bx-question-mark"; - break; - case "upToDate": - icon = "bx-check-circle"; - break; - case "minorUpdateAvailable": - icon = "bx-up-arrow-circle"; - break; - case "majorUpdateAvailable": - icon = "bxs-up-arrow-circle"; - break; - case "endOfLife": - icon = "bxs-x-circle"; - break; - } + const color = stateColors[state] ?? defaultColor; + const icon = stateIcons[state] ?? defaultIcon; + + const endOfLifeDate = lifetimes && getDependencyEndOfLifeDate(dependency, lifetimes.lifetimes); + const endOfLifeRelative = endOfLifeDate && formatDistance(endOfLifeDate, startOfToday(), { addSuffix: true }); + + const isOutdated = state !== "upToDate" && state !== "unknown"; + const isOutOfSupport = state === "endOfLife"; + const isEndOfLifeSoon = !!endOfLifeDate && !isOutOfSupport && differenceInYears(endOfLifeDate, startOfToday()) < 1; return { name: dependency.name, @@ -79,10 +85,14 @@ export const mapDependencyFromStorageToUi = (dependency, persistedLifetimes) => tag: dependency.tag, color, icon, - isOutdated: state !== "upToDate" && state !== "unknown", latestVersion, - } -} + endOfLifeDate, + endOfLifeRelative, + isOutdated, + isOutOfSupport, + isEndOfLifeSoon, + }; +}; /** * Maps the persisted repo data from storage to a format suitable for the UI