diff --git a/src/components/Layout.tsx b/src/components/Layout.tsx index f1300123..a93bae95 100755 --- a/src/components/Layout.tsx +++ b/src/components/Layout.tsx @@ -48,6 +48,7 @@ import Link from 'next/link'; import { useRouter } from 'next/router'; import { useState } from 'react'; import ConfigProvider from './ConfigProvider'; +import VersionBadge from './VersionBadge'; type NavLinks = { label: string; @@ -357,23 +358,27 @@ export default function Layout({ children, config }: { children: React.ReactNode } })} - +
+ - - - {config.website.externalLinks.map(({ name, url }, i) => ( - } - variant='light' - component={Link} - href={url} - target='_blank' - /> - ))} - - + + + + + {config.website.externalLinks.map(({ name, url }, i) => ( + } + variant='light' + component={Link} + href={url} + target='_blank' + /> + ))} + + +
diff --git a/src/components/VersionBadge.tsx b/src/components/VersionBadge.tsx new file mode 100644 index 00000000..14948e0c --- /dev/null +++ b/src/components/VersionBadge.tsx @@ -0,0 +1,173 @@ +import useVersion from '@/lib/hooks/useVersion'; +import { + Anchor, + Badge, + Button, + Flex, + Indicator, + Modal, + Paper, + Stack, + Text, + Title, + Tooltip, +} from '@mantine/core'; +import { useDisclosure } from '@mantine/hooks'; + +function DataDisplay({ items }: { items: { label: string; value: string; href?: string }[] }) { + return ( + + + {items.map((item, index) => ( + + + {item.label} + + + {item.href ? ( + + {item.value} + + ) : ( + {item.value} + )} + + ))} + + + ); +} + +function VersionButton({ text, children, href }: { href: string; text: string; children: React.ReactNode }) { + return ( + + ); +} + +export default function VersionBadge() { + const { version, isLoading } = useVersion(); + const [opened, { open, close }] = useDisclosure(false); + + if (isLoading) return null; + if (!version) return null; + + return ( + <> + + {version.isLatest && Running the latest version of Zipline.} + {version.isUpstream && ( + + You are running an unstable version of Zipline. Upstream versions are not fully tested and + may contain bugs. + + )} + {!version.isLatest && !version.isUpstream && version.isRelease && ( + + You are running an outdated version of Zipline. It is recommended to update to the{' '} + latest version. + + )} + + + + Current Version + + + + + {!version.isLatest && version.isUpstream && ( + <> + + Latest Commit Available + + + This is only visible when running an upstream version. + + + + + )} + + {!version.isLatest && version.isRelease && ( + <> + + {version.latest?.tag} is available + + + + {version.latest?.tag} + + + + {version.latest?.tag} + + + )} + + + + + {version.version?.tag} + + + + ); +} diff --git a/src/lib/hooks/useVersion.ts b/src/lib/hooks/useVersion.ts new file mode 100755 index 00000000..4eac3a8d --- /dev/null +++ b/src/lib/hooks/useVersion.ts @@ -0,0 +1,23 @@ +import useSWR from 'swr'; +import { Response } from '../api/response'; +const f = async () => { + const res = await fetch('/api/version', { + cache: 'force-cache', + }); + if (!res.ok) throw new Error('Failed to fetch version'); + const r = await res.json(); + return r; +}; + +export default function useVersion() { + const { isLoading, data } = useSWR('/api/version', f, { + refreshInterval: undefined, + revalidateOnFocus: false, + revalidateIfStale: false, + refreshWhenOffline: false, + refreshWhenHidden: false, + revalidateOnReconnect: false, + }); + + return { version: data?.data, isLoading }; +} diff --git a/src/server/routes/api/version.ts b/src/server/routes/api/version.ts index 9650d8b5..bdcd5c57 100755 --- a/src/server/routes/api/version.ts +++ b/src/server/routes/api/version.ts @@ -3,16 +3,49 @@ import fastifyPlugin from 'fastify-plugin'; import { getVersion } from '@/lib/version'; export type ApiVersionResponse = { - version: string; + details: ReturnType; + data: VersionAPI; }; +interface VersionAPI { + isUpstream?: boolean; + isRelease?: boolean; + isLatest?: boolean; + version?: { + tag: string; + sha: string; + url: string; + }; + latest?: { + tag: string; + url: string; + commit?: { + sha: string; + url: string; + pull: boolean; + }; + }; +} + export const PATH = '/api/version'; export default fastifyPlugin( (server, _, done) => { server.get(PATH, { preHandler: [userMiddleware] }, async (_, res) => { const details = getVersion(); + const params = new URLSearchParams([['details', JSON.stringify(details)]]); - return res.send(details); + const resp = await fetch(`https://zipline-version.diced.sh/?${params.toString()}`); + + if (!resp.ok) { + return res.internalServerError('failed to fetch version details: ' + await resp.text()); + } + + const data: VersionAPI = await resp.json(); + + return res.send({ + data, + details, + }); }); done();