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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vibespot",
3
- "version": "1.0.2",
3
+ "version": "1.0.4",
4
4
  "description": "AI-powered HubSpot CMS landing page builder — vibe coding & React converter",
5
5
  "type": "module",
6
6
  "bin": {
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.classList.add("pipeline-step--done");
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.classList.add("pipeline-step--done");
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 ok = await vibeConfirm("Delete this template?", "This cannot be undone.", { confirmLabel: "Delete" });
451
- if (!ok) return;
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">&times;</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 {