Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
version: 2
updates:
- package-ecosystem: github-actions
directory: "/"
schedule:
interval: weekly
- package-ecosystem: npm
directory: "/frontend"
schedule:
interval: weekly
- package-ecosystem: npm
directory: "/chrome/extension-src"
schedule:
interval: weekly
- package-ecosystem: pip
directory: "/"
schedule:
interval: weekly
- package-ecosystem: cargo
directory: "/odp-rs"
schedule:
interval: weekly
47 changes: 47 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,53 @@ jobs:
name: extension-dist
path: chrome/extension-src/dist

frontend:
runs-on: ubuntu-latest
name: Next Frontend
defaults:
run:
working-directory: frontend
steps:
- name: Checkout
uses: actions/checkout@v6

- name: Setup Node
uses: actions/setup-node@v6
with:
node-version-file: .nvmrc

- name: Setup Python for workflow contract check
uses: actions/setup-python@v6
with:
python-version: "3.13"

- name: Install workflow contract dependency
run: python -m pip install "pydantic>=2.10.0"

- name: Install dependencies
run: |
corepack enable
corepack prepare pnpm@11.10.0 --activate
pnpm install --frozen-lockfile

- name: Lint
run: pnpm lint

- name: Typecheck
run: pnpm exec tsc --noEmit

- name: Workflow regressions
run: pnpm check:workflow-regressions

- name: Production build
run: pnpm build

- name: Install Chromium
run: pnpm exec playwright install --with-deps chromium

- name: Browser smoke test
run: pnpm test:smoke

backend:
runs-on: ubuntu-latest
name: Backend Quality
Expand Down
2 changes: 1 addition & 1 deletion .nvmrc
Original file line number Diff line number Diff line change
@@ -1 +1 @@
20.12.2
26.3.1
2 changes: 2 additions & 0 deletions frontend/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ node_modules
.next/
.DS_Store
tsconfig.tsbuildinfo
test-results/
playwright-report/
*.log
.tmp-*.log
.mcp.json
Expand Down
3 changes: 0 additions & 3 deletions frontend/components/error-boundary.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,9 @@ export class ErrorBoundary extends Component<Props, State> {

componentDidCatch(error: Error, info: ErrorInfo) {
const tag = this.props.label ? `[ErrorBoundary:${this.props.label}]` : "[ErrorBoundary]"
// eslint-disable-next-line no-console
console.error(`${tag} ${error.name}: ${error.message}`)
// eslint-disable-next-line no-console
console.error(`${tag} stack:\n${error.stack ?? "(no stack)"}`)
if (info.componentStack) {
// eslint-disable-next-line no-console
console.error(`${tag} componentStack:${info.componentStack}`)
}
}
Expand Down
4 changes: 2 additions & 2 deletions frontend/components/flow/edges/editable-edge.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"use client"

import { memo, useCallback, useRef } from "react"
import { memo, useCallback, useMemo, useRef } from "react"
import {
BaseEdge,
EdgeLabelRenderer,
Expand Down Expand Up @@ -49,7 +49,7 @@ function EditableEdgeComponent({
const onEdgesChange = useFlowStore((s) => s.onEdgesChange)
const draggingRef = useRef<number | null>(null)

const waypoints = data?.waypoints ?? []
const waypoints = useMemo(() => data?.waypoints ?? [], [data?.waypoints])
const points: XYPosition[] = [{ x: sourceX, y: sourceY }, ...waypoints, { x: targetX, y: targetY }]
const path = buildPath(points)
const labelPoint = points[Math.floor(points.length / 2)]
Expand Down
3 changes: 0 additions & 3 deletions frontend/components/flow/error-logger.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ export function ErrorLogger() {
return
}
seen.first = true
// eslint-disable-next-line no-console
console.error(`[ErrorLogger:${label}] FIRST ERROR`, detail)
}

Expand Down Expand Up @@ -54,7 +53,6 @@ export function ErrorLogger() {
po = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
if (entry.duration > 500) {
// eslint-disable-next-line no-console
console.warn("[ErrorLogger:longtask]", {
duration: Math.round(entry.duration),
startTime: Math.round(entry.startTime),
Expand All @@ -66,7 +64,6 @@ export function ErrorLogger() {
po.observe({ entryTypes: ["longtask"] })
} catch {}

// eslint-disable-next-line no-console
console.info("[ErrorLogger] armed")

return () => {
Expand Down
7 changes: 7 additions & 0 deletions frontend/e2e/login.spec.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { expect, test } from '@playwright/test'

test('login page renders its administrator credentials form', async ({ page }) => {
await page.goto('/login')
await expect(page.getByText('登录控制台')).toBeVisible()
await expect(page.getByLabel('管理员身份令牌')).toBeVisible()
})
52 changes: 27 additions & 25 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,21 @@
"check:workflow-regressions": "node --test scripts/check-workflow-regressions.mjs",
"check:navigation-transitions": "node --test scripts/check-navigation-transition-regressions.mjs",
"check:control-plane": "node --test scripts/check-control-plane-regressions.mjs scripts/check-dashboard-regressions.mjs scripts/check-inbox-regressions.mjs",
"test:smoke": "playwright test",
"test:workflow-contracts": "node scripts/assert-workflow-contracts.mjs",
"start": "next start",
"lint": "eslint ."
},
"dependencies": {
"@base-ui/react": "^1.5.0",
"@base-ui/react": "^1.6.0",
"@dagrejs/dagre": "^3.0.0",
"@react-three/fiber": "^9.6.1",
"@react-three/postprocessing": "^3.0.4",
"@ssgoi/react": "6.6.6",
"@tanstack/react-query": "^5.101.2",
"@vercel/analytics": "1.6.1",
"@xyflow/react": "^12.11.1",
"ai": "^7.0.15",
"@ssgoi/react": "6.6.10",
"@tanstack/react-query": "^5.101.4",
"@vercel/analytics": "2.0.1",
"@xyflow/react": "^12.11.2",
"ai": "^7.0.36",
"animejs": "^4.5.0",
"axios": "^1.18.1",
"class-variance-authority": "^0.7.1",
Expand All @@ -31,25 +32,25 @@
"d3-force": "^3.0.0",
"d3-hierarchy": "^3.1.2",
"dagre": "^0.8.5",
"elkjs": "^0.11.1",
"elkjs": "^0.12.0",
"gsap": "^3.15.0",
"html-to-image": "^1.11.13",
"lucide-react": "^1.16.0",
"lucide-react": "^1.26.0",
"lz-string": "^1.5.0",
"motion": "^12.42.2",
"nanoid": "^5.1.16",
"next": "16.2.6",
"nanoid": "^6.0.0",
"next": "16.2.11",
"next-themes": "^0.4.6",
"ogl": "^1.0.11",
"oidc-client-ts": "^3.5.0",
"perfect-freehand": "^1.2.3",
"postprocessing": "^6.39.2",
"react": "^19",
"react-dom": "^19",
"recharts": "3.8.0",
"shadcn": "^4.8.0",
"postprocessing": "^6.39.3",
"react": "^19.2.8",
"react-dom": "^19.2.8",
"recharts": "3.10.0",
"shadcn": "^4.14.1",
"sonner": "^2.0.7",
"tailwind-merge": "^3.3.1",
"tailwind-merge": "^3.6.0",
"three": "^0.185.1",
"tw-animate-css": "^1.4.0",
"y-protocols": "^1.0.7",
Expand All @@ -61,18 +62,19 @@
},
"devDependencies": {
"@material/material-color-utilities": "^0.4.0",
"@tailwindcss/postcss": "^4.2.0",
"@playwright/test": "^1.61.1",
"@tailwindcss/postcss": "^4.3.3",
"@types/d3-force": "^3.0.10",
"@types/d3-hierarchy": "^3.1.7",
"@types/dagre": "^0.7.54",
"@types/node": "^24",
"@types/react": "^19",
"@types/react-dom": "^19",
"@types/node": "^26.1.1",
"@types/react": "^19.2.17",
"@types/react-dom": "^19.2.3",
"@types/three": "^0.185.1",
"eslint": "^9.39.2",
"eslint-config-next": "^16.2.10",
"postcss": "^8.5",
"tailwindcss": "^4.2.0",
"typescript": "5.7.3"
"eslint": "^9.39.5",
"eslint-config-next": "^16.2.11",
"postcss": "^8.5.22",
"tailwindcss": "^4.3.3",
"typescript": "6.0.3"
}
}
14 changes: 14 additions & 0 deletions frontend/playwright.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { defineConfig } from '@playwright/test'

export default defineConfig({
testDir: './e2e',
use: {
baseURL: 'http://127.0.0.1:3000',
browserName: 'chromium',
},
webServer: {
command: 'pnpm start --hostname 127.0.0.1 --port 3000',
reuseExistingServer: !process.env.CI,
timeout: 30_000,
},
})
Loading
Loading