vibespot 0.4.4 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/conversion-guide.md +28 -0
- package/assets/design-guide.md +1 -0
- package/assets/hubspot-rules.md +16 -3
- package/assets/humanify-guide.md +459 -0
- package/dist/index.js +99 -33
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/ui/chat.js +199 -55
- package/ui/dashboard.js +19 -0
- package/ui/field-editor.js +9 -7
- package/ui/index.html +58 -31
- package/ui/setup.js +117 -36
- package/ui/styles.css +678 -243
package/ui/setup.js
CHANGED
|
@@ -21,11 +21,21 @@ const ENGINE_DISPLAY_NAMES = {
|
|
|
21
21
|
|
|
22
22
|
async function initSetup() {
|
|
23
23
|
try {
|
|
24
|
+
// Show loading spinner in rail while fetching
|
|
25
|
+
const railItems = document.getElementById("project-rail-items");
|
|
26
|
+
if (railItems) {
|
|
27
|
+
railItems.innerHTML = `
|
|
28
|
+
<div class="project-rail__loading">
|
|
29
|
+
<div class="setup__spinner"></div>
|
|
30
|
+
<span>Loading projects...</span>
|
|
31
|
+
</div>`;
|
|
32
|
+
}
|
|
33
|
+
|
|
24
34
|
const res = await fetch("/api/setup");
|
|
25
35
|
const info = await res.json();
|
|
26
36
|
|
|
27
|
-
// Populate
|
|
28
|
-
|
|
37
|
+
// Populate the project rail with all projects
|
|
38
|
+
populateProjectRail(info);
|
|
29
39
|
|
|
30
40
|
// Auto-select engine if available but not yet chosen
|
|
31
41
|
if (info.availableEngines && info.availableEngines.length > 0 && !info.activeEngine) {
|
|
@@ -118,19 +128,14 @@ async function saveAlertApiKey(key) {
|
|
|
118
128
|
}
|
|
119
129
|
|
|
120
130
|
// ---------------------------------------------------------------------------
|
|
121
|
-
//
|
|
131
|
+
// Project list helpers
|
|
122
132
|
// ---------------------------------------------------------------------------
|
|
123
133
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
const countEl = document.getElementById("sidebar-project-count");
|
|
127
|
-
list.innerHTML = "";
|
|
128
|
-
|
|
129
|
-
// Build a combined, deduplicated list of projects
|
|
134
|
+
/** Dedup sessions + local themes into a single project list */
|
|
135
|
+
function deduplicateProjects(info) {
|
|
130
136
|
const projects = [];
|
|
131
137
|
const seen = new Set();
|
|
132
138
|
|
|
133
|
-
// Add sessions first (most recent)
|
|
134
139
|
for (const s of info.sessions || []) {
|
|
135
140
|
if (!seen.has(s.themeName)) {
|
|
136
141
|
seen.add(s.themeName);
|
|
@@ -139,51 +144,75 @@ function populateSidebar(info) {
|
|
|
139
144
|
type: "session",
|
|
140
145
|
sessionId: s.id,
|
|
141
146
|
updatedAt: s.updatedAt,
|
|
147
|
+
moduleCount: s.moduleCount ?? null,
|
|
148
|
+
templateCount: s.templateCount ?? null,
|
|
142
149
|
});
|
|
143
150
|
}
|
|
144
151
|
}
|
|
145
152
|
|
|
146
|
-
|
|
147
|
-
|
|
153
|
+
for (const t of info.localThemes || []) {
|
|
154
|
+
const name = typeof t === "string" ? t : t.name;
|
|
148
155
|
if (!seen.has(name)) {
|
|
149
156
|
seen.add(name);
|
|
150
|
-
projects.push({
|
|
157
|
+
projects.push({
|
|
158
|
+
name,
|
|
159
|
+
type: "local",
|
|
160
|
+
sessionId: null,
|
|
161
|
+
updatedAt: null,
|
|
162
|
+
moduleCount: typeof t === "object" ? t.moduleCount ?? null : null,
|
|
163
|
+
templateCount: null,
|
|
164
|
+
});
|
|
151
165
|
}
|
|
152
166
|
}
|
|
153
167
|
|
|
154
|
-
|
|
168
|
+
return projects;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// ---------------------------------------------------------------------------
|
|
172
|
+
// Collapsible Project Rail (expanded on setup, collapsed on dashboard/chat)
|
|
173
|
+
// ---------------------------------------------------------------------------
|
|
174
|
+
|
|
175
|
+
const railTooltip = document.getElementById("project-rail-tooltip");
|
|
176
|
+
|
|
177
|
+
function populateProjectRail(info) {
|
|
178
|
+
const rail = document.getElementById("project-rail-items");
|
|
179
|
+
const countEl = document.getElementById("rail-project-count");
|
|
180
|
+
if (!rail) return;
|
|
181
|
+
rail.innerHTML = "";
|
|
182
|
+
|
|
183
|
+
const projects = deduplicateProjects(info);
|
|
184
|
+
if (countEl) countEl.textContent = projects.length;
|
|
155
185
|
|
|
156
186
|
if (projects.length === 0) {
|
|
157
|
-
|
|
187
|
+
rail.innerHTML = '<div class="project-rail__empty">No projects yet.<br>Create one to get started.</div>';
|
|
158
188
|
return;
|
|
159
189
|
}
|
|
160
190
|
|
|
161
191
|
for (const p of projects) {
|
|
162
192
|
const item = document.createElement("div");
|
|
163
|
-
item.className = "
|
|
193
|
+
item.className = "project-rail__item";
|
|
194
|
+
item.dataset.name = p.name;
|
|
195
|
+
|
|
164
196
|
const initial = p.name.charAt(0).toUpperCase();
|
|
165
197
|
const meta = p.updatedAt ? timeAgo(p.updatedAt) : "on disk";
|
|
166
198
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
});
|
|
183
|
-
item.appendChild(openBtn);
|
|
184
|
-
|
|
199
|
+
// Bubble (always visible — in collapsed mode this is the only thing shown)
|
|
200
|
+
const bubble = document.createElement("div");
|
|
201
|
+
bubble.className = "project-rail__item-bubble";
|
|
202
|
+
bubble.textContent = initial;
|
|
203
|
+
item.appendChild(bubble);
|
|
204
|
+
|
|
205
|
+
// Info (visible when expanded via CSS)
|
|
206
|
+
const infoEl = document.createElement("div");
|
|
207
|
+
infoEl.className = "project-rail__item-info";
|
|
208
|
+
infoEl.innerHTML = `
|
|
209
|
+
<span class="project-rail__item-name">${esc(p.name)}</span>
|
|
210
|
+
<span class="project-rail__item-meta">${meta}</span>`;
|
|
211
|
+
item.appendChild(infoEl);
|
|
212
|
+
|
|
213
|
+
// Delete button (visible when expanded + hover)
|
|
185
214
|
const delBtn = document.createElement("button");
|
|
186
|
-
delBtn.className = "
|
|
215
|
+
delBtn.className = "project-rail__item-delete";
|
|
187
216
|
delBtn.innerHTML = "×";
|
|
188
217
|
delBtn.title = "Delete project";
|
|
189
218
|
delBtn.addEventListener("click", (e) => {
|
|
@@ -192,10 +221,57 @@ function populateSidebar(info) {
|
|
|
192
221
|
});
|
|
193
222
|
item.appendChild(delBtn);
|
|
194
223
|
|
|
195
|
-
|
|
224
|
+
// Tooltip (only when collapsed — skip when expanded since name is visible)
|
|
225
|
+
item.addEventListener("mouseenter", () => {
|
|
226
|
+
const railEl = document.getElementById("project-rail");
|
|
227
|
+
if (railEl && railEl.classList.contains("project-rail--expanded")) return;
|
|
228
|
+
|
|
229
|
+
let stats = "";
|
|
230
|
+
if (p.moduleCount != null) {
|
|
231
|
+
stats = p.moduleCount + " module" + (p.moduleCount !== 1 ? "s" : "");
|
|
232
|
+
if (p.templateCount > 1) stats += " \u00b7 " + p.templateCount + " templates";
|
|
233
|
+
stats += p.updatedAt ? " \u00b7 " + timeAgo(p.updatedAt) : " \u00b7 on disk";
|
|
234
|
+
} else {
|
|
235
|
+
stats = p.updatedAt ? timeAgo(p.updatedAt) : "on disk";
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
railTooltip.innerHTML =
|
|
239
|
+
'<div class="project-rail__tooltip-name">' + esc(p.name) + "</div>" +
|
|
240
|
+
'<div class="project-rail__tooltip-stats">' + stats + "</div>";
|
|
241
|
+
|
|
242
|
+
const rect = item.getBoundingClientRect();
|
|
243
|
+
railTooltip.style.top = rect.top + "px";
|
|
244
|
+
railTooltip.classList.add("project-rail__tooltip--visible");
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
item.addEventListener("mouseleave", () => {
|
|
248
|
+
railTooltip.classList.remove("project-rail__tooltip--visible");
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
// Click to open
|
|
252
|
+
item.addEventListener("click", () => {
|
|
253
|
+
if (p.sessionId) resumeSession(p.sessionId);
|
|
254
|
+
else openTheme(p.name);
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
rail.appendChild(item);
|
|
196
258
|
}
|
|
259
|
+
|
|
260
|
+
updateRailActive();
|
|
197
261
|
}
|
|
198
262
|
|
|
263
|
+
function updateRailActive() {
|
|
264
|
+
const current = currentAppTheme || currentDashboardTheme || "";
|
|
265
|
+
document.querySelectorAll(".project-rail__item").forEach((btn) => {
|
|
266
|
+
btn.classList.toggle("project-rail__item--active", btn.dataset.name === current);
|
|
267
|
+
});
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
// "+" button → go to setup
|
|
271
|
+
document.getElementById("project-rail-add")?.addEventListener("click", () => {
|
|
272
|
+
showSetup();
|
|
273
|
+
});
|
|
274
|
+
|
|
199
275
|
// ---------------------------------------------------------------------------
|
|
200
276
|
// Delete project confirmation
|
|
201
277
|
// ---------------------------------------------------------------------------
|
|
@@ -568,6 +644,7 @@ function showApp(themeName) {
|
|
|
568
644
|
if (typeof showDashboard === "function") {
|
|
569
645
|
currentAppTheme = themeName;
|
|
570
646
|
showDashboard(themeName);
|
|
647
|
+
updateRailActive();
|
|
571
648
|
} else {
|
|
572
649
|
// Fallback if dashboard.js not loaded
|
|
573
650
|
showAppDirect(themeName);
|
|
@@ -581,6 +658,7 @@ function showApp(themeName) {
|
|
|
581
658
|
function showAppDirect(themeName) {
|
|
582
659
|
setupScreen.classList.add("hidden");
|
|
583
660
|
document.getElementById("setup-topbar").classList.add("hidden");
|
|
661
|
+
document.getElementById("project-rail")?.classList.remove("project-rail--expanded");
|
|
584
662
|
if (typeof hideDashboard === "function") hideDashboard();
|
|
585
663
|
appScreen.classList.remove("hidden");
|
|
586
664
|
document.getElementById("theme-name").textContent = themeName;
|
|
@@ -600,6 +678,7 @@ function showAppDirect(themeName) {
|
|
|
600
678
|
if (typeof refreshPreview === "function") {
|
|
601
679
|
refreshPreview();
|
|
602
680
|
}
|
|
681
|
+
updateRailActive();
|
|
603
682
|
}
|
|
604
683
|
|
|
605
684
|
function showSetup() {
|
|
@@ -607,9 +686,11 @@ function showSetup() {
|
|
|
607
686
|
if (typeof hideDashboard === "function") hideDashboard();
|
|
608
687
|
setupScreen.classList.remove("hidden");
|
|
609
688
|
document.getElementById("setup-topbar").classList.remove("hidden");
|
|
689
|
+
document.getElementById("project-rail")?.classList.add("project-rail--expanded");
|
|
610
690
|
currentAppTheme = "";
|
|
611
691
|
|
|
612
692
|
hideLoading();
|
|
693
|
+
updateRailActive();
|
|
613
694
|
|
|
614
695
|
if (location.hash && location.hash !== "#/") {
|
|
615
696
|
history.pushState(null, "", "#/");
|