@mulmoclaude/collection-plugin 0.7.6 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/style.css +26 -0
- package/dist/vue/components/CollectionBacklinksView.vue.d.ts +9 -0
- package/dist/vue/components/CollectionBacklinksView.vue.d.ts.map +1 -0
- package/dist/vue/components/CollectionMutateParamsModal.vue.d.ts +19 -0
- package/dist/vue/components/CollectionMutateParamsModal.vue.d.ts.map +1 -0
- package/dist/vue/components/CollectionRecordPanel.vue.d.ts +73 -8
- package/dist/vue/components/CollectionRecordPanel.vue.d.ts.map +1 -1
- package/dist/vue/components/CollectionView.vue.d.ts.map +1 -1
- package/dist/vue/uiContext.d.ts +26 -5
- package/dist/vue/uiContext.d.ts.map +1 -1
- package/dist/vue/useCollectionRendering.d.ts +12 -1
- package/dist/vue/useCollectionRendering.d.ts.map +1 -1
- package/dist/vue/useCollectionRendering.helpers.d.ts +12 -0
- package/dist/vue/useCollectionRendering.helpers.d.ts.map +1 -1
- package/dist/vue/useCollectionRendering.renderers.d.ts +28 -2
- package/dist/vue/useCollectionRendering.renderers.d.ts.map +1 -1
- package/dist/vue/useLinkedCollectionCaches.d.ts +5 -1
- package/dist/vue/useLinkedCollectionCaches.d.ts.map +1 -1
- package/dist/vue.cjs +968 -474
- package/dist/vue.cjs.map +1 -1
- package/dist/vue.js +970 -476
- package/dist/vue.js.map +1 -1
- package/package.json +3 -3
package/dist/vue.cjs
CHANGED
|
@@ -1233,19 +1233,351 @@ var CollectionRecordModal_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
1233
1233
|
}
|
|
1234
1234
|
});
|
|
1235
1235
|
//#endregion
|
|
1236
|
+
//#region src/vue/useCollectionRendering.helpers.ts
|
|
1237
|
+
var EM_DASH = "—";
|
|
1238
|
+
var DEFAULT_CURRENCY = "USD";
|
|
1239
|
+
var MARKDOWN_CELL_PREVIEW_MAX = 80;
|
|
1240
|
+
function stepForFieldType(type) {
|
|
1241
|
+
if (type === "money") return "0.01";
|
|
1242
|
+
if (type === "number") return "any";
|
|
1243
|
+
}
|
|
1244
|
+
function inputTypeFor(type) {
|
|
1245
|
+
if (type === "email") return "email";
|
|
1246
|
+
if (type === "number") return "number";
|
|
1247
|
+
if (type === "money") return "number";
|
|
1248
|
+
if (type === "date") return "date";
|
|
1249
|
+
if (type === "datetime") return "datetime-local";
|
|
1250
|
+
return "text";
|
|
1251
|
+
}
|
|
1252
|
+
function isExternalUrl(value) {
|
|
1253
|
+
return typeof value === "string" && /^https?:\/\//i.test(value);
|
|
1254
|
+
}
|
|
1255
|
+
function detailText(value) {
|
|
1256
|
+
if (value === void 0 || value === null || value === "") return EM_DASH;
|
|
1257
|
+
return String(value);
|
|
1258
|
+
}
|
|
1259
|
+
function formatCell(value, type) {
|
|
1260
|
+
if (value === void 0 || value === null || value === "") return EM_DASH;
|
|
1261
|
+
if (type === "markdown" && typeof value === "string") return value.length > MARKDOWN_CELL_PREVIEW_MAX ? `${value.slice(0, MARKDOWN_CELL_PREVIEW_MAX)}…` : value;
|
|
1262
|
+
if (typeof value === "string" || typeof value === "number") return String(value);
|
|
1263
|
+
return JSON.stringify(value);
|
|
1264
|
+
}
|
|
1265
|
+
/** Resolve the ISO 4217 code for a money field: a per-record
|
|
1266
|
+
* `currencyField` (when present and non-blank) wins over the field's
|
|
1267
|
+
* literal `currency`. Only `money` / `derived` variants carry currency
|
|
1268
|
+
* keys; any other field resolves to undefined (the formatter's USD
|
|
1269
|
+
* fallback), as before. */
|
|
1270
|
+
function resolveCurrency(field, record) {
|
|
1271
|
+
if (field.type !== "money" && field.type !== "derived") return void 0;
|
|
1272
|
+
if (field.currencyField && record) {
|
|
1273
|
+
const code = record[field.currencyField];
|
|
1274
|
+
if (typeof code === "string" && code.trim().length > 0) return code;
|
|
1275
|
+
}
|
|
1276
|
+
return field.currency;
|
|
1277
|
+
}
|
|
1278
|
+
function formatMoney(value, currency, displayLocale) {
|
|
1279
|
+
if (value === void 0 || value === "") return EM_DASH;
|
|
1280
|
+
const amount = typeof value === "number" ? value : Number(value);
|
|
1281
|
+
if (!Number.isFinite(amount)) return String(value);
|
|
1282
|
+
const currencyCode = currency && currency.length > 0 ? currency : DEFAULT_CURRENCY;
|
|
1283
|
+
try {
|
|
1284
|
+
return new Intl.NumberFormat(displayLocale, {
|
|
1285
|
+
style: "currency",
|
|
1286
|
+
currency: currencyCode
|
|
1287
|
+
}).format(amount);
|
|
1288
|
+
} catch {
|
|
1289
|
+
return String(amount);
|
|
1290
|
+
}
|
|
1291
|
+
}
|
|
1292
|
+
function currencySymbolForLocale(currency, locale) {
|
|
1293
|
+
const code = currency && currency.length > 0 ? currency : DEFAULT_CURRENCY;
|
|
1294
|
+
try {
|
|
1295
|
+
return new Intl.NumberFormat(locale, {
|
|
1296
|
+
style: "currency",
|
|
1297
|
+
currency: code
|
|
1298
|
+
}).formatToParts(0).find((entry) => entry.type === "currency")?.value ?? code;
|
|
1299
|
+
} catch {
|
|
1300
|
+
return code;
|
|
1301
|
+
}
|
|
1302
|
+
}
|
|
1303
|
+
function tableRows(value) {
|
|
1304
|
+
if (!Array.isArray(value)) return [];
|
|
1305
|
+
return value.filter((row) => Boolean(row) && typeof row === "object" && !Array.isArray(row));
|
|
1306
|
+
}
|
|
1307
|
+
function hasTableRows(value) {
|
|
1308
|
+
return tableRows(value).length > 0;
|
|
1309
|
+
}
|
|
1310
|
+
/** Pick the field used to label a referenced/embedded record: prefer a
|
|
1311
|
+
* `name` field, then `title`, else fall back to the primary key. */
|
|
1312
|
+
function displayFieldFor(fields, primaryKey) {
|
|
1313
|
+
if ("name" in fields) return "name";
|
|
1314
|
+
if ("title" in fields) return "title";
|
|
1315
|
+
return primaryKey;
|
|
1316
|
+
}
|
|
1317
|
+
function uniqueRefTargets(schema) {
|
|
1318
|
+
const targets = /* @__PURE__ */ new Set();
|
|
1319
|
+
const walk = (fields) => {
|
|
1320
|
+
for (const field of Object.values(fields)) {
|
|
1321
|
+
if (field.type === "ref" && typeof field.to === "string" && field.to.length > 0) targets.add(field.to);
|
|
1322
|
+
if (field.type === "table" && field.of) walk(field.of);
|
|
1323
|
+
}
|
|
1324
|
+
};
|
|
1325
|
+
walk(schema.fields);
|
|
1326
|
+
return [...targets];
|
|
1327
|
+
}
|
|
1328
|
+
function uniqueEmbedTargets(schema) {
|
|
1329
|
+
const targets = /* @__PURE__ */ new Set();
|
|
1330
|
+
for (const field of Object.values(schema.fields)) if (field.type === "embed" && typeof field.to === "string" && field.to.length > 0) targets.add(field.to);
|
|
1331
|
+
return [...targets];
|
|
1332
|
+
}
|
|
1333
|
+
/** Slugs of every SOURCE collection a `backlinks` or `rollup` field
|
|
1334
|
+
* reverses over (the two share one load). Top-level only, like `embed`
|
|
1335
|
+
* (the schema rejects both inside a table's `of`). Mirrors the server's
|
|
1336
|
+
* `uniqueBacklinkSources`. */
|
|
1337
|
+
function uniqueBacklinkSources(schema) {
|
|
1338
|
+
const sources = /* @__PURE__ */ new Set();
|
|
1339
|
+
for (const field of Object.values(schema.fields)) if ((field.type === "backlinks" || field.type === "rollup") && field.from.length > 0) sources.add(field.from);
|
|
1340
|
+
return [...sources];
|
|
1341
|
+
}
|
|
1342
|
+
function buildRefDisplayMap(detail) {
|
|
1343
|
+
const { fields, primaryKey } = detail.collection.schema;
|
|
1344
|
+
const displayField = displayFieldFor(fields, primaryKey);
|
|
1345
|
+
const map = {};
|
|
1346
|
+
for (const item of detail.items) {
|
|
1347
|
+
const slugRaw = item[primaryKey];
|
|
1348
|
+
if (typeof slugRaw !== "string" || slugRaw.length === 0) continue;
|
|
1349
|
+
const displayRaw = item[displayField];
|
|
1350
|
+
map[slugRaw] = typeof displayRaw === "string" && displayRaw.length > 0 ? displayRaw : slugRaw;
|
|
1351
|
+
}
|
|
1352
|
+
return map;
|
|
1353
|
+
}
|
|
1354
|
+
/** Index DERIVED records by primary key — the client mirror of the
|
|
1355
|
+
* server's `loadTarget` indexing: string non-empty ids only, one record
|
|
1356
|
+
* per id (a duplicate keeps the LAST record in its FIRST position —
|
|
1357
|
+
* plain-object key semantics). Shared by the ref-record cache and the
|
|
1358
|
+
* backlinks view so every client consumer agrees with server enrichment
|
|
1359
|
+
* on which source records exist. */
|
|
1360
|
+
function derivedRecordsById(schema, items) {
|
|
1361
|
+
const map = {};
|
|
1362
|
+
for (const item of items) {
|
|
1363
|
+
const slugRaw = item[schema.primaryKey];
|
|
1364
|
+
if (typeof slugRaw === "string" && slugRaw.length > 0) map[slugRaw] = (0, _mulmoclaude_core_collection.deriveAll)(schema, item, {});
|
|
1365
|
+
}
|
|
1366
|
+
return map;
|
|
1367
|
+
}
|
|
1368
|
+
function buildRefRecordMap(detail) {
|
|
1369
|
+
return derivedRecordsById(detail.collection.schema, detail.items);
|
|
1370
|
+
}
|
|
1371
|
+
function sortedRefOptions(map) {
|
|
1372
|
+
return Object.entries(map).map(([slug, display]) => ({
|
|
1373
|
+
slug,
|
|
1374
|
+
display
|
|
1375
|
+
})).sort((left, right) => left.display.localeCompare(right.display));
|
|
1376
|
+
}
|
|
1377
|
+
/** Dropdown options for an `embed` field's per-record picker: every
|
|
1378
|
+
* record in the target collection, labelled by its name/title (or
|
|
1379
|
+
* primary key), skipping records without a slug and sorted by label. */
|
|
1380
|
+
function buildEmbedOptions(schema, items) {
|
|
1381
|
+
const { fields, primaryKey } = schema;
|
|
1382
|
+
const displayField = displayFieldFor(fields, primaryKey);
|
|
1383
|
+
return items.map((item) => {
|
|
1384
|
+
const slug = String(item[primaryKey] ?? "");
|
|
1385
|
+
const labelRaw = item[displayField];
|
|
1386
|
+
return {
|
|
1387
|
+
slug,
|
|
1388
|
+
display: typeof labelRaw === "string" && labelRaw.length > 0 ? labelRaw : slug
|
|
1389
|
+
};
|
|
1390
|
+
}).filter((opt) => opt.slug.length > 0).sort((left, right) => left.display.localeCompare(right.display));
|
|
1391
|
+
}
|
|
1392
|
+
//#endregion
|
|
1393
|
+
//#region src/vue/components/CollectionMutateParamsModal.vue?vue&type=script&setup=true&lang.ts
|
|
1394
|
+
var _hoisted_1$16 = { class: "flex items-center justify-between px-6 pt-5 pb-3" };
|
|
1395
|
+
var _hoisted_2$15 = { class: "text-sm font-bold text-slate-800 flex items-center gap-1.5" };
|
|
1396
|
+
var _hoisted_3$15 = {
|
|
1397
|
+
key: 0,
|
|
1398
|
+
class: "material-icons text-base text-indigo-600"
|
|
1399
|
+
};
|
|
1400
|
+
var _hoisted_4$15 = ["aria-label"];
|
|
1401
|
+
var _hoisted_5$14 = { class: "flex flex-col gap-4 px-6 pb-2" };
|
|
1402
|
+
var _hoisted_6$13 = ["for"];
|
|
1403
|
+
var _hoisted_7$11 = {
|
|
1404
|
+
key: 0,
|
|
1405
|
+
class: "text-rose-500 font-bold"
|
|
1406
|
+
};
|
|
1407
|
+
var _hoisted_8$11 = {
|
|
1408
|
+
key: 0,
|
|
1409
|
+
class: "inline-flex items-center gap-2.5 cursor-pointer select-none"
|
|
1410
|
+
};
|
|
1411
|
+
var _hoisted_9$11 = [
|
|
1412
|
+
"id",
|
|
1413
|
+
"onUpdate:modelValue",
|
|
1414
|
+
"data-testid",
|
|
1415
|
+
"onChange"
|
|
1416
|
+
];
|
|
1417
|
+
var _hoisted_10$11 = [
|
|
1418
|
+
"id",
|
|
1419
|
+
"onUpdate:modelValue",
|
|
1420
|
+
"required",
|
|
1421
|
+
"data-testid"
|
|
1422
|
+
];
|
|
1423
|
+
var _hoisted_11$11 = { value: "" };
|
|
1424
|
+
var _hoisted_12$10 = ["value"];
|
|
1425
|
+
var _hoisted_13$9 = [
|
|
1426
|
+
"id",
|
|
1427
|
+
"onUpdate:modelValue",
|
|
1428
|
+
"required",
|
|
1429
|
+
"data-testid"
|
|
1430
|
+
];
|
|
1431
|
+
var _hoisted_14$8 = [
|
|
1432
|
+
"id",
|
|
1433
|
+
"onUpdate:modelValue",
|
|
1434
|
+
"type",
|
|
1435
|
+
"step",
|
|
1436
|
+
"required",
|
|
1437
|
+
"data-testid"
|
|
1438
|
+
];
|
|
1439
|
+
var _hoisted_15$8 = {
|
|
1440
|
+
key: 0,
|
|
1441
|
+
class: "text-xs font-semibold text-red-600 bg-red-50 border border-red-100 p-2.5 rounded-xl",
|
|
1442
|
+
"data-testid": "collections-mutate-error"
|
|
1443
|
+
};
|
|
1444
|
+
var _hoisted_16$7 = { class: "flex items-center justify-end gap-2 px-6 py-4" };
|
|
1445
|
+
var _hoisted_17$7 = ["disabled"];
|
|
1446
|
+
var _hoisted_18$6 = {
|
|
1447
|
+
key: 0,
|
|
1448
|
+
class: "material-icons text-sm animate-spin"
|
|
1449
|
+
};
|
|
1450
|
+
//#endregion
|
|
1451
|
+
//#region src/vue/components/CollectionMutateParamsModal.vue
|
|
1452
|
+
var CollectionMutateParamsModal_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
1453
|
+
__name: "CollectionMutateParamsModal",
|
|
1454
|
+
props: {
|
|
1455
|
+
action: {},
|
|
1456
|
+
pending: { type: Boolean },
|
|
1457
|
+
error: {}
|
|
1458
|
+
},
|
|
1459
|
+
emits: ["close", "submit"],
|
|
1460
|
+
setup(__props, { emit: __emit }) {
|
|
1461
|
+
const props = __props;
|
|
1462
|
+
const emit = __emit;
|
|
1463
|
+
const { t } = useCollectionI18n();
|
|
1464
|
+
const text = (0, vue.reactive)({});
|
|
1465
|
+
const bool = (0, vue.reactive)({});
|
|
1466
|
+
const boolTouched = (0, vue.reactive)({});
|
|
1467
|
+
for (const [key, spec] of Object.entries(props.action.params ?? {})) if (spec.type === "boolean") bool[key] = false;
|
|
1468
|
+
else text[key] = "";
|
|
1469
|
+
/** Convert the draft to the submitted params: numbers parsed, booleans
|
|
1470
|
+
* included only when touched or required, empty optionals OMITTED (the
|
|
1471
|
+
* server treats an absent param as "don't write" for `$params` refs —
|
|
1472
|
+
* merge semantics). */
|
|
1473
|
+
function submit() {
|
|
1474
|
+
const params = {};
|
|
1475
|
+
for (const [key, spec] of Object.entries(props.action.params ?? {})) {
|
|
1476
|
+
if (spec.type === "boolean") {
|
|
1477
|
+
if (boolTouched[key] || spec.required) params[key] = bool[key] === true;
|
|
1478
|
+
continue;
|
|
1479
|
+
}
|
|
1480
|
+
const raw = (text[key] ?? "").trim();
|
|
1481
|
+
if (raw === "") continue;
|
|
1482
|
+
if (spec.type === "number" || spec.type === "money") {
|
|
1483
|
+
const num = Number(raw);
|
|
1484
|
+
params[key] = Number.isFinite(num) ? num : raw;
|
|
1485
|
+
continue;
|
|
1486
|
+
}
|
|
1487
|
+
params[key] = raw;
|
|
1488
|
+
}
|
|
1489
|
+
emit("submit", params);
|
|
1490
|
+
}
|
|
1491
|
+
return (_ctx, _cache) => {
|
|
1492
|
+
return (0, vue.openBlock)(), (0, vue.createBlock)(CollectionRecordModal_default, { onClose: _cache[2] || (_cache[2] = ($event) => emit("close")) }, {
|
|
1493
|
+
default: (0, vue.withCtx)(() => [(0, vue.createElementVNode)("form", {
|
|
1494
|
+
class: "flex flex-col overflow-y-auto",
|
|
1495
|
+
"data-testid": "collections-mutate-modal",
|
|
1496
|
+
onSubmit: (0, vue.withModifiers)(submit, ["prevent"])
|
|
1497
|
+
}, [
|
|
1498
|
+
(0, vue.createElementVNode)("div", _hoisted_1$16, [(0, vue.createElementVNode)("h2", _hoisted_2$15, [__props.action.icon ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_3$15, (0, vue.toDisplayString)(__props.action.icon), 1)) : (0, vue.createCommentVNode)("", true), (0, vue.createElementVNode)("span", null, (0, vue.toDisplayString)(__props.action.label), 1)]), (0, vue.createElementVNode)("button", {
|
|
1499
|
+
type: "button",
|
|
1500
|
+
class: "h-8 w-8 flex items-center justify-center rounded text-slate-400 hover:bg-slate-100 hover:text-slate-600 transition-colors",
|
|
1501
|
+
"aria-label": (0, vue.unref)(t)("common.close"),
|
|
1502
|
+
"data-testid": "collections-mutate-close",
|
|
1503
|
+
onClick: _cache[0] || (_cache[0] = ($event) => emit("close"))
|
|
1504
|
+
}, [..._cache[3] || (_cache[3] = [(0, vue.createElementVNode)("span", { class: "material-icons text-lg" }, "close", -1)])], 8, _hoisted_4$15)]),
|
|
1505
|
+
(0, vue.createElementVNode)("div", _hoisted_5$14, [((0, vue.openBlock)(true), (0, vue.createElementBlock)(vue.Fragment, null, (0, vue.renderList)(__props.action.params, (spec, key) => {
|
|
1506
|
+
return (0, vue.openBlock)(), (0, vue.createElementBlock)("div", {
|
|
1507
|
+
key,
|
|
1508
|
+
class: "flex flex-col gap-1.5"
|
|
1509
|
+
}, [(0, vue.createElementVNode)("label", {
|
|
1510
|
+
class: "text-[10px] font-bold text-slate-400 uppercase tracking-wider",
|
|
1511
|
+
for: `collections-mutate-${key}`
|
|
1512
|
+
}, [(0, vue.createTextVNode)((0, vue.toDisplayString)(spec.label) + " ", 1), spec.required ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_7$11, "*")) : (0, vue.createCommentVNode)("", true)], 8, _hoisted_6$13), spec.type === "boolean" ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("label", _hoisted_8$11, [(0, vue.withDirectives)((0, vue.createElementVNode)("input", {
|
|
1513
|
+
id: `collections-mutate-${key}`,
|
|
1514
|
+
"onUpdate:modelValue": ($event) => bool[key] = $event,
|
|
1515
|
+
type: "checkbox",
|
|
1516
|
+
class: "h-5 w-5 rounded border-slate-300 text-indigo-600 focus:ring-indigo-500/20 cursor-pointer",
|
|
1517
|
+
"data-testid": `collections-mutate-input-${key}`,
|
|
1518
|
+
onChange: ($event) => boolTouched[String(key)] = true
|
|
1519
|
+
}, null, 40, _hoisted_9$11), [[vue.vModelCheckbox, bool[key]]]), (0, vue.createElementVNode)("span", { class: (0, vue.normalizeClass)(["text-xs font-semibold", bool[key] ? "text-indigo-600" : "text-slate-500"]) }, (0, vue.toDisplayString)(bool[key] ? (0, vue.unref)(t)("common.yes") : (0, vue.unref)(t)("common.no")), 3)])) : spec.type === "enum" ? (0, vue.withDirectives)(((0, vue.openBlock)(), (0, vue.createElementBlock)("select", {
|
|
1520
|
+
key: 1,
|
|
1521
|
+
id: `collections-mutate-${key}`,
|
|
1522
|
+
"onUpdate:modelValue": ($event) => text[key] = $event,
|
|
1523
|
+
required: spec.required,
|
|
1524
|
+
class: "w-full rounded-xl border border-slate-200 px-3 py-2 text-xs bg-slate-50 focus:bg-white focus:border-indigo-500 focus:ring-2 focus:ring-indigo-500/20 focus:outline-none transition-all cursor-pointer font-medium text-slate-700",
|
|
1525
|
+
"data-testid": `collections-mutate-input-${key}`
|
|
1526
|
+
}, [(0, vue.createElementVNode)("option", _hoisted_11$11, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.selectPlaceholder")), 1), ((0, vue.openBlock)(true), (0, vue.createElementBlock)(vue.Fragment, null, (0, vue.renderList)(spec.values, (value) => {
|
|
1527
|
+
return (0, vue.openBlock)(), (0, vue.createElementBlock)("option", {
|
|
1528
|
+
key: value,
|
|
1529
|
+
value
|
|
1530
|
+
}, (0, vue.toDisplayString)(value), 9, _hoisted_12$10);
|
|
1531
|
+
}), 128))], 8, _hoisted_10$11)), [[vue.vModelSelect, text[key]]]) : spec.type === "text" || spec.type === "markdown" ? (0, vue.withDirectives)(((0, vue.openBlock)(), (0, vue.createElementBlock)("textarea", {
|
|
1532
|
+
key: 2,
|
|
1533
|
+
id: `collections-mutate-${key}`,
|
|
1534
|
+
"onUpdate:modelValue": ($event) => text[key] = $event,
|
|
1535
|
+
required: spec.required,
|
|
1536
|
+
rows: "3",
|
|
1537
|
+
class: "w-full rounded-xl border border-slate-200 px-3 py-2 text-xs focus:border-indigo-500 focus:ring-2 focus:ring-indigo-500/20 focus:outline-none font-medium text-slate-700 transition-all",
|
|
1538
|
+
"data-testid": `collections-mutate-input-${key}`
|
|
1539
|
+
}, null, 8, _hoisted_13$9)), [[vue.vModelText, text[key]]]) : (0, vue.withDirectives)(((0, vue.openBlock)(), (0, vue.createElementBlock)("input", {
|
|
1540
|
+
key: 3,
|
|
1541
|
+
id: `collections-mutate-${key}`,
|
|
1542
|
+
"onUpdate:modelValue": ($event) => text[key] = $event,
|
|
1543
|
+
type: (0, vue.unref)(inputTypeFor)(spec.type),
|
|
1544
|
+
step: (0, vue.unref)(stepForFieldType)(spec.type),
|
|
1545
|
+
required: spec.required,
|
|
1546
|
+
class: "w-full rounded-xl border border-slate-200 px-3 py-2 text-xs focus:border-indigo-500 focus:ring-2 focus:ring-indigo-500/20 focus:outline-none font-medium text-slate-700 transition-all",
|
|
1547
|
+
"data-testid": `collections-mutate-input-${key}`
|
|
1548
|
+
}, null, 8, _hoisted_14$8)), [[vue.vModelDynamic, text[key]]])]);
|
|
1549
|
+
}), 128)), __props.error ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("p", _hoisted_15$8, (0, vue.toDisplayString)(__props.error), 1)) : (0, vue.createCommentVNode)("", true)]),
|
|
1550
|
+
(0, vue.createElementVNode)("div", _hoisted_16$7, [(0, vue.createElementVNode)("button", {
|
|
1551
|
+
type: "button",
|
|
1552
|
+
class: "h-8 px-3 rounded border border-slate-200 bg-white text-slate-600 hover:bg-slate-50 font-bold text-xs transition-colors",
|
|
1553
|
+
"data-testid": "collections-mutate-cancel",
|
|
1554
|
+
onClick: _cache[1] || (_cache[1] = ($event) => emit("close"))
|
|
1555
|
+
}, (0, vue.toDisplayString)((0, vue.unref)(t)("common.cancel")), 1), (0, vue.createElementVNode)("button", {
|
|
1556
|
+
type: "submit",
|
|
1557
|
+
class: "h-8 px-3 rounded bg-indigo-600 hover:bg-indigo-700 text-white font-bold text-xs transition-colors shadow-sm disabled:opacity-50 flex items-center gap-1",
|
|
1558
|
+
disabled: __props.pending,
|
|
1559
|
+
"data-testid": "collections-mutate-submit"
|
|
1560
|
+
}, [__props.pending ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_18$6, "progress_activity")) : (0, vue.createCommentVNode)("", true), (0, vue.createElementVNode)("span", null, (0, vue.toDisplayString)(__props.action.label), 1)], 8, _hoisted_17$7)])
|
|
1561
|
+
], 32)]),
|
|
1562
|
+
_: 1
|
|
1563
|
+
});
|
|
1564
|
+
};
|
|
1565
|
+
}
|
|
1566
|
+
});
|
|
1567
|
+
//#endregion
|
|
1236
1568
|
//#region src/vue/components/CollectionCalendarView.vue?vue&type=script&setup=true&lang.ts
|
|
1237
|
-
var _hoisted_1$
|
|
1569
|
+
var _hoisted_1$15 = {
|
|
1238
1570
|
class: "flex flex-col gap-3",
|
|
1239
1571
|
"data-testid": "collection-calendar"
|
|
1240
1572
|
};
|
|
1241
|
-
var _hoisted_2$
|
|
1242
|
-
var _hoisted_3$
|
|
1243
|
-
var _hoisted_4$
|
|
1244
|
-
var _hoisted_5$
|
|
1573
|
+
var _hoisted_2$14 = { class: "flex items-center gap-2" };
|
|
1574
|
+
var _hoisted_3$14 = ["aria-label"];
|
|
1575
|
+
var _hoisted_4$14 = ["aria-label"];
|
|
1576
|
+
var _hoisted_5$13 = {
|
|
1245
1577
|
class: "text-sm font-bold text-slate-800 flex-1",
|
|
1246
1578
|
"data-testid": "collection-calendar-month"
|
|
1247
1579
|
};
|
|
1248
|
-
var _hoisted_6$
|
|
1580
|
+
var _hoisted_6$12 = { class: "grid grid-cols-7 gap-1 text-[10px] font-bold text-slate-400 uppercase tracking-wider select-none" };
|
|
1249
1581
|
var _hoisted_7$10 = { class: "grid grid-cols-7 gap-1" };
|
|
1250
1582
|
var _hoisted_8$10 = [
|
|
1251
1583
|
"aria-label",
|
|
@@ -1375,23 +1707,23 @@ var CollectionCalendarView_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
1375
1707
|
viewMonth.value = now.getMonth() + 1;
|
|
1376
1708
|
}
|
|
1377
1709
|
return (_ctx, _cache) => {
|
|
1378
|
-
return (0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_1$
|
|
1379
|
-
(0, vue.createElementVNode)("div", _hoisted_2$
|
|
1710
|
+
return (0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_1$15, [
|
|
1711
|
+
(0, vue.createElementVNode)("div", _hoisted_2$14, [
|
|
1380
1712
|
(0, vue.createElementVNode)("button", {
|
|
1381
1713
|
type: "button",
|
|
1382
1714
|
class: "h-8 w-8 flex items-center justify-center rounded text-slate-500 hover:bg-slate-100 transition-colors",
|
|
1383
1715
|
"aria-label": (0, vue.unref)(t)("collectionsView.calendarPrevMonth"),
|
|
1384
1716
|
"data-testid": "collection-calendar-prev",
|
|
1385
1717
|
onClick: _cache[0] || (_cache[0] = ($event) => stepMonth(-1))
|
|
1386
|
-
}, [..._cache[2] || (_cache[2] = [(0, vue.createElementVNode)("span", { class: "material-icons text-lg" }, "chevron_left", -1)])], 8, _hoisted_3$
|
|
1718
|
+
}, [..._cache[2] || (_cache[2] = [(0, vue.createElementVNode)("span", { class: "material-icons text-lg" }, "chevron_left", -1)])], 8, _hoisted_3$14),
|
|
1387
1719
|
(0, vue.createElementVNode)("button", {
|
|
1388
1720
|
type: "button",
|
|
1389
1721
|
class: "h-8 w-8 flex items-center justify-center rounded text-slate-500 hover:bg-slate-100 transition-colors",
|
|
1390
1722
|
"aria-label": (0, vue.unref)(t)("collectionsView.calendarNextMonth"),
|
|
1391
1723
|
"data-testid": "collection-calendar-next",
|
|
1392
1724
|
onClick: _cache[1] || (_cache[1] = ($event) => stepMonth(1))
|
|
1393
|
-
}, [..._cache[3] || (_cache[3] = [(0, vue.createElementVNode)("span", { class: "material-icons text-lg" }, "chevron_right", -1)])], 8, _hoisted_4$
|
|
1394
|
-
(0, vue.createElementVNode)("h3", _hoisted_5$
|
|
1725
|
+
}, [..._cache[3] || (_cache[3] = [(0, vue.createElementVNode)("span", { class: "material-icons text-lg" }, "chevron_right", -1)])], 8, _hoisted_4$14),
|
|
1726
|
+
(0, vue.createElementVNode)("h3", _hoisted_5$13, (0, vue.toDisplayString)(monthLabel.value), 1),
|
|
1395
1727
|
(0, vue.createElementVNode)("button", {
|
|
1396
1728
|
type: "button",
|
|
1397
1729
|
class: "h-8 px-2.5 flex items-center gap-1 rounded border border-slate-200 bg-white text-slate-600 hover:bg-slate-50 text-xs font-bold transition-colors",
|
|
@@ -1399,7 +1731,7 @@ var CollectionCalendarView_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
1399
1731
|
onClick: goToday
|
|
1400
1732
|
}, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.calendarToday")), 1)
|
|
1401
1733
|
]),
|
|
1402
|
-
(0, vue.createElementVNode)("div", _hoisted_6$
|
|
1734
|
+
(0, vue.createElementVNode)("div", _hoisted_6$12, [((0, vue.openBlock)(true), (0, vue.createElementBlock)(vue.Fragment, null, (0, vue.renderList)(weekdayLabels.value, (label, idx) => {
|
|
1403
1735
|
return (0, vue.openBlock)(), (0, vue.createElementBlock)("div", {
|
|
1404
1736
|
key: idx,
|
|
1405
1737
|
class: "px-1 py-1 text-center"
|
|
@@ -1440,18 +1772,18 @@ var CollectionCalendarView_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
1440
1772
|
});
|
|
1441
1773
|
//#endregion
|
|
1442
1774
|
//#region src/vue/components/CollectionDayView.vue?vue&type=script&setup=true&lang.ts
|
|
1443
|
-
var _hoisted_1$
|
|
1444
|
-
var _hoisted_2$
|
|
1775
|
+
var _hoisted_1$14 = { class: "flex items-center gap-2 border-b border-slate-200 px-4 py-3" };
|
|
1776
|
+
var _hoisted_2$13 = {
|
|
1445
1777
|
class: "flex-1 text-sm font-bold text-slate-800",
|
|
1446
1778
|
"data-testid": "collection-day-view-title"
|
|
1447
1779
|
};
|
|
1448
|
-
var _hoisted_3$
|
|
1449
|
-
var _hoisted_4$
|
|
1450
|
-
var _hoisted_5$
|
|
1780
|
+
var _hoisted_3$13 = ["aria-label"];
|
|
1781
|
+
var _hoisted_4$13 = ["aria-label"];
|
|
1782
|
+
var _hoisted_5$12 = {
|
|
1451
1783
|
key: 0,
|
|
1452
1784
|
class: "px-4 py-10 text-center text-sm text-slate-400"
|
|
1453
1785
|
};
|
|
1454
|
-
var _hoisted_6$
|
|
1786
|
+
var _hoisted_6$11 = { class: "absolute -top-2 left-0 w-10 pr-1 text-right text-[10px] tabular-nums text-slate-400" };
|
|
1455
1787
|
var _hoisted_7$9 = {
|
|
1456
1788
|
class: "absolute inset-y-0 right-0",
|
|
1457
1789
|
style: { "left": "2.75rem" }
|
|
@@ -1537,6 +1869,8 @@ var CollectionDayView_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
1537
1869
|
"datetime",
|
|
1538
1870
|
"table",
|
|
1539
1871
|
"embed",
|
|
1872
|
+
"backlinks",
|
|
1873
|
+
"rollup",
|
|
1540
1874
|
"image",
|
|
1541
1875
|
"markdown"
|
|
1542
1876
|
]);
|
|
@@ -1632,8 +1966,8 @@ var CollectionDayView_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
1632
1966
|
role: "dialog",
|
|
1633
1967
|
"aria-modal": "true"
|
|
1634
1968
|
}, [(0, vue.createElementVNode)("div", { class: (0, vue.normalizeClass)(["flex min-h-0 flex-col", __props.showDetail ? "w-80 shrink-0 border-r border-slate-200" : "w-full"]) }, [
|
|
1635
|
-
(0, vue.createElementVNode)("div", _hoisted_1$
|
|
1636
|
-
(0, vue.createElementVNode)("h3", _hoisted_2$
|
|
1969
|
+
(0, vue.createElementVNode)("div", _hoisted_1$14, [
|
|
1970
|
+
(0, vue.createElementVNode)("h3", _hoisted_2$13, (0, vue.toDisplayString)(dayLabel.value), 1),
|
|
1637
1971
|
__props.canCreate ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("button", {
|
|
1638
1972
|
key: 0,
|
|
1639
1973
|
type: "button",
|
|
@@ -1641,16 +1975,16 @@ var CollectionDayView_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
1641
1975
|
"aria-label": (0, vue.unref)(t)("collectionsView.calendarCreateOn", { date: dayKey.value }),
|
|
1642
1976
|
"data-testid": "collection-day-view-create",
|
|
1643
1977
|
onClick: onCreate
|
|
1644
|
-
}, [..._cache[3] || (_cache[3] = [(0, vue.createElementVNode)("span", { class: "material-icons text-lg" }, "add", -1)])], 8, _hoisted_3$
|
|
1978
|
+
}, [..._cache[3] || (_cache[3] = [(0, vue.createElementVNode)("span", { class: "material-icons text-lg" }, "add", -1)])], 8, _hoisted_3$13)) : (0, vue.createCommentVNode)("", true),
|
|
1645
1979
|
(0, vue.createElementVNode)("button", {
|
|
1646
1980
|
type: "button",
|
|
1647
1981
|
class: "h-8 w-8 flex items-center justify-center rounded text-slate-500 hover:bg-slate-100 transition-colors",
|
|
1648
1982
|
"aria-label": (0, vue.unref)(t)("collectionsView.dayViewClose"),
|
|
1649
1983
|
"data-testid": "collection-day-view-close",
|
|
1650
1984
|
onClick: _cache[0] || (_cache[0] = ($event) => emit("close"))
|
|
1651
|
-
}, [..._cache[4] || (_cache[4] = [(0, vue.createElementVNode)("span", { class: "material-icons text-lg" }, "close", -1)])], 8, _hoisted_4$
|
|
1985
|
+
}, [..._cache[4] || (_cache[4] = [(0, vue.createElementVNode)("span", { class: "material-icons text-lg" }, "close", -1)])], 8, _hoisted_4$13)
|
|
1652
1986
|
]),
|
|
1653
|
-
timedEntries.value.length === 0 && allDayEntries.value.length === 0 ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_5$
|
|
1987
|
+
timedEntries.value.length === 0 && allDayEntries.value.length === 0 ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_5$12, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.dayViewEmpty")), 1)) : ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", {
|
|
1654
1988
|
key: 1,
|
|
1655
1989
|
ref_key: "scrollEl",
|
|
1656
1990
|
ref: scrollEl,
|
|
@@ -1664,7 +1998,7 @@ var CollectionDayView_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
1664
1998
|
key: hour,
|
|
1665
1999
|
class: "absolute left-0 right-0 border-t border-slate-100",
|
|
1666
2000
|
style: (0, vue.normalizeStyle)({ top: `${(hour - 1) * HOUR_PX}px` })
|
|
1667
|
-
}, [(0, vue.createElementVNode)("span", _hoisted_6$
|
|
2001
|
+
}, [(0, vue.createElementVNode)("span", _hoisted_6$11, (0, vue.toDisplayString)(hourLabel(hour - 1)), 1)], 4);
|
|
1668
2002
|
}), 64)), (0, vue.createElementVNode)("div", _hoisted_7$9, [((0, vue.openBlock)(true), (0, vue.createElementBlock)(vue.Fragment, null, (0, vue.renderList)(timedEntries.value, (entry) => {
|
|
1669
2003
|
return (0, vue.openBlock)(), (0, vue.createElementBlock)("button", {
|
|
1670
2004
|
key: entry.id,
|
|
@@ -1699,15 +2033,15 @@ var CollectionDayView_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
1699
2033
|
});
|
|
1700
2034
|
//#endregion
|
|
1701
2035
|
//#region src/vue/components/CollectionKanbanView.vue?vue&type=script&setup=true&lang.ts
|
|
1702
|
-
var _hoisted_1$
|
|
2036
|
+
var _hoisted_1$13 = {
|
|
1703
2037
|
class: "h-full overflow-x-auto overflow-y-hidden",
|
|
1704
2038
|
"data-testid": "collection-kanban"
|
|
1705
2039
|
};
|
|
1706
|
-
var _hoisted_2$
|
|
1707
|
-
var _hoisted_3$
|
|
1708
|
-
var _hoisted_4$
|
|
1709
|
-
var _hoisted_5$
|
|
1710
|
-
var _hoisted_6$
|
|
2040
|
+
var _hoisted_2$12 = { class: "flex gap-3 h-full p-1 min-w-max" };
|
|
2041
|
+
var _hoisted_3$12 = ["data-testid"];
|
|
2042
|
+
var _hoisted_4$12 = { class: "flex items-center justify-between px-3 py-2 border-b border-slate-200" };
|
|
2043
|
+
var _hoisted_5$11 = { class: "flex items-center gap-2 min-w-0" };
|
|
2044
|
+
var _hoisted_6$10 = ["title"];
|
|
1711
2045
|
var _hoisted_7$8 = { class: "text-[11px] text-slate-400 shrink-0" };
|
|
1712
2046
|
var _hoisted_8$8 = [
|
|
1713
2047
|
"data-testid",
|
|
@@ -1826,15 +2160,15 @@ var CollectionKanbanView_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
1826
2160
|
emit("move", itemId(item), next);
|
|
1827
2161
|
}
|
|
1828
2162
|
return (_ctx, _cache) => {
|
|
1829
|
-
return (0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_1$
|
|
2163
|
+
return (0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_1$13, [(0, vue.createElementVNode)("div", _hoisted_2$12, [((0, vue.openBlock)(true), (0, vue.createElementBlock)(vue.Fragment, null, (0, vue.renderList)(columns.value, (column) => {
|
|
1830
2164
|
return (0, vue.openBlock)(), (0, vue.createElementBlock)("div", {
|
|
1831
2165
|
key: column.value,
|
|
1832
2166
|
"data-testid": `collection-kanban-column-${column.value || "uncategorized"}`,
|
|
1833
2167
|
class: "w-72 shrink-0 flex flex-col bg-slate-100 rounded-lg"
|
|
1834
|
-
}, [(0, vue.createElementVNode)("div", _hoisted_4$
|
|
2168
|
+
}, [(0, vue.createElementVNode)("div", _hoisted_4$12, [(0, vue.createElementVNode)("div", _hoisted_5$11, [(0, vue.createElementVNode)("span", { class: (0, vue.normalizeClass)(["w-2 h-2 rounded-full shrink-0", (0, vue.unref)(_mulmoclaude_core_collection.resolveEnumColor)(__props.schema, __props.groupField, column.value).dot]) }, null, 2), (0, vue.createElementVNode)("span", {
|
|
1835
2169
|
class: "font-semibold text-xs text-slate-600 truncate",
|
|
1836
2170
|
title: column.label
|
|
1837
|
-
}, (0, vue.toDisplayString)(column.label), 9, _hoisted_6$
|
|
2171
|
+
}, (0, vue.toDisplayString)(column.label), 9, _hoisted_6$10)]), (0, vue.createElementVNode)("span", _hoisted_7$8, (0, vue.toDisplayString)(itemsByColumn(column.value).length), 1)]), (0, vue.createVNode)((0, vue.unref)(vuedraggable.default), {
|
|
1838
2172
|
"model-value": itemsByColumn(column.value),
|
|
1839
2173
|
"item-key": __props.schema.primaryKey,
|
|
1840
2174
|
group: "collection-kanban-cards",
|
|
@@ -1865,7 +2199,7 @@ var CollectionKanbanView_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
1865
2199
|
"model-value",
|
|
1866
2200
|
"item-key",
|
|
1867
2201
|
"onChange"
|
|
1868
|
-
])], 8, _hoisted_3$
|
|
2202
|
+
])], 8, _hoisted_3$12);
|
|
1869
2203
|
}), 128))])]);
|
|
1870
2204
|
};
|
|
1871
2205
|
}
|
|
@@ -1894,6 +2228,61 @@ function activatePathLink(event, path, stop = false) {
|
|
|
1894
2228
|
nav(path);
|
|
1895
2229
|
}
|
|
1896
2230
|
//#endregion
|
|
2231
|
+
//#region src/vue/components/CollectionBacklinksView.vue?vue&type=script&setup=true&lang.ts
|
|
2232
|
+
var _hoisted_1$12 = ["data-testid"];
|
|
2233
|
+
var _hoisted_2$11 = { class: "w-full text-[11px] text-slate-600 bg-white" };
|
|
2234
|
+
var _hoisted_3$11 = { class: "bg-slate-50 border-b border-slate-200 text-slate-500 font-bold uppercase tracking-wider" };
|
|
2235
|
+
var _hoisted_4$11 = { class: "divide-y divide-slate-100" };
|
|
2236
|
+
var _hoisted_5$10 = [
|
|
2237
|
+
"data-testid",
|
|
2238
|
+
"onClick",
|
|
2239
|
+
"onKeydown"
|
|
2240
|
+
];
|
|
2241
|
+
var _hoisted_6$9 = ["data-testid"];
|
|
2242
|
+
//#endregion
|
|
2243
|
+
//#region src/vue/components/CollectionBacklinksView.vue
|
|
2244
|
+
var CollectionBacklinksView_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
2245
|
+
__name: "CollectionBacklinksView",
|
|
2246
|
+
props: {
|
|
2247
|
+
view: {},
|
|
2248
|
+
fieldKey: {}
|
|
2249
|
+
},
|
|
2250
|
+
setup(__props) {
|
|
2251
|
+
const { t } = useCollectionI18n();
|
|
2252
|
+
return (_ctx, _cache) => {
|
|
2253
|
+
return __props.view.rows.length > 0 ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", {
|
|
2254
|
+
key: 0,
|
|
2255
|
+
class: "border border-slate-200/80 rounded-xl overflow-hidden shadow-sm mt-1",
|
|
2256
|
+
"data-testid": `collections-backlinks-${__props.fieldKey}`
|
|
2257
|
+
}, [(0, vue.createElementVNode)("table", _hoisted_2$11, [(0, vue.createElementVNode)("thead", _hoisted_3$11, [(0, vue.createElementVNode)("tr", null, [((0, vue.openBlock)(true), (0, vue.createElementBlock)(vue.Fragment, null, (0, vue.renderList)(__props.view.columns, (column) => {
|
|
2258
|
+
return (0, vue.openBlock)(), (0, vue.createElementBlock)("th", {
|
|
2259
|
+
key: column.key,
|
|
2260
|
+
class: "text-left px-4 py-2 font-bold"
|
|
2261
|
+
}, (0, vue.toDisplayString)(column.label), 1);
|
|
2262
|
+
}), 128))])]), (0, vue.createElementVNode)("tbody", _hoisted_4$11, [((0, vue.openBlock)(true), (0, vue.createElementBlock)(vue.Fragment, null, (0, vue.renderList)(__props.view.rows, (row) => {
|
|
2263
|
+
return (0, vue.openBlock)(), (0, vue.createElementBlock)("tr", {
|
|
2264
|
+
key: row.id,
|
|
2265
|
+
class: "group hover:bg-indigo-50/30 cursor-pointer transition-colors",
|
|
2266
|
+
role: "link",
|
|
2267
|
+
tabindex: "0",
|
|
2268
|
+
"data-testid": `collections-backlinks-${__props.fieldKey}-${row.id}`,
|
|
2269
|
+
onClick: ($event) => (0, vue.unref)(activateRefLink)($event, __props.view.fromSlug, row.id),
|
|
2270
|
+
onKeydown: [(0, vue.withKeys)(($event) => (0, vue.unref)(activateRefLink)($event, __props.view.fromSlug, row.id), ["enter"]), (0, vue.withKeys)(($event) => (0, vue.unref)(activateRefLink)($event, __props.view.fromSlug, row.id), ["space"])]
|
|
2271
|
+
}, [((0, vue.openBlock)(true), (0, vue.createElementBlock)(vue.Fragment, null, (0, vue.renderList)(row.cells, (cell, cellIdx) => {
|
|
2272
|
+
return (0, vue.openBlock)(), (0, vue.createElementBlock)("td", {
|
|
2273
|
+
key: __props.view.columns[cellIdx]?.key ?? cellIdx,
|
|
2274
|
+
class: "px-4 py-2 align-middle font-medium"
|
|
2275
|
+
}, [(0, vue.createElementVNode)("span", { class: (0, vue.normalizeClass)(cellIdx === 0 ? "text-indigo-600 group-hover:text-indigo-800 font-bold" : "") }, (0, vue.toDisplayString)(cell), 3)]);
|
|
2276
|
+
}), 128))], 40, _hoisted_5$10);
|
|
2277
|
+
}), 128))])])], 8, _hoisted_1$12)) : ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", {
|
|
2278
|
+
key: 1,
|
|
2279
|
+
class: "text-slate-400 italic",
|
|
2280
|
+
"data-testid": `collections-backlinks-${__props.fieldKey}`
|
|
2281
|
+
}, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.noRows")), 9, _hoisted_6$9));
|
|
2282
|
+
};
|
|
2283
|
+
}
|
|
2284
|
+
});
|
|
2285
|
+
//#endregion
|
|
1897
2286
|
//#region src/vue/components/CollectionEmbedView.vue?vue&type=script&setup=true&lang.ts
|
|
1898
2287
|
var _hoisted_1$11 = [
|
|
1899
2288
|
"href",
|
|
@@ -2002,111 +2391,115 @@ var _hoisted_7$6 = [
|
|
|
2002
2391
|
];
|
|
2003
2392
|
var _hoisted_8$6 = {
|
|
2004
2393
|
key: 0,
|
|
2394
|
+
class: "material-icons text-sm animate-spin"
|
|
2395
|
+
};
|
|
2396
|
+
var _hoisted_9$6 = {
|
|
2397
|
+
key: 1,
|
|
2005
2398
|
class: "material-icons text-sm"
|
|
2006
2399
|
};
|
|
2007
|
-
var
|
|
2008
|
-
var
|
|
2400
|
+
var _hoisted_10$6 = ["aria-label"];
|
|
2401
|
+
var _hoisted_11$6 = {
|
|
2009
2402
|
key: 0,
|
|
2010
2403
|
class: "mb-3 text-xs font-semibold text-red-600 bg-red-50 border border-red-100 p-2.5 rounded-xl shadow-sm",
|
|
2011
2404
|
"data-testid": "collections-detail-action-error"
|
|
2012
2405
|
};
|
|
2013
|
-
var
|
|
2014
|
-
var
|
|
2015
|
-
var
|
|
2406
|
+
var _hoisted_12$6 = { class: "grid grid-cols-1 sm:grid-cols-2 gap-x-6 gap-y-4 bg-white rounded-2xl border border-slate-200/60 p-6 shadow-sm" };
|
|
2407
|
+
var _hoisted_13$5 = ["for"];
|
|
2408
|
+
var _hoisted_14$5 = {
|
|
2016
2409
|
key: 0,
|
|
2017
2410
|
class: "text-rose-500 font-bold"
|
|
2018
2411
|
};
|
|
2019
|
-
var
|
|
2412
|
+
var _hoisted_15$5 = [
|
|
2020
2413
|
"id",
|
|
2021
2414
|
"onUpdate:modelValue",
|
|
2022
2415
|
"required",
|
|
2023
2416
|
"data-testid"
|
|
2024
2417
|
];
|
|
2025
|
-
var
|
|
2026
|
-
var
|
|
2027
|
-
var
|
|
2418
|
+
var _hoisted_16$5 = { value: "" };
|
|
2419
|
+
var _hoisted_17$5 = ["value"];
|
|
2420
|
+
var _hoisted_18$5 = [
|
|
2028
2421
|
"id",
|
|
2029
2422
|
"onUpdate:modelValue",
|
|
2030
2423
|
"required",
|
|
2031
2424
|
"placeholder",
|
|
2032
2425
|
"data-testid"
|
|
2033
2426
|
];
|
|
2034
|
-
var
|
|
2427
|
+
var _hoisted_19$3 = {
|
|
2035
2428
|
key: 0,
|
|
2036
2429
|
class: "inline-flex items-center gap-2.5 text-sm text-slate-700 cursor-pointer select-none"
|
|
2037
2430
|
};
|
|
2038
|
-
var
|
|
2431
|
+
var _hoisted_20$3 = [
|
|
2039
2432
|
"id",
|
|
2040
2433
|
"onUpdate:modelValue",
|
|
2041
2434
|
"data-testid",
|
|
2042
2435
|
"onChange"
|
|
2043
2436
|
];
|
|
2044
|
-
var
|
|
2437
|
+
var _hoisted_21$3 = [
|
|
2045
2438
|
"id",
|
|
2046
2439
|
"onUpdate:modelValue",
|
|
2047
2440
|
"required",
|
|
2048
2441
|
"data-testid"
|
|
2049
2442
|
];
|
|
2050
|
-
var
|
|
2051
|
-
var
|
|
2052
|
-
var
|
|
2443
|
+
var _hoisted_22$3 = { value: "" };
|
|
2444
|
+
var _hoisted_23$3 = ["value"];
|
|
2445
|
+
var _hoisted_24$2 = [
|
|
2053
2446
|
"id",
|
|
2054
2447
|
"onUpdate:modelValue",
|
|
2055
2448
|
"required",
|
|
2056
2449
|
"data-testid"
|
|
2057
2450
|
];
|
|
2058
|
-
var
|
|
2059
|
-
var
|
|
2060
|
-
var
|
|
2061
|
-
var
|
|
2451
|
+
var _hoisted_25$2 = { value: "" };
|
|
2452
|
+
var _hoisted_26$2 = ["value"];
|
|
2453
|
+
var _hoisted_27$2 = ["data-testid"];
|
|
2454
|
+
var _hoisted_28$1 = {
|
|
2062
2455
|
key: 0,
|
|
2063
2456
|
class: "overflow-hidden border border-slate-200 rounded-lg shadow-sm"
|
|
2064
2457
|
};
|
|
2065
|
-
var
|
|
2066
|
-
var
|
|
2067
|
-
var
|
|
2068
|
-
var
|
|
2069
|
-
var
|
|
2070
|
-
var
|
|
2071
|
-
var
|
|
2072
|
-
var
|
|
2073
|
-
var
|
|
2074
|
-
var
|
|
2075
|
-
var
|
|
2458
|
+
var _hoisted_29$1 = { class: "w-full text-xs text-slate-600 bg-white" };
|
|
2459
|
+
var _hoisted_30$1 = { class: "bg-slate-50 border-b border-slate-200 text-slate-500 font-bold uppercase tracking-wider" };
|
|
2460
|
+
var _hoisted_31$1 = { class: "divide-y divide-slate-100" };
|
|
2461
|
+
var _hoisted_32$1 = ["onUpdate:modelValue", "onChange"];
|
|
2462
|
+
var _hoisted_33$1 = ["onUpdate:modelValue", "required"];
|
|
2463
|
+
var _hoisted_34$1 = { value: "" };
|
|
2464
|
+
var _hoisted_35$1 = ["value"];
|
|
2465
|
+
var _hoisted_36$1 = ["onUpdate:modelValue", "required"];
|
|
2466
|
+
var _hoisted_37$1 = { value: "" };
|
|
2467
|
+
var _hoisted_38$1 = ["value"];
|
|
2468
|
+
var _hoisted_39$1 = {
|
|
2076
2469
|
key: 3,
|
|
2077
2470
|
class: "relative flex items-center"
|
|
2078
2471
|
};
|
|
2079
|
-
var
|
|
2080
|
-
var
|
|
2081
|
-
var
|
|
2472
|
+
var _hoisted_40$1 = { class: "absolute left-1.5 text-[10px] text-slate-400 font-bold pr-1 border-r border-slate-200" };
|
|
2473
|
+
var _hoisted_41$1 = ["onUpdate:modelValue", "required"];
|
|
2474
|
+
var _hoisted_42$1 = [
|
|
2082
2475
|
"onUpdate:modelValue",
|
|
2083
2476
|
"type",
|
|
2084
2477
|
"step",
|
|
2085
2478
|
"required"
|
|
2086
2479
|
];
|
|
2087
|
-
var
|
|
2088
|
-
var
|
|
2480
|
+
var _hoisted_43$1 = { class: "text-center px-1" };
|
|
2481
|
+
var _hoisted_44$1 = [
|
|
2089
2482
|
"aria-label",
|
|
2090
2483
|
"data-testid",
|
|
2091
2484
|
"onClick"
|
|
2092
2485
|
];
|
|
2093
|
-
var
|
|
2486
|
+
var _hoisted_45$1 = {
|
|
2094
2487
|
key: 1,
|
|
2095
2488
|
class: "text-xs text-slate-400 italic"
|
|
2096
2489
|
};
|
|
2097
|
-
var
|
|
2098
|
-
var
|
|
2490
|
+
var _hoisted_46$1 = ["data-testid", "onClick"];
|
|
2491
|
+
var _hoisted_47$1 = {
|
|
2099
2492
|
key: 4,
|
|
2100
2493
|
class: "relative flex items-center"
|
|
2101
2494
|
};
|
|
2102
|
-
var
|
|
2103
|
-
var
|
|
2495
|
+
var _hoisted_48$1 = { class: "absolute left-3 text-slate-400 font-bold text-xs select-none pr-1.5 border-r border-slate-200" };
|
|
2496
|
+
var _hoisted_49$1 = [
|
|
2104
2497
|
"id",
|
|
2105
2498
|
"onUpdate:modelValue",
|
|
2106
2499
|
"required",
|
|
2107
2500
|
"data-testid"
|
|
2108
2501
|
];
|
|
2109
|
-
var
|
|
2502
|
+
var _hoisted_50$1 = [
|
|
2110
2503
|
"id",
|
|
2111
2504
|
"onUpdate:modelValue",
|
|
2112
2505
|
"type",
|
|
@@ -2115,104 +2508,105 @@ var _hoisted_49$1 = [
|
|
|
2115
2508
|
"disabled",
|
|
2116
2509
|
"data-testid"
|
|
2117
2510
|
];
|
|
2118
|
-
var
|
|
2511
|
+
var _hoisted_51$1 = [
|
|
2119
2512
|
"id",
|
|
2120
2513
|
"onUpdate:modelValue",
|
|
2121
2514
|
"rows",
|
|
2122
2515
|
"required",
|
|
2123
2516
|
"data-testid"
|
|
2124
2517
|
];
|
|
2125
|
-
var
|
|
2126
|
-
var
|
|
2518
|
+
var _hoisted_52$1 = ["data-testid"];
|
|
2519
|
+
var _hoisted_53$1 = {
|
|
2127
2520
|
key: 0,
|
|
2128
2521
|
class: "inline-flex items-center gap-1 px-2 py-0.5 rounded-full text-[10px] font-semibold bg-emerald-50 text-emerald-700 border border-emerald-200/40"
|
|
2129
2522
|
};
|
|
2130
|
-
var
|
|
2523
|
+
var _hoisted_54$1 = {
|
|
2131
2524
|
key: 1,
|
|
2132
2525
|
class: "inline-flex items-center gap-1 px-2 py-0.5 rounded-full text-[10px] font-semibold bg-slate-50 text-slate-400 border border-slate-200/20"
|
|
2133
2526
|
};
|
|
2134
|
-
var
|
|
2527
|
+
var _hoisted_55$1 = {
|
|
2135
2528
|
key: 0,
|
|
2136
2529
|
class: "inline-flex items-center gap-1 px-2 py-0.5 rounded-full text-[10px] font-semibold bg-emerald-50 text-emerald-700 border border-emerald-200/40"
|
|
2137
2530
|
};
|
|
2138
|
-
var
|
|
2531
|
+
var _hoisted_56$1 = {
|
|
2139
2532
|
key: 1,
|
|
2140
2533
|
class: "inline-flex items-center gap-1 px-2 py-0.5 rounded-full text-[10px] font-semibold bg-slate-50 text-slate-400 border border-slate-200/20"
|
|
2141
2534
|
};
|
|
2142
|
-
var
|
|
2535
|
+
var _hoisted_57$1 = {
|
|
2143
2536
|
key: 2,
|
|
2144
2537
|
class: "text-slate-300"
|
|
2145
2538
|
};
|
|
2146
|
-
var
|
|
2539
|
+
var _hoisted_58$1 = [
|
|
2147
2540
|
"href",
|
|
2148
2541
|
"tabindex",
|
|
2149
2542
|
"data-testid",
|
|
2150
2543
|
"onClick",
|
|
2151
2544
|
"onKeydown"
|
|
2152
2545
|
];
|
|
2153
|
-
var
|
|
2546
|
+
var _hoisted_59$1 = {
|
|
2154
2547
|
key: 3,
|
|
2155
2548
|
class: "font-semibold text-slate-900 tabular-nums text-sm"
|
|
2156
2549
|
};
|
|
2157
|
-
var
|
|
2550
|
+
var _hoisted_60$1 = {
|
|
2158
2551
|
key: 4,
|
|
2159
2552
|
class: "inline-block truncate tabular-nums font-bold text-indigo-900 bg-indigo-50/50 px-2 py-0.5 rounded border border-indigo-100/50"
|
|
2160
2553
|
};
|
|
2161
|
-
var
|
|
2162
|
-
|
|
2554
|
+
var _hoisted_61$1 = ["data-testid"];
|
|
2555
|
+
var _hoisted_62$1 = {
|
|
2556
|
+
key: 6,
|
|
2163
2557
|
class: "border border-slate-200/80 rounded-xl overflow-hidden shadow-sm mt-1"
|
|
2164
2558
|
};
|
|
2165
|
-
var
|
|
2166
|
-
var
|
|
2167
|
-
var
|
|
2168
|
-
var
|
|
2559
|
+
var _hoisted_63$1 = { class: "w-full text-[11px] text-slate-600 bg-white" };
|
|
2560
|
+
var _hoisted_64$1 = { class: "bg-slate-50 border-b border-slate-200 text-slate-500 font-bold uppercase tracking-wider" };
|
|
2561
|
+
var _hoisted_65$1 = { class: "divide-y divide-slate-100" };
|
|
2562
|
+
var _hoisted_66$1 = {
|
|
2169
2563
|
key: 0,
|
|
2170
2564
|
class: "material-icons text-emerald-600 text-base"
|
|
2171
2565
|
};
|
|
2172
|
-
var
|
|
2566
|
+
var _hoisted_67$1 = {
|
|
2173
2567
|
key: 1,
|
|
2174
2568
|
class: "text-slate-300"
|
|
2175
2569
|
};
|
|
2176
|
-
var
|
|
2177
|
-
key:
|
|
2570
|
+
var _hoisted_68$1 = {
|
|
2571
|
+
key: 7,
|
|
2178
2572
|
class: "text-slate-400 italic"
|
|
2179
2573
|
};
|
|
2180
|
-
var
|
|
2181
|
-
key:
|
|
2574
|
+
var _hoisted_69$1 = {
|
|
2575
|
+
key: 8,
|
|
2182
2576
|
class: "bg-slate-50 rounded-xl p-4 border border-slate-200/60 text-slate-600 text-xs whitespace-pre-wrap leading-relaxed max-h-[30vh] overflow-y-auto"
|
|
2183
2577
|
};
|
|
2184
|
-
var
|
|
2578
|
+
var _hoisted_70$1 = [
|
|
2185
2579
|
"src",
|
|
2186
2580
|
"alt",
|
|
2187
2581
|
"data-testid"
|
|
2188
2582
|
];
|
|
2189
|
-
var
|
|
2190
|
-
var
|
|
2191
|
-
var
|
|
2583
|
+
var _hoisted_71$1 = ["href", "data-testid"];
|
|
2584
|
+
var _hoisted_72$1 = ["href", "data-testid"];
|
|
2585
|
+
var _hoisted_73$1 = [
|
|
2192
2586
|
"href",
|
|
2193
2587
|
"data-testid",
|
|
2194
2588
|
"onClick"
|
|
2195
2589
|
];
|
|
2196
|
-
var
|
|
2197
|
-
key:
|
|
2590
|
+
var _hoisted_74$1 = {
|
|
2591
|
+
key: 15,
|
|
2198
2592
|
class: "text-slate-800 font-semibold"
|
|
2199
2593
|
};
|
|
2200
|
-
var
|
|
2594
|
+
var _hoisted_75$1 = {
|
|
2201
2595
|
key: 0,
|
|
2202
2596
|
class: "col-span-full text-xs font-semibold text-red-600 bg-red-50 border border-red-100 p-2.5 rounded-xl"
|
|
2203
2597
|
};
|
|
2204
|
-
var
|
|
2598
|
+
var _hoisted_76$1 = {
|
|
2205
2599
|
key: 1,
|
|
2206
2600
|
class: "mt-5 pt-4 border-t border-slate-200/60",
|
|
2207
2601
|
"data-testid": "collections-detail-chat"
|
|
2208
2602
|
};
|
|
2209
|
-
var
|
|
2603
|
+
var _hoisted_77$1 = {
|
|
2210
2604
|
class: "block text-[10px] font-bold text-slate-400 uppercase tracking-wider mb-1.5",
|
|
2211
2605
|
for: "collections-detail-chat-input"
|
|
2212
2606
|
};
|
|
2213
|
-
var
|
|
2214
|
-
var
|
|
2215
|
-
var
|
|
2607
|
+
var _hoisted_78$1 = { class: "flex items-end gap-2" };
|
|
2608
|
+
var _hoisted_79$1 = ["placeholder", "onKeydown"];
|
|
2609
|
+
var _hoisted_80$1 = ["disabled"];
|
|
2216
2610
|
//#endregion
|
|
2217
2611
|
//#region src/vue/components/CollectionRecordPanel.vue
|
|
2218
2612
|
var CollectionRecordPanel_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
@@ -2225,6 +2619,7 @@ var CollectionRecordPanel_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
2225
2619
|
actionError: {},
|
|
2226
2620
|
actionPending: { type: Boolean },
|
|
2227
2621
|
visibleActions: {},
|
|
2622
|
+
runningActionIds: {},
|
|
2228
2623
|
liveRecord: {},
|
|
2229
2624
|
liveDerived: {},
|
|
2230
2625
|
viewTitle: {},
|
|
@@ -2267,6 +2662,7 @@ var CollectionRecordPanel_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
2267
2662
|
* safe in the template. */
|
|
2268
2663
|
const detailRecord = (0, vue.computed)(() => editing.value ? props.liveDerived ?? props.liveRecord ?? {} : props.viewing ?? {});
|
|
2269
2664
|
const embedViews = (0, vue.computed)(() => props.render.embedViewsFor(detailRecord.value));
|
|
2665
|
+
const backlinksViews = (0, vue.computed)(() => props.render.backlinksViewsFor(detailRecord.value));
|
|
2270
2666
|
const embedOwnerByKey = (0, vue.computed)(() => {
|
|
2271
2667
|
const map = /* @__PURE__ */ new Map();
|
|
2272
2668
|
for (const field of Object.values(props.collection.schema.fields)) if (field.type === "embed" && field.idField) map.set(field.idField, field);
|
|
@@ -2282,12 +2678,12 @@ var CollectionRecordPanel_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
2282
2678
|
if (!editing.value) return "collections-detail";
|
|
2283
2679
|
return editing.value.mode === "create" ? "collections-create" : "collections-edit";
|
|
2284
2680
|
});
|
|
2285
|
-
/** Whether a field gets an editable control in edit mode.
|
|
2286
|
-
*
|
|
2287
|
-
*
|
|
2288
|
-
*
|
|
2681
|
+
/** Whether a field gets an editable control in edit mode. The computed /
|
|
2682
|
+
* projected kinds (COMPUTED_TYPES: derived, embed, backlinks, rollup,
|
|
2683
|
+
* toggle) stay read-only in both modes, so the cell geometry never
|
|
2684
|
+
* changes on the view↔edit toggle. */
|
|
2289
2685
|
function isEditableType(type) {
|
|
2290
|
-
return type
|
|
2686
|
+
return !_mulmoclaude_core_collection.COMPUTED_TYPES.has(type);
|
|
2291
2687
|
}
|
|
2292
2688
|
/** Wide field types span the full grid width in BOTH modes — keeping
|
|
2293
2689
|
* `image` full-width here (not just when viewing) is what stops a field
|
|
@@ -2297,6 +2693,7 @@ var CollectionRecordPanel_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
2297
2693
|
"table",
|
|
2298
2694
|
"markdown",
|
|
2299
2695
|
"embed",
|
|
2696
|
+
"backlinks",
|
|
2300
2697
|
"image"
|
|
2301
2698
|
].includes(field.type) ? "col-span-full" : "col-span-1";
|
|
2302
2699
|
}
|
|
@@ -2375,10 +2772,10 @@ var CollectionRecordPanel_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
2375
2772
|
key: action.id,
|
|
2376
2773
|
type: "button",
|
|
2377
2774
|
class: "h-8 px-2.5 rounded border border-indigo-200 bg-indigo-50/50 text-indigo-600 hover:bg-indigo-600 hover:text-white hover:border-indigo-600 font-bold text-xs transition-all flex items-center gap-1 disabled:opacity-50",
|
|
2378
|
-
disabled: __props.actionPending,
|
|
2775
|
+
disabled: __props.actionPending || __props.runningActionIds.includes(action.id),
|
|
2379
2776
|
"data-testid": `collections-detail-action-${action.id}`,
|
|
2380
2777
|
onClick: ($event) => emit("runAction", action)
|
|
2381
|
-
}, [action.
|
|
2778
|
+
}, [__props.runningActionIds.includes(action.id) ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_8$6, "progress_activity")) : action.icon ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_9$6, (0, vue.toDisplayString)(action.icon), 1)) : (0, vue.createCommentVNode)("", true), (0, vue.createElementVNode)("span", null, (0, vue.toDisplayString)(action.label), 1)], 8, _hoisted_7$6);
|
|
2382
2779
|
}), 128)),
|
|
2383
2780
|
(0, vue.createElementVNode)("button", {
|
|
2384
2781
|
type: "button",
|
|
@@ -2398,29 +2795,29 @@ var CollectionRecordPanel_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
2398
2795
|
"aria-label": (0, vue.unref)(t)("common.close"),
|
|
2399
2796
|
"data-testid": "collections-detail-close",
|
|
2400
2797
|
onClick: _cache[3] || (_cache[3] = ($event) => emit("close"))
|
|
2401
|
-
}, [..._cache[8] || (_cache[8] = [(0, vue.createElementVNode)("span", { class: "material-icons text-lg" }, "close", -1)])], 8,
|
|
2798
|
+
}, [..._cache[8] || (_cache[8] = [(0, vue.createElementVNode)("span", { class: "material-icons text-lg" }, "close", -1)])], 8, _hoisted_10$6)
|
|
2402
2799
|
]))]),
|
|
2403
|
-
!editing.value && __props.actionError ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("p",
|
|
2404
|
-
(0, vue.createElementVNode)("div",
|
|
2800
|
+
!editing.value && __props.actionError ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("p", _hoisted_11$6, (0, vue.toDisplayString)(__props.actionError), 1)) : (0, vue.createCommentVNode)("", true),
|
|
2801
|
+
(0, vue.createElementVNode)("div", _hoisted_12$6, [((0, vue.openBlock)(true), (0, vue.createElementBlock)(vue.Fragment, null, (0, vue.renderList)(__props.collection.schema.fields, (field, key) => {
|
|
2405
2802
|
return (0, vue.openBlock)(), (0, vue.createElementBlock)(vue.Fragment, { key }, [cellVisible(field, String(key)) ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", {
|
|
2406
2803
|
key: 0,
|
|
2407
2804
|
class: (0, vue.normalizeClass)(["flex flex-col gap-1.5", colSpanClass(field)])
|
|
2408
2805
|
}, [(0, vue.createElementVNode)("label", {
|
|
2409
2806
|
class: "text-[10px] font-bold text-slate-400 uppercase tracking-wider flex items-center gap-1",
|
|
2410
2807
|
for: `collections-field-${key}`
|
|
2411
|
-
}, [(0, vue.createTextVNode)((0, vue.toDisplayString)(field.label) + " ", 1), editing.value && field.required ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span",
|
|
2808
|
+
}, [(0, vue.createTextVNode)((0, vue.toDisplayString)(field.label) + " ", 1), editing.value && field.required ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_14$5, "*")) : (0, vue.createCommentVNode)("", true)], 8, _hoisted_13$5), editing.value && field.type === "embed" && field.idField && __props.render.embedOptions(field.to ?? "").length > 0 ? (0, vue.withDirectives)(((0, vue.openBlock)(), (0, vue.createElementBlock)("select", {
|
|
2412
2809
|
key: 0,
|
|
2413
2810
|
id: `collections-field-${key}`,
|
|
2414
2811
|
"onUpdate:modelValue": ($event) => editing.value.text[field.idField] = $event,
|
|
2415
2812
|
required: embedPickerRequired(field),
|
|
2416
2813
|
class: "w-full rounded-xl border border-slate-200 px-3 py-2 text-xs bg-slate-50 hover:bg-slate-50/50 focus:bg-white focus:border-indigo-500 focus:ring-2 focus:ring-indigo-500/20 focus:outline-none transition-all cursor-pointer font-medium text-slate-700",
|
|
2417
2814
|
"data-testid": `collections-input-${key}`
|
|
2418
|
-
}, [(0, vue.createElementVNode)("option",
|
|
2815
|
+
}, [(0, vue.createElementVNode)("option", _hoisted_16$5, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.selectPlaceholder")), 1), ((0, vue.openBlock)(true), (0, vue.createElementBlock)(vue.Fragment, null, (0, vue.renderList)(__props.render.embedOptions(field.to ?? ""), (opt) => {
|
|
2419
2816
|
return (0, vue.openBlock)(), (0, vue.createElementBlock)("option", {
|
|
2420
2817
|
key: opt.slug,
|
|
2421
2818
|
value: opt.slug
|
|
2422
|
-
}, (0, vue.toDisplayString)(opt.display), 9,
|
|
2423
|
-
}), 128))], 8,
|
|
2819
|
+
}, (0, vue.toDisplayString)(opt.display), 9, _hoisted_17$5);
|
|
2820
|
+
}), 128))], 8, _hoisted_15$5)), [[vue.vModelSelect, editing.value.text[field.idField]]]) : editing.value && field.type === "embed" && field.idField ? (0, vue.withDirectives)(((0, vue.openBlock)(), (0, vue.createElementBlock)("input", {
|
|
2424
2821
|
key: 1,
|
|
2425
2822
|
id: `collections-field-${key}`,
|
|
2426
2823
|
"onUpdate:modelValue": ($event) => editing.value.text[field.idField] = $event,
|
|
@@ -2429,47 +2826,47 @@ var CollectionRecordPanel_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
2429
2826
|
placeholder: (0, vue.unref)(t)("collectionsView.selectPlaceholder"),
|
|
2430
2827
|
class: "w-full rounded-xl border border-slate-200 px-3 py-2 text-xs focus:border-indigo-500 focus:ring-2 focus:ring-indigo-500/20 focus:outline-none font-medium text-slate-700 transition-all",
|
|
2431
2828
|
"data-testid": `collections-input-${key}`
|
|
2432
|
-
}, null, 8,
|
|
2829
|
+
}, null, 8, _hoisted_18$5)), [[vue.vModelText, editing.value.text[field.idField]]]) : editing.value && isEditableType(field.type) ? ((0, vue.openBlock)(), (0, vue.createElementBlock)(vue.Fragment, { key: 2 }, [field.type === "boolean" ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("label", _hoisted_19$3, [(0, vue.withDirectives)((0, vue.createElementVNode)("input", {
|
|
2433
2830
|
id: `collections-field-${key}`,
|
|
2434
2831
|
"onUpdate:modelValue": ($event) => editing.value.bool[key] = $event,
|
|
2435
2832
|
type: "checkbox",
|
|
2436
2833
|
class: "h-5 w-5 rounded border-slate-300 text-indigo-600 focus:ring-indigo-500/20 cursor-pointer",
|
|
2437
2834
|
"data-testid": `collections-input-${key}`,
|
|
2438
2835
|
onChange: ($event) => markBoolTouched(String(key))
|
|
2439
|
-
}, null, 40,
|
|
2836
|
+
}, null, 40, _hoisted_20$3), [[vue.vModelCheckbox, editing.value.bool[key]]]), (0, vue.createElementVNode)("span", { class: (0, vue.normalizeClass)(["text-xs font-semibold", editing.value.bool[key] ? "text-indigo-600" : "text-slate-500"]) }, (0, vue.toDisplayString)(editing.value.bool[key] ? (0, vue.unref)(t)("common.yes") : (0, vue.unref)(t)("common.no")), 3)])) : field.type === "ref" && field.to && __props.render.refOptions(field.to).length > 0 ? (0, vue.withDirectives)(((0, vue.openBlock)(), (0, vue.createElementBlock)("select", {
|
|
2440
2837
|
key: 1,
|
|
2441
2838
|
id: `collections-field-${key}`,
|
|
2442
2839
|
"onUpdate:modelValue": ($event) => editing.value.text[key] = $event,
|
|
2443
2840
|
required: isFieldRequiredInUi(field),
|
|
2444
2841
|
class: "w-full rounded-xl border border-slate-200 px-3 py-2 text-xs bg-slate-50 hover:bg-slate-50/50 focus:bg-white focus:border-indigo-500 focus:ring-2 focus:ring-indigo-500/20 focus:outline-none transition-all cursor-pointer font-medium text-slate-700",
|
|
2445
2842
|
"data-testid": `collections-input-${key}`
|
|
2446
|
-
}, [(0, vue.createElementVNode)("option",
|
|
2843
|
+
}, [(0, vue.createElementVNode)("option", _hoisted_22$3, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.selectPlaceholder")), 1), ((0, vue.openBlock)(true), (0, vue.createElementBlock)(vue.Fragment, null, (0, vue.renderList)(__props.render.refOptions(field.to), (opt) => {
|
|
2447
2844
|
return (0, vue.openBlock)(), (0, vue.createElementBlock)("option", {
|
|
2448
2845
|
key: opt.slug,
|
|
2449
2846
|
value: opt.slug
|
|
2450
|
-
}, (0, vue.toDisplayString)(opt.display), 9,
|
|
2451
|
-
}), 128))], 8,
|
|
2847
|
+
}, (0, vue.toDisplayString)(opt.display), 9, _hoisted_23$3);
|
|
2848
|
+
}), 128))], 8, _hoisted_21$3)), [[vue.vModelSelect, editing.value.text[key]]]) : field.type === "enum" && Array.isArray(field.values) && field.values.length > 0 ? (0, vue.withDirectives)(((0, vue.openBlock)(), (0, vue.createElementBlock)("select", {
|
|
2452
2849
|
key: 2,
|
|
2453
2850
|
id: `collections-field-${key}`,
|
|
2454
2851
|
"onUpdate:modelValue": ($event) => editing.value.text[key] = $event,
|
|
2455
2852
|
required: isFieldRequiredInUi(field),
|
|
2456
2853
|
class: (0, vue.normalizeClass)(["w-full rounded-xl border px-3 py-2 text-xs focus:bg-white focus:border-indigo-500 focus:ring-2 focus:ring-indigo-500/20 focus:outline-none transition-all cursor-pointer font-medium", enumControlClass(String(key), editing.value.text[key])]),
|
|
2457
2854
|
"data-testid": `collections-input-${key}`
|
|
2458
|
-
}, [(0, vue.createElementVNode)("option",
|
|
2855
|
+
}, [(0, vue.createElementVNode)("option", _hoisted_25$2, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.selectPlaceholder")), 1), ((0, vue.openBlock)(true), (0, vue.createElementBlock)(vue.Fragment, null, (0, vue.renderList)(field.values, (value) => {
|
|
2459
2856
|
return (0, vue.openBlock)(), (0, vue.createElementBlock)("option", {
|
|
2460
2857
|
key: value,
|
|
2461
2858
|
value
|
|
2462
|
-
}, (0, vue.toDisplayString)(value), 9,
|
|
2463
|
-
}), 128))], 10,
|
|
2859
|
+
}, (0, vue.toDisplayString)(value), 9, _hoisted_26$2);
|
|
2860
|
+
}), 128))], 10, _hoisted_24$2)), [[vue.vModelSelect, editing.value.text[key]]]) : field.type === "table" && field.of ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", {
|
|
2464
2861
|
key: 3,
|
|
2465
2862
|
class: "border border-slate-200 bg-slate-50/30 rounded-xl p-4 space-y-3",
|
|
2466
2863
|
"data-testid": `collections-table-${key}`
|
|
2467
|
-
}, [editing.value.table[key] && editing.value.table[key].length > 0 ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div",
|
|
2864
|
+
}, [editing.value.table[key] && editing.value.table[key].length > 0 ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_28$1, [(0, vue.createElementVNode)("table", _hoisted_29$1, [(0, vue.createElementVNode)("thead", _hoisted_30$1, [(0, vue.createElementVNode)("tr", null, [((0, vue.openBlock)(true), (0, vue.createElementBlock)(vue.Fragment, null, (0, vue.renderList)(field.of, (subField, subKey) => {
|
|
2468
2865
|
return (0, vue.openBlock)(), (0, vue.createElementBlock)("th", {
|
|
2469
2866
|
key: subKey,
|
|
2470
2867
|
class: "text-left px-3 py-2 font-bold"
|
|
2471
2868
|
}, (0, vue.toDisplayString)(subField.label), 1);
|
|
2472
|
-
}), 128)), _cache[9] || (_cache[9] = (0, vue.createElementVNode)("th", { class: "w-9" }, null, -1))])]), (0, vue.createElementVNode)("tbody",
|
|
2869
|
+
}), 128)), _cache[9] || (_cache[9] = (0, vue.createElementVNode)("th", { class: "w-9" }, null, -1))])]), (0, vue.createElementVNode)("tbody", _hoisted_31$1, [((0, vue.openBlock)(true), (0, vue.createElementBlock)(vue.Fragment, null, (0, vue.renderList)(editing.value.table[key], (row, rowIdx) => {
|
|
2473
2870
|
return (0, vue.openBlock)(), (0, vue.createElementBlock)("tr", {
|
|
2474
2871
|
key: rowIdx,
|
|
2475
2872
|
class: "hover:bg-slate-50/50"
|
|
@@ -2483,53 +2880,53 @@ var CollectionRecordPanel_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
2483
2880
|
type: "checkbox",
|
|
2484
2881
|
class: "h-4 w-4 rounded border-slate-300 text-indigo-600 focus:ring-indigo-500/20 cursor-pointer",
|
|
2485
2882
|
onChange: ($event) => markRowBoolTouched(row, String(subKey))
|
|
2486
|
-
}, null, 40,
|
|
2883
|
+
}, null, 40, _hoisted_32$1)), [[vue.vModelCheckbox, row.bool[subKey]]]) : subField.type === "enum" && Array.isArray(subField.values) && subField.values.length > 0 ? (0, vue.withDirectives)(((0, vue.openBlock)(), (0, vue.createElementBlock)("select", {
|
|
2487
2884
|
key: 1,
|
|
2488
2885
|
"onUpdate:modelValue": ($event) => row.text[subKey] = $event,
|
|
2489
2886
|
required: subField.required,
|
|
2490
2887
|
class: "w-full rounded-lg border border-slate-200 px-2 py-1 text-xs focus:border-indigo-500 focus:outline-none cursor-pointer bg-slate-50 font-medium"
|
|
2491
|
-
}, [(0, vue.createElementVNode)("option",
|
|
2888
|
+
}, [(0, vue.createElementVNode)("option", _hoisted_34$1, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.selectPlaceholder")), 1), ((0, vue.openBlock)(true), (0, vue.createElementBlock)(vue.Fragment, null, (0, vue.renderList)(subField.values, (value) => {
|
|
2492
2889
|
return (0, vue.openBlock)(), (0, vue.createElementBlock)("option", {
|
|
2493
2890
|
key: value,
|
|
2494
2891
|
value
|
|
2495
|
-
}, (0, vue.toDisplayString)(value), 9,
|
|
2496
|
-
}), 128))], 8,
|
|
2892
|
+
}, (0, vue.toDisplayString)(value), 9, _hoisted_35$1);
|
|
2893
|
+
}), 128))], 8, _hoisted_33$1)), [[vue.vModelSelect, row.text[subKey]]]) : subField.type === "ref" && subField.to && __props.render.refOptions(subField.to).length > 0 ? (0, vue.withDirectives)(((0, vue.openBlock)(), (0, vue.createElementBlock)("select", {
|
|
2497
2894
|
key: 2,
|
|
2498
2895
|
"onUpdate:modelValue": ($event) => row.text[subKey] = $event,
|
|
2499
2896
|
required: subField.required,
|
|
2500
2897
|
class: "w-full rounded-lg border border-slate-200 px-2 py-1 text-xs focus:border-indigo-500 focus:outline-none cursor-pointer bg-slate-50 font-medium"
|
|
2501
|
-
}, [(0, vue.createElementVNode)("option",
|
|
2898
|
+
}, [(0, vue.createElementVNode)("option", _hoisted_37$1, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.selectPlaceholder")), 1), ((0, vue.openBlock)(true), (0, vue.createElementBlock)(vue.Fragment, null, (0, vue.renderList)(__props.render.refOptions(subField.to), (opt) => {
|
|
2502
2899
|
return (0, vue.openBlock)(), (0, vue.createElementBlock)("option", {
|
|
2503
2900
|
key: opt.slug,
|
|
2504
2901
|
value: opt.slug
|
|
2505
|
-
}, (0, vue.toDisplayString)(opt.display), 9,
|
|
2506
|
-
}), 128))], 8,
|
|
2902
|
+
}, (0, vue.toDisplayString)(opt.display), 9, _hoisted_38$1);
|
|
2903
|
+
}), 128))], 8, _hoisted_36$1)), [[vue.vModelSelect, row.text[subKey]]]) : subField.type === "money" ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_39$1, [(0, vue.createElementVNode)("span", _hoisted_40$1, (0, vue.toDisplayString)(__props.render.currencySymbol(__props.render.resolveCurrency(subField, __props.liveRecord))), 1), (0, vue.withDirectives)((0, vue.createElementVNode)("input", {
|
|
2507
2904
|
"onUpdate:modelValue": ($event) => row.text[subKey] = $event,
|
|
2508
2905
|
type: "number",
|
|
2509
2906
|
step: "0.01",
|
|
2510
2907
|
required: subField.required,
|
|
2511
2908
|
class: "w-full rounded-lg border border-slate-200 pl-6 pr-1.5 py-1 text-xs focus:border-indigo-500 focus:outline-none font-semibold text-slate-800"
|
|
2512
|
-
}, null, 8,
|
|
2909
|
+
}, null, 8, _hoisted_41$1), [[vue.vModelText, row.text[subKey]]])])) : (0, vue.withDirectives)(((0, vue.openBlock)(), (0, vue.createElementBlock)("input", {
|
|
2513
2910
|
key: 4,
|
|
2514
2911
|
"onUpdate:modelValue": ($event) => row.text[subKey] = $event,
|
|
2515
2912
|
type: __props.render.inputTypeFor(subField.type),
|
|
2516
2913
|
step: __props.render.stepFor(subField.type),
|
|
2517
2914
|
required: subField.required,
|
|
2518
2915
|
class: "w-full rounded-lg border border-slate-200 px-2 py-1 text-xs focus:border-indigo-500 focus:outline-none font-medium text-slate-700"
|
|
2519
|
-
}, null, 8,
|
|
2520
|
-
}), 128)), (0, vue.createElementVNode)("td",
|
|
2916
|
+
}, null, 8, _hoisted_42$1)), [[vue.vModelDynamic, row.text[subKey]]])]);
|
|
2917
|
+
}), 128)), (0, vue.createElementVNode)("td", _hoisted_43$1, [(0, vue.createElementVNode)("button", {
|
|
2521
2918
|
type: "button",
|
|
2522
2919
|
class: "h-7 w-7 flex items-center justify-center rounded-lg text-slate-400 hover:text-rose-600 hover:bg-rose-50 transition-colors",
|
|
2523
2920
|
"aria-label": (0, vue.unref)(t)("collectionsView.removeRow"),
|
|
2524
2921
|
"data-testid": `collections-table-${key}-remove-${rowIdx}`,
|
|
2525
2922
|
onClick: ($event) => removeTableRow(String(key), rowIdx)
|
|
2526
|
-
}, [..._cache[10] || (_cache[10] = [(0, vue.createElementVNode)("span", { class: "material-icons text-base" }, "close", -1)])], 8,
|
|
2527
|
-
}), 128))])])])) : ((0, vue.openBlock)(), (0, vue.createElementBlock)("p",
|
|
2923
|
+
}, [..._cache[10] || (_cache[10] = [(0, vue.createElementVNode)("span", { class: "material-icons text-base" }, "close", -1)])], 8, _hoisted_44$1)])]);
|
|
2924
|
+
}), 128))])])])) : ((0, vue.openBlock)(), (0, vue.createElementBlock)("p", _hoisted_45$1, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.noRows")), 1)), (0, vue.createElementVNode)("button", {
|
|
2528
2925
|
type: "button",
|
|
2529
2926
|
class: "inline-flex items-center gap-1 text-xs text-indigo-600 hover:text-indigo-800 font-bold hover:underline",
|
|
2530
2927
|
"data-testid": `collections-table-${key}-add`,
|
|
2531
2928
|
onClick: ($event) => addTableRow(String(key), field.of)
|
|
2532
|
-
}, [_cache[11] || (_cache[11] = (0, vue.createElementVNode)("span", { class: "material-icons text-xs" }, "add", -1)), (0, vue.createElementVNode)("span", null, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.addRow")), 1)], 8,
|
|
2929
|
+
}, [_cache[11] || (_cache[11] = (0, vue.createElementVNode)("span", { class: "material-icons text-xs" }, "add", -1)), (0, vue.createElementVNode)("span", null, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.addRow")), 1)], 8, _hoisted_46$1)], 8, _hoisted_27$2)) : field.type === "money" ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_47$1, [(0, vue.createElementVNode)("div", _hoisted_48$1, (0, vue.toDisplayString)(__props.render.currencySymbol(__props.render.resolveCurrency(field, __props.liveRecord))), 1), (0, vue.withDirectives)((0, vue.createElementVNode)("input", {
|
|
2533
2930
|
id: `collections-field-${key}`,
|
|
2534
2931
|
"onUpdate:modelValue": ($event) => editing.value.text[key] = $event,
|
|
2535
2932
|
type: "number",
|
|
@@ -2537,7 +2934,7 @@ var CollectionRecordPanel_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
2537
2934
|
required: isFieldRequiredInUi(field),
|
|
2538
2935
|
class: "w-full rounded-xl border border-slate-200 pl-11 pr-3 py-2 text-xs focus:border-indigo-500 focus:ring-2 focus:ring-indigo-500/20 focus:outline-none font-semibold text-slate-800 transition-all",
|
|
2539
2936
|
"data-testid": `collections-input-${key}`
|
|
2540
|
-
}, null, 8,
|
|
2937
|
+
}, null, 8, _hoisted_49$1), [[vue.vModelText, editing.value.text[key]]])])) : [
|
|
2541
2938
|
"string",
|
|
2542
2939
|
"email",
|
|
2543
2940
|
"number",
|
|
@@ -2556,7 +2953,7 @@ var CollectionRecordPanel_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
2556
2953
|
disabled: field.primary === true && (editing.value.mode === "edit" || __props.isSingleton),
|
|
2557
2954
|
class: "w-full rounded-xl border border-slate-200 px-3 py-2 text-xs focus:border-indigo-500 focus:ring-2 focus:ring-indigo-500/20 focus:outline-none disabled:bg-slate-100 disabled:text-slate-400 font-medium text-slate-700 transition-all",
|
|
2558
2955
|
"data-testid": `collections-input-${key}`
|
|
2559
|
-
}, null, 8,
|
|
2956
|
+
}, null, 8, _hoisted_50$1)), [[vue.vModelDynamic, editing.value.text[key]]]) : (0, vue.withDirectives)(((0, vue.openBlock)(), (0, vue.createElementBlock)("textarea", {
|
|
2560
2957
|
key: 6,
|
|
2561
2958
|
id: `collections-field-${key}`,
|
|
2562
2959
|
"onUpdate:modelValue": ($event) => editing.value.text[key] = $event,
|
|
@@ -2564,11 +2961,11 @@ var CollectionRecordPanel_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
2564
2961
|
required: isFieldRequiredInUi(field),
|
|
2565
2962
|
class: "w-full rounded-xl border border-slate-200 px-3 py-2 text-xs focus:border-indigo-500 focus:ring-2 focus:ring-indigo-500/20 focus:outline-none font-medium text-slate-700 transition-all",
|
|
2566
2963
|
"data-testid": `collections-input-${key}`
|
|
2567
|
-
}, null, 8,
|
|
2964
|
+
}, null, 8, _hoisted_51$1)), [[vue.vModelText, editing.value.text[key]]])], 64)) : ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", {
|
|
2568
2965
|
key: 3,
|
|
2569
2966
|
class: "text-xs font-medium text-slate-700 break-words",
|
|
2570
2967
|
"data-testid": `collections-detail-value-${key}`
|
|
2571
|
-
}, [field.type === "toggle" ? ((0, vue.openBlock)(), (0, vue.createElementBlock)(vue.Fragment, { key: 0 }, [field.field !== void 0 && String(detailRecord.value[field.field] ?? "") === field.onValue ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span",
|
|
2968
|
+
}, [field.type === "toggle" ? ((0, vue.openBlock)(), (0, vue.createElementBlock)(vue.Fragment, { key: 0 }, [field.field !== void 0 && String(detailRecord.value[field.field] ?? "") === field.onValue ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_53$1, [_cache[12] || (_cache[12] = (0, vue.createElementVNode)("span", { class: "h-1.5 w-1.5 rounded-full bg-emerald-500" }, null, -1)), (0, vue.createTextVNode)(" " + (0, vue.toDisplayString)((0, vue.unref)(t)("common.yes")), 1)])) : ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_54$1, (0, vue.toDisplayString)((0, vue.unref)(t)("common.no")), 1))], 64)) : field.type === "boolean" ? ((0, vue.openBlock)(), (0, vue.createElementBlock)(vue.Fragment, { key: 1 }, [detailRecord.value[key] === true ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_55$1, [_cache[13] || (_cache[13] = (0, vue.createElementVNode)("span", { class: "h-1.5 w-1.5 rounded-full bg-emerald-500" }, null, -1)), (0, vue.createTextVNode)(" " + (0, vue.toDisplayString)((0, vue.unref)(t)("common.yes")), 1)])) : detailRecord.value[key] === false ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_56$1, (0, vue.toDisplayString)((0, vue.unref)(t)("common.no")), 1)) : ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_57$1, "—"))], 64)) : field.type === "ref" && field.to && typeof detailRecord.value[key] === "string" && detailRecord.value[key] ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("a", {
|
|
2572
2969
|
key: 2,
|
|
2573
2970
|
href: (0, vue.unref)(cui).recordHref?.(field.to, String(detailRecord.value[key])),
|
|
2574
2971
|
tabindex: (0, vue.unref)(cui).recordHref?.(field.to, String(detailRecord.value[key])) ? void 0 : 0,
|
|
@@ -2577,12 +2974,16 @@ var CollectionRecordPanel_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
2577
2974
|
"data-testid": `collections-detail-ref-${key}`,
|
|
2578
2975
|
onClick: ($event) => (0, vue.unref)(activateRefLink)($event, field.to, String(detailRecord.value[key])),
|
|
2579
2976
|
onKeydown: [(0, vue.withKeys)(($event) => (0, vue.unref)(activateRefLink)($event, field.to, String(detailRecord.value[key])), ["enter"]), (0, vue.withKeys)(($event) => (0, vue.unref)(activateRefLink)($event, field.to, String(detailRecord.value[key])), ["space"])]
|
|
2580
|
-
}, (0, vue.toDisplayString)(__props.render.refDisplay(field.to, String(detailRecord.value[key]))), 41,
|
|
2977
|
+
}, (0, vue.toDisplayString)(__props.render.refDisplay(field.to, String(detailRecord.value[key]))), 41, _hoisted_58$1)) : field.type === "money" ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_59$1, (0, vue.toDisplayString)(__props.render.formatMoney(detailRecord.value[key], __props.render.resolveCurrency(field, detailRecord.value), __props.locale)), 1)) : field.type === "derived" ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_60$1, (0, vue.toDisplayString)(__props.render.derivedDisplay(field, __props.render.evaluateDerivedAgainstItem(field, String(key), detailRecord.value), detailRecord.value)), 1)) : field.type === "rollup" ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", {
|
|
2978
|
+
key: 5,
|
|
2979
|
+
class: "inline-block truncate tabular-nums font-bold text-indigo-900 bg-indigo-50/50 px-2 py-0.5 rounded border border-indigo-100/50",
|
|
2980
|
+
"data-testid": `collections-detail-rollup-${key}`
|
|
2981
|
+
}, (0, vue.toDisplayString)(__props.render.rollupDisplay(field, detailRecord.value)), 9, _hoisted_61$1)) : field.type === "table" && field.of && __props.render.hasTableRows(detailRecord.value[key]) ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_62$1, [(0, vue.createElementVNode)("table", _hoisted_63$1, [(0, vue.createElementVNode)("thead", _hoisted_64$1, [(0, vue.createElementVNode)("tr", null, [((0, vue.openBlock)(true), (0, vue.createElementBlock)(vue.Fragment, null, (0, vue.renderList)(field.of, (subField, subKey) => {
|
|
2581
2982
|
return (0, vue.openBlock)(), (0, vue.createElementBlock)("th", {
|
|
2582
2983
|
key: subKey,
|
|
2583
2984
|
class: "text-left px-4 py-2 font-bold"
|
|
2584
2985
|
}, (0, vue.toDisplayString)(subField.label), 1);
|
|
2585
|
-
}), 128))])]), (0, vue.createElementVNode)("tbody",
|
|
2986
|
+
}), 128))])]), (0, vue.createElementVNode)("tbody", _hoisted_65$1, [((0, vue.openBlock)(true), (0, vue.createElementBlock)(vue.Fragment, null, (0, vue.renderList)(__props.render.tableRows(detailRecord.value[key]), (row, rowIdx) => {
|
|
2586
2987
|
return (0, vue.openBlock)(), (0, vue.createElementBlock)("tr", {
|
|
2587
2988
|
key: rowIdx,
|
|
2588
2989
|
class: "hover:bg-slate-50/50"
|
|
@@ -2590,44 +2991,48 @@ var CollectionRecordPanel_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
2590
2991
|
return (0, vue.openBlock)(), (0, vue.createElementBlock)("td", {
|
|
2591
2992
|
key: subKey,
|
|
2592
2993
|
class: "px-4 py-2 align-middle font-medium"
|
|
2593
|
-
}, [subField.type === "boolean" ? ((0, vue.openBlock)(), (0, vue.createElementBlock)(vue.Fragment, { key: 0 }, [row[subKey] === true ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span",
|
|
2994
|
+
}, [subField.type === "boolean" ? ((0, vue.openBlock)(), (0, vue.createElementBlock)(vue.Fragment, { key: 0 }, [row[subKey] === true ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_66$1, "check_circle")) : ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_67$1, "—"))], 64)) : ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", {
|
|
2594
2995
|
key: 1,
|
|
2595
2996
|
class: (0, vue.normalizeClass)([subField.type === "money" ? "font-bold text-slate-800 tabular-nums" : ""])
|
|
2596
2997
|
}, (0, vue.toDisplayString)(__props.render.formatSubCell(subField, row[subKey], detailRecord.value)), 3))]);
|
|
2597
2998
|
}), 128))]);
|
|
2598
|
-
}), 128))])])])) : field.type === "table" ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span",
|
|
2599
|
-
key:
|
|
2999
|
+
}), 128))])])])) : field.type === "table" ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_68$1, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.noRows")), 1)) : field.type === "markdown" ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_69$1, (0, vue.toDisplayString)(__props.render.detailText(detailRecord.value[key])), 1)) : field.type === "embed" && embedViews.value[key] ? ((0, vue.openBlock)(), (0, vue.createBlock)(CollectionEmbedView_default, {
|
|
3000
|
+
key: 9,
|
|
2600
3001
|
view: embedViews.value[key],
|
|
2601
3002
|
"field-key": String(key)
|
|
3003
|
+
}, null, 8, ["view", "field-key"])) : field.type === "backlinks" && backlinksViews.value[key] ? ((0, vue.openBlock)(), (0, vue.createBlock)(CollectionBacklinksView_default, {
|
|
3004
|
+
key: 10,
|
|
3005
|
+
view: backlinksViews.value[key],
|
|
3006
|
+
"field-key": String(key)
|
|
2602
3007
|
}, null, 8, ["view", "field-key"])) : field.type === "image" && typeof detailRecord.value[key] === "string" && detailRecord.value[key] ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("img", {
|
|
2603
|
-
key:
|
|
3008
|
+
key: 11,
|
|
2604
3009
|
src: (0, vue.unref)(resolveImageSrc)(String(detailRecord.value[key])),
|
|
2605
3010
|
alt: field.label,
|
|
2606
3011
|
class: "max-h-64 max-w-full object-contain rounded-lg border border-slate-200 bg-slate-50",
|
|
2607
3012
|
"data-testid": `collections-detail-image-${key}`
|
|
2608
|
-
}, null, 8,
|
|
2609
|
-
key:
|
|
3013
|
+
}, null, 8, _hoisted_70$1)) : field.type !== "file" && __props.render.isExternalUrl(detailRecord.value[key]) ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("a", {
|
|
3014
|
+
key: 12,
|
|
2610
3015
|
href: String(detailRecord.value[key]),
|
|
2611
3016
|
target: "_blank",
|
|
2612
3017
|
rel: "noopener noreferrer",
|
|
2613
3018
|
class: "text-blue-600 hover:text-blue-800 font-semibold hover:underline break-all",
|
|
2614
3019
|
"data-testid": `collections-detail-url-${key}`
|
|
2615
|
-
}, (0, vue.toDisplayString)(String(detailRecord.value[key])), 9,
|
|
2616
|
-
key:
|
|
3020
|
+
}, (0, vue.toDisplayString)(String(detailRecord.value[key])), 9, _hoisted_71$1)) : field.type === "file" && __props.render.artifactUrl(detailRecord.value[key]) ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("a", {
|
|
3021
|
+
key: 13,
|
|
2617
3022
|
href: __props.render.artifactUrl(detailRecord.value[key]) ?? void 0,
|
|
2618
3023
|
target: "_blank",
|
|
2619
3024
|
rel: "noopener noreferrer",
|
|
2620
3025
|
class: "text-blue-600 hover:text-blue-800 font-semibold hover:underline break-all",
|
|
2621
3026
|
"data-testid": `collections-detail-file-${key}`
|
|
2622
|
-
}, (0, vue.toDisplayString)(String(detailRecord.value[key])), 9,
|
|
2623
|
-
key:
|
|
3027
|
+
}, (0, vue.toDisplayString)(String(detailRecord.value[key])), 9, _hoisted_72$1)) : field.type === "file" && __props.render.fileRoutePath(detailRecord.value[key]) ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("a", {
|
|
3028
|
+
key: 14,
|
|
2624
3029
|
href: __props.render.fileRoutePath(detailRecord.value[key]) ?? void 0,
|
|
2625
3030
|
class: "text-blue-600 hover:text-blue-800 font-semibold hover:underline break-all",
|
|
2626
3031
|
"data-testid": `collections-detail-file-${key}`,
|
|
2627
3032
|
onClick: ($event) => (0, vue.unref)(activatePathLink)($event, __props.render.fileRoutePath(detailRecord.value[key]) ?? "")
|
|
2628
|
-
}, (0, vue.toDisplayString)(String(detailRecord.value[key])), 9,
|
|
2629
|
-
}), 128)), editing.value && __props.saveError ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("p",
|
|
2630
|
-
!editing.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div",
|
|
3033
|
+
}, (0, vue.toDisplayString)(String(detailRecord.value[key])), 9, _hoisted_73$1)) : ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_74$1, (0, vue.toDisplayString)(__props.render.formatCell(detailRecord.value[key], field.type)), 1))], 8, _hoisted_52$1))], 2)) : (0, vue.createCommentVNode)("", true)], 64);
|
|
3034
|
+
}), 128)), editing.value && __props.saveError ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("p", _hoisted_75$1, (0, vue.toDisplayString)(__props.saveError), 1)) : (0, vue.createCommentVNode)("", true)]),
|
|
3035
|
+
!editing.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_76$1, [(0, vue.createElementVNode)("label", _hoisted_77$1, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.itemChatLabel")), 1), (0, vue.createElementVNode)("div", _hoisted_78$1, [(0, vue.withDirectives)((0, vue.createElementVNode)("textarea", {
|
|
2631
3036
|
id: "collections-detail-chat-input",
|
|
2632
3037
|
"onUpdate:modelValue": _cache[4] || (_cache[4] = ($event) => chatMessage.value = $event),
|
|
2633
3038
|
rows: "2",
|
|
@@ -2635,13 +3040,13 @@ var CollectionRecordPanel_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
2635
3040
|
class: "flex-1 bg-slate-50 border border-slate-200/80 rounded-xl px-3 py-2 text-xs placeholder-slate-400 focus:outline-none focus:ring-2 focus:ring-indigo-500/20 focus:border-indigo-500 focus:bg-white transition-all resize-none",
|
|
2636
3041
|
"data-testid": "collections-detail-chat-input",
|
|
2637
3042
|
onKeydown: [(0, vue.withKeys)((0, vue.withModifiers)(submitItemChat, ["meta"]), ["enter"]), (0, vue.withKeys)((0, vue.withModifiers)(submitItemChat, ["ctrl"]), ["enter"])]
|
|
2638
|
-
}, null, 40,
|
|
3043
|
+
}, null, 40, _hoisted_79$1), [[vue.vModelText, chatMessage.value]]), (0, vue.createElementVNode)("button", {
|
|
2639
3044
|
type: "button",
|
|
2640
3045
|
class: "h-8 px-2.5 rounded bg-indigo-600 text-white font-bold text-xs hover:bg-indigo-700 disabled:opacity-50 transition-all shadow-sm shadow-indigo-600/10 flex items-center gap-1 shrink-0",
|
|
2641
3046
|
disabled: !chatMessage.value.trim(),
|
|
2642
3047
|
"data-testid": "collections-detail-chat-send",
|
|
2643
3048
|
onClick: submitItemChat
|
|
2644
|
-
}, [_cache[14] || (_cache[14] = (0, vue.createElementVNode)("span", { class: "material-icons text-sm" }, "forum", -1)), (0, vue.createElementVNode)("span", null, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.chat")), 1)], 8,
|
|
3049
|
+
}, [_cache[14] || (_cache[14] = (0, vue.createElementVNode)("span", { class: "material-icons text-sm" }, "forum", -1)), (0, vue.createElementVNode)("span", null, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.chat")), 1)], 8, _hoisted_80$1)])])) : (0, vue.createCommentVNode)("", true)
|
|
2645
3050
|
]),
|
|
2646
3051
|
_: 1
|
|
2647
3052
|
}, 40, ["data-testid"]);
|
|
@@ -3043,152 +3448,16 @@ var CollectionRemoteViewPreview_default = /*#__PURE__*/ _plugin_vue_export_helpe
|
|
|
3043
3448
|
}
|
|
3044
3449
|
}), [["__scopeId", "data-v-965ade6c"]]);
|
|
3045
3450
|
//#endregion
|
|
3046
|
-
//#region src/vue/useCollectionRendering.helpers.ts
|
|
3047
|
-
var EM_DASH = "—";
|
|
3048
|
-
var DEFAULT_CURRENCY = "USD";
|
|
3049
|
-
var MARKDOWN_CELL_PREVIEW_MAX = 80;
|
|
3050
|
-
function stepForFieldType(type) {
|
|
3051
|
-
if (type === "money") return "0.01";
|
|
3052
|
-
if (type === "number") return "any";
|
|
3053
|
-
}
|
|
3054
|
-
function inputTypeFor(type) {
|
|
3055
|
-
if (type === "email") return "email";
|
|
3056
|
-
if (type === "number") return "number";
|
|
3057
|
-
if (type === "money") return "number";
|
|
3058
|
-
if (type === "date") return "date";
|
|
3059
|
-
if (type === "datetime") return "datetime-local";
|
|
3060
|
-
return "text";
|
|
3061
|
-
}
|
|
3062
|
-
function isExternalUrl(value) {
|
|
3063
|
-
return typeof value === "string" && /^https?:\/\//i.test(value);
|
|
3064
|
-
}
|
|
3065
|
-
function detailText(value) {
|
|
3066
|
-
if (value === void 0 || value === null || value === "") return EM_DASH;
|
|
3067
|
-
return String(value);
|
|
3068
|
-
}
|
|
3069
|
-
function formatCell(value, type) {
|
|
3070
|
-
if (value === void 0 || value === null || value === "") return EM_DASH;
|
|
3071
|
-
if (type === "markdown" && typeof value === "string") return value.length > MARKDOWN_CELL_PREVIEW_MAX ? `${value.slice(0, MARKDOWN_CELL_PREVIEW_MAX)}…` : value;
|
|
3072
|
-
if (typeof value === "string" || typeof value === "number") return String(value);
|
|
3073
|
-
return JSON.stringify(value);
|
|
3074
|
-
}
|
|
3075
|
-
/** Resolve the ISO 4217 code for a money field: a per-record
|
|
3076
|
-
* `currencyField` (when present and non-blank) wins over the field's
|
|
3077
|
-
* literal `currency`. Only `money` / `derived` variants carry currency
|
|
3078
|
-
* keys; any other field resolves to undefined (the formatter's USD
|
|
3079
|
-
* fallback), as before. */
|
|
3080
|
-
function resolveCurrency(field, record) {
|
|
3081
|
-
if (field.type !== "money" && field.type !== "derived") return void 0;
|
|
3082
|
-
if (field.currencyField && record) {
|
|
3083
|
-
const code = record[field.currencyField];
|
|
3084
|
-
if (typeof code === "string" && code.trim().length > 0) return code;
|
|
3085
|
-
}
|
|
3086
|
-
return field.currency;
|
|
3087
|
-
}
|
|
3088
|
-
function formatMoney(value, currency, displayLocale) {
|
|
3089
|
-
if (value === void 0 || value === "") return EM_DASH;
|
|
3090
|
-
const amount = typeof value === "number" ? value : Number(value);
|
|
3091
|
-
if (!Number.isFinite(amount)) return String(value);
|
|
3092
|
-
const currencyCode = currency && currency.length > 0 ? currency : DEFAULT_CURRENCY;
|
|
3093
|
-
try {
|
|
3094
|
-
return new Intl.NumberFormat(displayLocale, {
|
|
3095
|
-
style: "currency",
|
|
3096
|
-
currency: currencyCode
|
|
3097
|
-
}).format(amount);
|
|
3098
|
-
} catch {
|
|
3099
|
-
return String(amount);
|
|
3100
|
-
}
|
|
3101
|
-
}
|
|
3102
|
-
function currencySymbolForLocale(currency, locale) {
|
|
3103
|
-
const code = currency && currency.length > 0 ? currency : DEFAULT_CURRENCY;
|
|
3104
|
-
try {
|
|
3105
|
-
return new Intl.NumberFormat(locale, {
|
|
3106
|
-
style: "currency",
|
|
3107
|
-
currency: code
|
|
3108
|
-
}).formatToParts(0).find((entry) => entry.type === "currency")?.value ?? code;
|
|
3109
|
-
} catch {
|
|
3110
|
-
return code;
|
|
3111
|
-
}
|
|
3112
|
-
}
|
|
3113
|
-
function tableRows(value) {
|
|
3114
|
-
if (!Array.isArray(value)) return [];
|
|
3115
|
-
return value.filter((row) => Boolean(row) && typeof row === "object" && !Array.isArray(row));
|
|
3116
|
-
}
|
|
3117
|
-
function hasTableRows(value) {
|
|
3118
|
-
return tableRows(value).length > 0;
|
|
3119
|
-
}
|
|
3120
|
-
/** Pick the field used to label a referenced/embedded record: prefer a
|
|
3121
|
-
* `name` field, then `title`, else fall back to the primary key. */
|
|
3122
|
-
function displayFieldFor(fields, primaryKey) {
|
|
3123
|
-
if ("name" in fields) return "name";
|
|
3124
|
-
if ("title" in fields) return "title";
|
|
3125
|
-
return primaryKey;
|
|
3126
|
-
}
|
|
3127
|
-
function uniqueRefTargets(schema) {
|
|
3128
|
-
const targets = /* @__PURE__ */ new Set();
|
|
3129
|
-
const walk = (fields) => {
|
|
3130
|
-
for (const field of Object.values(fields)) {
|
|
3131
|
-
if (field.type === "ref" && typeof field.to === "string" && field.to.length > 0) targets.add(field.to);
|
|
3132
|
-
if (field.type === "table" && field.of) walk(field.of);
|
|
3133
|
-
}
|
|
3134
|
-
};
|
|
3135
|
-
walk(schema.fields);
|
|
3136
|
-
return [...targets];
|
|
3137
|
-
}
|
|
3138
|
-
function uniqueEmbedTargets(schema) {
|
|
3139
|
-
const targets = /* @__PURE__ */ new Set();
|
|
3140
|
-
for (const field of Object.values(schema.fields)) if (field.type === "embed" && typeof field.to === "string" && field.to.length > 0) targets.add(field.to);
|
|
3141
|
-
return [...targets];
|
|
3142
|
-
}
|
|
3143
|
-
function buildRefDisplayMap(detail) {
|
|
3144
|
-
const { fields, primaryKey } = detail.collection.schema;
|
|
3145
|
-
const displayField = displayFieldFor(fields, primaryKey);
|
|
3146
|
-
const map = {};
|
|
3147
|
-
for (const item of detail.items) {
|
|
3148
|
-
const slugRaw = item[primaryKey];
|
|
3149
|
-
if (typeof slugRaw !== "string" || slugRaw.length === 0) continue;
|
|
3150
|
-
const displayRaw = item[displayField];
|
|
3151
|
-
map[slugRaw] = typeof displayRaw === "string" && displayRaw.length > 0 ? displayRaw : slugRaw;
|
|
3152
|
-
}
|
|
3153
|
-
return map;
|
|
3154
|
-
}
|
|
3155
|
-
function buildRefRecordMap(detail) {
|
|
3156
|
-
const { schema } = detail.collection;
|
|
3157
|
-
const map = {};
|
|
3158
|
-
for (const item of detail.items) {
|
|
3159
|
-
const slugRaw = item[schema.primaryKey];
|
|
3160
|
-
if (typeof slugRaw === "string" && slugRaw.length > 0) map[slugRaw] = (0, _mulmoclaude_core_collection.deriveAll)(schema, item, {});
|
|
3161
|
-
}
|
|
3162
|
-
return map;
|
|
3163
|
-
}
|
|
3164
|
-
function sortedRefOptions(map) {
|
|
3165
|
-
return Object.entries(map).map(([slug, display]) => ({
|
|
3166
|
-
slug,
|
|
3167
|
-
display
|
|
3168
|
-
})).sort((left, right) => left.display.localeCompare(right.display));
|
|
3169
|
-
}
|
|
3170
|
-
/** Dropdown options for an `embed` field's per-record picker: every
|
|
3171
|
-
* record in the target collection, labelled by its name/title (or
|
|
3172
|
-
* primary key), skipping records without a slug and sorted by label. */
|
|
3173
|
-
function buildEmbedOptions(schema, items) {
|
|
3174
|
-
const { fields, primaryKey } = schema;
|
|
3175
|
-
const displayField = displayFieldFor(fields, primaryKey);
|
|
3176
|
-
return items.map((item) => {
|
|
3177
|
-
const slug = String(item[primaryKey] ?? "");
|
|
3178
|
-
const labelRaw = item[displayField];
|
|
3179
|
-
return {
|
|
3180
|
-
slug,
|
|
3181
|
-
display: typeof labelRaw === "string" && labelRaw.length > 0 ? labelRaw : slug
|
|
3182
|
-
};
|
|
3183
|
-
}).filter((opt) => opt.slug.length > 0).sort((left, right) => left.display.localeCompare(right.display));
|
|
3184
|
-
}
|
|
3185
|
-
//#endregion
|
|
3186
3451
|
//#region src/vue/useLinkedCollectionCaches.ts
|
|
3187
3452
|
/** The de-duplicated ref + embed target slugs a schema links to. `allTargets`
|
|
3188
|
-
* is the union (each target fetched once even when both ref'd and embedded).
|
|
3453
|
+
* is the union (each target fetched once even when both ref'd and embedded).
|
|
3454
|
+
* `backlinks` SOURCE collections ride in `embedTargets`: a backlink needs
|
|
3455
|
+
* exactly what an embed target caches (the source's schema + items in
|
|
3456
|
+
* `embedCache`), so reverse sources reuse that cache rather than adding a
|
|
3457
|
+
* parallel one. */
|
|
3189
3458
|
function linkedTargets(schema) {
|
|
3190
3459
|
const refTargets = new Set(uniqueRefTargets(schema));
|
|
3191
|
-
const embedTargets = new Set(uniqueEmbedTargets(schema));
|
|
3460
|
+
const embedTargets = /* @__PURE__ */ new Set([...uniqueEmbedTargets(schema), ...uniqueBacklinkSources(schema)]);
|
|
3192
3461
|
return {
|
|
3193
3462
|
refTargets,
|
|
3194
3463
|
embedTargets,
|
|
@@ -3333,14 +3602,113 @@ function buildEmbedViews(schema, embedCache, record, locale) {
|
|
|
3333
3602
|
}
|
|
3334
3603
|
return out;
|
|
3335
3604
|
}
|
|
3605
|
+
/** One backlinks table CELL: money formatted with its currency, anything
|
|
3606
|
+
* else through the same `formatCell` list tables use — so a markdown
|
|
3607
|
+
* source column (a worklog `notes`) shows the one-line 80-char preview,
|
|
3608
|
+
* not the whole text. Unknown `display` key ⇒ plain text (fail-soft). */
|
|
3609
|
+
function formatBacklinkCell(sourceField, value, row, locale) {
|
|
3610
|
+
if (!sourceField) return detailText(value);
|
|
3611
|
+
if (sourceField.type === "money") return formatMoney(value, resolveCurrency(sourceField, row), locale);
|
|
3612
|
+
return formatCell(value, sourceField.type);
|
|
3613
|
+
}
|
|
3614
|
+
/** Build the read-only backlinks view-models for one record: for each
|
|
3615
|
+
* `backlinks` field, the rows of `from` whose `via` points at the open
|
|
3616
|
+
* record (matched via the SHARED `backlinkRows`, on source records
|
|
3617
|
+
* derived exactly like the server's enrichment — so a `display`/`filter`
|
|
3618
|
+
* on a derived column such as an invoice `total` agrees on both sides).
|
|
3619
|
+
* Source data comes out of `embedCache` (reverse sources ride the embed
|
|
3620
|
+
* fan-out — see `linkedTargets`). Fail-soft: an unloadable source or an
|
|
3621
|
+
* unknown `display` key degrades to `found: false` / a raw-key column,
|
|
3622
|
+
* never a throw. */
|
|
3623
|
+
function buildBacklinksViews(schema, embedCache, record, locale) {
|
|
3624
|
+
const out = {};
|
|
3625
|
+
if (!schema) return out;
|
|
3626
|
+
for (const [key, field] of Object.entries(schema.fields)) {
|
|
3627
|
+
if (field.type !== "backlinks") continue;
|
|
3628
|
+
const columns = field.display.map((col) => ({
|
|
3629
|
+
key: col,
|
|
3630
|
+
label: col
|
|
3631
|
+
}));
|
|
3632
|
+
const data = embedCache[field.from];
|
|
3633
|
+
if (!data) {
|
|
3634
|
+
out[key] = {
|
|
3635
|
+
found: false,
|
|
3636
|
+
columns,
|
|
3637
|
+
rows: [],
|
|
3638
|
+
fromSlug: field.from
|
|
3639
|
+
};
|
|
3640
|
+
continue;
|
|
3641
|
+
}
|
|
3642
|
+
for (const column of columns) column.label = data.schema.fields[column.key]?.label ?? column.key;
|
|
3643
|
+
out[key] = {
|
|
3644
|
+
found: true,
|
|
3645
|
+
columns,
|
|
3646
|
+
rows: (0, _mulmoclaude_core_collection.backlinkRows)(field, String(record?.[schema.primaryKey] ?? ""), derivedSourceItems(embedCache, field.from) ?? []).map((row) => ({
|
|
3647
|
+
id: String(row[data.schema.primaryKey] ?? ""),
|
|
3648
|
+
cells: columns.map((column) => formatBacklinkCell(data.schema.fields[column.key], row[column.key], row, locale))
|
|
3649
|
+
})),
|
|
3650
|
+
fromSlug: field.from
|
|
3651
|
+
};
|
|
3652
|
+
}
|
|
3653
|
+
return out;
|
|
3654
|
+
}
|
|
3655
|
+
var derivedSourceMemo = /* @__PURE__ */ new WeakMap();
|
|
3656
|
+
function derivedSourceItems(embedCache, from) {
|
|
3657
|
+
const data = embedCache[from];
|
|
3658
|
+
if (!data) return null;
|
|
3659
|
+
let bySlug = derivedSourceMemo.get(embedCache);
|
|
3660
|
+
if (!bySlug) {
|
|
3661
|
+
bySlug = /* @__PURE__ */ new Map();
|
|
3662
|
+
derivedSourceMemo.set(embedCache, bySlug);
|
|
3663
|
+
}
|
|
3664
|
+
let items = bySlug.get(from);
|
|
3665
|
+
if (!items) {
|
|
3666
|
+
items = Object.values(derivedRecordsById(data.schema, data.items));
|
|
3667
|
+
bySlug.set(from, items);
|
|
3668
|
+
}
|
|
3669
|
+
return items;
|
|
3670
|
+
}
|
|
3671
|
+
/** The rollup scalar for one record, from the reverse sources riding the
|
|
3672
|
+
* embed cache — the SAME index (non-empty ids, one record per id, derived
|
|
3673
|
+
* against themselves) and the SAME `rollupValue` the server enrichment
|
|
3674
|
+
* uses, so the cell and getItems can't disagree. Null (em-dash) when the
|
|
3675
|
+
* source collection isn't loadable; a real 0 for an empty match set. */
|
|
3676
|
+
function rollupValueFor(field, record, schema, embedCache) {
|
|
3677
|
+
if (field.type !== "rollup" || !schema || !record) return null;
|
|
3678
|
+
const items = derivedSourceItems(embedCache, field.from);
|
|
3679
|
+
if (items === null) return null;
|
|
3680
|
+
return (0, _mulmoclaude_core_collection.rollupValue)(field, String(record[schema.primaryKey] ?? ""), items);
|
|
3681
|
+
}
|
|
3682
|
+
/** Display string for a rollup cell: the aggregate as a plain number,
|
|
3683
|
+
* em-dash when the source collection couldn't be resolved. */
|
|
3684
|
+
function renderRollup(field, record, schema, embedCache) {
|
|
3685
|
+
const value = rollupValueFor(field, record, schema, embedCache);
|
|
3686
|
+
return value === null ? "—" : formatCell(value, "number");
|
|
3687
|
+
}
|
|
3688
|
+
/** Copy of `item` with every rollup field resolved from the reverse
|
|
3689
|
+
* sources — injected BEFORE the formula pass so a `derived` formula can
|
|
3690
|
+
* read rollup values as plain identifiers (`played = homePlayed +
|
|
3691
|
+
* awayPlayed`), in the same rollups-then-formulas order the server
|
|
3692
|
+
* enrichment runs. Returns `item` unchanged when the schema declares no
|
|
3693
|
+
* rollups (the overwhelmingly common case — no copy). */
|
|
3694
|
+
function withRollupValues(schema, item, embedCache) {
|
|
3695
|
+
if (!schema) return item;
|
|
3696
|
+
let out = item;
|
|
3697
|
+
for (const [key, field] of Object.entries(schema.fields)) {
|
|
3698
|
+
if (field.type !== "rollup") continue;
|
|
3699
|
+
if (out === item) out = { ...item };
|
|
3700
|
+
out[key] = rollupValueFor(field, item, schema, embedCache);
|
|
3701
|
+
}
|
|
3702
|
+
return out;
|
|
3703
|
+
}
|
|
3336
3704
|
function renderSubCell(subField, value, record, refCache, locale) {
|
|
3337
3705
|
if (subField.type === "money") return formatMoney(value, resolveCurrency(subField, record), locale);
|
|
3338
3706
|
if (subField.type === "ref" && subField.to && typeof value === "string" && value.length > 0) return lookupRefDisplay(refCache, subField.to, value);
|
|
3339
3707
|
return formatCell(value, subField.type);
|
|
3340
3708
|
}
|
|
3341
|
-
function evaluateDerived(field, fieldKey, item, schema, refRecords) {
|
|
3709
|
+
function evaluateDerived(field, fieldKey, item, schema, refRecords, embedCache = {}) {
|
|
3342
3710
|
if (field.type !== "derived" || !schema) return null;
|
|
3343
|
-
const result = (0, _mulmoclaude_core_collection.deriveAll)(schema, item, refRecords)[fieldKey];
|
|
3711
|
+
const result = (0, _mulmoclaude_core_collection.deriveAll)(schema, withRollupValues(schema, item, embedCache), refRecords)[fieldKey];
|
|
3344
3712
|
return typeof result === "number" && Number.isFinite(result) ? result : null;
|
|
3345
3713
|
}
|
|
3346
3714
|
function renderDerived(field, computedValue, record, locale) {
|
|
@@ -3373,11 +3741,18 @@ function useCollectionRendering(collection, locale) {
|
|
|
3373
3741
|
refOptions: (targetSlug) => refOptionsFor(refCache.value, targetSlug),
|
|
3374
3742
|
embedOptions: (targetSlug) => embedOptionsFor(embedCache.value, targetSlug),
|
|
3375
3743
|
embedViewsFor: (record) => buildEmbedViews(collection.value?.schema ?? null, embedCache.value, record, locale.value),
|
|
3744
|
+
backlinksViewsFor: (record) => buildBacklinksViews(collection.value?.schema ?? null, embedCache.value, record, locale.value),
|
|
3745
|
+
rollupDisplay: (field, record) => renderRollup(field, record, collection.value?.schema ?? null, embedCache.value),
|
|
3376
3746
|
currencySymbol: (currency) => currencySymbolForLocale(currency, locale.value),
|
|
3377
3747
|
artifactUrl: (value) => collectionUi().fileAssetUrl(value),
|
|
3378
3748
|
fileRoutePath: (value) => collectionUi().fileRoutePath(value),
|
|
3379
3749
|
formatSubCell: (subField, value, record) => renderSubCell(subField, value, record, refCache.value, locale.value),
|
|
3380
|
-
evaluateDerivedAgainstItem: (field, fieldKey, item) => evaluateDerived(field, fieldKey, item, collection.value?.schema ?? null, refRecordCache.value),
|
|
3750
|
+
evaluateDerivedAgainstItem: (field, fieldKey, item) => evaluateDerived(field, fieldKey, item, collection.value?.schema ?? null, refRecordCache.value, embedCache.value),
|
|
3751
|
+
deriveRecord: (item) => {
|
|
3752
|
+
const schema = collection.value?.schema ?? null;
|
|
3753
|
+
if (!schema) return item;
|
|
3754
|
+
return (0, _mulmoclaude_core_collection.deriveAll)(schema, withRollupValues(schema, item, embedCache.value), refRecordCache.value);
|
|
3755
|
+
},
|
|
3381
3756
|
derivedDisplay: (field, computedValue, record) => renderDerived(field, computedValue, record, locale.value)
|
|
3382
3757
|
};
|
|
3383
3758
|
}
|
|
@@ -3494,206 +3869,211 @@ var _hoisted_11$4 = [
|
|
|
3494
3869
|
];
|
|
3495
3870
|
var _hoisted_12$4 = {
|
|
3496
3871
|
key: 0,
|
|
3872
|
+
class: "material-icons text-sm animate-spin"
|
|
3873
|
+
};
|
|
3874
|
+
var _hoisted_13$4 = {
|
|
3875
|
+
key: 1,
|
|
3497
3876
|
class: "material-icons text-sm"
|
|
3498
3877
|
};
|
|
3499
|
-
var _hoisted_13$4 = ["title", "aria-label"];
|
|
3500
3878
|
var _hoisted_14$4 = ["title", "aria-label"];
|
|
3501
|
-
var _hoisted_15$4 =
|
|
3879
|
+
var _hoisted_15$4 = ["title", "aria-label"];
|
|
3880
|
+
var _hoisted_16$4 = {
|
|
3502
3881
|
key: 1,
|
|
3503
3882
|
class: "mx-6 mt-2 rounded-lg border border-indigo-200 bg-indigo-50/60 px-4 py-2 text-sm text-indigo-800 flex items-center gap-2",
|
|
3504
3883
|
"data-testid": "collections-refresh-note"
|
|
3505
3884
|
};
|
|
3506
|
-
var
|
|
3507
|
-
var
|
|
3885
|
+
var _hoisted_17$4 = { class: "flex-1" };
|
|
3886
|
+
var _hoisted_18$4 = {
|
|
3508
3887
|
key: 2,
|
|
3509
3888
|
class: "px-6 py-3 bg-white border-b border-slate-100 flex items-center justify-between gap-4"
|
|
3510
3889
|
};
|
|
3511
|
-
var
|
|
3890
|
+
var _hoisted_19$2 = {
|
|
3512
3891
|
key: 0,
|
|
3513
3892
|
class: "relative flex-1 max-w-md"
|
|
3514
3893
|
};
|
|
3515
|
-
var
|
|
3516
|
-
var
|
|
3517
|
-
var
|
|
3518
|
-
var
|
|
3519
|
-
var _hoisted_23$2 = ["aria-pressed"];
|
|
3894
|
+
var _hoisted_20$2 = ["placeholder", "aria-label"];
|
|
3895
|
+
var _hoisted_21$2 = ["aria-label"];
|
|
3896
|
+
var _hoisted_22$2 = { class: "flex items-center gap-2" };
|
|
3897
|
+
var _hoisted_23$2 = ["aria-label"];
|
|
3520
3898
|
var _hoisted_24$1 = ["aria-pressed"];
|
|
3521
3899
|
var _hoisted_25$1 = ["aria-pressed"];
|
|
3522
|
-
var _hoisted_26$1 = [
|
|
3900
|
+
var _hoisted_26$1 = ["aria-pressed"];
|
|
3901
|
+
var _hoisted_27$1 = [
|
|
3523
3902
|
"aria-pressed",
|
|
3524
3903
|
"data-testid",
|
|
3525
3904
|
"onClick"
|
|
3526
3905
|
];
|
|
3527
|
-
var
|
|
3528
|
-
var
|
|
3906
|
+
var _hoisted_28 = { class: "material-icons text-sm" };
|
|
3907
|
+
var _hoisted_29 = [
|
|
3529
3908
|
"title",
|
|
3530
3909
|
"aria-label",
|
|
3531
3910
|
"aria-expanded"
|
|
3532
3911
|
];
|
|
3533
|
-
var
|
|
3912
|
+
var _hoisted_30 = {
|
|
3534
3913
|
key: 0,
|
|
3535
3914
|
class: "absolute left-0 top-full mt-1 z-20 min-w-max rounded border border-slate-200 bg-white shadow-lg py-1",
|
|
3536
3915
|
"data-testid": "collection-view-add-menu"
|
|
3537
3916
|
};
|
|
3538
|
-
var
|
|
3539
|
-
var
|
|
3540
|
-
var
|
|
3541
|
-
var
|
|
3542
|
-
var
|
|
3543
|
-
var
|
|
3917
|
+
var _hoisted_31 = ["title", "aria-label"];
|
|
3918
|
+
var _hoisted_32 = ["value", "aria-label"];
|
|
3919
|
+
var _hoisted_33 = ["value"];
|
|
3920
|
+
var _hoisted_34 = ["value", "aria-label"];
|
|
3921
|
+
var _hoisted_35 = ["value"];
|
|
3922
|
+
var _hoisted_36 = {
|
|
3544
3923
|
key: 3,
|
|
3545
3924
|
class: "text-[10px] text-slate-400 font-bold uppercase tracking-wider select-none"
|
|
3546
3925
|
};
|
|
3547
|
-
var
|
|
3926
|
+
var _hoisted_37 = {
|
|
3548
3927
|
key: 3,
|
|
3549
3928
|
class: "mx-6 mt-4 rounded-xl border border-amber-200 bg-amber-50/60 p-4 text-sm text-amber-900 shadow-sm flex items-center gap-3",
|
|
3550
3929
|
"data-testid": "collections-data-issues"
|
|
3551
3930
|
};
|
|
3552
|
-
var
|
|
3553
|
-
var
|
|
3554
|
-
var
|
|
3931
|
+
var _hoisted_38 = { class: "flex-1" };
|
|
3932
|
+
var _hoisted_39 = { class: "flex-1 overflow-auto" };
|
|
3933
|
+
var _hoisted_40 = {
|
|
3555
3934
|
key: 0,
|
|
3556
3935
|
class: "flex flex-col items-center justify-center py-20 text-sm text-slate-500 gap-3"
|
|
3557
3936
|
};
|
|
3558
|
-
var
|
|
3937
|
+
var _hoisted_41 = {
|
|
3559
3938
|
key: 1,
|
|
3560
3939
|
class: "m-6 rounded-xl border border-red-200 bg-red-50/50 p-4 text-sm text-red-800 shadow-sm flex items-center gap-3"
|
|
3561
3940
|
};
|
|
3562
|
-
var
|
|
3563
|
-
var
|
|
3941
|
+
var _hoisted_42 = { key: 2 };
|
|
3942
|
+
var _hoisted_43 = {
|
|
3564
3943
|
key: 3,
|
|
3565
3944
|
class: "p-4"
|
|
3566
3945
|
};
|
|
3567
|
-
var
|
|
3946
|
+
var _hoisted_44 = {
|
|
3568
3947
|
key: 4,
|
|
3569
3948
|
class: "h-full flex flex-col"
|
|
3570
3949
|
};
|
|
3571
|
-
var
|
|
3950
|
+
var _hoisted_45 = {
|
|
3572
3951
|
key: 0,
|
|
3573
3952
|
class: "m-3 mb-0 rounded-xl border border-red-200 bg-red-50/50 p-4 text-sm text-red-800 shadow-sm flex items-center gap-3",
|
|
3574
3953
|
"data-testid": "collections-inline-error"
|
|
3575
3954
|
};
|
|
3576
|
-
var
|
|
3577
|
-
var
|
|
3578
|
-
var
|
|
3579
|
-
var
|
|
3955
|
+
var _hoisted_46 = { class: "flex-1" };
|
|
3956
|
+
var _hoisted_47 = ["aria-label"];
|
|
3957
|
+
var _hoisted_48 = { class: "flex-1 min-h-0 px-3 py-2" };
|
|
3958
|
+
var _hoisted_49 = {
|
|
3580
3959
|
key: 5,
|
|
3581
3960
|
class: "h-full",
|
|
3582
3961
|
"data-testid": "collection-custom-view-body"
|
|
3583
3962
|
};
|
|
3584
|
-
var
|
|
3963
|
+
var _hoisted_50 = {
|
|
3585
3964
|
key: 6,
|
|
3586
3965
|
class: "flex flex-col items-center justify-center py-20 text-sm text-slate-400 gap-2"
|
|
3587
3966
|
};
|
|
3588
|
-
var
|
|
3589
|
-
var
|
|
3967
|
+
var _hoisted_51 = { class: "font-semibold text-slate-600" };
|
|
3968
|
+
var _hoisted_52 = {
|
|
3590
3969
|
key: 7,
|
|
3591
3970
|
class: "flex flex-col items-center justify-center py-20 text-sm text-slate-400 gap-2"
|
|
3592
3971
|
};
|
|
3593
|
-
var
|
|
3594
|
-
var
|
|
3972
|
+
var _hoisted_53 = { class: "font-semibold text-slate-600" };
|
|
3973
|
+
var _hoisted_54 = {
|
|
3595
3974
|
key: 8,
|
|
3596
3975
|
class: "overflow-x-auto [container-type:inline-size]"
|
|
3597
3976
|
};
|
|
3598
|
-
var
|
|
3977
|
+
var _hoisted_55 = {
|
|
3599
3978
|
key: 0,
|
|
3600
3979
|
class: "m-4 rounded-xl border border-red-200 bg-red-50/50 p-4 text-sm text-red-800 shadow-sm flex items-center gap-3",
|
|
3601
3980
|
"data-testid": "collections-inline-error"
|
|
3602
3981
|
};
|
|
3603
|
-
var
|
|
3604
|
-
var
|
|
3605
|
-
var
|
|
3606
|
-
var
|
|
3607
|
-
var
|
|
3608
|
-
var
|
|
3609
|
-
var
|
|
3610
|
-
var
|
|
3982
|
+
var _hoisted_56 = { class: "flex-1" };
|
|
3983
|
+
var _hoisted_57 = ["aria-label"];
|
|
3984
|
+
var _hoisted_58 = { class: "min-w-full text-xs" };
|
|
3985
|
+
var _hoisted_59 = { class: "bg-slate-50 border-b border-slate-200" };
|
|
3986
|
+
var _hoisted_60 = ["aria-sort"];
|
|
3987
|
+
var _hoisted_61 = { class: "flex items-center gap-1" };
|
|
3988
|
+
var _hoisted_62 = ["title"];
|
|
3989
|
+
var _hoisted_63 = [
|
|
3611
3990
|
"data-testid",
|
|
3612
3991
|
"aria-label",
|
|
3613
3992
|
"onClick",
|
|
3614
3993
|
"onPointerenter"
|
|
3615
3994
|
];
|
|
3616
|
-
var
|
|
3617
|
-
var
|
|
3618
|
-
var
|
|
3995
|
+
var _hoisted_64 = { class: "material-icons text-base align-middle" };
|
|
3996
|
+
var _hoisted_65 = { class: "divide-y divide-slate-100 bg-white" };
|
|
3997
|
+
var _hoisted_66 = [
|
|
3619
3998
|
"aria-label",
|
|
3620
3999
|
"data-testid",
|
|
3621
4000
|
"onClick",
|
|
3622
4001
|
"onKeydown"
|
|
3623
4002
|
];
|
|
3624
|
-
var
|
|
4003
|
+
var _hoisted_67 = [
|
|
3625
4004
|
"checked",
|
|
3626
4005
|
"disabled",
|
|
3627
4006
|
"data-testid",
|
|
3628
4007
|
"aria-label",
|
|
3629
4008
|
"onChange"
|
|
3630
4009
|
];
|
|
3631
|
-
var
|
|
4010
|
+
var _hoisted_68 = [
|
|
3632
4011
|
"checked",
|
|
3633
4012
|
"disabled",
|
|
3634
4013
|
"data-testid",
|
|
3635
4014
|
"aria-label",
|
|
3636
4015
|
"onChange"
|
|
3637
4016
|
];
|
|
3638
|
-
var
|
|
4017
|
+
var _hoisted_69 = {
|
|
3639
4018
|
key: 2,
|
|
3640
4019
|
class: "block truncate"
|
|
3641
4020
|
};
|
|
3642
|
-
var
|
|
4021
|
+
var _hoisted_70 = [
|
|
3643
4022
|
"href",
|
|
3644
4023
|
"tabindex",
|
|
3645
4024
|
"data-testid",
|
|
3646
4025
|
"onClick",
|
|
3647
4026
|
"onKeydown"
|
|
3648
4027
|
];
|
|
3649
|
-
var
|
|
4028
|
+
var _hoisted_71 = [
|
|
3650
4029
|
"value",
|
|
3651
4030
|
"disabled",
|
|
3652
4031
|
"data-testid",
|
|
3653
4032
|
"aria-label",
|
|
3654
4033
|
"onChange"
|
|
3655
4034
|
];
|
|
3656
|
-
var
|
|
4035
|
+
var _hoisted_72 = {
|
|
3657
4036
|
key: 0,
|
|
3658
4037
|
value: ""
|
|
3659
4038
|
};
|
|
3660
|
-
var
|
|
3661
|
-
var
|
|
4039
|
+
var _hoisted_73 = ["value"];
|
|
4040
|
+
var _hoisted_74 = {
|
|
3662
4041
|
key: 4,
|
|
3663
4042
|
class: "block truncate tabular-nums font-semibold text-slate-900"
|
|
3664
4043
|
};
|
|
3665
|
-
var
|
|
4044
|
+
var _hoisted_75 = {
|
|
3666
4045
|
key: 5,
|
|
3667
4046
|
class: "inline-flex items-center gap-1 px-2 py-0.5 rounded-lg text-[10px] font-bold bg-slate-100 text-slate-600 border border-slate-200/40"
|
|
3668
4047
|
};
|
|
3669
|
-
var
|
|
4048
|
+
var _hoisted_76 = {
|
|
3670
4049
|
key: 6,
|
|
3671
4050
|
class: "inline-block truncate tabular-nums font-bold text-indigo-900 bg-indigo-50/50 px-1.5 py-0.5 rounded border border-indigo-100/50"
|
|
3672
4051
|
};
|
|
3673
|
-
var
|
|
3674
|
-
var
|
|
3675
|
-
var
|
|
4052
|
+
var _hoisted_77 = ["data-testid"];
|
|
4053
|
+
var _hoisted_78 = ["href", "data-testid"];
|
|
4054
|
+
var _hoisted_79 = ["href", "data-testid"];
|
|
4055
|
+
var _hoisted_80 = [
|
|
3676
4056
|
"href",
|
|
3677
4057
|
"data-testid",
|
|
3678
4058
|
"onClick"
|
|
3679
4059
|
];
|
|
3680
|
-
var
|
|
3681
|
-
key:
|
|
4060
|
+
var _hoisted_81 = {
|
|
4061
|
+
key: 11,
|
|
3682
4062
|
class: "block truncate text-slate-600"
|
|
3683
4063
|
};
|
|
3684
|
-
var
|
|
3685
|
-
var
|
|
3686
|
-
var
|
|
3687
|
-
var
|
|
4064
|
+
var _hoisted_82 = { class: "bg-white rounded-2xl shadow-2xl w-full max-w-xl flex flex-col border border-slate-200 overflow-hidden" };
|
|
4065
|
+
var _hoisted_83 = { class: "px-6 py-4 border-b border-slate-100 flex items-center gap-3 bg-slate-50/50" };
|
|
4066
|
+
var _hoisted_84 = { class: "flex-1" };
|
|
4067
|
+
var _hoisted_85 = {
|
|
3688
4068
|
id: "collections-chat-title",
|
|
3689
4069
|
class: "text-sm font-bold text-slate-800 uppercase tracking-wide"
|
|
3690
4070
|
};
|
|
3691
|
-
var
|
|
3692
|
-
var
|
|
3693
|
-
var
|
|
3694
|
-
var
|
|
3695
|
-
var
|
|
3696
|
-
var
|
|
4071
|
+
var _hoisted_86 = { class: "text-xs text-slate-400 font-semibold" };
|
|
4072
|
+
var _hoisted_87 = ["aria-label"];
|
|
4073
|
+
var _hoisted_88 = { class: "px-6 py-5" };
|
|
4074
|
+
var _hoisted_89 = ["placeholder", "onKeydown"];
|
|
4075
|
+
var _hoisted_90 = { class: "px-6 py-3.5 border-t border-slate-100 flex items-center justify-end gap-2 bg-slate-50/50" };
|
|
4076
|
+
var _hoisted_91 = ["disabled"];
|
|
3697
4077
|
/** `slug` / `selected` are supplied only in EMBEDDED mode (the
|
|
3698
4078
|
* `presentCollection` chat card mounts this component and drives both
|
|
3699
4079
|
* from the tool result). In standalone route mode (the
|
|
@@ -3795,11 +4175,26 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
3795
4175
|
const actionPending = (0, vue.ref)(false);
|
|
3796
4176
|
const actionError = (0, vue.ref)(null);
|
|
3797
4177
|
const collectionActionPending = (0, vue.ref)(false);
|
|
4178
|
+
const runningActions = (0, vue.ref)(/* @__PURE__ */ new Set());
|
|
4179
|
+
let runningActionsGen = 0;
|
|
4180
|
+
function mutateRunningActions(mutate) {
|
|
4181
|
+
runningActionsGen += 1;
|
|
4182
|
+
const next = new Set(runningActions.value);
|
|
4183
|
+
mutate(next);
|
|
4184
|
+
runningActions.value = next;
|
|
4185
|
+
}
|
|
4186
|
+
/** Adopt a detail response's `runningActions` — only when no local
|
|
4187
|
+
* mutation happened while the response was in flight (stale snapshots
|
|
4188
|
+
* are dropped; the completion ping's refetch reconciles soon after). */
|
|
4189
|
+
function applyServerRunningActions(keys, genAtFetch) {
|
|
4190
|
+
if (runningActionsGen !== genAtFetch) return;
|
|
4191
|
+
runningActions.value = new Set(keys ?? []);
|
|
4192
|
+
}
|
|
3798
4193
|
const chatOpen = (0, vue.ref)(false);
|
|
3799
4194
|
const chatMessage = (0, vue.ref)("");
|
|
3800
4195
|
const chatInputEl = (0, vue.ref)(null);
|
|
3801
4196
|
const render = useCollectionRendering(collection, locale);
|
|
3802
|
-
const {
|
|
4197
|
+
const { refDisplay, formatMoney, resolveCurrency, derivedDisplay, evaluateDerivedAgainstItem, formatCell, isExternalUrl, artifactUrl, fileRoutePath } = render;
|
|
3803
4198
|
const searchQuery = (0, vue.ref)("");
|
|
3804
4199
|
/** Case-insensitive substring match across an item's scalar fields.
|
|
3805
4200
|
* Object-valued fields (table rows, nested records) are skipped —
|
|
@@ -3873,7 +4268,7 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
3873
4268
|
function derivedSortValue(field, key, item) {
|
|
3874
4269
|
const display = field.type === "derived" ? field.display : void 0;
|
|
3875
4270
|
if (display === void 0 || display === "number" || display === "money") return (0, _mulmoclaude_core_collection.numericSortValue)(evaluateDerivedAgainstItem(field, key, item));
|
|
3876
|
-
const enriched =
|
|
4271
|
+
const enriched = render.deriveRecord(item);
|
|
3877
4272
|
if (display === "date") return (0, _mulmoclaude_core_collection.dateSortValue)(enriched[key]);
|
|
3878
4273
|
return (0, _mulmoclaude_core_collection.stringSortValue)(enriched[key]);
|
|
3879
4274
|
}
|
|
@@ -3961,20 +4356,33 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
3961
4356
|
}
|
|
3962
4357
|
/** Collection-level header actions. No `when` predicate (no record). */
|
|
3963
4358
|
const collectionActions = (0, vue.computed)(() => collection.value?.schema.collectionActions ?? []);
|
|
4359
|
+
/** True when a `kind: "agent"` action's hidden worker is in flight —
|
|
4360
|
+
* drives the button spinner + disable. Keys mirror the server's
|
|
4361
|
+
* dispatch guard via `agentActionRunKey`. */
|
|
4362
|
+
function isActionRunning(actionId, itemId) {
|
|
4363
|
+
return runningActions.value.has((0, _mulmoclaude_core_collection.agentActionRunKey)(actionId, itemId));
|
|
4364
|
+
}
|
|
3964
4365
|
/** Run a collection-level action: ask the server to assemble the seed
|
|
3965
|
-
* prompt (a progress summary of all records + the template)
|
|
3966
|
-
*
|
|
4366
|
+
* prompt (a progress summary of all records + the template). `kind:
|
|
4367
|
+
* "chat"` gets the seed back and starts a new chat; `kind: "agent"` is
|
|
4368
|
+
* dispatched server-side as a hidden worker — mark it running and let
|
|
4369
|
+
* the completion ping's refetch reconcile. Generic — no domain knowledge. */
|
|
3967
4370
|
async function runCollectionAction(action) {
|
|
3968
4371
|
const current = collection.value;
|
|
3969
|
-
if (!current || collectionActionPending.value) return;
|
|
4372
|
+
if (!current || collectionActionPending.value || isActionRunning(action.id)) return;
|
|
4373
|
+
const runKey = action.kind === "agent" ? (0, _mulmoclaude_core_collection.agentActionRunKey)(action.id) : null;
|
|
4374
|
+
if (runKey) mutateRunningActions((next) => next.add(runKey));
|
|
3970
4375
|
collectionActionPending.value = true;
|
|
3971
4376
|
inlineError.value = null;
|
|
3972
4377
|
const result = await cui.runCollectionAction(current.slug, action.id);
|
|
3973
4378
|
collectionActionPending.value = false;
|
|
3974
4379
|
if (!result.ok) {
|
|
4380
|
+
if (runKey && result.status !== 409) mutateRunningActions((next) => next.delete(runKey));
|
|
3975
4381
|
inlineError.value = result.error;
|
|
3976
4382
|
return;
|
|
3977
4383
|
}
|
|
4384
|
+
if (result.data.dispatched) return;
|
|
4385
|
+
if (result.data.written) return;
|
|
3978
4386
|
if (props.sendTextMessage) {
|
|
3979
4387
|
props.sendTextMessage(result.data.prompt);
|
|
3980
4388
|
return;
|
|
@@ -4009,27 +4417,88 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
4009
4417
|
if (!record) return [];
|
|
4010
4418
|
return (collection.value?.schema.actions ?? []).filter((action) => (0, _mulmoclaude_core_collection.actionVisible)(action, record));
|
|
4011
4419
|
});
|
|
4012
|
-
|
|
4013
|
-
|
|
4014
|
-
|
|
4420
|
+
const mutateModal = (0, vue.ref)(null);
|
|
4421
|
+
const mutatePending = (0, vue.ref)(false);
|
|
4422
|
+
const mutateError = (0, vue.ref)(null);
|
|
4423
|
+
/** POST one mutate action and, on success, adopt the written record for
|
|
4424
|
+
* the open panel (the write's change ping refreshes the table rows).
|
|
4425
|
+
* Errors land in the modal when one is open, else on the panel. */
|
|
4426
|
+
async function executeMutate(action, itemId, params) {
|
|
4427
|
+
if (!collection.value || mutatePending.value) return false;
|
|
4428
|
+
mutatePending.value = true;
|
|
4429
|
+
const result = await cui.runItemAction(collection.value.slug, itemId, action.id, params);
|
|
4430
|
+
mutatePending.value = false;
|
|
4431
|
+
if (!result.ok) {
|
|
4432
|
+
if (mutateModal.value) mutateError.value = result.error;
|
|
4433
|
+
else actionError.value = result.error;
|
|
4434
|
+
return false;
|
|
4435
|
+
}
|
|
4436
|
+
if (result.data.written && viewing.value && String(viewing.value[collection.value.schema.primaryKey] ?? "") === itemId) viewing.value = result.data.item;
|
|
4437
|
+
return true;
|
|
4438
|
+
}
|
|
4439
|
+
async function submitMutateParams(params) {
|
|
4440
|
+
const open = mutateModal.value;
|
|
4441
|
+
if (!open) return;
|
|
4442
|
+
mutateError.value = null;
|
|
4443
|
+
if (await executeMutate(open.action, open.itemId, params)) mutateModal.value = null;
|
|
4444
|
+
}
|
|
4445
|
+
/** Mutate kind: open the params mini-form when the action declares one,
|
|
4446
|
+
* else apply the declarative write immediately. */
|
|
4447
|
+
async function runMutateAction(action, itemId) {
|
|
4448
|
+
actionError.value = null;
|
|
4449
|
+
if (action.params && Object.keys(action.params).length > 0) {
|
|
4450
|
+
mutateError.value = null;
|
|
4451
|
+
mutateModal.value = {
|
|
4452
|
+
action,
|
|
4453
|
+
itemId
|
|
4454
|
+
};
|
|
4455
|
+
return;
|
|
4456
|
+
}
|
|
4457
|
+
await executeMutate(action, itemId, {});
|
|
4458
|
+
}
|
|
4459
|
+
/** Run a schema-declared action on the open record. `kind: "mutate"`
|
|
4460
|
+
* never leaves the host: with `params` it opens the mini-form, else it
|
|
4461
|
+
* applies immediately. `kind: "chat"` gets the seed back and starts a
|
|
4462
|
+
* new chat; `kind: "agent"` is dispatched server-side as a hidden
|
|
4463
|
+
* worker — mark it running and let the completion ping's refetch
|
|
4464
|
+
* reconcile. Generic — no knowledge of what the action does. */
|
|
4015
4465
|
async function runAction(action) {
|
|
4016
4466
|
if (!collection.value || !viewing.value) return;
|
|
4017
4467
|
const itemId = String(viewing.value[collection.value.schema.primaryKey] ?? "");
|
|
4018
|
-
if (!itemId) return;
|
|
4468
|
+
if (!itemId || isActionRunning(action.id, itemId)) return;
|
|
4469
|
+
if (action.kind === "mutate") {
|
|
4470
|
+
await runMutateAction(action, itemId);
|
|
4471
|
+
return;
|
|
4472
|
+
}
|
|
4473
|
+
const runKey = action.kind === "agent" ? (0, _mulmoclaude_core_collection.agentActionRunKey)(action.id, itemId) : null;
|
|
4474
|
+
if (runKey) mutateRunningActions((next) => next.add(runKey));
|
|
4019
4475
|
actionPending.value = true;
|
|
4020
4476
|
actionError.value = null;
|
|
4021
4477
|
const result = await cui.runItemAction(collection.value.slug, itemId, action.id);
|
|
4022
4478
|
actionPending.value = false;
|
|
4023
4479
|
if (!result.ok) {
|
|
4480
|
+
if (runKey && result.status !== 409) mutateRunningActions((next) => next.delete(runKey));
|
|
4024
4481
|
actionError.value = result.error;
|
|
4025
4482
|
return;
|
|
4026
4483
|
}
|
|
4484
|
+
if (result.data.dispatched) return;
|
|
4485
|
+
if (result.data.written) return;
|
|
4027
4486
|
if (props.sendTextMessage) {
|
|
4028
4487
|
props.sendTextMessage(result.data.prompt);
|
|
4029
4488
|
return;
|
|
4030
4489
|
}
|
|
4031
4490
|
appApi.startNewChat(result.data.prompt, result.data.role);
|
|
4032
4491
|
}
|
|
4492
|
+
/** Ids of the open record's actions whose hidden worker is running — the
|
|
4493
|
+
* record panel renders those buttons with a spinner, disabled. */
|
|
4494
|
+
const viewingRunningActionIds = (0, vue.computed)(() => {
|
|
4495
|
+
const current = collection.value;
|
|
4496
|
+
const record = viewing.value;
|
|
4497
|
+
if (!current || !record) return [];
|
|
4498
|
+
const itemId = String(record[current.schema.primaryKey] ?? "");
|
|
4499
|
+
if (!itemId) return [];
|
|
4500
|
+
return (current.schema.actions ?? []).filter((action) => isActionRunning(action.id, itemId)).map((action) => action.id);
|
|
4501
|
+
});
|
|
4033
4502
|
/** Open the chat modal, blanking any prior draft and focusing the input. */
|
|
4034
4503
|
function openChat() {
|
|
4035
4504
|
chatMessage.value = "";
|
|
@@ -4095,10 +4564,12 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
4095
4564
|
collection.value = null;
|
|
4096
4565
|
items.value = [];
|
|
4097
4566
|
dataIssues.value = [];
|
|
4567
|
+
mutateRunningActions((next) => next.clear());
|
|
4098
4568
|
searchQuery.value = "";
|
|
4099
4569
|
render.resetLinkedCaches();
|
|
4100
4570
|
viewing.value = null;
|
|
4101
4571
|
openDay.value = null;
|
|
4572
|
+
const runningGen = runningActionsGen;
|
|
4102
4573
|
const result = await cui.fetchCollectionDetail(slug);
|
|
4103
4574
|
loading.value = false;
|
|
4104
4575
|
if (!result.ok) {
|
|
@@ -4109,6 +4580,7 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
4109
4580
|
collection.value = result.data.collection;
|
|
4110
4581
|
items.value = result.data.items;
|
|
4111
4582
|
dataIssues.value = result.data.issues ?? [];
|
|
4583
|
+
applyServerRunningActions(result.data.runningActions, runningGen);
|
|
4112
4584
|
enumOriginallyEmpty.value = snapshotEmptyEnums(result.data.collection.schema, result.data.items);
|
|
4113
4585
|
await render.loadLinkedCollections(result.data.collection.schema, slug);
|
|
4114
4586
|
if (collection.value?.slug === slug) syncViewToSelected();
|
|
@@ -4124,11 +4596,13 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
4124
4596
|
* fetch is a no-op (keep the current data) — a transient blip shouldn't blank a
|
|
4125
4597
|
* view the user is reading. */
|
|
4126
4598
|
async function refreshItemsInPlace(slug) {
|
|
4599
|
+
const runningGen = runningActionsGen;
|
|
4127
4600
|
const result = await cui.fetchCollectionDetail(slug);
|
|
4128
4601
|
if (!result.ok || activeSlug.value !== slug) return;
|
|
4129
4602
|
collection.value = result.data.collection;
|
|
4130
4603
|
items.value = result.data.items;
|
|
4131
4604
|
dataIssues.value = result.data.issues ?? [];
|
|
4605
|
+
applyServerRunningActions(result.data.runningActions, runningGen);
|
|
4132
4606
|
enumOriginallyEmpty.value = snapshotEmptyEnums(result.data.collection.schema, result.data.items);
|
|
4133
4607
|
await render.loadLinkedCollections(result.data.collection.schema, slug);
|
|
4134
4608
|
if (activeSlug.value !== slug) return;
|
|
@@ -4149,7 +4623,7 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
4149
4623
|
* list table only (a whole embedded record doesn't fit a table cell,
|
|
4150
4624
|
* and it'd be identical in every row). The detail modal and the edit
|
|
4151
4625
|
* form iterate the full `schema.fields` so embeds render there too. */
|
|
4152
|
-
const listColumnFields = (0, vue.computed)(() => collection.value ? Object.entries(collection.value.schema.fields).filter(([key, field]) => field.type !== "embed" && field.type !== "image" && key !== collection.value?.schema.primaryKey) : []);
|
|
4626
|
+
const listColumnFields = (0, vue.computed)(() => collection.value ? Object.entries(collection.value.schema.fields).filter(([key, field]) => field.type !== "embed" && field.type !== "backlinks" && field.type !== "image" && key !== collection.value?.schema.primaryKey) : []);
|
|
4153
4627
|
/** True when the current collection declares `schema.singleton` —
|
|
4154
4628
|
* exactly one record, its primary key fixed to the declared value. */
|
|
4155
4629
|
const isSingleton = (0, vue.computed)(() => Boolean(collection.value?.schema.singleton));
|
|
@@ -4338,7 +4812,7 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
4338
4812
|
boolOriginallyPresent[key] = false;
|
|
4339
4813
|
boolTouched[key] = false;
|
|
4340
4814
|
} else if (field.type === "table") table[key] = [];
|
|
4341
|
-
else if (
|
|
4815
|
+
else if (!_mulmoclaude_core_collection.COMPUTED_TYPES.has(field.type)) text[key] = "";
|
|
4342
4816
|
const { singleton, primaryKey } = collection.value.schema;
|
|
4343
4817
|
if (singleton) text[primaryKey] = singleton;
|
|
4344
4818
|
else if (primaryKey in text) text[primaryKey] = generateUniqueItemId(primaryKey);
|
|
@@ -4370,7 +4844,7 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
4370
4844
|
} else if (field.type === "table" && field.of) {
|
|
4371
4845
|
const sub = field.of;
|
|
4372
4846
|
table[key] = (Array.isArray(raw) ? raw : []).filter((row) => Boolean(row) && typeof row === "object" && !Array.isArray(row)).map((row) => (0, _mulmoclaude_core_collection.rowFromItem)(row, sub));
|
|
4373
|
-
} else if (
|
|
4847
|
+
} else if (!_mulmoclaude_core_collection.COMPUTED_TYPES.has(field.type)) text[key] = raw === void 0 || raw === null ? "" : String(raw);
|
|
4374
4848
|
}
|
|
4375
4849
|
const primaryRaw = item[collection.value.schema.primaryKey];
|
|
4376
4850
|
const originalId = typeof primaryRaw === "string" ? primaryRaw : String(primaryRaw ?? "");
|
|
@@ -4497,7 +4971,7 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
4497
4971
|
* rendering composable; this binds it to the current draft. */
|
|
4498
4972
|
const liveDerived = (0, vue.computed)(() => {
|
|
4499
4973
|
if (!collection.value || !liveRecord.value) return null;
|
|
4500
|
-
return render.
|
|
4974
|
+
return render.deriveRecord(liveRecord.value);
|
|
4501
4975
|
});
|
|
4502
4976
|
/** Short summary for a `table`-typed cell in the main collection
|
|
4503
4977
|
* table. Counts rows; nothing fancier yet (per-row preview is
|
|
@@ -4818,7 +5292,7 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
4818
5292
|
"aria-label": (0, vue.unref)(t)("collectionsView.backToIndex"),
|
|
4819
5293
|
"data-testid": "collections-back",
|
|
4820
5294
|
onClick: goBack
|
|
4821
|
-
}, [..._cache[
|
|
5295
|
+
}, [..._cache[26] || (_cache[26] = [(0, vue.createElementVNode)("span", { class: "material-icons text-lg" }, "arrow_back", -1)])], 8, _hoisted_3$5)) : (0, vue.createCommentVNode)("", true),
|
|
4822
5296
|
collection.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_4$5, [(0, vue.createElementVNode)("span", _hoisted_5$5, (0, vue.toDisplayString)(collection.value.icon), 1)])) : (0, vue.createCommentVNode)("", true),
|
|
4823
5297
|
(0, vue.createElementVNode)("div", _hoisted_6$4, [(0, vue.createElementVNode)("h1", _hoisted_7$4, (0, vue.toDisplayString)(collection.value?.title ?? (0, vue.unref)(t)("collectionsView.title")), 1), collection.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_8$4, (0, vue.toDisplayString)(collection.value.slug), 1)) : (0, vue.createCommentVNode)("", true)]),
|
|
4824
5298
|
collection.value && !embedded.value ? ((0, vue.openBlock)(), (0, vue.createBlock)((0, vue.resolveDynamicComponent)((0, vue.unref)(pinToggle)), {
|
|
@@ -4847,16 +5321,16 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
4847
5321
|
class: "h-8 px-2.5 flex items-center gap-1 rounded border border-indigo-200 bg-white hover:bg-indigo-50 text-indigo-600 font-bold text-xs transition-colors",
|
|
4848
5322
|
"data-testid": "collections-chat",
|
|
4849
5323
|
onClick: openChat
|
|
4850
|
-
}, [_cache[
|
|
5324
|
+
}, [_cache[27] || (_cache[27] = (0, vue.createElementVNode)("span", { class: "material-icons text-sm" }, "forum", -1)), (0, vue.createElementVNode)("span", null, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.chat")), 1)])) : (0, vue.createCommentVNode)("", true),
|
|
4851
5325
|
((0, vue.openBlock)(true), (0, vue.createElementBlock)(vue.Fragment, null, (0, vue.renderList)(collectionActions.value, (action) => {
|
|
4852
5326
|
return (0, vue.openBlock)(), (0, vue.createElementBlock)("button", {
|
|
4853
5327
|
key: action.id,
|
|
4854
5328
|
type: "button",
|
|
4855
5329
|
class: "h-8 px-2.5 flex items-center gap-1 rounded border border-indigo-200 bg-white hover:bg-indigo-50 text-indigo-600 font-bold text-xs transition-colors disabled:opacity-50",
|
|
4856
|
-
disabled: collectionActionPending.value,
|
|
5330
|
+
disabled: collectionActionPending.value || isActionRunning(action.id),
|
|
4857
5331
|
"data-testid": `collections-action-${action.id}`,
|
|
4858
5332
|
onClick: ($event) => runCollectionAction(action)
|
|
4859
|
-
}, [action.
|
|
5333
|
+
}, [isActionRunning(action.id) ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_12$4, "progress_activity")) : action.icon ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_13$4, (0, vue.toDisplayString)(action.icon), 1)) : (0, vue.createCommentVNode)("", true), (0, vue.createElementVNode)("span", null, (0, vue.toDisplayString)(action.label), 1)], 8, _hoisted_11$4);
|
|
4860
5334
|
}), 128)),
|
|
4861
5335
|
canCreate.value && !calendarActive.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("button", {
|
|
4862
5336
|
key: 5,
|
|
@@ -4864,7 +5338,7 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
4864
5338
|
class: "h-8 px-2.5 flex items-center gap-1 rounded bg-indigo-600 hover:bg-indigo-700 text-white font-bold text-xs transition-colors shadow-sm",
|
|
4865
5339
|
"data-testid": "collections-add-item",
|
|
4866
5340
|
onClick: openCreate
|
|
4867
|
-
}, [_cache[
|
|
5341
|
+
}, [_cache[28] || (_cache[28] = (0, vue.createElementVNode)("span", { class: "material-icons text-sm" }, "add", -1)), (0, vue.createElementVNode)("span", null, (0, vue.toDisplayString)((0, vue.unref)(t)("common.add")), 1)])) : (0, vue.createCommentVNode)("", true),
|
|
4868
5342
|
canDeleteCollection.value && !embedded.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("button", {
|
|
4869
5343
|
key: 6,
|
|
4870
5344
|
type: "button",
|
|
@@ -4873,7 +5347,7 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
4873
5347
|
"aria-label": (0, vue.unref)(t)("collectionsView.deleteCollection"),
|
|
4874
5348
|
"data-testid": "collections-delete",
|
|
4875
5349
|
onClick: confirmCollectionDelete
|
|
4876
|
-
}, [..._cache[
|
|
5350
|
+
}, [..._cache[29] || (_cache[29] = [(0, vue.createElementVNode)("span", { class: "material-icons text-sm" }, "delete_forever", -1)])], 8, _hoisted_14$4)) : (0, vue.createCommentVNode)("", true),
|
|
4877
5351
|
canDeleteFeed.value && !embedded.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("button", {
|
|
4878
5352
|
key: 7,
|
|
4879
5353
|
type: "button",
|
|
@@ -4882,26 +5356,26 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
4882
5356
|
"aria-label": (0, vue.unref)(t)("collectionsView.deleteFeed"),
|
|
4883
5357
|
"data-testid": "feeds-delete",
|
|
4884
5358
|
onClick: confirmFeedDelete
|
|
4885
|
-
}, [..._cache[
|
|
5359
|
+
}, [..._cache[30] || (_cache[30] = [(0, vue.createElementVNode)("span", { class: "material-icons text-sm" }, "delete_forever", -1)])], 8, _hoisted_15$4)) : (0, vue.createCommentVNode)("", true)
|
|
4886
5360
|
])) : (0, vue.createCommentVNode)("", true),
|
|
4887
|
-
refreshNote.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div",
|
|
4888
|
-
collection.value && (!__props.hideSearch && items.value.length > 0 || !__props.hideViewToggle && (hasCalendar.value || hasKanban.value || hasCustomViews.value || canAddCustomView.value)) ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div",
|
|
4889
|
-
_cache[
|
|
5361
|
+
refreshNote.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_16$4, [_cache[31] || (_cache[31] = (0, vue.createElementVNode)("span", { class: "material-icons text-base text-indigo-600" }, "hourglass_top", -1)), (0, vue.createElementVNode)("span", _hoisted_17$4, (0, vue.toDisplayString)(refreshNote.value), 1)])) : (0, vue.createCommentVNode)("", true),
|
|
5362
|
+
collection.value && (!__props.hideSearch && items.value.length > 0 || !__props.hideViewToggle && (hasCalendar.value || hasKanban.value || hasCustomViews.value || canAddCustomView.value)) ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_18$4, [!__props.hideSearch && items.value.length > 0 ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_19$2, [
|
|
5363
|
+
_cache[33] || (_cache[33] = (0, vue.createElementVNode)("span", { class: "absolute inset-y-0 left-0 flex items-center pl-3 text-slate-400 pointer-events-none" }, [(0, vue.createElementVNode)("span", { class: "material-icons text-lg" }, "search")], -1)),
|
|
4890
5364
|
(0, vue.withDirectives)((0, vue.createElementVNode)("input", {
|
|
4891
5365
|
"onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => searchQuery.value = $event),
|
|
4892
5366
|
type: "text",
|
|
4893
5367
|
placeholder: (0, vue.unref)(t)("collectionsView.searchPlaceholder"),
|
|
4894
5368
|
"aria-label": (0, vue.unref)(t)("collectionsView.searchPlaceholder"),
|
|
4895
5369
|
class: "w-full bg-slate-50 border border-slate-200/80 rounded-xl pl-9 pr-8 py-1.5 text-xs placeholder-slate-400 focus:outline-none focus:ring-2 focus:ring-indigo-500/20 focus:border-indigo-500 focus:bg-white transition-all font-medium"
|
|
4896
|
-
}, null, 8,
|
|
5370
|
+
}, null, 8, _hoisted_20$2), [[vue.vModelText, searchQuery.value]]),
|
|
4897
5371
|
searchQuery.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("button", {
|
|
4898
5372
|
key: 0,
|
|
4899
5373
|
type: "button",
|
|
4900
5374
|
"aria-label": (0, vue.unref)(t)("collectionsView.clearSearch"),
|
|
4901
5375
|
class: "absolute inset-y-0 right-0 flex items-center pr-2.5 text-slate-400 hover:text-slate-600",
|
|
4902
5376
|
onClick: _cache[1] || (_cache[1] = ($event) => searchQuery.value = "")
|
|
4903
|
-
}, [..._cache[
|
|
4904
|
-
])) : (0, vue.createCommentVNode)("", true), (0, vue.createElementVNode)("div",
|
|
5377
|
+
}, [..._cache[32] || (_cache[32] = [(0, vue.createElementVNode)("span", { class: "material-icons text-sm" }, "close", -1)])], 8, _hoisted_21$2)) : (0, vue.createCommentVNode)("", true)
|
|
5378
|
+
])) : (0, vue.createCommentVNode)("", true), (0, vue.createElementVNode)("div", _hoisted_22$2, [
|
|
4905
5379
|
!__props.hideViewToggle && (hasCalendar.value || hasKanban.value || hasCustomViews.value || canAddCustomView.value) ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", {
|
|
4906
5380
|
key: 0,
|
|
4907
5381
|
class: "flex gap-0.5",
|
|
@@ -4914,7 +5388,7 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
4914
5388
|
"aria-pressed": activeView.value === "table",
|
|
4915
5389
|
"data-testid": "collection-view-toggle-table",
|
|
4916
5390
|
onClick: _cache[2] || (_cache[2] = ($event) => setView("table"))
|
|
4917
|
-
}, [_cache[
|
|
5391
|
+
}, [_cache[34] || (_cache[34] = (0, vue.createElementVNode)("span", { class: "material-icons text-sm" }, "table_rows", -1)), (0, vue.createElementVNode)("span", null, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.viewTable")), 1)], 10, _hoisted_24$1),
|
|
4918
5392
|
hasCalendar.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("button", {
|
|
4919
5393
|
key: 0,
|
|
4920
5394
|
type: "button",
|
|
@@ -4922,7 +5396,7 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
4922
5396
|
"aria-pressed": activeView.value === "calendar",
|
|
4923
5397
|
"data-testid": "collection-view-toggle-calendar",
|
|
4924
5398
|
onClick: _cache[3] || (_cache[3] = ($event) => setView("calendar"))
|
|
4925
|
-
}, [_cache[
|
|
5399
|
+
}, [_cache[35] || (_cache[35] = (0, vue.createElementVNode)("span", { class: "material-icons text-sm" }, "calendar_month", -1)), (0, vue.createElementVNode)("span", null, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.viewCalendar")), 1)], 10, _hoisted_25$1)) : (0, vue.createCommentVNode)("", true),
|
|
4926
5400
|
hasKanban.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("button", {
|
|
4927
5401
|
key: 1,
|
|
4928
5402
|
type: "button",
|
|
@@ -4930,7 +5404,7 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
4930
5404
|
"aria-pressed": activeView.value === "kanban",
|
|
4931
5405
|
"data-testid": "collection-view-toggle-kanban",
|
|
4932
5406
|
onClick: _cache[4] || (_cache[4] = ($event) => setView("kanban"))
|
|
4933
|
-
}, [_cache[
|
|
5407
|
+
}, [_cache[36] || (_cache[36] = (0, vue.createElementVNode)("span", { class: "material-icons text-sm" }, "view_kanban", -1)), (0, vue.createElementVNode)("span", null, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.viewKanban")), 1)], 10, _hoisted_26$1)) : (0, vue.createCommentVNode)("", true),
|
|
4934
5408
|
((0, vue.openBlock)(true), (0, vue.createElementBlock)(vue.Fragment, null, (0, vue.renderList)(customViews.value, (cv) => {
|
|
4935
5409
|
return (0, vue.openBlock)(), (0, vue.createElementBlock)("button", {
|
|
4936
5410
|
key: cv.id,
|
|
@@ -4939,7 +5413,7 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
4939
5413
|
"aria-pressed": activeView.value === (0, vue.unref)(customViewKey)(cv.id),
|
|
4940
5414
|
"data-testid": `collection-view-custom-${cv.id}`,
|
|
4941
5415
|
onClick: ($event) => setCustomView(cv.id)
|
|
4942
|
-
}, [(0, vue.createElementVNode)("span",
|
|
5416
|
+
}, [(0, vue.createElementVNode)("span", _hoisted_28, (0, vue.toDisplayString)(cv.icon || (cv.target === "mobile" ? "smartphone" : "dashboard_customize")), 1), (0, vue.createElementVNode)("span", null, (0, vue.toDisplayString)(cv.label), 1)], 10, _hoisted_27$1);
|
|
4943
5417
|
}), 128)),
|
|
4944
5418
|
canAddCustomView.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", {
|
|
4945
5419
|
key: 2,
|
|
@@ -4954,17 +5428,17 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
4954
5428
|
"aria-expanded": addMenuOpen.value,
|
|
4955
5429
|
"data-testid": "collection-view-add",
|
|
4956
5430
|
onClick: onAddViewClick
|
|
4957
|
-
}, [..._cache[
|
|
5431
|
+
}, [..._cache[37] || (_cache[37] = [(0, vue.createElementVNode)("span", { class: "material-icons text-sm" }, "add", -1)])], 8, _hoisted_29), addMenuOpen.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_30, [(0, vue.createElementVNode)("button", {
|
|
4958
5432
|
type: "button",
|
|
4959
5433
|
class: "w-full h-8 px-3 flex items-center gap-2 text-xs font-bold text-slate-600 hover:bg-slate-50",
|
|
4960
5434
|
"data-testid": "collection-view-add-desktop",
|
|
4961
5435
|
onClick: _cache[5] || (_cache[5] = ($event) => addCustomView("desktop"))
|
|
4962
|
-
}, [_cache[
|
|
5436
|
+
}, [_cache[38] || (_cache[38] = (0, vue.createElementVNode)("span", { class: "material-icons text-sm" }, "dashboard_customize", -1)), (0, vue.createElementVNode)("span", null, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.addViewDesktop")), 1)]), (0, vue.createElementVNode)("button", {
|
|
4963
5437
|
type: "button",
|
|
4964
5438
|
class: "w-full h-8 px-3 flex items-center gap-2 text-xs font-bold text-slate-600 hover:bg-slate-50",
|
|
4965
5439
|
"data-testid": "collection-view-add-mobile",
|
|
4966
5440
|
onClick: _cache[6] || (_cache[6] = ($event) => addCustomView("mobile"))
|
|
4967
|
-
}, [_cache[
|
|
5441
|
+
}, [_cache[39] || (_cache[39] = (0, vue.createElementVNode)("span", { class: "material-icons text-sm" }, "smartphone", -1)), (0, vue.createElementVNode)("span", null, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.addViewMobile")), 1)])])) : (0, vue.createCommentVNode)("", true)], 512)) : (0, vue.createCommentVNode)("", true),
|
|
4968
5442
|
canConfigureViews.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("button", {
|
|
4969
5443
|
key: 3,
|
|
4970
5444
|
type: "button",
|
|
@@ -4973,8 +5447,8 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
4973
5447
|
"aria-label": (0, vue.unref)(t)("collectionsView.config.open"),
|
|
4974
5448
|
"data-testid": "collection-config-open",
|
|
4975
5449
|
onClick: _cache[7] || (_cache[7] = ($event) => configOpen.value = true)
|
|
4976
|
-
}, [..._cache[
|
|
4977
|
-
], 8,
|
|
5450
|
+
}, [..._cache[40] || (_cache[40] = [(0, vue.createElementVNode)("span", { class: "material-icons text-sm" }, "settings", -1)])], 8, _hoisted_31)) : (0, vue.createCommentVNode)("", true)
|
|
5451
|
+
], 8, _hoisted_23$2)) : (0, vue.createCommentVNode)("", true),
|
|
4978
5452
|
calendarActive.value && dateFields.value.length > 1 ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("select", {
|
|
4979
5453
|
key: 1,
|
|
4980
5454
|
value: calendarAnchorField.value,
|
|
@@ -4986,8 +5460,8 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
4986
5460
|
return (0, vue.openBlock)(), (0, vue.createElementBlock)("option", {
|
|
4987
5461
|
key,
|
|
4988
5462
|
value: key
|
|
4989
|
-
}, (0, vue.toDisplayString)(collection.value?.schema.fields[key]?.label ?? key), 9,
|
|
4990
|
-
}), 128))], 40,
|
|
5463
|
+
}, (0, vue.toDisplayString)(collection.value?.schema.fields[key]?.label ?? key), 9, _hoisted_33);
|
|
5464
|
+
}), 128))], 40, _hoisted_32)) : (0, vue.createCommentVNode)("", true),
|
|
4991
5465
|
kanbanActive.value && enumFields.value.length > 1 ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("select", {
|
|
4992
5466
|
key: 2,
|
|
4993
5467
|
value: kanbanGroupField.value,
|
|
@@ -4999,24 +5473,24 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
4999
5473
|
return (0, vue.openBlock)(), (0, vue.createElementBlock)("option", {
|
|
5000
5474
|
key,
|
|
5001
5475
|
value: key
|
|
5002
|
-
}, (0, vue.toDisplayString)(collection.value?.schema.fields[key]?.label ?? key), 9,
|
|
5003
|
-
}), 128))], 40,
|
|
5004
|
-
items.value.length > 0 ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div",
|
|
5476
|
+
}, (0, vue.toDisplayString)(collection.value?.schema.fields[key]?.label ?? key), 9, _hoisted_35);
|
|
5477
|
+
}), 128))], 40, _hoisted_34)) : (0, vue.createCommentVNode)("", true),
|
|
5478
|
+
items.value.length > 0 ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_36, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.searchSummary", {
|
|
5005
5479
|
shown: filteredItems.value.length,
|
|
5006
5480
|
total: items.value.length
|
|
5007
5481
|
})), 1)) : (0, vue.createCommentVNode)("", true)
|
|
5008
5482
|
])])) : (0, vue.createCommentVNode)("", true),
|
|
5009
|
-
collection.value && dataIssues.value.length > 0 ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div",
|
|
5010
|
-
_cache[
|
|
5011
|
-
(0, vue.createElementVNode)("span",
|
|
5483
|
+
collection.value && dataIssues.value.length > 0 ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_37, [
|
|
5484
|
+
_cache[42] || (_cache[42] = (0, vue.createElementVNode)("span", { class: "material-icons text-amber-600" }, "warning", -1)),
|
|
5485
|
+
(0, vue.createElementVNode)("span", _hoisted_38, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.dataIssuesDetected", { count: dataIssues.value.length })), 1),
|
|
5012
5486
|
(0, vue.createElementVNode)("button", {
|
|
5013
5487
|
type: "button",
|
|
5014
5488
|
class: "h-8 px-2.5 flex items-center gap-1 rounded border border-amber-300 bg-white hover:bg-amber-100 text-amber-700 font-bold text-xs transition-colors",
|
|
5015
5489
|
"data-testid": "collections-repair",
|
|
5016
5490
|
onClick: repairCollection
|
|
5017
|
-
}, [_cache[
|
|
5491
|
+
}, [_cache[41] || (_cache[41] = (0, vue.createElementVNode)("span", { class: "material-icons text-sm" }, "build", -1)), (0, vue.createElementVNode)("span", null, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.repair")), 1)])
|
|
5018
5492
|
])) : (0, vue.createCommentVNode)("", true),
|
|
5019
|
-
(0, vue.createElementVNode)("div",
|
|
5493
|
+
(0, vue.createElementVNode)("div", _hoisted_39, [loading.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_40, [_cache[43] || (_cache[43] = (0, vue.createElementVNode)("div", { class: "h-8 w-8 border-2 border-indigo-600/20 border-t-indigo-600 rounded-full animate-spin" }, null, -1)), (0, vue.createElementVNode)("span", null, (0, vue.toDisplayString)((0, vue.unref)(t)("common.loading")), 1)])) : loadError.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_41, [_cache[44] || (_cache[44] = (0, vue.createElementVNode)("span", { class: "material-icons text-red-600" }, "error", -1)), (0, vue.createElementVNode)("span", null, (0, vue.toDisplayString)(loadError.value === "not-found" ? (0, vue.unref)(t)("collectionsView.notFound") : `${(0, vue.unref)(t)("collectionsView.loadFailed")}: ${loadError.value}`), 1)])) : !collection.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_42)) : calendarActive.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_43, [(0, vue.createVNode)(CollectionCalendarView_default, {
|
|
5020
5494
|
schema: collection.value.schema,
|
|
5021
5495
|
items: filteredItems.value,
|
|
5022
5496
|
"anchor-field": calendarAnchorField.value,
|
|
@@ -5060,6 +5534,7 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
5060
5534
|
"action-error": actionError.value,
|
|
5061
5535
|
"action-pending": actionPending.value,
|
|
5062
5536
|
"visible-actions": visibleActions.value,
|
|
5537
|
+
"running-action-ids": viewingRunningActionIds.value,
|
|
5063
5538
|
"live-record": liveRecord.value,
|
|
5064
5539
|
"live-derived": liveDerived.value,
|
|
5065
5540
|
"view-title": viewTitle.value,
|
|
@@ -5082,6 +5557,7 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
5082
5557
|
"action-error",
|
|
5083
5558
|
"action-pending",
|
|
5084
5559
|
"visible-actions",
|
|
5560
|
+
"running-action-ids",
|
|
5085
5561
|
"live-record",
|
|
5086
5562
|
"live-derived",
|
|
5087
5563
|
"view-title",
|
|
@@ -5101,16 +5577,16 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
5101
5577
|
"selected",
|
|
5102
5578
|
"can-create",
|
|
5103
5579
|
"show-detail"
|
|
5104
|
-
])) : (0, vue.createCommentVNode)("", true)])) : kanbanActive.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div",
|
|
5105
|
-
_cache[
|
|
5106
|
-
(0, vue.createElementVNode)("span",
|
|
5580
|
+
])) : (0, vue.createCommentVNode)("", true)])) : kanbanActive.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_44, [inlineError.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_45, [
|
|
5581
|
+
_cache[46] || (_cache[46] = (0, vue.createElementVNode)("span", { class: "material-icons text-red-600" }, "error", -1)),
|
|
5582
|
+
(0, vue.createElementVNode)("span", _hoisted_46, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.inlineSaveFailed", { error: inlineError.value })), 1),
|
|
5107
5583
|
(0, vue.createElementVNode)("button", {
|
|
5108
5584
|
type: "button",
|
|
5109
5585
|
class: "h-8 w-8 flex items-center justify-center rounded text-red-600 hover:bg-red-100",
|
|
5110
5586
|
"aria-label": (0, vue.unref)(t)("common.close"),
|
|
5111
5587
|
onClick: _cache[12] || (_cache[12] = ($event) => inlineError.value = null)
|
|
5112
|
-
}, [..._cache[
|
|
5113
|
-
])) : (0, vue.createCommentVNode)("", true), (0, vue.createElementVNode)("div",
|
|
5588
|
+
}, [..._cache[45] || (_cache[45] = [(0, vue.createElementVNode)("span", { class: "material-icons text-base" }, "close", -1)])], 8, _hoisted_47)
|
|
5589
|
+
])) : (0, vue.createCommentVNode)("", true), (0, vue.createElementVNode)("div", _hoisted_48, [(0, vue.createVNode)(CollectionKanbanView_default, {
|
|
5114
5590
|
schema: collection.value.schema,
|
|
5115
5591
|
items: filteredItems.value,
|
|
5116
5592
|
"group-field": kanbanGroupField.value,
|
|
@@ -5124,7 +5600,7 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
5124
5600
|
"group-field",
|
|
5125
5601
|
"selected",
|
|
5126
5602
|
"notified"
|
|
5127
|
-
])])])) : activeCustomView.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div",
|
|
5603
|
+
])])])) : activeCustomView.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_49, [activeCustomView.value.target === "mobile" ? ((0, vue.openBlock)(), (0, vue.createBlock)(CollectionRemoteViewPreview_default, {
|
|
5128
5604
|
key: 0,
|
|
5129
5605
|
slug: collection.value.slug,
|
|
5130
5606
|
view: activeCustomView.value,
|
|
@@ -5135,32 +5611,32 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
5135
5611
|
view: activeCustomView.value,
|
|
5136
5612
|
onOpenItem: onCustomViewOpenItem,
|
|
5137
5613
|
onStartChat: onCustomViewStartChat
|
|
5138
|
-
}, null, 8, ["slug", "view"]))])) : items.value.length === 0 && editing.value?.mode !== "create" ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div",
|
|
5139
|
-
_cache[
|
|
5140
|
-
(0, vue.createElementVNode)("p",
|
|
5614
|
+
}, null, 8, ["slug", "view"]))])) : items.value.length === 0 && editing.value?.mode !== "create" ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_50, [_cache[47] || (_cache[47] = (0, vue.createElementVNode)("span", { class: "material-icons text-4xl text-slate-300" }, "folder_open", -1)), (0, vue.createElementVNode)("p", _hoisted_51, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.itemsEmpty")), 1)])) : filteredItems.value.length === 0 && editing.value?.mode !== "create" ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_52, [
|
|
5615
|
+
_cache[48] || (_cache[48] = (0, vue.createElementVNode)("span", { class: "material-icons text-4xl text-slate-300" }, "search_off", -1)),
|
|
5616
|
+
(0, vue.createElementVNode)("p", _hoisted_53, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.noMatchingItems")), 1),
|
|
5141
5617
|
(0, vue.createElementVNode)("button", {
|
|
5142
5618
|
type: "button",
|
|
5143
5619
|
class: "text-xs text-indigo-600 font-semibold hover:underline",
|
|
5144
5620
|
onClick: _cache[13] || (_cache[13] = ($event) => searchQuery.value = "")
|
|
5145
5621
|
}, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.clearSearch")), 1)
|
|
5146
|
-
])) : ((0, vue.openBlock)(), (0, vue.createElementBlock)("div",
|
|
5147
|
-
_cache[
|
|
5148
|
-
(0, vue.createElementVNode)("span",
|
|
5622
|
+
])) : ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_54, [inlineError.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_55, [
|
|
5623
|
+
_cache[50] || (_cache[50] = (0, vue.createElementVNode)("span", { class: "material-icons text-red-600" }, "error", -1)),
|
|
5624
|
+
(0, vue.createElementVNode)("span", _hoisted_56, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.inlineSaveFailed", { error: inlineError.value })), 1),
|
|
5149
5625
|
(0, vue.createElementVNode)("button", {
|
|
5150
5626
|
type: "button",
|
|
5151
5627
|
class: "h-8 w-8 flex items-center justify-center rounded text-red-600 hover:bg-red-100",
|
|
5152
5628
|
"aria-label": (0, vue.unref)(t)("common.close"),
|
|
5153
5629
|
onClick: _cache[14] || (_cache[14] = ($event) => inlineError.value = null)
|
|
5154
|
-
}, [..._cache[
|
|
5155
|
-
])) : (0, vue.createCommentVNode)("", true), (0, vue.createElementVNode)("table",
|
|
5630
|
+
}, [..._cache[49] || (_cache[49] = [(0, vue.createElementVNode)("span", { class: "material-icons text-base" }, "close", -1)])], 8, _hoisted_57)
|
|
5631
|
+
])) : (0, vue.createCommentVNode)("", true), (0, vue.createElementVNode)("table", _hoisted_58, [(0, vue.createElementVNode)("thead", null, [(0, vue.createElementVNode)("tr", _hoisted_59, [((0, vue.openBlock)(true), (0, vue.createElementBlock)(vue.Fragment, null, (0, vue.renderList)(listColumnFields.value, ([key, field]) => {
|
|
5156
5632
|
return (0, vue.openBlock)(), (0, vue.createElementBlock)("th", {
|
|
5157
5633
|
key,
|
|
5158
5634
|
"aria-sort": (0, vue.unref)(_mulmoclaude_core_collection.isSortableField)(field) ? sortAriaValue(key) : void 0,
|
|
5159
5635
|
class: "px-5 py-3 font-bold text-slate-500 text-left uppercase tracking-wider whitespace-nowrap"
|
|
5160
|
-
}, [(0, vue.createElementVNode)("div",
|
|
5636
|
+
}, [(0, vue.createElementVNode)("div", _hoisted_61, [(0, vue.createElementVNode)("span", {
|
|
5161
5637
|
class: "truncate max-w-[14rem]",
|
|
5162
5638
|
title: field.label
|
|
5163
|
-
}, (0, vue.toDisplayString)(field.label), 9,
|
|
5639
|
+
}, (0, vue.toDisplayString)(field.label), 9, _hoisted_62), (0, vue.unref)(_mulmoclaude_core_collection.isSortableField)(field) ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("button", {
|
|
5164
5640
|
key: 0,
|
|
5165
5641
|
type: "button",
|
|
5166
5642
|
class: (0, vue.normalizeClass)(["inline-flex items-center justify-center rounded p-0.5 -my-1 leading-none transition-colors", sortButtonClass(key)]),
|
|
@@ -5169,8 +5645,8 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
5169
5645
|
onClick: (0, vue.withModifiers)(($event) => cycleSort(key), ["stop"]),
|
|
5170
5646
|
onPointerenter: ($event) => hoveredSortKey.value = key,
|
|
5171
5647
|
onPointerleave: _cache[15] || (_cache[15] = ($event) => hoveredSortKey.value = null)
|
|
5172
|
-
}, [(0, vue.createElementVNode)("span",
|
|
5173
|
-
}), 128))])]), (0, vue.createElementVNode)("tbody",
|
|
5648
|
+
}, [(0, vue.createElementVNode)("span", _hoisted_64, (0, vue.toDisplayString)(sortIconName(key)), 1)], 42, _hoisted_63)) : (0, vue.createCommentVNode)("", true)])], 8, _hoisted_60);
|
|
5649
|
+
}), 128))])]), (0, vue.createElementVNode)("tbody", _hoisted_65, [((0, vue.openBlock)(true), (0, vue.createElementBlock)(vue.Fragment, null, (0, vue.renderList)(sortedItems.value, (item) => {
|
|
5174
5650
|
return (0, vue.openBlock)(), (0, vue.createElementBlock)("tr", {
|
|
5175
5651
|
key: String(item[collection.value.schema.primaryKey] ?? ""),
|
|
5176
5652
|
class: (0, vue.normalizeClass)(["hover:bg-slate-50/70 cursor-pointer transition-colors focus:outline-none focus:bg-indigo-50/30", isRowOpen(item) || isEditingRow(item) ? "bg-indigo-50/40" : ""]),
|
|
@@ -5194,7 +5670,7 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
5194
5670
|
"aria-label": field.label,
|
|
5195
5671
|
onClick: _cache[16] || (_cache[16] = (0, vue.withModifiers)(() => {}, ["stop"])),
|
|
5196
5672
|
onChange: ($event) => commitToggle(item, field)
|
|
5197
|
-
}, null, 40,
|
|
5673
|
+
}, null, 40, _hoisted_67)) : field.type === "boolean" ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("input", {
|
|
5198
5674
|
key: 1,
|
|
5199
5675
|
type: "checkbox",
|
|
5200
5676
|
checked: item[key] === true,
|
|
@@ -5204,7 +5680,7 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
5204
5680
|
"aria-label": field.label,
|
|
5205
5681
|
onClick: _cache[17] || (_cache[17] = (0, vue.withModifiers)(() => {}, ["stop"])),
|
|
5206
5682
|
onChange: ($event) => commitInlineEdit(item, String(key), field, $event.target.checked)
|
|
5207
|
-
}, null, 40,
|
|
5683
|
+
}, null, 40, _hoisted_68)) : field.type === "ref" && field.to && typeof item[key] === "string" && item[key] ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_69, [(0, vue.createElementVNode)("a", {
|
|
5208
5684
|
href: (0, vue.unref)(cui).recordHref?.(field.to, String(item[key])),
|
|
5209
5685
|
tabindex: (0, vue.unref)(cui).recordHref?.(field.to, String(item[key])) ? void 0 : 0,
|
|
5210
5686
|
role: "link",
|
|
@@ -5212,7 +5688,7 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
5212
5688
|
"data-testid": `collections-ref-link-${key}-${item[key]}`,
|
|
5213
5689
|
onClick: ($event) => (0, vue.unref)(activateRefLink)($event, field.to, String(item[key]), true),
|
|
5214
5690
|
onKeydown: [(0, vue.withKeys)(($event) => (0, vue.unref)(activateRefLink)($event, field.to, String(item[key]), true), ["enter"]), (0, vue.withKeys)(($event) => (0, vue.unref)(activateRefLink)($event, field.to, String(item[key]), true), ["space"])]
|
|
5215
|
-
}, (0, vue.toDisplayString)((0, vue.unref)(refDisplay)(field.to, String(item[key]))), 41,
|
|
5691
|
+
}, (0, vue.toDisplayString)((0, vue.unref)(refDisplay)(field.to, String(item[key]))), 41, _hoisted_70)])) : field.type === "enum" && Array.isArray(field.values) && field.values.length > 0 ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("select", {
|
|
5216
5692
|
key: 3,
|
|
5217
5693
|
value: item[key] == null ? "" : String(item[key]),
|
|
5218
5694
|
disabled: isRowInlineSaving(item),
|
|
@@ -5221,35 +5697,39 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
5221
5697
|
"aria-label": field.label,
|
|
5222
5698
|
onClick: _cache[18] || (_cache[18] = (0, vue.withModifiers)(() => {}, ["stop"])),
|
|
5223
5699
|
onChange: ($event) => commitInlineEdit(item, String(key), field, $event.target.value)
|
|
5224
|
-
}, [showEnumPlaceholder(item, String(key)) ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("option",
|
|
5700
|
+
}, [showEnumPlaceholder(item, String(key)) ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("option", _hoisted_72, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.selectPlaceholder")), 1)) : (0, vue.createCommentVNode)("", true), ((0, vue.openBlock)(true), (0, vue.createElementBlock)(vue.Fragment, null, (0, vue.renderList)(field.values, (value) => {
|
|
5225
5701
|
return (0, vue.openBlock)(), (0, vue.createElementBlock)("option", {
|
|
5226
5702
|
key: value,
|
|
5227
5703
|
value
|
|
5228
|
-
}, (0, vue.toDisplayString)(value), 9,
|
|
5229
|
-
}), 128))], 42,
|
|
5704
|
+
}, (0, vue.toDisplayString)(value), 9, _hoisted_73);
|
|
5705
|
+
}), 128))], 42, _hoisted_71)) : field.type === "money" ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_74, (0, vue.toDisplayString)((0, vue.unref)(formatMoney)(item[key], (0, vue.unref)(resolveCurrency)(field, item), (0, vue.unref)(locale))), 1)) : field.type === "table" ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_75, [_cache[51] || (_cache[51] = (0, vue.createElementVNode)("span", { class: "material-icons text-[11px]" }, "list", -1)), (0, vue.createElementVNode)("span", null, (0, vue.toDisplayString)(tableSummary(item[key])), 1)])) : field.type === "derived" ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_76, (0, vue.toDisplayString)((0, vue.unref)(derivedDisplay)(field, (0, vue.unref)(evaluateDerivedAgainstItem)(field, String(key), item), item)), 1)) : field.type === "rollup" ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", {
|
|
5230
5706
|
key: 7,
|
|
5707
|
+
class: "inline-block truncate tabular-nums font-bold text-indigo-900 bg-indigo-50/50 px-1.5 py-0.5 rounded border border-indigo-100/50",
|
|
5708
|
+
"data-testid": `collections-rollup-${key}-${item[collection.value.schema.primaryKey]}`
|
|
5709
|
+
}, (0, vue.toDisplayString)((0, vue.unref)(render).rollupDisplay(field, item)), 9, _hoisted_77)) : field.type !== "file" && (0, vue.unref)(isExternalUrl)(item[key]) ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("a", {
|
|
5710
|
+
key: 8,
|
|
5231
5711
|
href: String(item[key]),
|
|
5232
5712
|
target: "_blank",
|
|
5233
5713
|
rel: "noopener noreferrer",
|
|
5234
5714
|
class: "block truncate text-blue-600 hover:text-blue-800 hover:underline font-semibold",
|
|
5235
5715
|
"data-testid": `collections-url-link-${key}-${item[collection.value.schema.primaryKey]}`,
|
|
5236
5716
|
onClick: _cache[19] || (_cache[19] = (0, vue.withModifiers)(() => {}, ["stop"]))
|
|
5237
|
-
}, (0, vue.toDisplayString)(String(item[key])), 9,
|
|
5238
|
-
key:
|
|
5717
|
+
}, (0, vue.toDisplayString)(String(item[key])), 9, _hoisted_78)) : field.type === "file" && (0, vue.unref)(artifactUrl)(item[key]) ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("a", {
|
|
5718
|
+
key: 9,
|
|
5239
5719
|
href: (0, vue.unref)(artifactUrl)(item[key]) ?? void 0,
|
|
5240
5720
|
target: "_blank",
|
|
5241
5721
|
rel: "noopener noreferrer",
|
|
5242
5722
|
class: "block truncate text-blue-600 hover:text-blue-800 hover:underline font-semibold",
|
|
5243
5723
|
"data-testid": `collections-file-link-${key}-${item[collection.value.schema.primaryKey]}`,
|
|
5244
5724
|
onClick: _cache[20] || (_cache[20] = (0, vue.withModifiers)(() => {}, ["stop"]))
|
|
5245
|
-
}, (0, vue.toDisplayString)(String(item[key])), 9,
|
|
5246
|
-
key:
|
|
5725
|
+
}, (0, vue.toDisplayString)(String(item[key])), 9, _hoisted_79)) : field.type === "file" && (0, vue.unref)(fileRoutePath)(item[key]) ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("a", {
|
|
5726
|
+
key: 10,
|
|
5247
5727
|
href: (0, vue.unref)(fileRoutePath)(item[key]) ?? void 0,
|
|
5248
5728
|
class: "block truncate text-blue-600 hover:text-blue-800 hover:underline font-semibold",
|
|
5249
5729
|
"data-testid": `collections-file-link-${key}-${item[collection.value.schema.primaryKey]}`,
|
|
5250
5730
|
onClick: ($event) => (0, vue.unref)(activatePathLink)($event, (0, vue.unref)(fileRoutePath)(item[key]) ?? "", true)
|
|
5251
|
-
}, (0, vue.toDisplayString)(String(item[key])), 9,
|
|
5252
|
-
}), 128))], 42,
|
|
5731
|
+
}, (0, vue.toDisplayString)(String(item[key])), 9, _hoisted_80)) : ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_81, (0, vue.toDisplayString)((0, vue.unref)(formatCell)(item[key], field.type)), 1))], 64)) : (0, vue.createCommentVNode)("", true)]);
|
|
5732
|
+
}), 128))], 42, _hoisted_66);
|
|
5253
5733
|
}), 128))])])]))]),
|
|
5254
5734
|
collection.value && (viewing.value || editing.value) && !(calendarActive.value && openDay.value) ? ((0, vue.openBlock)(), (0, vue.createBlock)(CollectionRecordModal_default, {
|
|
5255
5735
|
key: 4,
|
|
@@ -5265,6 +5745,7 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
5265
5745
|
"action-error": actionError.value,
|
|
5266
5746
|
"action-pending": actionPending.value,
|
|
5267
5747
|
"visible-actions": visibleActions.value,
|
|
5748
|
+
"running-action-ids": viewingRunningActionIds.value,
|
|
5268
5749
|
"live-record": liveRecord.value,
|
|
5269
5750
|
"live-derived": liveDerived.value,
|
|
5270
5751
|
"view-title": viewTitle.value,
|
|
@@ -5287,6 +5768,7 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
5287
5768
|
"action-error",
|
|
5288
5769
|
"action-pending",
|
|
5289
5770
|
"visible-actions",
|
|
5771
|
+
"running-action-ids",
|
|
5290
5772
|
"live-record",
|
|
5291
5773
|
"live-derived",
|
|
5292
5774
|
"view-title",
|
|
@@ -5296,20 +5778,32 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
5296
5778
|
])]),
|
|
5297
5779
|
_: 1
|
|
5298
5780
|
})) : (0, vue.createCommentVNode)("", true),
|
|
5781
|
+
mutateModal.value ? ((0, vue.openBlock)(), (0, vue.createBlock)(CollectionMutateParamsModal_default, {
|
|
5782
|
+
key: `${mutateModal.value.action.id}-${mutateModal.value.itemId}`,
|
|
5783
|
+
action: mutateModal.value.action,
|
|
5784
|
+
pending: mutatePending.value,
|
|
5785
|
+
error: mutateError.value,
|
|
5786
|
+
onClose: _cache[23] || (_cache[23] = ($event) => mutateModal.value = null),
|
|
5787
|
+
onSubmit: submitMutateParams
|
|
5788
|
+
}, null, 8, [
|
|
5789
|
+
"action",
|
|
5790
|
+
"pending",
|
|
5791
|
+
"error"
|
|
5792
|
+
])) : (0, vue.createCommentVNode)("", true),
|
|
5299
5793
|
configOpen.value && collection.value ? ((0, vue.openBlock)(), (0, vue.createBlock)(CollectionViewConfigModal_default, {
|
|
5300
|
-
key:
|
|
5794
|
+
key: 6,
|
|
5301
5795
|
slug: collection.value.slug,
|
|
5302
5796
|
title: collection.value.title,
|
|
5303
5797
|
views: customViews.value,
|
|
5304
5798
|
onChanged: onViewsChanged,
|
|
5305
|
-
onClose: _cache[
|
|
5799
|
+
onClose: _cache[24] || (_cache[24] = ($event) => configOpen.value = false)
|
|
5306
5800
|
}, null, 8, [
|
|
5307
5801
|
"slug",
|
|
5308
5802
|
"title",
|
|
5309
5803
|
"views"
|
|
5310
5804
|
])) : (0, vue.createCommentVNode)("", true),
|
|
5311
5805
|
chatOpen.value && collection.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", {
|
|
5312
|
-
key:
|
|
5806
|
+
key: 7,
|
|
5313
5807
|
class: "fixed inset-0 z-30 flex items-center justify-center bg-slate-900/60 backdrop-blur-sm p-4 transition-all duration-300",
|
|
5314
5808
|
role: "dialog",
|
|
5315
5809
|
"aria-modal": "true",
|
|
@@ -5317,29 +5811,29 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
5317
5811
|
"data-testid": "collections-chat-modal",
|
|
5318
5812
|
onClick: (0, vue.withModifiers)(closeChat, ["self"]),
|
|
5319
5813
|
onKeydown: (0, vue.withKeys)(closeChat, ["esc"])
|
|
5320
|
-
}, [(0, vue.createElementVNode)("div",
|
|
5321
|
-
(0, vue.createElementVNode)("header",
|
|
5322
|
-
_cache[
|
|
5323
|
-
(0, vue.createElementVNode)("div",
|
|
5814
|
+
}, [(0, vue.createElementVNode)("div", _hoisted_82, [
|
|
5815
|
+
(0, vue.createElementVNode)("header", _hoisted_83, [
|
|
5816
|
+
_cache[53] || (_cache[53] = (0, vue.createElementVNode)("div", { class: "h-9 w-9 flex items-center justify-center rounded-xl bg-indigo-50 text-indigo-600 border border-indigo-100/50" }, [(0, vue.createElementVNode)("span", { class: "material-icons text-lg" }, "forum")], -1)),
|
|
5817
|
+
(0, vue.createElementVNode)("div", _hoisted_84, [(0, vue.createElementVNode)("h2", _hoisted_85, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.chatTitle")), 1), (0, vue.createElementVNode)("span", _hoisted_86, (0, vue.toDisplayString)(collection.value.title), 1)]),
|
|
5324
5818
|
(0, vue.createElementVNode)("button", {
|
|
5325
5819
|
type: "button",
|
|
5326
5820
|
class: "h-8 w-8 flex items-center justify-center rounded text-slate-400 hover:bg-slate-200/50 hover:text-slate-600 transition-colors",
|
|
5327
5821
|
"aria-label": (0, vue.unref)(t)("common.close"),
|
|
5328
5822
|
"data-testid": "collections-chat-close",
|
|
5329
5823
|
onClick: closeChat
|
|
5330
|
-
}, [..._cache[
|
|
5824
|
+
}, [..._cache[52] || (_cache[52] = [(0, vue.createElementVNode)("span", { class: "material-icons text-lg" }, "close", -1)])], 8, _hoisted_87)
|
|
5331
5825
|
]),
|
|
5332
|
-
(0, vue.createElementVNode)("div",
|
|
5826
|
+
(0, vue.createElementVNode)("div", _hoisted_88, [(0, vue.withDirectives)((0, vue.createElementVNode)("textarea", {
|
|
5333
5827
|
ref_key: "chatInputEl",
|
|
5334
5828
|
ref: chatInputEl,
|
|
5335
|
-
"onUpdate:modelValue": _cache[
|
|
5829
|
+
"onUpdate:modelValue": _cache[25] || (_cache[25] = ($event) => chatMessage.value = $event),
|
|
5336
5830
|
rows: "4",
|
|
5337
5831
|
placeholder: (0, vue.unref)(t)("collectionsView.chatPlaceholder"),
|
|
5338
5832
|
class: "w-full bg-slate-50 border border-slate-200/80 rounded-xl px-3 py-2.5 text-sm placeholder-slate-400 focus:outline-none focus:ring-2 focus:ring-indigo-500/20 focus:border-indigo-500 focus:bg-white transition-all resize-none",
|
|
5339
5833
|
"data-testid": "collections-chat-input",
|
|
5340
5834
|
onKeydown: [(0, vue.withKeys)((0, vue.withModifiers)(submitChat, ["meta"]), ["enter"]), (0, vue.withKeys)((0, vue.withModifiers)(submitChat, ["ctrl"]), ["enter"])]
|
|
5341
|
-
}, null, 40,
|
|
5342
|
-
(0, vue.createElementVNode)("footer",
|
|
5835
|
+
}, null, 40, _hoisted_89), [[vue.vModelText, chatMessage.value]])]),
|
|
5836
|
+
(0, vue.createElementVNode)("footer", _hoisted_90, [(0, vue.createElementVNode)("button", {
|
|
5343
5837
|
type: "button",
|
|
5344
5838
|
class: "h-8 px-2.5 rounded text-xs font-bold text-slate-500 hover:bg-slate-200/50 transition-colors",
|
|
5345
5839
|
"data-testid": "collections-chat-cancel",
|
|
@@ -5350,7 +5844,7 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
5350
5844
|
disabled: !chatMessage.value.trim(),
|
|
5351
5845
|
"data-testid": "collections-chat-send",
|
|
5352
5846
|
onClick: submitChat
|
|
5353
|
-
}, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.chatStart")), 9,
|
|
5847
|
+
}, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.chatStart")), 9, _hoisted_91)])
|
|
5354
5848
|
])], 32)) : (0, vue.createCommentVNode)("", true)
|
|
5355
5849
|
]);
|
|
5356
5850
|
};
|