@mulmoclaude/collection-plugin 0.4.1 → 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +4 -47
- package/dist/index.js +1 -44
- package/dist/{promptSafety-BSO2gdsg.cjs → promptSafety-B0pPJkfQ.cjs} +60 -1
- package/dist/promptSafety-B0pPJkfQ.cjs.map +1 -0
- package/dist/{promptSafety-DShN_VCG.js → promptSafety-DIQ2yDca.js} +43 -2
- package/dist/promptSafety-DIQ2yDca.js.map +1 -0
- package/dist/style.css +102 -0
- package/dist/vue/chat/Preview.vue.d.ts +8 -0
- package/dist/vue/chat/Preview.vue.d.ts.map +1 -0
- package/dist/vue/chat/View.vue.d.ts +16 -0
- package/dist/vue/chat/View.vue.d.ts.map +1 -0
- package/dist/vue/components/CollectionEmbedView.vue.d.ts.map +1 -1
- package/dist/vue/components/CollectionRecordModal.vue.d.ts.map +1 -1
- 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/index.d.ts +6 -0
- package/dist/vue/index.d.ts.map +1 -1
- package/dist/vue/lang/de.d.ts.map +1 -1
- package/dist/vue/lang/en.d.ts +5 -0
- package/dist/vue/lang/en.d.ts.map +1 -1
- package/dist/vue/lang/es.d.ts.map +1 -1
- package/dist/vue/lang/fr.d.ts.map +1 -1
- package/dist/vue/lang/index.d.ts +5 -0
- package/dist/vue/lang/index.d.ts.map +1 -1
- package/dist/vue/lang/ja.d.ts.map +1 -1
- package/dist/vue/lang/ko.d.ts.map +1 -1
- package/dist/vue/lang/ptBR.d.ts.map +1 -1
- package/dist/vue/lang/zh.d.ts.map +1 -1
- package/dist/vue/refLink.d.ts +7 -0
- package/dist/vue/refLink.d.ts.map +1 -0
- package/dist/vue/uiContext.d.ts +18 -0
- package/dist/vue/uiContext.d.ts.map +1 -1
- package/dist/vue.cjs +914 -711
- package/dist/vue.cjs.map +1 -1
- package/dist/vue.js +913 -713
- package/dist/vue.js.map +1 -1
- package/package.json +1 -1
- package/dist/index.cjs.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/promptSafety-BSO2gdsg.cjs.map +0 -1
- package/dist/promptSafety-DShN_VCG.js.map +0 -1
package/dist/vue.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { A as buildUpdatedRecord, C as dateSortValue, D as numericSortValue, E as nextSortDirection, F as rowFromItem, I as actionVisible, L as fieldVisible, M as draftToRecord, N as emptyRow, O as sortItems, P as firstMissingRequiredField, T as isSortableField, W as resolveEnumColor, _ as ymdKey, a as assignLanes, b as labelFieldFor, i as MINUTES_PER_DAY, j as coerceInlineValue, k as stringSortValue, l as dateOf, n as shortHexId, o as bucketRecords, r as errorMessage, s as buildMonthGrid, t as defangForPrompt, u as daySlice, v as itemIdOf, w as enumSortValue, x as boolSortValue, y as itemLabelOf } from "./promptSafety-
|
|
1
|
+
import { A as buildUpdatedRecord, C as dateSortValue, D as numericSortValue, E as nextSortDirection, F as rowFromItem, G as TOOL_DEFINITION, I as actionVisible, L as fieldVisible, M as draftToRecord, N as emptyRow, O as sortItems, P as firstMissingRequiredField, T as isSortableField, W as resolveEnumColor, _ as ymdKey, a as assignLanes, b as labelFieldFor, i as MINUTES_PER_DAY, j as coerceInlineValue, k as stringSortValue, l as dateOf, n as shortHexId, o as bucketRecords, q as executePresentCollection, r as errorMessage, s as buildMonthGrid, t as defangForPrompt, u as daySlice, v as itemIdOf, w as enumSortValue, x as boolSortValue, y as itemLabelOf } from "./promptSafety-DIQ2yDca.js";
|
|
2
2
|
import { t as deriveAll } from "./deriveAll-BHcs1erT.js";
|
|
3
|
-
import { Fragment, Teleport, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createTextVNode, createVNode, defineComponent, effectScope, mergeModels, nextTick, normalizeClass, normalizeStyle, onBeforeUnmount, onMounted, openBlock, ref, renderList, renderSlot,
|
|
3
|
+
import { Fragment, Teleport, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createTextVNode, createVNode, defineComponent, effectScope, mergeModels, nextTick, normalizeClass, normalizeStyle, onBeforeUnmount, onMounted, openBlock, ref, renderList, renderSlot, resolveDynamicComponent, toDisplayString, unref, useModel, vModelCheckbox, vModelDynamic, vModelSelect, vModelText, watch, watchEffect, withCtx, withDirectives, withKeys, withModifiers } from "vue";
|
|
4
4
|
import { createI18n } from "vue-i18n";
|
|
5
5
|
import draggable from "vuedraggable";
|
|
6
6
|
//#region src/vue/uiContext.ts
|
|
@@ -14,395 +14,6 @@ function collectionUi() {
|
|
|
14
14
|
return current;
|
|
15
15
|
}
|
|
16
16
|
//#endregion
|
|
17
|
-
//#region src/vue/useCollectionRendering.ts
|
|
18
|
-
function useCollectionRendering(collection, locale) {
|
|
19
|
-
const refCache = ref({});
|
|
20
|
-
const refRecordCache = ref({});
|
|
21
|
-
const embedCache = ref({});
|
|
22
|
-
function resetLinkedCaches() {
|
|
23
|
-
refCache.value = {};
|
|
24
|
-
refRecordCache.value = {};
|
|
25
|
-
embedCache.value = {};
|
|
26
|
-
}
|
|
27
|
-
function uniqueRefTargets(schema) {
|
|
28
|
-
const targets = /* @__PURE__ */ new Set();
|
|
29
|
-
const walk = (fields) => {
|
|
30
|
-
for (const field of Object.values(fields)) {
|
|
31
|
-
if (field.type === "ref" && typeof field.to === "string" && field.to.length > 0) targets.add(field.to);
|
|
32
|
-
if (field.type === "table" && field.of) walk(field.of);
|
|
33
|
-
}
|
|
34
|
-
};
|
|
35
|
-
walk(schema.fields);
|
|
36
|
-
return [...targets];
|
|
37
|
-
}
|
|
38
|
-
function uniqueEmbedTargets(schema) {
|
|
39
|
-
const targets = /* @__PURE__ */ new Set();
|
|
40
|
-
for (const field of Object.values(schema.fields)) if (field.type === "embed" && typeof field.to === "string" && field.to.length > 0) targets.add(field.to);
|
|
41
|
-
return [...targets];
|
|
42
|
-
}
|
|
43
|
-
function buildRefDisplayMap(detail) {
|
|
44
|
-
const { fields, primaryKey } = detail.collection.schema;
|
|
45
|
-
const displayField = "name" in fields ? "name" : "title" in fields ? "title" : primaryKey;
|
|
46
|
-
const map = {};
|
|
47
|
-
for (const item of detail.items) {
|
|
48
|
-
const slugRaw = item[primaryKey];
|
|
49
|
-
if (typeof slugRaw !== "string" || slugRaw.length === 0) continue;
|
|
50
|
-
const displayRaw = item[displayField];
|
|
51
|
-
map[slugRaw] = typeof displayRaw === "string" && displayRaw.length > 0 ? displayRaw : slugRaw;
|
|
52
|
-
}
|
|
53
|
-
return map;
|
|
54
|
-
}
|
|
55
|
-
function buildRefRecordMap(detail) {
|
|
56
|
-
const { schema } = detail.collection;
|
|
57
|
-
const map = {};
|
|
58
|
-
for (const item of detail.items) {
|
|
59
|
-
const slugRaw = item[schema.primaryKey];
|
|
60
|
-
if (typeof slugRaw === "string" && slugRaw.length > 0) map[slugRaw] = deriveAll(schema, item, {});
|
|
61
|
-
}
|
|
62
|
-
return map;
|
|
63
|
-
}
|
|
64
|
-
async function loadLinkedCollections(schema, expectedSlug) {
|
|
65
|
-
const refTargets = new Set(uniqueRefTargets(schema));
|
|
66
|
-
const embedTargets = new Set(uniqueEmbedTargets(schema));
|
|
67
|
-
const allTargets = [...new Set([...refTargets, ...embedTargets])];
|
|
68
|
-
if (allTargets.length === 0) return;
|
|
69
|
-
const binding = collectionUi();
|
|
70
|
-
const results = await Promise.all(allTargets.map(async (target) => {
|
|
71
|
-
try {
|
|
72
|
-
return {
|
|
73
|
-
target,
|
|
74
|
-
result: await binding.fetchCollectionDetail(target)
|
|
75
|
-
};
|
|
76
|
-
} catch {
|
|
77
|
-
return {
|
|
78
|
-
target,
|
|
79
|
-
result: { ok: false }
|
|
80
|
-
};
|
|
81
|
-
}
|
|
82
|
-
}));
|
|
83
|
-
if (collection.value?.slug !== expectedSlug) return;
|
|
84
|
-
const nextRef = {};
|
|
85
|
-
const nextRefRecords = {};
|
|
86
|
-
const nextEmbed = {};
|
|
87
|
-
for (const { target, result } of results) {
|
|
88
|
-
if (!result.ok) continue;
|
|
89
|
-
if (refTargets.has(target)) {
|
|
90
|
-
nextRef[target] = buildRefDisplayMap(result.data);
|
|
91
|
-
nextRefRecords[target] = buildRefRecordMap(result.data);
|
|
92
|
-
}
|
|
93
|
-
if (embedTargets.has(target)) nextEmbed[target] = {
|
|
94
|
-
schema: result.data.collection.schema,
|
|
95
|
-
items: result.data.items
|
|
96
|
-
};
|
|
97
|
-
}
|
|
98
|
-
refCache.value = nextRef;
|
|
99
|
-
refRecordCache.value = nextRefRecords;
|
|
100
|
-
embedCache.value = nextEmbed;
|
|
101
|
-
}
|
|
102
|
-
function refDisplay(targetSlug, itemSlug) {
|
|
103
|
-
const map = refCache.value[targetSlug];
|
|
104
|
-
return map && map[itemSlug] || itemSlug;
|
|
105
|
-
}
|
|
106
|
-
function refOptions(targetSlug) {
|
|
107
|
-
const map = refCache.value[targetSlug];
|
|
108
|
-
if (!map) return [];
|
|
109
|
-
return Object.entries(map).map(([slug, display]) => ({
|
|
110
|
-
slug,
|
|
111
|
-
display
|
|
112
|
-
})).sort((left, right) => left.display.localeCompare(right.display));
|
|
113
|
-
}
|
|
114
|
-
function resolveEmbed(field) {
|
|
115
|
-
if (field.type !== "embed" || !field.to || !field.id) return {
|
|
116
|
-
schema: null,
|
|
117
|
-
item: null
|
|
118
|
-
};
|
|
119
|
-
const data = embedCache.value[field.to];
|
|
120
|
-
if (!data) return {
|
|
121
|
-
schema: null,
|
|
122
|
-
item: null
|
|
123
|
-
};
|
|
124
|
-
const item = data.items.find((entry) => String(entry[data.schema.primaryKey] ?? "") === field.id) ?? null;
|
|
125
|
-
return {
|
|
126
|
-
schema: data.schema,
|
|
127
|
-
item
|
|
128
|
-
};
|
|
129
|
-
}
|
|
130
|
-
function embedValue(field, value, record) {
|
|
131
|
-
if (field.type === "money") return formatMoney(value, resolveCurrency(field, record), locale.value);
|
|
132
|
-
return detailText(value);
|
|
133
|
-
}
|
|
134
|
-
const embedViews = computed(() => {
|
|
135
|
-
const out = {};
|
|
136
|
-
if (!collection.value) return out;
|
|
137
|
-
for (const [key, field] of Object.entries(collection.value.schema.fields)) {
|
|
138
|
-
if (field.type !== "embed") continue;
|
|
139
|
-
const { schema, item } = resolveEmbed(field);
|
|
140
|
-
const rows = [];
|
|
141
|
-
if (schema && item) for (const [subKey, subField] of Object.entries(schema.fields)) {
|
|
142
|
-
const value = item[subKey];
|
|
143
|
-
if (value === void 0 || value === null || value === "") continue;
|
|
144
|
-
rows.push({
|
|
145
|
-
key: subKey,
|
|
146
|
-
label: subField.label,
|
|
147
|
-
type: subField.type,
|
|
148
|
-
value,
|
|
149
|
-
display: embedValue(subField, value, item)
|
|
150
|
-
});
|
|
151
|
-
}
|
|
152
|
-
out[key] = {
|
|
153
|
-
found: Boolean(item),
|
|
154
|
-
rows,
|
|
155
|
-
targetSlug: field.to ?? "",
|
|
156
|
-
recordId: field.id ?? ""
|
|
157
|
-
};
|
|
158
|
-
}
|
|
159
|
-
return out;
|
|
160
|
-
});
|
|
161
|
-
function resolveCurrency(field, record) {
|
|
162
|
-
if (field.currencyField && record) {
|
|
163
|
-
const code = record[field.currencyField];
|
|
164
|
-
if (typeof code === "string" && code.trim().length > 0) return code;
|
|
165
|
-
}
|
|
166
|
-
return field.currency;
|
|
167
|
-
}
|
|
168
|
-
function currencySymbol(currency) {
|
|
169
|
-
const code = currency && currency.length > 0 ? currency : "USD";
|
|
170
|
-
try {
|
|
171
|
-
return new Intl.NumberFormat(locale.value, {
|
|
172
|
-
style: "currency",
|
|
173
|
-
currency: code
|
|
174
|
-
}).formatToParts(0).find((entry) => entry.type === "currency")?.value ?? code;
|
|
175
|
-
} catch {
|
|
176
|
-
return code;
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
function formatMoney(value, currency, displayLocale) {
|
|
180
|
-
if (value === void 0 || value === "") return "—";
|
|
181
|
-
const amount = typeof value === "number" ? value : Number(value);
|
|
182
|
-
if (!Number.isFinite(amount)) return String(value);
|
|
183
|
-
const currencyCode = currency && currency.length > 0 ? currency : "USD";
|
|
184
|
-
try {
|
|
185
|
-
return new Intl.NumberFormat(displayLocale, {
|
|
186
|
-
style: "currency",
|
|
187
|
-
currency: currencyCode
|
|
188
|
-
}).format(amount);
|
|
189
|
-
} catch {
|
|
190
|
-
return String(amount);
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
function formatCell(value, type) {
|
|
194
|
-
if (value === void 0 || value === null || value === "") return "—";
|
|
195
|
-
if (type === "markdown" && typeof value === "string") return value.length > 80 ? `${value.slice(0, 80)}…` : value;
|
|
196
|
-
if (typeof value === "string" || typeof value === "number") return String(value);
|
|
197
|
-
return JSON.stringify(value);
|
|
198
|
-
}
|
|
199
|
-
function isExternalUrl(value) {
|
|
200
|
-
return typeof value === "string" && /^https?:\/\//i.test(value);
|
|
201
|
-
}
|
|
202
|
-
function artifactUrl(value) {
|
|
203
|
-
return collectionUi().fileAssetUrl(value);
|
|
204
|
-
}
|
|
205
|
-
function fileRoutePath(value) {
|
|
206
|
-
return collectionUi().fileRoutePath(value);
|
|
207
|
-
}
|
|
208
|
-
function detailText(value) {
|
|
209
|
-
if (value === void 0 || value === null || value === "") return "—";
|
|
210
|
-
return String(value);
|
|
211
|
-
}
|
|
212
|
-
function tableRows(value) {
|
|
213
|
-
if (!Array.isArray(value)) return [];
|
|
214
|
-
return value.filter((row) => Boolean(row) && typeof row === "object" && !Array.isArray(row));
|
|
215
|
-
}
|
|
216
|
-
function hasTableRows(value) {
|
|
217
|
-
return tableRows(value).length > 0;
|
|
218
|
-
}
|
|
219
|
-
function formatSubCell(subField, value, record) {
|
|
220
|
-
if (subField.type === "money") return formatMoney(value, resolveCurrency(subField, record), locale.value);
|
|
221
|
-
if (subField.type === "ref" && subField.to && typeof value === "string" && value.length > 0) return refDisplay(subField.to, value);
|
|
222
|
-
return formatCell(value, subField.type);
|
|
223
|
-
}
|
|
224
|
-
function inputTypeFor(type) {
|
|
225
|
-
if (type === "email") return "email";
|
|
226
|
-
if (type === "number") return "number";
|
|
227
|
-
if (type === "money") return "number";
|
|
228
|
-
if (type === "date") return "date";
|
|
229
|
-
if (type === "datetime") return "datetime-local";
|
|
230
|
-
return "text";
|
|
231
|
-
}
|
|
232
|
-
function evaluateDerivedAgainstItem(field, fieldKey, item) {
|
|
233
|
-
if (!field.formula || !collection.value) return null;
|
|
234
|
-
const result = deriveAll(collection.value.schema, item, refRecordCache.value)[fieldKey];
|
|
235
|
-
return typeof result === "number" && Number.isFinite(result) ? result : null;
|
|
236
|
-
}
|
|
237
|
-
function derivedDisplay(field, computedValue, record) {
|
|
238
|
-
if (computedValue === null || computedValue === void 0) return "—";
|
|
239
|
-
if (field.display === "money") return formatMoney(computedValue, resolveCurrency(field, record), locale.value);
|
|
240
|
-
return formatCell(computedValue, field.display ?? "number");
|
|
241
|
-
}
|
|
242
|
-
return {
|
|
243
|
-
refCache,
|
|
244
|
-
refRecordCache,
|
|
245
|
-
embedCache,
|
|
246
|
-
resetLinkedCaches,
|
|
247
|
-
loadLinkedCollections,
|
|
248
|
-
refDisplay,
|
|
249
|
-
refOptions,
|
|
250
|
-
embedViews,
|
|
251
|
-
resolveCurrency,
|
|
252
|
-
currencySymbol,
|
|
253
|
-
formatMoney,
|
|
254
|
-
formatCell,
|
|
255
|
-
detailText,
|
|
256
|
-
isExternalUrl,
|
|
257
|
-
artifactUrl,
|
|
258
|
-
fileRoutePath,
|
|
259
|
-
tableRows,
|
|
260
|
-
hasTableRows,
|
|
261
|
-
formatSubCell,
|
|
262
|
-
inputTypeFor,
|
|
263
|
-
deriveAll,
|
|
264
|
-
evaluateDerivedAgainstItem,
|
|
265
|
-
derivedDisplay
|
|
266
|
-
};
|
|
267
|
-
}
|
|
268
|
-
//#endregion
|
|
269
|
-
//#region src/vue/collectionViewMode.ts
|
|
270
|
-
var STORAGE_KEY = "collection_view_modes";
|
|
271
|
-
var SORT_STORAGE_KEY = "collection_sorts";
|
|
272
|
-
var BUILT_IN_MODES = [
|
|
273
|
-
"table",
|
|
274
|
-
"calendar",
|
|
275
|
-
"kanban"
|
|
276
|
-
];
|
|
277
|
-
/** A persisted mode is valid if it's a known built-in OR any `custom:<id>`
|
|
278
|
-
* key (the id is validated against the live schema at render time, so an
|
|
279
|
-
* unknown custom id simply collapses to the table there). Takes `unknown`
|
|
280
|
-
* and type-guards `string` first: a corrupted localStorage entry could hold a
|
|
281
|
-
* number/object, and calling `.startsWith` on that would throw. */
|
|
282
|
-
function isValidViewMode(value) {
|
|
283
|
-
return typeof value === "string" && (BUILT_IN_MODES.includes(value) || value.startsWith("custom:"));
|
|
284
|
-
}
|
|
285
|
-
function readAll() {
|
|
286
|
-
try {
|
|
287
|
-
const raw = localStorage.getItem(STORAGE_KEY);
|
|
288
|
-
if (!raw) return {};
|
|
289
|
-
const parsed = JSON.parse(raw);
|
|
290
|
-
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
|
|
291
|
-
} catch {
|
|
292
|
-
return {};
|
|
293
|
-
}
|
|
294
|
-
}
|
|
295
|
-
function readCollectionViewMode(slug) {
|
|
296
|
-
const stored = readAll()[slug];
|
|
297
|
-
return isValidViewMode(stored) ? stored : null;
|
|
298
|
-
}
|
|
299
|
-
function writeCollectionViewMode(slug, view) {
|
|
300
|
-
try {
|
|
301
|
-
const all = readAll();
|
|
302
|
-
all[slug] = view;
|
|
303
|
-
localStorage.setItem(STORAGE_KEY, JSON.stringify(all));
|
|
304
|
-
} catch {}
|
|
305
|
-
}
|
|
306
|
-
function isSortState(value) {
|
|
307
|
-
if (!value || typeof value !== "object") return false;
|
|
308
|
-
const rec = value;
|
|
309
|
-
return typeof rec.field === "string" && (rec.direction === "asc" || rec.direction === "desc");
|
|
310
|
-
}
|
|
311
|
-
function readAllSorts() {
|
|
312
|
-
try {
|
|
313
|
-
const raw = localStorage.getItem(SORT_STORAGE_KEY);
|
|
314
|
-
if (!raw) return {};
|
|
315
|
-
const parsed = JSON.parse(raw);
|
|
316
|
-
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return {};
|
|
317
|
-
const out = {};
|
|
318
|
-
for (const [slug, value] of Object.entries(parsed)) if (isSortState(value)) out[slug] = value;
|
|
319
|
-
return out;
|
|
320
|
-
} catch {
|
|
321
|
-
return {};
|
|
322
|
-
}
|
|
323
|
-
}
|
|
324
|
-
function readCollectionSort(slug) {
|
|
325
|
-
return readAllSorts()[slug] ?? null;
|
|
326
|
-
}
|
|
327
|
-
/** Persist (or, when `sort` is null, clear) the slug's active column sort. */
|
|
328
|
-
function writeCollectionSort(slug, sort) {
|
|
329
|
-
try {
|
|
330
|
-
const all = Object.fromEntries(Object.entries(readAllSorts()).filter(([key]) => key !== slug));
|
|
331
|
-
if (sort) all[slug] = sort;
|
|
332
|
-
localStorage.setItem(SORT_STORAGE_KEY, JSON.stringify(all));
|
|
333
|
-
} catch {}
|
|
334
|
-
}
|
|
335
|
-
//#endregion
|
|
336
|
-
//#region src/vue/components/CollectionRecordModal.vue
|
|
337
|
-
var CollectionRecordModal_default = /* @__PURE__ */ defineComponent({
|
|
338
|
-
__name: "CollectionRecordModal",
|
|
339
|
-
emits: ["close"],
|
|
340
|
-
setup(__props, { emit: __emit }) {
|
|
341
|
-
const emit = __emit;
|
|
342
|
-
const dialogEl = ref(null);
|
|
343
|
-
let previouslyFocused = null;
|
|
344
|
-
const FOCUSABLE_SELECTOR = [
|
|
345
|
-
"a[href]",
|
|
346
|
-
"button:not([disabled])",
|
|
347
|
-
"input:not([disabled])",
|
|
348
|
-
"select:not([disabled])",
|
|
349
|
-
"textarea:not([disabled])",
|
|
350
|
-
"[tabindex]:not([tabindex=\"-1\"])"
|
|
351
|
-
].join(",");
|
|
352
|
-
/** Visible, focusable controls inside the dialog, in DOM order. */
|
|
353
|
-
function focusableItems() {
|
|
354
|
-
if (!dialogEl.value) return [];
|
|
355
|
-
return Array.from(dialogEl.value.querySelectorAll(FOCUSABLE_SELECTOR)).filter((node) => node.offsetParent !== null);
|
|
356
|
-
}
|
|
357
|
-
/** Trap Tab / Shift+Tab inside the dialog so focus can't escape to the
|
|
358
|
-
* page behind the overlay. Wraps at both ends; the dialog container
|
|
359
|
-
* itself (tabindex -1) counts as "before the first item". */
|
|
360
|
-
function onTab(event) {
|
|
361
|
-
const items = focusableItems();
|
|
362
|
-
if (items.length === 0) {
|
|
363
|
-
event.preventDefault();
|
|
364
|
-
dialogEl.value?.focus();
|
|
365
|
-
return;
|
|
366
|
-
}
|
|
367
|
-
const [first] = items;
|
|
368
|
-
const last = items[items.length - 1];
|
|
369
|
-
const active = document.activeElement;
|
|
370
|
-
if (event.shiftKey) {
|
|
371
|
-
if (active === first || active === dialogEl.value) {
|
|
372
|
-
event.preventDefault();
|
|
373
|
-
last.focus();
|
|
374
|
-
}
|
|
375
|
-
} else if (active === last) {
|
|
376
|
-
event.preventDefault();
|
|
377
|
-
first.focus();
|
|
378
|
-
}
|
|
379
|
-
}
|
|
380
|
-
onMounted(async () => {
|
|
381
|
-
previouslyFocused = document.activeElement instanceof HTMLElement ? document.activeElement : null;
|
|
382
|
-
await nextTick();
|
|
383
|
-
dialogEl.value?.focus();
|
|
384
|
-
});
|
|
385
|
-
onBeforeUnmount(() => {
|
|
386
|
-
previouslyFocused?.focus?.();
|
|
387
|
-
});
|
|
388
|
-
return (_ctx, _cache) => {
|
|
389
|
-
return openBlock(), createBlock(Teleport, { to: "body" }, [createElementVNode("div", {
|
|
390
|
-
class: "fixed inset-0 z-40 flex items-center justify-center bg-slate-900/40 p-4",
|
|
391
|
-
"data-testid": "collections-record-modal",
|
|
392
|
-
onClick: _cache[1] || (_cache[1] = withModifiers(($event) => emit("close"), ["self"]))
|
|
393
|
-
}, [createElementVNode("div", {
|
|
394
|
-
ref_key: "dialogEl",
|
|
395
|
-
ref: dialogEl,
|
|
396
|
-
class: "flex max-h-[85vh] w-full max-w-2xl flex-col overflow-hidden rounded-2xl bg-white shadow-xl focus:outline-none",
|
|
397
|
-
role: "dialog",
|
|
398
|
-
"aria-modal": "true",
|
|
399
|
-
tabindex: "-1",
|
|
400
|
-
onKeydown: [_cache[0] || (_cache[0] = withKeys(($event) => emit("close"), ["esc"])), withKeys(onTab, ["tab"])]
|
|
401
|
-
}, [renderSlot(_ctx.$slots, "default")], 544)])]);
|
|
402
|
-
};
|
|
403
|
-
}
|
|
404
|
-
});
|
|
405
|
-
//#endregion
|
|
406
17
|
//#region src/vue/lang/index.ts
|
|
407
18
|
var i18n = createI18n({
|
|
408
19
|
legacy: false,
|
|
@@ -503,6 +114,11 @@ var i18n = createI18n({
|
|
|
503
114
|
save: "Save",
|
|
504
115
|
saving: "Saving...",
|
|
505
116
|
yes: "Yes"
|
|
117
|
+
},
|
|
118
|
+
pluginPresentCollection: {
|
|
119
|
+
fallbackTitle: "Collection",
|
|
120
|
+
itemLabel: "Item: {id}",
|
|
121
|
+
listLabel: "All records"
|
|
506
122
|
}
|
|
507
123
|
},
|
|
508
124
|
ja: {
|
|
@@ -599,6 +215,11 @@ var i18n = createI18n({
|
|
|
599
215
|
save: "保存",
|
|
600
216
|
saving: "保存中...",
|
|
601
217
|
yes: "はい"
|
|
218
|
+
},
|
|
219
|
+
pluginPresentCollection: {
|
|
220
|
+
fallbackTitle: "コレクション",
|
|
221
|
+
itemLabel: "項目: {id}",
|
|
222
|
+
listLabel: "すべてのレコード"
|
|
602
223
|
}
|
|
603
224
|
},
|
|
604
225
|
zh: {
|
|
@@ -695,6 +316,11 @@ var i18n = createI18n({
|
|
|
695
316
|
save: "保存",
|
|
696
317
|
saving: "保存中...",
|
|
697
318
|
yes: "是"
|
|
319
|
+
},
|
|
320
|
+
pluginPresentCollection: {
|
|
321
|
+
fallbackTitle: "集合",
|
|
322
|
+
itemLabel: "项目:{id}",
|
|
323
|
+
listLabel: "全部记录"
|
|
698
324
|
}
|
|
699
325
|
},
|
|
700
326
|
ko: {
|
|
@@ -791,6 +417,11 @@ var i18n = createI18n({
|
|
|
791
417
|
save: "저장",
|
|
792
418
|
saving: "저장 중...",
|
|
793
419
|
yes: "예"
|
|
420
|
+
},
|
|
421
|
+
pluginPresentCollection: {
|
|
422
|
+
fallbackTitle: "컬렉션",
|
|
423
|
+
itemLabel: "항목: {id}",
|
|
424
|
+
listLabel: "모든 레코드"
|
|
794
425
|
}
|
|
795
426
|
},
|
|
796
427
|
es: {
|
|
@@ -887,6 +518,11 @@ var i18n = createI18n({
|
|
|
887
518
|
save: "Guardar",
|
|
888
519
|
saving: "Guardando...",
|
|
889
520
|
yes: "Sí"
|
|
521
|
+
},
|
|
522
|
+
pluginPresentCollection: {
|
|
523
|
+
fallbackTitle: "Colección",
|
|
524
|
+
itemLabel: "Elemento: {id}",
|
|
525
|
+
listLabel: "Todos los registros"
|
|
890
526
|
}
|
|
891
527
|
},
|
|
892
528
|
"pt-BR": {
|
|
@@ -983,6 +619,11 @@ var i18n = createI18n({
|
|
|
983
619
|
save: "Salvar",
|
|
984
620
|
saving: "Salvando...",
|
|
985
621
|
yes: "Sim"
|
|
622
|
+
},
|
|
623
|
+
pluginPresentCollection: {
|
|
624
|
+
fallbackTitle: "Coleção",
|
|
625
|
+
itemLabel: "Item: {id}",
|
|
626
|
+
listLabel: "Todos os registros"
|
|
986
627
|
}
|
|
987
628
|
},
|
|
988
629
|
fr: {
|
|
@@ -1079,6 +720,11 @@ var i18n = createI18n({
|
|
|
1079
720
|
save: "Enregistrer",
|
|
1080
721
|
saving: "Enregistrement...",
|
|
1081
722
|
yes: "Oui"
|
|
723
|
+
},
|
|
724
|
+
pluginPresentCollection: {
|
|
725
|
+
fallbackTitle: "Collection",
|
|
726
|
+
itemLabel: "Élément : {id}",
|
|
727
|
+
listLabel: "Tous les enregistrements"
|
|
1082
728
|
}
|
|
1083
729
|
},
|
|
1084
730
|
de: {
|
|
@@ -1175,6 +821,11 @@ var i18n = createI18n({
|
|
|
1175
821
|
save: "Speichern",
|
|
1176
822
|
saving: "Wird gespeichert...",
|
|
1177
823
|
yes: "Ja"
|
|
824
|
+
},
|
|
825
|
+
pluginPresentCollection: {
|
|
826
|
+
fallbackTitle: "Sammlung",
|
|
827
|
+
itemLabel: "Eintrag: {id}",
|
|
828
|
+
listLabel: "Alle Datensätze"
|
|
1178
829
|
}
|
|
1179
830
|
}
|
|
1180
831
|
}
|
|
@@ -1206,121 +857,106 @@ function useCollectionI18n() {
|
|
|
1206
857
|
};
|
|
1207
858
|
}
|
|
1208
859
|
//#endregion
|
|
1209
|
-
//#region src/vue/components/
|
|
1210
|
-
var
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
"
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
class: "text-xs text-red-600",
|
|
1277
|
-
"data-testid": `collections-embed-missing-${__props.fieldKey}`
|
|
1278
|
-
}, toDisplayString(unref(t)("collectionsView.embedMissing", {
|
|
1279
|
-
collection: __props.view.targetSlug,
|
|
1280
|
-
id: __props.view.recordId
|
|
1281
|
-
})), 9, _hoisted_15$5),
|
|
1282
|
-
__props.view.targetSlug ? (openBlock(), createBlock(_component_router_link, {
|
|
1283
|
-
key: 0,
|
|
1284
|
-
to: { path: `/collections/${__props.view.targetSlug}` },
|
|
1285
|
-
class: "inline-flex items-center gap-0.5 text-xs text-indigo-600 hover:text-indigo-800 font-semibold mt-2 hover:underline"
|
|
1286
|
-
}, {
|
|
1287
|
-
default: withCtx(() => [createElementVNode("span", null, toDisplayString(unref(t)("collectionsView.embedCreate")), 1), _cache[2] || (_cache[2] = createElementVNode("span", { class: "material-icons text-xs" }, "arrow_forward", -1))]),
|
|
1288
|
-
_: 1
|
|
1289
|
-
}, 8, ["to"])) : createCommentVNode("", true)
|
|
1290
|
-
])])], 8, _hoisted_11$8));
|
|
860
|
+
//#region src/vue/components/CollectionRecordModal.vue
|
|
861
|
+
var CollectionRecordModal_default = /* @__PURE__ */ defineComponent({
|
|
862
|
+
__name: "CollectionRecordModal",
|
|
863
|
+
emits: ["close"],
|
|
864
|
+
setup(__props, { emit: __emit }) {
|
|
865
|
+
const emit = __emit;
|
|
866
|
+
const teleportTarget = collectionUi().modalTeleportTarget?.() ?? "body";
|
|
867
|
+
const dialogEl = ref(null);
|
|
868
|
+
let previouslyFocused = null;
|
|
869
|
+
const FOCUSABLE_SELECTOR = [
|
|
870
|
+
"a[href]",
|
|
871
|
+
"button:not([disabled])",
|
|
872
|
+
"input:not([disabled])",
|
|
873
|
+
"select:not([disabled])",
|
|
874
|
+
"textarea:not([disabled])",
|
|
875
|
+
"[tabindex]:not([tabindex=\"-1\"])"
|
|
876
|
+
].join(",");
|
|
877
|
+
/** Visible, focusable controls inside the dialog, in DOM order. */
|
|
878
|
+
function focusableItems() {
|
|
879
|
+
if (!dialogEl.value) return [];
|
|
880
|
+
return Array.from(dialogEl.value.querySelectorAll(FOCUSABLE_SELECTOR)).filter((node) => node.offsetParent !== null);
|
|
881
|
+
}
|
|
882
|
+
/** Trap Tab / Shift+Tab inside the dialog so focus can't escape to the
|
|
883
|
+
* page behind the overlay. Wraps at both ends; the dialog container
|
|
884
|
+
* itself (tabindex -1) counts as "before the first item". */
|
|
885
|
+
function onTab(event) {
|
|
886
|
+
const items = focusableItems();
|
|
887
|
+
if (items.length === 0) {
|
|
888
|
+
event.preventDefault();
|
|
889
|
+
dialogEl.value?.focus();
|
|
890
|
+
return;
|
|
891
|
+
}
|
|
892
|
+
const [first] = items;
|
|
893
|
+
const last = items[items.length - 1];
|
|
894
|
+
const active = document.activeElement;
|
|
895
|
+
if (event.shiftKey) {
|
|
896
|
+
if (active === first || active === dialogEl.value) {
|
|
897
|
+
event.preventDefault();
|
|
898
|
+
last.focus();
|
|
899
|
+
}
|
|
900
|
+
} else if (active === last) {
|
|
901
|
+
event.preventDefault();
|
|
902
|
+
first.focus();
|
|
903
|
+
}
|
|
904
|
+
}
|
|
905
|
+
onMounted(async () => {
|
|
906
|
+
previouslyFocused = document.activeElement instanceof HTMLElement ? document.activeElement : null;
|
|
907
|
+
await nextTick();
|
|
908
|
+
dialogEl.value?.focus();
|
|
909
|
+
});
|
|
910
|
+
onBeforeUnmount(() => {
|
|
911
|
+
previouslyFocused?.focus?.();
|
|
912
|
+
});
|
|
913
|
+
return (_ctx, _cache) => {
|
|
914
|
+
return openBlock(), createBlock(Teleport, { to: unref(teleportTarget) }, [createElementVNode("div", {
|
|
915
|
+
class: "fixed inset-0 z-40 flex items-center justify-center bg-slate-900/40 p-4",
|
|
916
|
+
"data-testid": "collections-record-modal",
|
|
917
|
+
onClick: _cache[1] || (_cache[1] = withModifiers(($event) => emit("close"), ["self"]))
|
|
918
|
+
}, [createElementVNode("div", {
|
|
919
|
+
ref_key: "dialogEl",
|
|
920
|
+
ref: dialogEl,
|
|
921
|
+
class: "flex max-h-[85vh] w-full max-w-2xl flex-col overflow-hidden rounded-2xl bg-white shadow-xl focus:outline-none",
|
|
922
|
+
role: "dialog",
|
|
923
|
+
"aria-modal": "true",
|
|
924
|
+
tabindex: "-1",
|
|
925
|
+
onKeydown: [_cache[0] || (_cache[0] = withKeys(($event) => emit("close"), ["esc"])), withKeys(onTab, ["tab"])]
|
|
926
|
+
}, [renderSlot(_ctx.$slots, "default")], 544)])], 8, ["to"]);
|
|
1291
927
|
};
|
|
1292
928
|
}
|
|
1293
929
|
});
|
|
1294
930
|
//#endregion
|
|
1295
931
|
//#region src/vue/components/CollectionCalendarView.vue?vue&type=script&setup=true&lang.ts
|
|
1296
|
-
var _hoisted_1$
|
|
932
|
+
var _hoisted_1$11 = {
|
|
1297
933
|
class: "flex flex-col gap-3",
|
|
1298
934
|
"data-testid": "collection-calendar"
|
|
1299
935
|
};
|
|
1300
|
-
var _hoisted_2$
|
|
1301
|
-
var _hoisted_3$
|
|
1302
|
-
var _hoisted_4$
|
|
1303
|
-
var _hoisted_5$
|
|
936
|
+
var _hoisted_2$10 = { class: "flex items-center gap-2" };
|
|
937
|
+
var _hoisted_3$10 = ["aria-label"];
|
|
938
|
+
var _hoisted_4$10 = ["aria-label"];
|
|
939
|
+
var _hoisted_5$9 = {
|
|
1304
940
|
class: "text-sm font-bold text-slate-800 flex-1",
|
|
1305
941
|
"data-testid": "collection-calendar-month"
|
|
1306
942
|
};
|
|
1307
|
-
var _hoisted_6$
|
|
1308
|
-
var _hoisted_7$
|
|
1309
|
-
var _hoisted_8$
|
|
943
|
+
var _hoisted_6$8 = { class: "grid grid-cols-7 gap-1 text-[10px] font-bold text-slate-400 uppercase tracking-wider select-none" };
|
|
944
|
+
var _hoisted_7$8 = { class: "grid grid-cols-7 gap-1" };
|
|
945
|
+
var _hoisted_8$8 = [
|
|
1310
946
|
"aria-label",
|
|
1311
947
|
"data-testid",
|
|
1312
948
|
"onClick",
|
|
1313
949
|
"onKeydown"
|
|
1314
950
|
];
|
|
1315
|
-
var _hoisted_9$
|
|
1316
|
-
var _hoisted_10$
|
|
1317
|
-
var _hoisted_11$
|
|
951
|
+
var _hoisted_9$8 = { class: "flex items-center justify-end" };
|
|
952
|
+
var _hoisted_10$8 = ["data-testid", "onClick"];
|
|
953
|
+
var _hoisted_11$8 = {
|
|
1318
954
|
key: 0,
|
|
1319
955
|
class: "flex flex-wrap items-center gap-1.5 pt-1",
|
|
1320
956
|
"data-testid": "collection-calendar-no-date"
|
|
1321
957
|
};
|
|
1322
|
-
var _hoisted_12$
|
|
1323
|
-
var _hoisted_13$
|
|
958
|
+
var _hoisted_12$7 = { class: "text-[10px] font-bold text-slate-400 uppercase tracking-wider mr-1" };
|
|
959
|
+
var _hoisted_13$6 = ["data-testid", "onClick"];
|
|
1324
960
|
/** Sort key for ordering a day's chips by start time: earliest first, with
|
|
1325
961
|
* clock-less all-day records sinking to the bottom (matching the day view). */
|
|
1326
962
|
var DAY_CHIP_DEFAULT = "bg-indigo-50 text-indigo-700 border-indigo-100 hover:bg-indigo-100";
|
|
@@ -1434,23 +1070,23 @@ var CollectionCalendarView_default = /* @__PURE__ */ defineComponent({
|
|
|
1434
1070
|
viewMonth.value = now.getMonth() + 1;
|
|
1435
1071
|
}
|
|
1436
1072
|
return (_ctx, _cache) => {
|
|
1437
|
-
return openBlock(), createElementBlock("div", _hoisted_1$
|
|
1438
|
-
createElementVNode("div", _hoisted_2$
|
|
1073
|
+
return openBlock(), createElementBlock("div", _hoisted_1$11, [
|
|
1074
|
+
createElementVNode("div", _hoisted_2$10, [
|
|
1439
1075
|
createElementVNode("button", {
|
|
1440
1076
|
type: "button",
|
|
1441
1077
|
class: "h-8 w-8 flex items-center justify-center rounded text-slate-500 hover:bg-slate-100 transition-colors",
|
|
1442
1078
|
"aria-label": unref(t)("collectionsView.calendarPrevMonth"),
|
|
1443
1079
|
"data-testid": "collection-calendar-prev",
|
|
1444
1080
|
onClick: _cache[0] || (_cache[0] = ($event) => stepMonth(-1))
|
|
1445
|
-
}, [..._cache[2] || (_cache[2] = [createElementVNode("span", { class: "material-icons text-lg" }, "chevron_left", -1)])], 8, _hoisted_3$
|
|
1081
|
+
}, [..._cache[2] || (_cache[2] = [createElementVNode("span", { class: "material-icons text-lg" }, "chevron_left", -1)])], 8, _hoisted_3$10),
|
|
1446
1082
|
createElementVNode("button", {
|
|
1447
1083
|
type: "button",
|
|
1448
1084
|
class: "h-8 w-8 flex items-center justify-center rounded text-slate-500 hover:bg-slate-100 transition-colors",
|
|
1449
1085
|
"aria-label": unref(t)("collectionsView.calendarNextMonth"),
|
|
1450
1086
|
"data-testid": "collection-calendar-next",
|
|
1451
1087
|
onClick: _cache[1] || (_cache[1] = ($event) => stepMonth(1))
|
|
1452
|
-
}, [..._cache[3] || (_cache[3] = [createElementVNode("span", { class: "material-icons text-lg" }, "chevron_right", -1)])], 8, _hoisted_4$
|
|
1453
|
-
createElementVNode("h3", _hoisted_5$
|
|
1088
|
+
}, [..._cache[3] || (_cache[3] = [createElementVNode("span", { class: "material-icons text-lg" }, "chevron_right", -1)])], 8, _hoisted_4$10),
|
|
1089
|
+
createElementVNode("h3", _hoisted_5$9, toDisplayString(monthLabel.value), 1),
|
|
1454
1090
|
createElementVNode("button", {
|
|
1455
1091
|
type: "button",
|
|
1456
1092
|
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",
|
|
@@ -1458,13 +1094,13 @@ var CollectionCalendarView_default = /* @__PURE__ */ defineComponent({
|
|
|
1458
1094
|
onClick: goToday
|
|
1459
1095
|
}, toDisplayString(unref(t)("collectionsView.calendarToday")), 1)
|
|
1460
1096
|
]),
|
|
1461
|
-
createElementVNode("div", _hoisted_6$
|
|
1097
|
+
createElementVNode("div", _hoisted_6$8, [(openBlock(true), createElementBlock(Fragment, null, renderList(weekdayLabels.value, (label, idx) => {
|
|
1462
1098
|
return openBlock(), createElementBlock("div", {
|
|
1463
1099
|
key: idx,
|
|
1464
1100
|
class: "px-1 py-1 text-center"
|
|
1465
1101
|
}, toDisplayString(label), 1);
|
|
1466
1102
|
}), 128))]),
|
|
1467
|
-
createElementVNode("div", _hoisted_7$
|
|
1103
|
+
createElementVNode("div", _hoisted_7$8, [(openBlock(true), createElementBlock(Fragment, null, renderList(cells.value, ({ cell, entries }) => {
|
|
1468
1104
|
return openBlock(), createElementBlock("div", {
|
|
1469
1105
|
key: cell.key,
|
|
1470
1106
|
class: normalizeClass(["min-h-[5.5rem] rounded-lg border p-1 flex flex-col gap-1 overflow-hidden transition-colors cursor-pointer hover:border-indigo-300 focus:outline-none focus:ring-2 focus:ring-indigo-500/30", cell.inMonth ? "bg-white border-slate-200" : "bg-slate-50/50 border-slate-100"]),
|
|
@@ -1474,24 +1110,24 @@ var CollectionCalendarView_default = /* @__PURE__ */ defineComponent({
|
|
|
1474
1110
|
"data-testid": `collection-calendar-day-${cell.key}`,
|
|
1475
1111
|
onClick: ($event) => emit("openDay", cell.ymd),
|
|
1476
1112
|
onKeydown: [withKeys(withModifiers(($event) => emit("openDay", cell.ymd), ["self", "prevent"]), ["enter"]), withKeys(withModifiers(($event) => emit("openDay", cell.ymd), ["self", "prevent"]), ["space"])]
|
|
1477
|
-
}, [createElementVNode("div", _hoisted_9$
|
|
1113
|
+
}, [createElementVNode("div", _hoisted_9$8, [createElementVNode("span", { class: normalizeClass(["text-[11px] font-bold h-5 min-w-5 px-1 inline-flex items-center justify-center rounded-full", cell.key === unref(todayKey) ? "bg-indigo-600 text-white" : cell.inMonth ? "text-slate-500" : "text-slate-300"]) }, toDisplayString(cell.ymd.day), 3)]), (openBlock(true), createElementBlock(Fragment, null, renderList(entries, (entry) => {
|
|
1478
1114
|
return openBlock(), createElementBlock("button", {
|
|
1479
1115
|
key: entry.id,
|
|
1480
1116
|
type: "button",
|
|
1481
1117
|
class: normalizeClass(["text-left text-[11px] leading-tight font-semibold truncate rounded px-1.5 py-0.5 border transition-colors", chipClass(entry, DAY_CHIP_DEFAULT)]),
|
|
1482
1118
|
"data-testid": `collection-calendar-chip-${entry.id}`,
|
|
1483
1119
|
onClick: withModifiers(($event) => emit("select", entry.id), ["stop"])
|
|
1484
|
-
}, toDisplayString(entry.label), 11, _hoisted_10$
|
|
1485
|
-
}), 128))], 42, _hoisted_8$
|
|
1120
|
+
}, toDisplayString(entry.label), 11, _hoisted_10$8);
|
|
1121
|
+
}), 128))], 42, _hoisted_8$8);
|
|
1486
1122
|
}), 128))]),
|
|
1487
|
-
bucketed.value.noDate.length > 0 ? (openBlock(), createElementBlock("div", _hoisted_11$
|
|
1123
|
+
bucketed.value.noDate.length > 0 ? (openBlock(), createElementBlock("div", _hoisted_11$8, [createElementVNode("span", _hoisted_12$7, toDisplayString(unref(t)("collectionsView.calendarNoDate")), 1), (openBlock(true), createElementBlock(Fragment, null, renderList(undatedEntries.value, (entry) => {
|
|
1488
1124
|
return openBlock(), createElementBlock("button", {
|
|
1489
1125
|
key: entry.id,
|
|
1490
1126
|
type: "button",
|
|
1491
1127
|
class: normalizeClass(["text-[11px] font-semibold truncate rounded px-1.5 py-0.5 border transition-colors", chipClass(entry, UNDATED_CHIP_DEFAULT)]),
|
|
1492
1128
|
"data-testid": `collection-calendar-undated-${entry.id}`,
|
|
1493
1129
|
onClick: ($event) => emit("select", entry.id)
|
|
1494
|
-
}, toDisplayString(entry.label), 11, _hoisted_13$
|
|
1130
|
+
}, toDisplayString(entry.label), 11, _hoisted_13$6);
|
|
1495
1131
|
}), 128))])) : createCommentVNode("", true)
|
|
1496
1132
|
]);
|
|
1497
1133
|
};
|
|
@@ -1499,40 +1135,40 @@ var CollectionCalendarView_default = /* @__PURE__ */ defineComponent({
|
|
|
1499
1135
|
});
|
|
1500
1136
|
//#endregion
|
|
1501
1137
|
//#region src/vue/components/CollectionDayView.vue?vue&type=script&setup=true&lang.ts
|
|
1502
|
-
var _hoisted_1$
|
|
1503
|
-
var _hoisted_2$
|
|
1138
|
+
var _hoisted_1$10 = { class: "flex items-center gap-2 border-b border-slate-200 px-4 py-3" };
|
|
1139
|
+
var _hoisted_2$9 = {
|
|
1504
1140
|
class: "flex-1 text-sm font-bold text-slate-800",
|
|
1505
1141
|
"data-testid": "collection-day-view-title"
|
|
1506
1142
|
};
|
|
1507
|
-
var _hoisted_3$
|
|
1508
|
-
var _hoisted_4$
|
|
1509
|
-
var _hoisted_5$
|
|
1143
|
+
var _hoisted_3$9 = ["aria-label"];
|
|
1144
|
+
var _hoisted_4$9 = ["aria-label"];
|
|
1145
|
+
var _hoisted_5$8 = {
|
|
1510
1146
|
key: 0,
|
|
1511
1147
|
class: "px-4 py-10 text-center text-sm text-slate-400"
|
|
1512
1148
|
};
|
|
1513
|
-
var _hoisted_6$
|
|
1514
|
-
var _hoisted_7$
|
|
1149
|
+
var _hoisted_6$7 = { class: "absolute -top-2 left-0 w-10 pr-1 text-right text-[10px] tabular-nums text-slate-400" };
|
|
1150
|
+
var _hoisted_7$7 = {
|
|
1515
1151
|
class: "absolute inset-y-0 right-0",
|
|
1516
1152
|
style: { "left": "2.75rem" }
|
|
1517
1153
|
};
|
|
1518
|
-
var _hoisted_8$
|
|
1519
|
-
var _hoisted_9$
|
|
1520
|
-
var _hoisted_10$
|
|
1154
|
+
var _hoisted_8$7 = ["data-testid", "onClick"];
|
|
1155
|
+
var _hoisted_9$7 = { class: "block truncate text-[11px] font-semibold leading-tight" };
|
|
1156
|
+
var _hoisted_10$7 = {
|
|
1521
1157
|
key: 0,
|
|
1522
1158
|
"aria-hidden": "true"
|
|
1523
1159
|
};
|
|
1524
|
-
var _hoisted_11$
|
|
1160
|
+
var _hoisted_11$7 = {
|
|
1525
1161
|
key: 1,
|
|
1526
1162
|
"aria-hidden": "true"
|
|
1527
1163
|
};
|
|
1528
|
-
var _hoisted_12$
|
|
1164
|
+
var _hoisted_12$6 = {
|
|
1529
1165
|
key: 2,
|
|
1530
1166
|
class: "flex flex-wrap items-center gap-1.5 border-t border-slate-200 px-4 py-2",
|
|
1531
1167
|
"data-testid": "collection-day-view-all-day"
|
|
1532
1168
|
};
|
|
1533
|
-
var _hoisted_13$
|
|
1534
|
-
var _hoisted_14$
|
|
1535
|
-
var _hoisted_15$
|
|
1169
|
+
var _hoisted_13$5 = { class: "mr-1 text-[10px] font-bold uppercase tracking-wider text-slate-400" };
|
|
1170
|
+
var _hoisted_14$5 = ["data-testid", "onClick"];
|
|
1171
|
+
var _hoisted_15$5 = {
|
|
1536
1172
|
key: 0,
|
|
1537
1173
|
class: "min-w-0 flex-1 overflow-y-auto",
|
|
1538
1174
|
"data-testid": "collection-day-view-detail"
|
|
@@ -1691,8 +1327,8 @@ var CollectionDayView_default = /* @__PURE__ */ defineComponent({
|
|
|
1691
1327
|
role: "dialog",
|
|
1692
1328
|
"aria-modal": "true"
|
|
1693
1329
|
}, [createElementVNode("div", { class: normalizeClass(["flex min-h-0 flex-col", __props.showDetail ? "w-80 shrink-0 border-r border-slate-200" : "w-full"]) }, [
|
|
1694
|
-
createElementVNode("div", _hoisted_1$
|
|
1695
|
-
createElementVNode("h3", _hoisted_2$
|
|
1330
|
+
createElementVNode("div", _hoisted_1$10, [
|
|
1331
|
+
createElementVNode("h3", _hoisted_2$9, toDisplayString(dayLabel.value), 1),
|
|
1696
1332
|
__props.canCreate ? (openBlock(), createElementBlock("button", {
|
|
1697
1333
|
key: 0,
|
|
1698
1334
|
type: "button",
|
|
@@ -1700,16 +1336,16 @@ var CollectionDayView_default = /* @__PURE__ */ defineComponent({
|
|
|
1700
1336
|
"aria-label": unref(t)("collectionsView.calendarCreateOn", { date: dayKey.value }),
|
|
1701
1337
|
"data-testid": "collection-day-view-create",
|
|
1702
1338
|
onClick: onCreate
|
|
1703
|
-
}, [..._cache[3] || (_cache[3] = [createElementVNode("span", { class: "material-icons text-lg" }, "add", -1)])], 8, _hoisted_3$
|
|
1339
|
+
}, [..._cache[3] || (_cache[3] = [createElementVNode("span", { class: "material-icons text-lg" }, "add", -1)])], 8, _hoisted_3$9)) : createCommentVNode("", true),
|
|
1704
1340
|
createElementVNode("button", {
|
|
1705
1341
|
type: "button",
|
|
1706
1342
|
class: "h-8 w-8 flex items-center justify-center rounded text-slate-500 hover:bg-slate-100 transition-colors",
|
|
1707
1343
|
"aria-label": unref(t)("collectionsView.dayViewClose"),
|
|
1708
1344
|
"data-testid": "collection-day-view-close",
|
|
1709
1345
|
onClick: _cache[0] || (_cache[0] = ($event) => emit("close"))
|
|
1710
|
-
}, [..._cache[4] || (_cache[4] = [createElementVNode("span", { class: "material-icons text-lg" }, "close", -1)])], 8, _hoisted_4$
|
|
1346
|
+
}, [..._cache[4] || (_cache[4] = [createElementVNode("span", { class: "material-icons text-lg" }, "close", -1)])], 8, _hoisted_4$9)
|
|
1711
1347
|
]),
|
|
1712
|
-
timedEntries.value.length === 0 && allDayEntries.value.length === 0 ? (openBlock(), createElementBlock("div", _hoisted_5$
|
|
1348
|
+
timedEntries.value.length === 0 && allDayEntries.value.length === 0 ? (openBlock(), createElementBlock("div", _hoisted_5$8, toDisplayString(unref(t)("collectionsView.dayViewEmpty")), 1)) : (openBlock(), createElementBlock("div", {
|
|
1713
1349
|
key: 1,
|
|
1714
1350
|
ref_key: "scrollEl",
|
|
1715
1351
|
ref: scrollEl,
|
|
@@ -1723,8 +1359,8 @@ var CollectionDayView_default = /* @__PURE__ */ defineComponent({
|
|
|
1723
1359
|
key: hour,
|
|
1724
1360
|
class: "absolute left-0 right-0 border-t border-slate-100",
|
|
1725
1361
|
style: normalizeStyle({ top: `${(hour - 1) * HOUR_PX}px` })
|
|
1726
|
-
}, [createElementVNode("span", _hoisted_6$
|
|
1727
|
-
}), 64)), createElementVNode("div", _hoisted_7$
|
|
1362
|
+
}, [createElementVNode("span", _hoisted_6$7, toDisplayString(hourLabel(hour - 1)), 1)], 4);
|
|
1363
|
+
}), 64)), createElementVNode("div", _hoisted_7$7, [(openBlock(true), createElementBlock(Fragment, null, renderList(timedEntries.value, (entry) => {
|
|
1728
1364
|
return openBlock(), createElementBlock("button", {
|
|
1729
1365
|
key: entry.id,
|
|
1730
1366
|
type: "button",
|
|
@@ -1732,56 +1368,56 @@ var CollectionDayView_default = /* @__PURE__ */ defineComponent({
|
|
|
1732
1368
|
style: normalizeStyle(entry.style),
|
|
1733
1369
|
"data-testid": `collection-day-view-chip-${entry.id}`,
|
|
1734
1370
|
onClick: ($event) => onSelect(entry.id)
|
|
1735
|
-
}, [createElementVNode("span", _hoisted_9$
|
|
1736
|
-
entry.slice.bleedsBefore ? (openBlock(), createElementBlock("span", _hoisted_10$
|
|
1371
|
+
}, [createElementVNode("span", _hoisted_9$7, [
|
|
1372
|
+
entry.slice.bleedsBefore ? (openBlock(), createElementBlock("span", _hoisted_10$7, "▲ ")) : createCommentVNode("", true),
|
|
1737
1373
|
createTextVNode(toDisplayString(entry.label), 1),
|
|
1738
|
-
entry.slice.bleedsAfter ? (openBlock(), createElementBlock("span", _hoisted_11$
|
|
1374
|
+
entry.slice.bleedsAfter ? (openBlock(), createElementBlock("span", _hoisted_11$7, " ▼")) : createCommentVNode("", true)
|
|
1739
1375
|
]), (openBlock(true), createElementBlock(Fragment, null, renderList(entry.secondary, (text, i) => {
|
|
1740
1376
|
return openBlock(), createElementBlock("span", {
|
|
1741
1377
|
key: i,
|
|
1742
1378
|
class: "block truncate text-[10px] leading-tight opacity-70"
|
|
1743
1379
|
}, toDisplayString(text), 1);
|
|
1744
|
-
}), 128))], 14, _hoisted_8$
|
|
1380
|
+
}), 128))], 14, _hoisted_8$7);
|
|
1745
1381
|
}), 128))])], 4)], 512)),
|
|
1746
|
-
allDayEntries.value.length > 0 ? (openBlock(), createElementBlock("div", _hoisted_12$
|
|
1382
|
+
allDayEntries.value.length > 0 ? (openBlock(), createElementBlock("div", _hoisted_12$6, [createElementVNode("span", _hoisted_13$5, toDisplayString(unref(t)("collectionsView.dayViewAllDay")), 1), (openBlock(true), createElementBlock(Fragment, null, renderList(allDayEntries.value, (entry) => {
|
|
1747
1383
|
return openBlock(), createElementBlock("button", {
|
|
1748
1384
|
key: entry.id,
|
|
1749
1385
|
type: "button",
|
|
1750
1386
|
class: normalizeClass(["truncate rounded border px-1.5 py-0.5 text-[11px] font-semibold transition-colors", allDayChipClass(entry)]),
|
|
1751
1387
|
"data-testid": `collection-day-view-allday-${entry.id}`,
|
|
1752
1388
|
onClick: ($event) => onSelect(entry.id)
|
|
1753
|
-
}, toDisplayString(entry.label), 11, _hoisted_14$
|
|
1389
|
+
}, toDisplayString(entry.label), 11, _hoisted_14$5);
|
|
1754
1390
|
}), 128))])) : createCommentVNode("", true)
|
|
1755
|
-
], 2), __props.showDetail ? (openBlock(), createElementBlock("div", _hoisted_15$
|
|
1391
|
+
], 2), __props.showDetail ? (openBlock(), createElementBlock("div", _hoisted_15$5, [renderSlot(_ctx.$slots, "detail")])) : createCommentVNode("", true)], 2)], 32);
|
|
1756
1392
|
};
|
|
1757
1393
|
}
|
|
1758
1394
|
});
|
|
1759
1395
|
//#endregion
|
|
1760
1396
|
//#region src/vue/components/CollectionKanbanView.vue?vue&type=script&setup=true&lang.ts
|
|
1761
|
-
var _hoisted_1$
|
|
1397
|
+
var _hoisted_1$9 = {
|
|
1762
1398
|
class: "h-full overflow-x-auto overflow-y-hidden",
|
|
1763
1399
|
"data-testid": "collection-kanban"
|
|
1764
1400
|
};
|
|
1765
|
-
var _hoisted_2$
|
|
1766
|
-
var _hoisted_3$
|
|
1767
|
-
var _hoisted_4$
|
|
1768
|
-
var _hoisted_5$
|
|
1769
|
-
var _hoisted_6$
|
|
1770
|
-
var _hoisted_7$
|
|
1771
|
-
var _hoisted_8$
|
|
1401
|
+
var _hoisted_2$8 = { class: "flex gap-3 h-full p-1 min-w-max" };
|
|
1402
|
+
var _hoisted_3$8 = ["data-testid"];
|
|
1403
|
+
var _hoisted_4$8 = { class: "flex items-center justify-between px-3 py-2 border-b border-slate-200" };
|
|
1404
|
+
var _hoisted_5$7 = { class: "flex items-center gap-2 min-w-0" };
|
|
1405
|
+
var _hoisted_6$6 = ["title"];
|
|
1406
|
+
var _hoisted_7$6 = { class: "text-[11px] text-slate-400 shrink-0" };
|
|
1407
|
+
var _hoisted_8$6 = [
|
|
1772
1408
|
"data-testid",
|
|
1773
1409
|
"aria-label",
|
|
1774
1410
|
"onClick",
|
|
1775
1411
|
"onKeydown"
|
|
1776
1412
|
];
|
|
1777
|
-
var _hoisted_9$
|
|
1778
|
-
var _hoisted_10$
|
|
1413
|
+
var _hoisted_9$6 = { class: "flex items-start gap-2" };
|
|
1414
|
+
var _hoisted_10$6 = [
|
|
1779
1415
|
"checked",
|
|
1780
1416
|
"aria-label",
|
|
1781
1417
|
"data-testid",
|
|
1782
1418
|
"onChange"
|
|
1783
1419
|
];
|
|
1784
|
-
var _hoisted_11$
|
|
1420
|
+
var _hoisted_11$6 = { class: "text-sm font-medium text-slate-800 truncate" };
|
|
1785
1421
|
var UNCATEGORIZED = "";
|
|
1786
1422
|
//#endregion
|
|
1787
1423
|
//#region src/vue/components/CollectionKanbanView.vue
|
|
@@ -1879,15 +1515,15 @@ var CollectionKanbanView_default = /* @__PURE__ */ defineComponent({
|
|
|
1879
1515
|
emit("move", itemId(item), next);
|
|
1880
1516
|
}
|
|
1881
1517
|
return (_ctx, _cache) => {
|
|
1882
|
-
return openBlock(), createElementBlock("div", _hoisted_1$
|
|
1518
|
+
return openBlock(), createElementBlock("div", _hoisted_1$9, [createElementVNode("div", _hoisted_2$8, [(openBlock(true), createElementBlock(Fragment, null, renderList(columns.value, (column) => {
|
|
1883
1519
|
return openBlock(), createElementBlock("div", {
|
|
1884
1520
|
key: column.value,
|
|
1885
1521
|
"data-testid": `collection-kanban-column-${column.value || "uncategorized"}`,
|
|
1886
1522
|
class: "w-72 shrink-0 flex flex-col bg-slate-100 rounded-lg"
|
|
1887
|
-
}, [createElementVNode("div", _hoisted_4$
|
|
1523
|
+
}, [createElementVNode("div", _hoisted_4$8, [createElementVNode("div", _hoisted_5$7, [createElementVNode("span", { class: normalizeClass(["w-2 h-2 rounded-full shrink-0", unref(resolveEnumColor)(__props.schema, __props.groupField, column.value).dot]) }, null, 2), createElementVNode("span", {
|
|
1888
1524
|
class: "font-semibold text-xs text-slate-600 truncate",
|
|
1889
1525
|
title: column.label
|
|
1890
|
-
}, toDisplayString(column.label), 9, _hoisted_6$
|
|
1526
|
+
}, toDisplayString(column.label), 9, _hoisted_6$6)]), createElementVNode("span", _hoisted_7$6, toDisplayString(itemsByColumn(column.value).length), 1)]), createVNode(unref(draggable), {
|
|
1891
1527
|
"model-value": itemsByColumn(column.value),
|
|
1892
1528
|
"item-key": __props.schema.primaryKey,
|
|
1893
1529
|
group: "collection-kanban-cards",
|
|
@@ -1903,7 +1539,7 @@ var CollectionKanbanView_default = /* @__PURE__ */ defineComponent({
|
|
|
1903
1539
|
class: normalizeClass(["bg-white border border-slate-200 rounded shadow-sm p-2 cursor-grab hover:shadow active:cursor-grabbing focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-indigo-400", [itemId(element) === __props.selected ? "ring-2 ring-indigo-500 border-indigo-300" : "", notifyAccentClass(element)]]),
|
|
1904
1540
|
onClick: ($event) => emit("select", itemId(element)),
|
|
1905
1541
|
onKeydown: [withKeys(withModifiers((e) => !e.repeat && emit("select", itemId(element)), ["prevent", "self"]), ["enter"]), withKeys(withModifiers((e) => !e.repeat && emit("select", itemId(element)), ["prevent", "self"]), ["space"])]
|
|
1906
|
-
}, [createElementVNode("div", _hoisted_9$
|
|
1542
|
+
}, [createElementVNode("div", _hoisted_9$6, [cardToggle.value ? (openBlock(), createElementBlock("input", {
|
|
1907
1543
|
key: 0,
|
|
1908
1544
|
type: "checkbox",
|
|
1909
1545
|
checked: cardChecked(element),
|
|
@@ -1912,24 +1548,138 @@ var CollectionKanbanView_default = /* @__PURE__ */ defineComponent({
|
|
|
1912
1548
|
"data-testid": `collection-kanban-toggle-${itemId(element)}`,
|
|
1913
1549
|
onClick: _cache[0] || (_cache[0] = withModifiers(() => {}, ["stop"])),
|
|
1914
1550
|
onChange: ($event) => onCardToggle(element)
|
|
1915
|
-
}, null, 40, _hoisted_10$
|
|
1551
|
+
}, null, 40, _hoisted_10$6)) : createCommentVNode("", true), createElementVNode("div", _hoisted_11$6, toDisplayString(itemLabel(element)), 1)])], 42, _hoisted_8$6)]),
|
|
1916
1552
|
_: 1
|
|
1917
1553
|
}, 8, [
|
|
1918
1554
|
"model-value",
|
|
1919
1555
|
"item-key",
|
|
1920
1556
|
"onChange"
|
|
1921
|
-
])], 8, _hoisted_3$
|
|
1557
|
+
])], 8, _hoisted_3$8);
|
|
1922
1558
|
}), 128))])]);
|
|
1923
1559
|
};
|
|
1924
1560
|
}
|
|
1925
1561
|
});
|
|
1926
1562
|
//#endregion
|
|
1563
|
+
//#region src/vue/refLink.ts
|
|
1564
|
+
function isModifiedClick(event) {
|
|
1565
|
+
return event instanceof MouseEvent && (event.metaKey || event.ctrlKey || event.shiftKey || event.altKey);
|
|
1566
|
+
}
|
|
1567
|
+
/** Activate a ref/embed link → navigate to `targetSlug` (optionally a record). */
|
|
1568
|
+
function activateRefLink(event, targetSlug, recordId, stop = false) {
|
|
1569
|
+
if (stop) event.stopPropagation();
|
|
1570
|
+
if (isModifiedClick(event)) return;
|
|
1571
|
+
event.preventDefault();
|
|
1572
|
+
collectionUi().navigateToRecord(targetSlug, recordId);
|
|
1573
|
+
}
|
|
1574
|
+
/** Activate a `file` cell link → navigate to a host path. When the host has no
|
|
1575
|
+
* `navigate` capability, do NOT preventDefault so the `href` still works (or, in
|
|
1576
|
+
* a router-less host that also has no path, the link simply isn't rendered). */
|
|
1577
|
+
function activatePathLink(event, path, stop = false) {
|
|
1578
|
+
if (stop) event.stopPropagation();
|
|
1579
|
+
if (isModifiedClick(event)) return;
|
|
1580
|
+
const nav = collectionUi().navigate;
|
|
1581
|
+
if (!nav) return;
|
|
1582
|
+
event.preventDefault();
|
|
1583
|
+
nav(path);
|
|
1584
|
+
}
|
|
1585
|
+
//#endregion
|
|
1586
|
+
//#region src/vue/components/CollectionEmbedView.vue?vue&type=script&setup=true&lang.ts
|
|
1587
|
+
var _hoisted_1$8 = [
|
|
1588
|
+
"href",
|
|
1589
|
+
"tabindex",
|
|
1590
|
+
"data-testid"
|
|
1591
|
+
];
|
|
1592
|
+
var _hoisted_2$7 = { class: "flex items-center justify-between text-[10px] font-bold text-indigo-600/90 tracking-wider uppercase" };
|
|
1593
|
+
var _hoisted_3$7 = { class: "flex items-center gap-1.5" };
|
|
1594
|
+
var _hoisted_4$7 = { class: "bg-indigo-100/60 text-indigo-700 px-1.5 py-0.5 rounded font-mono font-medium lowercase" };
|
|
1595
|
+
var _hoisted_5$6 = { class: "grid gap-x-4 gap-y-3 grid-cols-2" };
|
|
1596
|
+
var _hoisted_6$5 = { class: "text-[10px] font-semibold text-slate-400 uppercase tracking-wide" };
|
|
1597
|
+
var _hoisted_7$5 = ["data-testid"];
|
|
1598
|
+
var _hoisted_8$5 = {
|
|
1599
|
+
key: 0,
|
|
1600
|
+
class: "material-icons text-emerald-600 text-sm align-middle"
|
|
1601
|
+
};
|
|
1602
|
+
var _hoisted_9$5 = {
|
|
1603
|
+
key: 1,
|
|
1604
|
+
class: "text-slate-300"
|
|
1605
|
+
};
|
|
1606
|
+
var _hoisted_10$5 = {
|
|
1607
|
+
key: 1,
|
|
1608
|
+
class: "whitespace-pre-wrap font-normal text-slate-600"
|
|
1609
|
+
};
|
|
1610
|
+
var _hoisted_11$5 = { key: 2 };
|
|
1611
|
+
var _hoisted_12$5 = ["data-testid"];
|
|
1612
|
+
var _hoisted_13$4 = { class: "flex items-start gap-3" };
|
|
1613
|
+
var _hoisted_14$4 = { class: "flex-1 min-w-0" };
|
|
1614
|
+
var _hoisted_15$4 = { class: "text-xs font-semibold text-red-800 uppercase tracking-wider mb-1" };
|
|
1615
|
+
var _hoisted_16$3 = ["data-testid"];
|
|
1616
|
+
var _hoisted_17$3 = ["href", "tabindex"];
|
|
1617
|
+
//#endregion
|
|
1618
|
+
//#region src/vue/components/CollectionEmbedView.vue
|
|
1619
|
+
var CollectionEmbedView_default = /* @__PURE__ */ defineComponent({
|
|
1620
|
+
__name: "CollectionEmbedView",
|
|
1621
|
+
props: {
|
|
1622
|
+
view: {},
|
|
1623
|
+
fieldKey: {}
|
|
1624
|
+
},
|
|
1625
|
+
setup(__props) {
|
|
1626
|
+
const { t } = useCollectionI18n();
|
|
1627
|
+
const cui = collectionUi();
|
|
1628
|
+
return (_ctx, _cache) => {
|
|
1629
|
+
return __props.view.found ? (openBlock(), createElementBlock("a", {
|
|
1630
|
+
key: 0,
|
|
1631
|
+
href: unref(cui).recordHref?.(__props.view.targetSlug, __props.view.recordId),
|
|
1632
|
+
tabindex: unref(cui).recordHref?.(__props.view.targetSlug, __props.view.recordId) ? void 0 : 0,
|
|
1633
|
+
role: "link",
|
|
1634
|
+
class: "group block relative rounded-xl border border-slate-200 bg-slate-50/50 p-4 pl-5 space-y-3 hover:bg-indigo-50/20 hover:border-indigo-200 transition-all duration-300 shadow-sm",
|
|
1635
|
+
"data-testid": `collections-embed-${__props.fieldKey}`,
|
|
1636
|
+
onClick: _cache[0] || (_cache[0] = ($event) => unref(activateRefLink)($event, __props.view.targetSlug, __props.view.recordId)),
|
|
1637
|
+
onKeydown: [_cache[1] || (_cache[1] = withKeys(($event) => unref(activateRefLink)($event, __props.view.targetSlug, __props.view.recordId), ["enter"])), _cache[2] || (_cache[2] = withKeys(($event) => unref(activateRefLink)($event, __props.view.targetSlug, __props.view.recordId), ["space"]))]
|
|
1638
|
+
}, [
|
|
1639
|
+
_cache[7] || (_cache[7] = createElementVNode("div", { class: "absolute left-0 top-0 bottom-0 w-1 bg-indigo-500 rounded-l-xl transition-all duration-300 group-hover:w-1.5 group-hover:bg-indigo-600" }, null, -1)),
|
|
1640
|
+
createElementVNode("div", _hoisted_2$7, [createElementVNode("div", _hoisted_3$7, [_cache[6] || (_cache[6] = createElementVNode("span", { class: "material-icons text-sm" }, "link", -1)), createElementVNode("span", null, toDisplayString(__props.view.targetSlug), 1)]), createElementVNode("span", _hoisted_4$7, toDisplayString(__props.view.recordId), 1)]),
|
|
1641
|
+
createElementVNode("div", _hoisted_5$6, [(openBlock(true), createElementBlock(Fragment, null, renderList(__props.view.rows, (row) => {
|
|
1642
|
+
return openBlock(), createElementBlock("div", {
|
|
1643
|
+
key: row.key,
|
|
1644
|
+
class: "space-y-0.5"
|
|
1645
|
+
}, [createElementVNode("div", _hoisted_6$5, toDisplayString(row.label), 1), createElementVNode("div", {
|
|
1646
|
+
class: "text-xs text-slate-700 font-medium break-words",
|
|
1647
|
+
"data-testid": `collections-embed-${__props.fieldKey}-${row.key}`
|
|
1648
|
+
}, [row.type === "boolean" ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [row.value === true ? (openBlock(), createElementBlock("span", _hoisted_8$5, "check_circle")) : (openBlock(), createElementBlock("span", _hoisted_9$5, "—"))], 64)) : row.type === "markdown" ? (openBlock(), createElementBlock("p", _hoisted_10$5, toDisplayString(row.display), 1)) : (openBlock(), createElementBlock("span", _hoisted_11$5, toDisplayString(row.display), 1))], 8, _hoisted_7$5)]);
|
|
1649
|
+
}), 128))])
|
|
1650
|
+
], 40, _hoisted_1$8)) : (openBlock(), createElementBlock("div", {
|
|
1651
|
+
key: 1,
|
|
1652
|
+
class: "relative rounded-xl border border-red-100 bg-red-50/30 p-4 pl-5 shadow-sm",
|
|
1653
|
+
"data-testid": `collections-embed-${__props.fieldKey}`
|
|
1654
|
+
}, [_cache[10] || (_cache[10] = createElementVNode("div", { class: "absolute left-0 top-0 bottom-0 w-1 bg-red-400 rounded-l-xl" }, null, -1)), createElementVNode("div", _hoisted_13$4, [_cache[9] || (_cache[9] = createElementVNode("span", { class: "material-icons text-red-500 text-lg mt-0.5" }, "error_outline", -1)), createElementVNode("div", _hoisted_14$4, [
|
|
1655
|
+
createElementVNode("p", _hoisted_15$4, toDisplayString(unref(t)("collectionsView.embedMissingTitle")), 1),
|
|
1656
|
+
createElementVNode("p", {
|
|
1657
|
+
class: "text-xs text-red-600",
|
|
1658
|
+
"data-testid": `collections-embed-missing-${__props.fieldKey}`
|
|
1659
|
+
}, toDisplayString(unref(t)("collectionsView.embedMissing", {
|
|
1660
|
+
collection: __props.view.targetSlug,
|
|
1661
|
+
id: __props.view.recordId
|
|
1662
|
+
})), 9, _hoisted_16$3),
|
|
1663
|
+
__props.view.targetSlug ? (openBlock(), createElementBlock("a", {
|
|
1664
|
+
key: 0,
|
|
1665
|
+
href: unref(cui).recordHref?.(__props.view.targetSlug),
|
|
1666
|
+
tabindex: unref(cui).recordHref?.(__props.view.targetSlug) ? void 0 : 0,
|
|
1667
|
+
role: "link",
|
|
1668
|
+
class: "inline-flex items-center gap-0.5 text-xs text-indigo-600 hover:text-indigo-800 font-semibold mt-2 hover:underline",
|
|
1669
|
+
onClick: _cache[3] || (_cache[3] = ($event) => unref(activateRefLink)($event, __props.view.targetSlug)),
|
|
1670
|
+
onKeydown: [_cache[4] || (_cache[4] = withKeys(($event) => unref(activateRefLink)($event, __props.view.targetSlug), ["enter"])), _cache[5] || (_cache[5] = withKeys(($event) => unref(activateRefLink)($event, __props.view.targetSlug), ["space"]))]
|
|
1671
|
+
}, [createElementVNode("span", null, toDisplayString(unref(t)("collectionsView.embedCreate")), 1), _cache[8] || (_cache[8] = createElementVNode("span", { class: "material-icons text-xs" }, "arrow_forward", -1))], 40, _hoisted_17$3)) : createCommentVNode("", true)
|
|
1672
|
+
])])], 8, _hoisted_12$5));
|
|
1673
|
+
};
|
|
1674
|
+
}
|
|
1675
|
+
});
|
|
1676
|
+
//#endregion
|
|
1927
1677
|
//#region src/vue/components/CollectionRecordPanel.vue?vue&type=script&setup=true&lang.ts
|
|
1928
|
-
var _hoisted_1$
|
|
1929
|
-
var _hoisted_2$
|
|
1930
|
-
var _hoisted_3$
|
|
1931
|
-
var _hoisted_4$
|
|
1932
|
-
var _hoisted_5$
|
|
1678
|
+
var _hoisted_1$7 = { class: "flex items-center gap-2 mb-4" };
|
|
1679
|
+
var _hoisted_2$6 = { class: "flex-1 min-w-0" };
|
|
1680
|
+
var _hoisted_3$6 = { class: "block text-[9px] font-bold text-slate-400 uppercase tracking-wider" };
|
|
1681
|
+
var _hoisted_4$6 = ["data-testid"];
|
|
1682
|
+
var _hoisted_5$5 = ["disabled"];
|
|
1933
1683
|
var _hoisted_6$4 = {
|
|
1934
1684
|
key: 1,
|
|
1935
1685
|
class: "flex items-center gap-2"
|
|
@@ -2065,49 +1815,61 @@ var _hoisted_52$1 = {
|
|
|
2065
1815
|
key: 2,
|
|
2066
1816
|
class: "text-slate-300"
|
|
2067
1817
|
};
|
|
2068
|
-
var _hoisted_53$1 =
|
|
1818
|
+
var _hoisted_53$1 = [
|
|
1819
|
+
"href",
|
|
1820
|
+
"tabindex",
|
|
1821
|
+
"data-testid",
|
|
1822
|
+
"onClick",
|
|
1823
|
+
"onKeydown"
|
|
1824
|
+
];
|
|
1825
|
+
var _hoisted_54$1 = {
|
|
2069
1826
|
key: 3,
|
|
2070
1827
|
class: "font-semibold text-slate-900 tabular-nums text-sm"
|
|
2071
1828
|
};
|
|
2072
|
-
var
|
|
1829
|
+
var _hoisted_55$1 = {
|
|
2073
1830
|
key: 4,
|
|
2074
1831
|
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"
|
|
2075
1832
|
};
|
|
2076
|
-
var
|
|
1833
|
+
var _hoisted_56$1 = {
|
|
2077
1834
|
key: 5,
|
|
2078
1835
|
class: "border border-slate-200/80 rounded-xl overflow-hidden shadow-sm mt-1"
|
|
2079
1836
|
};
|
|
2080
|
-
var
|
|
2081
|
-
var
|
|
2082
|
-
var
|
|
2083
|
-
var
|
|
1837
|
+
var _hoisted_57$1 = { class: "w-full text-[11px] text-slate-600 bg-white" };
|
|
1838
|
+
var _hoisted_58$1 = { class: "bg-slate-50 border-b border-slate-200 text-slate-500 font-bold uppercase tracking-wider" };
|
|
1839
|
+
var _hoisted_59$1 = { class: "divide-y divide-slate-100" };
|
|
1840
|
+
var _hoisted_60$1 = {
|
|
2084
1841
|
key: 0,
|
|
2085
1842
|
class: "material-icons text-emerald-600 text-base"
|
|
2086
1843
|
};
|
|
2087
|
-
var
|
|
1844
|
+
var _hoisted_61$1 = {
|
|
2088
1845
|
key: 1,
|
|
2089
1846
|
class: "text-slate-300"
|
|
2090
1847
|
};
|
|
2091
|
-
var
|
|
1848
|
+
var _hoisted_62$1 = {
|
|
2092
1849
|
key: 6,
|
|
2093
1850
|
class: "text-slate-400 italic"
|
|
2094
1851
|
};
|
|
2095
|
-
var
|
|
1852
|
+
var _hoisted_63$1 = {
|
|
2096
1853
|
key: 7,
|
|
2097
1854
|
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"
|
|
2098
1855
|
};
|
|
2099
|
-
var
|
|
1856
|
+
var _hoisted_64$1 = [
|
|
2100
1857
|
"src",
|
|
2101
1858
|
"alt",
|
|
2102
1859
|
"data-testid"
|
|
2103
1860
|
];
|
|
2104
|
-
var _hoisted_64$1 = ["href", "data-testid"];
|
|
2105
1861
|
var _hoisted_65$1 = ["href", "data-testid"];
|
|
2106
|
-
var _hoisted_66$1 =
|
|
1862
|
+
var _hoisted_66$1 = ["href", "data-testid"];
|
|
1863
|
+
var _hoisted_67$1 = [
|
|
1864
|
+
"href",
|
|
1865
|
+
"data-testid",
|
|
1866
|
+
"onClick"
|
|
1867
|
+
];
|
|
1868
|
+
var _hoisted_68$1 = {
|
|
2107
1869
|
key: 13,
|
|
2108
1870
|
class: "text-slate-800 font-semibold"
|
|
2109
1871
|
};
|
|
2110
|
-
var
|
|
1872
|
+
var _hoisted_69$1 = {
|
|
2111
1873
|
key: 0,
|
|
2112
1874
|
class: "col-span-full text-xs font-semibold text-red-600 bg-red-50 border border-red-100 p-2.5 rounded-xl"
|
|
2113
1875
|
};
|
|
@@ -2142,7 +1904,8 @@ var CollectionRecordPanel_default = /* @__PURE__ */ defineComponent({
|
|
|
2142
1904
|
"runAction"
|
|
2143
1905
|
], ["update:editing"]),
|
|
2144
1906
|
setup(__props, { emit: __emit }) {
|
|
2145
|
-
const
|
|
1907
|
+
const cui = collectionUi();
|
|
1908
|
+
const resolveImageSrc = cui.imageSrc;
|
|
2146
1909
|
const props = __props;
|
|
2147
1910
|
const editing = useModel(__props, "editing");
|
|
2148
1911
|
const emit = __emit;
|
|
@@ -2222,17 +1985,16 @@ var CollectionRecordPanel_default = /* @__PURE__ */ defineComponent({
|
|
|
2222
1985
|
if (rows) rows.splice(index, 1);
|
|
2223
1986
|
}
|
|
2224
1987
|
return (_ctx, _cache) => {
|
|
2225
|
-
const _component_router_link = resolveComponent("router-link");
|
|
2226
1988
|
return openBlock(), createBlock(resolveDynamicComponent(editing.value ? "form" : "div"), {
|
|
2227
1989
|
class: "px-6 py-5 max-h-[60vh] overflow-y-auto",
|
|
2228
1990
|
"data-testid": rootTestid.value,
|
|
2229
1991
|
onSubmit: _cache[4] || (_cache[4] = withModifiers(($event) => emit("submit"), ["prevent"]))
|
|
2230
1992
|
}, {
|
|
2231
1993
|
default: withCtx(() => [
|
|
2232
|
-
createElementVNode("div", _hoisted_1$
|
|
1994
|
+
createElementVNode("div", _hoisted_1$7, [createElementVNode("div", _hoisted_2$6, [createElementVNode("span", _hoisted_3$6, toDisplayString(__props.collection.title), 1), createElementVNode("h2", {
|
|
2233
1995
|
class: "text-base font-bold text-slate-800 truncate",
|
|
2234
1996
|
"data-testid": editing.value ? "collections-edit-title" : "collections-detail-title"
|
|
2235
|
-
}, toDisplayString(headerTitle.value), 9, _hoisted_4$
|
|
1997
|
+
}, toDisplayString(headerTitle.value), 9, _hoisted_4$6)]), editing.value ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [createElementVNode("button", {
|
|
2236
1998
|
type: "button",
|
|
2237
1999
|
class: "h-8 px-2.5 rounded text-xs font-bold text-slate-500 hover:bg-slate-200/50 transition-colors",
|
|
2238
2000
|
"data-testid": "collections-editor-cancel",
|
|
@@ -2242,7 +2004,7 @@ var CollectionRecordPanel_default = /* @__PURE__ */ defineComponent({
|
|
|
2242
2004
|
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",
|
|
2243
2005
|
disabled: __props.saving,
|
|
2244
2006
|
"data-testid": "collections-editor-save"
|
|
2245
|
-
}, toDisplayString(__props.saving ? unref(t)("common.saving") : unref(t)("common.save")), 9, _hoisted_5$
|
|
2007
|
+
}, toDisplayString(__props.saving ? unref(t)("common.saving") : unref(t)("common.save")), 9, _hoisted_5$5)], 64)) : (openBlock(), createElementBlock("div", _hoisted_6$4, [
|
|
2246
2008
|
(openBlock(true), createElementBlock(Fragment, null, renderList(__props.visibleActions, (action) => {
|
|
2247
2009
|
return openBlock(), createElementBlock("button", {
|
|
2248
2010
|
key: action.id,
|
|
@@ -2418,23 +2180,21 @@ var CollectionRecordPanel_default = /* @__PURE__ */ defineComponent({
|
|
|
2418
2180
|
key: 1,
|
|
2419
2181
|
class: "text-xs font-medium text-slate-700 break-words",
|
|
2420
2182
|
"data-testid": `collections-detail-value-${key}`
|
|
2421
|
-
}, [field.type === "toggle" ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [field.field !== void 0 && String(detailRecord.value[field.field] ?? "") === field.onValue ? (openBlock(), createElementBlock("span", _hoisted_48$1, [_cache[11] || (_cache[11] = createElementVNode("span", { class: "h-1.5 w-1.5 rounded-full bg-emerald-500" }, null, -1)), createTextVNode(" " + toDisplayString(unref(t)("common.yes")), 1)])) : (openBlock(), createElementBlock("span", _hoisted_49$1, toDisplayString(unref(t)("common.no")), 1))], 64)) : field.type === "boolean" ? (openBlock(), createElementBlock(Fragment, { key: 1 }, [detailRecord.value[key] === true ? (openBlock(), createElementBlock("span", _hoisted_50$1, [_cache[12] || (_cache[12] = createElementVNode("span", { class: "h-1.5 w-1.5 rounded-full bg-emerald-500" }, null, -1)), createTextVNode(" " + toDisplayString(unref(t)("common.yes")), 1)])) : detailRecord.value[key] === false ? (openBlock(), createElementBlock("span", _hoisted_51$1, toDisplayString(unref(t)("common.no")), 1)) : (openBlock(), createElementBlock("span", _hoisted_52$1, "—"))], 64)) : field.type === "ref" && field.to && typeof detailRecord.value[key] === "string" && detailRecord.value[key] ? (openBlock(),
|
|
2183
|
+
}, [field.type === "toggle" ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [field.field !== void 0 && String(detailRecord.value[field.field] ?? "") === field.onValue ? (openBlock(), createElementBlock("span", _hoisted_48$1, [_cache[11] || (_cache[11] = createElementVNode("span", { class: "h-1.5 w-1.5 rounded-full bg-emerald-500" }, null, -1)), createTextVNode(" " + toDisplayString(unref(t)("common.yes")), 1)])) : (openBlock(), createElementBlock("span", _hoisted_49$1, toDisplayString(unref(t)("common.no")), 1))], 64)) : field.type === "boolean" ? (openBlock(), createElementBlock(Fragment, { key: 1 }, [detailRecord.value[key] === true ? (openBlock(), createElementBlock("span", _hoisted_50$1, [_cache[12] || (_cache[12] = createElementVNode("span", { class: "h-1.5 w-1.5 rounded-full bg-emerald-500" }, null, -1)), createTextVNode(" " + toDisplayString(unref(t)("common.yes")), 1)])) : detailRecord.value[key] === false ? (openBlock(), createElementBlock("span", _hoisted_51$1, toDisplayString(unref(t)("common.no")), 1)) : (openBlock(), createElementBlock("span", _hoisted_52$1, "—"))], 64)) : field.type === "ref" && field.to && typeof detailRecord.value[key] === "string" && detailRecord.value[key] ? (openBlock(), createElementBlock("a", {
|
|
2422
2184
|
key: 2,
|
|
2423
|
-
|
|
2424
|
-
|
|
2425
|
-
|
|
2426
|
-
},
|
|
2185
|
+
href: unref(cui).recordHref?.(field.to, String(detailRecord.value[key])),
|
|
2186
|
+
tabindex: unref(cui).recordHref?.(field.to, String(detailRecord.value[key])) ? void 0 : 0,
|
|
2187
|
+
role: "link",
|
|
2427
2188
|
class: "text-indigo-600 hover:text-indigo-800 font-bold hover:underline",
|
|
2428
|
-
"data-testid": `collections-detail-ref-${key}
|
|
2429
|
-
|
|
2430
|
-
|
|
2431
|
-
|
|
2432
|
-
}, 1032, ["to", "data-testid"])) : field.type === "money" ? (openBlock(), createElementBlock("span", _hoisted_53$1, toDisplayString(__props.render.formatMoney(detailRecord.value[key], __props.render.resolveCurrency(field, detailRecord.value), __props.locale)), 1)) : field.type === "derived" ? (openBlock(), createElementBlock("span", _hoisted_54$1, toDisplayString(__props.render.derivedDisplay(field, __props.render.evaluateDerivedAgainstItem(field, String(key), detailRecord.value), detailRecord.value)), 1)) : field.type === "table" && field.of && __props.render.hasTableRows(detailRecord.value[key]) ? (openBlock(), createElementBlock("div", _hoisted_55$1, [createElementVNode("table", _hoisted_56$1, [createElementVNode("thead", _hoisted_57$1, [createElementVNode("tr", null, [(openBlock(true), createElementBlock(Fragment, null, renderList(field.of, (subField, subKey) => {
|
|
2189
|
+
"data-testid": `collections-detail-ref-${key}`,
|
|
2190
|
+
onClick: ($event) => unref(activateRefLink)($event, field.to, String(detailRecord.value[key])),
|
|
2191
|
+
onKeydown: [withKeys(($event) => unref(activateRefLink)($event, field.to, String(detailRecord.value[key])), ["enter"]), withKeys(($event) => unref(activateRefLink)($event, field.to, String(detailRecord.value[key])), ["space"])]
|
|
2192
|
+
}, toDisplayString(__props.render.refDisplay(field.to, String(detailRecord.value[key]))), 41, _hoisted_53$1)) : field.type === "money" ? (openBlock(), createElementBlock("span", _hoisted_54$1, toDisplayString(__props.render.formatMoney(detailRecord.value[key], __props.render.resolveCurrency(field, detailRecord.value), __props.locale)), 1)) : field.type === "derived" ? (openBlock(), createElementBlock("span", _hoisted_55$1, toDisplayString(__props.render.derivedDisplay(field, __props.render.evaluateDerivedAgainstItem(field, String(key), detailRecord.value), detailRecord.value)), 1)) : field.type === "table" && field.of && __props.render.hasTableRows(detailRecord.value[key]) ? (openBlock(), createElementBlock("div", _hoisted_56$1, [createElementVNode("table", _hoisted_57$1, [createElementVNode("thead", _hoisted_58$1, [createElementVNode("tr", null, [(openBlock(true), createElementBlock(Fragment, null, renderList(field.of, (subField, subKey) => {
|
|
2433
2193
|
return openBlock(), createElementBlock("th", {
|
|
2434
2194
|
key: subKey,
|
|
2435
2195
|
class: "text-left px-4 py-2 font-bold"
|
|
2436
2196
|
}, toDisplayString(subField.label), 1);
|
|
2437
|
-
}), 128))])]), createElementVNode("tbody",
|
|
2197
|
+
}), 128))])]), createElementVNode("tbody", _hoisted_59$1, [(openBlock(true), createElementBlock(Fragment, null, renderList(__props.render.tableRows(detailRecord.value[key]), (row, rowIdx) => {
|
|
2438
2198
|
return openBlock(), createElementBlock("tr", {
|
|
2439
2199
|
key: rowIdx,
|
|
2440
2200
|
class: "hover:bg-slate-50/50"
|
|
@@ -2442,12 +2202,12 @@ var CollectionRecordPanel_default = /* @__PURE__ */ defineComponent({
|
|
|
2442
2202
|
return openBlock(), createElementBlock("td", {
|
|
2443
2203
|
key: subKey,
|
|
2444
2204
|
class: "px-4 py-2 align-middle font-medium"
|
|
2445
|
-
}, [subField.type === "boolean" ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [row[subKey] === true ? (openBlock(), createElementBlock("span",
|
|
2205
|
+
}, [subField.type === "boolean" ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [row[subKey] === true ? (openBlock(), createElementBlock("span", _hoisted_60$1, "check_circle")) : (openBlock(), createElementBlock("span", _hoisted_61$1, "—"))], 64)) : (openBlock(), createElementBlock("span", {
|
|
2446
2206
|
key: 1,
|
|
2447
2207
|
class: normalizeClass([subField.type === "money" ? "font-bold text-slate-800 tabular-nums" : ""])
|
|
2448
2208
|
}, toDisplayString(__props.render.formatSubCell(subField, row[subKey], detailRecord.value)), 3))]);
|
|
2449
2209
|
}), 128))]);
|
|
2450
|
-
}), 128))])])])) : field.type === "table" ? (openBlock(), createElementBlock("span",
|
|
2210
|
+
}), 128))])])])) : field.type === "table" ? (openBlock(), createElementBlock("span", _hoisted_62$1, toDisplayString(unref(t)("collectionsView.noRows")), 1)) : field.type === "markdown" ? (openBlock(), createElementBlock("div", _hoisted_63$1, toDisplayString(__props.render.detailText(detailRecord.value[key])), 1)) : field.type === "embed" && embedViews.value[key] ? (openBlock(), createBlock(CollectionEmbedView_default, {
|
|
2451
2211
|
key: 8,
|
|
2452
2212
|
view: embedViews.value[key],
|
|
2453
2213
|
"field-key": String(key)
|
|
@@ -2457,30 +2217,28 @@ var CollectionRecordPanel_default = /* @__PURE__ */ defineComponent({
|
|
|
2457
2217
|
alt: field.label,
|
|
2458
2218
|
class: "max-h-64 max-w-full object-contain rounded-lg border border-slate-200 bg-slate-50",
|
|
2459
2219
|
"data-testid": `collections-detail-image-${key}`
|
|
2460
|
-
}, null, 8,
|
|
2220
|
+
}, null, 8, _hoisted_64$1)) : field.type !== "file" && __props.render.isExternalUrl(detailRecord.value[key]) ? (openBlock(), createElementBlock("a", {
|
|
2461
2221
|
key: 10,
|
|
2462
2222
|
href: String(detailRecord.value[key]),
|
|
2463
2223
|
target: "_blank",
|
|
2464
2224
|
rel: "noopener noreferrer",
|
|
2465
2225
|
class: "text-blue-600 hover:text-blue-800 font-semibold hover:underline break-all",
|
|
2466
2226
|
"data-testid": `collections-detail-url-${key}`
|
|
2467
|
-
}, toDisplayString(String(detailRecord.value[key])), 9,
|
|
2227
|
+
}, toDisplayString(String(detailRecord.value[key])), 9, _hoisted_65$1)) : field.type === "file" && __props.render.artifactUrl(detailRecord.value[key]) ? (openBlock(), createElementBlock("a", {
|
|
2468
2228
|
key: 11,
|
|
2469
2229
|
href: __props.render.artifactUrl(detailRecord.value[key]) ?? void 0,
|
|
2470
2230
|
target: "_blank",
|
|
2471
2231
|
rel: "noopener noreferrer",
|
|
2472
2232
|
class: "text-blue-600 hover:text-blue-800 font-semibold hover:underline break-all",
|
|
2473
2233
|
"data-testid": `collections-detail-file-${key}`
|
|
2474
|
-
}, toDisplayString(String(detailRecord.value[key])), 9,
|
|
2234
|
+
}, toDisplayString(String(detailRecord.value[key])), 9, _hoisted_66$1)) : field.type === "file" && __props.render.fileRoutePath(detailRecord.value[key]) ? (openBlock(), createElementBlock("a", {
|
|
2475
2235
|
key: 12,
|
|
2476
|
-
|
|
2236
|
+
href: __props.render.fileRoutePath(detailRecord.value[key]) ?? void 0,
|
|
2477
2237
|
class: "text-blue-600 hover:text-blue-800 font-semibold hover:underline break-all",
|
|
2478
|
-
"data-testid": `collections-detail-file-${key}
|
|
2479
|
-
|
|
2480
|
-
|
|
2481
|
-
|
|
2482
|
-
}, 1032, ["to", "data-testid"])) : (openBlock(), createElementBlock("span", _hoisted_66$1, toDisplayString(__props.render.formatCell(detailRecord.value[key], field.type)), 1))], 8, _hoisted_47$1))], 2)) : createCommentVNode("", true)], 64);
|
|
2483
|
-
}), 128)), editing.value && __props.saveError ? (openBlock(), createElementBlock("p", _hoisted_67$1, toDisplayString(__props.saveError), 1)) : createCommentVNode("", true)])
|
|
2238
|
+
"data-testid": `collections-detail-file-${key}`,
|
|
2239
|
+
onClick: ($event) => unref(activatePathLink)($event, __props.render.fileRoutePath(detailRecord.value[key]) ?? "")
|
|
2240
|
+
}, toDisplayString(String(detailRecord.value[key])), 9, _hoisted_67$1)) : (openBlock(), createElementBlock("span", _hoisted_68$1, toDisplayString(__props.render.formatCell(detailRecord.value[key], field.type)), 1))], 8, _hoisted_47$1))], 2)) : createCommentVNode("", true)], 64);
|
|
2241
|
+
}), 128)), editing.value && __props.saveError ? (openBlock(), createElementBlock("p", _hoisted_69$1, toDisplayString(__props.saveError), 1)) : createCommentVNode("", true)])
|
|
2484
2242
|
]),
|
|
2485
2243
|
_: 1
|
|
2486
2244
|
}, 40, ["data-testid"]);
|
|
@@ -2489,14 +2247,14 @@ var CollectionRecordPanel_default = /* @__PURE__ */ defineComponent({
|
|
|
2489
2247
|
});
|
|
2490
2248
|
//#endregion
|
|
2491
2249
|
//#region src/vue/components/CollectionViewConfigModal.vue?vue&type=script&setup=true&lang.ts
|
|
2492
|
-
var _hoisted_1$
|
|
2250
|
+
var _hoisted_1$6 = {
|
|
2493
2251
|
"data-testid": "collection-config-modal",
|
|
2494
2252
|
class: "flex flex-col overflow-hidden"
|
|
2495
2253
|
};
|
|
2496
|
-
var _hoisted_2$
|
|
2497
|
-
var _hoisted_3$
|
|
2498
|
-
var _hoisted_4$
|
|
2499
|
-
var _hoisted_5$
|
|
2254
|
+
var _hoisted_2$5 = { class: "flex items-center justify-between gap-2 border-b border-slate-100 px-5 py-3" };
|
|
2255
|
+
var _hoisted_3$5 = { class: "text-sm font-bold text-slate-700" };
|
|
2256
|
+
var _hoisted_4$5 = ["title", "aria-label"];
|
|
2257
|
+
var _hoisted_5$4 = { class: "overflow-y-auto px-5 py-4" };
|
|
2500
2258
|
var _hoisted_6$3 = { class: "mb-2 text-[10px] font-bold uppercase tracking-wider text-slate-400" };
|
|
2501
2259
|
var _hoisted_7$3 = {
|
|
2502
2260
|
key: 0,
|
|
@@ -2561,14 +2319,14 @@ var CollectionViewConfigModal_default = /* @__PURE__ */ defineComponent({
|
|
|
2561
2319
|
}
|
|
2562
2320
|
return (_ctx, _cache) => {
|
|
2563
2321
|
return openBlock(), createBlock(CollectionRecordModal_default, { onClose: _cache[1] || (_cache[1] = ($event) => emit("close")) }, {
|
|
2564
|
-
default: withCtx(() => [createElementVNode("div", _hoisted_1$
|
|
2322
|
+
default: withCtx(() => [createElementVNode("div", _hoisted_1$6, [createElementVNode("header", _hoisted_2$5, [createElementVNode("h2", _hoisted_3$5, toDisplayString(unref(t)("collectionsView.config.title", { title: __props.title })), 1), createElementVNode("button", {
|
|
2565
2323
|
type: "button",
|
|
2566
2324
|
class: "h-8 w-8 flex items-center justify-center rounded text-slate-400 hover:bg-slate-50 hover:text-slate-600",
|
|
2567
2325
|
title: unref(t)("common.close"),
|
|
2568
2326
|
"aria-label": unref(t)("common.close"),
|
|
2569
2327
|
"data-testid": "collection-config-close",
|
|
2570
2328
|
onClick: _cache[0] || (_cache[0] = ($event) => emit("close"))
|
|
2571
|
-
}, [..._cache[2] || (_cache[2] = [createElementVNode("span", { class: "material-icons text-sm" }, "close", -1)])], 8, _hoisted_4$
|
|
2329
|
+
}, [..._cache[2] || (_cache[2] = [createElementVNode("span", { class: "material-icons text-sm" }, "close", -1)])], 8, _hoisted_4$5)]), createElementVNode("div", _hoisted_5$4, [
|
|
2572
2330
|
createElementVNode("h3", _hoisted_6$3, toDisplayString(unref(t)("collectionsView.config.viewsHeading")), 1),
|
|
2573
2331
|
error.value ? (openBlock(), createElementBlock("p", _hoisted_7$3, toDisplayString(error.value), 1)) : createCommentVNode("", true),
|
|
2574
2332
|
__props.views.length > 0 ? (openBlock(), createElementBlock("ul", _hoisted_8$3, [(openBlock(true), createElementBlock(Fragment, null, renderList(__props.views, (view) => {
|
|
@@ -2597,19 +2355,19 @@ var CollectionViewConfigModal_default = /* @__PURE__ */ defineComponent({
|
|
|
2597
2355
|
});
|
|
2598
2356
|
//#endregion
|
|
2599
2357
|
//#region src/vue/components/CollectionCustomView.vue?vue&type=script&setup=true&lang.ts
|
|
2600
|
-
var _hoisted_1$
|
|
2601
|
-
var _hoisted_2$
|
|
2358
|
+
var _hoisted_1$5 = { class: "custom-view-container" };
|
|
2359
|
+
var _hoisted_2$4 = {
|
|
2602
2360
|
key: 0,
|
|
2603
2361
|
class: "custom-view-message",
|
|
2604
2362
|
role: "alert",
|
|
2605
2363
|
"data-testid": "collection-custom-view-error"
|
|
2606
2364
|
};
|
|
2607
|
-
var _hoisted_3$
|
|
2365
|
+
var _hoisted_3$4 = {
|
|
2608
2366
|
key: 1,
|
|
2609
2367
|
class: "custom-view-message",
|
|
2610
2368
|
"data-testid": "collection-custom-view-loading"
|
|
2611
2369
|
};
|
|
2612
|
-
var _hoisted_4$
|
|
2370
|
+
var _hoisted_4$4 = ["title", "srcdoc"];
|
|
2613
2371
|
var REMINT_LEAD_MS = 6e4;
|
|
2614
2372
|
var MIN_REMINT_DELAY_MS = 1e4;
|
|
2615
2373
|
var CollectionCustomView_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineComponent({
|
|
@@ -2665,46 +2423,365 @@ var CollectionCustomView_vue_vue_type_script_setup_true_lang_default = /* @__PUR
|
|
|
2665
2423
|
dataUrl: mint.data.dataUrl,
|
|
2666
2424
|
origin: window.location.origin
|
|
2667
2425
|
});
|
|
2668
|
-
} catch (err) {
|
|
2669
|
-
if (!stale()) error.value = errorMessage(err);
|
|
2670
|
-
} finally {
|
|
2671
|
-
if (!stale()) loading.value = false;
|
|
2426
|
+
} catch (err) {
|
|
2427
|
+
if (!stale()) error.value = errorMessage(err);
|
|
2428
|
+
} finally {
|
|
2429
|
+
if (!stale()) loading.value = false;
|
|
2430
|
+
}
|
|
2431
|
+
}
|
|
2432
|
+
watch([() => props.slug, () => props.view.id], () => void load(), { immediate: true });
|
|
2433
|
+
onBeforeUnmount(clearRefresh);
|
|
2434
|
+
return (_ctx, _cache) => {
|
|
2435
|
+
return openBlock(), createElementBlock("div", _hoisted_1$5, [error.value ? (openBlock(), createElementBlock("div", _hoisted_2$4, toDisplayString(unref(t)("collectionsView.customViewError", { error: error.value })), 1)) : loading.value ? (openBlock(), createElementBlock("div", _hoisted_3$4, toDisplayString(unref(t)("collectionsView.customViewLoading")), 1)) : srcdoc.value ? (openBlock(), createElementBlock("iframe", {
|
|
2436
|
+
key: __props.view.id,
|
|
2437
|
+
"data-testid": "collection-custom-view-iframe",
|
|
2438
|
+
title: __props.view.label,
|
|
2439
|
+
srcdoc: srcdoc.value,
|
|
2440
|
+
sandbox: "allow-scripts allow-popups allow-popups-to-escape-sandbox",
|
|
2441
|
+
class: "w-full h-full border-0"
|
|
2442
|
+
}, null, 8, _hoisted_4$4)) : createCommentVNode("", true)]);
|
|
2443
|
+
};
|
|
2444
|
+
}
|
|
2445
|
+
});
|
|
2446
|
+
//#endregion
|
|
2447
|
+
//#region \0plugin-vue:export-helper
|
|
2448
|
+
var _plugin_vue_export_helper_default = (sfc, props) => {
|
|
2449
|
+
const target = sfc.__vccOpts || sfc;
|
|
2450
|
+
for (const [key, val] of props) target[key] = val;
|
|
2451
|
+
return target;
|
|
2452
|
+
};
|
|
2453
|
+
//#endregion
|
|
2454
|
+
//#region src/vue/components/CollectionCustomView.vue
|
|
2455
|
+
var CollectionCustomView_default = /* @__PURE__ */ _plugin_vue_export_helper_default(CollectionCustomView_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-3ab71997"]]);
|
|
2456
|
+
//#endregion
|
|
2457
|
+
//#region src/vue/useCollectionRendering.ts
|
|
2458
|
+
function useCollectionRendering(collection, locale) {
|
|
2459
|
+
const refCache = ref({});
|
|
2460
|
+
const refRecordCache = ref({});
|
|
2461
|
+
const embedCache = ref({});
|
|
2462
|
+
function resetLinkedCaches() {
|
|
2463
|
+
refCache.value = {};
|
|
2464
|
+
refRecordCache.value = {};
|
|
2465
|
+
embedCache.value = {};
|
|
2466
|
+
}
|
|
2467
|
+
function uniqueRefTargets(schema) {
|
|
2468
|
+
const targets = /* @__PURE__ */ new Set();
|
|
2469
|
+
const walk = (fields) => {
|
|
2470
|
+
for (const field of Object.values(fields)) {
|
|
2471
|
+
if (field.type === "ref" && typeof field.to === "string" && field.to.length > 0) targets.add(field.to);
|
|
2472
|
+
if (field.type === "table" && field.of) walk(field.of);
|
|
2473
|
+
}
|
|
2474
|
+
};
|
|
2475
|
+
walk(schema.fields);
|
|
2476
|
+
return [...targets];
|
|
2477
|
+
}
|
|
2478
|
+
function uniqueEmbedTargets(schema) {
|
|
2479
|
+
const targets = /* @__PURE__ */ new Set();
|
|
2480
|
+
for (const field of Object.values(schema.fields)) if (field.type === "embed" && typeof field.to === "string" && field.to.length > 0) targets.add(field.to);
|
|
2481
|
+
return [...targets];
|
|
2482
|
+
}
|
|
2483
|
+
function buildRefDisplayMap(detail) {
|
|
2484
|
+
const { fields, primaryKey } = detail.collection.schema;
|
|
2485
|
+
const displayField = "name" in fields ? "name" : "title" in fields ? "title" : primaryKey;
|
|
2486
|
+
const map = {};
|
|
2487
|
+
for (const item of detail.items) {
|
|
2488
|
+
const slugRaw = item[primaryKey];
|
|
2489
|
+
if (typeof slugRaw !== "string" || slugRaw.length === 0) continue;
|
|
2490
|
+
const displayRaw = item[displayField];
|
|
2491
|
+
map[slugRaw] = typeof displayRaw === "string" && displayRaw.length > 0 ? displayRaw : slugRaw;
|
|
2492
|
+
}
|
|
2493
|
+
return map;
|
|
2494
|
+
}
|
|
2495
|
+
function buildRefRecordMap(detail) {
|
|
2496
|
+
const { schema } = detail.collection;
|
|
2497
|
+
const map = {};
|
|
2498
|
+
for (const item of detail.items) {
|
|
2499
|
+
const slugRaw = item[schema.primaryKey];
|
|
2500
|
+
if (typeof slugRaw === "string" && slugRaw.length > 0) map[slugRaw] = deriveAll(schema, item, {});
|
|
2501
|
+
}
|
|
2502
|
+
return map;
|
|
2503
|
+
}
|
|
2504
|
+
async function loadLinkedCollections(schema, expectedSlug) {
|
|
2505
|
+
const refTargets = new Set(uniqueRefTargets(schema));
|
|
2506
|
+
const embedTargets = new Set(uniqueEmbedTargets(schema));
|
|
2507
|
+
const allTargets = [...new Set([...refTargets, ...embedTargets])];
|
|
2508
|
+
if (allTargets.length === 0) return;
|
|
2509
|
+
const binding = collectionUi();
|
|
2510
|
+
const results = await Promise.all(allTargets.map(async (target) => {
|
|
2511
|
+
try {
|
|
2512
|
+
return {
|
|
2513
|
+
target,
|
|
2514
|
+
result: await binding.fetchCollectionDetail(target)
|
|
2515
|
+
};
|
|
2516
|
+
} catch {
|
|
2517
|
+
return {
|
|
2518
|
+
target,
|
|
2519
|
+
result: { ok: false }
|
|
2520
|
+
};
|
|
2521
|
+
}
|
|
2522
|
+
}));
|
|
2523
|
+
if (collection.value?.slug !== expectedSlug) return;
|
|
2524
|
+
const nextRef = {};
|
|
2525
|
+
const nextRefRecords = {};
|
|
2526
|
+
const nextEmbed = {};
|
|
2527
|
+
for (const { target, result } of results) {
|
|
2528
|
+
if (!result.ok) continue;
|
|
2529
|
+
if (refTargets.has(target)) {
|
|
2530
|
+
nextRef[target] = buildRefDisplayMap(result.data);
|
|
2531
|
+
nextRefRecords[target] = buildRefRecordMap(result.data);
|
|
2532
|
+
}
|
|
2533
|
+
if (embedTargets.has(target)) nextEmbed[target] = {
|
|
2534
|
+
schema: result.data.collection.schema,
|
|
2535
|
+
items: result.data.items
|
|
2536
|
+
};
|
|
2537
|
+
}
|
|
2538
|
+
refCache.value = nextRef;
|
|
2539
|
+
refRecordCache.value = nextRefRecords;
|
|
2540
|
+
embedCache.value = nextEmbed;
|
|
2541
|
+
}
|
|
2542
|
+
function refDisplay(targetSlug, itemSlug) {
|
|
2543
|
+
const map = refCache.value[targetSlug];
|
|
2544
|
+
return map && map[itemSlug] || itemSlug;
|
|
2545
|
+
}
|
|
2546
|
+
function refOptions(targetSlug) {
|
|
2547
|
+
const map = refCache.value[targetSlug];
|
|
2548
|
+
if (!map) return [];
|
|
2549
|
+
return Object.entries(map).map(([slug, display]) => ({
|
|
2550
|
+
slug,
|
|
2551
|
+
display
|
|
2552
|
+
})).sort((left, right) => left.display.localeCompare(right.display));
|
|
2553
|
+
}
|
|
2554
|
+
function resolveEmbed(field) {
|
|
2555
|
+
if (field.type !== "embed" || !field.to || !field.id) return {
|
|
2556
|
+
schema: null,
|
|
2557
|
+
item: null
|
|
2558
|
+
};
|
|
2559
|
+
const data = embedCache.value[field.to];
|
|
2560
|
+
if (!data) return {
|
|
2561
|
+
schema: null,
|
|
2562
|
+
item: null
|
|
2563
|
+
};
|
|
2564
|
+
const item = data.items.find((entry) => String(entry[data.schema.primaryKey] ?? "") === field.id) ?? null;
|
|
2565
|
+
return {
|
|
2566
|
+
schema: data.schema,
|
|
2567
|
+
item
|
|
2568
|
+
};
|
|
2569
|
+
}
|
|
2570
|
+
function embedValue(field, value, record) {
|
|
2571
|
+
if (field.type === "money") return formatMoney(value, resolveCurrency(field, record), locale.value);
|
|
2572
|
+
return detailText(value);
|
|
2573
|
+
}
|
|
2574
|
+
const embedViews = computed(() => {
|
|
2575
|
+
const out = {};
|
|
2576
|
+
if (!collection.value) return out;
|
|
2577
|
+
for (const [key, field] of Object.entries(collection.value.schema.fields)) {
|
|
2578
|
+
if (field.type !== "embed") continue;
|
|
2579
|
+
const { schema, item } = resolveEmbed(field);
|
|
2580
|
+
const rows = [];
|
|
2581
|
+
if (schema && item) for (const [subKey, subField] of Object.entries(schema.fields)) {
|
|
2582
|
+
const value = item[subKey];
|
|
2583
|
+
if (value === void 0 || value === null || value === "") continue;
|
|
2584
|
+
rows.push({
|
|
2585
|
+
key: subKey,
|
|
2586
|
+
label: subField.label,
|
|
2587
|
+
type: subField.type,
|
|
2588
|
+
value,
|
|
2589
|
+
display: embedValue(subField, value, item)
|
|
2590
|
+
});
|
|
2672
2591
|
}
|
|
2592
|
+
out[key] = {
|
|
2593
|
+
found: Boolean(item),
|
|
2594
|
+
rows,
|
|
2595
|
+
targetSlug: field.to ?? "",
|
|
2596
|
+
recordId: field.id ?? ""
|
|
2597
|
+
};
|
|
2673
2598
|
}
|
|
2674
|
-
|
|
2675
|
-
|
|
2676
|
-
|
|
2677
|
-
|
|
2678
|
-
|
|
2679
|
-
|
|
2680
|
-
|
|
2681
|
-
|
|
2682
|
-
sandbox: "allow-scripts allow-popups allow-popups-to-escape-sandbox",
|
|
2683
|
-
class: "w-full h-full border-0"
|
|
2684
|
-
}, null, 8, _hoisted_4$3)) : createCommentVNode("", true)]);
|
|
2685
|
-
};
|
|
2599
|
+
return out;
|
|
2600
|
+
});
|
|
2601
|
+
function resolveCurrency(field, record) {
|
|
2602
|
+
if (field.currencyField && record) {
|
|
2603
|
+
const code = record[field.currencyField];
|
|
2604
|
+
if (typeof code === "string" && code.trim().length > 0) return code;
|
|
2605
|
+
}
|
|
2606
|
+
return field.currency;
|
|
2686
2607
|
}
|
|
2687
|
-
|
|
2688
|
-
|
|
2689
|
-
|
|
2690
|
-
|
|
2691
|
-
|
|
2692
|
-
|
|
2693
|
-
|
|
2694
|
-
}
|
|
2608
|
+
function currencySymbol(currency) {
|
|
2609
|
+
const code = currency && currency.length > 0 ? currency : "USD";
|
|
2610
|
+
try {
|
|
2611
|
+
return new Intl.NumberFormat(locale.value, {
|
|
2612
|
+
style: "currency",
|
|
2613
|
+
currency: code
|
|
2614
|
+
}).formatToParts(0).find((entry) => entry.type === "currency")?.value ?? code;
|
|
2615
|
+
} catch {
|
|
2616
|
+
return code;
|
|
2617
|
+
}
|
|
2618
|
+
}
|
|
2619
|
+
function formatMoney(value, currency, displayLocale) {
|
|
2620
|
+
if (value === void 0 || value === "") return "—";
|
|
2621
|
+
const amount = typeof value === "number" ? value : Number(value);
|
|
2622
|
+
if (!Number.isFinite(amount)) return String(value);
|
|
2623
|
+
const currencyCode = currency && currency.length > 0 ? currency : "USD";
|
|
2624
|
+
try {
|
|
2625
|
+
return new Intl.NumberFormat(displayLocale, {
|
|
2626
|
+
style: "currency",
|
|
2627
|
+
currency: currencyCode
|
|
2628
|
+
}).format(amount);
|
|
2629
|
+
} catch {
|
|
2630
|
+
return String(amount);
|
|
2631
|
+
}
|
|
2632
|
+
}
|
|
2633
|
+
function formatCell(value, type) {
|
|
2634
|
+
if (value === void 0 || value === null || value === "") return "—";
|
|
2635
|
+
if (type === "markdown" && typeof value === "string") return value.length > 80 ? `${value.slice(0, 80)}…` : value;
|
|
2636
|
+
if (typeof value === "string" || typeof value === "number") return String(value);
|
|
2637
|
+
return JSON.stringify(value);
|
|
2638
|
+
}
|
|
2639
|
+
function isExternalUrl(value) {
|
|
2640
|
+
return typeof value === "string" && /^https?:\/\//i.test(value);
|
|
2641
|
+
}
|
|
2642
|
+
function artifactUrl(value) {
|
|
2643
|
+
return collectionUi().fileAssetUrl(value);
|
|
2644
|
+
}
|
|
2645
|
+
function fileRoutePath(value) {
|
|
2646
|
+
return collectionUi().fileRoutePath(value);
|
|
2647
|
+
}
|
|
2648
|
+
function detailText(value) {
|
|
2649
|
+
if (value === void 0 || value === null || value === "") return "—";
|
|
2650
|
+
return String(value);
|
|
2651
|
+
}
|
|
2652
|
+
function tableRows(value) {
|
|
2653
|
+
if (!Array.isArray(value)) return [];
|
|
2654
|
+
return value.filter((row) => Boolean(row) && typeof row === "object" && !Array.isArray(row));
|
|
2655
|
+
}
|
|
2656
|
+
function hasTableRows(value) {
|
|
2657
|
+
return tableRows(value).length > 0;
|
|
2658
|
+
}
|
|
2659
|
+
function formatSubCell(subField, value, record) {
|
|
2660
|
+
if (subField.type === "money") return formatMoney(value, resolveCurrency(subField, record), locale.value);
|
|
2661
|
+
if (subField.type === "ref" && subField.to && typeof value === "string" && value.length > 0) return refDisplay(subField.to, value);
|
|
2662
|
+
return formatCell(value, subField.type);
|
|
2663
|
+
}
|
|
2664
|
+
function inputTypeFor(type) {
|
|
2665
|
+
if (type === "email") return "email";
|
|
2666
|
+
if (type === "number") return "number";
|
|
2667
|
+
if (type === "money") return "number";
|
|
2668
|
+
if (type === "date") return "date";
|
|
2669
|
+
if (type === "datetime") return "datetime-local";
|
|
2670
|
+
return "text";
|
|
2671
|
+
}
|
|
2672
|
+
function evaluateDerivedAgainstItem(field, fieldKey, item) {
|
|
2673
|
+
if (!field.formula || !collection.value) return null;
|
|
2674
|
+
const result = deriveAll(collection.value.schema, item, refRecordCache.value)[fieldKey];
|
|
2675
|
+
return typeof result === "number" && Number.isFinite(result) ? result : null;
|
|
2676
|
+
}
|
|
2677
|
+
function derivedDisplay(field, computedValue, record) {
|
|
2678
|
+
if (computedValue === null || computedValue === void 0) return "—";
|
|
2679
|
+
if (field.display === "money") return formatMoney(computedValue, resolveCurrency(field, record), locale.value);
|
|
2680
|
+
return formatCell(computedValue, field.display ?? "number");
|
|
2681
|
+
}
|
|
2682
|
+
return {
|
|
2683
|
+
refCache,
|
|
2684
|
+
refRecordCache,
|
|
2685
|
+
embedCache,
|
|
2686
|
+
resetLinkedCaches,
|
|
2687
|
+
loadLinkedCollections,
|
|
2688
|
+
refDisplay,
|
|
2689
|
+
refOptions,
|
|
2690
|
+
embedViews,
|
|
2691
|
+
resolveCurrency,
|
|
2692
|
+
currencySymbol,
|
|
2693
|
+
formatMoney,
|
|
2694
|
+
formatCell,
|
|
2695
|
+
detailText,
|
|
2696
|
+
isExternalUrl,
|
|
2697
|
+
artifactUrl,
|
|
2698
|
+
fileRoutePath,
|
|
2699
|
+
tableRows,
|
|
2700
|
+
hasTableRows,
|
|
2701
|
+
formatSubCell,
|
|
2702
|
+
inputTypeFor,
|
|
2703
|
+
deriveAll,
|
|
2704
|
+
evaluateDerivedAgainstItem,
|
|
2705
|
+
derivedDisplay
|
|
2706
|
+
};
|
|
2707
|
+
}
|
|
2695
2708
|
//#endregion
|
|
2696
|
-
//#region src/vue/
|
|
2697
|
-
var
|
|
2709
|
+
//#region src/vue/collectionViewMode.ts
|
|
2710
|
+
var STORAGE_KEY = "collection_view_modes";
|
|
2711
|
+
var SORT_STORAGE_KEY = "collection_sorts";
|
|
2712
|
+
var BUILT_IN_MODES = [
|
|
2713
|
+
"table",
|
|
2714
|
+
"calendar",
|
|
2715
|
+
"kanban"
|
|
2716
|
+
];
|
|
2717
|
+
/** A persisted mode is valid if it's a known built-in OR any `custom:<id>`
|
|
2718
|
+
* key (the id is validated against the live schema at render time, so an
|
|
2719
|
+
* unknown custom id simply collapses to the table there). Takes `unknown`
|
|
2720
|
+
* and type-guards `string` first: a corrupted localStorage entry could hold a
|
|
2721
|
+
* number/object, and calling `.startsWith` on that would throw. */
|
|
2722
|
+
function isValidViewMode(value) {
|
|
2723
|
+
return typeof value === "string" && (BUILT_IN_MODES.includes(value) || value.startsWith("custom:"));
|
|
2724
|
+
}
|
|
2725
|
+
function readAll() {
|
|
2726
|
+
try {
|
|
2727
|
+
const raw = localStorage.getItem(STORAGE_KEY);
|
|
2728
|
+
if (!raw) return {};
|
|
2729
|
+
const parsed = JSON.parse(raw);
|
|
2730
|
+
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
|
|
2731
|
+
} catch {
|
|
2732
|
+
return {};
|
|
2733
|
+
}
|
|
2734
|
+
}
|
|
2735
|
+
function readCollectionViewMode(slug) {
|
|
2736
|
+
const stored = readAll()[slug];
|
|
2737
|
+
return isValidViewMode(stored) ? stored : null;
|
|
2738
|
+
}
|
|
2739
|
+
function writeCollectionViewMode(slug, view) {
|
|
2740
|
+
try {
|
|
2741
|
+
const all = readAll();
|
|
2742
|
+
all[slug] = view;
|
|
2743
|
+
localStorage.setItem(STORAGE_KEY, JSON.stringify(all));
|
|
2744
|
+
} catch {}
|
|
2745
|
+
}
|
|
2746
|
+
function isSortState(value) {
|
|
2747
|
+
if (!value || typeof value !== "object") return false;
|
|
2748
|
+
const rec = value;
|
|
2749
|
+
return typeof rec.field === "string" && (rec.direction === "asc" || rec.direction === "desc");
|
|
2750
|
+
}
|
|
2751
|
+
function readAllSorts() {
|
|
2752
|
+
try {
|
|
2753
|
+
const raw = localStorage.getItem(SORT_STORAGE_KEY);
|
|
2754
|
+
if (!raw) return {};
|
|
2755
|
+
const parsed = JSON.parse(raw);
|
|
2756
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return {};
|
|
2757
|
+
const out = {};
|
|
2758
|
+
for (const [slug, value] of Object.entries(parsed)) if (isSortState(value)) out[slug] = value;
|
|
2759
|
+
return out;
|
|
2760
|
+
} catch {
|
|
2761
|
+
return {};
|
|
2762
|
+
}
|
|
2763
|
+
}
|
|
2764
|
+
function readCollectionSort(slug) {
|
|
2765
|
+
return readAllSorts()[slug] ?? null;
|
|
2766
|
+
}
|
|
2767
|
+
/** Persist (or, when `sort` is null, clear) the slug's active column sort. */
|
|
2768
|
+
function writeCollectionSort(slug, sort) {
|
|
2769
|
+
try {
|
|
2770
|
+
const all = Object.fromEntries(Object.entries(readAllSorts()).filter(([key]) => key !== slug));
|
|
2771
|
+
if (sort) all[slug] = sort;
|
|
2772
|
+
localStorage.setItem(SORT_STORAGE_KEY, JSON.stringify(all));
|
|
2773
|
+
} catch {}
|
|
2774
|
+
}
|
|
2698
2775
|
//#endregion
|
|
2699
2776
|
//#region src/vue/components/CollectionView.vue?vue&type=script&setup=true&lang.ts
|
|
2700
|
-
var _hoisted_1$
|
|
2701
|
-
var _hoisted_2$
|
|
2702
|
-
var _hoisted_3$
|
|
2703
|
-
var _hoisted_4$
|
|
2777
|
+
var _hoisted_1$4 = { class: "h-full flex flex-col bg-slate-50/30" };
|
|
2778
|
+
var _hoisted_2$3 = { class: "flex items-center gap-3 px-6 py-2 border-b border-slate-200 bg-white" };
|
|
2779
|
+
var _hoisted_3$3 = ["title", "aria-label"];
|
|
2780
|
+
var _hoisted_4$3 = {
|
|
2704
2781
|
key: 1,
|
|
2705
2782
|
class: "h-9 w-9 flex items-center justify-center rounded-xl bg-indigo-50 text-indigo-600 border border-indigo-100"
|
|
2706
2783
|
};
|
|
2707
|
-
var _hoisted_5$
|
|
2784
|
+
var _hoisted_5$3 = { class: "material-symbols-outlined text-xl" };
|
|
2708
2785
|
var _hoisted_6$2 = { class: "flex-1 min-w-0" };
|
|
2709
2786
|
var _hoisted_7$2 = { class: "text-base font-bold text-slate-800 truncate" };
|
|
2710
2787
|
var _hoisted_8$2 = {
|
|
@@ -2851,48 +2928,60 @@ var _hoisted_65 = {
|
|
|
2851
2928
|
class: "block truncate"
|
|
2852
2929
|
};
|
|
2853
2930
|
var _hoisted_66 = [
|
|
2931
|
+
"href",
|
|
2932
|
+
"tabindex",
|
|
2933
|
+
"data-testid",
|
|
2934
|
+
"onClick",
|
|
2935
|
+
"onKeydown"
|
|
2936
|
+
];
|
|
2937
|
+
var _hoisted_67 = [
|
|
2854
2938
|
"value",
|
|
2855
2939
|
"disabled",
|
|
2856
2940
|
"data-testid",
|
|
2857
2941
|
"aria-label",
|
|
2858
2942
|
"onChange"
|
|
2859
2943
|
];
|
|
2860
|
-
var
|
|
2944
|
+
var _hoisted_68 = {
|
|
2861
2945
|
key: 0,
|
|
2862
2946
|
value: ""
|
|
2863
2947
|
};
|
|
2864
|
-
var
|
|
2865
|
-
var
|
|
2948
|
+
var _hoisted_69 = ["value"];
|
|
2949
|
+
var _hoisted_70 = {
|
|
2866
2950
|
key: 4,
|
|
2867
2951
|
class: "block truncate tabular-nums font-semibold text-slate-900"
|
|
2868
2952
|
};
|
|
2869
|
-
var
|
|
2953
|
+
var _hoisted_71 = {
|
|
2870
2954
|
key: 5,
|
|
2871
2955
|
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"
|
|
2872
2956
|
};
|
|
2873
|
-
var
|
|
2957
|
+
var _hoisted_72 = {
|
|
2874
2958
|
key: 6,
|
|
2875
2959
|
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"
|
|
2876
2960
|
};
|
|
2877
|
-
var _hoisted_72 = ["href", "data-testid"];
|
|
2878
2961
|
var _hoisted_73 = ["href", "data-testid"];
|
|
2879
|
-
var _hoisted_74 =
|
|
2962
|
+
var _hoisted_74 = ["href", "data-testid"];
|
|
2963
|
+
var _hoisted_75 = [
|
|
2964
|
+
"href",
|
|
2965
|
+
"data-testid",
|
|
2966
|
+
"onClick"
|
|
2967
|
+
];
|
|
2968
|
+
var _hoisted_76 = {
|
|
2880
2969
|
key: 10,
|
|
2881
2970
|
class: "block truncate text-slate-600"
|
|
2882
2971
|
};
|
|
2883
|
-
var
|
|
2884
|
-
var
|
|
2885
|
-
var
|
|
2886
|
-
var
|
|
2972
|
+
var _hoisted_77 = { class: "bg-white rounded-2xl shadow-2xl w-full max-w-xl flex flex-col border border-slate-200 overflow-hidden" };
|
|
2973
|
+
var _hoisted_78 = { class: "px-6 py-4 border-b border-slate-100 flex items-center gap-3 bg-slate-50/50" };
|
|
2974
|
+
var _hoisted_79 = { class: "flex-1" };
|
|
2975
|
+
var _hoisted_80 = {
|
|
2887
2976
|
id: "collections-chat-title",
|
|
2888
2977
|
class: "text-sm font-bold text-slate-800 uppercase tracking-wide"
|
|
2889
2978
|
};
|
|
2890
|
-
var
|
|
2891
|
-
var
|
|
2892
|
-
var
|
|
2893
|
-
var
|
|
2894
|
-
var
|
|
2895
|
-
var
|
|
2979
|
+
var _hoisted_81 = { class: "text-xs text-slate-400 font-semibold" };
|
|
2980
|
+
var _hoisted_82 = ["aria-label"];
|
|
2981
|
+
var _hoisted_83 = { class: "px-6 py-5" };
|
|
2982
|
+
var _hoisted_84 = ["placeholder", "onKeydown"];
|
|
2983
|
+
var _hoisted_85 = { class: "px-6 py-3.5 border-t border-slate-100 flex items-center justify-end gap-2 bg-slate-50/50" };
|
|
2984
|
+
var _hoisted_86 = ["disabled"];
|
|
2896
2985
|
//#endregion
|
|
2897
2986
|
//#region src/vue/components/CollectionView.vue
|
|
2898
2987
|
var CollectionView_default = /* @__PURE__ */ defineComponent({
|
|
@@ -3859,9 +3948,8 @@ var CollectionView_default = /* @__PURE__ */ defineComponent({
|
|
|
3859
3948
|
openDay.value = viewing.value ? dayOfItem(viewing.value) : null;
|
|
3860
3949
|
});
|
|
3861
3950
|
return (_ctx, _cache) => {
|
|
3862
|
-
|
|
3863
|
-
|
|
3864
|
-
createElementVNode("header", _hoisted_2$2, [
|
|
3951
|
+
return openBlock(), createElementBlock("div", _hoisted_1$4, [
|
|
3952
|
+
createElementVNode("header", _hoisted_2$3, [
|
|
3865
3953
|
!embedded.value ? (openBlock(), createElementBlock("button", {
|
|
3866
3954
|
key: 0,
|
|
3867
3955
|
type: "button",
|
|
@@ -3870,8 +3958,8 @@ var CollectionView_default = /* @__PURE__ */ defineComponent({
|
|
|
3870
3958
|
"aria-label": unref(t)("collectionsView.backToIndex"),
|
|
3871
3959
|
"data-testid": "collections-back",
|
|
3872
3960
|
onClick: goBack
|
|
3873
|
-
}, [..._cache[
|
|
3874
|
-
collection.value ? (openBlock(), createElementBlock("div", _hoisted_4$
|
|
3961
|
+
}, [..._cache[23] || (_cache[23] = [createElementVNode("span", { class: "material-icons text-lg" }, "arrow_back", -1)])], 8, _hoisted_3$3)) : createCommentVNode("", true),
|
|
3962
|
+
collection.value ? (openBlock(), createElementBlock("div", _hoisted_4$3, [createElementVNode("span", _hoisted_5$3, toDisplayString(collection.value.icon), 1)])) : createCommentVNode("", true),
|
|
3875
3963
|
createElementVNode("div", _hoisted_6$2, [createElementVNode("h1", _hoisted_7$2, toDisplayString(collection.value?.title ?? unref(t)("collectionsView.title")), 1), collection.value ? (openBlock(), createElementBlock("span", _hoisted_8$2, toDisplayString(collection.value.slug), 1)) : createCommentVNode("", true)]),
|
|
3876
3964
|
collection.value && !embedded.value ? (openBlock(), createBlock(resolveDynamicComponent(unref(pinToggle)), {
|
|
3877
3965
|
key: 2,
|
|
@@ -3899,7 +3987,7 @@ var CollectionView_default = /* @__PURE__ */ defineComponent({
|
|
|
3899
3987
|
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",
|
|
3900
3988
|
"data-testid": "collections-chat",
|
|
3901
3989
|
onClick: openChat
|
|
3902
|
-
}, [_cache[
|
|
3990
|
+
}, [_cache[24] || (_cache[24] = createElementVNode("span", { class: "material-icons text-sm" }, "forum", -1)), createElementVNode("span", null, toDisplayString(unref(t)("collectionsView.chat")), 1)])) : createCommentVNode("", true),
|
|
3903
3991
|
(openBlock(true), createElementBlock(Fragment, null, renderList(collectionActions.value, (action) => {
|
|
3904
3992
|
return openBlock(), createElementBlock("button", {
|
|
3905
3993
|
key: action.id,
|
|
@@ -3916,7 +4004,7 @@ var CollectionView_default = /* @__PURE__ */ defineComponent({
|
|
|
3916
4004
|
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",
|
|
3917
4005
|
"data-testid": "collections-add-item",
|
|
3918
4006
|
onClick: openCreate
|
|
3919
|
-
}, [_cache[
|
|
4007
|
+
}, [_cache[25] || (_cache[25] = createElementVNode("span", { class: "material-icons text-sm" }, "add", -1)), createElementVNode("span", null, toDisplayString(unref(t)("common.add")), 1)])) : createCommentVNode("", true),
|
|
3920
4008
|
canDeleteCollection.value && !embedded.value ? (openBlock(), createElementBlock("button", {
|
|
3921
4009
|
key: 6,
|
|
3922
4010
|
type: "button",
|
|
@@ -3925,7 +4013,7 @@ var CollectionView_default = /* @__PURE__ */ defineComponent({
|
|
|
3925
4013
|
"aria-label": unref(t)("collectionsView.deleteCollection"),
|
|
3926
4014
|
"data-testid": "collections-delete",
|
|
3927
4015
|
onClick: confirmCollectionDelete
|
|
3928
|
-
}, [..._cache[
|
|
4016
|
+
}, [..._cache[26] || (_cache[26] = [createElementVNode("span", { class: "material-icons text-sm" }, "delete_forever", -1)])], 8, _hoisted_13$2)) : createCommentVNode("", true),
|
|
3929
4017
|
canDeleteFeed.value && !embedded.value ? (openBlock(), createElementBlock("button", {
|
|
3930
4018
|
key: 7,
|
|
3931
4019
|
type: "button",
|
|
@@ -3934,10 +4022,10 @@ var CollectionView_default = /* @__PURE__ */ defineComponent({
|
|
|
3934
4022
|
"aria-label": unref(t)("collectionsView.deleteFeed"),
|
|
3935
4023
|
"data-testid": "feeds-delete",
|
|
3936
4024
|
onClick: confirmFeedDelete
|
|
3937
|
-
}, [..._cache[
|
|
4025
|
+
}, [..._cache[27] || (_cache[27] = [createElementVNode("span", { class: "material-icons text-sm" }, "delete_forever", -1)])], 8, _hoisted_14$2)) : createCommentVNode("", true)
|
|
3938
4026
|
]),
|
|
3939
4027
|
collection.value && (items.value.length > 0 || hasCalendar.value || hasKanban.value || hasCustomViews.value || canAddCustomView.value) ? (openBlock(), createElementBlock("div", _hoisted_15$2, [items.value.length > 0 ? (openBlock(), createElementBlock("div", _hoisted_16$1, [
|
|
3940
|
-
_cache[
|
|
4028
|
+
_cache[29] || (_cache[29] = createElementVNode("span", { class: "absolute inset-y-0 left-0 flex items-center pl-3 text-slate-400 pointer-events-none" }, [createElementVNode("span", { class: "material-icons text-lg" }, "search")], -1)),
|
|
3941
4029
|
withDirectives(createElementVNode("input", {
|
|
3942
4030
|
"onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => searchQuery.value = $event),
|
|
3943
4031
|
type: "text",
|
|
@@ -3951,7 +4039,7 @@ var CollectionView_default = /* @__PURE__ */ defineComponent({
|
|
|
3951
4039
|
"aria-label": unref(t)("collectionsView.clearSearch"),
|
|
3952
4040
|
class: "absolute inset-y-0 right-0 flex items-center pr-2.5 text-slate-400 hover:text-slate-600",
|
|
3953
4041
|
onClick: _cache[1] || (_cache[1] = ($event) => searchQuery.value = "")
|
|
3954
|
-
}, [..._cache[
|
|
4042
|
+
}, [..._cache[28] || (_cache[28] = [createElementVNode("span", { class: "material-icons text-sm" }, "close", -1)])], 8, _hoisted_18$1)) : createCommentVNode("", true)
|
|
3955
4043
|
])) : createCommentVNode("", true), createElementVNode("div", _hoisted_19$1, [
|
|
3956
4044
|
hasCalendar.value || hasKanban.value || hasCustomViews.value || canAddCustomView.value ? (openBlock(), createElementBlock("div", {
|
|
3957
4045
|
key: 0,
|
|
@@ -3965,7 +4053,7 @@ var CollectionView_default = /* @__PURE__ */ defineComponent({
|
|
|
3965
4053
|
"aria-pressed": activeView.value === "table",
|
|
3966
4054
|
"data-testid": "collection-view-toggle-table",
|
|
3967
4055
|
onClick: _cache[2] || (_cache[2] = ($event) => setView("table"))
|
|
3968
|
-
}, [_cache[
|
|
4056
|
+
}, [_cache[30] || (_cache[30] = createElementVNode("span", { class: "material-icons text-sm" }, "table_rows", -1)), createElementVNode("span", null, toDisplayString(unref(t)("collectionsView.viewTable")), 1)], 10, _hoisted_21$1),
|
|
3969
4057
|
hasCalendar.value ? (openBlock(), createElementBlock("button", {
|
|
3970
4058
|
key: 0,
|
|
3971
4059
|
type: "button",
|
|
@@ -3973,7 +4061,7 @@ var CollectionView_default = /* @__PURE__ */ defineComponent({
|
|
|
3973
4061
|
"aria-pressed": activeView.value === "calendar",
|
|
3974
4062
|
"data-testid": "collection-view-toggle-calendar",
|
|
3975
4063
|
onClick: _cache[3] || (_cache[3] = ($event) => setView("calendar"))
|
|
3976
|
-
}, [_cache[
|
|
4064
|
+
}, [_cache[31] || (_cache[31] = createElementVNode("span", { class: "material-icons text-sm" }, "calendar_month", -1)), createElementVNode("span", null, toDisplayString(unref(t)("collectionsView.viewCalendar")), 1)], 10, _hoisted_22$1)) : createCommentVNode("", true),
|
|
3977
4065
|
hasKanban.value ? (openBlock(), createElementBlock("button", {
|
|
3978
4066
|
key: 1,
|
|
3979
4067
|
type: "button",
|
|
@@ -3981,7 +4069,7 @@ var CollectionView_default = /* @__PURE__ */ defineComponent({
|
|
|
3981
4069
|
"aria-pressed": activeView.value === "kanban",
|
|
3982
4070
|
"data-testid": "collection-view-toggle-kanban",
|
|
3983
4071
|
onClick: _cache[4] || (_cache[4] = ($event) => setView("kanban"))
|
|
3984
|
-
}, [_cache[
|
|
4072
|
+
}, [_cache[32] || (_cache[32] = createElementVNode("span", { class: "material-icons text-sm" }, "view_kanban", -1)), createElementVNode("span", null, toDisplayString(unref(t)("collectionsView.viewKanban")), 1)], 10, _hoisted_23$1)) : createCommentVNode("", true),
|
|
3985
4073
|
(openBlock(true), createElementBlock(Fragment, null, renderList(customViews.value, (cv) => {
|
|
3986
4074
|
return openBlock(), createElementBlock("button", {
|
|
3987
4075
|
key: cv.id,
|
|
@@ -4000,7 +4088,7 @@ var CollectionView_default = /* @__PURE__ */ defineComponent({
|
|
|
4000
4088
|
"aria-label": unref(t)("collectionsView.addView"),
|
|
4001
4089
|
"data-testid": "collection-view-add",
|
|
4002
4090
|
onClick: addCustomView
|
|
4003
|
-
}, [..._cache[
|
|
4091
|
+
}, [..._cache[33] || (_cache[33] = [createElementVNode("span", { class: "material-icons text-sm" }, "add", -1)])], 8, _hoisted_26)) : createCommentVNode("", true),
|
|
4004
4092
|
canConfigureViews.value ? (openBlock(), createElementBlock("button", {
|
|
4005
4093
|
key: 3,
|
|
4006
4094
|
type: "button",
|
|
@@ -4009,7 +4097,7 @@ var CollectionView_default = /* @__PURE__ */ defineComponent({
|
|
|
4009
4097
|
"aria-label": unref(t)("collectionsView.config.open"),
|
|
4010
4098
|
"data-testid": "collection-config-open",
|
|
4011
4099
|
onClick: _cache[5] || (_cache[5] = ($event) => configOpen.value = true)
|
|
4012
|
-
}, [..._cache[
|
|
4100
|
+
}, [..._cache[34] || (_cache[34] = [createElementVNode("span", { class: "material-icons text-sm" }, "settings", -1)])], 8, _hoisted_27)) : createCommentVNode("", true)
|
|
4013
4101
|
], 8, _hoisted_20$1)) : createCommentVNode("", true),
|
|
4014
4102
|
calendarActive.value && dateFields.value.length > 1 ? (openBlock(), createElementBlock("select", {
|
|
4015
4103
|
key: 1,
|
|
@@ -4043,16 +4131,16 @@ var CollectionView_default = /* @__PURE__ */ defineComponent({
|
|
|
4043
4131
|
})), 1)) : createCommentVNode("", true)
|
|
4044
4132
|
])])) : createCommentVNode("", true),
|
|
4045
4133
|
collection.value && dataIssues.value.length > 0 ? (openBlock(), createElementBlock("div", _hoisted_33, [
|
|
4046
|
-
_cache[
|
|
4134
|
+
_cache[36] || (_cache[36] = createElementVNode("span", { class: "material-icons text-amber-600" }, "warning", -1)),
|
|
4047
4135
|
createElementVNode("span", _hoisted_34, toDisplayString(unref(t)("collectionsView.dataIssuesDetected", { count: dataIssues.value.length })), 1),
|
|
4048
4136
|
createElementVNode("button", {
|
|
4049
4137
|
type: "button",
|
|
4050
4138
|
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",
|
|
4051
4139
|
"data-testid": "collections-repair",
|
|
4052
4140
|
onClick: repairCollection
|
|
4053
|
-
}, [_cache[
|
|
4141
|
+
}, [_cache[35] || (_cache[35] = createElementVNode("span", { class: "material-icons text-sm" }, "build", -1)), createElementVNode("span", null, toDisplayString(unref(t)("collectionsView.repair")), 1)])
|
|
4054
4142
|
])) : createCommentVNode("", true),
|
|
4055
|
-
createElementVNode("div", _hoisted_35, [loading.value ? (openBlock(), createElementBlock("div", _hoisted_36, [_cache[
|
|
4143
|
+
createElementVNode("div", _hoisted_35, [loading.value ? (openBlock(), createElementBlock("div", _hoisted_36, [_cache[37] || (_cache[37] = createElementVNode("div", { class: "h-8 w-8 border-2 border-indigo-600/20 border-t-indigo-600 rounded-full animate-spin" }, null, -1)), createElementVNode("span", null, toDisplayString(unref(t)("common.loading")), 1)])) : loadError.value ? (openBlock(), createElementBlock("div", _hoisted_37, [_cache[38] || (_cache[38] = createElementVNode("span", { class: "material-icons text-red-600" }, "error", -1)), createElementVNode("span", null, toDisplayString(loadError.value === "not-found" ? unref(t)("collectionsView.notFound") : `${unref(t)("collectionsView.loadFailed")}: ${loadError.value}`), 1)])) : !collection.value ? (openBlock(), createElementBlock("div", _hoisted_38)) : calendarActive.value ? (openBlock(), createElementBlock("div", _hoisted_39, [createVNode(CollectionCalendarView_default, {
|
|
4056
4144
|
schema: collection.value.schema,
|
|
4057
4145
|
items: filteredItems.value,
|
|
4058
4146
|
"anchor-field": calendarAnchorField.value,
|
|
@@ -4137,14 +4225,14 @@ var CollectionView_default = /* @__PURE__ */ defineComponent({
|
|
|
4137
4225
|
"can-create",
|
|
4138
4226
|
"show-detail"
|
|
4139
4227
|
])) : createCommentVNode("", true)])) : kanbanActive.value ? (openBlock(), createElementBlock("div", _hoisted_40, [inlineError.value ? (openBlock(), createElementBlock("div", _hoisted_41, [
|
|
4140
|
-
_cache[
|
|
4228
|
+
_cache[40] || (_cache[40] = createElementVNode("span", { class: "material-icons text-red-600" }, "error", -1)),
|
|
4141
4229
|
createElementVNode("span", _hoisted_42, toDisplayString(unref(t)("collectionsView.inlineSaveFailed", { error: inlineError.value })), 1),
|
|
4142
4230
|
createElementVNode("button", {
|
|
4143
4231
|
type: "button",
|
|
4144
4232
|
class: "h-8 w-8 flex items-center justify-center rounded text-red-600 hover:bg-red-100",
|
|
4145
4233
|
"aria-label": unref(t)("common.close"),
|
|
4146
4234
|
onClick: _cache[10] || (_cache[10] = ($event) => inlineError.value = null)
|
|
4147
|
-
}, [..._cache[
|
|
4235
|
+
}, [..._cache[39] || (_cache[39] = [createElementVNode("span", { class: "material-icons text-base" }, "close", -1)])], 8, _hoisted_43)
|
|
4148
4236
|
])) : createCommentVNode("", true), createElementVNode("div", _hoisted_44, [createVNode(CollectionKanbanView_default, {
|
|
4149
4237
|
schema: collection.value.schema,
|
|
4150
4238
|
items: filteredItems.value,
|
|
@@ -4162,8 +4250,8 @@ var CollectionView_default = /* @__PURE__ */ defineComponent({
|
|
|
4162
4250
|
])])])) : activeCustomView.value ? (openBlock(), createElementBlock("div", _hoisted_45, [createVNode(CollectionCustomView_default, {
|
|
4163
4251
|
slug: collection.value.slug,
|
|
4164
4252
|
view: activeCustomView.value
|
|
4165
|
-
}, null, 8, ["slug", "view"])])) : items.value.length === 0 && editing.value?.mode !== "create" ? (openBlock(), createElementBlock("div", _hoisted_46, [_cache[
|
|
4166
|
-
_cache[
|
|
4253
|
+
}, null, 8, ["slug", "view"])])) : items.value.length === 0 && editing.value?.mode !== "create" ? (openBlock(), createElementBlock("div", _hoisted_46, [_cache[41] || (_cache[41] = createElementVNode("span", { class: "material-icons text-4xl text-slate-300" }, "folder_open", -1)), createElementVNode("p", _hoisted_47, toDisplayString(unref(t)("collectionsView.itemsEmpty")), 1)])) : filteredItems.value.length === 0 && editing.value?.mode !== "create" ? (openBlock(), createElementBlock("div", _hoisted_48, [
|
|
4254
|
+
_cache[42] || (_cache[42] = createElementVNode("span", { class: "material-icons text-4xl text-slate-300" }, "search_off", -1)),
|
|
4167
4255
|
createElementVNode("p", _hoisted_49, toDisplayString(unref(t)("collectionsView.noMatchingItems")), 1),
|
|
4168
4256
|
createElementVNode("button", {
|
|
4169
4257
|
type: "button",
|
|
@@ -4171,14 +4259,14 @@ var CollectionView_default = /* @__PURE__ */ defineComponent({
|
|
|
4171
4259
|
onClick: _cache[11] || (_cache[11] = ($event) => searchQuery.value = "")
|
|
4172
4260
|
}, toDisplayString(unref(t)("collectionsView.clearSearch")), 1)
|
|
4173
4261
|
])) : (openBlock(), createElementBlock("div", _hoisted_50, [inlineError.value ? (openBlock(), createElementBlock("div", _hoisted_51, [
|
|
4174
|
-
_cache[
|
|
4262
|
+
_cache[44] || (_cache[44] = createElementVNode("span", { class: "material-icons text-red-600" }, "error", -1)),
|
|
4175
4263
|
createElementVNode("span", _hoisted_52, toDisplayString(unref(t)("collectionsView.inlineSaveFailed", { error: inlineError.value })), 1),
|
|
4176
4264
|
createElementVNode("button", {
|
|
4177
4265
|
type: "button",
|
|
4178
4266
|
class: "h-8 w-8 flex items-center justify-center rounded text-red-600 hover:bg-red-100",
|
|
4179
4267
|
"aria-label": unref(t)("common.close"),
|
|
4180
4268
|
onClick: _cache[12] || (_cache[12] = ($event) => inlineError.value = null)
|
|
4181
|
-
}, [..._cache[
|
|
4269
|
+
}, [..._cache[43] || (_cache[43] = [createElementVNode("span", { class: "material-icons text-base" }, "close", -1)])], 8, _hoisted_53)
|
|
4182
4270
|
])) : createCommentVNode("", true), createElementVNode("table", _hoisted_54, [createElementVNode("thead", null, [createElementVNode("tr", _hoisted_55, [(openBlock(true), createElementBlock(Fragment, null, renderList(listColumnFields.value, ([key, field]) => {
|
|
4183
4271
|
return openBlock(), createElementBlock("th", {
|
|
4184
4272
|
key,
|
|
@@ -4231,57 +4319,51 @@ var CollectionView_default = /* @__PURE__ */ defineComponent({
|
|
|
4231
4319
|
"aria-label": field.label,
|
|
4232
4320
|
onClick: _cache[15] || (_cache[15] = withModifiers(() => {}, ["stop"])),
|
|
4233
4321
|
onChange: ($event) => commitInlineEdit(item, String(key), field, $event.target.checked)
|
|
4234
|
-
}, null, 40, _hoisted_64)) : field.type === "ref" && field.to && typeof item[key] === "string" && item[key] ? (openBlock(), createElementBlock("span", _hoisted_65, [
|
|
4235
|
-
|
|
4236
|
-
|
|
4237
|
-
|
|
4238
|
-
},
|
|
4322
|
+
}, null, 40, _hoisted_64)) : field.type === "ref" && field.to && typeof item[key] === "string" && item[key] ? (openBlock(), createElementBlock("span", _hoisted_65, [createElementVNode("a", {
|
|
4323
|
+
href: unref(cui).recordHref?.(field.to, String(item[key])),
|
|
4324
|
+
tabindex: unref(cui).recordHref?.(field.to, String(item[key])) ? void 0 : 0,
|
|
4325
|
+
role: "link",
|
|
4239
4326
|
class: "text-indigo-600 hover:text-indigo-800 hover:underline font-semibold",
|
|
4240
4327
|
"data-testid": `collections-ref-link-${key}-${item[key]}`,
|
|
4241
|
-
onClick:
|
|
4242
|
-
|
|
4243
|
-
|
|
4244
|
-
_: 2
|
|
4245
|
-
}, 1032, ["to", "data-testid"])])) : field.type === "enum" && Array.isArray(field.values) && field.values.length > 0 ? (openBlock(), createElementBlock("select", {
|
|
4328
|
+
onClick: ($event) => unref(activateRefLink)($event, field.to, String(item[key]), true),
|
|
4329
|
+
onKeydown: [withKeys(($event) => unref(activateRefLink)($event, field.to, String(item[key]), true), ["enter"]), withKeys(($event) => unref(activateRefLink)($event, field.to, String(item[key]), true), ["space"])]
|
|
4330
|
+
}, toDisplayString(unref(refDisplay)(field.to, String(item[key]))), 41, _hoisted_66)])) : field.type === "enum" && Array.isArray(field.values) && field.values.length > 0 ? (openBlock(), createElementBlock("select", {
|
|
4246
4331
|
key: 3,
|
|
4247
4332
|
value: item[key] == null ? "" : String(item[key]),
|
|
4248
4333
|
disabled: isRowInlineSaving(item),
|
|
4249
4334
|
class: normalizeClass(["rounded-lg border px-2 py-0.5 text-[11px] font-semibold focus:border-indigo-500 focus:ring-2 focus:ring-indigo-500/20 focus:outline-none cursor-pointer disabled:opacity-50 disabled:cursor-not-allowed", enumControlClass(String(key), item[key])]),
|
|
4250
4335
|
"data-testid": `collections-inline-enum-${key}-${item[collection.value.schema.primaryKey]}`,
|
|
4251
4336
|
"aria-label": field.label,
|
|
4252
|
-
onClick: _cache[
|
|
4337
|
+
onClick: _cache[16] || (_cache[16] = withModifiers(() => {}, ["stop"])),
|
|
4253
4338
|
onChange: ($event) => commitInlineEdit(item, String(key), field, $event.target.value)
|
|
4254
|
-
}, [showEnumPlaceholder(item, String(key)) ? (openBlock(), createElementBlock("option",
|
|
4339
|
+
}, [showEnumPlaceholder(item, String(key)) ? (openBlock(), createElementBlock("option", _hoisted_68, toDisplayString(unref(t)("collectionsView.selectPlaceholder")), 1)) : createCommentVNode("", true), (openBlock(true), createElementBlock(Fragment, null, renderList(field.values, (value) => {
|
|
4255
4340
|
return openBlock(), createElementBlock("option", {
|
|
4256
4341
|
key: value,
|
|
4257
4342
|
value
|
|
4258
|
-
}, toDisplayString(value), 9,
|
|
4259
|
-
}), 128))], 42,
|
|
4343
|
+
}, toDisplayString(value), 9, _hoisted_69);
|
|
4344
|
+
}), 128))], 42, _hoisted_67)) : field.type === "money" ? (openBlock(), createElementBlock("span", _hoisted_70, toDisplayString(unref(formatMoney)(item[key], unref(resolveCurrency)(field, item), unref(locale))), 1)) : field.type === "table" ? (openBlock(), createElementBlock("span", _hoisted_71, [_cache[45] || (_cache[45] = createElementVNode("span", { class: "material-icons text-[11px]" }, "list", -1)), createElementVNode("span", null, toDisplayString(tableSummary(item[key])), 1)])) : field.type === "derived" ? (openBlock(), createElementBlock("span", _hoisted_72, toDisplayString(unref(derivedDisplay)(field, unref(evaluateDerivedAgainstItem)(field, String(key), item), item)), 1)) : field.type !== "file" && unref(isExternalUrl)(item[key]) ? (openBlock(), createElementBlock("a", {
|
|
4260
4345
|
key: 7,
|
|
4261
4346
|
href: String(item[key]),
|
|
4262
4347
|
target: "_blank",
|
|
4263
4348
|
rel: "noopener noreferrer",
|
|
4264
4349
|
class: "block truncate text-blue-600 hover:text-blue-800 hover:underline font-semibold",
|
|
4265
4350
|
"data-testid": `collections-url-link-${key}-${item[collection.value.schema.primaryKey]}`,
|
|
4266
|
-
onClick: _cache[
|
|
4267
|
-
}, toDisplayString(String(item[key])), 9,
|
|
4351
|
+
onClick: _cache[17] || (_cache[17] = withModifiers(() => {}, ["stop"]))
|
|
4352
|
+
}, toDisplayString(String(item[key])), 9, _hoisted_73)) : field.type === "file" && unref(artifactUrl)(item[key]) ? (openBlock(), createElementBlock("a", {
|
|
4268
4353
|
key: 8,
|
|
4269
4354
|
href: unref(artifactUrl)(item[key]) ?? void 0,
|
|
4270
4355
|
target: "_blank",
|
|
4271
4356
|
rel: "noopener noreferrer",
|
|
4272
4357
|
class: "block truncate text-blue-600 hover:text-blue-800 hover:underline font-semibold",
|
|
4273
4358
|
"data-testid": `collections-file-link-${key}-${item[collection.value.schema.primaryKey]}`,
|
|
4274
|
-
onClick: _cache[
|
|
4275
|
-
}, toDisplayString(String(item[key])), 9,
|
|
4359
|
+
onClick: _cache[18] || (_cache[18] = withModifiers(() => {}, ["stop"]))
|
|
4360
|
+
}, toDisplayString(String(item[key])), 9, _hoisted_74)) : field.type === "file" && unref(fileRoutePath)(item[key]) ? (openBlock(), createElementBlock("a", {
|
|
4276
4361
|
key: 9,
|
|
4277
|
-
|
|
4362
|
+
href: unref(fileRoutePath)(item[key]) ?? void 0,
|
|
4278
4363
|
class: "block truncate text-blue-600 hover:text-blue-800 hover:underline font-semibold",
|
|
4279
4364
|
"data-testid": `collections-file-link-${key}-${item[collection.value.schema.primaryKey]}`,
|
|
4280
|
-
onClick:
|
|
4281
|
-
},
|
|
4282
|
-
default: withCtx(() => [createTextVNode(toDisplayString(String(item[key])), 1)]),
|
|
4283
|
-
_: 2
|
|
4284
|
-
}, 1032, ["to", "data-testid"])) : (openBlock(), createElementBlock("span", _hoisted_74, toDisplayString(unref(formatCell)(item[key], field.type)), 1))], 64)) : createCommentVNode("", true)]);
|
|
4365
|
+
onClick: ($event) => unref(activatePathLink)($event, unref(fileRoutePath)(item[key]) ?? "", true)
|
|
4366
|
+
}, toDisplayString(String(item[key])), 9, _hoisted_75)) : (openBlock(), createElementBlock("span", _hoisted_76, toDisplayString(unref(formatCell)(item[key], field.type)), 1))], 64)) : createCommentVNode("", true)]);
|
|
4285
4367
|
}), 128))], 42, _hoisted_62);
|
|
4286
4368
|
}), 128))])])]))]),
|
|
4287
4369
|
collection.value && (viewing.value || editing.value) && !(calendarActive.value && openDay.value) ? (openBlock(), createBlock(CollectionRecordModal_default, {
|
|
@@ -4290,7 +4372,7 @@ var CollectionView_default = /* @__PURE__ */ defineComponent({
|
|
|
4290
4372
|
}, {
|
|
4291
4373
|
default: withCtx(() => [createVNode(CollectionRecordPanel_default, {
|
|
4292
4374
|
editing: editing.value,
|
|
4293
|
-
"onUpdate:editing": _cache[
|
|
4375
|
+
"onUpdate:editing": _cache[19] || (_cache[19] = ($event) => editing.value = $event),
|
|
4294
4376
|
collection: collection.value,
|
|
4295
4377
|
viewing: viewing.value,
|
|
4296
4378
|
saving: saving.value,
|
|
@@ -4308,7 +4390,7 @@ var CollectionView_default = /* @__PURE__ */ defineComponent({
|
|
|
4308
4390
|
onCancel: cancelEditor,
|
|
4309
4391
|
onEdit: editFromView,
|
|
4310
4392
|
onClose: closeView,
|
|
4311
|
-
onDelete: _cache[
|
|
4393
|
+
onDelete: _cache[20] || (_cache[20] = ($event) => viewing.value && confirmDelete(viewing.value)),
|
|
4312
4394
|
onRunAction: runAction
|
|
4313
4395
|
}, null, 8, [
|
|
4314
4396
|
"editing",
|
|
@@ -4334,7 +4416,7 @@ var CollectionView_default = /* @__PURE__ */ defineComponent({
|
|
|
4334
4416
|
title: collection.value.title,
|
|
4335
4417
|
views: customViews.value,
|
|
4336
4418
|
onChanged: onViewsChanged,
|
|
4337
|
-
onClose: _cache[
|
|
4419
|
+
onClose: _cache[21] || (_cache[21] = ($event) => configOpen.value = false)
|
|
4338
4420
|
}, null, 8, [
|
|
4339
4421
|
"slug",
|
|
4340
4422
|
"title",
|
|
@@ -4349,29 +4431,29 @@ var CollectionView_default = /* @__PURE__ */ defineComponent({
|
|
|
4349
4431
|
"data-testid": "collections-chat-modal",
|
|
4350
4432
|
onClick: withModifiers(closeChat, ["self"]),
|
|
4351
4433
|
onKeydown: withKeys(closeChat, ["esc"])
|
|
4352
|
-
}, [createElementVNode("div",
|
|
4353
|
-
createElementVNode("header",
|
|
4354
|
-
_cache[
|
|
4355
|
-
createElementVNode("div",
|
|
4434
|
+
}, [createElementVNode("div", _hoisted_77, [
|
|
4435
|
+
createElementVNode("header", _hoisted_78, [
|
|
4436
|
+
_cache[47] || (_cache[47] = 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" }, [createElementVNode("span", { class: "material-icons text-lg" }, "forum")], -1)),
|
|
4437
|
+
createElementVNode("div", _hoisted_79, [createElementVNode("h2", _hoisted_80, toDisplayString(unref(t)("collectionsView.chatTitle")), 1), createElementVNode("span", _hoisted_81, toDisplayString(collection.value.title), 1)]),
|
|
4356
4438
|
createElementVNode("button", {
|
|
4357
4439
|
type: "button",
|
|
4358
4440
|
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",
|
|
4359
4441
|
"aria-label": unref(t)("common.close"),
|
|
4360
4442
|
"data-testid": "collections-chat-close",
|
|
4361
4443
|
onClick: closeChat
|
|
4362
|
-
}, [..._cache[
|
|
4444
|
+
}, [..._cache[46] || (_cache[46] = [createElementVNode("span", { class: "material-icons text-lg" }, "close", -1)])], 8, _hoisted_82)
|
|
4363
4445
|
]),
|
|
4364
|
-
createElementVNode("div",
|
|
4446
|
+
createElementVNode("div", _hoisted_83, [withDirectives(createElementVNode("textarea", {
|
|
4365
4447
|
ref_key: "chatInputEl",
|
|
4366
4448
|
ref: chatInputEl,
|
|
4367
|
-
"onUpdate:modelValue": _cache[
|
|
4449
|
+
"onUpdate:modelValue": _cache[22] || (_cache[22] = ($event) => chatMessage.value = $event),
|
|
4368
4450
|
rows: "4",
|
|
4369
4451
|
placeholder: unref(t)("collectionsView.chatPlaceholder"),
|
|
4370
4452
|
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",
|
|
4371
4453
|
"data-testid": "collections-chat-input",
|
|
4372
4454
|
onKeydown: [withKeys(withModifiers(submitChat, ["meta"]), ["enter"]), withKeys(withModifiers(submitChat, ["ctrl"]), ["enter"])]
|
|
4373
|
-
}, null, 40,
|
|
4374
|
-
createElementVNode("footer",
|
|
4455
|
+
}, null, 40, _hoisted_84), [[vModelText, chatMessage.value]])]),
|
|
4456
|
+
createElementVNode("footer", _hoisted_85, [createElementVNode("button", {
|
|
4375
4457
|
type: "button",
|
|
4376
4458
|
class: "h-8 px-2.5 rounded text-xs font-bold text-slate-500 hover:bg-slate-200/50 transition-colors",
|
|
4377
4459
|
"data-testid": "collections-chat-cancel",
|
|
@@ -4382,13 +4464,121 @@ var CollectionView_default = /* @__PURE__ */ defineComponent({
|
|
|
4382
4464
|
disabled: !chatMessage.value.trim(),
|
|
4383
4465
|
"data-testid": "collections-chat-send",
|
|
4384
4466
|
onClick: submitChat
|
|
4385
|
-
}, toDisplayString(unref(t)("collectionsView.chatStart")), 9,
|
|
4467
|
+
}, toDisplayString(unref(t)("collectionsView.chatStart")), 9, _hoisted_86)])
|
|
4386
4468
|
])], 32)) : createCommentVNode("", true)
|
|
4387
4469
|
]);
|
|
4388
4470
|
};
|
|
4389
4471
|
}
|
|
4390
4472
|
});
|
|
4391
4473
|
//#endregion
|
|
4474
|
+
//#region src/vue/chat/View.vue?vue&type=script&setup=true&lang.ts
|
|
4475
|
+
var _hoisted_1$3 = {
|
|
4476
|
+
class: "w-full h-full",
|
|
4477
|
+
"data-testid": "present-collection"
|
|
4478
|
+
};
|
|
4479
|
+
//#endregion
|
|
4480
|
+
//#region src/vue/chat/View.vue
|
|
4481
|
+
var View_default = /* @__PURE__ */ defineComponent({
|
|
4482
|
+
__name: "View",
|
|
4483
|
+
props: {
|
|
4484
|
+
selectedResult: {},
|
|
4485
|
+
sendTextMessage: { type: Function }
|
|
4486
|
+
},
|
|
4487
|
+
emits: ["updateResult"],
|
|
4488
|
+
setup(__props, { emit: __emit }) {
|
|
4489
|
+
const props = __props;
|
|
4490
|
+
const emit = __emit;
|
|
4491
|
+
const data = computed(() => props.selectedResult?.data ?? props.selectedResult?.jsonData ?? null);
|
|
4492
|
+
const slug = computed(() => data.value?.collectionSlug);
|
|
4493
|
+
const viewState = computed(() => props.selectedResult?.viewState ?? null);
|
|
4494
|
+
/** Open record: the card-local `viewState.selected` once the user has
|
|
4495
|
+
* navigated within the card (including an explicit close → null), else
|
|
4496
|
+
* the tool's initial `itemId`. */
|
|
4497
|
+
const selected = computed(() => {
|
|
4498
|
+
const state = viewState.value;
|
|
4499
|
+
if (state && "selected" in state) return state.selected ?? void 0;
|
|
4500
|
+
return data.value?.itemId;
|
|
4501
|
+
});
|
|
4502
|
+
function onSelect(itemId) {
|
|
4503
|
+
if (!props.selectedResult) return;
|
|
4504
|
+
emit("updateResult", {
|
|
4505
|
+
...props.selectedResult,
|
|
4506
|
+
viewState: {
|
|
4507
|
+
...viewState.value,
|
|
4508
|
+
selected: itemId
|
|
4509
|
+
}
|
|
4510
|
+
});
|
|
4511
|
+
}
|
|
4512
|
+
function onViewStateChange(state) {
|
|
4513
|
+
if (!props.selectedResult) return;
|
|
4514
|
+
const current = viewState.value;
|
|
4515
|
+
if (current?.view === state.view && current?.anchorField === state.anchorField && current?.groupField === state.groupField) return;
|
|
4516
|
+
emit("updateResult", {
|
|
4517
|
+
...props.selectedResult,
|
|
4518
|
+
viewState: {
|
|
4519
|
+
...current,
|
|
4520
|
+
view: state.view,
|
|
4521
|
+
anchorField: state.anchorField,
|
|
4522
|
+
groupField: state.groupField
|
|
4523
|
+
}
|
|
4524
|
+
});
|
|
4525
|
+
}
|
|
4526
|
+
return (_ctx, _cache) => {
|
|
4527
|
+
return openBlock(), createElementBlock("div", _hoisted_1$3, [slug.value ? (openBlock(), createBlock(CollectionView_default, {
|
|
4528
|
+
key: 0,
|
|
4529
|
+
slug: slug.value,
|
|
4530
|
+
selected: selected.value,
|
|
4531
|
+
"initial-view": viewState.value?.view,
|
|
4532
|
+
"initial-anchor-field": viewState.value?.anchorField,
|
|
4533
|
+
"initial-group-field": viewState.value?.groupField,
|
|
4534
|
+
"send-text-message": __props.sendTextMessage,
|
|
4535
|
+
onSelect,
|
|
4536
|
+
onViewStateChange
|
|
4537
|
+
}, null, 8, [
|
|
4538
|
+
"slug",
|
|
4539
|
+
"selected",
|
|
4540
|
+
"initial-view",
|
|
4541
|
+
"initial-anchor-field",
|
|
4542
|
+
"initial-group-field",
|
|
4543
|
+
"send-text-message"
|
|
4544
|
+
])) : createCommentVNode("", true)]);
|
|
4545
|
+
};
|
|
4546
|
+
}
|
|
4547
|
+
});
|
|
4548
|
+
//#endregion
|
|
4549
|
+
//#region src/vue/chat/Preview.vue?vue&type=script&setup=true&lang.ts
|
|
4550
|
+
var _hoisted_1$2 = { class: "w-full h-full flex flex-col items-center justify-center p-4 bg-gradient-to-br from-indigo-50 to-slate-50 rounded-lg border-2 border-gray-200" };
|
|
4551
|
+
var _hoisted_2$2 = { class: "text-center" };
|
|
4552
|
+
var _hoisted_3$2 = { class: "text-gray-900 font-bold text-lg mb-1 line-clamp-2" };
|
|
4553
|
+
var _hoisted_4$2 = {
|
|
4554
|
+
key: 0,
|
|
4555
|
+
class: "text-gray-600 text-sm"
|
|
4556
|
+
};
|
|
4557
|
+
var _hoisted_5$2 = {
|
|
4558
|
+
key: 1,
|
|
4559
|
+
class: "text-gray-500 text-sm"
|
|
4560
|
+
};
|
|
4561
|
+
//#endregion
|
|
4562
|
+
//#region src/vue/chat/Preview.vue
|
|
4563
|
+
var Preview_default = /* @__PURE__ */ defineComponent({
|
|
4564
|
+
__name: "Preview",
|
|
4565
|
+
props: { result: {} },
|
|
4566
|
+
setup(__props) {
|
|
4567
|
+
const { t } = useCollectionI18n();
|
|
4568
|
+
const props = __props;
|
|
4569
|
+
const data = computed(() => props.result?.data ?? props.result?.jsonData ?? null);
|
|
4570
|
+
const collectionSlug = computed(() => data.value?.collectionSlug ?? "");
|
|
4571
|
+
const itemId = computed(() => data.value?.itemId);
|
|
4572
|
+
return (_ctx, _cache) => {
|
|
4573
|
+
return openBlock(), createElementBlock("div", _hoisted_1$2, [createElementVNode("div", _hoisted_2$2, [
|
|
4574
|
+
_cache[0] || (_cache[0] = createElementVNode("span", { class: "material-icons text-4xl text-indigo-600 mb-2" }, "collections_bookmark", -1)),
|
|
4575
|
+
createElementVNode("h3", _hoisted_3$2, toDisplayString(collectionSlug.value || unref(t)("pluginPresentCollection.fallbackTitle")), 1),
|
|
4576
|
+
itemId.value ? (openBlock(), createElementBlock("p", _hoisted_4$2, toDisplayString(unref(t)("pluginPresentCollection.itemLabel", { id: itemId.value })), 1)) : (openBlock(), createElementBlock("p", _hoisted_5$2, toDisplayString(unref(t)("pluginPresentCollection.listLabel")), 1))
|
|
4577
|
+
])]);
|
|
4578
|
+
};
|
|
4579
|
+
}
|
|
4580
|
+
});
|
|
4581
|
+
//#endregion
|
|
4392
4582
|
//#region src/vue/components/CollectionsIndexView.vue?vue&type=script&setup=true&lang.ts
|
|
4393
4583
|
var _hoisted_1$1 = {
|
|
4394
4584
|
class: "h-full overflow-y-auto bg-slate-50/50 px-6 py-6",
|
|
@@ -4696,6 +4886,16 @@ var FeedsView_default = /* @__PURE__ */ defineComponent({
|
|
|
4696
4886
|
}
|
|
4697
4887
|
});
|
|
4698
4888
|
//#endregion
|
|
4699
|
-
|
|
4889
|
+
//#region src/vue/index.ts
|
|
4890
|
+
var plugin = {
|
|
4891
|
+
toolDefinition: TOOL_DEFINITION,
|
|
4892
|
+
execute: executePresentCollection,
|
|
4893
|
+
generatingMessage: "Loading collection...",
|
|
4894
|
+
isEnabled: () => true,
|
|
4895
|
+
viewComponent: View_default,
|
|
4896
|
+
previewComponent: Preview_default
|
|
4897
|
+
};
|
|
4898
|
+
//#endregion
|
|
4899
|
+
export { CollectionCalendarView_default as CollectionCalendarView, CollectionCustomView_default as CollectionCustomView, CollectionDayView_default as CollectionDayView, CollectionEmbedView_default as CollectionEmbedView, CollectionKanbanView_default as CollectionKanbanView, CollectionRecordModal_default as CollectionRecordModal, CollectionRecordPanel_default as CollectionRecordPanel, CollectionView_default as CollectionView, CollectionViewConfigModal_default as CollectionViewConfigModal, CollectionsIndexView_default as CollectionsIndexView, FeedsView_default as FeedsView, Preview_default as PresentCollectionPreview, View_default as PresentCollectionView, collectionUi, configureCollectionUi, plugin, readCollectionSort, readCollectionViewMode, useCollectionRendering, writeCollectionSort, writeCollectionViewMode };
|
|
4700
4900
|
|
|
4701
4901
|
//# sourceMappingURL=vue.js.map
|