mirror of
https://github.com/fosrl/pangolin.git
synced 2025-08-16 07:28:06 +02:00
add newt version update available to table
This commit is contained in:
parent
4ffdd6f74f
commit
1e5141c27c
4 changed files with 98 additions and 7 deletions
|
@ -1145,5 +1145,7 @@
|
|||
"settingsErrorUpdate": "Failed to update settings",
|
||||
"settingsErrorUpdateDescription": "An error occurred while updating settings",
|
||||
"sidebarCollapse": "Collapse",
|
||||
"sidebarExpand": "Expand"
|
||||
"sidebarExpand": "Expand",
|
||||
"newtUpdateAvailable": "Update Available",
|
||||
"newtUpdateAvailableInfo": "A new version of Newt is available. Please update to the latest version for the best experience."
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { db } from "@server/db";
|
||||
import { db, newts } from "@server/db";
|
||||
import { orgs, roleSites, sites, userSites } from "@server/db";
|
||||
import logger from "@server/logger";
|
||||
import HttpCode from "@server/types/HttpCode";
|
||||
|
@ -9,6 +9,42 @@ import createHttpError from "http-errors";
|
|||
import { z } from "zod";
|
||||
import { fromError } from "zod-validation-error";
|
||||
import { OpenAPITags, registry } from "@server/openApi";
|
||||
import NodeCache from "node-cache";
|
||||
import semver from "semver";
|
||||
|
||||
const newtVersionCache = new NodeCache({ stdTTL: 3600 }); // 1 hours in seconds
|
||||
|
||||
async function getLatestNewtVersion(): Promise<string | null> {
|
||||
try {
|
||||
const cachedVersion = newtVersionCache.get<string>("latestNewtVersion");
|
||||
if (cachedVersion) {
|
||||
return cachedVersion;
|
||||
}
|
||||
|
||||
const response = await fetch(
|
||||
"https://api.github.com/repos/fosrl/newt/tags"
|
||||
);
|
||||
if (!response.ok) {
|
||||
logger.warn("Failed to fetch latest Newt version from GitHub");
|
||||
return null;
|
||||
}
|
||||
|
||||
const tags = await response.json();
|
||||
if (!Array.isArray(tags) || tags.length === 0) {
|
||||
logger.warn("No tags found for Newt repository");
|
||||
return null;
|
||||
}
|
||||
|
||||
const latestVersion = tags[0].name;
|
||||
|
||||
newtVersionCache.set("latestNewtVersion", latestVersion);
|
||||
|
||||
return latestVersion;
|
||||
} catch (error) {
|
||||
logger.error("Error fetching latest Newt version:", error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
const listSitesParamsSchema = z
|
||||
.object({
|
||||
|
@ -45,9 +81,11 @@ function querySites(orgId: string, accessibleSiteIds: number[]) {
|
|||
type: sites.type,
|
||||
online: sites.online,
|
||||
address: sites.address,
|
||||
newtVersion: newts.version
|
||||
})
|
||||
.from(sites)
|
||||
.leftJoin(orgs, eq(sites.orgId, orgs.orgId))
|
||||
.leftJoin(newts, eq(newts.siteId, sites.siteId))
|
||||
.where(
|
||||
and(
|
||||
inArray(sites.siteId, accessibleSiteIds),
|
||||
|
@ -56,8 +94,12 @@ function querySites(orgId: string, accessibleSiteIds: number[]) {
|
|||
);
|
||||
}
|
||||
|
||||
type SiteWithUpdateAvailable = Awaited<ReturnType<typeof querySites>>[0] & {
|
||||
newtUpdateAvailable?: boolean;
|
||||
};
|
||||
|
||||
export type ListSitesResponse = {
|
||||
sites: Awaited<ReturnType<typeof querySites>>;
|
||||
sites: SiteWithUpdateAvailable[];
|
||||
pagination: { total: number; limit: number; offset: number };
|
||||
};
|
||||
|
||||
|
@ -148,9 +190,36 @@ export async function listSites(
|
|||
const totalCountResult = await countQuery;
|
||||
const totalCount = totalCountResult[0].count;
|
||||
|
||||
const latestNewtVersion = await getLatestNewtVersion();
|
||||
|
||||
const sitesWithUpdates: SiteWithUpdateAvailable[] = sitesList.map(
|
||||
(site) => {
|
||||
const siteWithUpdate: SiteWithUpdateAvailable = { ...site };
|
||||
|
||||
if (
|
||||
site.type === "newt" &&
|
||||
site.newtVersion &&
|
||||
latestNewtVersion
|
||||
) {
|
||||
try {
|
||||
siteWithUpdate.newtUpdateAvailable = semver.lt(
|
||||
site.newtVersion,
|
||||
latestNewtVersion
|
||||
);
|
||||
} catch (error) {
|
||||
siteWithUpdate.newtUpdateAvailable = false;
|
||||
}
|
||||
} else {
|
||||
siteWithUpdate.newtUpdateAvailable = false;
|
||||
}
|
||||
|
||||
return siteWithUpdate;
|
||||
}
|
||||
);
|
||||
|
||||
return response<ListSitesResponse>(res, {
|
||||
data: {
|
||||
sites: sitesList,
|
||||
sites: sitesWithUpdates,
|
||||
pagination: {
|
||||
total: totalCount,
|
||||
limit,
|
||||
|
|
|
@ -29,6 +29,8 @@ import { useEnvContext } from "@app/hooks/useEnvContext";
|
|||
import CreateSiteFormModal from "./CreateSiteModal";
|
||||
import { useTranslations } from "next-intl";
|
||||
import { parseDataSize } from "@app/lib/dataSize";
|
||||
import { Badge } from "@app/components/ui/badge";
|
||||
import { InfoPopup } from "@app/components/ui/info-popup";
|
||||
|
||||
export type SiteRow = {
|
||||
id: number;
|
||||
|
@ -38,6 +40,8 @@ export type SiteRow = {
|
|||
mbOut: string;
|
||||
orgId: string;
|
||||
type: "newt" | "wireguard";
|
||||
newtVersion?: string;
|
||||
newtUpdateAvailable?: boolean;
|
||||
online: boolean;
|
||||
address?: string;
|
||||
};
|
||||
|
@ -238,8 +242,22 @@ export default function SitesTable({ sites, orgId }: SitesTableProps) {
|
|||
|
||||
if (originalRow.type === "newt") {
|
||||
return (
|
||||
<div className="flex items-center space-x-1">
|
||||
<Badge variant="secondary">
|
||||
<div className="flex items-center space-x-2">
|
||||
<span>Newt</span>
|
||||
{originalRow.newtVersion && (
|
||||
<span className="text-xs text-gray-500">
|
||||
v{originalRow.newtVersion}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
</Badge>
|
||||
{originalRow.newtUpdateAvailable && (
|
||||
<InfoPopup
|
||||
info={t("newtUpdateAvailableInfo")}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -49,7 +49,9 @@ export default async function SitesPage(props: SitesPageProps) {
|
|||
mbOut: formatSize(site.megabytesOut || 0, site.type),
|
||||
orgId: params.orgId,
|
||||
type: site.type as any,
|
||||
online: site.online
|
||||
online: site.online,
|
||||
newtVersion: site.newtVersion || undefined,
|
||||
newtUpdateAvailable: site.newtUpdateAvailable || false,
|
||||
};
|
||||
});
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue