vibespot 0.7.1 → 0.9.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/dist/index.js +160 -99
- package/dist/index.js.map +1 -1
- package/package.json +5 -1
- package/ui/chat.js +175 -7
- package/ui/index.html +58 -31
- package/ui/settings.js +456 -238
- package/ui/setup.js +205 -18
- package/ui/styles.css +343 -0
- package/ui/upload-panel.js +99 -35
package/ui/upload-panel.js
CHANGED
|
@@ -23,34 +23,45 @@ async function startUpload() {
|
|
|
23
23
|
if (uploadBtn) { uploadBtn.textContent = "Deploy"; uploadBtn.disabled = false; }
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
// Fetch portal info and check
|
|
26
|
+
// Fetch portal info and check readiness
|
|
27
27
|
try {
|
|
28
28
|
const res = await fetch("/api/settings/status");
|
|
29
29
|
const data = await res.json();
|
|
30
|
+
const uploadMode = data.config?.hubspotUploadMode || "api";
|
|
30
31
|
let hs = data.environment?.tools?.hubspot;
|
|
31
32
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
const
|
|
35
|
-
if (
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
33
|
+
if (uploadMode === "api") {
|
|
34
|
+
// API mode — just need a PAK configured
|
|
35
|
+
const accounts = data.config?.hubspotAccounts || [];
|
|
36
|
+
if (accounts.length === 0) {
|
|
37
|
+
const authed = await showHubSpotSetupDialog("auth");
|
|
38
|
+
if (!authed) { resetUploadBtn(); return; }
|
|
39
|
+
const recheck = await fetch("/api/settings/status").then((r) => r.json());
|
|
40
|
+
hs = recheck.environment?.tools?.hubspot;
|
|
41
|
+
}
|
|
42
|
+
// Confirm portal
|
|
43
|
+
if (hs && hs.authenticated && hs.portalName) {
|
|
44
|
+
const confirmed = await confirmUpload(hs.portalName, hs.portalId);
|
|
45
|
+
if (!confirmed) { resetUploadBtn(); return; }
|
|
46
|
+
}
|
|
47
|
+
} else {
|
|
48
|
+
// CLI mode — need CLI installed and authed
|
|
49
|
+
if (!hs || !hs.found) {
|
|
50
|
+
const installed = await showHubSpotSetupDialog("install");
|
|
51
|
+
if (!installed) { resetUploadBtn(); return; }
|
|
52
|
+
const recheck = await fetch("/api/settings/status").then((r) => r.json());
|
|
53
|
+
hs = recheck.environment?.tools?.hubspot;
|
|
54
|
+
}
|
|
55
|
+
if (hs && hs.found && !hs.authenticated) {
|
|
56
|
+
const authed = await showHubSpotSetupDialog("auth");
|
|
57
|
+
if (!authed) { resetUploadBtn(); return; }
|
|
58
|
+
const recheck = await fetch("/api/settings/status").then((r) => r.json());
|
|
59
|
+
hs = recheck.environment?.tools?.hubspot;
|
|
60
|
+
}
|
|
61
|
+
if (hs && hs.authenticated && hs.portalName) {
|
|
62
|
+
const confirmed = await confirmUpload(hs.portalName, hs.portalId);
|
|
63
|
+
if (!confirmed) { resetUploadBtn(); return; }
|
|
64
|
+
}
|
|
54
65
|
}
|
|
55
66
|
} catch {
|
|
56
67
|
// If we can't detect, proceed and let the upload fail with a meaningful error
|
|
@@ -125,8 +136,8 @@ function showHubSpotSetupDialog(mode) {
|
|
|
125
136
|
<div class="confirm-dialog__title">Connect your HubSpot account</div>
|
|
126
137
|
<p class="confirm-dialog__detail">Create a Personal Access Key to connect vibeSpot to your HubSpot portal.</p>
|
|
127
138
|
<ol class="hs-setup__steps">
|
|
128
|
-
<li>Open <a href="https://app.hubspot.com/
|
|
129
|
-
<li>
|
|
139
|
+
<li>Open <a href="https://app.hubspot.com/l/personal-access-key" target="_blank" rel="noopener">HubSpot Personal Access Key</a></li>
|
|
140
|
+
<li>Create a key with the <strong>Content</strong> scope enabled</li>
|
|
130
141
|
<li>Paste the key below</li>
|
|
131
142
|
</ol>
|
|
132
143
|
<input type="password" class="confirm-dialog__input" id="hs-pak-input" placeholder="pat-na1-..." />
|
|
@@ -206,7 +217,9 @@ function confirmUpload(portalName, portalId) {
|
|
|
206
217
|
<div class="confirm-dialog__title">Deploy to HubSpot?</div>
|
|
207
218
|
<p class="confirm-dialog__detail">
|
|
208
219
|
Uploading to <strong>${esc(portalName)}</strong>${portalId ? ` (${esc(portalId)})` : ""}
|
|
220
|
+
<button class="btn-link" id="confirm-upload-change">Change</button>
|
|
209
221
|
</p>
|
|
222
|
+
<div id="confirm-upload-switch" class="hidden" style="margin:12px 0"></div>
|
|
210
223
|
<div class="confirm-dialog__actions">
|
|
211
224
|
<button class="btn btn--secondary" id="confirm-upload-cancel">Cancel</button>
|
|
212
225
|
<button class="btn btn--primary" id="confirm-upload-go">Deploy</button>
|
|
@@ -215,16 +228,57 @@ function confirmUpload(portalName, portalId) {
|
|
|
215
228
|
`;
|
|
216
229
|
document.body.appendChild(overlay);
|
|
217
230
|
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
});
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
231
|
+
const close = (val) => { overlay.remove(); resolve(val); };
|
|
232
|
+
|
|
233
|
+
document.getElementById("confirm-upload-cancel").addEventListener("click", () => close(false));
|
|
234
|
+
overlay.addEventListener("click", (e) => { if (e.target === overlay) close(false); });
|
|
235
|
+
document.getElementById("confirm-upload-go").addEventListener("click", () => close(true));
|
|
236
|
+
|
|
237
|
+
document.getElementById("confirm-upload-change").addEventListener("click", async () => {
|
|
238
|
+
const switchArea = document.getElementById("confirm-upload-switch");
|
|
239
|
+
if (!switchArea.classList.contains("hidden")) { switchArea.classList.add("hidden"); return; }
|
|
240
|
+
switchArea.classList.remove("hidden");
|
|
241
|
+
switchArea.innerHTML = '<span class="upload-spinner"></span> Loading accounts...';
|
|
242
|
+
|
|
243
|
+
try {
|
|
244
|
+
const res = await fetch("/api/settings/status");
|
|
245
|
+
const data = await res.json();
|
|
246
|
+
const accounts = data.config?.hubspotAccounts || [];
|
|
247
|
+
const activeId = data.config?.activeHubSpotAccount;
|
|
248
|
+
|
|
249
|
+
let html = '<div style="display:flex;flex-direction:column;gap:6px">';
|
|
250
|
+
for (const acct of accounts) {
|
|
251
|
+
const isActive = acct.portalId === activeId;
|
|
252
|
+
html += `<button class="btn btn--${isActive ? "primary" : "secondary"} confirm-acct-btn" data-portal="${esc(acct.portalId)}" style="text-align:left;padding:6px 12px;font-size:13px">${esc(acct.portalName || acct.portalId)} (${esc(acct.portalId)})${isActive ? " ✓" : ""}</button>`;
|
|
253
|
+
}
|
|
254
|
+
html += `<button class="btn btn--secondary confirm-acct-btn" data-portal="__new" style="text-align:left;padding:6px 12px;font-size:13px">+ Add another account</button>`;
|
|
255
|
+
html += '</div>';
|
|
256
|
+
switchArea.innerHTML = html;
|
|
257
|
+
|
|
258
|
+
switchArea.querySelectorAll(".confirm-acct-btn").forEach((btn) => {
|
|
259
|
+
btn.addEventListener("click", async () => {
|
|
260
|
+
const pid = btn.dataset.portal;
|
|
261
|
+
if (pid === "__new") {
|
|
262
|
+
close(false);
|
|
263
|
+
const added = await showHubSpotSetupDialog("auth");
|
|
264
|
+
if (added) startUpload();
|
|
265
|
+
return;
|
|
266
|
+
}
|
|
267
|
+
if (pid === activeId) { switchArea.classList.add("hidden"); return; }
|
|
268
|
+
// Switch active account
|
|
269
|
+
await fetch("/api/settings/hs-switch", {
|
|
270
|
+
method: "POST",
|
|
271
|
+
headers: { "Content-Type": "application/json" },
|
|
272
|
+
body: JSON.stringify({ portalId: pid }),
|
|
273
|
+
});
|
|
274
|
+
// Restart the deploy flow with the new account
|
|
275
|
+
close(false);
|
|
276
|
+
startUpload();
|
|
277
|
+
});
|
|
278
|
+
});
|
|
279
|
+
} catch {
|
|
280
|
+
switchArea.innerHTML = '<span style="color:var(--error)">Failed to load accounts</span>';
|
|
281
|
+
}
|
|
228
282
|
});
|
|
229
283
|
});
|
|
230
284
|
}
|
|
@@ -421,6 +475,16 @@ function handleUploadWsMessage(msg) {
|
|
|
421
475
|
setUploadState("uploading");
|
|
422
476
|
break;
|
|
423
477
|
|
|
478
|
+
case "upload_progress":
|
|
479
|
+
if (msg.completed !== undefined && msg.total) {
|
|
480
|
+
const pct = Math.round((msg.completed / msg.total) * 100);
|
|
481
|
+
const statusEl = document.getElementById("upload-status-text");
|
|
482
|
+
if (statusEl) {
|
|
483
|
+
statusEl.textContent = `Uploading to HubSpot... ${msg.completed}/${msg.total} files (${pct}%)`;
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
break;
|
|
487
|
+
|
|
424
488
|
case "upload_output":
|
|
425
489
|
appendUploadLog(msg.chunk);
|
|
426
490
|
break;
|