Make documentation standalone and generalize examples
This commit is contained in:
+8
-1
@@ -1 +1,8 @@
|
||||
# Fluksio Frontend
|
||||
# Fluksio frontend
|
||||
|
||||
React dashboard for the flow engine. From the repository root, run
|
||||
`make install`, then `make dev-backend` and `make dev-frontend` in separate
|
||||
terminals.
|
||||
|
||||
See [Development](../development.md) for Docker, tests and lint, and
|
||||
[the design reference](../DESIGN-GUIDELINES.md) before changing the UI.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* The house panels, at the size of the screen they hang on.
|
||||
* Capture dashboards at their target screen size.
|
||||
*
|
||||
* `/view/{name}` is the wall-panel route: no sidebar, no editor. Shooting it
|
||||
* at exactly the panel's pixels is the only way to see whether a tile fell off
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
/**
|
||||
* Visual verification for the integrated local stack (root `make verify`).
|
||||
* Capture the app at desktop and phone sizes in both themes.
|
||||
*
|
||||
* Logs into the dashboard with the bootstrap superuser and captures the app
|
||||
* shell plus the website hero in both themes. This is the standard "did the
|
||||
* change actually work" gate — look at the PNGs, do not just trust the build.
|
||||
* shell. Set WEBSITE_URL to also capture another site's landing page.
|
||||
*
|
||||
* Env (all set by the root Makefile):
|
||||
* Env:
|
||||
* APP_URL, WEBSITE_URL, FIRST_SUPERUSER, FIRST_SUPERUSER_PASSWORD
|
||||
* SCREENSHOT_DIR (default: ./screenshots)
|
||||
*/
|
||||
@@ -13,14 +12,14 @@ import { mkdir } from "node:fs/promises"
|
||||
import { chromium } from "@playwright/test"
|
||||
|
||||
const APP_URL = process.env.APP_URL || "http://app.localhost"
|
||||
const WEBSITE_URL = process.env.WEBSITE_URL || "http://localhost"
|
||||
const WEBSITE_URL = process.env.WEBSITE_URL
|
||||
const EMAIL = process.env.FIRST_SUPERUSER
|
||||
const PASSWORD = process.env.FIRST_SUPERUSER_PASSWORD
|
||||
const OUT = process.env.SCREENSHOT_DIR || "screenshots"
|
||||
|
||||
if (!EMAIL || !PASSWORD) {
|
||||
console.error(
|
||||
"FIRST_SUPERUSER / FIRST_SUPERUSER_PASSWORD are unset — run from the root `make verify`.",
|
||||
"Set FIRST_SUPERUSER and FIRST_SUPERUSER_PASSWORD before running this script.",
|
||||
)
|
||||
process.exit(1)
|
||||
}
|
||||
@@ -50,8 +49,8 @@ async function withTheme(browser, theme, viewport) {
|
||||
}
|
||||
|
||||
// Chromium pins *.localhost to loopback (RFC 6761), so /etc/hosts cannot point
|
||||
// it at Traefik. The containerised run (root `make verify-docker`) passes the
|
||||
// mapping through here instead; empty on a host run.
|
||||
// it at Traefik. A containerised run can pass the mapping through
|
||||
// HOST_RESOLVER_RULES instead.
|
||||
const RESOLVER = process.env.HOST_RESOLVER_RULES
|
||||
const browser = await chromium.launch(
|
||||
RESOLVER ? { args: [`--host-resolver-rules=${RESOLVER}`] } : {},
|
||||
@@ -64,11 +63,12 @@ for (const theme of ["light", "dark"]) {
|
||||
const context = await withTheme(browser, theme, viewport)
|
||||
const page = await context.newPage()
|
||||
|
||||
await page.goto(`${WEBSITE_URL}/`, { waitUntil: "networkidle" })
|
||||
// networkidle fires before the staggered entrance animations settle, which
|
||||
// would capture buttons mid-fade and make contrast look broken.
|
||||
await page.waitForTimeout(1500)
|
||||
await page.screenshot({ path: `${dir}/website-hero.png` })
|
||||
if (WEBSITE_URL) {
|
||||
await page.goto(`${WEBSITE_URL}/`, { waitUntil: "networkidle" })
|
||||
// Wait for entrance animations before capturing the page.
|
||||
await page.waitForTimeout(1500)
|
||||
await page.screenshot({ path: `${dir}/website-hero.png` })
|
||||
}
|
||||
|
||||
await page.goto(`${APP_URL}/login`, { waitUntil: "networkidle" })
|
||||
await page.screenshot({ path: `${dir}/app-login.png` })
|
||||
@@ -223,8 +223,8 @@ async function captureDevices(page, dir) {
|
||||
* A media tile drawing what a camera published: the Demo's Media screen,
|
||||
* whose house is drawn by a node as heat.
|
||||
*
|
||||
* Skipped unless the Demo is seeded (root `make seed-hosted-demo`), since it
|
||||
* is the one shot that needs a source of frames. The bytes arrive as
|
||||
* Skipped unless the instance has the Demo's Media dashboard and frame source.
|
||||
* The bytes arrive as
|
||||
* a blob — pushed down the socket, or fetched with the session's credential,
|
||||
* which no `img` could carry on its own — so a `blob:` source is the proof the
|
||||
* whole path ran rather than that a picture is merely present.
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { SiGitea } from "react-icons/si"
|
||||
import { BookOpen } from "lucide-react"
|
||||
|
||||
const socialLinks = [
|
||||
{
|
||||
icon: SiGitea,
|
||||
href: "https://git.stroblme.de/Fluksio",
|
||||
label: "Gitea",
|
||||
icon: BookOpen,
|
||||
href: "https://docs.fluksio.com",
|
||||
label: "Documentation",
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
* Raised from anywhere through `notify()` in `lib/notificationStore`, which is
|
||||
* where the semantics live; this only draws them.
|
||||
*
|
||||
* Byte-identical with the portal's copy — see DESIGN-GUIDELINES.md § Sync rule.
|
||||
* See DESIGN-GUIDELINES.md at the repository root for notification styling.
|
||||
*/
|
||||
|
||||
import { CircleAlert, CircleCheck, Info, TriangleAlert, X } from "lucide-react"
|
||||
|
||||
@@ -2,10 +2,8 @@ import Avatar from "boring-avatars"
|
||||
|
||||
import useAuth from "@/hooks/useAuth"
|
||||
|
||||
// Shared avatar identity config, kept in step with the portal's copy
|
||||
// (index/frontend/src/components/Common/UserAvatar.tsx) so one account renders
|
||||
// the same face in both shells. The seed is the email, the only stable per-user
|
||||
// id both sides hold. These are decorative identity colours, not design tokens.
|
||||
// Email provides a stable seed for each account's avatar.
|
||||
// These are decorative identity colours, not design tokens.
|
||||
export const AVATAR_VARIANT = "marble" as const
|
||||
export const AVATAR_COLORS = [
|
||||
"#EAAC0F",
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
/**
|
||||
* How each look moves.
|
||||
*
|
||||
* `lib/motion.ts` is the app's own set and is duplicated verbatim in the
|
||||
* website repo (`make design-check` holds the two byte-identical), so a
|
||||
* dashboard that moves differently needs its own table rather than an entry
|
||||
* there. The two looks are meant to *feel* different: material settles quickly
|
||||
* Dashboard motion has its own presets, separate from the app shell's
|
||||
* `lib/motion.ts`. The two looks are meant to *feel* different: material settles quickly
|
||||
* and squarely, glass carries a little overshoot.
|
||||
*
|
||||
* Physics only. What animates is each set's business; this is how it moves
|
||||
|
||||
@@ -10,9 +10,8 @@
|
||||
*
|
||||
* The result is written onto the canvas as the plain token variables the app
|
||||
* already themes with (`--background`, `--card`, `--primary`, …), which is the
|
||||
* same mechanism `.theme-light` and `.theme-dark` use on a subtree. Nothing here touches
|
||||
* `index.css`: that file's token blocks are byte-identical with the website's
|
||||
* and `make design-check` holds them there.
|
||||
* same mechanism `.theme-light` and `.theme-dark` use on a subtree. Palette
|
||||
* overrides leave the app's base tokens in `index.css` unchanged.
|
||||
*
|
||||
* Every value written out is a literal hex. uPlot draws on a canvas, and a
|
||||
* canvas takes neither `color-mix()` nor an unresolved custom property, so a
|
||||
|
||||
@@ -9,12 +9,8 @@
|
||||
));
|
||||
|
||||
/*
|
||||
* Self-hosted font, duplicated verbatim across the fluksio and website repos (a
|
||||
* sync point like `lib/motion.ts`; see the root DESIGN-GUIDELINES.md,
|
||||
* Typography). Kept OUT of the byte-identical `@theme inline` / `:root` /
|
||||
* `.theme-dark` blocks. Inter is used for both body (set on `body` in
|
||||
* `@layer base`) and the display face applied via the `.font-display` class
|
||||
* below.
|
||||
* Self-hosted Inter for body text and the `.font-display` class.
|
||||
* See DESIGN-GUIDELINES.md → Typography.
|
||||
*/
|
||||
@font-face {
|
||||
font-family: "Inter";
|
||||
@@ -95,8 +91,7 @@
|
||||
*
|
||||
* `--primary` is #4a7189, not the identity blue #59849b: the latter measures
|
||||
* 4.04:1 against white, below AA for the label sitting on a bg-primary fill.
|
||||
* #59849b remains the wordmark colour (index/src/assets/fluksio-*.svg). See the root
|
||||
* DESIGN-GUIDELINES.md → Colour tokens.
|
||||
* #59849b remains the wordmark colour. See DESIGN-GUIDELINES.md → Colour tokens.
|
||||
*
|
||||
* `--primary-nested` is that same hue and saturation a few steps deeper, for
|
||||
* a reading drawn inside a `--primary` fill — the bar widget's stacked
|
||||
|
||||
@@ -5,9 +5,7 @@
|
||||
* across the app. Mirrors the `--ease-*` / `--duration-*` timing tokens defined
|
||||
* in `index.css`, so CSS transitions and JS animations stay in sync.
|
||||
*
|
||||
* This file is duplicated verbatim in `app` and `index` (the shadcn model,
|
||||
* see ../../DESIGN.md / the root DESIGN-GUIDELINES.md). Keep the two copies
|
||||
* identical; `make design-check` at the workspace root verifies it.
|
||||
* See DESIGN-GUIDELINES.md at the repository root for the motion rules.
|
||||
*
|
||||
* Reduced motion: wrap each app root in `<MotionConfig reducedMotion="user">` so
|
||||
* transform/layout animations are disabled automatically when the OS requests it.
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
* Same hand-rolled external store as `connectionStore`, for the same reason: a
|
||||
* `useSyncExternalStore` snapshot is the whole requirement.
|
||||
*
|
||||
* Byte-identical with the portal's copy — see DESIGN-GUIDELINES.md § Sync rule.
|
||||
* See DESIGN-GUIDELINES.md at the repository root for notification styling.
|
||||
*/
|
||||
|
||||
export type NotificationSeverity = "error" | "warning" | "info" | "success"
|
||||
|
||||
@@ -57,7 +57,7 @@ test.beforeAll(async ({ browser }) => {
|
||||
await api(page, `/messages/${flowName}.label`, {
|
||||
method: "POST",
|
||||
data: {
|
||||
value: "ubuntu-gpu-node-01.lab.internal (numpy 2.5.2, cuda 12.4)",
|
||||
value: "research-gpu-worker.example.test (numpy 2.5.2, cuda 12.4)",
|
||||
},
|
||||
})
|
||||
await page.close()
|
||||
|
||||
Reference in New Issue
Block a user