@jay-framework/aiditor 0.18.4 → 0.19.1
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/actions/list-add-menu-items.jay-action +9 -0
- package/dist/actions/list-add-menu-items.jay-action.d.ts +3 -0
- package/dist/actions/resolve-add-menu-contract-params.jay-action +12 -0
- package/dist/actions/resolve-add-menu-contract-params.jay-action.d.ts +5 -0
- package/dist/actions/sync-add-menu-attachments.jay-action +13 -0
- package/dist/actions/sync-add-menu-attachments.jay-action.d.ts +10 -0
- package/dist/agent-kit-template/plugin/aiditor-add-menu.md +106 -0
- package/dist/index.client.d.ts +784 -5
- package/dist/index.client.js +1354 -564
- package/dist/index.d.ts +89 -729
- package/dist/index.js +981 -503
- package/dist/pages/aiditor/page.css +1350 -1
- package/dist/pages/aiditor/page.jay-html +1656 -484
- package/package.json +15 -7
- package/plugin.yaml +10 -0
package/dist/index.client.js
CHANGED
|
@@ -8275,6 +8275,18 @@ async function seekVideoToTime(video, timeSec, options) {
|
|
|
8275
8275
|
let dur = effectiveVideoDuration(video);
|
|
8276
8276
|
if (!Number.isFinite(dur) || dur <= 0) dur = Number.POSITIVE_INFINITY;
|
|
8277
8277
|
const t = Math.max(0, Math.min(timeSec, dur));
|
|
8278
|
+
const skipSeek = Math.abs(video.currentTime - t) < 1e-4;
|
|
8279
|
+
console.info("[aiditor:video-capture] seek start", {
|
|
8280
|
+
t,
|
|
8281
|
+
currentTime: video.currentTime,
|
|
8282
|
+
skipSeek,
|
|
8283
|
+
paused: video.paused
|
|
8284
|
+
});
|
|
8285
|
+
if (skipSeek) {
|
|
8286
|
+
await flushLayout();
|
|
8287
|
+
console.info("[aiditor:video-capture] seek done", { t, via: "skipSeek" });
|
|
8288
|
+
return;
|
|
8289
|
+
}
|
|
8278
8290
|
await new Promise((resolve, reject) => {
|
|
8279
8291
|
let settled = false;
|
|
8280
8292
|
const timer = window.setTimeout(() => {
|
|
@@ -8287,25 +8299,22 @@ async function seekVideoToTime(video, timeSec, options) {
|
|
|
8287
8299
|
)
|
|
8288
8300
|
);
|
|
8289
8301
|
}, timeoutMs);
|
|
8290
|
-
const
|
|
8302
|
+
const onSeeked = () => {
|
|
8291
8303
|
if (settled) return;
|
|
8292
8304
|
settled = true;
|
|
8293
8305
|
window.clearTimeout(timer);
|
|
8294
8306
|
video.removeEventListener("seeked", onSeeked);
|
|
8295
|
-
|
|
8296
|
-
|
|
8297
|
-
|
|
8298
|
-
}
|
|
8299
|
-
|
|
8300
|
-
|
|
8307
|
+
console.info("[aiditor:video-capture] seeked", {
|
|
8308
|
+
t,
|
|
8309
|
+
currentTime: video.currentTime
|
|
8310
|
+
});
|
|
8311
|
+
void flushLayout().then(() => {
|
|
8312
|
+
console.info("[aiditor:video-capture] seek done", { t, via: "seeked" });
|
|
8313
|
+
resolve();
|
|
8314
|
+
});
|
|
8301
8315
|
};
|
|
8302
|
-
const onSeeked = () => done();
|
|
8303
8316
|
video.addEventListener("seeked", onSeeked);
|
|
8304
|
-
|
|
8305
|
-
queueMicrotask(() => onSeeked());
|
|
8306
|
-
} else {
|
|
8307
|
-
video.currentTime = t;
|
|
8308
|
-
}
|
|
8317
|
+
video.currentTime = t;
|
|
8309
8318
|
});
|
|
8310
8319
|
}
|
|
8311
8320
|
async function capturePreviewForVideoFrame(rootEl, videoEl, mode = "full") {
|
|
@@ -8495,12 +8504,22 @@ function blobToImage(blob) {
|
|
|
8495
8504
|
});
|
|
8496
8505
|
}
|
|
8497
8506
|
async function captureVideoInstantDual(rootEl, videoEl) {
|
|
8507
|
+
console.info("[aiditor:video-capture] capture start", { mode: "clean" });
|
|
8498
8508
|
const clean = await capturePreviewForVideoFrame(rootEl, videoEl, "clean");
|
|
8509
|
+
console.info("[aiditor:video-capture] capture done", {
|
|
8510
|
+
mode: "clean",
|
|
8511
|
+
bytes: clean.size
|
|
8512
|
+
});
|
|
8513
|
+
console.info("[aiditor:video-capture] capture start", { mode: "markersOnly" });
|
|
8499
8514
|
const markersOnly = await capturePreviewForVideoFrame(
|
|
8500
8515
|
rootEl,
|
|
8501
8516
|
videoEl,
|
|
8502
8517
|
"markersOnly"
|
|
8503
8518
|
);
|
|
8519
|
+
console.info("[aiditor:video-capture] capture done", {
|
|
8520
|
+
mode: "markersOnly",
|
|
8521
|
+
bytes: markersOnly.size
|
|
8522
|
+
});
|
|
8504
8523
|
return { clean, markersOnly };
|
|
8505
8524
|
}
|
|
8506
8525
|
function getRestrictionTargetCtor() {
|
|
@@ -8787,19 +8806,54 @@ async function ensureAddPageRequestId(pageRoute, currentRequestId) {
|
|
|
8787
8806
|
}
|
|
8788
8807
|
return { requestId: result.requestId };
|
|
8789
8808
|
}
|
|
8790
|
-
function
|
|
8791
|
-
|
|
8792
|
-
|
|
8809
|
+
function formatRouteParamToken(paramName) {
|
|
8810
|
+
return `[${paramName}]`;
|
|
8811
|
+
}
|
|
8812
|
+
function insertRouteParamInField(input, currentRoute, paramName) {
|
|
8813
|
+
const token = formatRouteParamToken(paramName);
|
|
8814
|
+
const route = currentRoute.trim() || "/";
|
|
8815
|
+
if (route.includes(token)) return route;
|
|
8816
|
+
const insertWithSlash = (before) => {
|
|
8817
|
+
if (before.length === 0) return token;
|
|
8818
|
+
const last = before[before.length - 1];
|
|
8819
|
+
if (last === "/" || last === "]") return token;
|
|
8820
|
+
return `/${token}`;
|
|
8821
|
+
};
|
|
8822
|
+
if (input && document.activeElement === input) {
|
|
8823
|
+
const start = input.selectionStart ?? route.length;
|
|
8824
|
+
const end = input.selectionEnd ?? start;
|
|
8825
|
+
const before = route.slice(0, start);
|
|
8826
|
+
const after = route.slice(end);
|
|
8827
|
+
const insert2 = insertWithSlash(before);
|
|
8828
|
+
const next = before + insert2 + after;
|
|
8829
|
+
queueMicrotask(() => {
|
|
8830
|
+
const pos = before.length + insert2.length;
|
|
8831
|
+
input.setSelectionRange(pos, pos);
|
|
8832
|
+
input.focus();
|
|
8833
|
+
});
|
|
8834
|
+
return next;
|
|
8835
|
+
}
|
|
8836
|
+
const insert = insertWithSlash(route);
|
|
8837
|
+
return route.endsWith("/") ? `${route}${token}` : `${route}${insert}`;
|
|
8838
|
+
}
|
|
8839
|
+
function insertTextAtRange(currentValue, text, selectionStart, selectionEnd = selectionStart) {
|
|
8840
|
+
const start = Math.max(0, Math.min(selectionStart, currentValue.length));
|
|
8841
|
+
const end = Math.max(start, Math.min(selectionEnd, currentValue.length));
|
|
8793
8842
|
const before = currentValue.slice(0, start);
|
|
8794
8843
|
const after = currentValue.slice(end);
|
|
8795
8844
|
const prefix = before.length > 0 && !before.endsWith("\n") ? "\n" : "";
|
|
8796
8845
|
const insertion = `${prefix}${text}
|
|
8797
8846
|
`;
|
|
8798
8847
|
const next = before + insertion + after;
|
|
8799
|
-
|
|
8848
|
+
return { next, cursor: before.length + insertion.length };
|
|
8849
|
+
}
|
|
8850
|
+
function insertTextAtCursor(textarea, text, currentValue, selection) {
|
|
8851
|
+
const start = textarea.selectionStart ?? currentValue.length;
|
|
8852
|
+
const end = textarea.selectionEnd ?? start;
|
|
8853
|
+
const { next, cursor } = insertTextAtRange(currentValue, text, start, end);
|
|
8800
8854
|
queueMicrotask(() => {
|
|
8801
|
-
textarea.selectionStart =
|
|
8802
|
-
textarea.selectionEnd =
|
|
8855
|
+
textarea.selectionStart = cursor;
|
|
8856
|
+
textarea.selectionEnd = cursor;
|
|
8803
8857
|
textarea.focus();
|
|
8804
8858
|
});
|
|
8805
8859
|
return next;
|
|
@@ -9223,383 +9277,459 @@ ${md}`);
|
|
|
9223
9277
|
briefFillGenerating: generating
|
|
9224
9278
|
};
|
|
9225
9279
|
}
|
|
9226
|
-
|
|
9227
|
-
|
|
9228
|
-
|
|
9229
|
-
|
|
9230
|
-
|
|
9231
|
-
|
|
9232
|
-
|
|
9233
|
-
|
|
9234
|
-
|
|
9235
|
-
|
|
9236
|
-
|
|
9237
|
-
|
|
9238
|
-
|
|
9239
|
-
|
|
9240
|
-
|
|
9241
|
-
|
|
9242
|
-
|
|
9243
|
-
|
|
9244
|
-
|
|
9245
|
-
|
|
9246
|
-
|
|
9247
|
-
|
|
9248
|
-
|
|
9249
|
-
|
|
9250
|
-
showInAddPagePicker: true,
|
|
9251
|
-
configFiles: ["config/.wix-stores.yaml"]
|
|
9252
|
-
},
|
|
9253
|
-
{
|
|
9254
|
-
pluginName: "wix-stores-v1",
|
|
9255
|
-
packageName: "@jay-framework/wix-stores-v1",
|
|
9256
|
-
description: "Wix Stores v1 catalog API",
|
|
9257
|
-
kind: "headless",
|
|
9258
|
-
requires: ["wix-server-client", "wix-cart"],
|
|
9259
|
-
showInAddPagePicker: true
|
|
9260
|
-
},
|
|
9261
|
-
{
|
|
9262
|
-
pluginName: "wix-data",
|
|
9263
|
-
packageName: "@jay-framework/wix-data",
|
|
9264
|
-
description: "Wix Data collections CMS",
|
|
9265
|
-
kind: "headless",
|
|
9266
|
-
requires: ["wix-server-client"],
|
|
9267
|
-
showInAddPagePicker: true,
|
|
9268
|
-
configFiles: ["config/.wix-data.yaml"]
|
|
9269
|
-
},
|
|
9270
|
-
{
|
|
9271
|
-
pluginName: "wix-media",
|
|
9272
|
-
packageName: "@jay-framework/wix-media",
|
|
9273
|
-
description: "Wix media service (no page components)",
|
|
9274
|
-
kind: "service-only",
|
|
9275
|
-
requires: ["wix-server-client"],
|
|
9276
|
-
showInAddPagePicker: true
|
|
9277
|
-
},
|
|
9278
|
-
{
|
|
9279
|
-
pluginName: "ui-kit",
|
|
9280
|
-
packageName: "@jay-framework/ui-kit",
|
|
9281
|
-
description: "Jay UI kit headless components",
|
|
9282
|
-
kind: "headless",
|
|
9283
|
-
requires: [],
|
|
9284
|
-
showInAddPagePicker: true
|
|
9285
|
-
},
|
|
9286
|
-
{
|
|
9287
|
-
pluginName: "gemini-agent",
|
|
9288
|
-
packageName: "@jay-framework/gemini-agent",
|
|
9289
|
-
description: "Gemini AI agent plugin",
|
|
9290
|
-
kind: "headless",
|
|
9291
|
-
requires: [],
|
|
9292
|
-
showInAddPagePicker: true,
|
|
9293
|
-
configFiles: ["config/.gemini-agent.yaml"]
|
|
9294
|
-
},
|
|
9295
|
-
{
|
|
9296
|
-
pluginName: "webmcp",
|
|
9297
|
-
packageName: "@jay-framework/webmcp",
|
|
9298
|
-
description: "Web MCP tooling",
|
|
9299
|
-
kind: "tooling",
|
|
9300
|
-
requires: [],
|
|
9301
|
-
showInAddPagePicker: false
|
|
9302
|
-
},
|
|
9303
|
-
{
|
|
9304
|
-
pluginName: "aiditor",
|
|
9305
|
-
packageName: "@jay-framework/aiditor",
|
|
9306
|
-
description: "AIditor self plugin",
|
|
9307
|
-
kind: "tooling",
|
|
9308
|
-
requires: [],
|
|
9309
|
-
showInAddPagePicker: false
|
|
9280
|
+
function detectRequiredParamCollisions(resolved) {
|
|
9281
|
+
const byContract = /* @__PURE__ */ new Map();
|
|
9282
|
+
for (const r of resolved) {
|
|
9283
|
+
byContract.set(r.contractName, r);
|
|
9284
|
+
}
|
|
9285
|
+
const contracts = [...byContract.values()];
|
|
9286
|
+
if (contracts.length < 2) return [];
|
|
9287
|
+
const warnings = [];
|
|
9288
|
+
for (let i = 0; i < contracts.length; i++) {
|
|
9289
|
+
for (let j = i + 1; j < contracts.length; j++) {
|
|
9290
|
+
const a2 = contracts[i];
|
|
9291
|
+
const b = contracts[j];
|
|
9292
|
+
if (a2.contractName === b.contractName) continue;
|
|
9293
|
+
const overlap = a2.requiredParams.filter(
|
|
9294
|
+
(p) => b.requiredParams.includes(p)
|
|
9295
|
+
);
|
|
9296
|
+
for (const param of overlap) {
|
|
9297
|
+
warnings.push({
|
|
9298
|
+
overlappingParam: param,
|
|
9299
|
+
contractNames: [a2.contractName, b.contractName],
|
|
9300
|
+
message: `${a2.contractName} and ${b.contractName} both require [${param}] for different data. One URL segment cannot serve both. Use separate pages, distinct param names in the route, or instance mode for one component.`
|
|
9301
|
+
});
|
|
9302
|
+
}
|
|
9303
|
+
}
|
|
9310
9304
|
}
|
|
9311
|
-
|
|
9312
|
-
function getCatalogEntry(pluginName) {
|
|
9313
|
-
return CATALOG.find((e2) => e2.pluginName === pluginName);
|
|
9305
|
+
return warnings;
|
|
9314
9306
|
}
|
|
9315
|
-
|
|
9316
|
-
|
|
9317
|
-
|
|
9318
|
-
|
|
9319
|
-
"cart-page": "cartPage",
|
|
9320
|
-
"category-list": "categories"
|
|
9321
|
-
};
|
|
9322
|
-
function getDefaultComponentKey(contractName) {
|
|
9323
|
-
if (contractName in DEFAULT_COMPONENT_KEYS) {
|
|
9324
|
-
return DEFAULT_COMPONENT_KEYS[contractName];
|
|
9307
|
+
function collectRouteSegmentNames(resolved) {
|
|
9308
|
+
const names = /* @__PURE__ */ new Set();
|
|
9309
|
+
for (const r of resolved) {
|
|
9310
|
+
for (const p of r.allParams) names.add(p);
|
|
9325
9311
|
}
|
|
9326
|
-
return
|
|
9312
|
+
return [...names].sort((a2, b) => a2.localeCompare(b));
|
|
9327
9313
|
}
|
|
9328
|
-
|
|
9329
|
-
|
|
9330
|
-
const checkPluginUpdateAction = createActionCaller("aiditor.checkPluginUpdate", "GET");
|
|
9331
|
-
const ensureProjectPluginAction = createStreamCaller("aiditor.ensureProjectPlugin");
|
|
9332
|
-
createActionCaller("aiditor.getPluginSetupStatus", "GET");
|
|
9333
|
-
const rerunPluginSetupAction = createActionCaller("aiditor.rerunPluginSetup", "GET");
|
|
9334
|
-
const syncAddPagePluginManifestAction = createActionCaller("aiditor.syncAddPagePluginManifest", "GET");
|
|
9335
|
-
const writePluginSourceAction = createActionCaller("aiditor.writePluginSource", "GET");
|
|
9336
|
-
async function listJayPlugins(refreshSetupStatus = false) {
|
|
9337
|
-
return listJayPluginsAction({ refreshSetupStatus });
|
|
9314
|
+
function routeHasDynamicSegment(route, paramName) {
|
|
9315
|
+
return route.includes(`[${paramName}]`);
|
|
9338
9316
|
}
|
|
9339
|
-
|
|
9340
|
-
return
|
|
9317
|
+
function routeHasAnyDynamicSegment(route) {
|
|
9318
|
+
return /\[[^\]]+\]/.test(route);
|
|
9341
9319
|
}
|
|
9342
|
-
function
|
|
9343
|
-
|
|
9344
|
-
const
|
|
9345
|
-
|
|
9320
|
+
function suggestMissingRouteSegments(route, segmentNames) {
|
|
9321
|
+
const trimmed = route.replace(/\/+$/, "") || "/";
|
|
9322
|
+
const missing = segmentNames.filter(
|
|
9323
|
+
(name) => !routeHasDynamicSegment(trimmed, name)
|
|
9324
|
+
);
|
|
9325
|
+
if (missing.length === 0) return null;
|
|
9326
|
+
const suffix = missing.map((n) => `[${n}]`).join("/");
|
|
9327
|
+
if (trimmed === "/") return `/${suffix}`;
|
|
9328
|
+
return `${trimmed}/${suffix}`;
|
|
9329
|
+
}
|
|
9330
|
+
function stripNavRowCore(row) {
|
|
9331
|
+
const { item: _item, ...viewRow } = row;
|
|
9332
|
+
return viewRow;
|
|
9333
|
+
}
|
|
9334
|
+
function stripNavRowForView(row) {
|
|
9335
|
+
return stripNavRowCore(row);
|
|
9336
|
+
}
|
|
9337
|
+
function stripMarkerAddMenuNavRowForPage(row) {
|
|
9338
|
+
return stripNavRowCore(row);
|
|
9339
|
+
}
|
|
9340
|
+
function stripMarkerPickerNavRowForVisual(row) {
|
|
9341
|
+
return stripNavRowCore(row);
|
|
9342
|
+
}
|
|
9343
|
+
function stripMarkerPickerNavRowForVideo(row) {
|
|
9344
|
+
return stripNavRowCore(row);
|
|
9345
|
+
}
|
|
9346
|
+
function stripMarkerPickerNavRowForSnapshot(row) {
|
|
9347
|
+
return stripNavRowCore(row);
|
|
9348
|
+
}
|
|
9349
|
+
function buildAddMenuNavRows(categories, panelOpen, selectedCategory, selectedSubCategory) {
|
|
9350
|
+
if (!panelOpen) return [];
|
|
9351
|
+
const cat = selectedCategory;
|
|
9352
|
+
if (!cat) {
|
|
9353
|
+
return categories.map((c) => ({
|
|
9354
|
+
rowKey: `cat:${c.category}`,
|
|
9355
|
+
label: c.category,
|
|
9356
|
+
value: c.category,
|
|
9357
|
+
kind: 0
|
|
9358
|
+
/* category */
|
|
9359
|
+
}));
|
|
9360
|
+
}
|
|
9361
|
+
const group = categories.find((c) => c.category === cat);
|
|
9362
|
+
if (!group) return [];
|
|
9363
|
+
const sub = selectedSubCategory;
|
|
9364
|
+
if (sub === null && group.subCategories.length > 1) {
|
|
9365
|
+
return group.subCategories.map((s) => ({
|
|
9366
|
+
rowKey: `sub:${cat}:${s.subCategory ?? ""}`,
|
|
9367
|
+
label: s.subCategory ?? "General",
|
|
9368
|
+
value: s.subCategory ?? "",
|
|
9369
|
+
kind: 1
|
|
9370
|
+
/* subCategory */
|
|
9371
|
+
}));
|
|
9372
|
+
}
|
|
9373
|
+
const subKey = sub ?? group.subCategories[0]?.subCategory ?? null;
|
|
9374
|
+
const items = group.subCategories.find((s) => s.subCategory === subKey)?.items ?? group.subCategories[0]?.items ?? [];
|
|
9375
|
+
return items.map((item) => ({
|
|
9376
|
+
rowKey: `item:${item.id}`,
|
|
9377
|
+
label: item.title,
|
|
9378
|
+
value: item.id,
|
|
9379
|
+
kind: 2,
|
|
9380
|
+
item
|
|
9381
|
+
}));
|
|
9382
|
+
}
|
|
9383
|
+
const listAddMenuItemsAction = createActionCaller("aiditor.listAddMenuItems", "GET");
|
|
9384
|
+
const resolveAddMenuContractParamsAction = createActionCaller("aiditor.resolveAddMenuContractParams", "GET");
|
|
9385
|
+
const syncAddMenuAttachmentsAction = createActionCaller("aiditor.syncAddMenuAttachments", "GET");
|
|
9386
|
+
async function listAddMenuItems() {
|
|
9387
|
+
return listAddMenuItemsAction({});
|
|
9388
|
+
}
|
|
9389
|
+
async function resolveContractParamsForItem(_projectDir, item) {
|
|
9390
|
+
const result = await resolveAddMenuContractParamsAction({
|
|
9391
|
+
itemId: item.id,
|
|
9392
|
+
pluginName: item.pluginName
|
|
9393
|
+
});
|
|
9394
|
+
if (!result.contractName || !result.pluginName) return null;
|
|
9395
|
+
return {
|
|
9396
|
+
contractName: result.contractName,
|
|
9397
|
+
pluginName: result.pluginName,
|
|
9398
|
+
requiredParams: result.requiredParams ?? [],
|
|
9399
|
+
allParams: result.allParams ?? []
|
|
9346
9400
|
};
|
|
9347
|
-
void (async () => {
|
|
9348
|
-
try {
|
|
9349
|
-
for await (const chunk of ensureProjectPluginAction(input)) {
|
|
9350
|
-
if (aborted) break;
|
|
9351
|
-
callbacks.onChunk(chunk);
|
|
9352
|
-
if (chunk.type === "done" || chunk.type === "error") {
|
|
9353
|
-
callbacks.onEnd();
|
|
9354
|
-
return;
|
|
9355
|
-
}
|
|
9356
|
-
}
|
|
9357
|
-
if (!aborted) callbacks.onEnd();
|
|
9358
|
-
} catch (err) {
|
|
9359
|
-
if (!aborted) {
|
|
9360
|
-
callbacks.onError(err instanceof Error ? err : new Error(String(err)));
|
|
9361
|
-
}
|
|
9362
|
-
}
|
|
9363
|
-
})();
|
|
9364
|
-
return abort;
|
|
9365
9401
|
}
|
|
9366
|
-
async function
|
|
9367
|
-
return
|
|
9402
|
+
async function syncAddMenuAttachments(input) {
|
|
9403
|
+
return syncAddMenuAttachmentsAction(input);
|
|
9368
9404
|
}
|
|
9369
|
-
|
|
9370
|
-
return
|
|
9405
|
+
function attachmentScopeKey(a2) {
|
|
9406
|
+
return a2.annotationId ?? "";
|
|
9371
9407
|
}
|
|
9372
|
-
|
|
9373
|
-
|
|
9408
|
+
function dedupeAddMenuAttachment(prev, next) {
|
|
9409
|
+
const scope = attachmentScopeKey(next);
|
|
9410
|
+
const exists = prev.some(
|
|
9411
|
+
(a2) => a2.itemId === next.itemId && attachmentScopeKey(a2) === scope
|
|
9412
|
+
);
|
|
9413
|
+
if (exists) return prev;
|
|
9414
|
+
return [...prev, next];
|
|
9374
9415
|
}
|
|
9375
|
-
|
|
9376
|
-
|
|
9377
|
-
|
|
9378
|
-
|
|
9379
|
-
if (!plugin) {
|
|
9380
|
-
plugin = {
|
|
9381
|
-
pluginName,
|
|
9382
|
-
packageName,
|
|
9383
|
-
contracts: [],
|
|
9384
|
-
installStatus: "not_needed"
|
|
9385
|
-
};
|
|
9386
|
-
next.push(plugin);
|
|
9387
|
-
}
|
|
9388
|
-
const exists = plugin.contracts.some((c) => c.contractName === contractName);
|
|
9389
|
-
const contracts = exists ? plugin.contracts.map(
|
|
9390
|
-
(c) => c.contractName === contractName ? { ...c, componentKey } : c
|
|
9391
|
-
) : [...plugin.contracts, { contractName, componentKey }];
|
|
9392
|
-
return next.map(
|
|
9393
|
-
(p) => p.pluginName === pluginName ? { ...p, packageName, contracts } : p
|
|
9416
|
+
function removeAddMenuAttachment(prev, itemId, annotationId) {
|
|
9417
|
+
const scope = annotationId ?? "";
|
|
9418
|
+
return prev.filter(
|
|
9419
|
+
(a2) => !(a2.itemId === itemId && attachmentScopeKey(a2) === scope)
|
|
9394
9420
|
);
|
|
9395
9421
|
}
|
|
9396
|
-
function
|
|
9397
|
-
|
|
9398
|
-
|
|
9399
|
-
|
|
9400
|
-
|
|
9401
|
-
|
|
9402
|
-
|
|
9403
|
-
|
|
9404
|
-
|
|
9405
|
-
|
|
9406
|
-
|
|
9407
|
-
const
|
|
9408
|
-
const [
|
|
9409
|
-
const [
|
|
9410
|
-
const [
|
|
9422
|
+
function initAddMenuPanel(deps) {
|
|
9423
|
+
const [attachments, setAttachments] = createSignal([]);
|
|
9424
|
+
const [catalogItems, setCatalogItems] = createSignal([]);
|
|
9425
|
+
const [catalogCategories, setCatalogCategories] = createSignal([]);
|
|
9426
|
+
const [catalogWarnings, setCatalogWarnings] = createSignal([]);
|
|
9427
|
+
const [panelOpen, setPanelOpen] = createSignal(false);
|
|
9428
|
+
const [selectedCategory, setSelectedCategory] = createSignal("");
|
|
9429
|
+
const [selectedSubCategory, setSelectedSubCategory] = createSignal(null);
|
|
9430
|
+
const [routeMigration, setRouteMigration] = createSignal(null);
|
|
9431
|
+
const [paramCollisionWarning, setParamCollisionWarning] = createSignal("");
|
|
9432
|
+
const [routeParamHint, setRouteParamHint] = createSignal("");
|
|
9433
|
+
const [pendingRouteParamItem, setPendingRouteParamItem] = createSignal(null);
|
|
9434
|
+
const [showRouteParamConfirm, setShowRouteParamConfirm] = createSignal(false);
|
|
9435
|
+
const [catalogLoading, setCatalogLoading] = createSignal(false);
|
|
9436
|
+
const [catalogLoaded, setCatalogLoaded] = createSignal(false);
|
|
9411
9437
|
let syncTimer;
|
|
9412
|
-
const
|
|
9413
|
-
|
|
9414
|
-
|
|
9415
|
-
|
|
9438
|
+
const itemById = createMemo(() => {
|
|
9439
|
+
const map = /* @__PURE__ */ new Map();
|
|
9440
|
+
for (const item of catalogItems()) map.set(item.id, item);
|
|
9441
|
+
return map;
|
|
9442
|
+
});
|
|
9443
|
+
const chipRows = createMemo(
|
|
9444
|
+
() => attachments().map((a2) => {
|
|
9445
|
+
const item = itemById().get(a2.itemId);
|
|
9446
|
+
return {
|
|
9447
|
+
rowKey: `${a2.itemId}:${a2.annotationId ?? "request"}`,
|
|
9448
|
+
itemId: a2.itemId,
|
|
9449
|
+
title: item?.title ?? a2.itemId,
|
|
9450
|
+
subtitle: item?.pluginName ?? item?.id.split(":")[0] ?? "",
|
|
9451
|
+
annotationId: a2.annotationId
|
|
9452
|
+
};
|
|
9453
|
+
})
|
|
9416
9454
|
);
|
|
9417
|
-
const
|
|
9418
|
-
|
|
9419
|
-
|
|
9420
|
-
rowKey: p.pluginName,
|
|
9421
|
-
value: p.pluginName,
|
|
9422
|
-
label: p.pluginName
|
|
9423
|
-
}));
|
|
9424
|
-
options.push({
|
|
9425
|
-
rowKey: ADD_PAGE_MANAGE_PLUGINS_VALUE,
|
|
9426
|
-
value: ADD_PAGE_MANAGE_PLUGINS_VALUE,
|
|
9427
|
-
label: "Manage plugins…"
|
|
9428
|
-
});
|
|
9429
|
-
return options;
|
|
9430
|
-
}
|
|
9455
|
+
const showAddMenuPanel = createMemo(() => true);
|
|
9456
|
+
const showAddMenuEmptyHint = createMemo(
|
|
9457
|
+
() => catalogItems().length === 0 && !catalogLoading()
|
|
9431
9458
|
);
|
|
9432
|
-
const
|
|
9433
|
-
|
|
9434
|
-
|
|
9435
|
-
|
|
9436
|
-
|
|
9437
|
-
|
|
9438
|
-
|
|
9439
|
-
|
|
9440
|
-
rowKey: `${pluginName}:${c.contractName}`,
|
|
9441
|
-
pluginName,
|
|
9442
|
-
packageName: entry.packageName,
|
|
9443
|
-
contractName: c.contractName,
|
|
9444
|
-
description: c.description ?? "",
|
|
9445
|
-
onPage: !!sel?.contracts.some((x) => x.contractName === c.contractName),
|
|
9446
|
-
componentKey: sel?.contracts.find((x) => x.contractName === c.contractName)?.componentKey ?? getDefaultComponentKey(c.contractName)
|
|
9447
|
-
}));
|
|
9448
|
-
}
|
|
9459
|
+
const showAddMenuChips = createMemo(() => chipRows().length > 0);
|
|
9460
|
+
const menuNavRows = createMemo(
|
|
9461
|
+
() => buildAddMenuNavRows(
|
|
9462
|
+
catalogCategories(),
|
|
9463
|
+
panelOpen(),
|
|
9464
|
+
selectedCategory(),
|
|
9465
|
+
selectedSubCategory()
|
|
9466
|
+
)
|
|
9449
9467
|
);
|
|
9450
|
-
const
|
|
9451
|
-
|
|
9452
|
-
for (const plugin of selectedPlugins()) {
|
|
9453
|
-
for (const contract of plugin.contracts) {
|
|
9454
|
-
chips.push({
|
|
9455
|
-
rowKey: `${plugin.pluginName}:${contract.contractName}`,
|
|
9456
|
-
label: `${plugin.pluginName} · ${contract.contractName}`,
|
|
9457
|
-
pluginName: plugin.pluginName,
|
|
9458
|
-
packageName: plugin.packageName,
|
|
9459
|
-
contractName: contract.contractName,
|
|
9460
|
-
componentKey: contract.componentKey ?? getDefaultComponentKey(contract.contractName)
|
|
9461
|
-
});
|
|
9462
|
-
}
|
|
9463
|
-
}
|
|
9464
|
-
return chips;
|
|
9465
|
-
});
|
|
9466
|
-
const showContractPicker = createMemo(() => pickerPlugin().length > 0);
|
|
9467
|
-
const showPagePluginsZone = createMemo(() => true);
|
|
9468
|
-
const showPluginsPanel = createMemo(
|
|
9469
|
-
() => projectPlugins.pluginsLoaded() && projectPlugins.pluginsList().length > 0
|
|
9468
|
+
const menuNavRowsForView = createMemo(
|
|
9469
|
+
() => menuNavRows().map(stripNavRowForView)
|
|
9470
9470
|
);
|
|
9471
|
-
const
|
|
9472
|
-
|
|
9471
|
+
const [routeSegmentNames, setRouteSegmentNames] = createSignal([]);
|
|
9472
|
+
const routeParamRows = createMemo(
|
|
9473
|
+
() => routeSegmentNames().map((name) => ({
|
|
9474
|
+
rowKey: name,
|
|
9475
|
+
name
|
|
9476
|
+
}))
|
|
9473
9477
|
);
|
|
9474
|
-
|
|
9475
|
-
|
|
9476
|
-
|
|
9477
|
-
|
|
9478
|
+
async function refreshCatalog() {
|
|
9479
|
+
setCatalogLoading(true);
|
|
9480
|
+
try {
|
|
9481
|
+
const result = await listAddMenuItems();
|
|
9482
|
+
setCatalogItems(result.items);
|
|
9483
|
+
setCatalogCategories(result.categories);
|
|
9484
|
+
setCatalogWarnings(result.warnings);
|
|
9485
|
+
if (result.warnings.length > 0) {
|
|
9486
|
+
console.warn("[aiditor] Add Menu catalog warnings:", result.warnings);
|
|
9487
|
+
}
|
|
9488
|
+
} catch (err) {
|
|
9489
|
+
console.error("[aiditor] listAddMenuItems failed:", err);
|
|
9490
|
+
setCatalogItems([]);
|
|
9491
|
+
setCatalogCategories([]);
|
|
9492
|
+
setCatalogWarnings([]);
|
|
9493
|
+
} finally {
|
|
9494
|
+
setCatalogLoaded(true);
|
|
9495
|
+
setCatalogLoading(false);
|
|
9496
|
+
}
|
|
9497
|
+
}
|
|
9498
|
+
async function ensureCatalogLoaded() {
|
|
9499
|
+
if (catalogLoaded() || catalogLoading()) return;
|
|
9500
|
+
await refreshCatalog();
|
|
9501
|
+
}
|
|
9502
|
+
async function updateRouteHelpers() {
|
|
9503
|
+
const resolved = [];
|
|
9504
|
+
for (const a2 of attachments()) {
|
|
9505
|
+
const item = itemById().get(a2.itemId);
|
|
9506
|
+
if (!item) continue;
|
|
9507
|
+
const params = await resolveContractParamsForItem(
|
|
9508
|
+
deps.projectDir(),
|
|
9509
|
+
item
|
|
9510
|
+
);
|
|
9511
|
+
if (params) resolved.push(params);
|
|
9512
|
+
}
|
|
9513
|
+
const collisions = detectRequiredParamCollisions(resolved);
|
|
9514
|
+
setParamCollisionWarning(collisions[0]?.message ?? "");
|
|
9515
|
+
const segments = collectRouteSegmentNames(resolved);
|
|
9516
|
+
if (segments.length === 0) {
|
|
9517
|
+
setRouteParamHint("");
|
|
9518
|
+
return segments;
|
|
9519
|
+
}
|
|
9520
|
+
const route = deps.getPageRoute();
|
|
9521
|
+
const suggested = suggestMissingRouteSegments(route, segments);
|
|
9522
|
+
setRouteParamHint(
|
|
9523
|
+
suggested && suggested !== route ? `Suggested route segments: ${suggested}` : ""
|
|
9478
9524
|
);
|
|
9479
|
-
|
|
9525
|
+
setRouteSegmentNames(segments);
|
|
9526
|
+
return segments;
|
|
9527
|
+
}
|
|
9480
9528
|
function scheduleManifestSync() {
|
|
9481
9529
|
const requestId = deps.getRequestId();
|
|
9482
9530
|
if (!requestId) return;
|
|
9483
9531
|
if (syncTimer) clearTimeout(syncTimer);
|
|
9484
9532
|
syncTimer = setTimeout(() => {
|
|
9485
|
-
void
|
|
9533
|
+
void syncAddMenuAttachments({
|
|
9486
9534
|
requestId,
|
|
9487
|
-
|
|
9488
|
-
|
|
9489
|
-
if (res.ok && res.contentMd) {
|
|
9490
|
-
deps.setContentMd(res.contentMd);
|
|
9491
|
-
}
|
|
9535
|
+
addMenuAttachments: attachments(),
|
|
9536
|
+
routeMigration: routeMigration() ?? void 0
|
|
9492
9537
|
});
|
|
9493
9538
|
}, 300);
|
|
9494
9539
|
}
|
|
9495
|
-
function
|
|
9496
|
-
|
|
9497
|
-
|
|
9498
|
-
|
|
9499
|
-
pluginName,
|
|
9500
|
-
packageName,
|
|
9501
|
-
contractName,
|
|
9502
|
-
componentKey
|
|
9503
|
-
)
|
|
9504
|
-
);
|
|
9505
|
-
scheduleManifestSync();
|
|
9506
|
-
}
|
|
9507
|
-
function removeFromPage(pluginName, packageName, contractName) {
|
|
9508
|
-
setSelectedPlugins(
|
|
9509
|
-
(prev) => removePagePluginContract(prev, pluginName, contractName)
|
|
9540
|
+
async function commitAttachment(item, annotationId) {
|
|
9541
|
+
deps.preserveEditorContent();
|
|
9542
|
+
setAttachments(
|
|
9543
|
+
(prev) => dedupeAddMenuAttachment(prev, { itemId: item.id, annotationId })
|
|
9510
9544
|
);
|
|
9545
|
+
await updateRouteHelpers();
|
|
9511
9546
|
scheduleManifestSync();
|
|
9512
|
-
|
|
9513
|
-
|
|
9514
|
-
|
|
9515
|
-
|
|
9516
|
-
|
|
9517
|
-
|
|
9547
|
+
setPanelOpen(false);
|
|
9548
|
+
setSelectedCategory("");
|
|
9549
|
+
setSelectedSubCategory(null);
|
|
9550
|
+
}
|
|
9551
|
+
async function tryAddItem(item, annotationId) {
|
|
9552
|
+
const params = await resolveContractParamsForItem(deps.projectDir(), item);
|
|
9553
|
+
const hasRouteParams = !!params && params.allParams.length > 0;
|
|
9554
|
+
if (deps.changeRequestMode?.() && hasRouteParams && deps.getCurrentRoute && !routeHasAnyDynamicSegment(deps.getCurrentRoute() ?? "")) {
|
|
9555
|
+
setPendingRouteParamItem(item);
|
|
9556
|
+
setShowRouteParamConfirm(true);
|
|
9518
9557
|
return;
|
|
9519
9558
|
}
|
|
9520
|
-
|
|
9521
|
-
|
|
9522
|
-
|
|
9523
|
-
|
|
9524
|
-
|
|
9559
|
+
await commitAttachment(item, annotationId);
|
|
9560
|
+
}
|
|
9561
|
+
async function confirmRouteParamAttach(annotationId) {
|
|
9562
|
+
const item = pendingRouteParamItem();
|
|
9563
|
+
if (!item) return;
|
|
9564
|
+
const current = deps.getCurrentRoute?.() ?? "/";
|
|
9565
|
+
const params = await resolveContractParamsForItem(deps.projectDir(), item);
|
|
9566
|
+
const segments = params ? collectRouteSegmentNames([params]) : [];
|
|
9567
|
+
const planned = suggestMissingRouteSegments(current, segments) ?? `${current}/[slug]`;
|
|
9568
|
+
deps.setPlannedRoute?.(planned);
|
|
9569
|
+
setRouteMigration({
|
|
9570
|
+
currentRoute: current,
|
|
9571
|
+
plannedRoute: planned,
|
|
9572
|
+
reason: "add-menu-route-param-component",
|
|
9573
|
+
triggeringItemIds: [item.id]
|
|
9574
|
+
});
|
|
9575
|
+
setShowRouteParamConfirm(false);
|
|
9576
|
+
setPendingRouteParamItem(null);
|
|
9577
|
+
await commitAttachment(item, annotationId);
|
|
9578
|
+
}
|
|
9579
|
+
function cancelRouteParamAttach() {
|
|
9580
|
+
setShowRouteParamConfirm(false);
|
|
9581
|
+
setPendingRouteParamItem(null);
|
|
9582
|
+
}
|
|
9583
|
+
function removeChip(itemId, annotationId) {
|
|
9584
|
+
deps.preserveEditorContent();
|
|
9585
|
+
setAttachments(
|
|
9586
|
+
(prev) => removeAddMenuAttachment(prev, itemId, annotationId)
|
|
9587
|
+
);
|
|
9588
|
+
void updateRouteHelpers();
|
|
9589
|
+
scheduleManifestSync();
|
|
9525
9590
|
}
|
|
9526
|
-
function
|
|
9527
|
-
|
|
9528
|
-
|
|
9529
|
-
|
|
9591
|
+
function openPanel() {
|
|
9592
|
+
void ensureCatalogLoaded();
|
|
9593
|
+
setPanelOpen(true);
|
|
9594
|
+
setSelectedCategory("");
|
|
9595
|
+
setSelectedSubCategory(null);
|
|
9596
|
+
}
|
|
9597
|
+
function closePanel() {
|
|
9598
|
+
setPanelOpen(false);
|
|
9599
|
+
}
|
|
9600
|
+
function resetAddMenuPanel() {
|
|
9601
|
+
setAttachments([]);
|
|
9602
|
+
setRouteMigration(null);
|
|
9603
|
+
setParamCollisionWarning("");
|
|
9604
|
+
setRouteParamHint("");
|
|
9605
|
+
setPanelOpen(false);
|
|
9530
9606
|
if (syncTimer) clearTimeout(syncTimer);
|
|
9531
9607
|
}
|
|
9532
|
-
function
|
|
9533
|
-
|
|
9534
|
-
|
|
9535
|
-
|
|
9536
|
-
|
|
9608
|
+
function bindRouteParamButtons(el) {
|
|
9609
|
+
el?.onclick(({ event }) => {
|
|
9610
|
+
const paramBtn = event.target.closest(
|
|
9611
|
+
"[data-add-menu-param]"
|
|
9612
|
+
);
|
|
9613
|
+
if (paramBtn?.dataset.param) {
|
|
9614
|
+
deps.insertRouteParam(paramBtn.dataset.param);
|
|
9537
9615
|
}
|
|
9538
|
-
);
|
|
9539
|
-
|
|
9540
|
-
|
|
9541
|
-
|
|
9542
|
-
|
|
9543
|
-
|
|
9544
|
-
|
|
9545
|
-
|
|
9546
|
-
|
|
9547
|
-
|
|
9548
|
-
"[data-add-page-add-contract]"
|
|
9549
|
-
);
|
|
9550
|
-
if (addBtn?.dataset.plugin && addBtn.dataset.contract && addBtn.dataset.package) {
|
|
9551
|
-
addContractToPage(
|
|
9552
|
-
addBtn.dataset.plugin,
|
|
9553
|
-
addBtn.dataset.package,
|
|
9554
|
-
addBtn.dataset.contract,
|
|
9555
|
-
addBtn.dataset.key ?? getDefaultComponentKey(addBtn.dataset.contract)
|
|
9556
|
-
);
|
|
9557
|
-
return;
|
|
9558
|
-
}
|
|
9559
|
-
const removeChip = target.closest(
|
|
9560
|
-
"[data-add-page-remove-chip]"
|
|
9561
|
-
);
|
|
9562
|
-
if (removeChip?.dataset.plugin && removeChip.dataset.contract && removeChip.dataset.package) {
|
|
9563
|
-
removeFromPage(
|
|
9564
|
-
removeChip.dataset.plugin,
|
|
9565
|
-
removeChip.dataset.package,
|
|
9566
|
-
removeChip.dataset.contract
|
|
9567
|
-
);
|
|
9568
|
-
}
|
|
9616
|
+
});
|
|
9617
|
+
}
|
|
9618
|
+
function bindAddMenuPanelRefs(refs) {
|
|
9619
|
+
bindRouteParamButtons(refs.addPageRouteParamsPanel);
|
|
9620
|
+
refs.addMenuPanel?.onclick(({ event }) => {
|
|
9621
|
+
const target = event.target;
|
|
9622
|
+
const openBtn = target.closest("[data-add-menu-open]");
|
|
9623
|
+
if (openBtn) {
|
|
9624
|
+
openPanel();
|
|
9625
|
+
return;
|
|
9569
9626
|
}
|
|
9570
|
-
|
|
9627
|
+
const closeBtn = target.closest("[data-add-menu-close]");
|
|
9628
|
+
if (closeBtn) {
|
|
9629
|
+
closePanel();
|
|
9630
|
+
return;
|
|
9631
|
+
}
|
|
9632
|
+
const manage = target.closest("[data-add-menu-manage-plugins]");
|
|
9633
|
+
if (manage) {
|
|
9634
|
+
deps.openProjectSettings();
|
|
9635
|
+
return;
|
|
9636
|
+
}
|
|
9637
|
+
const catBtn = target.closest(
|
|
9638
|
+
"[data-add-menu-category]"
|
|
9639
|
+
);
|
|
9640
|
+
if (catBtn?.dataset.category) {
|
|
9641
|
+
setSelectedCategory(catBtn.dataset.category);
|
|
9642
|
+
setSelectedSubCategory(null);
|
|
9643
|
+
return;
|
|
9644
|
+
}
|
|
9645
|
+
const subBtn = target.closest(
|
|
9646
|
+
"[data-add-menu-subcategory]"
|
|
9647
|
+
);
|
|
9648
|
+
if (subBtn?.dataset.subcategory !== void 0) {
|
|
9649
|
+
setSelectedSubCategory(subBtn.dataset.subcategory || null);
|
|
9650
|
+
return;
|
|
9651
|
+
}
|
|
9652
|
+
const pickBtn = target.closest(
|
|
9653
|
+
"[data-add-menu-pick]"
|
|
9654
|
+
);
|
|
9655
|
+
if (pickBtn?.dataset.itemId) {
|
|
9656
|
+
const item = itemById().get(pickBtn.dataset.itemId);
|
|
9657
|
+
if (item) void tryAddItem(item);
|
|
9658
|
+
return;
|
|
9659
|
+
}
|
|
9660
|
+
const removeBtn = target.closest(
|
|
9661
|
+
"[data-add-menu-remove-chip]"
|
|
9662
|
+
);
|
|
9663
|
+
if (removeBtn?.dataset.itemId) {
|
|
9664
|
+
removeChip(removeBtn.dataset.itemId, removeBtn.dataset.annotationId);
|
|
9665
|
+
return;
|
|
9666
|
+
}
|
|
9667
|
+
const paramBtn = target.closest(
|
|
9668
|
+
"[data-add-menu-param]"
|
|
9669
|
+
);
|
|
9670
|
+
if (paramBtn?.dataset.param) {
|
|
9671
|
+
deps.insertRouteParam(paramBtn.dataset.param);
|
|
9672
|
+
return;
|
|
9673
|
+
}
|
|
9674
|
+
const atBtn = target.closest(
|
|
9675
|
+
"[data-add-menu-at-title]"
|
|
9676
|
+
);
|
|
9677
|
+
if (atBtn?.dataset.title) {
|
|
9678
|
+
deps.insertAtCursor(`@${atBtn.dataset.title}`);
|
|
9679
|
+
return;
|
|
9680
|
+
}
|
|
9681
|
+
const confirmBtn = target.closest("[data-add-menu-route-confirm]");
|
|
9682
|
+
if (confirmBtn) {
|
|
9683
|
+
void confirmRouteParamAttach();
|
|
9684
|
+
return;
|
|
9685
|
+
}
|
|
9686
|
+
const cancelBtn = target.closest("[data-add-menu-route-cancel]");
|
|
9687
|
+
if (cancelBtn) cancelRouteParamAttach();
|
|
9688
|
+
});
|
|
9571
9689
|
}
|
|
9572
9690
|
return {
|
|
9573
|
-
|
|
9574
|
-
|
|
9691
|
+
attachments,
|
|
9692
|
+
setAttachments,
|
|
9693
|
+
catalogItems,
|
|
9694
|
+
refreshCatalog,
|
|
9695
|
+
ensureCatalogLoaded,
|
|
9696
|
+
panelOpen,
|
|
9697
|
+
openPanel,
|
|
9698
|
+
closePanel,
|
|
9699
|
+
chipRows,
|
|
9700
|
+
menuNavRows: menuNavRowsForView,
|
|
9701
|
+
selectedCategory,
|
|
9702
|
+
showAddMenuPanel,
|
|
9703
|
+
showAddMenuEmptyHint,
|
|
9704
|
+
showAddMenuChips,
|
|
9705
|
+
showAddMenuPopover: panelOpen,
|
|
9706
|
+
catalogLoading,
|
|
9707
|
+
catalogWarnings,
|
|
9708
|
+
paramCollisionWarning,
|
|
9709
|
+
routeParamHint,
|
|
9710
|
+
routeSegmentButtons: routeSegmentNames,
|
|
9711
|
+
routeParamRows,
|
|
9712
|
+
showRouteParamConfirm,
|
|
9713
|
+
pendingRouteParamTitle: createMemo(
|
|
9714
|
+
() => pendingRouteParamItem()?.title ?? ""
|
|
9715
|
+
),
|
|
9575
9716
|
scheduleManifestSync,
|
|
9576
9717
|
syncManifestNow: async () => {
|
|
9577
9718
|
const requestId = deps.getRequestId();
|
|
9578
9719
|
if (!requestId) return;
|
|
9579
|
-
|
|
9720
|
+
await syncAddMenuAttachments({
|
|
9580
9721
|
requestId,
|
|
9581
|
-
|
|
9722
|
+
addMenuAttachments: attachments(),
|
|
9723
|
+
routeMigration: routeMigration() ?? void 0
|
|
9582
9724
|
});
|
|
9583
|
-
if (res.ok && res.contentMd) deps.setContentMd(res.contentMd);
|
|
9584
9725
|
},
|
|
9585
|
-
|
|
9586
|
-
|
|
9587
|
-
|
|
9588
|
-
|
|
9589
|
-
|
|
9590
|
-
|
|
9591
|
-
|
|
9592
|
-
addPageContractPickerRows,
|
|
9593
|
-
pagePluginChipRows,
|
|
9594
|
-
showContractPicker,
|
|
9595
|
-
showPagePluginsZone,
|
|
9596
|
-
showPluginsPanel,
|
|
9597
|
-
showPagePluginsEmptyHint,
|
|
9598
|
-
pluginsBlockCreatePage,
|
|
9599
|
-
pickerPlugin,
|
|
9600
|
-
setPickerPlugin,
|
|
9601
|
-
handlePickerChange,
|
|
9602
|
-
resetPluginsPanel
|
|
9726
|
+
tryAddItem,
|
|
9727
|
+
removeChip,
|
|
9728
|
+
bindAddMenuPanelRefs,
|
|
9729
|
+
resetAddMenuPanel,
|
|
9730
|
+
updateRouteHelpers,
|
|
9731
|
+
routeMigration,
|
|
9732
|
+
setRouteMigration
|
|
9603
9733
|
};
|
|
9604
9734
|
}
|
|
9605
9735
|
function tryJayRefExec(refObj, fn) {
|
|
@@ -9627,11 +9757,44 @@ function initAddPageComposer(deps) {
|
|
|
9627
9757
|
const [addPageShowDesignHint, setAddPageShowDesignHint] = createSignal(false);
|
|
9628
9758
|
const [addPageIsDynamicRoute, setAddPageIsDynamicRoute] = createSignal(false);
|
|
9629
9759
|
const [addPageSubmitting, setAddPageSubmitting] = createSignal(false);
|
|
9630
|
-
const
|
|
9760
|
+
const addMenuPanel = initAddMenuPanel({
|
|
9631
9761
|
projectPlugins: deps.projectPlugins,
|
|
9762
|
+
projectDir: deps.projectDir,
|
|
9632
9763
|
getRequestId: () => addPageRequestId(),
|
|
9633
|
-
|
|
9634
|
-
|
|
9764
|
+
preserveEditorContent: () => {
|
|
9765
|
+
const el = contentTextareaEl;
|
|
9766
|
+
if (el) setAddPageContentMd(el.value);
|
|
9767
|
+
},
|
|
9768
|
+
getPageRoute: () => addPageRoute(),
|
|
9769
|
+
setPageRoute: setAddPageRoute,
|
|
9770
|
+
insertAtCursor: (text) => {
|
|
9771
|
+
const current = contentTextareaEl?.value ?? addPageContentMd();
|
|
9772
|
+
const { next, cursor } = insertTextAtRange(
|
|
9773
|
+
current,
|
|
9774
|
+
text,
|
|
9775
|
+
contentTextareaEl?.selectionStart ?? contentSelectionStart,
|
|
9776
|
+
contentTextareaEl?.selectionEnd ?? contentSelectionEnd
|
|
9777
|
+
);
|
|
9778
|
+
setAddPageContentMd(next);
|
|
9779
|
+
contentSelectionStart = contentSelectionEnd = cursor;
|
|
9780
|
+
const el = contentTextareaEl;
|
|
9781
|
+
if (el) {
|
|
9782
|
+
queueMicrotask(() => {
|
|
9783
|
+
el.selectionStart = cursor;
|
|
9784
|
+
el.selectionEnd = cursor;
|
|
9785
|
+
el.focus();
|
|
9786
|
+
});
|
|
9787
|
+
}
|
|
9788
|
+
},
|
|
9789
|
+
insertRouteParam: (paramName) => {
|
|
9790
|
+
const next = insertRouteParamInField(
|
|
9791
|
+
routeInputEl,
|
|
9792
|
+
addPageRoute(),
|
|
9793
|
+
paramName
|
|
9794
|
+
);
|
|
9795
|
+
setAddPageRoute(next);
|
|
9796
|
+
scheduleRouteCheck(next);
|
|
9797
|
+
},
|
|
9635
9798
|
openProjectSettings: deps.openProjectSettings
|
|
9636
9799
|
});
|
|
9637
9800
|
const briefFillPanel = initAddPageBriefFillPanel({
|
|
@@ -9653,8 +9816,20 @@ function initAddPageComposer(deps) {
|
|
|
9653
9816
|
setComposerError: setAddPageComposerError
|
|
9654
9817
|
});
|
|
9655
9818
|
let routeCheckTimer;
|
|
9819
|
+
let routeInputEl = null;
|
|
9656
9820
|
let contentTextareaEl = null;
|
|
9821
|
+
let contentSelectionStart = 0;
|
|
9822
|
+
let contentSelectionEnd = 0;
|
|
9657
9823
|
let designTextareaEl = null;
|
|
9824
|
+
let designSelectionStart = 0;
|
|
9825
|
+
function trackTextareaSelection(el) {
|
|
9826
|
+
contentSelectionStart = el.selectionStart ?? 0;
|
|
9827
|
+
contentSelectionEnd = el.selectionEnd ?? contentSelectionStart;
|
|
9828
|
+
}
|
|
9829
|
+
function trackDesignTextareaSelection(el) {
|
|
9830
|
+
designSelectionStart = el.selectionStart ?? 0;
|
|
9831
|
+
el.selectionEnd ?? designSelectionStart;
|
|
9832
|
+
}
|
|
9658
9833
|
const showAddPageRouteError = createMemo(
|
|
9659
9834
|
() => addPageRouteError().length > 0
|
|
9660
9835
|
);
|
|
@@ -9683,7 +9858,7 @@ function initAddPageComposer(deps) {
|
|
|
9683
9858
|
if (deps.isRunning() || addPageSubmitting() || briefFillPanel.briefFillGenerating()) {
|
|
9684
9859
|
return false;
|
|
9685
9860
|
}
|
|
9686
|
-
if (
|
|
9861
|
+
if (deps.projectPlugins.installInProgress()) return false;
|
|
9687
9862
|
const route = addPageRoute().trim();
|
|
9688
9863
|
if (!route || addPageRouteError()) return false;
|
|
9689
9864
|
const hasMd = addPageContentMd().trim().length > 0 || addPageDesignMd().trim().length > 0;
|
|
@@ -9704,13 +9879,14 @@ function initAddPageComposer(deps) {
|
|
|
9704
9879
|
setAddPageAttachments([]);
|
|
9705
9880
|
setAddPageShowDesignHint(false);
|
|
9706
9881
|
setAddPageIsDynamicRoute(false);
|
|
9707
|
-
|
|
9882
|
+
addMenuPanel.resetAddMenuPanel();
|
|
9708
9883
|
briefFillPanel.resetBriefFill();
|
|
9709
9884
|
}
|
|
9710
9885
|
function openAddPageComposer() {
|
|
9711
9886
|
resetAddPageComposer();
|
|
9712
9887
|
setShowAddPageComposer(true);
|
|
9713
9888
|
void deps.projectPlugins.refreshPluginsList();
|
|
9889
|
+
void addMenuPanel.ensureCatalogLoaded();
|
|
9714
9890
|
}
|
|
9715
9891
|
async function refreshCurrentPageBriefAvailability() {
|
|
9716
9892
|
const filePath = deps.selectedPageFilePath().trim();
|
|
@@ -9985,7 +10161,7 @@ function initAddPageComposer(deps) {
|
|
|
9985
10161
|
deps.setIsRunning(true);
|
|
9986
10162
|
deps.setBottomPanelCollapsed(false);
|
|
9987
10163
|
deps.setAddPageResultBanner(null);
|
|
9988
|
-
await
|
|
10164
|
+
await addMenuPanel.syncManifestNow();
|
|
9989
10165
|
deps.getStopStream()?.();
|
|
9990
10166
|
const abort = submitAddPageStream(
|
|
9991
10167
|
{
|
|
@@ -10075,17 +10251,37 @@ function initAddPageComposer(deps) {
|
|
|
10075
10251
|
});
|
|
10076
10252
|
refs.addPageCreateBtn.onclick(() => submitAddPage(false));
|
|
10077
10253
|
refs.addPageRouteInput.oninput(({ event }) => {
|
|
10078
|
-
|
|
10254
|
+
routeInputEl = event.target;
|
|
10255
|
+
const v = routeInputEl.value;
|
|
10079
10256
|
setAddPageRoute(v);
|
|
10080
10257
|
scheduleRouteCheck(v);
|
|
10081
10258
|
});
|
|
10259
|
+
refs.addPageRouteInput.onfocus(({ event }) => {
|
|
10260
|
+
routeInputEl = event.target;
|
|
10261
|
+
});
|
|
10262
|
+
refs.addPageContentMd.onfocus(({ event }) => {
|
|
10263
|
+
contentTextareaEl = event.target;
|
|
10264
|
+
trackTextareaSelection(contentTextareaEl);
|
|
10265
|
+
});
|
|
10082
10266
|
refs.addPageContentMd.oninput(({ event }) => {
|
|
10083
10267
|
contentTextareaEl = event.target;
|
|
10268
|
+
trackTextareaSelection(contentTextareaEl);
|
|
10084
10269
|
setAddPageContentMd(contentTextareaEl.value);
|
|
10085
10270
|
updateDesignHint();
|
|
10086
10271
|
});
|
|
10272
|
+
refs.addPageContentMd.addEventListener(
|
|
10273
|
+
"select",
|
|
10274
|
+
(ev) => {
|
|
10275
|
+
trackTextareaSelection(ev.event.target);
|
|
10276
|
+
}
|
|
10277
|
+
);
|
|
10278
|
+
refs.addPageDesignMd.onfocus(({ event }) => {
|
|
10279
|
+
designTextareaEl = event.target;
|
|
10280
|
+
trackDesignTextareaSelection(designTextareaEl);
|
|
10281
|
+
});
|
|
10087
10282
|
refs.addPageDesignMd.oninput(({ event }) => {
|
|
10088
10283
|
designTextareaEl = event.target;
|
|
10284
|
+
trackDesignTextareaSelection(designTextareaEl);
|
|
10089
10285
|
setAddPageDesignMd(designTextareaEl.value);
|
|
10090
10286
|
updateDesignHint();
|
|
10091
10287
|
});
|
|
@@ -10146,7 +10342,7 @@ function initAddPageComposer(deps) {
|
|
|
10146
10342
|
el.click();
|
|
10147
10343
|
});
|
|
10148
10344
|
});
|
|
10149
|
-
|
|
10345
|
+
addMenuPanel.bindAddMenuPanelRefs(refs);
|
|
10150
10346
|
briefFillPanel.bindBriefFillRefs(refs);
|
|
10151
10347
|
refs.addPageAttachmentsList.onchange(
|
|
10152
10348
|
({ event }) => {
|
|
@@ -10199,18 +10395,21 @@ function initAddPageComposer(deps) {
|
|
|
10199
10395
|
addPageUploadHint,
|
|
10200
10396
|
addPageAttachmentRows: addPageAttachmentDisplayRows,
|
|
10201
10397
|
addPageShowDesignHint,
|
|
10202
|
-
|
|
10203
|
-
|
|
10204
|
-
|
|
10205
|
-
|
|
10206
|
-
|
|
10207
|
-
|
|
10208
|
-
|
|
10209
|
-
|
|
10210
|
-
|
|
10211
|
-
|
|
10398
|
+
showAddMenuPanel: addMenuPanel.showAddMenuPanel,
|
|
10399
|
+
showAddMenuChips: addMenuPanel.showAddMenuChips,
|
|
10400
|
+
addMenuChipRows: addMenuPanel.chipRows,
|
|
10401
|
+
showAddMenuEmptyHint: addMenuPanel.showAddMenuEmptyHint,
|
|
10402
|
+
showAddMenuPopover: addMenuPanel.showAddMenuPopover,
|
|
10403
|
+
addMenuNavRows: addMenuPanel.menuNavRows,
|
|
10404
|
+
addMenuSelectedCategory: addMenuPanel.selectedCategory,
|
|
10405
|
+
addMenuParamCollisionWarning: addMenuPanel.paramCollisionWarning,
|
|
10406
|
+
addMenuRouteParamHint: addMenuPanel.routeParamHint,
|
|
10407
|
+
addMenuRouteParamRows: addMenuPanel.routeParamRows,
|
|
10408
|
+
showAddMenuRouteParams: createMemo(
|
|
10409
|
+
() => addMenuPanel.routeParamRows().length > 0
|
|
10212
10410
|
),
|
|
10213
|
-
|
|
10411
|
+
showAddMenuRouteParamConfirm: addMenuPanel.showRouteParamConfirm,
|
|
10412
|
+
addMenuPendingRouteParamTitle: addMenuPanel.pendingRouteParamTitle,
|
|
10214
10413
|
addPageIsDynamicRoute,
|
|
10215
10414
|
addPageCreateDisabled,
|
|
10216
10415
|
showAddPageRouteError,
|
|
@@ -10240,102 +10439,558 @@ function initAddPageComposer(deps) {
|
|
|
10240
10439
|
submitAddPage,
|
|
10241
10440
|
retryAddPage,
|
|
10242
10441
|
openPreviewForRoute,
|
|
10243
|
-
bindAddPageRefs
|
|
10442
|
+
bindAddPageRefs,
|
|
10443
|
+
refreshAddMenuCatalog: () => addMenuPanel.refreshCatalog()
|
|
10244
10444
|
};
|
|
10245
10445
|
}
|
|
10246
|
-
function
|
|
10247
|
-
|
|
10248
|
-
|
|
10249
|
-
|
|
10446
|
+
function markerAddMenuAttachments(annotation) {
|
|
10447
|
+
return (annotation.addMenuAttachments ?? []).filter(
|
|
10448
|
+
(a2) => a2.annotationId === annotation.id || a2.annotationId === void 0
|
|
10449
|
+
);
|
|
10250
10450
|
}
|
|
10251
|
-
function
|
|
10252
|
-
const
|
|
10253
|
-
|
|
10451
|
+
function enrichAnnotationAddMenuUi(annotation, itemById, pickerOpenForAnnotation, selectedCategory) {
|
|
10452
|
+
const attachments = markerAddMenuAttachments(annotation);
|
|
10453
|
+
const open = !!annotation.addMenuSectionOpen;
|
|
10454
|
+
const pickerOpen = pickerOpenForAnnotation && open;
|
|
10455
|
+
return {
|
|
10456
|
+
addMenuSectionOpen: open,
|
|
10457
|
+
showAddMenuControls: open,
|
|
10458
|
+
showMarkerAddMenuChips: attachments.length > 0,
|
|
10459
|
+
showMarkerAddMenuEmptyHint: attachments.length === 0,
|
|
10460
|
+
markerAddMenuChips: attachments.map((a2) => {
|
|
10461
|
+
const item = itemById.get(a2.itemId);
|
|
10462
|
+
return {
|
|
10463
|
+
rowKey: `${a2.itemId}:${annotation.id}`,
|
|
10464
|
+
itemId: a2.itemId,
|
|
10465
|
+
title: item?.title ?? a2.itemId,
|
|
10466
|
+
subtitle: item?.pluginName ?? item?.id.split(":")[0] ?? ""
|
|
10467
|
+
};
|
|
10468
|
+
}),
|
|
10469
|
+
addMenuSelectedCategory: selectedCategory,
|
|
10470
|
+
showAddMenuItemPicker: pickerOpen,
|
|
10471
|
+
markerPickerNavRows: [],
|
|
10472
|
+
showMarkerPickerLoading: false,
|
|
10473
|
+
showMarkerPickerCatalogEmpty: false,
|
|
10474
|
+
crAddMenuParamCollisionWarning: "",
|
|
10475
|
+
crAddMenuRouteParamHint: "",
|
|
10476
|
+
showCrAddMenuRouteParams: false,
|
|
10477
|
+
crAddMenuRouteParamRows: [],
|
|
10478
|
+
showCrRouteParamConfirm: false,
|
|
10479
|
+
crPendingRouteParamTitle: "",
|
|
10480
|
+
showCrPlannedRoutePanel: false,
|
|
10481
|
+
crPlannedRoute: ""
|
|
10482
|
+
};
|
|
10483
|
+
}
|
|
10484
|
+
function addMenuItemToAnnotation(prev, annotationId, itemId) {
|
|
10485
|
+
return dedupeAddMenuAttachment(prev ?? [], {
|
|
10486
|
+
itemId,
|
|
10487
|
+
annotationId
|
|
10488
|
+
});
|
|
10254
10489
|
}
|
|
10255
|
-
function
|
|
10256
|
-
|
|
10257
|
-
|
|
10490
|
+
function removeMenuItemFromAnnotation(prev, annotationId, itemId) {
|
|
10491
|
+
return removeAddMenuAttachment(prev ?? [], itemId, annotationId);
|
|
10492
|
+
}
|
|
10493
|
+
function initVisualAddMenuController(deps) {
|
|
10494
|
+
const [catalogItems, setCatalogItems] = createSignal([]);
|
|
10495
|
+
const [catalogCategories, setCatalogCategories] = createSignal([]);
|
|
10496
|
+
const [catalogLoading, setCatalogLoading] = createSignal(false);
|
|
10497
|
+
const [catalogLoaded, setCatalogLoaded] = createSignal(false);
|
|
10498
|
+
let catalogRefreshPromise = null;
|
|
10499
|
+
const [pickerAnnotationId, setPickerAnnotationId] = createSignal(void 0);
|
|
10500
|
+
const [pickerCategory, setPickerCategory] = createSignal("");
|
|
10501
|
+
const [pickerSubCategory, setPickerSubCategory] = createSignal(
|
|
10502
|
+
null
|
|
10503
|
+
);
|
|
10504
|
+
const [requestAttachments, setRequestAttachments] = createSignal([]);
|
|
10505
|
+
const [routeMigration, setRouteMigration] = createSignal(null);
|
|
10506
|
+
const [plannedRoute, setPlannedRoute] = createSignal("");
|
|
10507
|
+
const [paramCollisionWarning, setParamCollisionWarning] = createSignal("");
|
|
10508
|
+
const [routeParamHint, setRouteParamHint] = createSignal("");
|
|
10509
|
+
const [routeSegmentNames, setRouteSegmentNames] = createSignal([]);
|
|
10510
|
+
const [pendingRouteParamItem, setPendingRouteParamItem] = createSignal(null);
|
|
10511
|
+
const [pendingRouteParamAnnotationId, setPendingRouteParamAnnotationId] = createSignal(null);
|
|
10512
|
+
const [showRouteParamConfirm, setShowRouteParamConfirm] = createSignal(false);
|
|
10513
|
+
const itemById = createMemo(() => {
|
|
10514
|
+
const map = /* @__PURE__ */ new Map();
|
|
10515
|
+
for (const item of catalogItems()) map.set(item.id, item);
|
|
10516
|
+
return map;
|
|
10517
|
+
});
|
|
10518
|
+
const pickerPanelOpen = createMemo(
|
|
10519
|
+
() => pickerAnnotationId() !== void 0
|
|
10520
|
+
);
|
|
10521
|
+
const pickerNavRows = createMemo(
|
|
10522
|
+
() => buildAddMenuNavRows(
|
|
10523
|
+
catalogCategories(),
|
|
10524
|
+
pickerPanelOpen(),
|
|
10525
|
+
pickerCategory(),
|
|
10526
|
+
pickerSubCategory()
|
|
10527
|
+
)
|
|
10528
|
+
);
|
|
10529
|
+
const markerPickerNavRowsForView = createMemo(
|
|
10530
|
+
() => pickerNavRows().map(stripMarkerAddMenuNavRowForPage)
|
|
10531
|
+
);
|
|
10532
|
+
const markerPickerNavRowsForVideo = markerPickerNavRowsForView;
|
|
10533
|
+
const markerPickerNavRowsForSnapshot = markerPickerNavRowsForView;
|
|
10534
|
+
const showMarkerPickerCatalogEmpty = createMemo(() => {
|
|
10535
|
+
const id = pickerAnnotationId();
|
|
10536
|
+
if (id === void 0 || id === null) return false;
|
|
10537
|
+
return !catalogLoading() && catalogItems().length === 0;
|
|
10538
|
+
});
|
|
10539
|
+
const showMarkerPickerLoading = createMemo(() => {
|
|
10540
|
+
const id = pickerAnnotationId();
|
|
10541
|
+
if (id === void 0 || id === null) return false;
|
|
10542
|
+
return catalogLoading();
|
|
10543
|
+
});
|
|
10544
|
+
const markerPickerSnapshot = createMemo(() => ({
|
|
10545
|
+
pickerId: pickerAnnotationId(),
|
|
10546
|
+
category: pickerCategory(),
|
|
10547
|
+
subCategory: pickerSubCategory(),
|
|
10548
|
+
navVisual: markerPickerNavRowsForView(),
|
|
10549
|
+
navVideo: markerPickerNavRowsForVideo(),
|
|
10550
|
+
navSnapshot: markerPickerNavRowsForSnapshot(),
|
|
10551
|
+
loading: showMarkerPickerLoading(),
|
|
10552
|
+
empty: showMarkerPickerCatalogEmpty()
|
|
10553
|
+
}));
|
|
10554
|
+
createMemo(
|
|
10555
|
+
() => requestAttachments().map((a2) => {
|
|
10556
|
+
const item = itemById().get(a2.itemId);
|
|
10557
|
+
return {
|
|
10558
|
+
rowKey: `req:${a2.itemId}`,
|
|
10559
|
+
itemId: a2.itemId,
|
|
10560
|
+
title: item?.title ?? a2.itemId,
|
|
10561
|
+
subtitle: item?.pluginName ?? item?.id.split(":")[0] ?? ""
|
|
10562
|
+
};
|
|
10563
|
+
})
|
|
10564
|
+
);
|
|
10565
|
+
const routeParamRows = createMemo(
|
|
10566
|
+
() => routeSegmentNames().map((name) => ({ rowKey: name, name }))
|
|
10567
|
+
);
|
|
10568
|
+
async function refreshCatalog() {
|
|
10569
|
+
if (catalogRefreshPromise) return catalogRefreshPromise;
|
|
10570
|
+
catalogRefreshPromise = (async () => {
|
|
10571
|
+
setCatalogLoading(true);
|
|
10572
|
+
try {
|
|
10573
|
+
const result = await listAddMenuItems();
|
|
10574
|
+
setCatalogItems(result.items);
|
|
10575
|
+
setCatalogCategories(result.categories);
|
|
10576
|
+
if (result.warnings.length > 0) {
|
|
10577
|
+
console.warn("[aiditor] Add Menu catalog warnings:", result.warnings);
|
|
10578
|
+
}
|
|
10579
|
+
} catch (err) {
|
|
10580
|
+
console.error("[aiditor] listAddMenuItems failed:", err);
|
|
10581
|
+
setCatalogItems([]);
|
|
10582
|
+
setCatalogCategories([]);
|
|
10583
|
+
} finally {
|
|
10584
|
+
setCatalogLoaded(true);
|
|
10585
|
+
setCatalogLoading(false);
|
|
10586
|
+
catalogRefreshPromise = null;
|
|
10587
|
+
}
|
|
10588
|
+
})();
|
|
10589
|
+
return catalogRefreshPromise;
|
|
10590
|
+
}
|
|
10591
|
+
async function ensureCatalogLoaded() {
|
|
10592
|
+
if (catalogLoading()) return;
|
|
10593
|
+
if (catalogLoaded() && catalogCategories().length > 0) return;
|
|
10594
|
+
await refreshCatalog();
|
|
10595
|
+
}
|
|
10596
|
+
async function updateRouteHelpers(attachments) {
|
|
10597
|
+
const resolved = [];
|
|
10598
|
+
for (const a2 of attachments) {
|
|
10599
|
+
const item = itemById().get(a2.itemId);
|
|
10600
|
+
if (!item) continue;
|
|
10601
|
+
const params = await resolveContractParamsForItem(
|
|
10602
|
+
deps.projectDir(),
|
|
10603
|
+
item
|
|
10604
|
+
);
|
|
10605
|
+
if (params) resolved.push(params);
|
|
10606
|
+
}
|
|
10607
|
+
const collisions = detectRequiredParamCollisions(resolved);
|
|
10608
|
+
setParamCollisionWarning(collisions[0]?.message ?? "");
|
|
10609
|
+
const segments = collectRouteSegmentNames(resolved);
|
|
10610
|
+
setRouteSegmentNames(segments);
|
|
10611
|
+
const route = plannedRoute() || deps.getCurrentRoute();
|
|
10612
|
+
const suggested = suggestMissingRouteSegments(route, segments);
|
|
10613
|
+
setRouteParamHint(
|
|
10614
|
+
suggested && suggested !== route ? `Suggested route segments: ${suggested}` : ""
|
|
10615
|
+
);
|
|
10616
|
+
}
|
|
10617
|
+
async function openPicker(annotationId) {
|
|
10618
|
+
setPickerAnnotationId(annotationId);
|
|
10619
|
+
setPickerCategory("");
|
|
10620
|
+
setPickerSubCategory(null);
|
|
10621
|
+
await ensureCatalogLoaded();
|
|
10622
|
+
if (catalogCategories().length === 0 && !catalogLoading()) {
|
|
10623
|
+
await refreshCatalog();
|
|
10624
|
+
}
|
|
10625
|
+
}
|
|
10626
|
+
function closePicker() {
|
|
10627
|
+
setPickerAnnotationId(void 0);
|
|
10628
|
+
setPickerCategory("");
|
|
10629
|
+
setPickerSubCategory(null);
|
|
10630
|
+
}
|
|
10631
|
+
async function commitItem(item, updateAnnotation, annotationId) {
|
|
10632
|
+
if (annotationId) {
|
|
10633
|
+
updateAnnotation(annotationId, (a2) => ({
|
|
10634
|
+
...a2,
|
|
10635
|
+
addMenuSectionOpen: true,
|
|
10636
|
+
pickerOpen: false,
|
|
10637
|
+
addMenuAttachments: addMenuItemToAnnotation(
|
|
10638
|
+
a2.addMenuAttachments,
|
|
10639
|
+
annotationId,
|
|
10640
|
+
item.id
|
|
10641
|
+
)
|
|
10642
|
+
}));
|
|
10643
|
+
} else {
|
|
10644
|
+
setRequestAttachments((prev) => {
|
|
10645
|
+
const exists = prev.some(
|
|
10646
|
+
(a2) => a2.itemId === item.id && !a2.annotationId
|
|
10647
|
+
);
|
|
10648
|
+
if (exists) return prev;
|
|
10649
|
+
return [...prev, { itemId: item.id }];
|
|
10650
|
+
});
|
|
10651
|
+
closePicker();
|
|
10652
|
+
}
|
|
10653
|
+
const all = [
|
|
10654
|
+
...requestAttachments(),
|
|
10655
|
+
...annotationId ? [{ itemId: item.id, annotationId }] : [{ itemId: item.id }]
|
|
10656
|
+
];
|
|
10657
|
+
await updateRouteHelpers(all);
|
|
10658
|
+
}
|
|
10659
|
+
async function tryPickItem(item, updateAnnotation, annotationId) {
|
|
10660
|
+
const params = await resolveContractParamsForItem(deps.projectDir(), item);
|
|
10661
|
+
const hasRouteParams = !!params && params.allParams.length > 0;
|
|
10662
|
+
const current = deps.getCurrentRoute();
|
|
10663
|
+
if (hasRouteParams && current && !routeHasAnyDynamicSegment(current)) {
|
|
10664
|
+
setPendingRouteParamItem(item);
|
|
10665
|
+
setPendingRouteParamAnnotationId(annotationId);
|
|
10666
|
+
setShowRouteParamConfirm(true);
|
|
10667
|
+
return;
|
|
10668
|
+
}
|
|
10669
|
+
await commitItem(item, updateAnnotation, annotationId);
|
|
10670
|
+
}
|
|
10671
|
+
async function confirmRouteParamPick(updateAnnotation) {
|
|
10672
|
+
const item = pendingRouteParamItem();
|
|
10673
|
+
if (!item) return;
|
|
10674
|
+
const current = deps.getCurrentRoute() || "/";
|
|
10675
|
+
const params = await resolveContractParamsForItem(deps.projectDir(), item);
|
|
10676
|
+
const segments = params ? collectRouteSegmentNames([params]) : [];
|
|
10677
|
+
const planned = suggestMissingRouteSegments(current, segments) ?? `${current}/[slug]`;
|
|
10678
|
+
setPlannedRoute(planned);
|
|
10679
|
+
setRouteMigration({
|
|
10680
|
+
currentRoute: current,
|
|
10681
|
+
plannedRoute: planned,
|
|
10682
|
+
reason: "add-menu-route-param-component",
|
|
10683
|
+
triggeringItemIds: [item.id]
|
|
10684
|
+
});
|
|
10685
|
+
setShowRouteParamConfirm(false);
|
|
10686
|
+
setPendingRouteParamItem(null);
|
|
10687
|
+
const aid = pendingRouteParamAnnotationId();
|
|
10688
|
+
setPendingRouteParamAnnotationId(null);
|
|
10689
|
+
await commitItem(item, updateAnnotation, aid);
|
|
10690
|
+
}
|
|
10691
|
+
function cancelRouteParamPick() {
|
|
10692
|
+
setShowRouteParamConfirm(false);
|
|
10693
|
+
setPendingRouteParamItem(null);
|
|
10694
|
+
setPendingRouteParamAnnotationId(null);
|
|
10695
|
+
}
|
|
10696
|
+
function enrichUi(annotation, _stripMarkerRow) {
|
|
10697
|
+
const pickerOpen = !!annotation.pickerOpen;
|
|
10698
|
+
const cat = annotation.selectedCategory ?? "";
|
|
10699
|
+
const sub = annotation.selectedSubCategory ?? null;
|
|
10700
|
+
const base = enrichAnnotationAddMenuUi(
|
|
10701
|
+
annotation,
|
|
10702
|
+
itemById(),
|
|
10703
|
+
pickerOpen,
|
|
10704
|
+
cat
|
|
10705
|
+
);
|
|
10706
|
+
const navRows = buildAddMenuNavRows(
|
|
10707
|
+
catalogCategories(),
|
|
10708
|
+
pickerOpen,
|
|
10709
|
+
cat,
|
|
10710
|
+
sub
|
|
10711
|
+
).map(_stripMarkerRow);
|
|
10712
|
+
const hasAttachments = !!annotation.addMenuAttachments && annotation.addMenuAttachments.length > 0;
|
|
10713
|
+
const isPendingRoute = pendingRouteParamAnnotationId() === annotation.id;
|
|
10714
|
+
const showRouteUi = isPendingRoute || hasAttachments && routeMigration() !== null;
|
|
10715
|
+
const showParamsUi = isPendingRoute || hasAttachments && routeParamRows().length > 0;
|
|
10716
|
+
const showConfirm = isPendingRoute && showRouteParamConfirm();
|
|
10717
|
+
return {
|
|
10718
|
+
...base,
|
|
10719
|
+
showAddMenuItemPicker: pickerOpen,
|
|
10720
|
+
markerPickerNavRows: navRows,
|
|
10721
|
+
showMarkerPickerLoading: pickerOpen && catalogLoading(),
|
|
10722
|
+
showMarkerPickerCatalogEmpty: pickerOpen && !catalogLoading() && catalogItems().length === 0,
|
|
10723
|
+
crAddMenuParamCollisionWarning: showParamsUi ? paramCollisionWarning() : "",
|
|
10724
|
+
crAddMenuRouteParamHint: showParamsUi ? routeParamHint() : "",
|
|
10725
|
+
showCrAddMenuRouteParams: showParamsUi && routeParamRows().length > 0,
|
|
10726
|
+
crAddMenuRouteParamRows: showParamsUi ? routeParamRows() : [],
|
|
10727
|
+
showCrRouteParamConfirm: showConfirm,
|
|
10728
|
+
crPendingRouteParamTitle: isPendingRoute && pendingRouteParamItem() ? pendingRouteParamItem().title : "",
|
|
10729
|
+
showCrPlannedRoutePanel: showRouteUi,
|
|
10730
|
+
crPlannedRoute: showRouteUi ? plannedRoute() : ""
|
|
10731
|
+
};
|
|
10732
|
+
}
|
|
10733
|
+
function handleMarkerAddMenuClick(target, annotationId, updateAnnotation) {
|
|
10734
|
+
if (target.classList.contains("annotation-add-menu-toggle")) {
|
|
10735
|
+
updateAnnotation(annotationId, (a2) => ({
|
|
10736
|
+
...a2,
|
|
10737
|
+
addMenuSectionOpen: !a2.addMenuSectionOpen
|
|
10738
|
+
}));
|
|
10739
|
+
return true;
|
|
10740
|
+
}
|
|
10741
|
+
if (target.closest("[data-marker-add-menu-open]")) {
|
|
10742
|
+
updateAnnotation(annotationId, (a2) => ({
|
|
10743
|
+
...a2,
|
|
10744
|
+
addMenuSectionOpen: true,
|
|
10745
|
+
pickerOpen: true,
|
|
10746
|
+
selectedCategory: "",
|
|
10747
|
+
selectedSubCategory: null
|
|
10748
|
+
}));
|
|
10749
|
+
void ensureCatalogLoaded();
|
|
10750
|
+
return true;
|
|
10751
|
+
}
|
|
10752
|
+
if (target.closest("[data-marker-add-menu-close]")) {
|
|
10753
|
+
updateAnnotation(annotationId, (a2) => ({
|
|
10754
|
+
...a2,
|
|
10755
|
+
pickerOpen: false
|
|
10756
|
+
}));
|
|
10757
|
+
return true;
|
|
10758
|
+
}
|
|
10759
|
+
if (target.closest("[data-marker-add-menu-manage]")) {
|
|
10760
|
+
deps.openProjectSettings();
|
|
10761
|
+
return true;
|
|
10762
|
+
}
|
|
10763
|
+
const catBtn = target.closest(
|
|
10764
|
+
"[data-marker-add-menu-category]"
|
|
10765
|
+
);
|
|
10766
|
+
if (catBtn?.dataset.category) {
|
|
10767
|
+
updateAnnotation(annotationId, (a2) => ({
|
|
10768
|
+
...a2,
|
|
10769
|
+
selectedCategory: catBtn.dataset.category,
|
|
10770
|
+
selectedSubCategory: null
|
|
10771
|
+
}));
|
|
10772
|
+
return true;
|
|
10773
|
+
}
|
|
10774
|
+
const subBtn = target.closest(
|
|
10775
|
+
"[data-marker-add-menu-subcategory]"
|
|
10776
|
+
);
|
|
10777
|
+
if (subBtn?.dataset.subcategory !== void 0) {
|
|
10778
|
+
updateAnnotation(annotationId, (a2) => ({
|
|
10779
|
+
...a2,
|
|
10780
|
+
selectedSubCategory: subBtn.dataset.subcategory || null
|
|
10781
|
+
}));
|
|
10782
|
+
return true;
|
|
10783
|
+
}
|
|
10784
|
+
const pickBtn = target.closest(
|
|
10785
|
+
"[data-marker-add-menu-pick]"
|
|
10786
|
+
);
|
|
10787
|
+
if (pickBtn?.dataset.itemId) {
|
|
10788
|
+
const item = itemById().get(pickBtn.dataset.itemId);
|
|
10789
|
+
if (item) void tryPickItem(item, updateAnnotation, annotationId);
|
|
10790
|
+
return true;
|
|
10791
|
+
}
|
|
10792
|
+
const removeBtn = target.closest(
|
|
10793
|
+
"[data-marker-add-menu-remove]"
|
|
10794
|
+
);
|
|
10795
|
+
if (removeBtn?.dataset.itemId) {
|
|
10796
|
+
updateAnnotation(annotationId, (a2) => ({
|
|
10797
|
+
...a2,
|
|
10798
|
+
addMenuAttachments: removeMenuItemFromAnnotation(
|
|
10799
|
+
a2.addMenuAttachments,
|
|
10800
|
+
annotationId,
|
|
10801
|
+
removeBtn.dataset.itemId
|
|
10802
|
+
)
|
|
10803
|
+
}));
|
|
10804
|
+
return true;
|
|
10805
|
+
}
|
|
10806
|
+
return false;
|
|
10807
|
+
}
|
|
10808
|
+
function handleRequestAddMenuClick(target, updateAnnotation) {
|
|
10809
|
+
if (target.closest("[data-cr-add-menu-open]")) {
|
|
10810
|
+
void openPicker(null);
|
|
10811
|
+
return;
|
|
10812
|
+
}
|
|
10813
|
+
if (target.closest("[data-cr-add-menu-close]")) {
|
|
10814
|
+
closePicker();
|
|
10815
|
+
return;
|
|
10816
|
+
}
|
|
10817
|
+
if (target.closest("[data-cr-add-menu-manage]")) {
|
|
10818
|
+
deps.openProjectSettings();
|
|
10819
|
+
return;
|
|
10820
|
+
}
|
|
10821
|
+
const catBtn = target.closest(
|
|
10822
|
+
"[data-cr-add-menu-category]"
|
|
10823
|
+
);
|
|
10824
|
+
if (catBtn?.dataset.category) {
|
|
10825
|
+
setPickerCategory(catBtn.dataset.category);
|
|
10826
|
+
setPickerSubCategory(null);
|
|
10827
|
+
return;
|
|
10828
|
+
}
|
|
10829
|
+
const subBtn = target.closest(
|
|
10830
|
+
"[data-cr-add-menu-subcategory]"
|
|
10831
|
+
);
|
|
10832
|
+
if (subBtn?.dataset.subcategory !== void 0) {
|
|
10833
|
+
setPickerSubCategory(subBtn.dataset.subcategory || null);
|
|
10834
|
+
return;
|
|
10835
|
+
}
|
|
10836
|
+
const pickBtn = target.closest(
|
|
10837
|
+
"[data-cr-add-menu-pick]"
|
|
10838
|
+
);
|
|
10839
|
+
if (pickBtn?.dataset.itemId) {
|
|
10840
|
+
const item = itemById().get(pickBtn.dataset.itemId);
|
|
10841
|
+
if (item) void tryPickItem(item, updateAnnotation, null);
|
|
10842
|
+
return;
|
|
10843
|
+
}
|
|
10844
|
+
const removeBtn = target.closest(
|
|
10845
|
+
"[data-cr-add-menu-remove]"
|
|
10846
|
+
);
|
|
10847
|
+
if (removeBtn?.dataset.itemId) {
|
|
10848
|
+
setRequestAttachments(
|
|
10849
|
+
(prev) => prev.filter((a2) => a2.itemId !== removeBtn.dataset.itemId)
|
|
10850
|
+
);
|
|
10851
|
+
return;
|
|
10852
|
+
}
|
|
10853
|
+
if (target.closest("[data-cr-route-param-confirm]")) {
|
|
10854
|
+
void confirmRouteParamPick(updateAnnotation);
|
|
10855
|
+
return;
|
|
10856
|
+
}
|
|
10857
|
+
if (target.closest("[data-cr-route-param-cancel]")) {
|
|
10858
|
+
setShowRouteParamConfirm(false);
|
|
10859
|
+
setPendingRouteParamItem(null);
|
|
10860
|
+
}
|
|
10861
|
+
}
|
|
10862
|
+
const showRequestAddMenuPicker = createMemo(
|
|
10863
|
+
() => pickerAnnotationId() === null
|
|
10258
10864
|
);
|
|
10259
|
-
|
|
10260
|
-
|
|
10261
|
-
value: p.pluginName,
|
|
10262
|
-
label: p.pluginName
|
|
10263
|
-
}));
|
|
10264
|
-
options.push({
|
|
10265
|
-
rowKey: ADD_PAGE_MANAGE_PLUGINS_VALUE,
|
|
10266
|
-
value: ADD_PAGE_MANAGE_PLUGINS_VALUE,
|
|
10267
|
-
label: "Manage plugins…"
|
|
10268
|
-
});
|
|
10269
|
-
return options;
|
|
10270
|
-
}
|
|
10271
|
-
function markerContractPickerRows(plugins, pluginName, bindings) {
|
|
10272
|
-
const entry = plugins.find((p) => p.pluginName === pluginName);
|
|
10273
|
-
if (!entry?.installed) return [];
|
|
10274
|
-
return entry.contracts.map((c) => ({
|
|
10275
|
-
rowKey: `${pluginName}:${c.contractName}`,
|
|
10276
|
-
pluginName,
|
|
10277
|
-
packageName: entry.packageName,
|
|
10278
|
-
contractName: c.contractName,
|
|
10279
|
-
description: c.description ?? "",
|
|
10280
|
-
onPage: bindings.some(
|
|
10281
|
-
(b) => b.pluginName === pluginName && b.contractName === c.contractName
|
|
10282
|
-
),
|
|
10283
|
-
componentKey: bindings.find(
|
|
10284
|
-
(b) => b.pluginName === pluginName && b.contractName === c.contractName
|
|
10285
|
-
)?.componentKey ?? getDefaultComponentKey(c.contractName)
|
|
10286
|
-
}));
|
|
10287
|
-
}
|
|
10288
|
-
function upsertAnnotationBinding(prev, binding) {
|
|
10289
|
-
const idx = prev.findIndex(
|
|
10290
|
-
(b) => b.pluginName === binding.pluginName && b.contractName === binding.contractName
|
|
10865
|
+
createMemo(
|
|
10866
|
+
() => showRequestAddMenuPicker() && catalogLoading()
|
|
10291
10867
|
);
|
|
10292
|
-
|
|
10293
|
-
|
|
10294
|
-
next[idx] = binding;
|
|
10295
|
-
return next;
|
|
10296
|
-
}
|
|
10297
|
-
function removeAnnotationBinding(prev, pluginName, contractName) {
|
|
10298
|
-
return prev.filter(
|
|
10299
|
-
(b) => !(b.pluginName === pluginName && b.contractName === contractName)
|
|
10868
|
+
createMemo(
|
|
10869
|
+
() => showRequestAddMenuPicker() && !catalogLoading() && catalogItems().length === 0
|
|
10300
10870
|
);
|
|
10301
|
-
}
|
|
10302
|
-
function enrichAnnotationBindingUi(annotation, plugins) {
|
|
10303
|
-
const bindings = annotationPluginBindings(annotation);
|
|
10304
|
-
const pickerPlugin = annotation.bindingPickerPlugin ?? "";
|
|
10305
|
-
const open = !!annotation.bindingSectionOpen;
|
|
10306
10871
|
return {
|
|
10307
|
-
|
|
10308
|
-
|
|
10309
|
-
|
|
10310
|
-
|
|
10311
|
-
|
|
10312
|
-
|
|
10313
|
-
|
|
10314
|
-
|
|
10315
|
-
|
|
10316
|
-
|
|
10317
|
-
|
|
10318
|
-
|
|
10319
|
-
|
|
10320
|
-
|
|
10321
|
-
|
|
10322
|
-
|
|
10323
|
-
|
|
10872
|
+
refreshCatalog,
|
|
10873
|
+
enrichUi,
|
|
10874
|
+
markerPickerSnapshot,
|
|
10875
|
+
handleMarkerAddMenuClick,
|
|
10876
|
+
handleRequestAddMenuClick,
|
|
10877
|
+
requestAttachments,
|
|
10878
|
+
routeMigration,
|
|
10879
|
+
plannedRoute,
|
|
10880
|
+
setPlannedRoute,
|
|
10881
|
+
catalogLoading,
|
|
10882
|
+
markerPickerNavRowsForView,
|
|
10883
|
+
markerPickerNavRowsForVideo,
|
|
10884
|
+
markerPickerNavRowsForSnapshot,
|
|
10885
|
+
markerPickerSelectedCategory: pickerCategory,
|
|
10886
|
+
showMarkerPickerLoading,
|
|
10887
|
+
showMarkerPickerCatalogEmpty,
|
|
10888
|
+
paramCollisionWarning,
|
|
10889
|
+
routeParamHint,
|
|
10890
|
+
routeParamRows,
|
|
10891
|
+
showRouteParams: createMemo(() => routeParamRows().length > 0),
|
|
10892
|
+
showRouteParamConfirm,
|
|
10893
|
+
pendingRouteParamTitle: createMemo(
|
|
10894
|
+
() => pendingRouteParamItem()?.title ?? ""
|
|
10324
10895
|
),
|
|
10325
|
-
|
|
10326
|
-
|
|
10896
|
+
confirmRouteParamPick,
|
|
10897
|
+
cancelRouteParamPick,
|
|
10898
|
+
reset: () => {
|
|
10899
|
+
setRequestAttachments([]);
|
|
10900
|
+
setRouteMigration(null);
|
|
10901
|
+
setPlannedRoute("");
|
|
10902
|
+
closePicker();
|
|
10903
|
+
}
|
|
10327
10904
|
};
|
|
10328
10905
|
}
|
|
10329
|
-
|
|
10330
|
-
|
|
10331
|
-
|
|
10332
|
-
|
|
10333
|
-
|
|
10334
|
-
|
|
10335
|
-
|
|
10336
|
-
|
|
10337
|
-
|
|
10338
|
-
}
|
|
10906
|
+
const CATALOG = [
|
|
10907
|
+
{
|
|
10908
|
+
pluginName: "wix-server-client",
|
|
10909
|
+
packageName: "@jay-framework/wix-server-client",
|
|
10910
|
+
description: "Wix API client and authentication",
|
|
10911
|
+
kind: "service-only",
|
|
10912
|
+
requires: [],
|
|
10913
|
+
showInAddPagePicker: false,
|
|
10914
|
+
configFiles: ["config/.wix.yaml"]
|
|
10915
|
+
},
|
|
10916
|
+
{
|
|
10917
|
+
pluginName: "wix-cart",
|
|
10918
|
+
packageName: "@jay-framework/wix-cart",
|
|
10919
|
+
description: "Shopping cart headless components",
|
|
10920
|
+
kind: "headless",
|
|
10921
|
+
requires: ["wix-server-client"],
|
|
10922
|
+
showInAddPagePicker: true
|
|
10923
|
+
},
|
|
10924
|
+
{
|
|
10925
|
+
pluginName: "wix-stores",
|
|
10926
|
+
packageName: "@jay-framework/wix-stores",
|
|
10927
|
+
description: "Wix Stores product search, product page, categories",
|
|
10928
|
+
kind: "headless",
|
|
10929
|
+
requires: ["wix-server-client", "wix-cart"],
|
|
10930
|
+
showInAddPagePicker: true,
|
|
10931
|
+
configFiles: ["config/.wix-stores.yaml"]
|
|
10932
|
+
},
|
|
10933
|
+
{
|
|
10934
|
+
pluginName: "wix-stores-v1",
|
|
10935
|
+
packageName: "@jay-framework/wix-stores-v1",
|
|
10936
|
+
description: "Wix Stores v1 catalog API",
|
|
10937
|
+
kind: "headless",
|
|
10938
|
+
requires: ["wix-server-client", "wix-cart"],
|
|
10939
|
+
showInAddPagePicker: true
|
|
10940
|
+
},
|
|
10941
|
+
{
|
|
10942
|
+
pluginName: "wix-data",
|
|
10943
|
+
packageName: "@jay-framework/wix-data",
|
|
10944
|
+
description: "Wix Data collections CMS",
|
|
10945
|
+
kind: "headless",
|
|
10946
|
+
requires: ["wix-server-client"],
|
|
10947
|
+
showInAddPagePicker: true,
|
|
10948
|
+
configFiles: ["config/.wix-data.yaml"]
|
|
10949
|
+
},
|
|
10950
|
+
{
|
|
10951
|
+
pluginName: "wix-media",
|
|
10952
|
+
packageName: "@jay-framework/wix-media",
|
|
10953
|
+
description: "Wix media service (no page components)",
|
|
10954
|
+
kind: "service-only",
|
|
10955
|
+
requires: ["wix-server-client"],
|
|
10956
|
+
showInAddPagePicker: true
|
|
10957
|
+
},
|
|
10958
|
+
{
|
|
10959
|
+
pluginName: "ui-kit",
|
|
10960
|
+
packageName: "@jay-framework/ui-kit",
|
|
10961
|
+
description: "Jay UI kit headless components",
|
|
10962
|
+
kind: "headless",
|
|
10963
|
+
requires: [],
|
|
10964
|
+
showInAddPagePicker: true
|
|
10965
|
+
},
|
|
10966
|
+
{
|
|
10967
|
+
pluginName: "gemini-agent",
|
|
10968
|
+
packageName: "@jay-framework/gemini-agent",
|
|
10969
|
+
description: "Gemini AI agent plugin",
|
|
10970
|
+
kind: "headless",
|
|
10971
|
+
requires: [],
|
|
10972
|
+
showInAddPagePicker: true,
|
|
10973
|
+
configFiles: ["config/.gemini-agent.yaml"]
|
|
10974
|
+
},
|
|
10975
|
+
{
|
|
10976
|
+
pluginName: "webmcp",
|
|
10977
|
+
packageName: "@jay-framework/webmcp",
|
|
10978
|
+
description: "Web MCP tooling",
|
|
10979
|
+
kind: "tooling",
|
|
10980
|
+
requires: [],
|
|
10981
|
+
showInAddPagePicker: false
|
|
10982
|
+
},
|
|
10983
|
+
{
|
|
10984
|
+
pluginName: "aiditor",
|
|
10985
|
+
packageName: "@jay-framework/aiditor",
|
|
10986
|
+
description: "AIditor self plugin",
|
|
10987
|
+
kind: "tooling",
|
|
10988
|
+
requires: [],
|
|
10989
|
+
showInAddPagePicker: false
|
|
10990
|
+
}
|
|
10991
|
+
];
|
|
10992
|
+
function getCatalogEntry(pluginName) {
|
|
10993
|
+
return CATALOG.find((e2) => e2.pluginName === pluginName);
|
|
10339
10994
|
}
|
|
10340
10995
|
function buildPluginInstallAgentNotes(entry, installError, projectDirHint) {
|
|
10341
10996
|
const requires = entry.requires.length > 0 ? entry.requires.join(", ") : "(none — install this plugin only)";
|
|
@@ -10367,6 +11022,7 @@ function buildPluginInstallAgentNotes(entry, installError, projectDirHint) {
|
|
|
10367
11022
|
"## Local / monorepo alternative",
|
|
10368
11023
|
wixPortal,
|
|
10369
11024
|
"- Read `agent-kit/plugin/INSTRUCTIONS.md` for plugin setup conventions.",
|
|
11025
|
+
"- To contribute Add Menu catalog items, read `agent-kit/plugin/aiditor-add-menu.md`.",
|
|
10370
11026
|
"",
|
|
10371
11027
|
"When finished, summarize what you installed and any config files the user must edit (e.g. config/.wix.yaml)."
|
|
10372
11028
|
].filter((line) => line !== "").join("\n");
|
|
@@ -10380,6 +11036,50 @@ const VALID_INSTALL_PREFIXES = ["portal:", "file:", "workspace:"];
|
|
|
10380
11036
|
function isValidInstallSpec(spec) {
|
|
10381
11037
|
return VALID_INSTALL_PREFIXES.some((p) => spec.startsWith(p));
|
|
10382
11038
|
}
|
|
11039
|
+
const listJayPluginsAction = createActionCaller("aiditor.listJayPlugins", "GET");
|
|
11040
|
+
createActionCaller("aiditor.listPluginContracts", "GET");
|
|
11041
|
+
const checkPluginUpdateAction = createActionCaller("aiditor.checkPluginUpdate", "GET");
|
|
11042
|
+
const ensureProjectPluginAction = createStreamCaller("aiditor.ensureProjectPlugin");
|
|
11043
|
+
createActionCaller("aiditor.getPluginSetupStatus", "GET");
|
|
11044
|
+
const rerunPluginSetupAction = createActionCaller("aiditor.rerunPluginSetup", "GET");
|
|
11045
|
+
createActionCaller("aiditor.syncAddPagePluginManifest", "GET");
|
|
11046
|
+
const writePluginSourceAction = createActionCaller("aiditor.writePluginSource", "GET");
|
|
11047
|
+
async function listJayPlugins(refreshSetupStatus = false) {
|
|
11048
|
+
return listJayPluginsAction({ refreshSetupStatus });
|
|
11049
|
+
}
|
|
11050
|
+
async function checkPluginUpdate(pluginName) {
|
|
11051
|
+
return checkPluginUpdateAction({ pluginName });
|
|
11052
|
+
}
|
|
11053
|
+
function ensureProjectPluginStream(input, callbacks) {
|
|
11054
|
+
let aborted = false;
|
|
11055
|
+
const abort = () => {
|
|
11056
|
+
aborted = true;
|
|
11057
|
+
};
|
|
11058
|
+
void (async () => {
|
|
11059
|
+
try {
|
|
11060
|
+
for await (const chunk of ensureProjectPluginAction(input)) {
|
|
11061
|
+
if (aborted) break;
|
|
11062
|
+
callbacks.onChunk(chunk);
|
|
11063
|
+
if (chunk.type === "done" || chunk.type === "error") {
|
|
11064
|
+
callbacks.onEnd();
|
|
11065
|
+
return;
|
|
11066
|
+
}
|
|
11067
|
+
}
|
|
11068
|
+
if (!aborted) callbacks.onEnd();
|
|
11069
|
+
} catch (err) {
|
|
11070
|
+
if (!aborted) {
|
|
11071
|
+
callbacks.onError(err instanceof Error ? err : new Error(String(err)));
|
|
11072
|
+
}
|
|
11073
|
+
}
|
|
11074
|
+
})();
|
|
11075
|
+
return abort;
|
|
11076
|
+
}
|
|
11077
|
+
async function rerunPluginSetup(pluginName, force) {
|
|
11078
|
+
return rerunPluginSetupAction({ pluginName, force });
|
|
11079
|
+
}
|
|
11080
|
+
async function writePluginSource(input) {
|
|
11081
|
+
return writePluginSourceAction(input);
|
|
11082
|
+
}
|
|
10383
11083
|
function initProjectPluginsManager(deps) {
|
|
10384
11084
|
const [pluginsList, setPluginsList] = createSignal([]);
|
|
10385
11085
|
const [pluginsLoaded, setPluginsLoaded] = createSignal(false);
|
|
@@ -10559,6 +11259,7 @@ function initProjectPluginsManager(deps) {
|
|
|
10559
11259
|
updateAvailable: false
|
|
10560
11260
|
});
|
|
10561
11261
|
void refreshPluginsList(true).then(() => deps.loadProjectInfo());
|
|
11262
|
+
deps.onInstallComplete?.(pluginName);
|
|
10562
11263
|
setShowReloadPreviewBanner(true);
|
|
10563
11264
|
}
|
|
10564
11265
|
},
|
|
@@ -10759,20 +11460,31 @@ function serializeGeometry(a2) {
|
|
|
10759
11460
|
return { kind: "area", x: a2.x, y: a2.y, w: a2.w, h: a2.h };
|
|
10760
11461
|
return { kind: "arrow", x1: a2.x1, y1: a2.y1, x2: a2.x2, y2: a2.y2 };
|
|
10761
11462
|
}
|
|
10762
|
-
function
|
|
11463
|
+
function serializeAnnotationNotesFields(a2) {
|
|
11464
|
+
if (a2.addMenuAttachments?.length) {
|
|
11465
|
+
return { addMenuAttachments: a2.addMenuAttachments };
|
|
11466
|
+
}
|
|
11467
|
+
if (a2.pluginBindings?.length) {
|
|
11468
|
+
return { pluginBindings: a2.pluginBindings };
|
|
11469
|
+
}
|
|
11470
|
+
return {};
|
|
11471
|
+
}
|
|
11472
|
+
function toNotesPayload(annotations, breakpoint, requestLevel) {
|
|
10763
11473
|
return {
|
|
10764
11474
|
version: AIDITOR_NOTES_VERSION,
|
|
10765
11475
|
breakpoint,
|
|
11476
|
+
...requestLevel?.addMenuAttachments?.length ? { addMenuAttachments: requestLevel.addMenuAttachments } : {},
|
|
11477
|
+
...requestLevel?.routeMigration ? { routeMigration: requestLevel.routeMigration } : {},
|
|
10766
11478
|
annotations: annotations.map((a2) => ({
|
|
10767
11479
|
id: a2.id,
|
|
10768
11480
|
mode: a2.kind,
|
|
10769
11481
|
instruction: a2.instruction.trim(),
|
|
10770
11482
|
geometry: serializeGeometry(a2),
|
|
10771
|
-
...a2
|
|
11483
|
+
...serializeAnnotationNotesFields(a2)
|
|
10772
11484
|
}))
|
|
10773
11485
|
};
|
|
10774
11486
|
}
|
|
10775
|
-
function toVideoNotesPayload(annotations, videoMeta, notesContext) {
|
|
11487
|
+
function toVideoNotesPayload(annotations, videoMeta, notesContext, requestLevel) {
|
|
10776
11488
|
const baseOrigin = typeof window !== "undefined" ? window.location.origin : JAY_DEV_URL_DEFAULT;
|
|
10777
11489
|
const fallback = fallbackPreviewContextFromBar(notesContext.fallbackRenderedUrl, notesContext.fallbackRoute, baseOrigin);
|
|
10778
11490
|
const navLog = notesContext.previewNavLog.length > 0 ? notesContext.previewNavLog : void 0;
|
|
@@ -10782,6 +11494,8 @@ function toVideoNotesPayload(annotations, videoMeta, notesContext) {
|
|
|
10782
11494
|
videoMeta,
|
|
10783
11495
|
previewNavLog: navLog,
|
|
10784
11496
|
breakpoint: notesContext.breakpoint,
|
|
11497
|
+
...requestLevel?.addMenuAttachments?.length ? { addMenuAttachments: requestLevel.addMenuAttachments } : {},
|
|
11498
|
+
...requestLevel?.routeMigration ? { routeMigration: requestLevel.routeMigration } : {},
|
|
10785
11499
|
annotations: annotations.map((a2) => {
|
|
10786
11500
|
const ctx = resolvePreviewContextAtTime(a2.timeSec, navLog, fallback);
|
|
10787
11501
|
return {
|
|
@@ -10792,7 +11506,7 @@ function toVideoNotesPayload(annotations, videoMeta, notesContext) {
|
|
|
10792
11506
|
timeSec: a2.timeSec,
|
|
10793
11507
|
previewUrlAtTime: ctx.href,
|
|
10794
11508
|
pagePathAtTime: ctx.locationPath,
|
|
10795
|
-
...a2
|
|
11509
|
+
...serializeAnnotationNotesFields(a2)
|
|
10796
11510
|
};
|
|
10797
11511
|
})
|
|
10798
11512
|
};
|
|
@@ -11020,12 +11734,22 @@ function aiditorConstructor(_props, refs) {
|
|
|
11020
11734
|
const [visualSubmitError, setVisualSubmitError] = createSignal("");
|
|
11021
11735
|
const [showProjectSettingsModal, setShowProjectSettingsModal] = createSignal(false);
|
|
11022
11736
|
let runPluginInstallAgent;
|
|
11737
|
+
let refreshAddMenuCatalog;
|
|
11023
11738
|
const projectPlugins = initProjectPluginsManager({
|
|
11024
11739
|
loadProjectInfo: () => loadProjectInfo(),
|
|
11025
11740
|
fixInstallWithAgent: (pluginName, installError) => {
|
|
11026
11741
|
runPluginInstallAgent?.(pluginName, installError);
|
|
11742
|
+
},
|
|
11743
|
+
onInstallComplete: () => {
|
|
11744
|
+
void refreshAddMenuCatalog?.();
|
|
11027
11745
|
}
|
|
11028
11746
|
});
|
|
11747
|
+
const visualAddMenu = initVisualAddMenuController({
|
|
11748
|
+
projectDir: () => projectDir(),
|
|
11749
|
+
projectPlugins,
|
|
11750
|
+
openProjectSettings,
|
|
11751
|
+
getCurrentRoute: () => selectedPageUrl() || "/"
|
|
11752
|
+
});
|
|
11029
11753
|
function openProjectSettings() {
|
|
11030
11754
|
setShowProjectSettingsModal(true);
|
|
11031
11755
|
void projectPlugins.refreshPluginsList();
|
|
@@ -11307,9 +12031,28 @@ function aiditorConstructor(_props, refs) {
|
|
|
11307
12031
|
return true;
|
|
11308
12032
|
return list.some((a2) => a2.instruction.trim().length === 0);
|
|
11309
12033
|
});
|
|
12034
|
+
createMemo(() => {
|
|
12035
|
+
return {
|
|
12036
|
+
show: false,
|
|
12037
|
+
annotationId: "",
|
|
12038
|
+
leftPct: 0,
|
|
12039
|
+
topPct: 0,
|
|
12040
|
+
navRows: [],
|
|
12041
|
+
selectedCategory: "",
|
|
12042
|
+
loading: false,
|
|
12043
|
+
empty: false
|
|
12044
|
+
};
|
|
12045
|
+
});
|
|
12046
|
+
const showMarkerAddMenuPopover = createMemo(() => false);
|
|
12047
|
+
const markerAddMenuPopoverLeftPct = createMemo(() => 0);
|
|
12048
|
+
const markerAddMenuPopoverTopPct = createMemo(() => 0);
|
|
12049
|
+
const markerAddMenuPickerAnnotationId = createMemo(() => "");
|
|
12050
|
+
const markerAddMenuNavRows = createMemo(() => []);
|
|
12051
|
+
const markerAddMenuSelectedCategory = createMemo(() => "");
|
|
12052
|
+
const showMarkerAddMenuPickerLoading = createMemo(() => false);
|
|
12053
|
+
const showMarkerAddMenuPickerCatalogEmpty = createMemo(() => false);
|
|
11310
12054
|
const visualAnnotationRows = createMemo(() => {
|
|
11311
12055
|
const runDisabled = visualRunDisabled();
|
|
11312
|
-
const plugins = projectPlugins.pluginsList();
|
|
11313
12056
|
return visualAnnotations().map((a2) => {
|
|
11314
12057
|
const { nx, ny } = bubbleAnchorNorm(a2);
|
|
11315
12058
|
const leftPct = nx * 100;
|
|
@@ -11331,10 +12074,11 @@ function aiditorConstructor(_props, refs) {
|
|
|
11331
12074
|
popoverFlipX: flipX,
|
|
11332
12075
|
popoverFlipY: flipY,
|
|
11333
12076
|
attachmentChips,
|
|
11334
|
-
...
|
|
12077
|
+
...visualAddMenu.enrichUi(a2, stripMarkerPickerNavRowForVisual)
|
|
11335
12078
|
};
|
|
11336
12079
|
});
|
|
11337
12080
|
});
|
|
12081
|
+
const showCrPlannedRoutePanel = createMemo(() => visualAddMenu.routeMigration() !== null);
|
|
11338
12082
|
const recordingDraftPopoverRow = createMemo(() => {
|
|
11339
12083
|
const a2 = recordingDraftAnnotation();
|
|
11340
12084
|
if (!a2)
|
|
@@ -11462,7 +12206,6 @@ function aiditorConstructor(_props, refs) {
|
|
|
11462
12206
|
const t = videoReviewCurrentTimeSec();
|
|
11463
12207
|
const list = fullList.filter((a2) => isVideoAnnotationAtPlayhead(t, a2.timeSec));
|
|
11464
12208
|
const runDisabled = fullList.length > 0 && (isRunning() || fullList.some((a2) => a2.instruction.trim().length === 0));
|
|
11465
|
-
const plugins = projectPlugins.pluginsList();
|
|
11466
12209
|
return list.map((a2) => {
|
|
11467
12210
|
const { nx, ny } = bubbleAnchorNorm(a2);
|
|
11468
12211
|
const leftPct = nx * 100;
|
|
@@ -11485,7 +12228,7 @@ function aiditorConstructor(_props, refs) {
|
|
|
11485
12228
|
popoverFlipX: flipX,
|
|
11486
12229
|
popoverFlipY: flipY,
|
|
11487
12230
|
attachmentChips,
|
|
11488
|
-
...
|
|
12231
|
+
...visualAddMenu.enrichUi(a2, stripMarkerPickerNavRowForVideo)
|
|
11489
12232
|
};
|
|
11490
12233
|
});
|
|
11491
12234
|
});
|
|
@@ -11611,7 +12354,6 @@ function aiditorConstructor(_props, refs) {
|
|
|
11611
12354
|
const snapshotAreaDraftWidthPct = createMemo(() => (snapshotAreaDraftNorm()?.w ?? 0) * 100);
|
|
11612
12355
|
const snapshotAreaDraftHeightPct = createMemo(() => (snapshotAreaDraftNorm()?.h ?? 0) * 100);
|
|
11613
12356
|
const snapshotAnnotationItems = createMemo(() => {
|
|
11614
|
-
const plugins = projectPlugins.pluginsList();
|
|
11615
12357
|
return snapshotAnnotations().map((a2) => {
|
|
11616
12358
|
const { nx, ny } = bubbleAnchorNorm(a2);
|
|
11617
12359
|
const leftPct = nx * 100;
|
|
@@ -11634,7 +12376,7 @@ function aiditorConstructor(_props, refs) {
|
|
|
11634
12376
|
popoverFlipX: flipX,
|
|
11635
12377
|
popoverFlipY: flipY,
|
|
11636
12378
|
attachmentChips,
|
|
11637
|
-
...
|
|
12379
|
+
...visualAddMenu.enrichUi(a2, stripMarkerPickerNavRowForSnapshot)
|
|
11638
12380
|
};
|
|
11639
12381
|
});
|
|
11640
12382
|
});
|
|
@@ -11714,6 +12456,7 @@ function aiditorConstructor(_props, refs) {
|
|
|
11714
12456
|
setAreaDraft(null);
|
|
11715
12457
|
setArrowPending(null);
|
|
11716
12458
|
setVisualSubmitError("");
|
|
12459
|
+
visualAddMenu.reset();
|
|
11717
12460
|
cancelAreaDragListeners();
|
|
11718
12461
|
setVisualTool("none");
|
|
11719
12462
|
}
|
|
@@ -11901,68 +12644,27 @@ function aiditorConstructor(_props, refs) {
|
|
|
11901
12644
|
function updateVideoAsVisual(id, updater) {
|
|
11902
12645
|
updateVideoAnnotation(id, (a2) => updater(a2));
|
|
11903
12646
|
}
|
|
11904
|
-
function
|
|
11905
|
-
|
|
11906
|
-
...a2,
|
|
11907
|
-
bindingSectionOpen: !a2.bindingSectionOpen
|
|
11908
|
-
}));
|
|
11909
|
-
}
|
|
11910
|
-
function setBindingPickerPlugin(update, id, pluginName) {
|
|
11911
|
-
if (pluginName === ADD_PAGE_MANAGE_PLUGINS_VALUE || pluginName === "__install__") {
|
|
11912
|
-
openProjectSettings();
|
|
11913
|
-
return;
|
|
11914
|
-
}
|
|
11915
|
-
update(id, (a2) => ({
|
|
11916
|
-
...a2,
|
|
11917
|
-
bindingSectionOpen: true,
|
|
11918
|
-
bindingPickerPlugin: pluginName
|
|
11919
|
-
}));
|
|
11920
|
-
}
|
|
11921
|
-
function addBindingToAnnotation(update, id, pluginName, _packageName, contractName, componentKey) {
|
|
11922
|
-
const plugins = projectPlugins.pluginsList();
|
|
11923
|
-
update(id, (a2) => {
|
|
11924
|
-
const binding = bindingFromSelection(plugins, pluginName, contractName, "marker");
|
|
11925
|
-
if (!binding)
|
|
11926
|
-
return a2;
|
|
11927
|
-
if (componentKey)
|
|
11928
|
-
binding.componentKey = componentKey;
|
|
11929
|
-
return {
|
|
11930
|
-
...a2,
|
|
11931
|
-
bindingSectionOpen: true,
|
|
11932
|
-
pluginBindings: upsertAnnotationBinding(a2.pluginBindings ?? [], binding)
|
|
11933
|
-
};
|
|
11934
|
-
});
|
|
11935
|
-
}
|
|
11936
|
-
function removeBindingFromAnnotation(update, id, pluginName, contractName) {
|
|
11937
|
-
update(id, (a2) => ({
|
|
11938
|
-
...a2,
|
|
11939
|
-
pluginBindings: removeAnnotationBinding(a2.pluginBindings ?? [], pluginName, contractName)
|
|
11940
|
-
}));
|
|
11941
|
-
}
|
|
11942
|
-
function handleBindingUiEvent(target, id, update) {
|
|
11943
|
-
if (target.classList.contains("annotation-binding-toggle")) {
|
|
11944
|
-
toggleBindingSection(update, id);
|
|
11945
|
-
return;
|
|
11946
|
-
}
|
|
11947
|
-
if (target.closest("[data-marker-manage-plugins]")) {
|
|
11948
|
-
openProjectSettings();
|
|
11949
|
-
return;
|
|
11950
|
-
}
|
|
11951
|
-
if (target.classList.contains("annotation-binding-plugin")) {
|
|
11952
|
-
setBindingPickerPlugin(update, id, target.value);
|
|
12647
|
+
function updateMarkerAddMenuAnnotation(id, updater) {
|
|
12648
|
+
if (visualAnnotations().some((a2) => a2.id === id)) {
|
|
12649
|
+
updateVisualAnnotation(id, (a2) => ({ ...a2, ...updater(a2) }));
|
|
11953
12650
|
return;
|
|
11954
12651
|
}
|
|
11955
|
-
|
|
11956
|
-
|
|
11957
|
-
addBindingToAnnotation(update, id, addBtn.dataset.plugin, addBtn.dataset.package, addBtn.dataset.contract, addBtn.dataset.key ?? "");
|
|
12652
|
+
if (videoSessionAnnotations().some((a2) => a2.id === id)) {
|
|
12653
|
+
updateVideoAsVisual(id, (a2) => ({ ...a2, ...updater(a2) }));
|
|
11958
12654
|
return;
|
|
11959
12655
|
}
|
|
11960
|
-
|
|
11961
|
-
|
|
11962
|
-
removeBindingFromAnnotation(update, id, removeChip.dataset.plugin, removeChip.dataset.contract);
|
|
11963
|
-
return;
|
|
12656
|
+
if (snapshotAnnotations().some((a2) => a2.id === id)) {
|
|
12657
|
+
updateSnapshotAnnotation(id, (a2) => ({ ...a2, ...updater(a2) }));
|
|
11964
12658
|
}
|
|
11965
12659
|
}
|
|
12660
|
+
function changeRequestAddMenuPayload() {
|
|
12661
|
+
const attachments = visualAddMenu.requestAttachments();
|
|
12662
|
+
const migration = visualAddMenu.routeMigration();
|
|
12663
|
+
return {
|
|
12664
|
+
...attachments.length ? { addMenuAttachments: attachments } : {},
|
|
12665
|
+
...migration ? { routeMigration: migration } : {}
|
|
12666
|
+
};
|
|
12667
|
+
}
|
|
11966
12668
|
function setRecordingDraftInstruction(instruction) {
|
|
11967
12669
|
setRecordingDraftAnnotation((prev) => {
|
|
11968
12670
|
if (!prev)
|
|
@@ -12117,6 +12819,7 @@ function aiditorConstructor(_props, refs) {
|
|
|
12117
12819
|
setIsBootstrapping(false);
|
|
12118
12820
|
paramsCache.clear();
|
|
12119
12821
|
loadProjectInfo();
|
|
12822
|
+
void refreshAddMenuCatalog?.();
|
|
12120
12823
|
}).catch((err) => {
|
|
12121
12824
|
console.error("[aiditor] bootstrap", err);
|
|
12122
12825
|
setIsBootstrapping(false);
|
|
@@ -12296,6 +12999,10 @@ function aiditorConstructor(_props, refs) {
|
|
|
12296
12999
|
selectedPageUrl,
|
|
12297
13000
|
setCurrentPageHasBrief
|
|
12298
13001
|
});
|
|
13002
|
+
refreshAddMenuCatalog = () => {
|
|
13003
|
+
void addPage.refreshAddMenuCatalog();
|
|
13004
|
+
void visualAddMenu.refreshCatalog();
|
|
13005
|
+
};
|
|
12299
13006
|
refreshPageBriefRef.current = () => {
|
|
12300
13007
|
void addPage.refreshCurrentPageBriefAvailability();
|
|
12301
13008
|
};
|
|
@@ -12545,6 +13252,10 @@ function aiditorConstructor(_props, refs) {
|
|
|
12545
13252
|
});
|
|
12546
13253
|
refs.visualAnnotationRows.annotationRow.oninput(({ event }) => {
|
|
12547
13254
|
const t = event.target;
|
|
13255
|
+
if (t.classList.contains("cr-planned-route-input")) {
|
|
13256
|
+
visualAddMenu.setPlannedRoute(t.value);
|
|
13257
|
+
return;
|
|
13258
|
+
}
|
|
12548
13259
|
if (t.tagName !== "TEXTAREA" || !t.classList.contains("visual-annotation-instruction"))
|
|
12549
13260
|
return;
|
|
12550
13261
|
const id = t.dataset.annotationId;
|
|
@@ -12617,19 +13328,31 @@ function aiditorConstructor(_props, refs) {
|
|
|
12617
13328
|
tryJayRefExec2(refs.visualAttachFileInput, (el) => el.click());
|
|
12618
13329
|
}
|
|
12619
13330
|
});
|
|
12620
|
-
refs.visualAnnotationRows.annotationRow.onchange(({ event }) => {
|
|
12621
|
-
const t = event.target;
|
|
12622
|
-
const card = t.closest("[data-annotation-id]");
|
|
12623
|
-
const id = card?.getAttribute("data-annotation-id");
|
|
12624
|
-
if (!id)
|
|
12625
|
-
return;
|
|
12626
|
-
handleBindingUiEvent(t, id, updateVisualAnnotation);
|
|
12627
|
-
});
|
|
12628
13331
|
refs.visualAnnotationRows.annotationRow.onclick(({ event, viewState }) => {
|
|
12629
13332
|
const raw = event.target;
|
|
12630
|
-
if (raw.closest(".annotation-
|
|
13333
|
+
if (raw.closest(".annotation-add-menu")) {
|
|
12631
13334
|
event.preventDefault();
|
|
12632
|
-
|
|
13335
|
+
const handled = visualAddMenu.handleMarkerAddMenuClick(raw, viewState.id, updateMarkerAddMenuAnnotation);
|
|
13336
|
+
if (!handled) {
|
|
13337
|
+
const paramBtn = raw.closest("[data-cr-route-param]");
|
|
13338
|
+
if (paramBtn?.dataset.param) {
|
|
13339
|
+
const name = paramBtn.dataset.param;
|
|
13340
|
+
visualAddMenu.setPlannedRoute((route) => {
|
|
13341
|
+
const base = route || selectedPageUrl() || "/";
|
|
13342
|
+
if (base.includes(`[${name}]`))
|
|
13343
|
+
return base;
|
|
13344
|
+
return base.endsWith("/") ? `${base}[${name}]` : `${base}/[${name}]`;
|
|
13345
|
+
});
|
|
13346
|
+
return;
|
|
13347
|
+
}
|
|
13348
|
+
if (raw.closest("[data-cr-route-param-confirm]")) {
|
|
13349
|
+
void visualAddMenu.confirmRouteParamPick(updateMarkerAddMenuAnnotation);
|
|
13350
|
+
return;
|
|
13351
|
+
}
|
|
13352
|
+
if (raw.closest("[data-cr-route-param-cancel]")) {
|
|
13353
|
+
visualAddMenu.cancelRouteParamPick();
|
|
13354
|
+
}
|
|
13355
|
+
}
|
|
12633
13356
|
return;
|
|
12634
13357
|
}
|
|
12635
13358
|
const t = raw.closest("button");
|
|
@@ -12678,7 +13401,7 @@ function aiditorConstructor(_props, refs) {
|
|
|
12678
13401
|
return;
|
|
12679
13402
|
}
|
|
12680
13403
|
const list = visualAnnotations();
|
|
12681
|
-
const notesJson = serializeAiditorNotes(toNotesPayload(list, previewBreakpoint()));
|
|
13404
|
+
const notesJson = serializeAiditorNotes(toNotesPayload(list, previewBreakpoint(), changeRequestAddMenuPayload()));
|
|
12682
13405
|
try {
|
|
12683
13406
|
setIsRunning(true);
|
|
12684
13407
|
setVisualSubmitError("");
|
|
@@ -12722,7 +13445,7 @@ function aiditorConstructor(_props, refs) {
|
|
|
12722
13445
|
setSnapshotSubmitError("Screenshot data is missing.");
|
|
12723
13446
|
return;
|
|
12724
13447
|
}
|
|
12725
|
-
const notesJson = serializeAiditorNotes(toNotesPayload(list, previewBreakpoint()));
|
|
13448
|
+
const notesJson = serializeAiditorNotes(toNotesPayload(list, previewBreakpoint(), changeRequestAddMenuPayload()));
|
|
12726
13449
|
try {
|
|
12727
13450
|
setIsRunning(true);
|
|
12728
13451
|
setSnapshotSubmitError("");
|
|
@@ -13262,7 +13985,7 @@ function aiditorConstructor(_props, refs) {
|
|
|
13262
13985
|
fallbackRenderedUrl: rendered,
|
|
13263
13986
|
fallbackRoute: route,
|
|
13264
13987
|
breakpoint: previewBreakpoint()
|
|
13265
|
-
});
|
|
13988
|
+
}, changeRequestAddMenuPayload());
|
|
13266
13989
|
try {
|
|
13267
13990
|
setIsRunning(true);
|
|
13268
13991
|
setVideoSubmitError("");
|
|
@@ -13270,12 +13993,26 @@ function aiditorConstructor(_props, refs) {
|
|
|
13270
13993
|
const frameDuals = [];
|
|
13271
13994
|
const nFrames = distinctTimes.length;
|
|
13272
13995
|
let frameIdx = 0;
|
|
13996
|
+
videoEl.pause();
|
|
13273
13997
|
for (const t of distinctTimes) {
|
|
13274
13998
|
frameIdx += 1;
|
|
13275
13999
|
setVideoSubmitProgress(`Capturing annotated frames (${frameIdx}/${nFrames})…`);
|
|
14000
|
+
console.info("[aiditor:video-capture] frame start", {
|
|
14001
|
+
frameIdx,
|
|
14002
|
+
nFrames,
|
|
14003
|
+
timeSec: t,
|
|
14004
|
+
currentTime: videoEl.currentTime,
|
|
14005
|
+
paused: videoEl.paused
|
|
14006
|
+
});
|
|
13276
14007
|
await seekVideoToTime(videoEl, t);
|
|
14008
|
+
setVideoReviewCurrentTimeSec(t);
|
|
14009
|
+
await flushLayout();
|
|
13277
14010
|
const dual = await captureVideoInstantDual(captureRoot, videoEl);
|
|
13278
14011
|
frameDuals.push({ timeSec: t, ...dual });
|
|
14012
|
+
console.info("[aiditor:video-capture] frame done", {
|
|
14013
|
+
frameIdx,
|
|
14014
|
+
timeSec: t
|
|
14015
|
+
});
|
|
13279
14016
|
}
|
|
13280
14017
|
const attachmentsByPin = /* @__PURE__ */ new Map();
|
|
13281
14018
|
for (const a2 of list) {
|
|
@@ -13353,6 +14090,7 @@ function aiditorConstructor(_props, refs) {
|
|
|
13353
14090
|
}
|
|
13354
14091
|
function finishAgentStreamRun() {
|
|
13355
14092
|
setIsRunning(false);
|
|
14093
|
+
void refreshAddMenuCatalog?.();
|
|
13356
14094
|
focusAgentChatInput();
|
|
13357
14095
|
}
|
|
13358
14096
|
function runAgentStream(notes2, options, streamOptions) {
|
|
@@ -13665,16 +14403,12 @@ function aiditorConstructor(_props, refs) {
|
|
|
13665
14403
|
}
|
|
13666
14404
|
}
|
|
13667
14405
|
});
|
|
13668
|
-
refs.videoAnnotationRows.videoAnnotationRow.onchange(({ event }) => {
|
|
13669
|
-
const t = event.target;
|
|
13670
|
-
const card = t.closest("[data-annotation-id]");
|
|
13671
|
-
const id = card?.getAttribute("data-annotation-id");
|
|
13672
|
-
if (!id)
|
|
13673
|
-
return;
|
|
13674
|
-
handleBindingUiEvent(t, id, updateVideoAsVisual);
|
|
13675
|
-
});
|
|
13676
14406
|
refs.videoAnnotationRows.videoAnnotationRow.oninput(({ event }) => {
|
|
13677
14407
|
const t = event.target;
|
|
14408
|
+
if (t.classList.contains("cr-planned-route-input")) {
|
|
14409
|
+
visualAddMenu.setPlannedRoute(t.value);
|
|
14410
|
+
return;
|
|
14411
|
+
}
|
|
13678
14412
|
if (t.tagName !== "TEXTAREA" || !t.classList.contains("visual-annotation-instruction"))
|
|
13679
14413
|
return;
|
|
13680
14414
|
const id = t.dataset.annotationId;
|
|
@@ -13684,9 +14418,29 @@ function aiditorConstructor(_props, refs) {
|
|
|
13684
14418
|
});
|
|
13685
14419
|
refs.videoAnnotationRows.videoAnnotationRow.onclick(({ event, viewState }) => {
|
|
13686
14420
|
const raw = event.target;
|
|
13687
|
-
if (raw.closest(".annotation-
|
|
14421
|
+
if (raw.closest(".annotation-add-menu")) {
|
|
13688
14422
|
event.preventDefault();
|
|
13689
|
-
|
|
14423
|
+
const handled = visualAddMenu.handleMarkerAddMenuClick(raw, viewState.id, updateMarkerAddMenuAnnotation);
|
|
14424
|
+
if (!handled) {
|
|
14425
|
+
const paramBtn = raw.closest("[data-cr-route-param]");
|
|
14426
|
+
if (paramBtn?.dataset.param) {
|
|
14427
|
+
const name = paramBtn.dataset.param;
|
|
14428
|
+
visualAddMenu.setPlannedRoute((route) => {
|
|
14429
|
+
const base = route || selectedPageUrl() || "/";
|
|
14430
|
+
if (base.includes(`[${name}]`))
|
|
14431
|
+
return base;
|
|
14432
|
+
return base.endsWith("/") ? `${base}[${name}]` : `${base}/[${name}]`;
|
|
14433
|
+
});
|
|
14434
|
+
return;
|
|
14435
|
+
}
|
|
14436
|
+
if (raw.closest("[data-cr-route-param-confirm]")) {
|
|
14437
|
+
void visualAddMenu.confirmRouteParamPick(updateMarkerAddMenuAnnotation);
|
|
14438
|
+
return;
|
|
14439
|
+
}
|
|
14440
|
+
if (raw.closest("[data-cr-route-param-cancel]")) {
|
|
14441
|
+
visualAddMenu.cancelRouteParamPick();
|
|
14442
|
+
}
|
|
14443
|
+
}
|
|
13690
14444
|
return;
|
|
13691
14445
|
}
|
|
13692
14446
|
const t = raw.closest("button");
|
|
@@ -13930,16 +14684,12 @@ function aiditorConstructor(_props, refs) {
|
|
|
13930
14684
|
}
|
|
13931
14685
|
}
|
|
13932
14686
|
});
|
|
13933
|
-
refs.snapshotAnnotationItems.snapshotAnnotationRow.onchange(({ event }) => {
|
|
13934
|
-
const t = event.target;
|
|
13935
|
-
const card = t.closest("[data-annotation-id]");
|
|
13936
|
-
const id = card?.getAttribute("data-annotation-id");
|
|
13937
|
-
if (!id)
|
|
13938
|
-
return;
|
|
13939
|
-
handleBindingUiEvent(t, id, updateSnapshotAnnotation);
|
|
13940
|
-
});
|
|
13941
14687
|
refs.snapshotAnnotationItems.snapshotAnnotationRow.oninput(({ event }) => {
|
|
13942
14688
|
const t = event.target;
|
|
14689
|
+
if (t.classList.contains("cr-planned-route-input")) {
|
|
14690
|
+
visualAddMenu.setPlannedRoute(t.value);
|
|
14691
|
+
return;
|
|
14692
|
+
}
|
|
13943
14693
|
if (t.tagName !== "TEXTAREA" || !t.classList.contains("visual-annotation-instruction"))
|
|
13944
14694
|
return;
|
|
13945
14695
|
const id = t.dataset.annotationId;
|
|
@@ -13964,12 +14714,33 @@ function aiditorConstructor(_props, refs) {
|
|
|
13964
14714
|
});
|
|
13965
14715
|
refs.snapshotAnnotationItems.snapshotAnnotationRow.onclick(({ event }) => {
|
|
13966
14716
|
const raw = event.target;
|
|
13967
|
-
if (raw.closest(".annotation-
|
|
14717
|
+
if (raw.closest(".annotation-add-menu")) {
|
|
13968
14718
|
event.preventDefault();
|
|
13969
14719
|
const card = raw.closest("[data-annotation-id]");
|
|
13970
14720
|
const id = card?.getAttribute("data-annotation-id");
|
|
13971
|
-
if (id)
|
|
13972
|
-
|
|
14721
|
+
if (id) {
|
|
14722
|
+
const handled = visualAddMenu.handleMarkerAddMenuClick(raw, id, updateMarkerAddMenuAnnotation);
|
|
14723
|
+
if (!handled) {
|
|
14724
|
+
const paramBtn = raw.closest("[data-cr-route-param]");
|
|
14725
|
+
if (paramBtn?.dataset.param) {
|
|
14726
|
+
const name = paramBtn.dataset.param;
|
|
14727
|
+
visualAddMenu.setPlannedRoute((route) => {
|
|
14728
|
+
const base = route || selectedPageUrl() || "/";
|
|
14729
|
+
if (base.includes(`[${name}]`))
|
|
14730
|
+
return base;
|
|
14731
|
+
return base.endsWith("/") ? `${base}[${name}]` : `${base}/[${name}]`;
|
|
14732
|
+
});
|
|
14733
|
+
return;
|
|
14734
|
+
}
|
|
14735
|
+
if (raw.closest("[data-cr-route-param-confirm]")) {
|
|
14736
|
+
void visualAddMenu.confirmRouteParamPick(updateMarkerAddMenuAnnotation);
|
|
14737
|
+
return;
|
|
14738
|
+
}
|
|
14739
|
+
if (raw.closest("[data-cr-route-param-cancel]")) {
|
|
14740
|
+
visualAddMenu.cancelRouteParamPick();
|
|
14741
|
+
}
|
|
14742
|
+
}
|
|
14743
|
+
}
|
|
13973
14744
|
return;
|
|
13974
14745
|
}
|
|
13975
14746
|
const btn = raw.closest("button");
|
|
@@ -14189,6 +14960,14 @@ function aiditorConstructor(_props, refs) {
|
|
|
14189
14960
|
recordingDraftUi,
|
|
14190
14961
|
recordingDraftAttachmentChips,
|
|
14191
14962
|
showRecordingDraftPopover,
|
|
14963
|
+
showMarkerAddMenuPopover,
|
|
14964
|
+
markerAddMenuPopoverLeftPct,
|
|
14965
|
+
markerAddMenuPopoverTopPct,
|
|
14966
|
+
markerAddMenuPickerAnnotationId,
|
|
14967
|
+
markerAddMenuNavRows,
|
|
14968
|
+
markerAddMenuSelectedCategory,
|
|
14969
|
+
showMarkerAddMenuPickerLoading,
|
|
14970
|
+
showMarkerAddMenuPickerCatalogEmpty,
|
|
14192
14971
|
showVisualAnnotationsPanel,
|
|
14193
14972
|
showVisualSubmitError,
|
|
14194
14973
|
visualSubmitError,
|
|
@@ -14301,16 +15080,19 @@ function aiditorConstructor(_props, refs) {
|
|
|
14301
15080
|
projectLocalPluginName: projectPlugins.addLocalPluginName,
|
|
14302
15081
|
projectLocalPackageName: projectPlugins.addLocalPackageName,
|
|
14303
15082
|
projectLocalPath: projectPlugins.addLocalPath,
|
|
14304
|
-
|
|
14305
|
-
|
|
14306
|
-
|
|
14307
|
-
|
|
14308
|
-
|
|
14309
|
-
|
|
14310
|
-
|
|
14311
|
-
|
|
14312
|
-
|
|
14313
|
-
|
|
15083
|
+
showAddMenuPanel: addPage.showAddMenuPanel,
|
|
15084
|
+
showAddMenuChips: addPage.showAddMenuChips,
|
|
15085
|
+
addMenuChipRows: addPage.addMenuChipRows,
|
|
15086
|
+
showAddMenuEmptyHint: addPage.showAddMenuEmptyHint,
|
|
15087
|
+
showAddMenuPopover: addPage.showAddMenuPopover,
|
|
15088
|
+
addMenuNavRows: addPage.addMenuNavRows,
|
|
15089
|
+
addMenuSelectedCategory: addPage.addMenuSelectedCategory,
|
|
15090
|
+
addMenuParamCollisionWarning: addPage.addMenuParamCollisionWarning,
|
|
15091
|
+
addMenuRouteParamHint: addPage.addMenuRouteParamHint,
|
|
15092
|
+
showAddMenuRouteParams: addPage.showAddMenuRouteParams,
|
|
15093
|
+
addMenuRouteParamRows: addPage.addMenuRouteParamRows,
|
|
15094
|
+
showAddMenuRouteParamConfirm: addPage.showAddMenuRouteParamConfirm,
|
|
15095
|
+
addMenuPendingRouteParamTitle: addPage.addMenuPendingRouteParamTitle,
|
|
14314
15096
|
showAddPageResultBanner,
|
|
14315
15097
|
addPageResultBannerClass,
|
|
14316
15098
|
addPageResultBannerMessage,
|
|
@@ -14330,7 +15112,15 @@ function aiditorConstructor(_props, refs) {
|
|
|
14330
15112
|
showBriefFillThumbnails: addPage.showBriefFillThumbnails,
|
|
14331
15113
|
addPageBriefFillThumbRows: addPage.addPageBriefFillThumbRows,
|
|
14332
15114
|
showSuggestedRouteBanner: addPage.showSuggestedRouteBanner,
|
|
14333
|
-
suggestedRouteLabel: addPage.suggestedRouteLabel
|
|
15115
|
+
suggestedRouteLabel: addPage.suggestedRouteLabel,
|
|
15116
|
+
crAddMenuParamCollisionWarning: visualAddMenu.paramCollisionWarning,
|
|
15117
|
+
crAddMenuRouteParamHint: visualAddMenu.routeParamHint,
|
|
15118
|
+
showCrAddMenuRouteParams: visualAddMenu.showRouteParams,
|
|
15119
|
+
crAddMenuRouteParamRows: visualAddMenu.routeParamRows,
|
|
15120
|
+
showCrRouteParamConfirm: visualAddMenu.showRouteParamConfirm,
|
|
15121
|
+
crPendingRouteParamTitle: visualAddMenu.pendingRouteParamTitle,
|
|
15122
|
+
showCrPlannedRoutePanel,
|
|
15123
|
+
crPlannedRoute: visualAddMenu.plannedRoute
|
|
14334
15124
|
})
|
|
14335
15125
|
};
|
|
14336
15126
|
}
|