From 87bafc9d74d25a3109ecb92818220dec510776b7 Mon Sep 17 00:00:00 2001 From: Jeff Emmett Date: Thu, 2 Apr 2026 15:08:43 -0700 Subject: [PATCH] feat(rtime): port 14 missing hcc-mem-staging features to rTime module - Connection & exec state persistence (POST /api/connections, PUT exec-state) - Exec step detail forms for all 5 types (venue, comms, notes, prep, launch) - Step state machine fix: click to expand/collapse, action button to complete - Task editor links field with dynamic add/remove and server persistence - Cyclos-aware launch handler with fallback to demo celebration - Fix dead EXEC_STEPS[taskId] lookup, auto-place first task on empty canvas - DID display truncation for unreadable DIDs in intent routes - Dark/light theme toggle with localStorage persistence - Hex hover stroke, commitment description in hex nodes, edit pencil on tasks Co-Authored-By: Claude Opus 4.6 --- modules/rtime/components/folk-timebank-app.ts | 446 +++++++++++++++++- modules/rtime/intent-routes.ts | 7 +- 2 files changed, 429 insertions(+), 24 deletions(-) diff --git a/modules/rtime/components/folk-timebank-app.ts b/modules/rtime/components/folk-timebank-app.ts index 6f1a72a..38603f9 100644 --- a/modules/rtime/components/folk-timebank-app.ts +++ b/modules/rtime/components/folk-timebank-app.ts @@ -292,6 +292,10 @@ class FolkTimebankApp extends HTMLElement { // Exec state private execStepStates: Record> = {}; + private _restoredConnections: { fromCommitmentId: string; toTaskId: string; skill: string }[] = []; + private _currentExecTaskId: string | null = null; + private _cyclosMembers: { id: string; name: string; balance: number }[] = []; + private _theme: 'dark' | 'light' = 'dark'; constructor() { super(); @@ -309,7 +313,9 @@ class FolkTimebankApp extends HTMLElement { this.space = this.getAttribute('space') || 'demo'; this.currentView = (this.getAttribute('view') as any) || 'pool'; this.dpr = window.devicePixelRatio || 1; + this._theme = (localStorage.getItem('rtime-theme') as 'dark' | 'light') || 'dark'; this.render(); + this.applyTheme(); this.setupPool(); this.setupWeave(); this.setupCollaborate(); @@ -329,6 +335,16 @@ class FolkTimebankApp extends HTMLElement { return token ? { Authorization: `Bearer ${token}` } : {}; } + private applyTheme() { + if (this._theme === 'light') { + this.setAttribute('data-theme', 'light'); + } else { + this.removeAttribute('data-theme'); + } + const btn = this.shadow.getElementById('themeToggle'); + if (btn) btn.textContent = this._theme === 'dark' ? '☀' : '☾'; + } + disconnectedCallback() { if (this.animFrame) cancelAnimationFrame(this.animFrame); } @@ -347,13 +363,49 @@ class FolkTimebankApp extends HTMLElement { if (tResp.ok) { const tData = await tResp.json(); this.tasks = tData.tasks || []; + // Restore connections + this._restoredConnections = (tData.connections || []).map((cn: any) => ({ + fromCommitmentId: cn.fromCommitmentId, + toTaskId: cn.toTaskId, + skill: cn.skill, + })); + // Restore exec states + for (const es of (tData.execStates || [])) { + if (es.taskId && es.steps) { + this.execStepStates[es.taskId] = {}; + for (const [k, v] of Object.entries(es.steps)) { + this.execStepStates[es.taskId][Number(k)] = v as string; + } + } + } } } catch { // Offline — use empty state } + + // Fetch Cyclos members (silent failure → demo mode) + try { + const mResp = await fetch(`${base}/api/cyclos/members`); + if (mResp.ok) { + const mData = await mResp.json(); + this._cyclosMembers = (mData.members || []).map((m: any) => ({ id: m.id, name: m.name, balance: m.balance || 0 })); + } + } catch { /* Cyclos not configured — demo mode */ } + this.buildOrbs(); this.updateStats(); this.rebuildSidebar(); + this.applyRestoredConnections(); + + // Auto-place first task if canvas is empty + if (this.weaveNodes.length === 0 && this.tasks.length > 0) { + const svgRect = this.svgEl?.getBoundingClientRect(); + const x = svgRect ? svgRect.width * 0.55 : 400; + const y = svgRect ? svgRect.height * 0.2 : 80; + this.weaveNodes.push(this.mkTaskNode(this.tasks[0], x - TASK_W / 2, y)); + this.renderAll(); + this.rebuildSidebar(); + } } private render() { @@ -363,6 +415,7 @@ class FolkTimebankApp extends HTMLElement {
Commitment Pool
Weaving Dashboard
Collaborate
+
0 hours available
@@ -538,6 +591,10 @@ class FolkTimebankApp extends HTMLElement {
+
+ + +