@jay-framework/aiditor 0.18.4 → 0.19.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/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 +1360 -564
- package/dist/index.d.ts +89 -729
- package/dist/index.js +981 -503
- package/dist/pages/aiditor/page.css +2259 -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,24 @@ 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", {
|
|
8514
|
+
mode: "markersOnly"
|
|
8515
|
+
});
|
|
8499
8516
|
const markersOnly = await capturePreviewForVideoFrame(
|
|
8500
8517
|
rootEl,
|
|
8501
8518
|
videoEl,
|
|
8502
8519
|
"markersOnly"
|
|
8503
8520
|
);
|
|
8521
|
+
console.info("[aiditor:video-capture] capture done", {
|
|
8522
|
+
mode: "markersOnly",
|
|
8523
|
+
bytes: markersOnly.size
|
|
8524
|
+
});
|
|
8504
8525
|
return { clean, markersOnly };
|
|
8505
8526
|
}
|
|
8506
8527
|
function getRestrictionTargetCtor() {
|
|
@@ -8787,19 +8808,54 @@ async function ensureAddPageRequestId(pageRoute, currentRequestId) {
|
|
|
8787
8808
|
}
|
|
8788
8809
|
return { requestId: result.requestId };
|
|
8789
8810
|
}
|
|
8790
|
-
function
|
|
8791
|
-
|
|
8792
|
-
|
|
8811
|
+
function formatRouteParamToken(paramName) {
|
|
8812
|
+
return `[${paramName}]`;
|
|
8813
|
+
}
|
|
8814
|
+
function insertRouteParamInField(input, currentRoute, paramName) {
|
|
8815
|
+
const token = formatRouteParamToken(paramName);
|
|
8816
|
+
const route = currentRoute.trim() || "/";
|
|
8817
|
+
if (route.includes(token)) return route;
|
|
8818
|
+
const insertWithSlash = (before) => {
|
|
8819
|
+
if (before.length === 0) return token;
|
|
8820
|
+
const last = before[before.length - 1];
|
|
8821
|
+
if (last === "/" || last === "]") return token;
|
|
8822
|
+
return `/${token}`;
|
|
8823
|
+
};
|
|
8824
|
+
if (input && document.activeElement === input) {
|
|
8825
|
+
const start = input.selectionStart ?? route.length;
|
|
8826
|
+
const end = input.selectionEnd ?? start;
|
|
8827
|
+
const before = route.slice(0, start);
|
|
8828
|
+
const after = route.slice(end);
|
|
8829
|
+
const insert2 = insertWithSlash(before);
|
|
8830
|
+
const next = before + insert2 + after;
|
|
8831
|
+
queueMicrotask(() => {
|
|
8832
|
+
const pos = before.length + insert2.length;
|
|
8833
|
+
input.setSelectionRange(pos, pos);
|
|
8834
|
+
input.focus();
|
|
8835
|
+
});
|
|
8836
|
+
return next;
|
|
8837
|
+
}
|
|
8838
|
+
const insert = insertWithSlash(route);
|
|
8839
|
+
return route.endsWith("/") ? `${route}${token}` : `${route}${insert}`;
|
|
8840
|
+
}
|
|
8841
|
+
function insertTextAtRange(currentValue, text, selectionStart, selectionEnd = selectionStart) {
|
|
8842
|
+
const start = Math.max(0, Math.min(selectionStart, currentValue.length));
|
|
8843
|
+
const end = Math.max(start, Math.min(selectionEnd, currentValue.length));
|
|
8793
8844
|
const before = currentValue.slice(0, start);
|
|
8794
8845
|
const after = currentValue.slice(end);
|
|
8795
8846
|
const prefix = before.length > 0 && !before.endsWith("\n") ? "\n" : "";
|
|
8796
8847
|
const insertion = `${prefix}${text}
|
|
8797
8848
|
`;
|
|
8798
8849
|
const next = before + insertion + after;
|
|
8799
|
-
|
|
8850
|
+
return { next, cursor: before.length + insertion.length };
|
|
8851
|
+
}
|
|
8852
|
+
function insertTextAtCursor(textarea, text, currentValue, selection) {
|
|
8853
|
+
const start = textarea.selectionStart ?? currentValue.length;
|
|
8854
|
+
const end = textarea.selectionEnd ?? start;
|
|
8855
|
+
const { next, cursor } = insertTextAtRange(currentValue, text, start, end);
|
|
8800
8856
|
queueMicrotask(() => {
|
|
8801
|
-
textarea.selectionStart =
|
|
8802
|
-
textarea.selectionEnd =
|
|
8857
|
+
textarea.selectionStart = cursor;
|
|
8858
|
+
textarea.selectionEnd = cursor;
|
|
8803
8859
|
textarea.focus();
|
|
8804
8860
|
});
|
|
8805
8861
|
return next;
|
|
@@ -9223,383 +9279,465 @@ ${md}`);
|
|
|
9223
9279
|
briefFillGenerating: generating
|
|
9224
9280
|
};
|
|
9225
9281
|
}
|
|
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
|
|
9282
|
+
function detectRequiredParamCollisions(resolved) {
|
|
9283
|
+
const byContract = /* @__PURE__ */ new Map();
|
|
9284
|
+
for (const r of resolved) {
|
|
9285
|
+
byContract.set(r.contractName, r);
|
|
9286
|
+
}
|
|
9287
|
+
const contracts = [...byContract.values()];
|
|
9288
|
+
if (contracts.length < 2) return [];
|
|
9289
|
+
const warnings = [];
|
|
9290
|
+
for (let i = 0; i < contracts.length; i++) {
|
|
9291
|
+
for (let j = i + 1; j < contracts.length; j++) {
|
|
9292
|
+
const a2 = contracts[i];
|
|
9293
|
+
const b = contracts[j];
|
|
9294
|
+
if (a2.contractName === b.contractName) continue;
|
|
9295
|
+
const overlap = a2.requiredParams.filter(
|
|
9296
|
+
(p) => b.requiredParams.includes(p)
|
|
9297
|
+
);
|
|
9298
|
+
for (const param of overlap) {
|
|
9299
|
+
warnings.push({
|
|
9300
|
+
overlappingParam: param,
|
|
9301
|
+
contractNames: [a2.contractName, b.contractName],
|
|
9302
|
+
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.`
|
|
9303
|
+
});
|
|
9304
|
+
}
|
|
9305
|
+
}
|
|
9310
9306
|
}
|
|
9311
|
-
|
|
9312
|
-
function getCatalogEntry(pluginName) {
|
|
9313
|
-
return CATALOG.find((e2) => e2.pluginName === pluginName);
|
|
9307
|
+
return warnings;
|
|
9314
9308
|
}
|
|
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];
|
|
9309
|
+
function collectRouteSegmentNames(resolved) {
|
|
9310
|
+
const names = /* @__PURE__ */ new Set();
|
|
9311
|
+
for (const r of resolved) {
|
|
9312
|
+
for (const p of r.allParams) names.add(p);
|
|
9325
9313
|
}
|
|
9326
|
-
return
|
|
9314
|
+
return [...names].sort((a2, b) => a2.localeCompare(b));
|
|
9327
9315
|
}
|
|
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 });
|
|
9316
|
+
function routeHasDynamicSegment(route, paramName) {
|
|
9317
|
+
return route.includes(`[${paramName}]`);
|
|
9338
9318
|
}
|
|
9339
|
-
|
|
9340
|
-
return
|
|
9319
|
+
function routeHasAnyDynamicSegment(route) {
|
|
9320
|
+
return /\[[^\]]+\]/.test(route);
|
|
9341
9321
|
}
|
|
9342
|
-
function
|
|
9343
|
-
|
|
9344
|
-
const
|
|
9345
|
-
|
|
9322
|
+
function suggestMissingRouteSegments(route, segmentNames) {
|
|
9323
|
+
const trimmed = route.replace(/\/+$/, "") || "/";
|
|
9324
|
+
const missing = segmentNames.filter(
|
|
9325
|
+
(name) => !routeHasDynamicSegment(trimmed, name)
|
|
9326
|
+
);
|
|
9327
|
+
if (missing.length === 0) return null;
|
|
9328
|
+
const suffix = missing.map((n) => `[${n}]`).join("/");
|
|
9329
|
+
if (trimmed === "/") return `/${suffix}`;
|
|
9330
|
+
return `${trimmed}/${suffix}`;
|
|
9331
|
+
}
|
|
9332
|
+
function stripNavRowCore(row) {
|
|
9333
|
+
const { item: _item, ...viewRow } = row;
|
|
9334
|
+
return viewRow;
|
|
9335
|
+
}
|
|
9336
|
+
function stripNavRowForView(row) {
|
|
9337
|
+
return stripNavRowCore(row);
|
|
9338
|
+
}
|
|
9339
|
+
function stripMarkerAddMenuNavRowForPage(row) {
|
|
9340
|
+
return stripNavRowCore(row);
|
|
9341
|
+
}
|
|
9342
|
+
function stripMarkerPickerNavRowForVisual(row) {
|
|
9343
|
+
return stripNavRowCore(
|
|
9344
|
+
row
|
|
9345
|
+
);
|
|
9346
|
+
}
|
|
9347
|
+
function stripMarkerPickerNavRowForVideo(row) {
|
|
9348
|
+
return stripNavRowCore(
|
|
9349
|
+
row
|
|
9350
|
+
);
|
|
9351
|
+
}
|
|
9352
|
+
function stripMarkerPickerNavRowForSnapshot(row) {
|
|
9353
|
+
return stripNavRowCore(
|
|
9354
|
+
row
|
|
9355
|
+
);
|
|
9356
|
+
}
|
|
9357
|
+
function buildAddMenuNavRows(categories, panelOpen, selectedCategory, selectedSubCategory) {
|
|
9358
|
+
if (!panelOpen) return [];
|
|
9359
|
+
const cat = selectedCategory;
|
|
9360
|
+
if (!cat) {
|
|
9361
|
+
return categories.map((c) => ({
|
|
9362
|
+
rowKey: `cat:${c.category}`,
|
|
9363
|
+
label: c.category,
|
|
9364
|
+
value: c.category,
|
|
9365
|
+
kind: 0
|
|
9366
|
+
/* category */
|
|
9367
|
+
}));
|
|
9368
|
+
}
|
|
9369
|
+
const group = categories.find((c) => c.category === cat);
|
|
9370
|
+
if (!group) return [];
|
|
9371
|
+
const sub = selectedSubCategory;
|
|
9372
|
+
if (sub === null && group.subCategories.length > 1) {
|
|
9373
|
+
return group.subCategories.map((s) => ({
|
|
9374
|
+
rowKey: `sub:${cat}:${s.subCategory ?? ""}`,
|
|
9375
|
+
label: s.subCategory ?? "General",
|
|
9376
|
+
value: s.subCategory ?? "",
|
|
9377
|
+
kind: 1
|
|
9378
|
+
/* subCategory */
|
|
9379
|
+
}));
|
|
9380
|
+
}
|
|
9381
|
+
const subKey = sub ?? group.subCategories[0]?.subCategory ?? null;
|
|
9382
|
+
const items = group.subCategories.find((s) => s.subCategory === subKey)?.items ?? group.subCategories[0]?.items ?? [];
|
|
9383
|
+
return items.map((item) => ({
|
|
9384
|
+
rowKey: `item:${item.id}`,
|
|
9385
|
+
label: item.title,
|
|
9386
|
+
value: item.id,
|
|
9387
|
+
kind: 2,
|
|
9388
|
+
item
|
|
9389
|
+
}));
|
|
9390
|
+
}
|
|
9391
|
+
const listAddMenuItemsAction = createActionCaller("aiditor.listAddMenuItems", "GET");
|
|
9392
|
+
const resolveAddMenuContractParamsAction = createActionCaller("aiditor.resolveAddMenuContractParams", "GET");
|
|
9393
|
+
const syncAddMenuAttachmentsAction = createActionCaller("aiditor.syncAddMenuAttachments", "GET");
|
|
9394
|
+
async function listAddMenuItems() {
|
|
9395
|
+
return listAddMenuItemsAction({});
|
|
9396
|
+
}
|
|
9397
|
+
async function resolveContractParamsForItem(_projectDir, item) {
|
|
9398
|
+
const result = await resolveAddMenuContractParamsAction({
|
|
9399
|
+
itemId: item.id,
|
|
9400
|
+
pluginName: item.pluginName
|
|
9401
|
+
});
|
|
9402
|
+
if (!result.contractName || !result.pluginName) return null;
|
|
9403
|
+
return {
|
|
9404
|
+
contractName: result.contractName,
|
|
9405
|
+
pluginName: result.pluginName,
|
|
9406
|
+
requiredParams: result.requiredParams ?? [],
|
|
9407
|
+
allParams: result.allParams ?? []
|
|
9346
9408
|
};
|
|
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
9409
|
}
|
|
9366
|
-
async function
|
|
9367
|
-
return
|
|
9410
|
+
async function syncAddMenuAttachments(input) {
|
|
9411
|
+
return syncAddMenuAttachmentsAction(input);
|
|
9368
9412
|
}
|
|
9369
|
-
|
|
9370
|
-
return
|
|
9413
|
+
function attachmentScopeKey(a2) {
|
|
9414
|
+
return a2.annotationId ?? "";
|
|
9371
9415
|
}
|
|
9372
|
-
|
|
9373
|
-
|
|
9416
|
+
function dedupeAddMenuAttachment(prev, next) {
|
|
9417
|
+
const scope = attachmentScopeKey(next);
|
|
9418
|
+
const exists = prev.some(
|
|
9419
|
+
(a2) => a2.itemId === next.itemId && attachmentScopeKey(a2) === scope
|
|
9420
|
+
);
|
|
9421
|
+
if (exists) return prev;
|
|
9422
|
+
return [...prev, next];
|
|
9374
9423
|
}
|
|
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
|
|
9424
|
+
function removeAddMenuAttachment(prev, itemId, annotationId) {
|
|
9425
|
+
const scope = annotationId ?? "";
|
|
9426
|
+
return prev.filter(
|
|
9427
|
+
(a2) => !(a2.itemId === itemId && attachmentScopeKey(a2) === scope)
|
|
9394
9428
|
);
|
|
9395
9429
|
}
|
|
9396
|
-
function
|
|
9397
|
-
|
|
9398
|
-
|
|
9399
|
-
|
|
9400
|
-
|
|
9401
|
-
|
|
9402
|
-
|
|
9403
|
-
|
|
9404
|
-
|
|
9405
|
-
|
|
9406
|
-
|
|
9407
|
-
const
|
|
9408
|
-
const [
|
|
9409
|
-
const [
|
|
9410
|
-
const [
|
|
9430
|
+
function initAddMenuPanel(deps) {
|
|
9431
|
+
const [attachments, setAttachments] = createSignal([]);
|
|
9432
|
+
const [catalogItems, setCatalogItems] = createSignal([]);
|
|
9433
|
+
const [catalogCategories, setCatalogCategories] = createSignal([]);
|
|
9434
|
+
const [catalogWarnings, setCatalogWarnings] = createSignal([]);
|
|
9435
|
+
const [panelOpen, setPanelOpen] = createSignal(false);
|
|
9436
|
+
const [selectedCategory, setSelectedCategory] = createSignal("");
|
|
9437
|
+
const [selectedSubCategory, setSelectedSubCategory] = createSignal(null);
|
|
9438
|
+
const [routeMigration, setRouteMigration] = createSignal(null);
|
|
9439
|
+
const [paramCollisionWarning, setParamCollisionWarning] = createSignal("");
|
|
9440
|
+
const [routeParamHint, setRouteParamHint] = createSignal("");
|
|
9441
|
+
const [pendingRouteParamItem, setPendingRouteParamItem] = createSignal(null);
|
|
9442
|
+
const [showRouteParamConfirm, setShowRouteParamConfirm] = createSignal(false);
|
|
9443
|
+
const [catalogLoading, setCatalogLoading] = createSignal(false);
|
|
9444
|
+
const [catalogLoaded, setCatalogLoaded] = createSignal(false);
|
|
9411
9445
|
let syncTimer;
|
|
9412
|
-
const
|
|
9413
|
-
|
|
9414
|
-
|
|
9415
|
-
|
|
9446
|
+
const itemById = createMemo(() => {
|
|
9447
|
+
const map = /* @__PURE__ */ new Map();
|
|
9448
|
+
for (const item of catalogItems()) map.set(item.id, item);
|
|
9449
|
+
return map;
|
|
9450
|
+
});
|
|
9451
|
+
const chipRows = createMemo(
|
|
9452
|
+
() => attachments().map((a2) => {
|
|
9453
|
+
const item = itemById().get(a2.itemId);
|
|
9454
|
+
return {
|
|
9455
|
+
rowKey: `${a2.itemId}:${a2.annotationId ?? "request"}`,
|
|
9456
|
+
itemId: a2.itemId,
|
|
9457
|
+
title: item?.title ?? a2.itemId,
|
|
9458
|
+
subtitle: item?.pluginName ?? item?.id.split(":")[0] ?? "",
|
|
9459
|
+
annotationId: a2.annotationId
|
|
9460
|
+
};
|
|
9461
|
+
})
|
|
9416
9462
|
);
|
|
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
|
-
}
|
|
9463
|
+
const showAddMenuPanel = createMemo(() => true);
|
|
9464
|
+
const showAddMenuEmptyHint = createMemo(
|
|
9465
|
+
() => catalogItems().length === 0 && !catalogLoading()
|
|
9431
9466
|
);
|
|
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
|
-
}
|
|
9467
|
+
const showAddMenuChips = createMemo(() => chipRows().length > 0);
|
|
9468
|
+
const menuNavRows = createMemo(
|
|
9469
|
+
() => buildAddMenuNavRows(
|
|
9470
|
+
catalogCategories(),
|
|
9471
|
+
panelOpen(),
|
|
9472
|
+
selectedCategory(),
|
|
9473
|
+
selectedSubCategory()
|
|
9474
|
+
)
|
|
9449
9475
|
);
|
|
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
|
|
9476
|
+
const menuNavRowsForView = createMemo(
|
|
9477
|
+
() => menuNavRows().map(stripNavRowForView)
|
|
9470
9478
|
);
|
|
9471
|
-
const
|
|
9472
|
-
|
|
9479
|
+
const [routeSegmentNames, setRouteSegmentNames] = createSignal([]);
|
|
9480
|
+
const routeParamRows = createMemo(
|
|
9481
|
+
() => routeSegmentNames().map((name) => ({
|
|
9482
|
+
rowKey: name,
|
|
9483
|
+
name
|
|
9484
|
+
}))
|
|
9473
9485
|
);
|
|
9474
|
-
|
|
9475
|
-
|
|
9476
|
-
|
|
9477
|
-
|
|
9486
|
+
async function refreshCatalog() {
|
|
9487
|
+
setCatalogLoading(true);
|
|
9488
|
+
try {
|
|
9489
|
+
const result = await listAddMenuItems();
|
|
9490
|
+
setCatalogItems(result.items);
|
|
9491
|
+
setCatalogCategories(result.categories);
|
|
9492
|
+
setCatalogWarnings(result.warnings);
|
|
9493
|
+
if (result.warnings.length > 0) {
|
|
9494
|
+
console.warn("[aiditor] Add Menu catalog warnings:", result.warnings);
|
|
9495
|
+
}
|
|
9496
|
+
} catch (err) {
|
|
9497
|
+
console.error("[aiditor] listAddMenuItems failed:", err);
|
|
9498
|
+
setCatalogItems([]);
|
|
9499
|
+
setCatalogCategories([]);
|
|
9500
|
+
setCatalogWarnings([]);
|
|
9501
|
+
} finally {
|
|
9502
|
+
setCatalogLoaded(true);
|
|
9503
|
+
setCatalogLoading(false);
|
|
9504
|
+
}
|
|
9505
|
+
}
|
|
9506
|
+
async function ensureCatalogLoaded() {
|
|
9507
|
+
if (catalogLoaded() || catalogLoading()) return;
|
|
9508
|
+
await refreshCatalog();
|
|
9509
|
+
}
|
|
9510
|
+
async function updateRouteHelpers() {
|
|
9511
|
+
const resolved = [];
|
|
9512
|
+
for (const a2 of attachments()) {
|
|
9513
|
+
const item = itemById().get(a2.itemId);
|
|
9514
|
+
if (!item) continue;
|
|
9515
|
+
const params = await resolveContractParamsForItem(
|
|
9516
|
+
deps.projectDir(),
|
|
9517
|
+
item
|
|
9518
|
+
);
|
|
9519
|
+
if (params) resolved.push(params);
|
|
9520
|
+
}
|
|
9521
|
+
const collisions = detectRequiredParamCollisions(resolved);
|
|
9522
|
+
setParamCollisionWarning(collisions[0]?.message ?? "");
|
|
9523
|
+
const segments = collectRouteSegmentNames(resolved);
|
|
9524
|
+
if (segments.length === 0) {
|
|
9525
|
+
setRouteParamHint("");
|
|
9526
|
+
return segments;
|
|
9527
|
+
}
|
|
9528
|
+
const route = deps.getPageRoute();
|
|
9529
|
+
const suggested = suggestMissingRouteSegments(route, segments);
|
|
9530
|
+
setRouteParamHint(
|
|
9531
|
+
suggested && suggested !== route ? `Suggested route segments: ${suggested}` : ""
|
|
9478
9532
|
);
|
|
9479
|
-
|
|
9533
|
+
setRouteSegmentNames(segments);
|
|
9534
|
+
return segments;
|
|
9535
|
+
}
|
|
9480
9536
|
function scheduleManifestSync() {
|
|
9481
9537
|
const requestId = deps.getRequestId();
|
|
9482
9538
|
if (!requestId) return;
|
|
9483
9539
|
if (syncTimer) clearTimeout(syncTimer);
|
|
9484
9540
|
syncTimer = setTimeout(() => {
|
|
9485
|
-
void
|
|
9541
|
+
void syncAddMenuAttachments({
|
|
9486
9542
|
requestId,
|
|
9487
|
-
|
|
9488
|
-
|
|
9489
|
-
if (res.ok && res.contentMd) {
|
|
9490
|
-
deps.setContentMd(res.contentMd);
|
|
9491
|
-
}
|
|
9543
|
+
addMenuAttachments: attachments(),
|
|
9544
|
+
routeMigration: routeMigration() ?? void 0
|
|
9492
9545
|
});
|
|
9493
9546
|
}, 300);
|
|
9494
9547
|
}
|
|
9495
|
-
function
|
|
9496
|
-
|
|
9497
|
-
|
|
9498
|
-
|
|
9499
|
-
pluginName,
|
|
9500
|
-
packageName,
|
|
9501
|
-
contractName,
|
|
9502
|
-
componentKey
|
|
9503
|
-
)
|
|
9548
|
+
async function commitAttachment(item, annotationId) {
|
|
9549
|
+
deps.preserveEditorContent();
|
|
9550
|
+
setAttachments(
|
|
9551
|
+
(prev) => dedupeAddMenuAttachment(prev, { itemId: item.id, annotationId })
|
|
9504
9552
|
);
|
|
9553
|
+
await updateRouteHelpers();
|
|
9505
9554
|
scheduleManifestSync();
|
|
9506
|
-
|
|
9507
|
-
|
|
9508
|
-
|
|
9509
|
-
|
|
9510
|
-
|
|
9511
|
-
|
|
9512
|
-
|
|
9513
|
-
|
|
9514
|
-
|
|
9515
|
-
|
|
9516
|
-
openProjectSettings();
|
|
9517
|
-
setPickerPlugin("");
|
|
9555
|
+
setPanelOpen(false);
|
|
9556
|
+
setSelectedCategory("");
|
|
9557
|
+
setSelectedSubCategory(null);
|
|
9558
|
+
}
|
|
9559
|
+
async function tryAddItem(item, annotationId) {
|
|
9560
|
+
const params = await resolveContractParamsForItem(deps.projectDir(), item);
|
|
9561
|
+
const hasRouteParams = !!params && params.allParams.length > 0;
|
|
9562
|
+
if (deps.changeRequestMode?.() && hasRouteParams && deps.getCurrentRoute && !routeHasAnyDynamicSegment(deps.getCurrentRoute() ?? "")) {
|
|
9563
|
+
setPendingRouteParamItem(item);
|
|
9564
|
+
setShowRouteParamConfirm(true);
|
|
9518
9565
|
return;
|
|
9519
9566
|
}
|
|
9520
|
-
|
|
9521
|
-
|
|
9522
|
-
|
|
9523
|
-
|
|
9524
|
-
|
|
9567
|
+
await commitAttachment(item, annotationId);
|
|
9568
|
+
}
|
|
9569
|
+
async function confirmRouteParamAttach(annotationId) {
|
|
9570
|
+
const item = pendingRouteParamItem();
|
|
9571
|
+
if (!item) return;
|
|
9572
|
+
const current = deps.getCurrentRoute?.() ?? "/";
|
|
9573
|
+
const params = await resolveContractParamsForItem(deps.projectDir(), item);
|
|
9574
|
+
const segments = params ? collectRouteSegmentNames([params]) : [];
|
|
9575
|
+
const planned = suggestMissingRouteSegments(current, segments) ?? `${current}/[slug]`;
|
|
9576
|
+
deps.setPlannedRoute?.(planned);
|
|
9577
|
+
setRouteMigration({
|
|
9578
|
+
currentRoute: current,
|
|
9579
|
+
plannedRoute: planned,
|
|
9580
|
+
reason: "add-menu-route-param-component",
|
|
9581
|
+
triggeringItemIds: [item.id]
|
|
9582
|
+
});
|
|
9583
|
+
setShowRouteParamConfirm(false);
|
|
9584
|
+
setPendingRouteParamItem(null);
|
|
9585
|
+
await commitAttachment(item, annotationId);
|
|
9586
|
+
}
|
|
9587
|
+
function cancelRouteParamAttach() {
|
|
9588
|
+
setShowRouteParamConfirm(false);
|
|
9589
|
+
setPendingRouteParamItem(null);
|
|
9590
|
+
}
|
|
9591
|
+
function removeChip(itemId, annotationId) {
|
|
9592
|
+
deps.preserveEditorContent();
|
|
9593
|
+
setAttachments(
|
|
9594
|
+
(prev) => removeAddMenuAttachment(prev, itemId, annotationId)
|
|
9595
|
+
);
|
|
9596
|
+
void updateRouteHelpers();
|
|
9597
|
+
scheduleManifestSync();
|
|
9525
9598
|
}
|
|
9526
|
-
function
|
|
9527
|
-
|
|
9528
|
-
|
|
9529
|
-
|
|
9599
|
+
function openPanel() {
|
|
9600
|
+
void ensureCatalogLoaded();
|
|
9601
|
+
setPanelOpen(true);
|
|
9602
|
+
setSelectedCategory("");
|
|
9603
|
+
setSelectedSubCategory(null);
|
|
9604
|
+
}
|
|
9605
|
+
function closePanel() {
|
|
9606
|
+
setPanelOpen(false);
|
|
9607
|
+
}
|
|
9608
|
+
function resetAddMenuPanel() {
|
|
9609
|
+
setAttachments([]);
|
|
9610
|
+
setRouteMigration(null);
|
|
9611
|
+
setParamCollisionWarning("");
|
|
9612
|
+
setRouteParamHint("");
|
|
9613
|
+
setPanelOpen(false);
|
|
9530
9614
|
if (syncTimer) clearTimeout(syncTimer);
|
|
9531
9615
|
}
|
|
9532
|
-
function
|
|
9533
|
-
|
|
9534
|
-
|
|
9535
|
-
|
|
9536
|
-
|
|
9616
|
+
function bindRouteParamButtons(el) {
|
|
9617
|
+
el?.onclick(({ event }) => {
|
|
9618
|
+
const paramBtn = event.target.closest(
|
|
9619
|
+
"[data-add-menu-param]"
|
|
9620
|
+
);
|
|
9621
|
+
if (paramBtn?.dataset.param) {
|
|
9622
|
+
deps.insertRouteParam(paramBtn.dataset.param);
|
|
9537
9623
|
}
|
|
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
|
-
}
|
|
9624
|
+
});
|
|
9625
|
+
}
|
|
9626
|
+
function bindAddMenuPanelRefs(refs) {
|
|
9627
|
+
bindRouteParamButtons(refs.addPageRouteParamsPanel);
|
|
9628
|
+
refs.addMenuPanel?.onclick(({ event }) => {
|
|
9629
|
+
const target = event.target;
|
|
9630
|
+
const openBtn = target.closest("[data-add-menu-open]");
|
|
9631
|
+
if (openBtn) {
|
|
9632
|
+
openPanel();
|
|
9633
|
+
return;
|
|
9569
9634
|
}
|
|
9570
|
-
|
|
9635
|
+
const closeBtn = target.closest("[data-add-menu-close]");
|
|
9636
|
+
if (closeBtn) {
|
|
9637
|
+
closePanel();
|
|
9638
|
+
return;
|
|
9639
|
+
}
|
|
9640
|
+
const manage = target.closest("[data-add-menu-manage-plugins]");
|
|
9641
|
+
if (manage) {
|
|
9642
|
+
deps.openProjectSettings();
|
|
9643
|
+
return;
|
|
9644
|
+
}
|
|
9645
|
+
const catBtn = target.closest(
|
|
9646
|
+
"[data-add-menu-category]"
|
|
9647
|
+
);
|
|
9648
|
+
if (catBtn?.dataset.category) {
|
|
9649
|
+
setSelectedCategory(catBtn.dataset.category);
|
|
9650
|
+
setSelectedSubCategory(null);
|
|
9651
|
+
return;
|
|
9652
|
+
}
|
|
9653
|
+
const subBtn = target.closest(
|
|
9654
|
+
"[data-add-menu-subcategory]"
|
|
9655
|
+
);
|
|
9656
|
+
if (subBtn?.dataset.subcategory !== void 0) {
|
|
9657
|
+
setSelectedSubCategory(subBtn.dataset.subcategory || null);
|
|
9658
|
+
return;
|
|
9659
|
+
}
|
|
9660
|
+
const pickBtn = target.closest(
|
|
9661
|
+
"[data-add-menu-pick]"
|
|
9662
|
+
);
|
|
9663
|
+
if (pickBtn?.dataset.itemId) {
|
|
9664
|
+
const item = itemById().get(pickBtn.dataset.itemId);
|
|
9665
|
+
if (item) void tryAddItem(item);
|
|
9666
|
+
return;
|
|
9667
|
+
}
|
|
9668
|
+
const removeBtn = target.closest(
|
|
9669
|
+
"[data-add-menu-remove-chip]"
|
|
9670
|
+
);
|
|
9671
|
+
if (removeBtn?.dataset.itemId) {
|
|
9672
|
+
removeChip(removeBtn.dataset.itemId, removeBtn.dataset.annotationId);
|
|
9673
|
+
return;
|
|
9674
|
+
}
|
|
9675
|
+
const paramBtn = target.closest(
|
|
9676
|
+
"[data-add-menu-param]"
|
|
9677
|
+
);
|
|
9678
|
+
if (paramBtn?.dataset.param) {
|
|
9679
|
+
deps.insertRouteParam(paramBtn.dataset.param);
|
|
9680
|
+
return;
|
|
9681
|
+
}
|
|
9682
|
+
const atBtn = target.closest(
|
|
9683
|
+
"[data-add-menu-at-title]"
|
|
9684
|
+
);
|
|
9685
|
+
if (atBtn?.dataset.title) {
|
|
9686
|
+
deps.insertAtCursor(`@${atBtn.dataset.title}`);
|
|
9687
|
+
return;
|
|
9688
|
+
}
|
|
9689
|
+
const confirmBtn = target.closest("[data-add-menu-route-confirm]");
|
|
9690
|
+
if (confirmBtn) {
|
|
9691
|
+
void confirmRouteParamAttach();
|
|
9692
|
+
return;
|
|
9693
|
+
}
|
|
9694
|
+
const cancelBtn = target.closest("[data-add-menu-route-cancel]");
|
|
9695
|
+
if (cancelBtn) cancelRouteParamAttach();
|
|
9696
|
+
});
|
|
9571
9697
|
}
|
|
9572
9698
|
return {
|
|
9573
|
-
|
|
9574
|
-
|
|
9699
|
+
attachments,
|
|
9700
|
+
setAttachments,
|
|
9701
|
+
catalogItems,
|
|
9702
|
+
refreshCatalog,
|
|
9703
|
+
ensureCatalogLoaded,
|
|
9704
|
+
panelOpen,
|
|
9705
|
+
openPanel,
|
|
9706
|
+
closePanel,
|
|
9707
|
+
chipRows,
|
|
9708
|
+
menuNavRows: menuNavRowsForView,
|
|
9709
|
+
selectedCategory,
|
|
9710
|
+
showAddMenuPanel,
|
|
9711
|
+
showAddMenuEmptyHint,
|
|
9712
|
+
showAddMenuChips,
|
|
9713
|
+
showAddMenuPopover: panelOpen,
|
|
9714
|
+
catalogLoading,
|
|
9715
|
+
catalogWarnings,
|
|
9716
|
+
paramCollisionWarning,
|
|
9717
|
+
routeParamHint,
|
|
9718
|
+
routeSegmentButtons: routeSegmentNames,
|
|
9719
|
+
routeParamRows,
|
|
9720
|
+
showRouteParamConfirm,
|
|
9721
|
+
pendingRouteParamTitle: createMemo(
|
|
9722
|
+
() => pendingRouteParamItem()?.title ?? ""
|
|
9723
|
+
),
|
|
9575
9724
|
scheduleManifestSync,
|
|
9576
9725
|
syncManifestNow: async () => {
|
|
9577
9726
|
const requestId = deps.getRequestId();
|
|
9578
9727
|
if (!requestId) return;
|
|
9579
|
-
|
|
9728
|
+
await syncAddMenuAttachments({
|
|
9580
9729
|
requestId,
|
|
9581
|
-
|
|
9730
|
+
addMenuAttachments: attachments(),
|
|
9731
|
+
routeMigration: routeMigration() ?? void 0
|
|
9582
9732
|
});
|
|
9583
|
-
if (res.ok && res.contentMd) deps.setContentMd(res.contentMd);
|
|
9584
9733
|
},
|
|
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
|
|
9734
|
+
tryAddItem,
|
|
9735
|
+
removeChip,
|
|
9736
|
+
bindAddMenuPanelRefs,
|
|
9737
|
+
resetAddMenuPanel,
|
|
9738
|
+
updateRouteHelpers,
|
|
9739
|
+
routeMigration,
|
|
9740
|
+
setRouteMigration
|
|
9603
9741
|
};
|
|
9604
9742
|
}
|
|
9605
9743
|
function tryJayRefExec(refObj, fn) {
|
|
@@ -9627,11 +9765,44 @@ function initAddPageComposer(deps) {
|
|
|
9627
9765
|
const [addPageShowDesignHint, setAddPageShowDesignHint] = createSignal(false);
|
|
9628
9766
|
const [addPageIsDynamicRoute, setAddPageIsDynamicRoute] = createSignal(false);
|
|
9629
9767
|
const [addPageSubmitting, setAddPageSubmitting] = createSignal(false);
|
|
9630
|
-
const
|
|
9768
|
+
const addMenuPanel = initAddMenuPanel({
|
|
9631
9769
|
projectPlugins: deps.projectPlugins,
|
|
9770
|
+
projectDir: deps.projectDir,
|
|
9632
9771
|
getRequestId: () => addPageRequestId(),
|
|
9633
|
-
|
|
9634
|
-
|
|
9772
|
+
preserveEditorContent: () => {
|
|
9773
|
+
const el = contentTextareaEl;
|
|
9774
|
+
if (el) setAddPageContentMd(el.value);
|
|
9775
|
+
},
|
|
9776
|
+
getPageRoute: () => addPageRoute(),
|
|
9777
|
+
setPageRoute: setAddPageRoute,
|
|
9778
|
+
insertAtCursor: (text) => {
|
|
9779
|
+
const current = contentTextareaEl?.value ?? addPageContentMd();
|
|
9780
|
+
const { next, cursor } = insertTextAtRange(
|
|
9781
|
+
current,
|
|
9782
|
+
text,
|
|
9783
|
+
contentTextareaEl?.selectionStart ?? contentSelectionStart,
|
|
9784
|
+
contentTextareaEl?.selectionEnd ?? contentSelectionEnd
|
|
9785
|
+
);
|
|
9786
|
+
setAddPageContentMd(next);
|
|
9787
|
+
contentSelectionStart = contentSelectionEnd = cursor;
|
|
9788
|
+
const el = contentTextareaEl;
|
|
9789
|
+
if (el) {
|
|
9790
|
+
queueMicrotask(() => {
|
|
9791
|
+
el.selectionStart = cursor;
|
|
9792
|
+
el.selectionEnd = cursor;
|
|
9793
|
+
el.focus();
|
|
9794
|
+
});
|
|
9795
|
+
}
|
|
9796
|
+
},
|
|
9797
|
+
insertRouteParam: (paramName) => {
|
|
9798
|
+
const next = insertRouteParamInField(
|
|
9799
|
+
routeInputEl,
|
|
9800
|
+
addPageRoute(),
|
|
9801
|
+
paramName
|
|
9802
|
+
);
|
|
9803
|
+
setAddPageRoute(next);
|
|
9804
|
+
scheduleRouteCheck(next);
|
|
9805
|
+
},
|
|
9635
9806
|
openProjectSettings: deps.openProjectSettings
|
|
9636
9807
|
});
|
|
9637
9808
|
const briefFillPanel = initAddPageBriefFillPanel({
|
|
@@ -9653,8 +9824,20 @@ function initAddPageComposer(deps) {
|
|
|
9653
9824
|
setComposerError: setAddPageComposerError
|
|
9654
9825
|
});
|
|
9655
9826
|
let routeCheckTimer;
|
|
9827
|
+
let routeInputEl = null;
|
|
9656
9828
|
let contentTextareaEl = null;
|
|
9829
|
+
let contentSelectionStart = 0;
|
|
9830
|
+
let contentSelectionEnd = 0;
|
|
9657
9831
|
let designTextareaEl = null;
|
|
9832
|
+
let designSelectionStart = 0;
|
|
9833
|
+
function trackTextareaSelection(el) {
|
|
9834
|
+
contentSelectionStart = el.selectionStart ?? 0;
|
|
9835
|
+
contentSelectionEnd = el.selectionEnd ?? contentSelectionStart;
|
|
9836
|
+
}
|
|
9837
|
+
function trackDesignTextareaSelection(el) {
|
|
9838
|
+
designSelectionStart = el.selectionStart ?? 0;
|
|
9839
|
+
el.selectionEnd ?? designSelectionStart;
|
|
9840
|
+
}
|
|
9658
9841
|
const showAddPageRouteError = createMemo(
|
|
9659
9842
|
() => addPageRouteError().length > 0
|
|
9660
9843
|
);
|
|
@@ -9683,7 +9866,7 @@ function initAddPageComposer(deps) {
|
|
|
9683
9866
|
if (deps.isRunning() || addPageSubmitting() || briefFillPanel.briefFillGenerating()) {
|
|
9684
9867
|
return false;
|
|
9685
9868
|
}
|
|
9686
|
-
if (
|
|
9869
|
+
if (deps.projectPlugins.installInProgress()) return false;
|
|
9687
9870
|
const route = addPageRoute().trim();
|
|
9688
9871
|
if (!route || addPageRouteError()) return false;
|
|
9689
9872
|
const hasMd = addPageContentMd().trim().length > 0 || addPageDesignMd().trim().length > 0;
|
|
@@ -9704,13 +9887,14 @@ function initAddPageComposer(deps) {
|
|
|
9704
9887
|
setAddPageAttachments([]);
|
|
9705
9888
|
setAddPageShowDesignHint(false);
|
|
9706
9889
|
setAddPageIsDynamicRoute(false);
|
|
9707
|
-
|
|
9890
|
+
addMenuPanel.resetAddMenuPanel();
|
|
9708
9891
|
briefFillPanel.resetBriefFill();
|
|
9709
9892
|
}
|
|
9710
9893
|
function openAddPageComposer() {
|
|
9711
9894
|
resetAddPageComposer();
|
|
9712
9895
|
setShowAddPageComposer(true);
|
|
9713
9896
|
void deps.projectPlugins.refreshPluginsList();
|
|
9897
|
+
void addMenuPanel.ensureCatalogLoaded();
|
|
9714
9898
|
}
|
|
9715
9899
|
async function refreshCurrentPageBriefAvailability() {
|
|
9716
9900
|
const filePath = deps.selectedPageFilePath().trim();
|
|
@@ -9985,7 +10169,7 @@ function initAddPageComposer(deps) {
|
|
|
9985
10169
|
deps.setIsRunning(true);
|
|
9986
10170
|
deps.setBottomPanelCollapsed(false);
|
|
9987
10171
|
deps.setAddPageResultBanner(null);
|
|
9988
|
-
await
|
|
10172
|
+
await addMenuPanel.syncManifestNow();
|
|
9989
10173
|
deps.getStopStream()?.();
|
|
9990
10174
|
const abort = submitAddPageStream(
|
|
9991
10175
|
{
|
|
@@ -10075,17 +10259,37 @@ function initAddPageComposer(deps) {
|
|
|
10075
10259
|
});
|
|
10076
10260
|
refs.addPageCreateBtn.onclick(() => submitAddPage(false));
|
|
10077
10261
|
refs.addPageRouteInput.oninput(({ event }) => {
|
|
10078
|
-
|
|
10262
|
+
routeInputEl = event.target;
|
|
10263
|
+
const v = routeInputEl.value;
|
|
10079
10264
|
setAddPageRoute(v);
|
|
10080
10265
|
scheduleRouteCheck(v);
|
|
10081
10266
|
});
|
|
10267
|
+
refs.addPageRouteInput.onfocus(({ event }) => {
|
|
10268
|
+
routeInputEl = event.target;
|
|
10269
|
+
});
|
|
10270
|
+
refs.addPageContentMd.onfocus(({ event }) => {
|
|
10271
|
+
contentTextareaEl = event.target;
|
|
10272
|
+
trackTextareaSelection(contentTextareaEl);
|
|
10273
|
+
});
|
|
10082
10274
|
refs.addPageContentMd.oninput(({ event }) => {
|
|
10083
10275
|
contentTextareaEl = event.target;
|
|
10276
|
+
trackTextareaSelection(contentTextareaEl);
|
|
10084
10277
|
setAddPageContentMd(contentTextareaEl.value);
|
|
10085
10278
|
updateDesignHint();
|
|
10086
10279
|
});
|
|
10280
|
+
refs.addPageContentMd.addEventListener(
|
|
10281
|
+
"select",
|
|
10282
|
+
(ev) => {
|
|
10283
|
+
trackTextareaSelection(ev.event.target);
|
|
10284
|
+
}
|
|
10285
|
+
);
|
|
10286
|
+
refs.addPageDesignMd.onfocus(({ event }) => {
|
|
10287
|
+
designTextareaEl = event.target;
|
|
10288
|
+
trackDesignTextareaSelection(designTextareaEl);
|
|
10289
|
+
});
|
|
10087
10290
|
refs.addPageDesignMd.oninput(({ event }) => {
|
|
10088
10291
|
designTextareaEl = event.target;
|
|
10292
|
+
trackDesignTextareaSelection(designTextareaEl);
|
|
10089
10293
|
setAddPageDesignMd(designTextareaEl.value);
|
|
10090
10294
|
updateDesignHint();
|
|
10091
10295
|
});
|
|
@@ -10146,7 +10350,7 @@ function initAddPageComposer(deps) {
|
|
|
10146
10350
|
el.click();
|
|
10147
10351
|
});
|
|
10148
10352
|
});
|
|
10149
|
-
|
|
10353
|
+
addMenuPanel.bindAddMenuPanelRefs(refs);
|
|
10150
10354
|
briefFillPanel.bindBriefFillRefs(refs);
|
|
10151
10355
|
refs.addPageAttachmentsList.onchange(
|
|
10152
10356
|
({ event }) => {
|
|
@@ -10199,18 +10403,21 @@ function initAddPageComposer(deps) {
|
|
|
10199
10403
|
addPageUploadHint,
|
|
10200
10404
|
addPageAttachmentRows: addPageAttachmentDisplayRows,
|
|
10201
10405
|
addPageShowDesignHint,
|
|
10202
|
-
|
|
10203
|
-
|
|
10204
|
-
|
|
10205
|
-
|
|
10206
|
-
|
|
10207
|
-
|
|
10208
|
-
|
|
10209
|
-
|
|
10210
|
-
|
|
10211
|
-
|
|
10406
|
+
showAddMenuPanel: addMenuPanel.showAddMenuPanel,
|
|
10407
|
+
showAddMenuChips: addMenuPanel.showAddMenuChips,
|
|
10408
|
+
addMenuChipRows: addMenuPanel.chipRows,
|
|
10409
|
+
showAddMenuEmptyHint: addMenuPanel.showAddMenuEmptyHint,
|
|
10410
|
+
showAddMenuPopover: addMenuPanel.showAddMenuPopover,
|
|
10411
|
+
addMenuNavRows: addMenuPanel.menuNavRows,
|
|
10412
|
+
addMenuSelectedCategory: addMenuPanel.selectedCategory,
|
|
10413
|
+
addMenuParamCollisionWarning: addMenuPanel.paramCollisionWarning,
|
|
10414
|
+
addMenuRouteParamHint: addMenuPanel.routeParamHint,
|
|
10415
|
+
addMenuRouteParamRows: addMenuPanel.routeParamRows,
|
|
10416
|
+
showAddMenuRouteParams: createMemo(
|
|
10417
|
+
() => addMenuPanel.routeParamRows().length > 0
|
|
10212
10418
|
),
|
|
10213
|
-
|
|
10419
|
+
showAddMenuRouteParamConfirm: addMenuPanel.showRouteParamConfirm,
|
|
10420
|
+
addMenuPendingRouteParamTitle: addMenuPanel.pendingRouteParamTitle,
|
|
10214
10421
|
addPageIsDynamicRoute,
|
|
10215
10422
|
addPageCreateDisabled,
|
|
10216
10423
|
showAddPageRouteError,
|
|
@@ -10240,102 +10447,556 @@ function initAddPageComposer(deps) {
|
|
|
10240
10447
|
submitAddPage,
|
|
10241
10448
|
retryAddPage,
|
|
10242
10449
|
openPreviewForRoute,
|
|
10243
|
-
bindAddPageRefs
|
|
10450
|
+
bindAddPageRefs,
|
|
10451
|
+
refreshAddMenuCatalog: () => addMenuPanel.refreshCatalog()
|
|
10244
10452
|
};
|
|
10245
10453
|
}
|
|
10246
|
-
function
|
|
10247
|
-
|
|
10248
|
-
|
|
10249
|
-
|
|
10454
|
+
function markerAddMenuAttachments(annotation) {
|
|
10455
|
+
return (annotation.addMenuAttachments ?? []).filter(
|
|
10456
|
+
(a2) => a2.annotationId === annotation.id || a2.annotationId === void 0
|
|
10457
|
+
);
|
|
10458
|
+
}
|
|
10459
|
+
function enrichAnnotationAddMenuUi(annotation, itemById, pickerOpenForAnnotation, selectedCategory) {
|
|
10460
|
+
const attachments = markerAddMenuAttachments(annotation);
|
|
10461
|
+
const open = !!annotation.addMenuSectionOpen;
|
|
10462
|
+
const pickerOpen = pickerOpenForAnnotation && open;
|
|
10463
|
+
return {
|
|
10464
|
+
addMenuSectionOpen: open,
|
|
10465
|
+
showAddMenuControls: open,
|
|
10466
|
+
showMarkerAddMenuChips: attachments.length > 0,
|
|
10467
|
+
showMarkerAddMenuEmptyHint: attachments.length === 0,
|
|
10468
|
+
markerAddMenuChips: attachments.map((a2) => {
|
|
10469
|
+
const item = itemById.get(a2.itemId);
|
|
10470
|
+
return {
|
|
10471
|
+
rowKey: `${a2.itemId}:${annotation.id}`,
|
|
10472
|
+
itemId: a2.itemId,
|
|
10473
|
+
title: item?.title ?? a2.itemId,
|
|
10474
|
+
subtitle: item?.pluginName ?? item?.id.split(":")[0] ?? ""
|
|
10475
|
+
};
|
|
10476
|
+
}),
|
|
10477
|
+
addMenuSelectedCategory: selectedCategory,
|
|
10478
|
+
showAddMenuItemPicker: pickerOpen,
|
|
10479
|
+
markerPickerNavRows: [],
|
|
10480
|
+
showMarkerPickerLoading: false,
|
|
10481
|
+
showMarkerPickerCatalogEmpty: false,
|
|
10482
|
+
crAddMenuParamCollisionWarning: "",
|
|
10483
|
+
crAddMenuRouteParamHint: "",
|
|
10484
|
+
showCrAddMenuRouteParams: false,
|
|
10485
|
+
crAddMenuRouteParamRows: [],
|
|
10486
|
+
showCrRouteParamConfirm: false,
|
|
10487
|
+
crPendingRouteParamTitle: "",
|
|
10488
|
+
showCrPlannedRoutePanel: false,
|
|
10489
|
+
crPlannedRoute: ""
|
|
10490
|
+
};
|
|
10491
|
+
}
|
|
10492
|
+
function addMenuItemToAnnotation(prev, annotationId, itemId) {
|
|
10493
|
+
return dedupeAddMenuAttachment(prev ?? [], {
|
|
10494
|
+
itemId,
|
|
10495
|
+
annotationId
|
|
10496
|
+
});
|
|
10250
10497
|
}
|
|
10251
|
-
function
|
|
10252
|
-
|
|
10253
|
-
return `${binding.pluginName} · ${binding.contractName} · ${where}`;
|
|
10498
|
+
function removeMenuItemFromAnnotation(prev, annotationId, itemId) {
|
|
10499
|
+
return removeAddMenuAttachment(prev ?? [], itemId, annotationId);
|
|
10254
10500
|
}
|
|
10255
|
-
function
|
|
10256
|
-
const
|
|
10257
|
-
|
|
10501
|
+
function initVisualAddMenuController(deps) {
|
|
10502
|
+
const [catalogItems, setCatalogItems] = createSignal([]);
|
|
10503
|
+
const [catalogCategories, setCatalogCategories] = createSignal([]);
|
|
10504
|
+
const [catalogLoading, setCatalogLoading] = createSignal(false);
|
|
10505
|
+
const [catalogLoaded, setCatalogLoaded] = createSignal(false);
|
|
10506
|
+
let catalogRefreshPromise = null;
|
|
10507
|
+
const [pickerAnnotationId, setPickerAnnotationId] = createSignal(void 0);
|
|
10508
|
+
const [pickerCategory, setPickerCategory] = createSignal("");
|
|
10509
|
+
const [pickerSubCategory, setPickerSubCategory] = createSignal(
|
|
10510
|
+
null
|
|
10511
|
+
);
|
|
10512
|
+
const [requestAttachments, setRequestAttachments] = createSignal([]);
|
|
10513
|
+
const [routeMigration, setRouteMigration] = createSignal(null);
|
|
10514
|
+
const [plannedRoute, setPlannedRoute] = createSignal("");
|
|
10515
|
+
const [paramCollisionWarning, setParamCollisionWarning] = createSignal("");
|
|
10516
|
+
const [routeParamHint, setRouteParamHint] = createSignal("");
|
|
10517
|
+
const [routeSegmentNames, setRouteSegmentNames] = createSignal([]);
|
|
10518
|
+
const [pendingRouteParamItem, setPendingRouteParamItem] = createSignal(null);
|
|
10519
|
+
const [pendingRouteParamAnnotationId, setPendingRouteParamAnnotationId] = createSignal(null);
|
|
10520
|
+
const [showRouteParamConfirm, setShowRouteParamConfirm] = createSignal(false);
|
|
10521
|
+
const itemById = createMemo(() => {
|
|
10522
|
+
const map = /* @__PURE__ */ new Map();
|
|
10523
|
+
for (const item of catalogItems()) map.set(item.id, item);
|
|
10524
|
+
return map;
|
|
10525
|
+
});
|
|
10526
|
+
const pickerPanelOpen = createMemo(() => pickerAnnotationId() !== void 0);
|
|
10527
|
+
const pickerNavRows = createMemo(
|
|
10528
|
+
() => buildAddMenuNavRows(
|
|
10529
|
+
catalogCategories(),
|
|
10530
|
+
pickerPanelOpen(),
|
|
10531
|
+
pickerCategory(),
|
|
10532
|
+
pickerSubCategory()
|
|
10533
|
+
)
|
|
10534
|
+
);
|
|
10535
|
+
const markerPickerNavRowsForView = createMemo(
|
|
10536
|
+
() => pickerNavRows().map(stripMarkerAddMenuNavRowForPage)
|
|
10537
|
+
);
|
|
10538
|
+
const markerPickerNavRowsForVideo = markerPickerNavRowsForView;
|
|
10539
|
+
const markerPickerNavRowsForSnapshot = markerPickerNavRowsForView;
|
|
10540
|
+
const showMarkerPickerCatalogEmpty = createMemo(() => {
|
|
10541
|
+
const id = pickerAnnotationId();
|
|
10542
|
+
if (id === void 0 || id === null) return false;
|
|
10543
|
+
return !catalogLoading() && catalogItems().length === 0;
|
|
10544
|
+
});
|
|
10545
|
+
const showMarkerPickerLoading = createMemo(() => {
|
|
10546
|
+
const id = pickerAnnotationId();
|
|
10547
|
+
if (id === void 0 || id === null) return false;
|
|
10548
|
+
return catalogLoading();
|
|
10549
|
+
});
|
|
10550
|
+
const markerPickerSnapshot = createMemo(() => ({
|
|
10551
|
+
pickerId: pickerAnnotationId(),
|
|
10552
|
+
category: pickerCategory(),
|
|
10553
|
+
subCategory: pickerSubCategory(),
|
|
10554
|
+
navVisual: markerPickerNavRowsForView(),
|
|
10555
|
+
navVideo: markerPickerNavRowsForVideo(),
|
|
10556
|
+
navSnapshot: markerPickerNavRowsForSnapshot(),
|
|
10557
|
+
loading: showMarkerPickerLoading(),
|
|
10558
|
+
empty: showMarkerPickerCatalogEmpty()
|
|
10559
|
+
}));
|
|
10560
|
+
createMemo(
|
|
10561
|
+
() => requestAttachments().map((a2) => {
|
|
10562
|
+
const item = itemById().get(a2.itemId);
|
|
10563
|
+
return {
|
|
10564
|
+
rowKey: `req:${a2.itemId}`,
|
|
10565
|
+
itemId: a2.itemId,
|
|
10566
|
+
title: item?.title ?? a2.itemId,
|
|
10567
|
+
subtitle: item?.pluginName ?? item?.id.split(":")[0] ?? ""
|
|
10568
|
+
};
|
|
10569
|
+
})
|
|
10570
|
+
);
|
|
10571
|
+
const routeParamRows = createMemo(
|
|
10572
|
+
() => routeSegmentNames().map((name) => ({ rowKey: name, name }))
|
|
10573
|
+
);
|
|
10574
|
+
async function refreshCatalog() {
|
|
10575
|
+
if (catalogRefreshPromise) return catalogRefreshPromise;
|
|
10576
|
+
catalogRefreshPromise = (async () => {
|
|
10577
|
+
setCatalogLoading(true);
|
|
10578
|
+
try {
|
|
10579
|
+
const result = await listAddMenuItems();
|
|
10580
|
+
setCatalogItems(result.items);
|
|
10581
|
+
setCatalogCategories(result.categories);
|
|
10582
|
+
if (result.warnings.length > 0) {
|
|
10583
|
+
console.warn("[aiditor] Add Menu catalog warnings:", result.warnings);
|
|
10584
|
+
}
|
|
10585
|
+
} catch (err) {
|
|
10586
|
+
console.error("[aiditor] listAddMenuItems failed:", err);
|
|
10587
|
+
setCatalogItems([]);
|
|
10588
|
+
setCatalogCategories([]);
|
|
10589
|
+
} finally {
|
|
10590
|
+
setCatalogLoaded(true);
|
|
10591
|
+
setCatalogLoading(false);
|
|
10592
|
+
catalogRefreshPromise = null;
|
|
10593
|
+
}
|
|
10594
|
+
})();
|
|
10595
|
+
return catalogRefreshPromise;
|
|
10596
|
+
}
|
|
10597
|
+
async function ensureCatalogLoaded() {
|
|
10598
|
+
if (catalogLoading()) return;
|
|
10599
|
+
if (catalogLoaded() && catalogCategories().length > 0) return;
|
|
10600
|
+
await refreshCatalog();
|
|
10601
|
+
}
|
|
10602
|
+
async function updateRouteHelpers(attachments) {
|
|
10603
|
+
const resolved = [];
|
|
10604
|
+
for (const a2 of attachments) {
|
|
10605
|
+
const item = itemById().get(a2.itemId);
|
|
10606
|
+
if (!item) continue;
|
|
10607
|
+
const params = await resolveContractParamsForItem(
|
|
10608
|
+
deps.projectDir(),
|
|
10609
|
+
item
|
|
10610
|
+
);
|
|
10611
|
+
if (params) resolved.push(params);
|
|
10612
|
+
}
|
|
10613
|
+
const collisions = detectRequiredParamCollisions(resolved);
|
|
10614
|
+
setParamCollisionWarning(collisions[0]?.message ?? "");
|
|
10615
|
+
const segments = collectRouteSegmentNames(resolved);
|
|
10616
|
+
setRouteSegmentNames(segments);
|
|
10617
|
+
const route = plannedRoute() || deps.getCurrentRoute();
|
|
10618
|
+
const suggested = suggestMissingRouteSegments(route, segments);
|
|
10619
|
+
setRouteParamHint(
|
|
10620
|
+
suggested && suggested !== route ? `Suggested route segments: ${suggested}` : ""
|
|
10621
|
+
);
|
|
10622
|
+
}
|
|
10623
|
+
async function openPicker(annotationId) {
|
|
10624
|
+
setPickerAnnotationId(annotationId);
|
|
10625
|
+
setPickerCategory("");
|
|
10626
|
+
setPickerSubCategory(null);
|
|
10627
|
+
await ensureCatalogLoaded();
|
|
10628
|
+
if (catalogCategories().length === 0 && !catalogLoading()) {
|
|
10629
|
+
await refreshCatalog();
|
|
10630
|
+
}
|
|
10631
|
+
}
|
|
10632
|
+
function closePicker() {
|
|
10633
|
+
setPickerAnnotationId(void 0);
|
|
10634
|
+
setPickerCategory("");
|
|
10635
|
+
setPickerSubCategory(null);
|
|
10636
|
+
}
|
|
10637
|
+
async function commitItem(item, updateAnnotation, annotationId) {
|
|
10638
|
+
if (annotationId) {
|
|
10639
|
+
updateAnnotation(annotationId, (a2) => ({
|
|
10640
|
+
...a2,
|
|
10641
|
+
addMenuSectionOpen: true,
|
|
10642
|
+
pickerOpen: false,
|
|
10643
|
+
addMenuAttachments: addMenuItemToAnnotation(
|
|
10644
|
+
a2.addMenuAttachments,
|
|
10645
|
+
annotationId,
|
|
10646
|
+
item.id
|
|
10647
|
+
)
|
|
10648
|
+
}));
|
|
10649
|
+
} else {
|
|
10650
|
+
setRequestAttachments((prev) => {
|
|
10651
|
+
const exists = prev.some(
|
|
10652
|
+
(a2) => a2.itemId === item.id && !a2.annotationId
|
|
10653
|
+
);
|
|
10654
|
+
if (exists) return prev;
|
|
10655
|
+
return [...prev, { itemId: item.id }];
|
|
10656
|
+
});
|
|
10657
|
+
closePicker();
|
|
10658
|
+
}
|
|
10659
|
+
const all = [
|
|
10660
|
+
...requestAttachments(),
|
|
10661
|
+
...annotationId ? [{ itemId: item.id, annotationId }] : [{ itemId: item.id }]
|
|
10662
|
+
];
|
|
10663
|
+
await updateRouteHelpers(all);
|
|
10664
|
+
}
|
|
10665
|
+
async function tryPickItem(item, updateAnnotation, annotationId) {
|
|
10666
|
+
const params = await resolveContractParamsForItem(deps.projectDir(), item);
|
|
10667
|
+
const hasRouteParams = !!params && params.allParams.length > 0;
|
|
10668
|
+
const current = deps.getCurrentRoute();
|
|
10669
|
+
if (hasRouteParams && current && !routeHasAnyDynamicSegment(current)) {
|
|
10670
|
+
setPendingRouteParamItem(item);
|
|
10671
|
+
setPendingRouteParamAnnotationId(annotationId);
|
|
10672
|
+
setShowRouteParamConfirm(true);
|
|
10673
|
+
return;
|
|
10674
|
+
}
|
|
10675
|
+
await commitItem(item, updateAnnotation, annotationId);
|
|
10676
|
+
}
|
|
10677
|
+
async function confirmRouteParamPick(updateAnnotation) {
|
|
10678
|
+
const item = pendingRouteParamItem();
|
|
10679
|
+
if (!item) return;
|
|
10680
|
+
const current = deps.getCurrentRoute() || "/";
|
|
10681
|
+
const params = await resolveContractParamsForItem(deps.projectDir(), item);
|
|
10682
|
+
const segments = params ? collectRouteSegmentNames([params]) : [];
|
|
10683
|
+
const planned = suggestMissingRouteSegments(current, segments) ?? `${current}/[slug]`;
|
|
10684
|
+
setPlannedRoute(planned);
|
|
10685
|
+
setRouteMigration({
|
|
10686
|
+
currentRoute: current,
|
|
10687
|
+
plannedRoute: planned,
|
|
10688
|
+
reason: "add-menu-route-param-component",
|
|
10689
|
+
triggeringItemIds: [item.id]
|
|
10690
|
+
});
|
|
10691
|
+
setShowRouteParamConfirm(false);
|
|
10692
|
+
setPendingRouteParamItem(null);
|
|
10693
|
+
const aid = pendingRouteParamAnnotationId();
|
|
10694
|
+
setPendingRouteParamAnnotationId(null);
|
|
10695
|
+
await commitItem(item, updateAnnotation, aid);
|
|
10696
|
+
}
|
|
10697
|
+
function cancelRouteParamPick() {
|
|
10698
|
+
setShowRouteParamConfirm(false);
|
|
10699
|
+
setPendingRouteParamItem(null);
|
|
10700
|
+
setPendingRouteParamAnnotationId(null);
|
|
10701
|
+
}
|
|
10702
|
+
function enrichUi(annotation, _stripMarkerRow) {
|
|
10703
|
+
const pickerOpen = !!annotation.pickerOpen;
|
|
10704
|
+
const cat = annotation.selectedCategory ?? "";
|
|
10705
|
+
const sub = annotation.selectedSubCategory ?? null;
|
|
10706
|
+
const base = enrichAnnotationAddMenuUi(
|
|
10707
|
+
annotation,
|
|
10708
|
+
itemById(),
|
|
10709
|
+
pickerOpen,
|
|
10710
|
+
cat
|
|
10711
|
+
);
|
|
10712
|
+
const navRows = buildAddMenuNavRows(
|
|
10713
|
+
catalogCategories(),
|
|
10714
|
+
pickerOpen,
|
|
10715
|
+
cat,
|
|
10716
|
+
sub
|
|
10717
|
+
).map(_stripMarkerRow);
|
|
10718
|
+
const hasAttachments = !!annotation.addMenuAttachments && annotation.addMenuAttachments.length > 0;
|
|
10719
|
+
const isPendingRoute = pendingRouteParamAnnotationId() === annotation.id;
|
|
10720
|
+
const showRouteUi = isPendingRoute || hasAttachments && routeMigration() !== null;
|
|
10721
|
+
const showParamsUi = isPendingRoute || hasAttachments && routeParamRows().length > 0;
|
|
10722
|
+
const showConfirm = isPendingRoute && showRouteParamConfirm();
|
|
10723
|
+
return {
|
|
10724
|
+
...base,
|
|
10725
|
+
showAddMenuItemPicker: pickerOpen,
|
|
10726
|
+
markerPickerNavRows: navRows,
|
|
10727
|
+
showMarkerPickerLoading: pickerOpen && catalogLoading(),
|
|
10728
|
+
showMarkerPickerCatalogEmpty: pickerOpen && !catalogLoading() && catalogItems().length === 0,
|
|
10729
|
+
crAddMenuParamCollisionWarning: showParamsUi ? paramCollisionWarning() : "",
|
|
10730
|
+
crAddMenuRouteParamHint: showParamsUi ? routeParamHint() : "",
|
|
10731
|
+
showCrAddMenuRouteParams: showParamsUi && routeParamRows().length > 0,
|
|
10732
|
+
crAddMenuRouteParamRows: showParamsUi ? routeParamRows() : [],
|
|
10733
|
+
showCrRouteParamConfirm: showConfirm,
|
|
10734
|
+
crPendingRouteParamTitle: isPendingRoute && pendingRouteParamItem() ? pendingRouteParamItem().title : "",
|
|
10735
|
+
showCrPlannedRoutePanel: showRouteUi,
|
|
10736
|
+
crPlannedRoute: showRouteUi ? plannedRoute() : ""
|
|
10737
|
+
};
|
|
10738
|
+
}
|
|
10739
|
+
function handleMarkerAddMenuClick(target, annotationId, updateAnnotation) {
|
|
10740
|
+
if (target.classList.contains("annotation-add-menu-toggle")) {
|
|
10741
|
+
updateAnnotation(annotationId, (a2) => ({
|
|
10742
|
+
...a2,
|
|
10743
|
+
addMenuSectionOpen: !a2.addMenuSectionOpen
|
|
10744
|
+
}));
|
|
10745
|
+
return true;
|
|
10746
|
+
}
|
|
10747
|
+
if (target.closest("[data-marker-add-menu-open]")) {
|
|
10748
|
+
updateAnnotation(annotationId, (a2) => ({
|
|
10749
|
+
...a2,
|
|
10750
|
+
addMenuSectionOpen: true,
|
|
10751
|
+
pickerOpen: true,
|
|
10752
|
+
selectedCategory: "",
|
|
10753
|
+
selectedSubCategory: null
|
|
10754
|
+
}));
|
|
10755
|
+
void ensureCatalogLoaded();
|
|
10756
|
+
return true;
|
|
10757
|
+
}
|
|
10758
|
+
if (target.closest("[data-marker-add-menu-close]")) {
|
|
10759
|
+
updateAnnotation(annotationId, (a2) => ({
|
|
10760
|
+
...a2,
|
|
10761
|
+
pickerOpen: false
|
|
10762
|
+
}));
|
|
10763
|
+
return true;
|
|
10764
|
+
}
|
|
10765
|
+
if (target.closest("[data-marker-add-menu-manage]")) {
|
|
10766
|
+
deps.openProjectSettings();
|
|
10767
|
+
return true;
|
|
10768
|
+
}
|
|
10769
|
+
const catBtn = target.closest(
|
|
10770
|
+
"[data-marker-add-menu-category]"
|
|
10771
|
+
);
|
|
10772
|
+
if (catBtn?.dataset.category) {
|
|
10773
|
+
updateAnnotation(annotationId, (a2) => ({
|
|
10774
|
+
...a2,
|
|
10775
|
+
selectedCategory: catBtn.dataset.category,
|
|
10776
|
+
selectedSubCategory: null
|
|
10777
|
+
}));
|
|
10778
|
+
return true;
|
|
10779
|
+
}
|
|
10780
|
+
const subBtn = target.closest(
|
|
10781
|
+
"[data-marker-add-menu-subcategory]"
|
|
10782
|
+
);
|
|
10783
|
+
if (subBtn?.dataset.subcategory !== void 0) {
|
|
10784
|
+
updateAnnotation(annotationId, (a2) => ({
|
|
10785
|
+
...a2,
|
|
10786
|
+
selectedSubCategory: subBtn.dataset.subcategory || null
|
|
10787
|
+
}));
|
|
10788
|
+
return true;
|
|
10789
|
+
}
|
|
10790
|
+
const pickBtn = target.closest(
|
|
10791
|
+
"[data-marker-add-menu-pick]"
|
|
10792
|
+
);
|
|
10793
|
+
if (pickBtn?.dataset.itemId) {
|
|
10794
|
+
const item = itemById().get(pickBtn.dataset.itemId);
|
|
10795
|
+
if (item) void tryPickItem(item, updateAnnotation, annotationId);
|
|
10796
|
+
return true;
|
|
10797
|
+
}
|
|
10798
|
+
const removeBtn = target.closest(
|
|
10799
|
+
"[data-marker-add-menu-remove]"
|
|
10800
|
+
);
|
|
10801
|
+
if (removeBtn?.dataset.itemId) {
|
|
10802
|
+
updateAnnotation(annotationId, (a2) => ({
|
|
10803
|
+
...a2,
|
|
10804
|
+
addMenuAttachments: removeMenuItemFromAnnotation(
|
|
10805
|
+
a2.addMenuAttachments,
|
|
10806
|
+
annotationId,
|
|
10807
|
+
removeBtn.dataset.itemId
|
|
10808
|
+
)
|
|
10809
|
+
}));
|
|
10810
|
+
return true;
|
|
10811
|
+
}
|
|
10812
|
+
return false;
|
|
10813
|
+
}
|
|
10814
|
+
function handleRequestAddMenuClick(target, updateAnnotation) {
|
|
10815
|
+
if (target.closest("[data-cr-add-menu-open]")) {
|
|
10816
|
+
void openPicker(null);
|
|
10817
|
+
return;
|
|
10818
|
+
}
|
|
10819
|
+
if (target.closest("[data-cr-add-menu-close]")) {
|
|
10820
|
+
closePicker();
|
|
10821
|
+
return;
|
|
10822
|
+
}
|
|
10823
|
+
if (target.closest("[data-cr-add-menu-manage]")) {
|
|
10824
|
+
deps.openProjectSettings();
|
|
10825
|
+
return;
|
|
10826
|
+
}
|
|
10827
|
+
const catBtn = target.closest(
|
|
10828
|
+
"[data-cr-add-menu-category]"
|
|
10829
|
+
);
|
|
10830
|
+
if (catBtn?.dataset.category) {
|
|
10831
|
+
setPickerCategory(catBtn.dataset.category);
|
|
10832
|
+
setPickerSubCategory(null);
|
|
10833
|
+
return;
|
|
10834
|
+
}
|
|
10835
|
+
const subBtn = target.closest(
|
|
10836
|
+
"[data-cr-add-menu-subcategory]"
|
|
10837
|
+
);
|
|
10838
|
+
if (subBtn?.dataset.subcategory !== void 0) {
|
|
10839
|
+
setPickerSubCategory(subBtn.dataset.subcategory || null);
|
|
10840
|
+
return;
|
|
10841
|
+
}
|
|
10842
|
+
const pickBtn = target.closest(
|
|
10843
|
+
"[data-cr-add-menu-pick]"
|
|
10844
|
+
);
|
|
10845
|
+
if (pickBtn?.dataset.itemId) {
|
|
10846
|
+
const item = itemById().get(pickBtn.dataset.itemId);
|
|
10847
|
+
if (item) void tryPickItem(item, updateAnnotation, null);
|
|
10848
|
+
return;
|
|
10849
|
+
}
|
|
10850
|
+
const removeBtn = target.closest(
|
|
10851
|
+
"[data-cr-add-menu-remove]"
|
|
10852
|
+
);
|
|
10853
|
+
if (removeBtn?.dataset.itemId) {
|
|
10854
|
+
setRequestAttachments(
|
|
10855
|
+
(prev) => prev.filter((a2) => a2.itemId !== removeBtn.dataset.itemId)
|
|
10856
|
+
);
|
|
10857
|
+
return;
|
|
10858
|
+
}
|
|
10859
|
+
if (target.closest("[data-cr-route-param-confirm]")) {
|
|
10860
|
+
void confirmRouteParamPick(updateAnnotation);
|
|
10861
|
+
return;
|
|
10862
|
+
}
|
|
10863
|
+
if (target.closest("[data-cr-route-param-cancel]")) {
|
|
10864
|
+
setShowRouteParamConfirm(false);
|
|
10865
|
+
setPendingRouteParamItem(null);
|
|
10866
|
+
}
|
|
10867
|
+
}
|
|
10868
|
+
const showRequestAddMenuPicker = createMemo(
|
|
10869
|
+
() => pickerAnnotationId() === null
|
|
10258
10870
|
);
|
|
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
|
|
10871
|
+
createMemo(
|
|
10872
|
+
() => showRequestAddMenuPicker() && catalogLoading()
|
|
10291
10873
|
);
|
|
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)
|
|
10874
|
+
createMemo(
|
|
10875
|
+
() => showRequestAddMenuPicker() && !catalogLoading() && catalogItems().length === 0
|
|
10300
10876
|
);
|
|
10301
|
-
}
|
|
10302
|
-
function enrichAnnotationBindingUi(annotation, plugins) {
|
|
10303
|
-
const bindings = annotationPluginBindings(annotation);
|
|
10304
|
-
const pickerPlugin = annotation.bindingPickerPlugin ?? "";
|
|
10305
|
-
const open = !!annotation.bindingSectionOpen;
|
|
10306
10877
|
return {
|
|
10307
|
-
|
|
10308
|
-
|
|
10309
|
-
|
|
10310
|
-
|
|
10311
|
-
|
|
10312
|
-
|
|
10313
|
-
|
|
10314
|
-
|
|
10315
|
-
|
|
10316
|
-
|
|
10317
|
-
|
|
10318
|
-
|
|
10319
|
-
|
|
10320
|
-
|
|
10321
|
-
|
|
10322
|
-
|
|
10323
|
-
|
|
10878
|
+
refreshCatalog,
|
|
10879
|
+
enrichUi,
|
|
10880
|
+
markerPickerSnapshot,
|
|
10881
|
+
handleMarkerAddMenuClick,
|
|
10882
|
+
handleRequestAddMenuClick,
|
|
10883
|
+
requestAttachments,
|
|
10884
|
+
routeMigration,
|
|
10885
|
+
plannedRoute,
|
|
10886
|
+
setPlannedRoute,
|
|
10887
|
+
catalogLoading,
|
|
10888
|
+
markerPickerNavRowsForView,
|
|
10889
|
+
markerPickerNavRowsForVideo,
|
|
10890
|
+
markerPickerNavRowsForSnapshot,
|
|
10891
|
+
markerPickerSelectedCategory: pickerCategory,
|
|
10892
|
+
showMarkerPickerLoading,
|
|
10893
|
+
showMarkerPickerCatalogEmpty,
|
|
10894
|
+
paramCollisionWarning,
|
|
10895
|
+
routeParamHint,
|
|
10896
|
+
routeParamRows,
|
|
10897
|
+
showRouteParams: createMemo(() => routeParamRows().length > 0),
|
|
10898
|
+
showRouteParamConfirm,
|
|
10899
|
+
pendingRouteParamTitle: createMemo(
|
|
10900
|
+
() => pendingRouteParamItem()?.title ?? ""
|
|
10324
10901
|
),
|
|
10325
|
-
|
|
10326
|
-
|
|
10902
|
+
confirmRouteParamPick,
|
|
10903
|
+
cancelRouteParamPick,
|
|
10904
|
+
reset: () => {
|
|
10905
|
+
setRequestAttachments([]);
|
|
10906
|
+
setRouteMigration(null);
|
|
10907
|
+
setPlannedRoute("");
|
|
10908
|
+
closePicker();
|
|
10909
|
+
}
|
|
10327
10910
|
};
|
|
10328
10911
|
}
|
|
10329
|
-
|
|
10330
|
-
|
|
10331
|
-
|
|
10332
|
-
|
|
10333
|
-
|
|
10334
|
-
|
|
10335
|
-
|
|
10336
|
-
|
|
10337
|
-
|
|
10338
|
-
}
|
|
10912
|
+
const CATALOG = [
|
|
10913
|
+
{
|
|
10914
|
+
pluginName: "wix-server-client",
|
|
10915
|
+
packageName: "@jay-framework/wix-server-client",
|
|
10916
|
+
description: "Wix API client and authentication",
|
|
10917
|
+
kind: "service-only",
|
|
10918
|
+
requires: [],
|
|
10919
|
+
showInAddPagePicker: false,
|
|
10920
|
+
configFiles: ["config/.wix.yaml"]
|
|
10921
|
+
},
|
|
10922
|
+
{
|
|
10923
|
+
pluginName: "wix-cart",
|
|
10924
|
+
packageName: "@jay-framework/wix-cart",
|
|
10925
|
+
description: "Shopping cart headless components",
|
|
10926
|
+
kind: "headless",
|
|
10927
|
+
requires: ["wix-server-client"],
|
|
10928
|
+
showInAddPagePicker: true
|
|
10929
|
+
},
|
|
10930
|
+
{
|
|
10931
|
+
pluginName: "wix-stores",
|
|
10932
|
+
packageName: "@jay-framework/wix-stores",
|
|
10933
|
+
description: "Wix Stores product search, product page, categories",
|
|
10934
|
+
kind: "headless",
|
|
10935
|
+
requires: ["wix-server-client", "wix-cart"],
|
|
10936
|
+
showInAddPagePicker: true,
|
|
10937
|
+
configFiles: ["config/.wix-stores.yaml"]
|
|
10938
|
+
},
|
|
10939
|
+
{
|
|
10940
|
+
pluginName: "wix-stores-v1",
|
|
10941
|
+
packageName: "@jay-framework/wix-stores-v1",
|
|
10942
|
+
description: "Wix Stores v1 catalog API",
|
|
10943
|
+
kind: "headless",
|
|
10944
|
+
requires: ["wix-server-client", "wix-cart"],
|
|
10945
|
+
showInAddPagePicker: true
|
|
10946
|
+
},
|
|
10947
|
+
{
|
|
10948
|
+
pluginName: "wix-data",
|
|
10949
|
+
packageName: "@jay-framework/wix-data",
|
|
10950
|
+
description: "Wix Data collections CMS",
|
|
10951
|
+
kind: "headless",
|
|
10952
|
+
requires: ["wix-server-client"],
|
|
10953
|
+
showInAddPagePicker: true,
|
|
10954
|
+
configFiles: ["config/.wix-data.yaml"]
|
|
10955
|
+
},
|
|
10956
|
+
{
|
|
10957
|
+
pluginName: "wix-media",
|
|
10958
|
+
packageName: "@jay-framework/wix-media",
|
|
10959
|
+
description: "Wix media service (no page components)",
|
|
10960
|
+
kind: "service-only",
|
|
10961
|
+
requires: ["wix-server-client"],
|
|
10962
|
+
showInAddPagePicker: true
|
|
10963
|
+
},
|
|
10964
|
+
{
|
|
10965
|
+
pluginName: "ui-kit",
|
|
10966
|
+
packageName: "@jay-framework/ui-kit",
|
|
10967
|
+
description: "Jay UI kit headless components",
|
|
10968
|
+
kind: "headless",
|
|
10969
|
+
requires: [],
|
|
10970
|
+
showInAddPagePicker: true
|
|
10971
|
+
},
|
|
10972
|
+
{
|
|
10973
|
+
pluginName: "gemini-agent",
|
|
10974
|
+
packageName: "@jay-framework/gemini-agent",
|
|
10975
|
+
description: "Gemini AI agent plugin",
|
|
10976
|
+
kind: "headless",
|
|
10977
|
+
requires: [],
|
|
10978
|
+
showInAddPagePicker: true,
|
|
10979
|
+
configFiles: ["config/.gemini-agent.yaml"]
|
|
10980
|
+
},
|
|
10981
|
+
{
|
|
10982
|
+
pluginName: "webmcp",
|
|
10983
|
+
packageName: "@jay-framework/webmcp",
|
|
10984
|
+
description: "Web MCP tooling",
|
|
10985
|
+
kind: "tooling",
|
|
10986
|
+
requires: [],
|
|
10987
|
+
showInAddPagePicker: false
|
|
10988
|
+
},
|
|
10989
|
+
{
|
|
10990
|
+
pluginName: "aiditor",
|
|
10991
|
+
packageName: "@jay-framework/aiditor",
|
|
10992
|
+
description: "AIditor self plugin",
|
|
10993
|
+
kind: "tooling",
|
|
10994
|
+
requires: [],
|
|
10995
|
+
showInAddPagePicker: false
|
|
10996
|
+
}
|
|
10997
|
+
];
|
|
10998
|
+
function getCatalogEntry(pluginName) {
|
|
10999
|
+
return CATALOG.find((e2) => e2.pluginName === pluginName);
|
|
10339
11000
|
}
|
|
10340
11001
|
function buildPluginInstallAgentNotes(entry, installError, projectDirHint) {
|
|
10341
11002
|
const requires = entry.requires.length > 0 ? entry.requires.join(", ") : "(none — install this plugin only)";
|
|
@@ -10367,6 +11028,7 @@ function buildPluginInstallAgentNotes(entry, installError, projectDirHint) {
|
|
|
10367
11028
|
"## Local / monorepo alternative",
|
|
10368
11029
|
wixPortal,
|
|
10369
11030
|
"- Read `agent-kit/plugin/INSTRUCTIONS.md` for plugin setup conventions.",
|
|
11031
|
+
"- To contribute Add Menu catalog items, read `agent-kit/plugin/aiditor-add-menu.md`.",
|
|
10370
11032
|
"",
|
|
10371
11033
|
"When finished, summarize what you installed and any config files the user must edit (e.g. config/.wix.yaml)."
|
|
10372
11034
|
].filter((line) => line !== "").join("\n");
|
|
@@ -10380,6 +11042,50 @@ const VALID_INSTALL_PREFIXES = ["portal:", "file:", "workspace:"];
|
|
|
10380
11042
|
function isValidInstallSpec(spec) {
|
|
10381
11043
|
return VALID_INSTALL_PREFIXES.some((p) => spec.startsWith(p));
|
|
10382
11044
|
}
|
|
11045
|
+
const listJayPluginsAction = createActionCaller("aiditor.listJayPlugins", "GET");
|
|
11046
|
+
createActionCaller("aiditor.listPluginContracts", "GET");
|
|
11047
|
+
const checkPluginUpdateAction = createActionCaller("aiditor.checkPluginUpdate", "GET");
|
|
11048
|
+
const ensureProjectPluginAction = createStreamCaller("aiditor.ensureProjectPlugin");
|
|
11049
|
+
createActionCaller("aiditor.getPluginSetupStatus", "GET");
|
|
11050
|
+
const rerunPluginSetupAction = createActionCaller("aiditor.rerunPluginSetup", "GET");
|
|
11051
|
+
createActionCaller("aiditor.syncAddPagePluginManifest", "GET");
|
|
11052
|
+
const writePluginSourceAction = createActionCaller("aiditor.writePluginSource", "GET");
|
|
11053
|
+
async function listJayPlugins(refreshSetupStatus = false) {
|
|
11054
|
+
return listJayPluginsAction({ refreshSetupStatus });
|
|
11055
|
+
}
|
|
11056
|
+
async function checkPluginUpdate(pluginName) {
|
|
11057
|
+
return checkPluginUpdateAction({ pluginName });
|
|
11058
|
+
}
|
|
11059
|
+
function ensureProjectPluginStream(input, callbacks) {
|
|
11060
|
+
let aborted = false;
|
|
11061
|
+
const abort = () => {
|
|
11062
|
+
aborted = true;
|
|
11063
|
+
};
|
|
11064
|
+
void (async () => {
|
|
11065
|
+
try {
|
|
11066
|
+
for await (const chunk of ensureProjectPluginAction(input)) {
|
|
11067
|
+
if (aborted) break;
|
|
11068
|
+
callbacks.onChunk(chunk);
|
|
11069
|
+
if (chunk.type === "done" || chunk.type === "error") {
|
|
11070
|
+
callbacks.onEnd();
|
|
11071
|
+
return;
|
|
11072
|
+
}
|
|
11073
|
+
}
|
|
11074
|
+
if (!aborted) callbacks.onEnd();
|
|
11075
|
+
} catch (err) {
|
|
11076
|
+
if (!aborted) {
|
|
11077
|
+
callbacks.onError(err instanceof Error ? err : new Error(String(err)));
|
|
11078
|
+
}
|
|
11079
|
+
}
|
|
11080
|
+
})();
|
|
11081
|
+
return abort;
|
|
11082
|
+
}
|
|
11083
|
+
async function rerunPluginSetup(pluginName, force) {
|
|
11084
|
+
return rerunPluginSetupAction({ pluginName, force });
|
|
11085
|
+
}
|
|
11086
|
+
async function writePluginSource(input) {
|
|
11087
|
+
return writePluginSourceAction(input);
|
|
11088
|
+
}
|
|
10383
11089
|
function initProjectPluginsManager(deps) {
|
|
10384
11090
|
const [pluginsList, setPluginsList] = createSignal([]);
|
|
10385
11091
|
const [pluginsLoaded, setPluginsLoaded] = createSignal(false);
|
|
@@ -10559,6 +11265,7 @@ function initProjectPluginsManager(deps) {
|
|
|
10559
11265
|
updateAvailable: false
|
|
10560
11266
|
});
|
|
10561
11267
|
void refreshPluginsList(true).then(() => deps.loadProjectInfo());
|
|
11268
|
+
deps.onInstallComplete?.(pluginName);
|
|
10562
11269
|
setShowReloadPreviewBanner(true);
|
|
10563
11270
|
}
|
|
10564
11271
|
},
|
|
@@ -10759,20 +11466,31 @@ function serializeGeometry(a2) {
|
|
|
10759
11466
|
return { kind: "area", x: a2.x, y: a2.y, w: a2.w, h: a2.h };
|
|
10760
11467
|
return { kind: "arrow", x1: a2.x1, y1: a2.y1, x2: a2.x2, y2: a2.y2 };
|
|
10761
11468
|
}
|
|
10762
|
-
function
|
|
11469
|
+
function serializeAnnotationNotesFields(a2) {
|
|
11470
|
+
if (a2.addMenuAttachments?.length) {
|
|
11471
|
+
return { addMenuAttachments: a2.addMenuAttachments };
|
|
11472
|
+
}
|
|
11473
|
+
if (a2.pluginBindings?.length) {
|
|
11474
|
+
return { pluginBindings: a2.pluginBindings };
|
|
11475
|
+
}
|
|
11476
|
+
return {};
|
|
11477
|
+
}
|
|
11478
|
+
function toNotesPayload(annotations, breakpoint, requestLevel) {
|
|
10763
11479
|
return {
|
|
10764
11480
|
version: AIDITOR_NOTES_VERSION,
|
|
10765
11481
|
breakpoint,
|
|
11482
|
+
...requestLevel?.addMenuAttachments?.length ? { addMenuAttachments: requestLevel.addMenuAttachments } : {},
|
|
11483
|
+
...requestLevel?.routeMigration ? { routeMigration: requestLevel.routeMigration } : {},
|
|
10766
11484
|
annotations: annotations.map((a2) => ({
|
|
10767
11485
|
id: a2.id,
|
|
10768
11486
|
mode: a2.kind,
|
|
10769
11487
|
instruction: a2.instruction.trim(),
|
|
10770
11488
|
geometry: serializeGeometry(a2),
|
|
10771
|
-
...a2
|
|
11489
|
+
...serializeAnnotationNotesFields(a2)
|
|
10772
11490
|
}))
|
|
10773
11491
|
};
|
|
10774
11492
|
}
|
|
10775
|
-
function toVideoNotesPayload(annotations, videoMeta, notesContext) {
|
|
11493
|
+
function toVideoNotesPayload(annotations, videoMeta, notesContext, requestLevel) {
|
|
10776
11494
|
const baseOrigin = typeof window !== "undefined" ? window.location.origin : JAY_DEV_URL_DEFAULT;
|
|
10777
11495
|
const fallback = fallbackPreviewContextFromBar(notesContext.fallbackRenderedUrl, notesContext.fallbackRoute, baseOrigin);
|
|
10778
11496
|
const navLog = notesContext.previewNavLog.length > 0 ? notesContext.previewNavLog : void 0;
|
|
@@ -10782,6 +11500,8 @@ function toVideoNotesPayload(annotations, videoMeta, notesContext) {
|
|
|
10782
11500
|
videoMeta,
|
|
10783
11501
|
previewNavLog: navLog,
|
|
10784
11502
|
breakpoint: notesContext.breakpoint,
|
|
11503
|
+
...requestLevel?.addMenuAttachments?.length ? { addMenuAttachments: requestLevel.addMenuAttachments } : {},
|
|
11504
|
+
...requestLevel?.routeMigration ? { routeMigration: requestLevel.routeMigration } : {},
|
|
10785
11505
|
annotations: annotations.map((a2) => {
|
|
10786
11506
|
const ctx = resolvePreviewContextAtTime(a2.timeSec, navLog, fallback);
|
|
10787
11507
|
return {
|
|
@@ -10792,7 +11512,7 @@ function toVideoNotesPayload(annotations, videoMeta, notesContext) {
|
|
|
10792
11512
|
timeSec: a2.timeSec,
|
|
10793
11513
|
previewUrlAtTime: ctx.href,
|
|
10794
11514
|
pagePathAtTime: ctx.locationPath,
|
|
10795
|
-
...a2
|
|
11515
|
+
...serializeAnnotationNotesFields(a2)
|
|
10796
11516
|
};
|
|
10797
11517
|
})
|
|
10798
11518
|
};
|
|
@@ -11020,12 +11740,22 @@ function aiditorConstructor(_props, refs) {
|
|
|
11020
11740
|
const [visualSubmitError, setVisualSubmitError] = createSignal("");
|
|
11021
11741
|
const [showProjectSettingsModal, setShowProjectSettingsModal] = createSignal(false);
|
|
11022
11742
|
let runPluginInstallAgent;
|
|
11743
|
+
let refreshAddMenuCatalog;
|
|
11023
11744
|
const projectPlugins = initProjectPluginsManager({
|
|
11024
11745
|
loadProjectInfo: () => loadProjectInfo(),
|
|
11025
11746
|
fixInstallWithAgent: (pluginName, installError) => {
|
|
11026
11747
|
runPluginInstallAgent?.(pluginName, installError);
|
|
11748
|
+
},
|
|
11749
|
+
onInstallComplete: () => {
|
|
11750
|
+
void refreshAddMenuCatalog?.();
|
|
11027
11751
|
}
|
|
11028
11752
|
});
|
|
11753
|
+
const visualAddMenu = initVisualAddMenuController({
|
|
11754
|
+
projectDir: () => projectDir(),
|
|
11755
|
+
projectPlugins,
|
|
11756
|
+
openProjectSettings,
|
|
11757
|
+
getCurrentRoute: () => selectedPageUrl() || "/"
|
|
11758
|
+
});
|
|
11029
11759
|
function openProjectSettings() {
|
|
11030
11760
|
setShowProjectSettingsModal(true);
|
|
11031
11761
|
void projectPlugins.refreshPluginsList();
|
|
@@ -11307,9 +12037,28 @@ function aiditorConstructor(_props, refs) {
|
|
|
11307
12037
|
return true;
|
|
11308
12038
|
return list.some((a2) => a2.instruction.trim().length === 0);
|
|
11309
12039
|
});
|
|
12040
|
+
createMemo(() => {
|
|
12041
|
+
return {
|
|
12042
|
+
show: false,
|
|
12043
|
+
annotationId: "",
|
|
12044
|
+
leftPct: 0,
|
|
12045
|
+
topPct: 0,
|
|
12046
|
+
navRows: [],
|
|
12047
|
+
selectedCategory: "",
|
|
12048
|
+
loading: false,
|
|
12049
|
+
empty: false
|
|
12050
|
+
};
|
|
12051
|
+
});
|
|
12052
|
+
const showMarkerAddMenuPopover = createMemo(() => false);
|
|
12053
|
+
const markerAddMenuPopoverLeftPct = createMemo(() => 0);
|
|
12054
|
+
const markerAddMenuPopoverTopPct = createMemo(() => 0);
|
|
12055
|
+
const markerAddMenuPickerAnnotationId = createMemo(() => "");
|
|
12056
|
+
const markerAddMenuNavRows = createMemo(() => []);
|
|
12057
|
+
const markerAddMenuSelectedCategory = createMemo(() => "");
|
|
12058
|
+
const showMarkerAddMenuPickerLoading = createMemo(() => false);
|
|
12059
|
+
const showMarkerAddMenuPickerCatalogEmpty = createMemo(() => false);
|
|
11310
12060
|
const visualAnnotationRows = createMemo(() => {
|
|
11311
12061
|
const runDisabled = visualRunDisabled();
|
|
11312
|
-
const plugins = projectPlugins.pluginsList();
|
|
11313
12062
|
return visualAnnotations().map((a2) => {
|
|
11314
12063
|
const { nx, ny } = bubbleAnchorNorm(a2);
|
|
11315
12064
|
const leftPct = nx * 100;
|
|
@@ -11331,10 +12080,11 @@ function aiditorConstructor(_props, refs) {
|
|
|
11331
12080
|
popoverFlipX: flipX,
|
|
11332
12081
|
popoverFlipY: flipY,
|
|
11333
12082
|
attachmentChips,
|
|
11334
|
-
...
|
|
12083
|
+
...visualAddMenu.enrichUi(a2, stripMarkerPickerNavRowForVisual)
|
|
11335
12084
|
};
|
|
11336
12085
|
});
|
|
11337
12086
|
});
|
|
12087
|
+
const showCrPlannedRoutePanel = createMemo(() => visualAddMenu.routeMigration() !== null);
|
|
11338
12088
|
const recordingDraftPopoverRow = createMemo(() => {
|
|
11339
12089
|
const a2 = recordingDraftAnnotation();
|
|
11340
12090
|
if (!a2)
|
|
@@ -11462,7 +12212,6 @@ function aiditorConstructor(_props, refs) {
|
|
|
11462
12212
|
const t = videoReviewCurrentTimeSec();
|
|
11463
12213
|
const list = fullList.filter((a2) => isVideoAnnotationAtPlayhead(t, a2.timeSec));
|
|
11464
12214
|
const runDisabled = fullList.length > 0 && (isRunning() || fullList.some((a2) => a2.instruction.trim().length === 0));
|
|
11465
|
-
const plugins = projectPlugins.pluginsList();
|
|
11466
12215
|
return list.map((a2) => {
|
|
11467
12216
|
const { nx, ny } = bubbleAnchorNorm(a2);
|
|
11468
12217
|
const leftPct = nx * 100;
|
|
@@ -11485,7 +12234,7 @@ function aiditorConstructor(_props, refs) {
|
|
|
11485
12234
|
popoverFlipX: flipX,
|
|
11486
12235
|
popoverFlipY: flipY,
|
|
11487
12236
|
attachmentChips,
|
|
11488
|
-
...
|
|
12237
|
+
...visualAddMenu.enrichUi(a2, stripMarkerPickerNavRowForVideo)
|
|
11489
12238
|
};
|
|
11490
12239
|
});
|
|
11491
12240
|
});
|
|
@@ -11611,7 +12360,6 @@ function aiditorConstructor(_props, refs) {
|
|
|
11611
12360
|
const snapshotAreaDraftWidthPct = createMemo(() => (snapshotAreaDraftNorm()?.w ?? 0) * 100);
|
|
11612
12361
|
const snapshotAreaDraftHeightPct = createMemo(() => (snapshotAreaDraftNorm()?.h ?? 0) * 100);
|
|
11613
12362
|
const snapshotAnnotationItems = createMemo(() => {
|
|
11614
|
-
const plugins = projectPlugins.pluginsList();
|
|
11615
12363
|
return snapshotAnnotations().map((a2) => {
|
|
11616
12364
|
const { nx, ny } = bubbleAnchorNorm(a2);
|
|
11617
12365
|
const leftPct = nx * 100;
|
|
@@ -11634,7 +12382,7 @@ function aiditorConstructor(_props, refs) {
|
|
|
11634
12382
|
popoverFlipX: flipX,
|
|
11635
12383
|
popoverFlipY: flipY,
|
|
11636
12384
|
attachmentChips,
|
|
11637
|
-
...
|
|
12385
|
+
...visualAddMenu.enrichUi(a2, stripMarkerPickerNavRowForSnapshot)
|
|
11638
12386
|
};
|
|
11639
12387
|
});
|
|
11640
12388
|
});
|
|
@@ -11714,6 +12462,7 @@ function aiditorConstructor(_props, refs) {
|
|
|
11714
12462
|
setAreaDraft(null);
|
|
11715
12463
|
setArrowPending(null);
|
|
11716
12464
|
setVisualSubmitError("");
|
|
12465
|
+
visualAddMenu.reset();
|
|
11717
12466
|
cancelAreaDragListeners();
|
|
11718
12467
|
setVisualTool("none");
|
|
11719
12468
|
}
|
|
@@ -11901,68 +12650,27 @@ function aiditorConstructor(_props, refs) {
|
|
|
11901
12650
|
function updateVideoAsVisual(id, updater) {
|
|
11902
12651
|
updateVideoAnnotation(id, (a2) => updater(a2));
|
|
11903
12652
|
}
|
|
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);
|
|
12653
|
+
function updateMarkerAddMenuAnnotation(id, updater) {
|
|
12654
|
+
if (visualAnnotations().some((a2) => a2.id === id)) {
|
|
12655
|
+
updateVisualAnnotation(id, (a2) => ({ ...a2, ...updater(a2) }));
|
|
11953
12656
|
return;
|
|
11954
12657
|
}
|
|
11955
|
-
|
|
11956
|
-
|
|
11957
|
-
addBindingToAnnotation(update, id, addBtn.dataset.plugin, addBtn.dataset.package, addBtn.dataset.contract, addBtn.dataset.key ?? "");
|
|
12658
|
+
if (videoSessionAnnotations().some((a2) => a2.id === id)) {
|
|
12659
|
+
updateVideoAsVisual(id, (a2) => ({ ...a2, ...updater(a2) }));
|
|
11958
12660
|
return;
|
|
11959
12661
|
}
|
|
11960
|
-
|
|
11961
|
-
|
|
11962
|
-
removeBindingFromAnnotation(update, id, removeChip.dataset.plugin, removeChip.dataset.contract);
|
|
11963
|
-
return;
|
|
12662
|
+
if (snapshotAnnotations().some((a2) => a2.id === id)) {
|
|
12663
|
+
updateSnapshotAnnotation(id, (a2) => ({ ...a2, ...updater(a2) }));
|
|
11964
12664
|
}
|
|
11965
12665
|
}
|
|
12666
|
+
function changeRequestAddMenuPayload() {
|
|
12667
|
+
const attachments = visualAddMenu.requestAttachments();
|
|
12668
|
+
const migration = visualAddMenu.routeMigration();
|
|
12669
|
+
return {
|
|
12670
|
+
...attachments.length ? { addMenuAttachments: attachments } : {},
|
|
12671
|
+
...migration ? { routeMigration: migration } : {}
|
|
12672
|
+
};
|
|
12673
|
+
}
|
|
11966
12674
|
function setRecordingDraftInstruction(instruction) {
|
|
11967
12675
|
setRecordingDraftAnnotation((prev) => {
|
|
11968
12676
|
if (!prev)
|
|
@@ -12117,6 +12825,7 @@ function aiditorConstructor(_props, refs) {
|
|
|
12117
12825
|
setIsBootstrapping(false);
|
|
12118
12826
|
paramsCache.clear();
|
|
12119
12827
|
loadProjectInfo();
|
|
12828
|
+
void refreshAddMenuCatalog?.();
|
|
12120
12829
|
}).catch((err) => {
|
|
12121
12830
|
console.error("[aiditor] bootstrap", err);
|
|
12122
12831
|
setIsBootstrapping(false);
|
|
@@ -12296,6 +13005,10 @@ function aiditorConstructor(_props, refs) {
|
|
|
12296
13005
|
selectedPageUrl,
|
|
12297
13006
|
setCurrentPageHasBrief
|
|
12298
13007
|
});
|
|
13008
|
+
refreshAddMenuCatalog = () => {
|
|
13009
|
+
void addPage.refreshAddMenuCatalog();
|
|
13010
|
+
void visualAddMenu.refreshCatalog();
|
|
13011
|
+
};
|
|
12299
13012
|
refreshPageBriefRef.current = () => {
|
|
12300
13013
|
void addPage.refreshCurrentPageBriefAvailability();
|
|
12301
13014
|
};
|
|
@@ -12545,6 +13258,10 @@ function aiditorConstructor(_props, refs) {
|
|
|
12545
13258
|
});
|
|
12546
13259
|
refs.visualAnnotationRows.annotationRow.oninput(({ event }) => {
|
|
12547
13260
|
const t = event.target;
|
|
13261
|
+
if (t.classList.contains("cr-planned-route-input")) {
|
|
13262
|
+
visualAddMenu.setPlannedRoute(t.value);
|
|
13263
|
+
return;
|
|
13264
|
+
}
|
|
12548
13265
|
if (t.tagName !== "TEXTAREA" || !t.classList.contains("visual-annotation-instruction"))
|
|
12549
13266
|
return;
|
|
12550
13267
|
const id = t.dataset.annotationId;
|
|
@@ -12617,19 +13334,31 @@ function aiditorConstructor(_props, refs) {
|
|
|
12617
13334
|
tryJayRefExec2(refs.visualAttachFileInput, (el) => el.click());
|
|
12618
13335
|
}
|
|
12619
13336
|
});
|
|
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
13337
|
refs.visualAnnotationRows.annotationRow.onclick(({ event, viewState }) => {
|
|
12629
13338
|
const raw = event.target;
|
|
12630
|
-
if (raw.closest(".annotation-
|
|
13339
|
+
if (raw.closest(".annotation-add-menu")) {
|
|
12631
13340
|
event.preventDefault();
|
|
12632
|
-
|
|
13341
|
+
const handled = visualAddMenu.handleMarkerAddMenuClick(raw, viewState.id, updateMarkerAddMenuAnnotation);
|
|
13342
|
+
if (!handled) {
|
|
13343
|
+
const paramBtn = raw.closest("[data-cr-route-param]");
|
|
13344
|
+
if (paramBtn?.dataset.param) {
|
|
13345
|
+
const name = paramBtn.dataset.param;
|
|
13346
|
+
visualAddMenu.setPlannedRoute((route) => {
|
|
13347
|
+
const base = route || selectedPageUrl() || "/";
|
|
13348
|
+
if (base.includes(`[${name}]`))
|
|
13349
|
+
return base;
|
|
13350
|
+
return base.endsWith("/") ? `${base}[${name}]` : `${base}/[${name}]`;
|
|
13351
|
+
});
|
|
13352
|
+
return;
|
|
13353
|
+
}
|
|
13354
|
+
if (raw.closest("[data-cr-route-param-confirm]")) {
|
|
13355
|
+
void visualAddMenu.confirmRouteParamPick(updateMarkerAddMenuAnnotation);
|
|
13356
|
+
return;
|
|
13357
|
+
}
|
|
13358
|
+
if (raw.closest("[data-cr-route-param-cancel]")) {
|
|
13359
|
+
visualAddMenu.cancelRouteParamPick();
|
|
13360
|
+
}
|
|
13361
|
+
}
|
|
12633
13362
|
return;
|
|
12634
13363
|
}
|
|
12635
13364
|
const t = raw.closest("button");
|
|
@@ -12678,7 +13407,7 @@ function aiditorConstructor(_props, refs) {
|
|
|
12678
13407
|
return;
|
|
12679
13408
|
}
|
|
12680
13409
|
const list = visualAnnotations();
|
|
12681
|
-
const notesJson = serializeAiditorNotes(toNotesPayload(list, previewBreakpoint()));
|
|
13410
|
+
const notesJson = serializeAiditorNotes(toNotesPayload(list, previewBreakpoint(), changeRequestAddMenuPayload()));
|
|
12682
13411
|
try {
|
|
12683
13412
|
setIsRunning(true);
|
|
12684
13413
|
setVisualSubmitError("");
|
|
@@ -12722,7 +13451,7 @@ function aiditorConstructor(_props, refs) {
|
|
|
12722
13451
|
setSnapshotSubmitError("Screenshot data is missing.");
|
|
12723
13452
|
return;
|
|
12724
13453
|
}
|
|
12725
|
-
const notesJson = serializeAiditorNotes(toNotesPayload(list, previewBreakpoint()));
|
|
13454
|
+
const notesJson = serializeAiditorNotes(toNotesPayload(list, previewBreakpoint(), changeRequestAddMenuPayload()));
|
|
12726
13455
|
try {
|
|
12727
13456
|
setIsRunning(true);
|
|
12728
13457
|
setSnapshotSubmitError("");
|
|
@@ -13262,7 +13991,7 @@ function aiditorConstructor(_props, refs) {
|
|
|
13262
13991
|
fallbackRenderedUrl: rendered,
|
|
13263
13992
|
fallbackRoute: route,
|
|
13264
13993
|
breakpoint: previewBreakpoint()
|
|
13265
|
-
});
|
|
13994
|
+
}, changeRequestAddMenuPayload());
|
|
13266
13995
|
try {
|
|
13267
13996
|
setIsRunning(true);
|
|
13268
13997
|
setVideoSubmitError("");
|
|
@@ -13270,12 +13999,26 @@ function aiditorConstructor(_props, refs) {
|
|
|
13270
13999
|
const frameDuals = [];
|
|
13271
14000
|
const nFrames = distinctTimes.length;
|
|
13272
14001
|
let frameIdx = 0;
|
|
14002
|
+
videoEl.pause();
|
|
13273
14003
|
for (const t of distinctTimes) {
|
|
13274
14004
|
frameIdx += 1;
|
|
13275
14005
|
setVideoSubmitProgress(`Capturing annotated frames (${frameIdx}/${nFrames})…`);
|
|
14006
|
+
console.info("[aiditor:video-capture] frame start", {
|
|
14007
|
+
frameIdx,
|
|
14008
|
+
nFrames,
|
|
14009
|
+
timeSec: t,
|
|
14010
|
+
currentTime: videoEl.currentTime,
|
|
14011
|
+
paused: videoEl.paused
|
|
14012
|
+
});
|
|
13276
14013
|
await seekVideoToTime(videoEl, t);
|
|
14014
|
+
setVideoReviewCurrentTimeSec(t);
|
|
14015
|
+
await flushLayout();
|
|
13277
14016
|
const dual = await captureVideoInstantDual(captureRoot, videoEl);
|
|
13278
14017
|
frameDuals.push({ timeSec: t, ...dual });
|
|
14018
|
+
console.info("[aiditor:video-capture] frame done", {
|
|
14019
|
+
frameIdx,
|
|
14020
|
+
timeSec: t
|
|
14021
|
+
});
|
|
13279
14022
|
}
|
|
13280
14023
|
const attachmentsByPin = /* @__PURE__ */ new Map();
|
|
13281
14024
|
for (const a2 of list) {
|
|
@@ -13353,6 +14096,7 @@ function aiditorConstructor(_props, refs) {
|
|
|
13353
14096
|
}
|
|
13354
14097
|
function finishAgentStreamRun() {
|
|
13355
14098
|
setIsRunning(false);
|
|
14099
|
+
void refreshAddMenuCatalog?.();
|
|
13356
14100
|
focusAgentChatInput();
|
|
13357
14101
|
}
|
|
13358
14102
|
function runAgentStream(notes2, options, streamOptions) {
|
|
@@ -13665,16 +14409,12 @@ function aiditorConstructor(_props, refs) {
|
|
|
13665
14409
|
}
|
|
13666
14410
|
}
|
|
13667
14411
|
});
|
|
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
14412
|
refs.videoAnnotationRows.videoAnnotationRow.oninput(({ event }) => {
|
|
13677
14413
|
const t = event.target;
|
|
14414
|
+
if (t.classList.contains("cr-planned-route-input")) {
|
|
14415
|
+
visualAddMenu.setPlannedRoute(t.value);
|
|
14416
|
+
return;
|
|
14417
|
+
}
|
|
13678
14418
|
if (t.tagName !== "TEXTAREA" || !t.classList.contains("visual-annotation-instruction"))
|
|
13679
14419
|
return;
|
|
13680
14420
|
const id = t.dataset.annotationId;
|
|
@@ -13684,9 +14424,29 @@ function aiditorConstructor(_props, refs) {
|
|
|
13684
14424
|
});
|
|
13685
14425
|
refs.videoAnnotationRows.videoAnnotationRow.onclick(({ event, viewState }) => {
|
|
13686
14426
|
const raw = event.target;
|
|
13687
|
-
if (raw.closest(".annotation-
|
|
14427
|
+
if (raw.closest(".annotation-add-menu")) {
|
|
13688
14428
|
event.preventDefault();
|
|
13689
|
-
|
|
14429
|
+
const handled = visualAddMenu.handleMarkerAddMenuClick(raw, viewState.id, updateMarkerAddMenuAnnotation);
|
|
14430
|
+
if (!handled) {
|
|
14431
|
+
const paramBtn = raw.closest("[data-cr-route-param]");
|
|
14432
|
+
if (paramBtn?.dataset.param) {
|
|
14433
|
+
const name = paramBtn.dataset.param;
|
|
14434
|
+
visualAddMenu.setPlannedRoute((route) => {
|
|
14435
|
+
const base = route || selectedPageUrl() || "/";
|
|
14436
|
+
if (base.includes(`[${name}]`))
|
|
14437
|
+
return base;
|
|
14438
|
+
return base.endsWith("/") ? `${base}[${name}]` : `${base}/[${name}]`;
|
|
14439
|
+
});
|
|
14440
|
+
return;
|
|
14441
|
+
}
|
|
14442
|
+
if (raw.closest("[data-cr-route-param-confirm]")) {
|
|
14443
|
+
void visualAddMenu.confirmRouteParamPick(updateMarkerAddMenuAnnotation);
|
|
14444
|
+
return;
|
|
14445
|
+
}
|
|
14446
|
+
if (raw.closest("[data-cr-route-param-cancel]")) {
|
|
14447
|
+
visualAddMenu.cancelRouteParamPick();
|
|
14448
|
+
}
|
|
14449
|
+
}
|
|
13690
14450
|
return;
|
|
13691
14451
|
}
|
|
13692
14452
|
const t = raw.closest("button");
|
|
@@ -13930,16 +14690,12 @@ function aiditorConstructor(_props, refs) {
|
|
|
13930
14690
|
}
|
|
13931
14691
|
}
|
|
13932
14692
|
});
|
|
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
14693
|
refs.snapshotAnnotationItems.snapshotAnnotationRow.oninput(({ event }) => {
|
|
13942
14694
|
const t = event.target;
|
|
14695
|
+
if (t.classList.contains("cr-planned-route-input")) {
|
|
14696
|
+
visualAddMenu.setPlannedRoute(t.value);
|
|
14697
|
+
return;
|
|
14698
|
+
}
|
|
13943
14699
|
if (t.tagName !== "TEXTAREA" || !t.classList.contains("visual-annotation-instruction"))
|
|
13944
14700
|
return;
|
|
13945
14701
|
const id = t.dataset.annotationId;
|
|
@@ -13964,12 +14720,33 @@ function aiditorConstructor(_props, refs) {
|
|
|
13964
14720
|
});
|
|
13965
14721
|
refs.snapshotAnnotationItems.snapshotAnnotationRow.onclick(({ event }) => {
|
|
13966
14722
|
const raw = event.target;
|
|
13967
|
-
if (raw.closest(".annotation-
|
|
14723
|
+
if (raw.closest(".annotation-add-menu")) {
|
|
13968
14724
|
event.preventDefault();
|
|
13969
14725
|
const card = raw.closest("[data-annotation-id]");
|
|
13970
14726
|
const id = card?.getAttribute("data-annotation-id");
|
|
13971
|
-
if (id)
|
|
13972
|
-
|
|
14727
|
+
if (id) {
|
|
14728
|
+
const handled = visualAddMenu.handleMarkerAddMenuClick(raw, id, updateMarkerAddMenuAnnotation);
|
|
14729
|
+
if (!handled) {
|
|
14730
|
+
const paramBtn = raw.closest("[data-cr-route-param]");
|
|
14731
|
+
if (paramBtn?.dataset.param) {
|
|
14732
|
+
const name = paramBtn.dataset.param;
|
|
14733
|
+
visualAddMenu.setPlannedRoute((route) => {
|
|
14734
|
+
const base = route || selectedPageUrl() || "/";
|
|
14735
|
+
if (base.includes(`[${name}]`))
|
|
14736
|
+
return base;
|
|
14737
|
+
return base.endsWith("/") ? `${base}[${name}]` : `${base}/[${name}]`;
|
|
14738
|
+
});
|
|
14739
|
+
return;
|
|
14740
|
+
}
|
|
14741
|
+
if (raw.closest("[data-cr-route-param-confirm]")) {
|
|
14742
|
+
void visualAddMenu.confirmRouteParamPick(updateMarkerAddMenuAnnotation);
|
|
14743
|
+
return;
|
|
14744
|
+
}
|
|
14745
|
+
if (raw.closest("[data-cr-route-param-cancel]")) {
|
|
14746
|
+
visualAddMenu.cancelRouteParamPick();
|
|
14747
|
+
}
|
|
14748
|
+
}
|
|
14749
|
+
}
|
|
13973
14750
|
return;
|
|
13974
14751
|
}
|
|
13975
14752
|
const btn = raw.closest("button");
|
|
@@ -14189,6 +14966,14 @@ function aiditorConstructor(_props, refs) {
|
|
|
14189
14966
|
recordingDraftUi,
|
|
14190
14967
|
recordingDraftAttachmentChips,
|
|
14191
14968
|
showRecordingDraftPopover,
|
|
14969
|
+
showMarkerAddMenuPopover,
|
|
14970
|
+
markerAddMenuPopoverLeftPct,
|
|
14971
|
+
markerAddMenuPopoverTopPct,
|
|
14972
|
+
markerAddMenuPickerAnnotationId,
|
|
14973
|
+
markerAddMenuNavRows,
|
|
14974
|
+
markerAddMenuSelectedCategory,
|
|
14975
|
+
showMarkerAddMenuPickerLoading,
|
|
14976
|
+
showMarkerAddMenuPickerCatalogEmpty,
|
|
14192
14977
|
showVisualAnnotationsPanel,
|
|
14193
14978
|
showVisualSubmitError,
|
|
14194
14979
|
visualSubmitError,
|
|
@@ -14301,16 +15086,19 @@ function aiditorConstructor(_props, refs) {
|
|
|
14301
15086
|
projectLocalPluginName: projectPlugins.addLocalPluginName,
|
|
14302
15087
|
projectLocalPackageName: projectPlugins.addLocalPackageName,
|
|
14303
15088
|
projectLocalPath: projectPlugins.addLocalPath,
|
|
14304
|
-
|
|
14305
|
-
|
|
14306
|
-
|
|
14307
|
-
|
|
14308
|
-
|
|
14309
|
-
|
|
14310
|
-
|
|
14311
|
-
|
|
14312
|
-
|
|
14313
|
-
|
|
15089
|
+
showAddMenuPanel: addPage.showAddMenuPanel,
|
|
15090
|
+
showAddMenuChips: addPage.showAddMenuChips,
|
|
15091
|
+
addMenuChipRows: addPage.addMenuChipRows,
|
|
15092
|
+
showAddMenuEmptyHint: addPage.showAddMenuEmptyHint,
|
|
15093
|
+
showAddMenuPopover: addPage.showAddMenuPopover,
|
|
15094
|
+
addMenuNavRows: addPage.addMenuNavRows,
|
|
15095
|
+
addMenuSelectedCategory: addPage.addMenuSelectedCategory,
|
|
15096
|
+
addMenuParamCollisionWarning: addPage.addMenuParamCollisionWarning,
|
|
15097
|
+
addMenuRouteParamHint: addPage.addMenuRouteParamHint,
|
|
15098
|
+
showAddMenuRouteParams: addPage.showAddMenuRouteParams,
|
|
15099
|
+
addMenuRouteParamRows: addPage.addMenuRouteParamRows,
|
|
15100
|
+
showAddMenuRouteParamConfirm: addPage.showAddMenuRouteParamConfirm,
|
|
15101
|
+
addMenuPendingRouteParamTitle: addPage.addMenuPendingRouteParamTitle,
|
|
14314
15102
|
showAddPageResultBanner,
|
|
14315
15103
|
addPageResultBannerClass,
|
|
14316
15104
|
addPageResultBannerMessage,
|
|
@@ -14330,7 +15118,15 @@ function aiditorConstructor(_props, refs) {
|
|
|
14330
15118
|
showBriefFillThumbnails: addPage.showBriefFillThumbnails,
|
|
14331
15119
|
addPageBriefFillThumbRows: addPage.addPageBriefFillThumbRows,
|
|
14332
15120
|
showSuggestedRouteBanner: addPage.showSuggestedRouteBanner,
|
|
14333
|
-
suggestedRouteLabel: addPage.suggestedRouteLabel
|
|
15121
|
+
suggestedRouteLabel: addPage.suggestedRouteLabel,
|
|
15122
|
+
crAddMenuParamCollisionWarning: visualAddMenu.paramCollisionWarning,
|
|
15123
|
+
crAddMenuRouteParamHint: visualAddMenu.routeParamHint,
|
|
15124
|
+
showCrAddMenuRouteParams: visualAddMenu.showRouteParams,
|
|
15125
|
+
crAddMenuRouteParamRows: visualAddMenu.routeParamRows,
|
|
15126
|
+
showCrRouteParamConfirm: visualAddMenu.showRouteParamConfirm,
|
|
15127
|
+
crPendingRouteParamTitle: visualAddMenu.pendingRouteParamTitle,
|
|
15128
|
+
showCrPlannedRoutePanel,
|
|
15129
|
+
crPlannedRoute: visualAddMenu.plannedRoute
|
|
14334
15130
|
})
|
|
14335
15131
|
};
|
|
14336
15132
|
}
|