@cloudinary/asset-management-mcp 0.9.1 → 0.9.3
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 +12 -15
- package/bin/mcp-server.js +288 -369
- package/bin/mcp-server.js.map +13 -13
- package/esm/landing-page.d.ts.map +1 -1
- package/esm/landing-page.js +9 -3
- package/esm/landing-page.js.map +1 -1
- package/esm/lib/config.d.ts +3 -3
- package/esm/lib/config.js +3 -3
- package/esm/mcp-server/apps/app-shared.d.ts +6 -5
- package/esm/mcp-server/apps/app-shared.d.ts.map +1 -1
- package/esm/mcp-server/apps/app-shared.js +134 -14
- package/esm/mcp-server/apps/app-shared.js.map +1 -1
- package/esm/mcp-server/apps/asset-details-app.d.ts.map +1 -1
- package/esm/mcp-server/apps/asset-details-app.js +7 -14
- package/esm/mcp-server/apps/asset-details-app.js.map +1 -1
- package/esm/mcp-server/apps/asset-gallery-app.d.ts.map +1 -1
- package/esm/mcp-server/apps/asset-gallery-app.js +99 -306
- package/esm/mcp-server/apps/asset-gallery-app.js.map +1 -1
- package/esm/mcp-server/apps/asset-upload-app.d.ts.map +1 -1
- package/esm/mcp-server/apps/asset-upload-app.js +29 -24
- package/esm/mcp-server/apps/asset-upload-app.js.map +1 -1
- package/esm/mcp-server/apps/config.d.ts.map +1 -1
- package/esm/mcp-server/apps/config.js +1 -2
- package/esm/mcp-server/apps/config.js.map +1 -1
- package/esm/mcp-server/apps/extensions.d.ts.map +1 -1
- package/esm/mcp-server/apps/extensions.js +6 -1
- package/esm/mcp-server/apps/extensions.js.map +1 -1
- package/esm/mcp-server/cli/serve/impl.js +1 -1
- package/esm/mcp-server/cli/serve/impl.js.map +1 -1
- package/esm/mcp-server/mcp-server.js +1 -1
- package/esm/mcp-server/server.js +1 -1
- package/esm/types/bigint.d.ts.map +1 -1
- package/esm/types/bigint.js +4 -3
- package/esm/types/bigint.js.map +1 -1
- package/package.json +1 -1
- package/src/landing-page.ts +9 -3
- package/src/lib/config.ts +3 -3
- package/src/mcp-server/apps/app-shared.ts +135 -14
- package/src/mcp-server/apps/asset-details-app.ts +7 -13
- package/src/mcp-server/apps/asset-gallery-app.ts +99 -305
- package/src/mcp-server/apps/asset-upload-app.ts +29 -23
- package/src/mcp-server/apps/config.ts +1 -2
- package/src/mcp-server/apps/extensions.ts +6 -1
- package/src/mcp-server/cli/serve/impl.ts +1 -1
- package/src/mcp-server/mcp-server.ts +1 -1
- package/src/mcp-server/server.ts +1 -1
- package/src/types/bigint.ts +18 -17
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* Shares CLDS tokens, MCPApp client, helpers, and detail renderers
|
|
7
7
|
* with the details app via app-shared.ts.
|
|
8
8
|
*/
|
|
9
|
-
import { SHARED_CSS_TOKENS, SHARED_CSS_COMPONENTS, SHARED_JS_MCP_CLIENT, SHARED_JS_HELPERS, SHARED_JS_TOOLTIPS, SHARED_JS_MODAL, SHARED_JS_DETAIL_RENDERERS, SHARED_JS_HOST_CONTEXT, } from "./app-shared.js";
|
|
9
|
+
import { SHARED_CSS_TOKENS, SHARED_CSS_COMPONENTS, SHARED_JS_ICONS, SHARED_JS_MCP_CLIENT, SHARED_JS_HELPERS, SHARED_JS_TOOLTIPS, SHARED_JS_MODAL, SHARED_JS_DETAIL_RENDERERS, SHARED_JS_HOST_CONTEXT, } from "./app-shared.js";
|
|
10
10
|
import { injectToolName } from "./uri.js";
|
|
11
11
|
export function getAssetGalleryHtml(toolName) {
|
|
12
12
|
return injectToolName(ASSET_GALLERY_HTML, toolName);
|
|
@@ -25,90 +25,10 @@ const GALLERY_CSS = /* css */ `
|
|
|
25
25
|
font-size: var(--cld-font-xxs); color: var(--cld-text3); background: var(--cld-bg3);
|
|
26
26
|
padding: 2px 8px; border-radius: 20px; font-weight: 500;
|
|
27
27
|
}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
transition: color 0.15s, border-color 0.15s;
|
|
33
|
-
}
|
|
34
|
-
.select-all-btn:hover { color: var(--cld-accent); border-color: var(--cld-accent); }
|
|
35
|
-
.refresh-btn {
|
|
36
|
-
background: none; border: 1px solid var(--cld-border); border-radius: var(--cld-radius-sm);
|
|
37
|
-
color: var(--cld-text2); cursor: pointer; font-size: 14px; padding: 2px 7px;
|
|
38
|
-
line-height: 1; transition: background 0.15s, color 0.15s;
|
|
39
|
-
}
|
|
40
|
-
.refresh-btn:hover { background: var(--cld-bg3); color: var(--cld-text); }
|
|
41
|
-
|
|
42
|
-
/* ── Filter bar ── */
|
|
43
|
-
.filter-row {
|
|
44
|
-
margin-bottom: var(--cld-sp-md); display: flex; gap: 8px; align-items: center;
|
|
45
|
-
}
|
|
46
|
-
.filter-text-wrap { position: relative; flex: 1; }
|
|
47
|
-
.filter-input {
|
|
48
|
-
width: 100%; height: 36px; padding: 0 12px 0 34px;
|
|
49
|
-
border: 1px solid var(--cld-border); border-radius: var(--cld-radius);
|
|
50
|
-
background: var(--cld-bg); font-size: 12.5px; color: var(--cld-text);
|
|
51
|
-
outline: none; font-family: inherit;
|
|
52
|
-
transition: border-color 0.18s, box-shadow 0.18s;
|
|
53
|
-
}
|
|
54
|
-
.filter-input::placeholder { color: var(--cld-text3); }
|
|
55
|
-
.filter-input:focus {
|
|
56
|
-
border-color: var(--cld-accent);
|
|
57
|
-
box-shadow: 0 0 0 3px rgba(52,72,197,0.1);
|
|
58
|
-
}
|
|
59
|
-
[data-theme="dark"] .filter-input:focus { box-shadow: 0 0 0 3px rgba(13,154,255,0.15); }
|
|
60
|
-
.filter-icon {
|
|
61
|
-
position: absolute; left: 11px; top: 50%; transform: translateY(-50%);
|
|
62
|
-
color: var(--cld-text3); pointer-events: none; display: flex; align-items: center;
|
|
63
|
-
}
|
|
64
|
-
.filter-clear {
|
|
65
|
-
position: absolute; right: 10px; top: 50%; transform: translateY(-50%);
|
|
66
|
-
background: none; border: none; color: var(--cld-text3); cursor: pointer;
|
|
67
|
-
font-size: 14px; line-height: 1; padding: 2px 4px; border-radius: 4px;
|
|
68
|
-
display: none; font-family: inherit;
|
|
69
|
-
}
|
|
70
|
-
.filter-clear:hover { color: var(--cld-text); background: var(--cld-border); }
|
|
71
|
-
.filter-clear.visible { display: block; }
|
|
72
|
-
|
|
73
|
-
/* Aspect-ratio dropdown */
|
|
74
|
-
.aspect-dropdown { position: relative; flex-shrink: 0; user-select: none; }
|
|
75
|
-
.aspect-btn {
|
|
76
|
-
height: 36px; padding: 0 10px; border: 1px solid var(--cld-border);
|
|
77
|
-
border-radius: var(--cld-radius); background: var(--cld-bg);
|
|
78
|
-
font-size: 12.5px; color: var(--cld-text); cursor: pointer;
|
|
79
|
-
display: flex; align-items: center; gap: 6px; white-space: nowrap;
|
|
80
|
-
transition: border-color 0.18s, box-shadow 0.18s, background 0.18s;
|
|
81
|
-
font-family: inherit; outline: none;
|
|
82
|
-
}
|
|
83
|
-
.aspect-btn:hover { border-color: var(--cld-border2); }
|
|
84
|
-
.aspect-btn.active {
|
|
85
|
-
border-color: var(--cld-accent); background: var(--cld-accent-bg);
|
|
86
|
-
color: var(--cld-accent); font-weight: 600;
|
|
87
|
-
}
|
|
88
|
-
.aspect-btn-chevron { color: var(--cld-text3); flex-shrink: 0; transition: transform 0.18s; }
|
|
89
|
-
.aspect-btn.open .aspect-btn-chevron { transform: rotate(180deg); }
|
|
90
|
-
.aspect-menu {
|
|
91
|
-
position: absolute; top: calc(100% + 6px); right: 0;
|
|
92
|
-
background: var(--cld-bg); border: 1px solid var(--cld-border);
|
|
93
|
-
border-radius: 10px; box-shadow: var(--cld-shadow-md);
|
|
94
|
-
padding: 4px; min-width: 160px; z-index: 50; display: none;
|
|
95
|
-
}
|
|
96
|
-
.aspect-menu.open { display: block; }
|
|
97
|
-
.aspect-option {
|
|
98
|
-
display: flex; align-items: center; gap: 10px;
|
|
99
|
-
padding: 7px 10px; border-radius: 6px; font-size: 12.5px;
|
|
100
|
-
color: var(--cld-text); cursor: pointer; transition: background 0.18s;
|
|
101
|
-
}
|
|
102
|
-
.aspect-option:hover { background: var(--cld-bg3); }
|
|
103
|
-
.aspect-option.selected { color: var(--cld-accent); font-weight: 600; }
|
|
104
|
-
.aspect-opt-icon { color: var(--cld-text3); display: flex; align-items: center; flex-shrink: 0; }
|
|
105
|
-
.aspect-option.selected .aspect-opt-icon { color: var(--cld-accent); }
|
|
106
|
-
.aspect-check { margin-left: auto; color: var(--cld-accent); opacity: 0; }
|
|
107
|
-
.aspect-option.selected .aspect-check { opacity: 1; }
|
|
108
|
-
.no-results {
|
|
109
|
-
grid-column: 1 / -1; padding: 60px 20px;
|
|
110
|
-
text-align: center; color: var(--cld-text3); font-size: 13px;
|
|
111
|
-
}
|
|
28
|
+
/* action-btn svg sizing */
|
|
29
|
+
.action-btn svg { width: 12px; height: 12px; fill: none; stroke: currentColor; stroke-width: 2.5; stroke-linecap: round; stroke-linejoin: round; flex-shrink: 0; }
|
|
30
|
+
/* select bar svg */
|
|
31
|
+
.bar-btn svg { width: 13px; height: 13px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; flex-shrink: 0; }
|
|
112
32
|
|
|
113
33
|
/* ── Grid ── */
|
|
114
34
|
.grid {
|
|
@@ -167,18 +87,11 @@ const GALLERY_CSS = /* css */ `
|
|
|
167
87
|
opacity: 0; transition: opacity 0.18s; z-index: 4; pointer-events: none;
|
|
168
88
|
}
|
|
169
89
|
.card:hover .tags-overlay { opacity: 1; }
|
|
170
|
-
.grid.filtering .tags-overlay { opacity: 1; }
|
|
171
90
|
.tag-overlay {
|
|
172
91
|
font-size: 10px; color: white;
|
|
173
92
|
background: rgba(10, 12, 18, 0.55); padding: 2px 7px; border-radius: 20px;
|
|
174
93
|
backdrop-filter: blur(6px); font-weight: 600; letter-spacing: 0.02em;
|
|
175
94
|
}
|
|
176
|
-
.tag-overlay.tag-match { background: rgba(52, 72, 197, 0.82); }
|
|
177
|
-
.tag-overlay mark {
|
|
178
|
-
background: rgba(255, 213, 79, 0.5); color: white;
|
|
179
|
-
border-radius: 2px; padding: 0 1px;
|
|
180
|
-
}
|
|
181
|
-
|
|
182
95
|
/* Floating action buttons */
|
|
183
96
|
.card-actions {
|
|
184
97
|
position: absolute; bottom: 10px; left: 0; right: 0;
|
|
@@ -242,18 +155,27 @@ const GALLERY_CSS = /* css */ `
|
|
|
242
155
|
}
|
|
243
156
|
|
|
244
157
|
/* ── Multi-select bar ── */
|
|
158
|
+
/* Wrapper takes layout space ONLY when a selection is active. When idle
|
|
159
|
+
* it's display:none so it contributes 0 to scrollHeight (no phantom
|
|
160
|
+
* scrollbar gutter / no extra iframe height). */
|
|
161
|
+
.select-bar-wrap {
|
|
162
|
+
display: none;
|
|
163
|
+
position: sticky; bottom: 0; left: 0; right: 0;
|
|
164
|
+
justify-content: center; pointer-events: none;
|
|
165
|
+
z-index: 100; height: 64px;
|
|
166
|
+
}
|
|
167
|
+
.select-bar-wrap.visible { display: flex; }
|
|
245
168
|
.select-bar {
|
|
246
|
-
position:
|
|
247
|
-
transform:
|
|
169
|
+
position: absolute; bottom: 8px;
|
|
170
|
+
transform: translateY(80px);
|
|
248
171
|
background: #1a1d24; color: white; border-radius: 40px;
|
|
249
172
|
padding: 0 6px 0 16px; height: 48px;
|
|
250
173
|
display: flex; align-items: center; gap: 4px;
|
|
251
174
|
box-shadow: 0 8px 32px rgba(0,0,0,0.4);
|
|
252
175
|
transition: transform 0.25s cubic-bezier(0.34, 1.56, 0.64, 1), opacity 0.2s;
|
|
253
|
-
opacity: 0; pointer-events: none;
|
|
176
|
+
opacity: 0; pointer-events: none; white-space: nowrap;
|
|
254
177
|
}
|
|
255
|
-
.select-bar.visible { transform:
|
|
256
|
-
.select-bar-spacer { height: 72px; }
|
|
178
|
+
.select-bar-wrap.visible .select-bar { transform: translateY(0); opacity: 1; pointer-events: all; }
|
|
257
179
|
.select-count { font-size: 13px; font-weight: 600; margin-right: 8px; }
|
|
258
180
|
.bar-btn {
|
|
259
181
|
height: 36px; padding: 0 14px; border: none; border-radius: 30px;
|
|
@@ -293,8 +215,6 @@ var pendingCall = {
|
|
|
293
215
|
args: null,
|
|
294
216
|
};
|
|
295
217
|
var selected = new Set();
|
|
296
|
-
var filterQuery = "";
|
|
297
|
-
var aspectFilter = "";
|
|
298
218
|
var app = new MCPApp({ name: "Cloudinary Asset Gallery", version: "1.0.0" });
|
|
299
219
|
setupHostContext(app);
|
|
300
220
|
|
|
@@ -318,33 +238,13 @@ function showToast(msg) {
|
|
|
318
238
|
_toastTimer = setTimeout(function() { t.classList.remove("show"); }, 2000);
|
|
319
239
|
}
|
|
320
240
|
|
|
321
|
-
function getAspect(r) {
|
|
322
|
-
if (!r.width || !r.height) return "";
|
|
323
|
-
var ratio = r.width / r.height;
|
|
324
|
-
if (ratio > 1.1) return "landscape";
|
|
325
|
-
if (ratio < 0.9) return "portrait";
|
|
326
|
-
return "square";
|
|
327
|
-
}
|
|
328
|
-
|
|
329
|
-
function highlightText(text, query) {
|
|
330
|
-
if (!query) return esc(text);
|
|
331
|
-
var lo = text.toLowerCase();
|
|
332
|
-
var idx = lo.indexOf(query);
|
|
333
|
-
if (idx === -1) return esc(text);
|
|
334
|
-
return esc(text.slice(0, idx))
|
|
335
|
-
+ "<mark>" + esc(text.slice(idx, idx + query.length)) + "</mark>"
|
|
336
|
-
+ esc(text.slice(idx + query.length));
|
|
337
|
-
}
|
|
338
|
-
|
|
339
241
|
function updateSelectBar() {
|
|
340
|
-
var
|
|
242
|
+
var wrap = document.getElementById("select-bar-wrap");
|
|
341
243
|
var countEl = document.getElementById("select-count");
|
|
342
|
-
if (!
|
|
244
|
+
if (!wrap || !countEl) return;
|
|
343
245
|
var n = selected.size;
|
|
344
246
|
countEl.textContent = n + " selected";
|
|
345
|
-
|
|
346
|
-
var spacer = document.getElementById("select-bar-spacer");
|
|
347
|
-
if (spacer) spacer.style.display = n > 0 ? "" : "none";
|
|
247
|
+
wrap.classList.toggle("visible", n > 0);
|
|
348
248
|
var btn = document.getElementById("select-all-btn");
|
|
349
249
|
if (btn) {
|
|
350
250
|
var visible = getVisibleIndices();
|
|
@@ -411,11 +311,9 @@ function copyAssetUrl(type, idx) {
|
|
|
411
311
|
var url = r.secure_url || r.url || "";
|
|
412
312
|
var copyUrl = type === "optimized" ? optimizedUrl(url, r) : url;
|
|
413
313
|
if (!copyUrl) return;
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
});
|
|
418
|
-
} catch(e) { showError("Copy Failed", String(e)); }
|
|
314
|
+
copyText(copyUrl).then(function() {
|
|
315
|
+
showToast(type === "optimized" ? "\\u2728 Optimized URL copied" : "URL copied");
|
|
316
|
+
}).catch(function(e) { showError("Copy Failed", e && e.message ? e.message : String(e)); });
|
|
419
317
|
}
|
|
420
318
|
|
|
421
319
|
function downloadOne(idx) {
|
|
@@ -437,134 +335,74 @@ function copySelectedUrls(type) {
|
|
|
437
335
|
urls.push(type === "optimized" ? optimizedUrl(url, r) : url);
|
|
438
336
|
});
|
|
439
337
|
if (!urls.length) return;
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
});
|
|
444
|
-
} catch(e) { showError("Copy Failed", String(e)); }
|
|
338
|
+
copyText(urls.join("\\n")).then(function() {
|
|
339
|
+
showToast(urls.length + " " + (type === "optimized" ? "optimized " : "") + "URLs copied");
|
|
340
|
+
}).catch(function(e) { showError("Copy Failed", e && e.message ? e.message : String(e)); });
|
|
445
341
|
}
|
|
446
342
|
|
|
447
|
-
function downloadSelected() {
|
|
448
|
-
|
|
343
|
+
async function downloadSelected() {
|
|
344
|
+
if (selected.size === 0) return;
|
|
345
|
+
|
|
346
|
+
var picks = [];
|
|
449
347
|
selected.forEach(function(i) {
|
|
450
348
|
var r = allResources[i];
|
|
451
|
-
if (
|
|
452
|
-
var url = r.secure_url || r.url || "";
|
|
453
|
-
var dl = downloadUrl(url, r);
|
|
454
|
-
if (dl) { app._rpc("ui/open-link", { url: dl }); count++; }
|
|
349
|
+
if (r && r.public_id) picks.push(r);
|
|
455
350
|
});
|
|
456
|
-
if (
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
var
|
|
470
|
-
|
|
471
|
-
if (grid) grid.classList.toggle("filtering", anyFilter);
|
|
351
|
+
if (!picks.length) return;
|
|
352
|
+
|
|
353
|
+
var requestBody = {
|
|
354
|
+
mode: "create",
|
|
355
|
+
target_format: "zip",
|
|
356
|
+
keep_derived: true,
|
|
357
|
+
target_public_id: "mcp-gallery-archive-" + Date.now(),
|
|
358
|
+
fully_qualified_public_ids: picks.map(function(r) {
|
|
359
|
+
return (r.resource_type || "image") + "/" + (r.type || "upload") + "/" + r.public_id;
|
|
360
|
+
}),
|
|
361
|
+
};
|
|
362
|
+
|
|
363
|
+
var btn = document.getElementById("bar-download");
|
|
364
|
+
var origLabel = btn ? btn.innerHTML : "";
|
|
365
|
+
if (btn) { btn.innerHTML = "Creating archive\\u2026"; btn.disabled = true; }
|
|
472
366
|
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
367
|
+
try {
|
|
368
|
+
var res = await app.callServerTool({
|
|
369
|
+
name: "generate-archive",
|
|
370
|
+
arguments: {
|
|
371
|
+
resource_type: "all",
|
|
372
|
+
RequestBody: requestBody,
|
|
373
|
+
},
|
|
374
|
+
});
|
|
478
375
|
|
|
479
|
-
var
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|| tags.some(function(t) { return t.toLowerCase().indexOf(filterQuery) !== -1; });
|
|
484
|
-
|
|
485
|
-
var aspectMatch = !aspectFilter || getAspect(r) === aspectFilter;
|
|
486
|
-
var match = textMatch && aspectMatch;
|
|
487
|
-
card.style.display = match ? "" : "none";
|
|
488
|
-
|
|
489
|
-
var tagsEl = document.getElementById("tags-overlay-" + i);
|
|
490
|
-
if (tagsEl && tags.length) {
|
|
491
|
-
var maxOv = 3;
|
|
492
|
-
var matchedTags = [];
|
|
493
|
-
var otherTags = [];
|
|
494
|
-
for (var ti = 0; ti < tags.length; ti++) {
|
|
495
|
-
var isMatch = filterQuery && tags[ti].toLowerCase().indexOf(filterQuery) !== -1;
|
|
496
|
-
if (isMatch) matchedTags.push(tags[ti]);
|
|
497
|
-
else otherTags.push(tags[ti]);
|
|
498
|
-
}
|
|
499
|
-
var shown = matchedTags.slice();
|
|
500
|
-
var remaining = maxOv - shown.length;
|
|
501
|
-
if (remaining > 0) shown = shown.concat(otherTags.slice(0, remaining));
|
|
502
|
-
var hidden = tags.length - shown.length;
|
|
503
|
-
var hiddenTags = tags.filter(function(t) { return shown.indexOf(t) === -1; });
|
|
504
|
-
tagsEl.innerHTML = shown.map(function(t) {
|
|
505
|
-
var matched = filterQuery && t.toLowerCase().indexOf(filterQuery) !== -1;
|
|
506
|
-
return '<span class="tag-overlay' + (matched ? ' tag-match' : '') + '">' + highlightText(t, filterQuery) + '</span>';
|
|
507
|
-
}).join("") + (hidden > 0 ? '<span class="tag-overlay" title="' + esc(hiddenTags.join(", ")) + '">+' + hidden + '</span>' : '');
|
|
376
|
+
var data = ingestResult(res);
|
|
377
|
+
if (data && (data._error || data._parseError)) {
|
|
378
|
+
showError("Archive Failed", unwrapApiError(data._message));
|
|
379
|
+
return;
|
|
508
380
|
}
|
|
509
|
-
|
|
510
|
-
if (
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
var badge = document.getElementById("count-badge");
|
|
514
|
-
if (badge) {
|
|
515
|
-
badge.textContent = anyFilter
|
|
516
|
-
? visibleCount + " of " + allResources.length
|
|
517
|
-
: allResources.length + (lastCursor ? "+" : "") + " items";
|
|
518
|
-
}
|
|
519
|
-
|
|
520
|
-
var noRes = document.getElementById("no-results");
|
|
521
|
-
if (visibleCount === 0 && anyFilter) {
|
|
522
|
-
if (!noRes && grid) {
|
|
523
|
-
noRes = document.createElement("div");
|
|
524
|
-
noRes.id = "no-results";
|
|
525
|
-
noRes.className = "no-results";
|
|
526
|
-
grid.appendChild(noRes);
|
|
381
|
+
var archiveUrl = data && (data.secure_url || data.url);
|
|
382
|
+
if (!archiveUrl) {
|
|
383
|
+
showError("Archive Failed", "No delivery URL returned.");
|
|
384
|
+
return;
|
|
527
385
|
}
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
386
|
+
try { await copyText(archiveUrl); } catch (e) { /* ignore */ }
|
|
387
|
+
app._rpc("ui/open-link", { url: archiveUrl });
|
|
388
|
+
showToast("Archive saved as raw in Cloudinary \\u2014 opening URL (" + picks.length + " asset" + (picks.length > 1 ? "s" : "") + ")");
|
|
389
|
+
} catch (e) {
|
|
390
|
+
showError("Archive Failed", unwrapApiError(e && e.message ? e.message : String(e)));
|
|
391
|
+
} finally {
|
|
392
|
+
if (btn) { btn.innerHTML = origLabel; btn.disabled = false; }
|
|
531
393
|
}
|
|
532
394
|
}
|
|
533
395
|
|
|
534
|
-
function
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
})
|
|
543
|
-
|
|
544
|
-
}
|
|
545
|
-
|
|
546
|
-
function toggleAspectMenu(e) {
|
|
547
|
-
e.stopPropagation();
|
|
548
|
-
var btn = document.getElementById("aspect-btn");
|
|
549
|
-
var menu = document.getElementById("aspect-menu");
|
|
550
|
-
if (!btn || !menu) return;
|
|
551
|
-
var open = menu.classList.toggle("open");
|
|
552
|
-
btn.classList.toggle("open", open);
|
|
553
|
-
}
|
|
554
|
-
|
|
555
|
-
function selectAspect(val) {
|
|
556
|
-
aspectFilter = val;
|
|
557
|
-
var labels = { "": "All orientations", landscape: "Landscape", portrait: "Portrait", square: "Square" };
|
|
558
|
-
var label = document.getElementById("aspect-btn-label");
|
|
559
|
-
if (label) label.textContent = labels[aspectFilter] || "All orientations";
|
|
560
|
-
document.querySelectorAll(".aspect-option").forEach(function(o) {
|
|
561
|
-
o.classList.toggle("selected", o.getAttribute("data-value") === aspectFilter);
|
|
562
|
-
});
|
|
563
|
-
var menu = document.getElementById("aspect-menu");
|
|
564
|
-
var btn = document.getElementById("aspect-btn");
|
|
565
|
-
if (menu) menu.classList.remove("open");
|
|
566
|
-
if (btn) btn.classList.remove("open");
|
|
567
|
-
handleFilter();
|
|
396
|
+
function unwrapApiError(raw) {
|
|
397
|
+
if (!raw) return "Unknown error.";
|
|
398
|
+
var msg = String(raw);
|
|
399
|
+
try {
|
|
400
|
+
if (msg.charAt(0) === "{") {
|
|
401
|
+
var parsed = JSON.parse(msg);
|
|
402
|
+
msg = (parsed && parsed.error && parsed.error.message) || msg;
|
|
403
|
+
}
|
|
404
|
+
} catch (e) { /* keep raw */ }
|
|
405
|
+
return msg;
|
|
568
406
|
}
|
|
569
407
|
|
|
570
408
|
function render() {
|
|
@@ -584,41 +422,12 @@ function render() {
|
|
|
584
422
|
h += '<h1>Results</h1>';
|
|
585
423
|
h += '<span class="count-badge" id="count-badge">' + allResources.length + (lastCursor ? "+" : "") + ' items</span>';
|
|
586
424
|
h += '</div>';
|
|
587
|
-
h += '<div style="display:flex;align-items:center;gap:8px">';
|
|
588
|
-
h += '<button class="
|
|
589
|
-
h += '<button class="
|
|
425
|
+
h += '<div id="header-actions" style="display:flex;align-items:center;gap:8px">';
|
|
426
|
+
h += '<button class="icon-btn" id="select-all-btn">Select all</button>';
|
|
427
|
+
h += '<button class="icon-btn icon-only" id="refresh-gallery" title="Refresh">' + IC.refresh + '</button>';
|
|
590
428
|
h += '</div>';
|
|
591
429
|
h += '</div>';
|
|
592
430
|
|
|
593
|
-
// Filter bar
|
|
594
|
-
h += '<div class="filter-row">';
|
|
595
|
-
h += '<div class="filter-text-wrap">';
|
|
596
|
-
h += '<span class="filter-icon"><svg width="14" height="14" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><circle cx="6.5" cy="6.5" r="4.5"/><path d="M10.5 10.5l3 3"/></svg></span>';
|
|
597
|
-
h += '<input class="filter-input" id="filter-input" type="text" placeholder="Filter by filename or tag\\u2026" autocomplete="off" spellcheck="false">';
|
|
598
|
-
h += '<button class="filter-clear" id="filter-clear">\\u2715</button>';
|
|
599
|
-
h += '</div>';
|
|
600
|
-
h += '<div class="aspect-dropdown" id="aspect-dropdown">';
|
|
601
|
-
h += '<button class="aspect-btn" id="aspect-btn">';
|
|
602
|
-
h += '<span id="aspect-btn-label">All orientations</span>';
|
|
603
|
-
h += '<svg class="aspect-btn-chevron" width="11" height="11" viewBox="0 0 12 12" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="2,4 6,8 10,4"/></svg>';
|
|
604
|
-
h += '</button>';
|
|
605
|
-
h += '<div class="aspect-menu" id="aspect-menu">';
|
|
606
|
-
var aspects = [
|
|
607
|
-
{ val: "", label: "All orientations", icon: '<svg width="14" height="14" viewBox="0 0 14 14" fill="none" stroke="currentColor" stroke-width="1.5"><rect x="1" y="1" width="12" height="12" rx="1.5"/></svg>' },
|
|
608
|
-
{ val: "landscape", label: "Landscape", icon: '<svg width="14" height="10" viewBox="0 0 14 10" fill="none" stroke="currentColor" stroke-width="1.5"><rect x=".75" y=".75" width="12.5" height="8.5" rx="1.5"/></svg>' },
|
|
609
|
-
{ val: "portrait", label: "Portrait", icon: '<svg width="10" height="14" viewBox="0 0 10 14" fill="none" stroke="currentColor" stroke-width="1.5"><rect x=".75" y=".75" width="8.5" height="12.5" rx="1.5"/></svg>' },
|
|
610
|
-
{ val: "square", label: "Square", icon: '<svg width="12" height="12" viewBox="0 0 12 12" fill="none" stroke="currentColor" stroke-width="1.5"><rect x=".75" y=".75" width="10.5" height="10.5" rx="1.5"/></svg>' },
|
|
611
|
-
];
|
|
612
|
-
for (var ai = 0; ai < aspects.length; ai++) {
|
|
613
|
-
var ao = aspects[ai];
|
|
614
|
-
h += '<div class="aspect-option' + (ao.val === aspectFilter ? ' selected' : '') + '" data-value="' + ao.val + '">';
|
|
615
|
-
h += '<span class="aspect-opt-icon">' + ao.icon + '</span>';
|
|
616
|
-
h += ao.label;
|
|
617
|
-
h += '<svg class="aspect-check" width="12" height="12" viewBox="0 0 12 12" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><polyline points="2,6 5,9 10,3"/></svg>';
|
|
618
|
-
h += '</div>';
|
|
619
|
-
}
|
|
620
|
-
h += '</div></div></div>';
|
|
621
|
-
|
|
622
431
|
// Grid
|
|
623
432
|
h += '<div class="grid" id="gallery-grid">';
|
|
624
433
|
for (var i = 0; i < allResources.length; i++) {
|
|
@@ -667,8 +476,8 @@ function render() {
|
|
|
667
476
|
if (url) {
|
|
668
477
|
h += '<div class="card-actions">';
|
|
669
478
|
h += '<button class="action-btn act-original" data-copy-original="' + i + '">Copy URL</button>';
|
|
670
|
-
if (rt !== "raw") h += '<button class="action-btn act-optimized" data-copy-optimized="' + i + '"
|
|
671
|
-
h += '<button class="action-btn act-download" data-download="' + i + '" title="Download"
|
|
479
|
+
if (rt !== "raw") h += '<button class="action-btn act-optimized" data-copy-optimized="' + i + '">' + IC.zap + ' Optimized</button>';
|
|
480
|
+
h += '<button class="action-btn act-download" data-download="' + i + '" title="Download">' + IC.arrowDown + '</button>';
|
|
672
481
|
h += '</div>';
|
|
673
482
|
}
|
|
674
483
|
|
|
@@ -715,24 +524,24 @@ function render() {
|
|
|
715
524
|
h += "</div>";
|
|
716
525
|
}
|
|
717
526
|
|
|
718
|
-
//
|
|
719
|
-
h += '<div class="select-bar-
|
|
720
|
-
|
|
721
|
-
// Multi-select bar
|
|
527
|
+
// Multi-select bar (sticky, in-flow wrapper so iframe sizing stays truthful)
|
|
528
|
+
h += '<div class="select-bar-wrap" id="select-bar-wrap">';
|
|
722
529
|
h += '<div class="select-bar" id="select-bar">';
|
|
723
530
|
h += '<span class="select-count" id="select-count">0 selected</span>';
|
|
724
531
|
h += '<div class="bar-divider"></div>';
|
|
725
|
-
h += '<button class="bar-btn bar-primary" id="bar-copy-optimized" style="display:none"
|
|
532
|
+
h += '<button class="bar-btn bar-primary" id="bar-copy-optimized" style="display:none">' + IC.zap + ' Copy Optimized</button>';
|
|
726
533
|
h += '<button class="bar-btn bar-secondary" id="bar-copy-original">Copy Original</button>';
|
|
727
|
-
h += '<button class="bar-btn bar-secondary" id="bar-download"
|
|
534
|
+
h += '<button class="bar-btn bar-secondary" id="bar-download">' + IC.arrowDown + ' Download Selected</button>';
|
|
728
535
|
h += '<div class="bar-divider"></div>';
|
|
729
|
-
h += '<button class="bar-btn bar-ghost" id="bar-clear"
|
|
536
|
+
h += '<button class="bar-btn bar-ghost" id="bar-clear">' + IC.x + '</button>';
|
|
537
|
+
h += '</div>';
|
|
730
538
|
h += '</div>';
|
|
731
539
|
|
|
732
540
|
// Toast
|
|
733
541
|
h += '<div class="gallery-toast" id="gallery-toast"></div>';
|
|
734
542
|
|
|
735
543
|
root.innerHTML = h;
|
|
544
|
+
renderThemeToggle();
|
|
736
545
|
|
|
737
546
|
// Re-apply selection state
|
|
738
547
|
selected.forEach(function(i) {
|
|
@@ -766,37 +575,16 @@ function attachEvents() {
|
|
|
766
575
|
_eventsAttached = true;
|
|
767
576
|
var root = document.getElementById("app");
|
|
768
577
|
|
|
769
|
-
root.addEventListener("input", function(e) {
|
|
770
|
-
if (e.target && e.target.id === "filter-input") handleFilter();
|
|
771
|
-
});
|
|
772
|
-
|
|
773
|
-
document.addEventListener("click", function(e) {
|
|
774
|
-
var dd = document.getElementById("aspect-dropdown");
|
|
775
|
-
if (dd && !dd.contains(e.target)) {
|
|
776
|
-
var menu = document.getElementById("aspect-menu");
|
|
777
|
-
var btn = document.getElementById("aspect-btn");
|
|
778
|
-
if (menu) menu.classList.remove("open");
|
|
779
|
-
if (btn) btn.classList.remove("open");
|
|
780
|
-
}
|
|
781
|
-
});
|
|
782
|
-
|
|
783
578
|
root.addEventListener("click", function(e) {
|
|
784
579
|
var el = e.target;
|
|
785
580
|
while (el && el !== root) {
|
|
786
581
|
if (el.id === "load-more-btn") { loadMore(); return; }
|
|
787
582
|
if (el.id === "refresh-gallery") { refreshGallery(); return; }
|
|
788
583
|
if (el.id === "select-all-btn") { toggleSelectAll(); return; }
|
|
789
|
-
if (el.id === "filter-clear") { clearFilter(); return; }
|
|
790
584
|
if (el.id === "bar-copy-optimized") { copySelectedUrls("optimized"); return; }
|
|
791
585
|
if (el.id === "bar-copy-original") { copySelectedUrls("original"); return; }
|
|
792
586
|
if (el.id === "bar-download") { downloadSelected(); return; }
|
|
793
587
|
if (el.id === "bar-clear") { clearSelection(); return; }
|
|
794
|
-
if (el.id === "aspect-btn" || el.parentElement && el.parentElement.id === "aspect-btn") {
|
|
795
|
-
toggleAspectMenu(e); return;
|
|
796
|
-
}
|
|
797
|
-
if (el.classList && el.classList.contains("aspect-option")) {
|
|
798
|
-
selectAspect(el.getAttribute("data-value") || ""); return;
|
|
799
|
-
}
|
|
800
588
|
if (el.dataset && el.dataset.copyOriginal != null) {
|
|
801
589
|
e.stopPropagation();
|
|
802
590
|
copyAssetUrl("original", parseInt(el.dataset.copyOriginal, 10)); return;
|
|
@@ -957,6 +745,7 @@ function showFetchPrompt() {
|
|
|
957
745
|
h += '<button class="prompt-btn prompt-btn-primary" id="fetch-direct-btn">Fetch Directly</button>';
|
|
958
746
|
h += "</div></div>";
|
|
959
747
|
root.innerHTML = h;
|
|
748
|
+
renderThemeToggle();
|
|
960
749
|
document.getElementById("fetch-direct-btn").addEventListener("click", function() { fetchDirect(); });
|
|
961
750
|
}
|
|
962
751
|
|
|
@@ -976,6 +765,9 @@ async function fetchDirect() {
|
|
|
976
765
|
console.log(LOG_PREFIX, "fetchDirect ->", name);
|
|
977
766
|
|
|
978
767
|
document.getElementById("app").innerHTML = '<div class="status">Fetching assets\\u2026</div>';
|
|
768
|
+
requestAnimationFrame(function() {
|
|
769
|
+
app.reportSize(Math.max(document.documentElement.scrollHeight, MIN_HEIGHT));
|
|
770
|
+
});
|
|
979
771
|
try {
|
|
980
772
|
var res = await app.callServerTool({ name: name, arguments: args });
|
|
981
773
|
var data = ingestResult(res);
|
|
@@ -1027,6 +819,7 @@ async function loadMore() {
|
|
|
1027
819
|
function refreshGallery() {
|
|
1028
820
|
allResources = [];
|
|
1029
821
|
lastCursor = null;
|
|
822
|
+
selected.clear();
|
|
1030
823
|
fetchDirect();
|
|
1031
824
|
}
|
|
1032
825
|
|
|
@@ -1034,7 +827,6 @@ function refreshGallery() {
|
|
|
1034
827
|
document.addEventListener("keydown", function(e) {
|
|
1035
828
|
if (e.key === "Escape") {
|
|
1036
829
|
if (document.querySelector(".modal-overlay")) { closeModal(); return; }
|
|
1037
|
-
if (filterQuery || aspectFilter) { clearFilter(); return; }
|
|
1038
830
|
if (selected.size > 0) { clearSelection(); return; }
|
|
1039
831
|
}
|
|
1040
832
|
});
|
|
@@ -1064,6 +856,7 @@ ${GALLERY_CSS}
|
|
|
1064
856
|
<div class="gallery-toast" id="gallery-toast"></div>
|
|
1065
857
|
|
|
1066
858
|
<script>
|
|
859
|
+
${SHARED_JS_ICONS}
|
|
1067
860
|
${SHARED_JS_MCP_CLIENT}
|
|
1068
861
|
${SHARED_JS_HELPERS}
|
|
1069
862
|
${SHARED_JS_TOOLTIPS}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"asset-gallery-app.js","sourceRoot":"","sources":["../../../src/mcp-server/apps/asset-gallery-app.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EACL,iBAAiB,EACjB,qBAAqB,EACrB,oBAAoB,EACpB,iBAAiB,EACjB,kBAAkB,EAClB,eAAe,EACf,0BAA0B,EAC1B,sBAAsB,GACvB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAE1C,MAAM,UAAU,mBAAmB,CAAC,QAAiB;IACnD,OAAO,cAAc,CAAC,kBAAkB,EAAE,QAAQ,CAAC,CAAC;AACtD,CAAC;AAED,MAAM,WAAW,GAAG,SAAS,CAAC
|
|
1
|
+
{"version":3,"file":"asset-gallery-app.js","sourceRoot":"","sources":["../../../src/mcp-server/apps/asset-gallery-app.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EACL,iBAAiB,EACjB,qBAAqB,EACrB,eAAe,EACf,oBAAoB,EACpB,iBAAiB,EACjB,kBAAkB,EAClB,eAAe,EACf,0BAA0B,EAC1B,sBAAsB,GACvB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAE1C,MAAM,UAAU,mBAAmB,CAAC,QAAiB;IACnD,OAAO,cAAc,CAAC,kBAAkB,EAAE,QAAQ,CAAC,CAAC;AACtD,CAAC;AAED,MAAM,WAAW,GAAG,SAAS,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAiM7B,CAAC;AAEF,MAAM,UAAU,GAAG,QAAQ,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAynB3B,CAAC;AAEF,MAAM,kBAAkB,GAAG,UAAU,CAAC;;;;;;;EAOpC,iBAAiB;EACjB,qBAAqB;EACrB,WAAW;;;;;;;;EAQX,eAAe;EACf,oBAAoB;EACpB,iBAAiB;EACjB,kBAAkB;EAClB,eAAe;EACf,0BAA0B;EAC1B,sBAAsB;EACtB,UAAU;;;QAGJ,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"asset-upload-app.d.ts","sourceRoot":"","sources":["../../../src/mcp-server/apps/asset-upload-app.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"asset-upload-app.d.ts","sourceRoot":"","sources":["../../../src/mcp-server/apps/asset-upload-app.ts"],"names":[],"mappings":"AAgCA,wBAAgB,kBAAkB,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAE5D"}
|