refine workbench page usability
This commit is contained in:
@@ -0,0 +1,85 @@
|
||||
# Workbench Pages Usability Cleanup Implementation Plan
|
||||
|
||||
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
||||
|
||||
**Goal:** Reduce cognitive overload across all non-dashboard workbench pages while preserving the current StoryForge UI style and business logic.
|
||||
|
||||
**Architecture:** Keep the existing single-page shell and page render functions, but add lightweight page-level tab state, restore the missing settings route, and move admin-grade sections out of user pages. Prefer small render helpers and targeted page restructuring over a full rewrite.
|
||||
|
||||
**Tech Stack:** Vanilla JavaScript SPA, static HTML, CSS, Node built-in test runner, Playwright for live verification.
|
||||
|
||||
---
|
||||
|
||||
### Task 1: Add regression coverage for page routing and scope boundaries
|
||||
|
||||
**Files:**
|
||||
- Create: `/Users/kris/code/StoryForge-gitea/web/storyforge-web-v4/tests/workbench-pages.test.mjs`
|
||||
|
||||
- [ ] Write source-level regression tests for:
|
||||
- settings nav route exists
|
||||
- settings screen exists
|
||||
- `renderAll()` renders settings
|
||||
- automation page no longer renders quota / registry / admin ops
|
||||
- Agent page no longer renders quota / registry
|
||||
- discovery / production / admin pages expose page-tab interactions
|
||||
|
||||
### Task 2: Restore settings as a real page
|
||||
|
||||
**Files:**
|
||||
- Modify: `/Users/kris/code/StoryForge-gitea/web/storyforge-web-v4/index.html`
|
||||
- Modify: `/Users/kris/code/StoryForge-gitea/web/storyforge-web-v4/assets/app.js`
|
||||
|
||||
- [ ] Add `data-screen-target="settings"` to the sidebar button.
|
||||
- [ ] Add a real `data-screen="settings"` section.
|
||||
- [ ] Implement `renderSettingsScreen()` and include it in `renderAll()`.
|
||||
|
||||
### Task 3: Add shared page-tab state and event handling
|
||||
|
||||
**Files:**
|
||||
- Modify: `/Users/kris/code/StoryForge-gitea/web/storyforge-web-v4/assets/app.js`
|
||||
- Modify: `/Users/kris/code/StoryForge-gitea/web/storyforge-web-v4/assets/styles.css`
|
||||
|
||||
- [ ] Add page-level tab state to `appState`.
|
||||
- [ ] Add a small helper to render page tabs consistently.
|
||||
- [ ] Add click handling for `select-page-tab`.
|
||||
|
||||
### Task 4: Simplify the heaviest user pages
|
||||
|
||||
**Files:**
|
||||
- Modify: `/Users/kris/code/StoryForge-gitea/web/storyforge-web-v4/assets/app.js`
|
||||
- Modify: `/Users/kris/code/StoryForge-gitea/web/storyforge-web-v4/assets/styles.css`
|
||||
|
||||
- [ ] Refactor `renderDiscoveryScreen()` to use tabs for overview / snapshots / similar.
|
||||
- [ ] Refactor `renderProductionScreen()` to use tabs for queue / recovery / recorder / outputs.
|
||||
- [ ] Refactor `renderAutomationScreen()` to use tabs and remove admin-grade sections.
|
||||
- [ ] Refactor `renderPlaybookScreen()` to use tabs and remove quota / registry from the user page.
|
||||
|
||||
### Task 5: Strengthen thin pages and compress medium pages
|
||||
|
||||
**Files:**
|
||||
- Modify: `/Users/kris/code/StoryForge-gitea/web/storyforge-web-v4/assets/app.js`
|
||||
- Modify: `/Users/kris/code/StoryForge-gitea/web/storyforge-web-v4/assets/styles.css`
|
||||
|
||||
- [ ] Expand `renderOwnedScreen()` into a usable account workbench.
|
||||
- [ ] Expand `renderCreditsScreen()` into a readable quota page.
|
||||
- [ ] Lightly tune `renderProjectsScreen()` and `renderReviewScreen()` to reduce raw data feel and repetition.
|
||||
|
||||
### Task 6: Convert admin workbench into a tabbed control surface
|
||||
|
||||
**Files:**
|
||||
- Modify: `/Users/kris/code/StoryForge-gitea/web/storyforge-web-v4/assets/app.js`
|
||||
- Modify: `/Users/kris/code/StoryForge-gitea/web/storyforge-web-v4/assets/styles.css`
|
||||
|
||||
- [ ] Refactor `renderAdminWorkbenchScreen()` to use tabs for integrations / storage / agents / ops.
|
||||
- [ ] Keep all system governance sections here instead of user pages.
|
||||
|
||||
### Task 7: Verify locally and on the NAS page
|
||||
|
||||
**Files:**
|
||||
- None
|
||||
|
||||
- [ ] Run `node --test /Users/kris/code/StoryForge-gitea/web/storyforge-web-v4/tests/dashboard-home.test.mjs /Users/kris/code/StoryForge-gitea/web/storyforge-web-v4/tests/workbench-pages.test.mjs`
|
||||
- [ ] Run `node --check /Users/kris/code/StoryForge-gitea/web/storyforge-web-v4/assets/app.js`
|
||||
- [ ] Run `bash /Users/kris/code/StoryForge-gitea/scripts/check_repo_baseline.sh`
|
||||
- [ ] Redeploy the NAS frontend if needed.
|
||||
- [ ] Re-check the key pages in a real browser and confirm no new console errors.
|
||||
@@ -0,0 +1,134 @@
|
||||
# 非首页工作台页面可用性整改设计
|
||||
|
||||
## 目标
|
||||
|
||||
在不改变当前 StoryForge Web V4 整体视觉风格的前提下,整改首页之外的工作台页面,让页面更符合人类使用逻辑:
|
||||
|
||||
- 信息更容易扫读
|
||||
- 同页只处理一类任务
|
||||
- 普通用户更容易上手
|
||||
- 管理员页保留专业度,但不再是长页面堆叠
|
||||
|
||||
## 范围
|
||||
|
||||
本轮只处理首页之外的页面:
|
||||
|
||||
- 我的项目
|
||||
- 找对标
|
||||
- 跟踪账号
|
||||
- 我的账号
|
||||
- Agent
|
||||
- 生产中心
|
||||
- 发布与复盘
|
||||
- 自动流程
|
||||
- 额度
|
||||
- 管理员配置台
|
||||
- 设置
|
||||
|
||||
首页不在本轮范围内。
|
||||
|
||||
## 设计原则
|
||||
|
||||
1. 不换皮,只做信息减法和层级重排。
|
||||
2. 一个页面只允许一个主任务视角,深层信息通过页内 tab 切换。
|
||||
3. 系统治理内容从普通用户页面移走,优先归入管理员配置台。
|
||||
4. 太空的页面要补到能独立成立,太重的页面要压缩成单主区。
|
||||
|
||||
## 页面级方案
|
||||
|
||||
### 设置
|
||||
|
||||
- 修复现有切页异常,点击后必须真正进入设置页。
|
||||
- 新增轻量设置页,展示:
|
||||
- 当前连接状态
|
||||
- 当前工作区 / 当前项目
|
||||
- 自动连接说明
|
||||
- 页面使用偏好与帮助入口
|
||||
- 超级管理员在这里看到“去管理员配置台”的入口提示,但不把管理员配置内容塞进设置页。
|
||||
|
||||
### 自动流程
|
||||
|
||||
- 只保留普通用户真正需要理解的两层:
|
||||
- 依赖健康
|
||||
- 动作防呆
|
||||
- 租户额度、OneLiner 动作注册表、运维审计从本页移走。
|
||||
- 页面结构改成页内 tab,一次只看一个区块。
|
||||
|
||||
### Agent
|
||||
|
||||
- 普通用户 Agent 页只保留:
|
||||
- OneLiner 主 Agent 使用区
|
||||
- 当前 Agent
|
||||
- 平台 Agent 协作状态
|
||||
- 模型/学习/最近生成
|
||||
- 租户额度和 OneLiner 动作注册表移出本页。
|
||||
- 页面改成页内 tab,降低一次性信息密度。
|
||||
|
||||
### 找对标
|
||||
|
||||
- 保留当前业务逻辑,不删能力。
|
||||
- 但把深层信息改成页内 tab,一次只展示一种视角:
|
||||
- 账号概览
|
||||
- 快照 / 字段 / 报告
|
||||
- 相似对标 / 已绑关系
|
||||
- 账号列表和当前选中账号仍保留在主结构里。
|
||||
|
||||
### 生产中心
|
||||
|
||||
- 页面改成页内 tab:
|
||||
- 生产队列
|
||||
- 失败恢复
|
||||
- 录制维护
|
||||
- 作品与产物
|
||||
- 当前页顶部保留总览和主动作,不再把四大块内容同时展开。
|
||||
|
||||
### 管理员配置台
|
||||
|
||||
- 保留系统级治理边界:
|
||||
- 依赖健康
|
||||
- 存储状态
|
||||
- 平台 Agent / OneLiner 系统级管理
|
||||
- 运维与审计
|
||||
- 页面改成页内 tab,避免长页面堆叠。
|
||||
|
||||
### 我的账号
|
||||
|
||||
- 从“单张摘要卡”补成可成立的工作页面:
|
||||
- 当前身份
|
||||
- 当前负责项目与 Agent
|
||||
- 最近工作摘要
|
||||
- 常用快捷动作
|
||||
|
||||
### 额度
|
||||
|
||||
- 从“几个孤立数字”补成更接近产品化额度页:
|
||||
- 当前额度摘要
|
||||
- 已用 / 剩余 / 预估
|
||||
- 套餐化解释
|
||||
- 风险提示
|
||||
|
||||
### 我的项目 / 跟踪账号 / 发布与复盘
|
||||
|
||||
- 保持现有方向,不大改视觉骨架。
|
||||
- 只做轻量压缩:
|
||||
- 我的项目:弱化原始导入队列感,强调下一步动作
|
||||
- 跟踪账号:增强空状态可理解性
|
||||
- 发布与复盘:减少重复项,强调“待补复盘”
|
||||
|
||||
## 信息边界
|
||||
|
||||
普通用户页面不再承接这些系统级内容:
|
||||
|
||||
- OneLiner 动作注册表
|
||||
- 租户额度与审计全量治理面板
|
||||
- 运维与审计 Agent 全量事件墙
|
||||
|
||||
这些内容统一收口到管理员配置台。
|
||||
|
||||
## 验收标准
|
||||
|
||||
- 设置页可以真实切换并渲染独立内容。
|
||||
- 自动流程、Agent、找对标、生产中心、管理员配置台都改成“一次只展开一类信息”的结构。
|
||||
- 自动流程与 Agent 页面不再混入管理员治理内容。
|
||||
- 我的账号和额度页面不再显得像半成品空页。
|
||||
- 控制台无新增报错,现有 NAS 页面可正常浏览。
|
||||
@@ -39,7 +39,9 @@ for file in web/storyforge-web-v4/assets/app.js web/storyforge-web-v4/assets/sto
|
||||
done
|
||||
node --check scripts/douyin-browser-capture/control_panel.mjs
|
||||
|
||||
echo "[5/5] validate homepage dashboard tests"
|
||||
node --test web/storyforge-web-v4/tests/dashboard-home.test.mjs
|
||||
echo "[5/5] validate homepage and workbench tests"
|
||||
node --test \
|
||||
web/storyforge-web-v4/tests/dashboard-home.test.mjs \
|
||||
web/storyforge-web-v4/tests/workbench-pages.test.mjs
|
||||
|
||||
echo "baseline checks passed"
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -68,7 +68,7 @@
|
||||
<span class="icon">⚙</span>
|
||||
<span>管理员配置台</span>
|
||||
</button>
|
||||
<button class="nav-item">
|
||||
<button class="nav-item" data-screen-target="settings">
|
||||
<span class="icon">☰</span>
|
||||
<span>设置</span>
|
||||
</button>
|
||||
@@ -1915,6 +1915,7 @@
|
||||
</section>
|
||||
|
||||
<section class="screen" data-screen="admin-workbench"></section>
|
||||
<section class="screen" data-screen="settings"></section>
|
||||
</main>
|
||||
</div>
|
||||
|
||||
|
||||
49
web/storyforge-web-v4/tests/workbench-pages.test.mjs
Normal file
49
web/storyforge-web-v4/tests/workbench-pages.test.mjs
Normal file
@@ -0,0 +1,49 @@
|
||||
import test from "node:test";
|
||||
import assert from "node:assert/strict";
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
|
||||
const ROOT = path.resolve(process.cwd(), "web/storyforge-web-v4");
|
||||
const HTML = fs.readFileSync(path.join(ROOT, "index.html"), "utf8");
|
||||
const APP = fs.readFileSync(path.join(ROOT, "assets/app.js"), "utf8");
|
||||
|
||||
function extractBetween(source, startToken, endToken) {
|
||||
const start = source.indexOf(startToken);
|
||||
assert.notEqual(start, -1, `Missing token: ${startToken}`);
|
||||
const end = source.indexOf(endToken, start);
|
||||
assert.notEqual(end, -1, `Missing token: ${endToken}`);
|
||||
return source.slice(start, end);
|
||||
}
|
||||
|
||||
test("settings navigation and screen are real routes", () => {
|
||||
assert.match(HTML, /data-screen-target="settings"/);
|
||||
assert.match(HTML, /data-screen="settings"/);
|
||||
assert.match(APP, /function renderSettingsScreen\(/);
|
||||
assert.match(APP, /screenMap\.settings\.innerHTML = renderSettingsScreen\(\);/);
|
||||
assert.match(APP, /window\.addEventListener\("hashchange"/);
|
||||
});
|
||||
|
||||
test("automation screen stays user-facing and excludes admin-only panels", () => {
|
||||
const source = extractBetween(APP, "function renderAutomationScreen()", "function renderOwnedScreen()");
|
||||
assert.doesNotMatch(source, /renderTenantQuotaPanel\(/);
|
||||
assert.doesNotMatch(source, /renderOneLinerActionRegistryPanel\(/);
|
||||
assert.doesNotMatch(source, /renderAdminOpsPanel\(/);
|
||||
assert.match(source, /renderDetailTabs\("automationDetailTab"/);
|
||||
});
|
||||
|
||||
test("agent screen excludes quota and registry panels and uses page tabs", () => {
|
||||
const source = extractBetween(APP, "function renderPlaybookScreen()", "function renderProductionScreen()");
|
||||
assert.doesNotMatch(source, /renderTenantQuotaPanel\(/);
|
||||
assert.doesNotMatch(source, /renderOneLinerActionRegistryPanel\(/);
|
||||
assert.match(source, /renderDetailTabs\("playbookDetailTab"/);
|
||||
});
|
||||
|
||||
test("discovery, production, and admin screens use page tabs for heavy content", () => {
|
||||
const discovery = extractBetween(APP, "function renderDiscoveryScreen()", "function renderTrackingScreen()");
|
||||
const production = extractBetween(APP, "function renderProductionScreen()", "function renderReviewScreen()");
|
||||
const admin = extractBetween(APP, "function renderAdminWorkbenchScreen()", "function renderDashboardScreen()");
|
||||
|
||||
assert.match(discovery, /renderDetailTabs\("discoveryDetailTab"/);
|
||||
assert.match(production, /renderDetailTabs\("productionDetailTab"/);
|
||||
assert.match(admin, /renderDetailTabs\("adminWorkbenchTab"/);
|
||||
});
|
||||
Reference in New Issue
Block a user