feat: finalize portal no-iframe migration baseline and archive change

This commit is contained in:
egg
2026-02-11 13:25:03 +08:00
parent cd54d7cdcb
commit ccab10bee8
117 changed files with 6673 additions and 1098 deletions

View File

@@ -0,0 +1,2 @@
schema: spec-driven
created: 2026-02-11

View File

@@ -0,0 +1,172 @@
## Context
目前 `portal.html` 透過 `iframe + frame_id + toolFrame` 在同一頁面切換多個報表。此模式雖可避免整頁跳轉,但帶來以下問題:
- 內容生命週期拆成多個 frame除錯與事件追蹤困難
- 導覽邏輯被 iframe lazy-load、高度同步、active frame 狀態綁死
- 測試對 DOM/互動契約依賴 iframe 結構,變更成本高
- 已完成 Vite 模組化的頁面其實已可獨立路由載入,不需要 iframe 承載
此外,`drawers` 設定在目前環境已不是初始預設值,而是營運中配置(來源:`data/page_status.json`
- `reports`即時報表order=1admin_only=false
- `drawer-2`歷史報表order=2admin_only=false
- `drawer`查詢工具order=3admin_only=false
- `dev-tools`開發工具order=4admin_only=true
對應頁面已分散配置在上述抽屜,例如:
- 即時報表:`/wip-overview``/hold-overview``/resource``/qc-gate`
- 歷史報表:`/hold-history``/resource-history`
- 查詢工具:`/job-query`
- 開發工具admin pages 與部分工具頁(含 `tables``excel-query``query-tool``tmtt-defect``mid-section-defect`
因此本次改造不只是移除 iframe而是要把「抽屜資訊架構」從「載入技術frame耦合」解耦到「路由與權限治理」。
## Goals / Non-Goals
**Goals:**
- 移除 portal 內容區的 iframe 依賴與 frame 管理邏輯
- 保留抽屜分組、admin 權限過濾、健康狀態檢查 UI
- 將側欄點擊行為改為同視窗路由導頁
- 維持既有 route path 與頁面業務邏輯不變
- 更新測試使其驗證新契約link/navigation
- 在不破壞既有 `drawers/pages` 資料模型下,支持 Router-based 導覽
**Non-Goals:**
- 不在第一階段一次重寫全部 legacy 頁面內容
- 不調整後端 API 介面或權限模型
- 不更動 page_status.json 的資料模型(僅調整 portal 消費方式)
## Decisions
### Decision 1: 抽屜保留後端治理,前端改為 Router-aware 導覽
- **選擇**: `get_navigation_config()` 仍作為抽屜與頁面來源,前端側欄只消費 route / status / admin_only不再消費 frame_id/toolFrame。
- **理由**:
- 保留既有營運中的抽屜設定與管理流程
- 抽屜責任回到 IA分類、排序、權限避免綁定載入技術
- 降低一次性資料遷移與管理頁調整風險
- **備選方案**:
- 改由前端硬編抽屜:短期可行,但與管理後台脫鉤,營運成本增加
### Decision 2: 導入 SPA Shell + Vue Router分階段替換多入口模式
- **選擇**: 建立 SPA shell 承接抽屜導覽,主要報表頁優先轉為 router view既有可獨立頁先保持可直接訪問。
- **理由**:
- 符合大型遷移所需的漸進路線
- 可保留既有 URL 合約並分批改造
- **備選方案**:
- 一次切成全 SPA改動面過大回歸與 rollback 風險高
### Decision 3: Legacy 頁面採先包裝、後重寫策略(已確認)
- **選擇**: `job-query``excel-query``query-tool``tmtt-defect` 先以 wrapper route 納入新殼層,再逐頁重寫為標準 Vue 模組。
- **理由**:
- 先完成抽屜/導航/樣式治理,不被單頁重寫阻塞
- 可逐步替換,控制每次上線風險
- **備選方案**:
- 直接重寫四頁:會延後主幹遷移,且依賴資料邏輯盤點完整度
### Decision 4: Tailwind 為主樣式系統,保留過渡期雙軌
- **選擇**: 新增 Tailwind 設計 token 與元件規範,新功能優先用 Tailwind舊頁 CSS 分批遷移。
- **理由**:
- 先建立統一規範,避免繼續累積散落 CSS
- 遷移節奏可與功能迭代對齊
## Risks / Trade-offs
- **[Risk] 切頁不再常駐多頁狀態,使用者感知切換較慢** → **Mitigation**: 保持頁面 bundle 切分與快取策略,後續再評估 prefetch。
- **[Risk] 既有測試仍假設 iframe DOM 結構** → **Mitigation**: 分階段更新 template/e2e/stress 斷言為 router/navigation 契約。
- **[Risk] 抽屜配置與路由表可能出現不一致** → **Mitigation**: 新增導航一致性檢查(缺失 route、權限錯置、排序衝突
- **[Risk] Tailwind 與既有 CSS 共存期造成樣式衝突** → **Mitigation**: 設定 migration lint 規則與 page-level ownership限制新增散落 CSS。
- **[Risk] Legacy wrapper 週期拉長導致技術債滯留** → **Mitigation**: 在 tasks 中明確列出逐頁重寫里程碑與退出條件。
## Migration Plan
1. 定義抽屜-路由契約(來源、排序、權限、可見性)並建立檢查機制。
2. 建立 SPA shell 與 Router先接管 portal 導覽與主要報表頁入口。
3. 移除 iframe 導覽路徑,保留舊 URL 行為與 fallback。
4. 導入 Tailwind 設計系統並建立共用元件層。
5. 將四個 legacy 頁面先包裝接入新殼層,再分批重寫。
6. 完成測試與觀測遷移模板、E2E、壓測、性能基線
## Current Baseline Snapshot (2026-02-11)
### Effective drawer visibility (derived from current `drawers + pages + status + admin_only`)
- Non-admin visible routes:
- `reports`: `/wip-overview`, `/resource`, `/qc-gate`
- `drawer-2`: `/resource-history`
- `drawer`: `/job-query`
- Admin visible routes:
- `reports`: `/wip-overview`, `/hold-overview`, `/resource`, `/qc-gate`
- `drawer-2`: `/hold-history`, `/resource-history`
- `drawer`: `/job-query`
- `dev-tools`: `/tables`, `/admin/pages`, `/excel-query`, `/admin/performance`, `/query-tool`, `/tmtt-defect`, `/mid-section-defect`
### Query/route contracts that must not regress
- `/wip-overview`: query filters `workorder`, `lotid`, `package`, `type`, `status`
- `/wip-detail`: query filters `workcenter`, `workorder`, `lotid`, `package`, `type`, `status`
- `/hold-detail`: required query `reason` (missing reason redirects away by current server/client guard)
- `/resource-history`: query params built from date range, granularity, groups/families/machines, production flags
## Functional Parity Matrix
| Route / Surface | Migration Mode | Must Preserve |
| --- | --- | --- |
| `/` portal shell | SPA (router host) | Drawer grouping/order/visibility, health widget, auth-linked visibility |
| `/wip-overview` | Vue route view | Filter URL sync, status filter behavior, drill-down to detail pages |
| `/wip-detail` | Vue route view | Query-param entry, pagination/filter semantics, back-link query continuity |
| `/hold-overview` | Vue route view | Hold type/reason filter behavior, treemap/matrix interaction |
| `/hold-history` | Vue route view | Date/record type filter semantics, reason pareto interactions |
| `/resource` | Vue route view | Group/status filtering and summary parity |
| `/resource-history` | Vue route view | Query validation, summary/detail/export behavior parity |
| `/qc-gate` | Vue route view | Chart↔table linked filtering and refresh behaviors |
| `/job-query` | Wrapper first | Resource/date query, transaction query, CSV export |
| `/excel-query` | Wrapper first | Upload/column detect/query/export workflow |
| `/query-tool` | Wrapper first | Resolve/history/association/equipment-period workflow |
| `/tmtt-defect` | Wrapper first | Date-range query and CSV export workflow |
## Data Contract Safety Net
- 建立「遷移前基線快照」:
- drawer visibility snapshotadmin / non-admin
- route response smoke snapshotHTTP status + critical payload keys
- critical page JSON schema snapshotssummary/detail/pagination key sets
- 建立「遷移後對等檢查」:
- key presence parity不可缺欄位
- type compatibility數值/字串/陣列型別)
- empty-state semantics空資料行為一致
- 對 legacy wrapper 頁面增加 wrapper-contract 測試:
- route reachable
- primary query path success
- export path reachable (where applicable)
## Go / No-Go Gates (Cutover)
- G1 Route availability:
- P0 路由portal + major report routes100% 回應 2xx/3xx
- G2 Drawer parity:
- admin/non-admin 可見路由集合與 baseline 差異為 0
- G3 Workflow parity:
- parity matrix 中每頁核心流程至少 1 條 smoke path 通過率 100%
- G4 Client stability:
- E2E 測試中未捕獲未處理 JS runtime errorcritical path
- G5 Data contract:
- critical API payload key/type parity gate 全部通過
- G6 Performance:
- route switch latency 與 baseline 比較不得惡化超過既定閾值
- G7 Rollback readiness:
- rollback rehearsal 完成且時間達標(可在目標時間內恢復舊路徑)
## Rollback / Kill-Switch Strategy
1. 保留舊入口路徑與必要 fallback直到全量 gate 通過。
2. 使用可配置切換feature flag / env-based toggle控制新 shell 導航啟用。
3. 一旦觸發回滾條件G1/G2/G3 任一 critical fail立即切回舊導航路徑。
4. 回滾後保留觀測資料並建立失敗歸因報告,再進行下一輪修復與 rehearsal。
## Open Questions
- `frame_id/tool_src` 欄位何時在資料模型層正式退場?
- legacy wrapper 對使用者是否顯示遷移標記(例如 beta badge
- 動效方案是否在第一版限定 `Vue Transition`GSAP 延後到二階段?

View File

@@ -0,0 +1,64 @@
## Why
目前前端處於「多入口頁 + portal iframe 切頁 + 分散 CSS」型態已出現幾個結構性問題頁面生命週期分裂、導覽與內容耦合、樣式規範難以統一、重用元件難以制度化。專案已大量採用 Vite + Vue 3現在具備升級為單一 SPA Shell 的條件,應趁此時移除 iframe 並建立可持續擴充的前端架構基線。
## What Changes
- 建立前端 SPA Shell`Vite + Vue 3` 為單一入口,採 `Vue Router` 管理報表模組切換。
- 完整移除 iframe 架構portal 不再以 `frame_id/toolFrame` 嵌入內容,改為標準路由渲染。
- 導入 Tailwind CSS 作為主樣式系統,建立統一設計 token、元件風格與版面規則逐步取代現有分散 CSS。
- 建立前端動效機制基線:以 `Vue Transition` 為預設,保留 `Motion/GSAP` 擴充通道,用於跨頁過場與重點互動。
- 盤點可重用元件並收斂成共用 UI 層(如 Filter、Table、Card、KPI、Pagination 等),降低重複實作。
- 明確採用 legacy 頁面過渡策略:`job-query``excel-query``query-tool``tmtt-defect` 先以路由包裝整合進新殼層,後續再分批重寫為標準 Vue 模組。
- 保留既有後端 API 與權限邏輯,優先完成前端殼層與導航機制遷移,再進行頁面內部重構。
- **BREAKING**: portal 由「iframe 同頁切頁」改為「SPA 路由切換」,舊有 frame 相關 DOM/測試契約不再成立。
## Capabilities
### New Capabilities
- `spa-shell-navigation`: 建立 Vue Router 為核心的報表導航殼層,取代 iframe 切頁機制。
- `tailwind-design-system`: 以 Tailwind + token + 共用元件規範統一前端樣式。
- `frontend-motion-system`: 定義頁面過場與互動動效的可維護實作策略Vue Transition 為主,進階情境可擴充)。
- `legacy-page-wrapper-strategy`: 定義 legacy 頁面先包裝、後重寫的過渡標準與邊界。
### Modified Capabilities
- `portal-drawer-navigation`: 從 iframe frame-target 導覽改為 router-aware 導覽,維持抽屜分組與權限規則。
- `vue-vite-page-architecture`: 從多獨立頁入口演進到 SPA shell + 路由模組化,並納入 legacy-wrapper 相容模式。
- `full-vite-page-modularization`: 將既有共用邏輯由頁面級搬移至共用模組與設計系統層,提升重用與一致性。
- `migration-gates-and-rollout`: 將本次搬遷的上線/回滾條件明確化為可量測 gate避免「可部署但不可用」風險。
## Impact
- Affected frontend app structure:
- `frontend/src/portal/*`(改為 SPA shell / router host
- `frontend/vite.config.js`(入口與打包策略調整)
- `frontend/src/*` 多頁模組(路由化、共用元件化、樣式收斂)
- Affected templates/routes:
- `src/mes_dashboard/templates/portal.html`iframe 區塊移除)
- Flask route 對 SPA entry 與 fallback 行為需重新定義
- Affected shared styling:
- 現有 `wip-shared/resource-shared` 樣式與各頁 style.css 將分階段合併到 Tailwind 設計系統
- Affected testing:
- 模板整合測試、E2E、壓測需從 iframe 契約改為 router/navigation 契約
- 需新增 route-level smoke、drawer visibility parity、legacy wrapper contract、核心 API parity gate
- Dependency change:
- 新增 Tailwind CSS必要時含 PostCSS 生態)
- 動效方案預設不新增第三方;僅在必要場景引入 GSAP 或等價方案
- Explicit migration decision:
- `job-query``excel-query``query-tool``tmtt-defect` 採「先包裝、後重寫」策略
## Implementation Start Protocol
- 實作啟動時(第一個 `/opsx:apply` session必須先完成 baseline 產出,再進行功能改造:
- drawer visibility baselineadmin / non-admin
- route + query contract baselineP0/P1 頁面)
- critical API payload key/type baseline
- 在 baseline 產出並經 review 確認前,不進行 iframe 拆除與 Router 切換提交。
- 所有切換以 gate 驅動,不以主觀感受判定可上線。
## Release Safety Criteria
- 不可發生 P0 route 無法進入或 core workflow 中斷。
- 抽屜可見性admin / non-admin與 baseline 差異必須為 0。
- 既有 URL/query 行為不可破壞(含 drill-down 與 direct-link
- 必須具備可演練且可在時限內完成的回滾路徑(含 kill-switch

View File

@@ -0,0 +1,24 @@
## ADDED Requirements
### Requirement: Navigation transitions SHALL use a maintainable baseline motion system
The frontend SHALL provide route and panel transition effects using a baseline motion mechanism suitable for long-term maintenance.
#### Scenario: Route transition feedback
- **WHEN** a user navigates between report modules
- **THEN** the shell SHALL provide consistent transition feedback
- **THEN** transitions SHALL NOT block route completion or data loading
### Requirement: Motion behavior SHALL support reduced-motion accessibility
The motion system SHALL respect reduced-motion user preferences.
#### Scenario: Reduced-motion preference
- **WHEN** user agent indicates reduced motion preference
- **THEN** non-essential animations SHALL be minimized or disabled
- **THEN** primary interactions SHALL remain fully usable
### Requirement: Motion effects SHALL preserve functional correctness
Animation implementation SHALL NOT alter data correctness, query timing semantics, or interaction outcomes.
#### Scenario: Interactive action during motion
- **WHEN** users perform filtering, refresh, or drill-down actions during transitions
- **THEN** resulting API calls and state updates SHALL remain functionally equivalent to non-animated execution

View File

@@ -0,0 +1,23 @@
## MODIFIED Requirements
### Requirement: Major Pages SHALL be Managed by Vite Modules
The system SHALL provide Vite-managed module entries for major portal pages under a phased SPA-shell migration while keeping direct route access compatible.
#### Scenario: Portal shell module loading
- **WHEN** the portal experience is rendered
- **THEN** shell behavior MUST load from Vite-built module assets when available
#### Scenario: Module fallback continuity
- **WHEN** a required Vite asset is unavailable in a migration phase
- **THEN** the system MUST keep affected page behavior functional through explicit fallback logic
### Requirement: Modularization MUST Preserve Established Navigation and Drill-Down Semantics
Refactoring into Vite modules and SPA shell routing SHALL not alter existing route paths, query semantics, and drill-down entry points.
#### Scenario: User follows existing drill-down path
- **WHEN** the user navigates from summary page to detail views
- **THEN** the resulting flow and parameter semantics MUST match the established baseline behavior
#### Scenario: Direct detail route remains valid
- **WHEN** users open existing detail routes directly with query parameters (e.g., `/wip-detail?workcenter=...`, `/hold-detail?reason=...`)
- **THEN** route-level behavior MUST remain compatible with established baseline expectations

View File

@@ -0,0 +1,23 @@
## ADDED Requirements
### Requirement: Selected legacy pages SHALL be integrated via wrapper-first strategy
The migration SHALL integrate `job-query`, `excel-query`, `query-tool`, and `tmtt-defect` through wrapper-based routing before full rewrites.
#### Scenario: Wrapper route availability for selected pages
- **WHEN** users navigate to each selected legacy page from the new shell
- **THEN** the route SHALL remain reachable and functionally usable through the wrapper layer
### Requirement: Wrapper mode SHALL preserve legacy functional parity
Wrapper integration SHALL preserve current API interactions, core user workflows, and error handling semantics for wrapped pages.
#### Scenario: Legacy workflow parity under wrapper
- **WHEN** users execute core operations on a wrapped page (query/filter/export where applicable)
- **THEN** operation results SHALL remain behaviorally equivalent to pre-wrapper baseline
### Requirement: Wrapper phase SHALL define rewrite exit criteria
Each wrapped page SHALL have explicit readiness criteria that gate transition from wrapper mode to full Vue module rewrite.
#### Scenario: Rewrite readiness decision
- **WHEN** a wrapped page reaches agreed quality and parity thresholds
- **THEN** the page SHALL be eligible for rewrite scheduling
- **THEN** wrapper decommission SHALL only occur after rewrite parity validation passes

View File

@@ -0,0 +1,23 @@
## MODIFIED Requirements
### Requirement: Migration Gates SHALL Define Cutover Readiness
The system SHALL define explicit migration gates for functional parity, build integrity, drawer visibility parity, and operational health before final cutover.
#### Scenario: Gate evaluation before cutover
- **WHEN** release is prepared for final cutover
- **THEN** all required migration gates MUST pass or cutover SHALL be blocked
#### Scenario: Functional parity gate fails
- **WHEN** any critical route or core workflow parity check fails during gate execution
- **THEN** release governance MUST treat the cutover as failed and prevent promotion
### Requirement: Rollout and Rollback Procedures MUST be Actionable
The system SHALL document actionable rollout and rollback procedures for SPA-shell migration and iframe decommission.
#### Scenario: Rollback execution
- **WHEN** post-cutover validation fails critical checks
- **THEN** operators MUST be able to execute documented rollback steps to restore previous stable behavior
#### Scenario: Kill-switch rollback
- **WHEN** severe production regression is detected after cutover
- **THEN** operators MUST be able to disable the new navigation path through a documented kill-switch mechanism and recover service usability within the defined rollback target time

View File

@@ -0,0 +1,47 @@
## MODIFIED Requirements
### Requirement: Portal Navigation SHALL Group Entries by Functional Drawers
The portal SHALL group navigation entries into functional drawers as defined in the `drawers` configuration of `page_status.json`, rendered by the active portal runtime (server template or SPA shell) without changing drawer assignment semantics.
#### Scenario: Drawer grouping visibility
- **WHEN** users open the portal
- **THEN** the sidebar SHALL display drawers in the order defined by each drawer's `order` field
- **THEN** each drawer SHALL show only the pages assigned to it via `drawer_id`, sorted by each page's `order` field
#### Scenario: Admin-only drawer visibility
- **WHEN** a drawer has `admin_only: true` and the current user is not admin
- **THEN** the drawer and all its pages SHALL NOT be rendered in the sidebar
#### Scenario: Empty drawer visibility
- **WHEN** a drawer has no visible pages (all filtered out by page visibility checks)
- **THEN** the drawer group title SHALL NOT be rendered
### Requirement: Existing Page Behavior SHALL Remain Compatible
The portal navigation refactor SHALL preserve existing target routes while replacing iframe-based page embedding with route-driven navigation.
#### Scenario: Route continuity
- **WHEN** a user selects an existing page entry from a drawer
- **THEN** the corresponding original route SHALL be loaded without changing page business logic behavior
#### Scenario: Direct navigation without iframe
- **WHEN** a sidebar item is clicked
- **THEN** the browser SHALL navigate to the page's route in the same window
- **THEN** the portal SHALL NOT render or activate iframe elements for page content
## ADDED Requirements
### Requirement: Drawer Configuration and Visibility SHALL Remain Deterministic During Migration
Migration to SPA navigation SHALL preserve the effective drawer visibility outcomes defined by current `drawers + pages + status + admin_only` rules.
#### Scenario: Non-admin visible drawer pages remain stable
- **WHEN** a non-admin user opens the portal after migration
- **THEN** only pages with released visibility in non-admin drawers SHALL be visible
- **THEN** admin-only drawers SHALL remain hidden
#### Scenario: Admin visible drawer pages remain stable
- **WHEN** an admin user opens the portal after migration
- **THEN** all pages allowed by drawer assignment and page status rules SHALL remain visible
#### Scenario: Duplicate order values resolve deterministically
- **WHEN** multiple pages or drawers share the same `order` value
- **THEN** rendering order SHALL still be deterministic and repeatable across requests

View File

@@ -0,0 +1,28 @@
## ADDED Requirements
### Requirement: Portal SHALL provide a SPA shell driven by Vue Router
The portal frontend SHALL use a single SPA shell entry and Vue Router to render page modules without iframe embedding.
#### Scenario: Drawer navigation renders router view
- **WHEN** a user clicks a sidebar page entry
- **THEN** the active route SHALL be updated through Vue Router
- **THEN** the main content area SHALL render the corresponding route view without iframe usage
### Requirement: Existing route contracts SHALL remain stable in SPA mode
Migration to SPA shell SHALL preserve existing route paths and deep-link behavior.
#### Scenario: Direct route entry remains functional
- **WHEN** a user opens an existing route directly (bookmark or refresh)
- **THEN** the route SHALL resolve to the same page functionality as before migration
- **THEN** required query parameters SHALL continue to be interpreted with compatible semantics
### Requirement: SPA shell navigation SHALL enforce page visibility rules
SPA navigation SHALL respect backend-defined drawer and page visibility outcomes.
#### Scenario: Non-admin visibility in SPA shell
- **WHEN** a non-admin user opens the shell
- **THEN** routes and drawer items restricted to admin-only visibility SHALL NOT be presented as navigable entries
#### Scenario: Admin visibility in SPA shell
- **WHEN** an admin user opens the shell
- **THEN** pages allowed by drawer and page status rules SHALL be presented as navigable entries

View File

@@ -0,0 +1,25 @@
## ADDED Requirements
### Requirement: Frontend styles SHALL be governed by Tailwind design tokens
The frontend SHALL define a Tailwind-based design token system for color, spacing, typography, radius, and elevation to ensure consistent styling across modules.
#### Scenario: Shared token usage across modules
- **WHEN** two report modules render equivalent UI elements (e.g., card, filter chip, primary button)
- **THEN** they SHALL use the same token-backed style semantics
- **THEN** visual output SHALL remain consistent across modules
### Requirement: Tailwind migration SHALL support coexistence with legacy CSS
The migration SHALL allow Tailwind and existing page CSS to coexist during phased rollout without breaking existing pages.
#### Scenario: Legacy page remains functional during coexistence
- **WHEN** a not-yet-migrated page is rendered
- **THEN** existing CSS behavior SHALL remain intact
- **THEN** Tailwind introduction SHALL NOT cause blocking style regressions
### Requirement: New shared UI components SHALL prefer Tailwind-first styling
Newly introduced shared components SHALL be implemented with Tailwind-first conventions to avoid expanding duplicated page-local CSS.
#### Scenario: Shared component adoption
- **WHEN** a new shared component is introduced in migration scope
- **THEN** its primary style contract SHALL be expressed through Tailwind utilities/components
- **THEN** page-local CSS additions SHALL be minimized and justified

View File

@@ -0,0 +1,19 @@
## MODIFIED Requirements
### Requirement: Pure Vite pages SHALL be served as static HTML
The system SHALL support serving Vite-built HTML pages directly via Flask without Jinja2 rendering.
#### Scenario: Serve pure Vite page
- **WHEN** user navigates to a pure Vite page route (e.g., `/qc-gate`)
- **THEN** Flask SHALL serve the pre-built HTML file from `static/dist/` via `send_from_directory`
- **THEN** the HTML SHALL NOT pass through Jinja2 template rendering
#### Scenario: Page works as top-level navigation target
- **WHEN** a pure Vite page is opened from portal direct navigation
- **THEN** the page SHALL render correctly as a top-level route without iframe embedding dependency
- **THEN** page functionality SHALL NOT rely on portal-managed frame lifecycle
#### Scenario: Direct URL with query parameters remains valid
- **WHEN** users directly open a pure Vite route with existing query parameters (e.g., `/wip-detail?workcenter=...`)
- **THEN** the page SHALL preserve existing parameter semantics and load behavior
- **THEN** SPA shell integration SHALL NOT break direct route entry

View File

@@ -0,0 +1,97 @@
## 0. Implementation Kickoff (Apply Session Day-1)
- [x] 0.1 Generate and commit migration baseline snapshots (drawer visibility, route/query contracts, critical API payload key/type).
- [x] 0.2 Create parity checklist artifacts mapped to the functional parity matrix routes.
- [x] 0.3 Define and verify cutover control mechanism (feature flag / env toggle) before any breaking navigation change.
- [x] 0.4 Record rollback rehearsal plan with target recovery SLO and responsible operator steps.
## 1. Drawer Baseline and Governance Contract
- [x] 1.1 Capture the current production drawer baseline from `data/page_status.json` (id/name/order/admin_only/pages) as migration reference data.
- [x] 1.2 Define canonical drawer responsibilities: IA grouping, ordering, and permission visibility only (no iframe/frame loading semantics).
- [x] 1.3 Define a drawer-route consistency contract (route exists, drawer exists, order is valid, admin_only behavior is deterministic).
- [x] 1.4 Add validation checks/tests for admin and non-admin drawer visibility against the current baseline configuration.
- [x] 1.5 Define `frame_id/tool_src` deprecation policy and transition checkpoints.
## 2. SPA Shell and Router Foundation
- [x] 2.1 Create a SPA shell entry for portal navigation using Vue 3 + Vue Router.
- [x] 2.2 Build router records from drawer/page route contracts while preserving existing URL compatibility.
- [x] 2.3 Implement router-aware sidebar active state and breadcrumb/title metadata handling.
- [x] 2.4 Align auth/permission checks between backend route guard and frontend navigation guard behavior.
- [x] 2.5 Keep health-status widget behavior available in shell without iframe coupling.
## 3. Portal Iframe Decommission
- [x] 3.1 Refactor `portal.html` to remove iframe panel DOM and switch sidebar metadata to route-driven navigation.
- [x] 3.2 Refactor `frontend/src/portal/main.js` to remove frame activation/lazy-load/unload logic.
- [x] 3.3 Replace iframe-specific UI states with route-transition states and loading indicators.
- [x] 3.4 Remove portal CSS rules that target iframe layout while preserving current visual structure.
- [x] 3.5 Verify non-admin/admin navigation outcomes for all current drawers under direct routing.
## 4. Tailwind Design System Bootstrap
- [x] 4.1 Introduce Tailwind CSS + PostCSS configuration into the frontend build pipeline.
- [x] 4.2 Define design tokens (color, spacing, typography, radius, elevation, z-index) mapped to existing UI language.
- [x] 4.3 Establish global base/component/utility layers and migration-safe style ordering.
- [x] 4.4 Define style governance rules to prevent new large page-local CSS during migration.
- [x] 4.5 Publish migration guide for converting existing CSS modules/pages to Tailwind patterns.
## 5. Shared UI and Composable Consolidation
- [x] 5.1 Inventory duplicated UI patterns across WIP/Resource/Hold/QC pages (filter bar, KPI cards, tables, pagination, badges, banners).
- [x] 5.2 Create shared UI component layer and normalize props/events/slot contracts.
- [x] 5.3 Consolidate cross-page composables (auto-refresh, autocomplete, query state, pagination state) under shared modules.
- [x] 5.4 Migrate existing pages to shared components incrementally with visual parity checks.
- [x] 5.5 Remove obsolete duplicated component/style artifacts after each migration batch.
## 6. Legacy Page Wrapper Phase (Confirmed Decision)
- [x] 6.1 Implement wrapper integration for `job-query` inside the new router/shell flow.
- [x] 6.2 Implement wrapper integration for `excel-query` inside the new router/shell flow.
- [x] 6.3 Implement wrapper integration for `query-tool` inside the new router/shell flow.
- [x] 6.4 Implement wrapper integration for `tmtt-defect` inside the new router/shell flow.
- [x] 6.5 Define wrapper-level telemetry (load success, error, latency) and fallback behavior.
- [x] 6.6 Document hard exit criteria that determine when each wrapped page can be considered rewrite-ready.
## 7. Legacy Rewrite Execution (Post-Wrapper)
- Reference checklist: `docs/migration/portal-no-iframe/legacy_rewrite_smoke_checklists.md`
- Reference exemplar: `docs/migration/portal-no-iframe/tmtt_rewrite_exemplar.md`
- Reference playbook: `docs/migration/portal-no-iframe/legacy_rewrite_playbook.md`
- Reference decommission record: `docs/migration/portal-no-iframe/wrapper_decommission_report.md`
- [x] 7.1 Prioritize rewrite order among wrapped pages using usage/complexity/risk scoring.
- [x] 7.2 Rewrite first legacy page as canonical migration exemplar with shared UI + Tailwind.
- [x] 7.3 Rewrite remaining three legacy pages with reusable migration playbook and acceptance criteria.
- [x] 7.4 Decommission wrappers after rewrite completion and parity validation.
## 8. Interaction and Motion System
- [x] 8.1 Define baseline motion guidelines using Vue Transition (route transitions, panel changes, loading states).
- [x] 8.2 Implement reduced-motion accessibility behavior and fallback styles.
- [x] 8.3 Add key interaction transitions for filter apply, chart/table refresh, and drawer navigation.
- [x] 8.4 Define an escalation rule for when GSAP (or equivalent) is allowed beyond baseline transitions.
## 9. Testing, Quality Gates, and Performance
- [x] 9.1 Update unit/template tests from iframe assumptions to router/drawer contract assertions.
- [x] 9.2 Update E2E and stress suites to validate route navigation stability instead of iframe switching.
- [x] 9.3 Add regression tests for drawer ordering, admin_only filtering, and mixed release/dev visibility.
- [x] 9.4 Add contract tests for legacy wrapper routing and fallback behavior.
- [x] 9.5 Establish performance baselines (first paint, route switch latency, memory footprint) and compare pre/post migration.
## 10. Rollout, Cleanup, and Spec Closure
- [x] 10.1 Define phased rollout plan with canary scope and success/error thresholds.
- [x] 10.2 Define rollback strategy for shell/router cutover and wrapper failures.
- [x] 10.3 Remove `frame_id/tool_src` from runtime navigation payload after wrapper-to-rewrite milestones are complete.
- [x] 10.4 Sync changed requirements into main specs and prepare archive criteria for this migration change.
## 11. Cutover Gate Enforcement (Measurable)
- [x] 11.1 Enforce G1 route availability gate: P0 routes return 2xx/3xx at 100% pass rate in release validation.
- [x] 11.2 Enforce G2 drawer parity gate: admin/non-admin visible route sets must match pre-migration baseline exactly (delta = 0).
- [x] 11.3 Enforce G3 workflow parity gate: one critical smoke flow per route in parity matrix must pass at 100%.
- [x] 11.4 Enforce G4 client stability gate: zero unhandled JavaScript runtime errors on critical E2E paths.
- [x] 11.5 Enforce G5 data contract gate: required payload key/type parity checks must pass for all critical APIs.
- [x] 11.6 Enforce G7 rollback readiness gate: rollback rehearsal must recover stable navigation within target SLO (e.g., <= 15 minutes).