Shad cb9291b225
Some checks failed
build-and-publish / test (push) Has been cancelled
build-and-publish / image (push) Has been cancelled
feat: real backend mutations + Studio + Settings + live API console
Massive overhaul that turns the demo from presenter-mode into a
fully-functional FlowMaster operator surface.

NEW: real backend mutations
- api.executeAction(txId, actionId, actor, values) → POST /api/runtime/transactions/{tx}/actions/{actionId}
- api.startTransaction(defKey, business_subject) → POST /api/runtime/transactions
- api.createProcess(payload) → POST /api/ea2/flow
- store.executeAction / startInstance with toast feedback + auto-refresh
- Inspector Overview action buttons fire real backend calls (Submit/Save Draft/etc)
- LeftRail Confirm/Reject buttons fire real backend calls
- LeftRail 'Start new instance' button starts a real tx for live procurement
- CommandBar 'Real actions' group with 'Start new instance' + 'Execute action on headline tx'

NEW: Process Studio (src/scenes/Studio.tsx)
- in-UI process designer: name + display + hub + description + node list + edge list
- live JSON preview of the EA2 payload
- Publish button calls api.createProcess against demo.flow-master.ai
- Validates locally before publishing
- Auto-refreshes scenarios after publish so the new process shows up

NEW: Settings (src/scenes/Settings.tsx)
- Identity: sign in as any email (loginAs), see actor + display name
- Quick-user buttons for common demo identities
- Backend URL + clear-token diagnostic
- Polling cadence (2-120s)
- Dark/light theme toggle (CSS data-theme attribute)
- Show-console default toggle
- All persisted to localStorage (LS_KEY = fm.mc.prefs.v1)

NEW: Live API console (src/components/Console.tsx)
- Right-side drawer triggered from topbar
- Every fetch (GET/POST/etc) streams in real time with status + duration
- Click any entry to expand request + response JSON
- Filter: all / writes / errors
- Replaces the old guided-tour overlay entirely

NEW: live polling
- store.startPolling()/stopPolling() with setInterval guarded for SSR
- Auto-refresh while in LIVE mode at configurable cadence

REMOVED: Tour.tsx, all startTour() store actions and tour references
- Landing CTA now reads 'Enter Mission Control' / 'Design a process' / 'Open live console'

ALSO:
- api.ts: instrumentedFetch with observer pattern → store.apiLog
- Topbar: user identity chip linking to Settings, Console toggle with badge
- Light theme: minimal CSS data-theme override (text + surfaces only)
- localStorage persistence for mode, scenarioId, email, theme, pollEverySec, consoleOpen, recents
- 24/24 vitest, smoke quick run shows 0 console errors + 7 API calls captured

Confidence: high
Scope-risk: broad (~14 files)
Not-tested: actual end-to-end backend mutation roundtrip (requires LIVE + sign-in; structure proven via probe scripts)
2026-06-14 01:19:36 +04:00

44 lines
1.7 KiB
JavaScript

import { chromium } from "playwright";
const b = await chromium.launch({ headless: true });
const p = await b.newPage({ viewport: { width: 1440, height: 900 } });
const errors = [];
p.on("pageerror", e => errors.push(`pageerror ${e.message}`));
p.on("console", m => { if (m.type() === "error") errors.push(`console.error ${m.text().slice(0, 200)}`); });
await p.goto("http://127.0.0.1:5173", { waitUntil: "networkidle" });
await p.locator(".sc-card").first().click();
await p.waitForSelector(".mc"); await p.waitForTimeout(400);
// Open console first
await p.locator(".link-btn", { hasText: "Console" }).first().click();
await p.waitForSelector(".console");
// Toggle live
await p.locator(".mode-toggle").first().click();
await p.waitForTimeout(6000); // let all calls land
const callCount = await p.locator(".call").count();
console.log("api calls logged:", callCount);
const firstCall = await p.locator(".call-head").first();
if (await firstCall.count()) {
console.log("first call:", await firstCall.innerText());
}
// Click a call to expand
if (callCount > 0) {
await p.locator(".call-head").first().click();
await p.waitForTimeout(300);
console.log("expanded has body:", await p.locator(".call-body").first().isVisible());
}
// Sign in via settings
await p.locator(".tab", { hasText: "Settings" }).click();
await p.waitForSelector(".settings"); await p.waitForTimeout(300);
const userBtn = p.locator(".quick-users .link-btn", { hasText: "dev@flow-master.ai" }).first();
console.log("settings quick-user:", await userBtn.isVisible());
console.log("\nconsole errors:", errors.length);
errors.slice(0, 5).forEach(e => console.log(" -", e));
await p.screenshot({ path: "qa/screenshots/v3-console-open.png", fullPage: false });
await b.close();