From beeb329c3b4eb78fb95738d84920a7b8bb291b1a Mon Sep 17 00:00:00 2001 From: pikann Date: Tue, 12 May 2026 10:34:16 +0700 Subject: [PATCH 01/10] feat: update plugin-sdk-go dependency and enhance BDD scenario management --- backend/go.mod | 2 +- backend/go.sum | 4 +- backend/scenarios.go | 34 ++ frontend/src/BDDScenarioCard.tsx | 212 ----------- frontend/src/BDDScenariosSection.tsx | 541 ++++++++++++++++++++------- frontend/src/lib/interaction-api.ts | 85 +++++ frontend/src/lib/utils.ts | 3 + plugin.json | 2 +- 8 files changed, 536 insertions(+), 347 deletions(-) delete mode 100644 frontend/src/BDDScenarioCard.tsx create mode 100644 frontend/src/lib/interaction-api.ts create mode 100644 frontend/src/lib/utils.ts diff --git a/backend/go.mod b/backend/go.mod index 6d09bde..805bd6b 100644 --- a/backend/go.mod +++ b/backend/go.mod @@ -2,6 +2,6 @@ module github.com/Paca-AI/first-party/bdd go 1.24 -require github.com/Paca-AI/plugin-sdk-go v0.2.0-rc.3 +require github.com/Paca-AI/plugin-sdk-go v0.2.0-rc.5 require github.com/google/uuid v1.6.0 diff --git a/backend/go.sum b/backend/go.sum index 664e182..344bb56 100644 --- a/backend/go.sum +++ b/backend/go.sum @@ -1,4 +1,4 @@ -github.com/Paca-AI/plugin-sdk-go v0.2.0-rc.3 h1:2MFHmdVIKVo1/Cyo7GL3S/LsAFxpsqhJSAbTao+xNEw= -github.com/Paca-AI/plugin-sdk-go v0.2.0-rc.3/go.mod h1:5WeC6cSEf2wM1ovICZbDaVky9oi5id/Qpdfc5LDAQnw= +github.com/Paca-AI/plugin-sdk-go v0.2.0-rc.5 h1:xrEPnJLM2sdwtY/wRaGOdfeDPv5zPUpR8QZJ/w2nQVU= +github.com/Paca-AI/plugin-sdk-go v0.2.0-rc.5/go.mod h1:5WeC6cSEf2wM1ovICZbDaVky9oi5id/Qpdfc5LDAQnw= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= diff --git a/backend/scenarios.go b/backend/scenarios.go index ef5f724..6af0bc9 100644 --- a/backend/scenarios.go +++ b/backend/scenarios.go @@ -110,6 +110,8 @@ func (p *bddPlugin) createScenario(req *plugin.Request, res *plugin.Response) { CreatedAt: now, UpdatedAt: now, } + plugin.RecordActivity(taskID, projectID, req.Caller.UserID, "task.bdd_scenario.created", + map[string]any{"title": b.Title}) created(res, scenario) } @@ -225,6 +227,19 @@ func (p *bddPlugin) updateScenario(req *plugin.Request, res *plugin.Response) { res.Error(404, "bdd scenario not found") return } + // Collect which fields changed for the activity record. + var changedFields []string + if b.Given != nil && *b.Given != sc.str("given_text") { + changedFields = append(changedFields, "given") + } + if b.When != nil && *b.When != sc.str("when_text") { + changedFields = append(changedFields, "when") + } + if b.Then != nil && *b.Then != sc.str("then_text") { + changedFields = append(changedFields, "then") + } + plugin.RecordActivity(taskID, projectID, req.Caller.UserID, "task.bdd_scenario.updated", + map[string]any{"title": updTitle, "changes": changedFields}) ok(res, bddScenario{ ID: scenarioID, TaskID: taskID, @@ -247,6 +262,23 @@ func (p *bddPlugin) deleteScenario(req *plugin.Request, res *plugin.Response) { return } + // Fetch title before deletion for the activity record. + titleResult, err := p.db.Query( + `SELECT title FROM bdd_scenarios WHERE id = $1 AND task_id = $2`, + scenarioID, taskID, + ) + if err != nil { + p.log.Error("deleteScenario title fetch: " + err.Error()) + res.Error(500, "failed to delete bdd scenario") + return + } + if len(titleResult.Rows) == 0 { + res.Error(404, "bdd scenario not found") + return + } + scenarioTitleSC := newRowScanner(titleResult.Columns, titleResult.Rows[0]) + scenarioTitle := scenarioTitleSC.str("title") + affected, err := p.db.Exec( `DELETE FROM bdd_scenarios WHERE id = $1 AND task_id = $2`, scenarioID, taskID, @@ -260,6 +292,8 @@ func (p *bddPlugin) deleteScenario(req *plugin.Request, res *plugin.Response) { res.Error(404, "bdd scenario not found") return } + plugin.RecordActivity(taskID, projectID, req.Caller.UserID, "task.bdd_scenario.deleted", + map[string]any{"title": scenarioTitle}) res.NoContent() } diff --git a/frontend/src/BDDScenarioCard.tsx b/frontend/src/BDDScenarioCard.tsx deleted file mode 100644 index e095e1e..0000000 --- a/frontend/src/BDDScenarioCard.tsx +++ /dev/null @@ -1,212 +0,0 @@ -import { ChevronDown, ChevronUp, Pencil, Trash2, X, Check } from "lucide-react"; -import { useState } from "react"; -import type { BDDScenario } from "./types"; - -function cn(...classes: (string | boolean | undefined | null)[]): string { - return classes.filter(Boolean).join(" "); -} - -interface BDDScenarioCardProps { - scenario: BDDScenario; - canEdit: boolean; - onUpdate: ( - id: string, - patch: { title?: string; given?: string; when?: string; then?: string }, - ) => void; - onDelete: (id: string) => void; -} - -export function BDDScenarioCard({ - scenario, - canEdit, - onUpdate, - onDelete, -}: BDDScenarioCardProps) { - const [expanded, setExpanded] = useState(false); - const [editing, setEditing] = useState(false); - const [draft, setDraft] = useState({ - title: scenario.title, - given: scenario.given, - when: scenario.when, - then: scenario.then, - }); - - const startEdit = () => { - setDraft({ - title: scenario.title, - given: scenario.given, - when: scenario.when, - then: scenario.then, - }); - setEditing(true); - setExpanded(true); - }; - - const cancelEdit = () => { - setEditing(false); - setDraft({ - title: scenario.title, - given: scenario.given, - when: scenario.when, - then: scenario.then, - }); - }; - - const submitEdit = () => { - if (!draft.title.trim()) return; - onUpdate(scenario.id, { - title: draft.title.trim(), - given: draft.given, - when: draft.when, - then: draft.then, - }); - setEditing(false); - }; - - const hasContent = scenario.given || scenario.when || scenario.then; - - return ( -
- {/* Header */} -
- - - {canEdit && ( -
- {editing ? ( - <> - - - - ) : ( - <> - - - - )} -
- )} -
- - {/* Body */} - {(expanded || editing) && ( -
- {(["given", "when", "then"] as const).map((field) => ( -
- - {field} - - {editing ? ( -