重构插件异步状态与业务用例
This commit is contained in:
@@ -0,0 +1,108 @@
|
||||
# Shared Result UI Phase 2 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:** Remove duplicated export-history and empty-result UI code from Scanner and MyBatis SQL Export while preserving their behavior.
|
||||
|
||||
**Architecture:** Add a small immutable adapter model between plugin-specific history rows and a reusable JavaFX history pane. Keep file-opening side effects behind injected callbacks so the shared pane only renders data and emits commands. Add a reusable empty-state component for later plugin migrations.
|
||||
|
||||
**Tech Stack:** Java 17, JavaFX, JUnit 5, Maven.
|
||||
|
||||
## Global Constraints
|
||||
|
||||
- Work only in `C:\tmp\workutils-plugin-ui-refactor` on branch `codex/plugin-ui-refactor`.
|
||||
- Do not add raw `new Thread`.
|
||||
- Shared UI components must not read files or launch external programs.
|
||||
- Plugin-specific persistence formats must remain unchanged.
|
||||
- Write and observe a failing test before each production behavior.
|
||||
|
||||
---
|
||||
|
||||
### Task 1: Immutable history presentation model
|
||||
|
||||
**Files:**
|
||||
- Create: `src/main/java/com/example/workutils/system/ui/history/HistoryItem.java`
|
||||
- Test: `src/test/java/com/example/workutils/system/ui/history/HistoryItemTest.java`
|
||||
|
||||
**Interfaces:**
|
||||
- Produces: `HistoryItem(String index, String query, String filePath, String count, String timestamp)`.
|
||||
- Produces: `fileDisplay(int maxLength)` for bounded single-line display.
|
||||
|
||||
- [ ] Write tests proving short paths remain unchanged, long paths are ellipsized while retaining the filename, and constructor values cannot be null.
|
||||
- [ ] Run `.\mvnw.cmd -q -Dtest=HistoryItemTest test` and observe compilation failure because `HistoryItem` is absent.
|
||||
- [ ] Implement the immutable record and its display method.
|
||||
- [ ] Run the focused test and confirm it passes.
|
||||
|
||||
### Task 2: Reusable empty state
|
||||
|
||||
**Files:**
|
||||
- Create: `src/main/java/com/example/workutils/system/ui/EmptyStatePane.java`
|
||||
- Modify: `src/main/resources/css/light-theme.css`
|
||||
- Test: `src/test/java/com/example/workutils/system/ui/EmptyStateContentTest.java`
|
||||
|
||||
**Interfaces:**
|
||||
- Produces: `EmptyStatePane.Content(String title, String description, String actionLabel)`.
|
||||
- Produces: `EmptyStatePane(Content content, Runnable action, int fontSize)`.
|
||||
|
||||
- [ ] Write pure content-validation tests proving title is required and a blank action label is allowed only when no action is rendered.
|
||||
- [ ] Run the focused test and observe failure because the component is absent.
|
||||
- [ ] Implement the content model, pane, optional action button, and theme classes.
|
||||
- [ ] Run the focused test and confirm it passes.
|
||||
|
||||
### Task 3: Reusable export history pane
|
||||
|
||||
**Files:**
|
||||
- Create: `src/main/java/com/example/workutils/system/ui/history/HistoryFileCommands.java`
|
||||
- Create: `src/main/java/com/example/workutils/system/ui/history/ExportHistoryPane.java`
|
||||
- Test: `src/test/java/com/example/workutils/system/ui/history/HistoryFileCommandsTest.java`
|
||||
|
||||
**Interfaces:**
|
||||
- Consumes: `ObservableList<HistoryItem>`.
|
||||
- Consumes: `HistoryFileCommands` callbacks for open file, open editor, open folder, and copy path.
|
||||
- Produces: `ExportHistoryPane(String countColumnTitle, ObservableList<HistoryItem> items, HistoryFileCommands commands, int fontSize)`.
|
||||
|
||||
- [ ] Write tests proving `HistoryFileCommands` rejects missing callbacks and routes each command to the supplied consumer.
|
||||
- [ ] Run the focused test and observe failure because the type is absent.
|
||||
- [ ] Implement callback validation and the shared table, action cell, tooltip, context menu, and empty-state placeholder.
|
||||
- [ ] Run the focused test and confirm it passes.
|
||||
|
||||
### Task 4: Migrate Scanner
|
||||
|
||||
**Files:**
|
||||
- Modify: `src/main/java/com/example/workutils/biz/scanner/ScannerWindow.java`
|
||||
- Test: `src/test/java/com/example/workutils/biz/scanner/ScannerHistoryMappingTest.java`
|
||||
|
||||
**Interfaces:**
|
||||
- Consumes: `HistoryItem`, `ExportHistoryPane`, `HistoryFileCommands`.
|
||||
- Produces: package-visible `toHistoryItem(HistoryRow row)` for deterministic presentation mapping.
|
||||
|
||||
- [ ] Write a mapping test for index, query, path, match count, and timestamp.
|
||||
- [ ] Run the focused test and observe failure because the mapping method is absent.
|
||||
- [ ] Replace duplicated table/action-cell construction with `ExportHistoryPane`.
|
||||
- [ ] Run scanner tests and confirm they pass.
|
||||
|
||||
### Task 5: Migrate MyBatis SQL Export
|
||||
|
||||
**Files:**
|
||||
- Modify: `src/main/java/com/example/workutils/biz/mybatisexport/MyBatisExportWindow.java`
|
||||
- Test: `src/test/java/com/example/workutils/biz/mybatisexport/MyBatisExportHistoryMappingTest.java`
|
||||
|
||||
**Interfaces:**
|
||||
- Consumes: `HistoryItem`, `ExportHistoryPane`, `HistoryFileCommands`.
|
||||
- Produces: package-visible `toHistoryItem(HistoryRow row)`.
|
||||
|
||||
- [ ] Write a mapping test for index, query, path, export count, and timestamp.
|
||||
- [ ] Run the focused test and observe failure because the mapping method is absent.
|
||||
- [ ] Replace duplicated table/action-cell construction with `ExportHistoryPane`.
|
||||
- [ ] Run export tests and confirm they pass.
|
||||
|
||||
### Task 6: Verification
|
||||
|
||||
**Files:**
|
||||
- Modify only files required by failures found during verification.
|
||||
|
||||
- [ ] Run `.\mvnw.cmd -q test`.
|
||||
- [ ] Run `.\mvnw.cmd -q -DskipTests compile`.
|
||||
- [ ] Run `git diff --check`.
|
||||
- [ ] Confirm Scanner and MyBatis SQL Export no longer declare `buildActionCell`.
|
||||
- [ ] Inspect both pages without triggering scan, export, file-open, or delete side effects.
|
||||
Reference in New Issue
Block a user