vibespot 1.0.2 → 1.0.4
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/README.md +2 -1
- package/dist/index.js +98 -98
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/ui/chat.js +11 -12
- package/ui/dashboard.js +59 -3
- package/ui/index.html +1 -0
- package/ui/styles.css +1 -7
package/package.json
CHANGED
package/ui/chat.js
CHANGED
|
@@ -259,6 +259,13 @@ function ensurePipelineBubble() {
|
|
|
259
259
|
scrollToBottom();
|
|
260
260
|
}
|
|
261
261
|
|
|
262
|
+
function markStepDone(el) {
|
|
263
|
+
el.classList.add("pipeline-step--done");
|
|
264
|
+
el.classList.remove("pipeline-step--active");
|
|
265
|
+
const icon = el.querySelector(".pipeline-step__icon");
|
|
266
|
+
if (icon) icon.textContent = "✓";
|
|
267
|
+
}
|
|
268
|
+
|
|
262
269
|
function handleAgentStep(msg) {
|
|
263
270
|
ensurePipelineBubble();
|
|
264
271
|
|
|
@@ -267,15 +274,13 @@ function handleAgentStep(msg) {
|
|
|
267
274
|
const existingStep = pipelineStepsEl.querySelector(`[data-step="${CSS.escape(msg.step)}"]:not(.pipeline-step--done)`);
|
|
268
275
|
if (existingStep) {
|
|
269
276
|
// Mark the current one as done and create a fresh one below
|
|
270
|
-
existingStep
|
|
271
|
-
existingStep.classList.remove("pipeline-step--active");
|
|
277
|
+
markStepDone(existingStep);
|
|
272
278
|
} else {
|
|
273
279
|
// Mark all other active steps as done
|
|
274
280
|
const existing = pipelineStepsEl.querySelectorAll(".pipeline-step");
|
|
275
281
|
existing.forEach((el) => {
|
|
276
282
|
if (!el.classList.contains("pipeline-step--done")) {
|
|
277
|
-
el
|
|
278
|
-
el.classList.remove("pipeline-step--active");
|
|
283
|
+
markStepDone(el);
|
|
279
284
|
}
|
|
280
285
|
});
|
|
281
286
|
}
|
|
@@ -356,10 +361,7 @@ function handlePipelineComplete(msg) {
|
|
|
356
361
|
|
|
357
362
|
// Mark all steps as done (search whole bubble since quality_check is outside pipelineStepsEl)
|
|
358
363
|
const bubble = streamingMsgEl || pipelineBubbleEl;
|
|
359
|
-
bubble.querySelectorAll(".pipeline-step").forEach((el) =>
|
|
360
|
-
el.classList.add("pipeline-step--done");
|
|
361
|
-
el.classList.remove("pipeline-step--active");
|
|
362
|
-
});
|
|
364
|
+
bubble.querySelectorAll(".pipeline-step").forEach((el) => markStepDone(el));
|
|
363
365
|
|
|
364
366
|
// Add completion stats after the last element in the bubble
|
|
365
367
|
const stats = document.createElement("div");
|
|
@@ -397,10 +399,7 @@ function handlePipelinePartial(msg) {
|
|
|
397
399
|
if (timerEl) timerEl.remove();
|
|
398
400
|
|
|
399
401
|
const bubble = streamingMsgEl || pipelineBubbleEl;
|
|
400
|
-
bubble.querySelectorAll(".pipeline-step").forEach((el) =>
|
|
401
|
-
el.classList.add("pipeline-step--done");
|
|
402
|
-
el.classList.remove("pipeline-step--active");
|
|
403
|
-
});
|
|
402
|
+
bubble.querySelectorAll(".pipeline-step").forEach((el) => markStepDone(el));
|
|
404
403
|
|
|
405
404
|
const stats = document.createElement("div");
|
|
406
405
|
stats.className = "pipeline-stats pipeline-stats--partial";
|
package/ui/dashboard.js
CHANGED
|
@@ -269,6 +269,31 @@ function closeModulePreview() {
|
|
|
269
269
|
// Close button for module preview
|
|
270
270
|
document.getElementById("dashboard-preview-close").addEventListener("click", closeModulePreview);
|
|
271
271
|
|
|
272
|
+
// Delete button for module preview
|
|
273
|
+
document.getElementById("dashboard-preview-delete").addEventListener("click", async () => {
|
|
274
|
+
const moduleName = activePreviewModule;
|
|
275
|
+
if (!moduleName) return;
|
|
276
|
+
|
|
277
|
+
const ok = await vibeConfirm(
|
|
278
|
+
`Delete module "${moduleName}"?`,
|
|
279
|
+
"This will remove it from all templates and delete it from disk.",
|
|
280
|
+
{ confirmLabel: "Delete" }
|
|
281
|
+
);
|
|
282
|
+
if (!ok) return;
|
|
283
|
+
|
|
284
|
+
try {
|
|
285
|
+
await fetch("/api/modules", {
|
|
286
|
+
method: "DELETE",
|
|
287
|
+
headers: { "Content-Type": "application/json" },
|
|
288
|
+
body: JSON.stringify({ moduleName, deleteEntirely: true }),
|
|
289
|
+
});
|
|
290
|
+
closeModulePreview();
|
|
291
|
+
await refreshDashboard();
|
|
292
|
+
} catch (err) {
|
|
293
|
+
await vibeAlert("Failed to delete module: " + err.message, "Error");
|
|
294
|
+
}
|
|
295
|
+
});
|
|
296
|
+
|
|
272
297
|
// ---------------------------------------------------------------------------
|
|
273
298
|
// Brand assets
|
|
274
299
|
// ---------------------------------------------------------------------------
|
|
@@ -447,14 +472,16 @@ async function openTemplate(templateId) {
|
|
|
447
472
|
}
|
|
448
473
|
|
|
449
474
|
async function confirmDeleteTemplate(templateId) {
|
|
450
|
-
const
|
|
451
|
-
if (!
|
|
475
|
+
const result = await vibeDeleteTemplateDialog();
|
|
476
|
+
if (!result) return; // cancelled
|
|
477
|
+
|
|
478
|
+
const deleteModules = result === "with_modules";
|
|
452
479
|
|
|
453
480
|
try {
|
|
454
481
|
await fetch("/api/templates", {
|
|
455
482
|
method: "DELETE",
|
|
456
483
|
headers: { "Content-Type": "application/json" },
|
|
457
|
-
body: JSON.stringify({ templateId }),
|
|
484
|
+
body: JSON.stringify({ templateId, deleteModules }),
|
|
458
485
|
});
|
|
459
486
|
await refreshDashboard();
|
|
460
487
|
} catch (err) {
|
|
@@ -462,6 +489,35 @@ async function confirmDeleteTemplate(templateId) {
|
|
|
462
489
|
}
|
|
463
490
|
}
|
|
464
491
|
|
|
492
|
+
/**
|
|
493
|
+
* Three-option dialog: delete template only, delete template + modules, or cancel.
|
|
494
|
+
* @returns {Promise<"template_only"|"with_modules"|null>}
|
|
495
|
+
*/
|
|
496
|
+
function vibeDeleteTemplateDialog() {
|
|
497
|
+
return new Promise((resolve) => {
|
|
498
|
+
const overlay = document.createElement("div");
|
|
499
|
+
overlay.className = "confirm-overlay";
|
|
500
|
+
overlay.innerHTML = `
|
|
501
|
+
<div class="confirm-dialog">
|
|
502
|
+
<div class="confirm-dialog__title">Delete template?</div>
|
|
503
|
+
<p class="confirm-dialog__warn">This cannot be undone.</p>
|
|
504
|
+
<div class="confirm-dialog__actions" style="flex-direction:column;gap:8px">
|
|
505
|
+
<button class="btn btn--danger" data-action="with_modules" style="width:100%">Delete template and its modules</button>
|
|
506
|
+
<button class="btn btn--secondary" data-action="template_only" style="width:100%">Delete template only (keep modules)</button>
|
|
507
|
+
<button class="btn btn--secondary" data-action="cancel" style="width:100%">Cancel</button>
|
|
508
|
+
</div>
|
|
509
|
+
</div>
|
|
510
|
+
`;
|
|
511
|
+
document.body.appendChild(overlay);
|
|
512
|
+
|
|
513
|
+
const close = (val) => { overlay.remove(); resolve(val); };
|
|
514
|
+
overlay.querySelector('[data-action="with_modules"]').addEventListener("click", () => close("with_modules"));
|
|
515
|
+
overlay.querySelector('[data-action="template_only"]').addEventListener("click", () => close("template_only"));
|
|
516
|
+
overlay.querySelector('[data-action="cancel"]').addEventListener("click", () => close(null));
|
|
517
|
+
overlay.addEventListener("click", (e) => { if (e.target === overlay) close(null); });
|
|
518
|
+
});
|
|
519
|
+
}
|
|
520
|
+
|
|
465
521
|
async function cloneTemplateAction(templateId) {
|
|
466
522
|
const label = prompt("Name for the cloned template:");
|
|
467
523
|
if (!label) return;
|
package/ui/index.html
CHANGED
|
@@ -312,6 +312,7 @@
|
|
|
312
312
|
<div class="dashboard__module-preview-header">
|
|
313
313
|
<span class="dashboard__module-preview-name" id="dashboard-preview-name"></span>
|
|
314
314
|
<span class="dashboard__module-preview-used" id="dashboard-preview-used"></span>
|
|
315
|
+
<button class="btn btn--danger btn--sm dashboard__module-preview-delete" id="dashboard-preview-delete">Delete module</button>
|
|
315
316
|
<button class="dashboard__module-preview-close" id="dashboard-preview-close">×</button>
|
|
316
317
|
</div>
|
|
317
318
|
<iframe class="dashboard__module-preview-frame" id="dashboard-preview-frame" sandbox="allow-scripts allow-same-origin"></iframe>
|
package/ui/styles.css
CHANGED
|
@@ -2150,17 +2150,11 @@ body { display: flex; }
|
|
|
2150
2150
|
|
|
2151
2151
|
.pipeline-step--done .pipeline-step__icon {
|
|
2152
2152
|
animation: none;
|
|
2153
|
-
visibility: hidden;
|
|
2154
|
-
width: 0;
|
|
2155
2153
|
display: inline-block;
|
|
2156
|
-
position: relative;
|
|
2157
2154
|
}
|
|
2158
2155
|
|
|
2159
2156
|
.pipeline-step--done .pipeline-step__icon::after {
|
|
2160
|
-
content: "
|
|
2161
|
-
font-size: 13px;
|
|
2162
|
-
visibility: visible;
|
|
2163
|
-
position: relative;
|
|
2157
|
+
content: "";
|
|
2164
2158
|
}
|
|
2165
2159
|
|
|
2166
2160
|
.pipeline-step__decision {
|