mirror of
https://github.com/block/buzz.git
synced 2026-11-09 02:41:57 +00:00
**Category:** improvement **User Impact:** Users can scan what each workflow does and trigger, edit, duplicate, enable, disable, or delete it directly from the library. **Problem:** The workflow list buried common actions and did not expose each automation's trigger-to-action shape at a glance. **Solution:** Add a responsive workflow library with a persistent create tile, compact trigger/action diagrams, prominent workflow titles with supporting descriptions, and shared card actions while preserving existing detail, editor, and run-history entry points. Card toggles refresh both list and open-detail caches so status and definition stay consistent. <details> <summary>File changes</summary> **desktop/src/features/workflows/ui/WorkflowActionsMenu.tsx** Adds a shared card menu for trigger, edit, duplicate, enable/disable, and delete actions. **desktop/src/features/workflows/ui/WorkflowCard.tsx** Reworks cards around the prototype's visual hierarchy: color-coded trigger, action flow, sentence-case eyebrow, prominent title, supporting description, status, channel, and update date without a footer clock icon. **desktop/src/features/workflows/ui/WorkflowsView.tsx** Adds the responsive grid, create tile, mutation wiring, and list/detail cache invalidation. Container breakpoints keep cards two-across at medium widths and three-across in the 1280px desktop layout. **desktop/src/features/workflows/ui/workflowDefinition.ts** Adds immutable enabled-state updates plus narrow trigger and first-action readers used only to select card icons. **desktop/src/features/workflows/ui/workflowDefinition.test.mjs** Covers neutral icon selection, enabled-state immutability, and status presentation. **desktop/tests/e2e/workflows.spec.ts** Covers the create tile, title/description hierarchy, selected-card enable/disable consistency, and deterministic narrow/medium/wide captures while retaining existing action coverage. </details> ## Reproduction steps 1. Open **Workflows** and confirm the create tile stays first as cards flow from one to three columns with available width. 2. Confirm each card shows a sentence-case trigger eyebrow, prominent workflow title, supporting description when present, status, channel, and update date without a clock icon. 3. Open a card's overflow menu and trigger, edit, duplicate, enable/disable, or delete the workflow. 4. Leave the detail panel open while toggling and confirm its badge and JSON definition update with the card. ## Screenshots Real built E2E UI with representative workflow data at three viewport sizes. ### Narrow — 800 × 720  ### Medium — 1024 × 720  ### Wide — 1280 × 720  ### Card actions  --------- Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
51 lines
2.0 KiB
Rust
51 lines
2.0 KiB
Rust
use nostr::{EventBuilder, EventId, Kind};
|
|
|
|
use super::{check_content, tag};
|
|
|
|
/// Kind 30620 — replaceable workflow definition.
|
|
///
|
|
/// The `d` tag carries the workflow id; `h` tag carries the channel id; the
|
|
/// content is the YAML definition. Same (pubkey, d) replaces the prior version.
|
|
pub fn build_workflow_definition(
|
|
workflow_id: &str,
|
|
channel_id: &str,
|
|
yaml_definition: &str,
|
|
expected_revision: Option<&str>,
|
|
) -> Result<EventBuilder, String> {
|
|
check_content(yaml_definition)?;
|
|
let mut tags = vec![tag(vec!["d", workflow_id])?, tag(vec!["h", channel_id])?];
|
|
if let Some(revision) = expected_revision {
|
|
EventId::from_hex(revision).map_err(|_| "invalid workflow revision".to_string())?;
|
|
tags.push(tag(vec!["expected-revision", revision])?);
|
|
}
|
|
Ok(EventBuilder::new(Kind::Custom(30620), yaml_definition.to_string()).tags(tags))
|
|
}
|
|
|
|
/// Kind 5 — NIP-09 deletion targeting a kind:30620 workflow definition.
|
|
pub fn build_workflow_delete(
|
|
workflow_id: &str,
|
|
owner_pubkey_hex: &str,
|
|
) -> Result<EventBuilder, String> {
|
|
let coord = format!("30620:{owner_pubkey_hex}:{workflow_id}");
|
|
let tags = vec![tag(vec!["a", &coord])?];
|
|
Ok(EventBuilder::new(Kind::Custom(5), "").tags(tags))
|
|
}
|
|
|
|
/// Kind 46020 — trigger a workflow run by id.
|
|
pub fn build_workflow_trigger(workflow_id: &str) -> Result<EventBuilder, String> {
|
|
let tags = vec![tag(vec!["d", workflow_id])?];
|
|
Ok(EventBuilder::new(Kind::Custom(46020), "").tags(tags))
|
|
}
|
|
|
|
/// Kind 46030 — grant an approval token (with optional note).
|
|
pub fn build_approval_grant(token: &str, note: Option<&str>) -> Result<EventBuilder, String> {
|
|
let tags = vec![tag(vec!["t", token])?];
|
|
Ok(EventBuilder::new(Kind::Custom(46030), note.unwrap_or("")).tags(tags))
|
|
}
|
|
|
|
/// Kind 46031 — deny an approval token (with optional note).
|
|
pub fn build_approval_deny(token: &str, note: Option<&str>) -> Result<EventBuilder, String> {
|
|
let tags = vec![tag(vec!["t", token])?];
|
|
Ok(EventBuilder::new(Kind::Custom(46031), note.unwrap_or("")).tags(tags))
|
|
}
|