@directus/composables 10.1.2 → 10.1.4
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.d.ts +156 -10
- package/dist/index.js +733 -10
- package/package.json +10 -8
- package/dist/use-collection.d.ts +0 -13
- package/dist/use-collection.js +0 -48
- package/dist/use-custom-selection.d.ts +0 -17
- package/dist/use-custom-selection.js +0 -88
- package/dist/use-element-size.d.ts +0 -10
- package/dist/use-element-size.js +0 -22
- package/dist/use-filter-fields.d.ts +0 -5
- package/dist/use-filter-fields.js +0 -18
- package/dist/use-groupable.d.ts +0 -45
- package/dist/use-groupable.js +0 -183
- package/dist/use-items.d.ts +0 -29
- package/dist/use-items.js +0 -234
- package/dist/use-layout.d.ts +0 -4
- package/dist/use-layout.js +0 -100
- package/dist/use-size-class.d.ts +0 -27
- package/dist/use-size-class.js +0 -33
- package/dist/use-sync.d.ts +0 -2
- package/dist/use-sync.js +0 -11
- package/dist/use-system.d.ts +0 -5
- package/dist/use-system.js +0 -20
package/dist/index.js
CHANGED
|
@@ -1,10 +1,733 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
1
|
+
// src/use-collection.ts
|
|
2
|
+
import { computed, ref } from "vue";
|
|
3
|
+
|
|
4
|
+
// src/use-system.ts
|
|
5
|
+
import { API_INJECT, EXTENSIONS_INJECT, STORES_INJECT } from "@directus/constants";
|
|
6
|
+
import { inject } from "vue";
|
|
7
|
+
function useStores() {
|
|
8
|
+
const stores = inject(STORES_INJECT);
|
|
9
|
+
if (!stores)
|
|
10
|
+
throw new Error("[useStores]: The stores could not be found.");
|
|
11
|
+
return stores;
|
|
12
|
+
}
|
|
13
|
+
function useApi() {
|
|
14
|
+
const api = inject(API_INJECT);
|
|
15
|
+
if (!api)
|
|
16
|
+
throw new Error("[useApi]: The api could not be found.");
|
|
17
|
+
return api;
|
|
18
|
+
}
|
|
19
|
+
function useExtensions() {
|
|
20
|
+
const extensions = inject(EXTENSIONS_INJECT);
|
|
21
|
+
if (!extensions)
|
|
22
|
+
throw new Error("[useExtensions]: The extensions could not be found.");
|
|
23
|
+
return extensions;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// src/use-collection.ts
|
|
27
|
+
function useCollection(collectionKey) {
|
|
28
|
+
const { useCollectionsStore, useFieldsStore } = useStores();
|
|
29
|
+
const collectionsStore = useCollectionsStore();
|
|
30
|
+
const fieldsStore = useFieldsStore();
|
|
31
|
+
const collection = typeof collectionKey === "string" ? ref(collectionKey) : collectionKey;
|
|
32
|
+
const info = computed(() => {
|
|
33
|
+
return collectionsStore.collections.find(({ collection: key }) => key === collection.value) || null;
|
|
34
|
+
});
|
|
35
|
+
const fields = computed(() => {
|
|
36
|
+
if (!collection.value)
|
|
37
|
+
return [];
|
|
38
|
+
return fieldsStore.getFieldsForCollectionSorted(collection.value);
|
|
39
|
+
});
|
|
40
|
+
const defaults = computed(() => {
|
|
41
|
+
if (!fields.value)
|
|
42
|
+
return {};
|
|
43
|
+
const defaults2 = {};
|
|
44
|
+
for (const field of fields.value) {
|
|
45
|
+
if (field.schema !== null && "default_value" in field.schema) {
|
|
46
|
+
defaults2[field.field] = field.schema.default_value;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return defaults2;
|
|
50
|
+
});
|
|
51
|
+
const primaryKeyField = computed(() => {
|
|
52
|
+
return fields.value.find((field) => field.collection === collection.value && field.schema?.is_primary_key === true) || null;
|
|
53
|
+
});
|
|
54
|
+
const userCreatedField = computed(() => {
|
|
55
|
+
return fields.value?.find((field) => (field.meta?.special || []).includes("user_created")) || null;
|
|
56
|
+
});
|
|
57
|
+
const sortField = computed(() => {
|
|
58
|
+
return info.value?.meta?.sort_field || null;
|
|
59
|
+
});
|
|
60
|
+
const isSingleton = computed(() => {
|
|
61
|
+
return info.value?.meta?.singleton === true;
|
|
62
|
+
});
|
|
63
|
+
const accountabilityScope = computed(() => {
|
|
64
|
+
if (!info.value)
|
|
65
|
+
return null;
|
|
66
|
+
if (!info.value.meta)
|
|
67
|
+
return null;
|
|
68
|
+
return info.value.meta.accountability;
|
|
69
|
+
});
|
|
70
|
+
return { info, fields, defaults, primaryKeyField, userCreatedField, sortField, isSingleton, accountabilityScope };
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// src/use-custom-selection.ts
|
|
74
|
+
import { nanoid } from "nanoid";
|
|
75
|
+
import { computed as computed2, ref as ref2, watch } from "vue";
|
|
76
|
+
function useCustomSelection(currentValue, items, emit) {
|
|
77
|
+
const localOtherValue = ref2("");
|
|
78
|
+
const otherValue = computed2({
|
|
79
|
+
get() {
|
|
80
|
+
return localOtherValue.value || (usesOtherValue.value ? currentValue.value : "");
|
|
81
|
+
},
|
|
82
|
+
set(newValue) {
|
|
83
|
+
if (newValue === null) {
|
|
84
|
+
localOtherValue.value = "";
|
|
85
|
+
emit(null);
|
|
86
|
+
} else {
|
|
87
|
+
localOtherValue.value = newValue;
|
|
88
|
+
emit(newValue);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
const usesOtherValue = computed2(() => {
|
|
93
|
+
if (items.value === null)
|
|
94
|
+
return false;
|
|
95
|
+
const values = items.value.map((item) => item.value);
|
|
96
|
+
return currentValue.value !== null && currentValue.value.length > 0 && values.includes(currentValue.value) === false;
|
|
97
|
+
});
|
|
98
|
+
return { otherValue, usesOtherValue };
|
|
99
|
+
}
|
|
100
|
+
function useCustomSelectionMultiple(currentValues, items, emit) {
|
|
101
|
+
const otherValues = ref2([]);
|
|
102
|
+
watch(
|
|
103
|
+
currentValues,
|
|
104
|
+
(newValue) => {
|
|
105
|
+
if (newValue === null)
|
|
106
|
+
return;
|
|
107
|
+
if (!Array.isArray(newValue))
|
|
108
|
+
return;
|
|
109
|
+
if (items.value === null)
|
|
110
|
+
return;
|
|
111
|
+
newValue.forEach((value) => {
|
|
112
|
+
if (items.value === null)
|
|
113
|
+
return;
|
|
114
|
+
const values = items.value.map((item) => item.value);
|
|
115
|
+
const existsInValues = values.includes(value);
|
|
116
|
+
if (!existsInValues) {
|
|
117
|
+
const other = otherValues.value.map((o) => o.value);
|
|
118
|
+
const existsInOtherValues = other.includes(value);
|
|
119
|
+
if (!existsInOtherValues) {
|
|
120
|
+
addOtherValue(value);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
},
|
|
125
|
+
{ immediate: true }
|
|
126
|
+
);
|
|
127
|
+
return { otherValues, addOtherValue, setOtherValue };
|
|
128
|
+
function addOtherValue(value = "") {
|
|
129
|
+
otherValues.value = [
|
|
130
|
+
...otherValues.value,
|
|
131
|
+
{
|
|
132
|
+
key: nanoid(),
|
|
133
|
+
value
|
|
134
|
+
}
|
|
135
|
+
];
|
|
136
|
+
}
|
|
137
|
+
function setOtherValue(key, newValue) {
|
|
138
|
+
const previousValue = otherValues.value.find((o) => o.key === key);
|
|
139
|
+
const valueWithoutPrevious = (currentValues.value || []).filter(
|
|
140
|
+
(val) => val !== previousValue?.value
|
|
141
|
+
);
|
|
142
|
+
if (newValue === null) {
|
|
143
|
+
otherValues.value = otherValues.value.filter((o) => o.key !== key);
|
|
144
|
+
if (valueWithoutPrevious.length === 0) {
|
|
145
|
+
emit(null);
|
|
146
|
+
} else {
|
|
147
|
+
emit(valueWithoutPrevious);
|
|
148
|
+
}
|
|
149
|
+
} else {
|
|
150
|
+
otherValues.value = otherValues.value.map((otherValue) => {
|
|
151
|
+
if (otherValue.key === key)
|
|
152
|
+
otherValue.value = newValue;
|
|
153
|
+
return otherValue;
|
|
154
|
+
});
|
|
155
|
+
if (valueWithoutPrevious.length === currentValues.value?.length) {
|
|
156
|
+
emit(valueWithoutPrevious);
|
|
157
|
+
} else {
|
|
158
|
+
emit([...valueWithoutPrevious, newValue]);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// src/use-element-size.ts
|
|
165
|
+
import { isNil } from "lodash-es";
|
|
166
|
+
import { isRef, onMounted, onUnmounted, ref as ref3 } from "vue";
|
|
167
|
+
function useElementSize(target) {
|
|
168
|
+
const width = ref3(0);
|
|
169
|
+
const height = ref3(0);
|
|
170
|
+
const resizeObserver = new ResizeObserver(([entry]) => {
|
|
171
|
+
if (entry === void 0)
|
|
172
|
+
return;
|
|
173
|
+
width.value = entry.contentRect.width;
|
|
174
|
+
height.value = entry.contentRect.height;
|
|
175
|
+
});
|
|
176
|
+
onMounted(() => {
|
|
177
|
+
const t = isRef(target) ? target.value : target;
|
|
178
|
+
if (!isNil(t)) {
|
|
179
|
+
resizeObserver.observe(t);
|
|
180
|
+
}
|
|
181
|
+
});
|
|
182
|
+
onUnmounted(() => {
|
|
183
|
+
resizeObserver.disconnect();
|
|
184
|
+
});
|
|
185
|
+
return { width, height };
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// src/use-filter-fields.ts
|
|
189
|
+
import { computed as computed3 } from "vue";
|
|
190
|
+
function useFilterFields(fields, filters) {
|
|
191
|
+
const fieldGroups = computed3(() => {
|
|
192
|
+
const acc = {};
|
|
193
|
+
for (const name in filters) {
|
|
194
|
+
acc[name] = [];
|
|
195
|
+
}
|
|
196
|
+
return fields.value.reduce((acc2, field) => {
|
|
197
|
+
for (const name in filters) {
|
|
198
|
+
if (filters[name](field) === false)
|
|
199
|
+
continue;
|
|
200
|
+
acc2[name].push(field);
|
|
201
|
+
}
|
|
202
|
+
return acc2;
|
|
203
|
+
}, acc);
|
|
204
|
+
});
|
|
205
|
+
return { fieldGroups };
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
// src/use-groupable.ts
|
|
209
|
+
import { isEqual, isNil as isNil2 } from "lodash-es";
|
|
210
|
+
import { computed as computed4, inject as inject2, nextTick, onBeforeUnmount, provide, ref as ref4, shallowRef, watch as watch2 } from "vue";
|
|
211
|
+
function useGroupable(options) {
|
|
212
|
+
const parentFunctions = inject2(options?.group || "item-group", null);
|
|
213
|
+
if (isNil2(parentFunctions)) {
|
|
214
|
+
return {
|
|
215
|
+
active: ref4(false),
|
|
216
|
+
toggle: () => {
|
|
217
|
+
},
|
|
218
|
+
activate: () => {
|
|
219
|
+
},
|
|
220
|
+
deactivate: () => {
|
|
221
|
+
}
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
const {
|
|
225
|
+
register,
|
|
226
|
+
unregister,
|
|
227
|
+
toggle,
|
|
228
|
+
selection
|
|
229
|
+
} = parentFunctions;
|
|
230
|
+
let startActive = false;
|
|
231
|
+
if (options?.active?.value === true)
|
|
232
|
+
startActive = true;
|
|
233
|
+
if (options?.value && selection.value.includes(options.value))
|
|
234
|
+
startActive = true;
|
|
235
|
+
const active = ref4(startActive);
|
|
236
|
+
const item = { active, value: options?.value };
|
|
237
|
+
register(item);
|
|
238
|
+
if (options?.active !== void 0 && options.watch === true) {
|
|
239
|
+
watch2(options.active, () => {
|
|
240
|
+
if (options.active === void 0)
|
|
241
|
+
return;
|
|
242
|
+
if (options.active.value === true) {
|
|
243
|
+
if (active.value === false)
|
|
244
|
+
toggle(item);
|
|
245
|
+
active.value = true;
|
|
246
|
+
}
|
|
247
|
+
if (options.active.value === false) {
|
|
248
|
+
if (active.value === true)
|
|
249
|
+
toggle(item);
|
|
250
|
+
active.value = false;
|
|
251
|
+
}
|
|
252
|
+
});
|
|
253
|
+
}
|
|
254
|
+
onBeforeUnmount(() => unregister(item));
|
|
255
|
+
return {
|
|
256
|
+
active,
|
|
257
|
+
toggle: () => {
|
|
258
|
+
toggle(item);
|
|
259
|
+
},
|
|
260
|
+
activate: () => {
|
|
261
|
+
if (active.value === false)
|
|
262
|
+
toggle(item);
|
|
263
|
+
},
|
|
264
|
+
deactivate: () => {
|
|
265
|
+
if (active.value === true)
|
|
266
|
+
toggle(item);
|
|
267
|
+
}
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
function useGroupableParent(state = {}, options = {}, group = "item-group") {
|
|
271
|
+
const items = shallowRef([]);
|
|
272
|
+
const internalSelection = ref4([]);
|
|
273
|
+
const selection = computed4({
|
|
274
|
+
get() {
|
|
275
|
+
if (!isNil2(state.selection) && !isNil2(state.selection.value)) {
|
|
276
|
+
return state.selection.value;
|
|
277
|
+
}
|
|
278
|
+
return internalSelection.value;
|
|
279
|
+
},
|
|
280
|
+
set(newSelection) {
|
|
281
|
+
if (!isNil2(state.onSelectionChange)) {
|
|
282
|
+
state.onSelectionChange(newSelection);
|
|
283
|
+
}
|
|
284
|
+
internalSelection.value = [...newSelection];
|
|
285
|
+
}
|
|
286
|
+
});
|
|
287
|
+
provide(group, { register, unregister, toggle, selection });
|
|
288
|
+
watch2(selection, updateChildren, { immediate: true });
|
|
289
|
+
nextTick().then(updateChildren);
|
|
290
|
+
watch2(
|
|
291
|
+
() => options?.mandatory?.value,
|
|
292
|
+
(newValue, oldValue) => {
|
|
293
|
+
if (isEqual(newValue, oldValue))
|
|
294
|
+
return;
|
|
295
|
+
if (!selection.value || selection.value.length === 0 && options?.mandatory?.value === true) {
|
|
296
|
+
if (items.value[0])
|
|
297
|
+
selection.value = [getValueForItem(items.value[0])];
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
);
|
|
301
|
+
return { items, selection, internalSelection, getValueForItem, updateChildren };
|
|
302
|
+
function register(item) {
|
|
303
|
+
items.value = [...items.value, item];
|
|
304
|
+
const value = getValueForItem(item);
|
|
305
|
+
if (selection.value.length === 0 && options?.mandatory?.value === true && items.value.length === 1) {
|
|
306
|
+
selection.value = [value];
|
|
307
|
+
}
|
|
308
|
+
if (item.active.value && selection.value.includes(value) === false) {
|
|
309
|
+
toggle(item);
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
function unregister(item) {
|
|
313
|
+
items.value = items.value.filter((existingItem) => {
|
|
314
|
+
return existingItem !== item;
|
|
315
|
+
});
|
|
316
|
+
}
|
|
317
|
+
function toggle(item) {
|
|
318
|
+
if (options?.multiple?.value === true) {
|
|
319
|
+
toggleMultiple(item);
|
|
320
|
+
} else {
|
|
321
|
+
toggleSingle(item);
|
|
322
|
+
}
|
|
323
|
+
if (!isNil2(state.onToggle)) {
|
|
324
|
+
state.onToggle(item);
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
function toggleSingle(item) {
|
|
328
|
+
const itemValue = getValueForItem(item);
|
|
329
|
+
if (selection.value[0] === itemValue && options?.mandatory?.value !== true) {
|
|
330
|
+
selection.value = [];
|
|
331
|
+
return;
|
|
332
|
+
}
|
|
333
|
+
if (selection.value[0] !== itemValue) {
|
|
334
|
+
selection.value = [itemValue];
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
function toggleMultiple(item) {
|
|
338
|
+
const itemValue = getValueForItem(item);
|
|
339
|
+
if (selection.value.includes(itemValue)) {
|
|
340
|
+
if (options?.mandatory?.value === true && selection.value.length === 1) {
|
|
341
|
+
updateChildren();
|
|
342
|
+
return;
|
|
343
|
+
}
|
|
344
|
+
selection.value = selection.value.filter((value) => value !== itemValue);
|
|
345
|
+
return;
|
|
346
|
+
}
|
|
347
|
+
if (options?.max?.value && options.max.value !== -1 && selection.value.length >= options.max.value) {
|
|
348
|
+
updateChildren();
|
|
349
|
+
return;
|
|
350
|
+
}
|
|
351
|
+
selection.value = [...selection.value, itemValue];
|
|
352
|
+
}
|
|
353
|
+
function getValueForItem(item) {
|
|
354
|
+
return item.value || items.value.findIndex((child) => item === child);
|
|
355
|
+
}
|
|
356
|
+
function updateChildren() {
|
|
357
|
+
items.value.forEach((item) => {
|
|
358
|
+
item.active.value = selection.value.includes(getValueForItem(item));
|
|
359
|
+
});
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
// src/use-items.ts
|
|
364
|
+
import { getEndpoint, moveInArray } from "@directus/utils";
|
|
365
|
+
import axios from "axios";
|
|
366
|
+
import { isEqual as isEqual2, throttle } from "lodash-es";
|
|
367
|
+
import { computed as computed5, ref as ref5, unref, watch as watch3 } from "vue";
|
|
368
|
+
function useItems(collection, query) {
|
|
369
|
+
const api = useApi();
|
|
370
|
+
const { primaryKeyField } = useCollection(collection);
|
|
371
|
+
const { fields, limit, sort, search, filter, page, alias: queryAlias, deep: queryDeep } = query;
|
|
372
|
+
const alias = queryAlias ?? ref5();
|
|
373
|
+
const deep = queryDeep ?? ref5();
|
|
374
|
+
const endpoint = computed5(() => {
|
|
375
|
+
if (!collection.value)
|
|
376
|
+
return null;
|
|
377
|
+
return getEndpoint(collection.value);
|
|
378
|
+
});
|
|
379
|
+
const items = ref5([]);
|
|
380
|
+
const loading = ref5(false);
|
|
381
|
+
const error = ref5(null);
|
|
382
|
+
const itemCount = ref5(null);
|
|
383
|
+
const totalCount = ref5(null);
|
|
384
|
+
const totalPages = computed5(() => {
|
|
385
|
+
if (itemCount.value === null)
|
|
386
|
+
return 1;
|
|
387
|
+
if (itemCount.value < (unref(limit) ?? 100))
|
|
388
|
+
return 1;
|
|
389
|
+
return Math.ceil(itemCount.value / (unref(limit) ?? 100));
|
|
390
|
+
});
|
|
391
|
+
const existingRequests = {
|
|
392
|
+
items: null,
|
|
393
|
+
total: null,
|
|
394
|
+
filter: null
|
|
395
|
+
};
|
|
396
|
+
let loadingTimeout = null;
|
|
397
|
+
const fetchItems = throttle(getItems, 500);
|
|
398
|
+
watch3(
|
|
399
|
+
[collection, limit, sort, search, filter, fields, page, alias, deep],
|
|
400
|
+
async (after, before) => {
|
|
401
|
+
if (isEqual2(after, before))
|
|
402
|
+
return;
|
|
403
|
+
const [newCollection, newLimit, newSort, newSearch, newFilter] = after;
|
|
404
|
+
const [oldCollection, oldLimit, oldSort, oldSearch, oldFilter] = before;
|
|
405
|
+
if (!newCollection || !query)
|
|
406
|
+
return;
|
|
407
|
+
if (newCollection !== oldCollection) {
|
|
408
|
+
reset();
|
|
409
|
+
}
|
|
410
|
+
if (!isEqual2(newFilter, oldFilter) || !isEqual2(newSort, oldSort) || newLimit !== oldLimit || newSearch !== oldSearch) {
|
|
411
|
+
if (oldCollection) {
|
|
412
|
+
page.value = 1;
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
if (newCollection !== oldCollection || !isEqual2(newFilter, oldFilter) || newSearch !== oldSearch) {
|
|
416
|
+
getItemCount();
|
|
417
|
+
}
|
|
418
|
+
fetchItems();
|
|
419
|
+
},
|
|
420
|
+
{ deep: true, immediate: true }
|
|
421
|
+
);
|
|
422
|
+
return {
|
|
423
|
+
itemCount,
|
|
424
|
+
totalCount,
|
|
425
|
+
items,
|
|
426
|
+
totalPages,
|
|
427
|
+
loading,
|
|
428
|
+
error,
|
|
429
|
+
changeManualSort,
|
|
430
|
+
getItems,
|
|
431
|
+
getItemCount,
|
|
432
|
+
getTotalCount
|
|
433
|
+
};
|
|
434
|
+
async function getItems() {
|
|
435
|
+
if (!endpoint.value)
|
|
436
|
+
return;
|
|
437
|
+
let isCurrentRequestCanceled = false;
|
|
438
|
+
if (existingRequests.items)
|
|
439
|
+
existingRequests.items.abort();
|
|
440
|
+
existingRequests.items = new AbortController();
|
|
441
|
+
error.value = null;
|
|
442
|
+
if (loadingTimeout) {
|
|
443
|
+
clearTimeout(loadingTimeout);
|
|
444
|
+
}
|
|
445
|
+
loadingTimeout = setTimeout(() => {
|
|
446
|
+
loading.value = true;
|
|
447
|
+
}, 150);
|
|
448
|
+
if (unref(totalCount) === null) {
|
|
449
|
+
getTotalCount();
|
|
450
|
+
}
|
|
451
|
+
let fieldsToFetch = [...unref(fields) ?? []];
|
|
452
|
+
if (!unref(fields)?.includes("*") && primaryKeyField.value && fieldsToFetch.includes(primaryKeyField.value.field) === false) {
|
|
453
|
+
fieldsToFetch.push(primaryKeyField.value.field);
|
|
454
|
+
}
|
|
455
|
+
fieldsToFetch = fieldsToFetch.filter((field) => field.startsWith("$") === false);
|
|
456
|
+
try {
|
|
457
|
+
const response = await api.get(endpoint.value, {
|
|
458
|
+
params: {
|
|
459
|
+
limit: unref(limit),
|
|
460
|
+
fields: fieldsToFetch,
|
|
461
|
+
...alias ? { alias: unref(alias) } : {},
|
|
462
|
+
sort: unref(sort),
|
|
463
|
+
page: unref(page),
|
|
464
|
+
search: unref(search),
|
|
465
|
+
filter: unref(filter),
|
|
466
|
+
deep: unref(deep)
|
|
467
|
+
},
|
|
468
|
+
signal: existingRequests.items.signal
|
|
469
|
+
});
|
|
470
|
+
let fetchedItems = response.data.data;
|
|
471
|
+
existingRequests.items = null;
|
|
472
|
+
if (collection.value === "directus_files") {
|
|
473
|
+
fetchedItems = fetchedItems.map((file) => ({
|
|
474
|
+
...file,
|
|
475
|
+
$thumbnail: file
|
|
476
|
+
}));
|
|
477
|
+
}
|
|
478
|
+
items.value = fetchedItems;
|
|
479
|
+
if (page && fetchedItems.length === 0 && page?.value !== 1) {
|
|
480
|
+
page.value = 1;
|
|
481
|
+
}
|
|
482
|
+
} catch (err) {
|
|
483
|
+
if (axios.isCancel(err)) {
|
|
484
|
+
isCurrentRequestCanceled = true;
|
|
485
|
+
} else {
|
|
486
|
+
error.value = err;
|
|
487
|
+
}
|
|
488
|
+
} finally {
|
|
489
|
+
if (loadingTimeout && !isCurrentRequestCanceled) {
|
|
490
|
+
clearTimeout(loadingTimeout);
|
|
491
|
+
loadingTimeout = null;
|
|
492
|
+
}
|
|
493
|
+
if (!loadingTimeout)
|
|
494
|
+
loading.value = false;
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
function reset() {
|
|
498
|
+
items.value = [];
|
|
499
|
+
totalCount.value = null;
|
|
500
|
+
itemCount.value = null;
|
|
501
|
+
}
|
|
502
|
+
async function changeManualSort({ item, to }) {
|
|
503
|
+
const pk = primaryKeyField.value?.field;
|
|
504
|
+
if (!pk)
|
|
505
|
+
return;
|
|
506
|
+
const fromIndex = items.value.findIndex((existing) => existing[pk] === item);
|
|
507
|
+
const toIndex = items.value.findIndex((existing) => existing[pk] === to);
|
|
508
|
+
items.value = moveInArray(items.value, fromIndex, toIndex);
|
|
509
|
+
const endpoint2 = computed5(() => `/utils/sort/${collection.value}`);
|
|
510
|
+
await api.post(endpoint2.value, { item, to });
|
|
511
|
+
}
|
|
512
|
+
async function getTotalCount() {
|
|
513
|
+
if (!endpoint.value)
|
|
514
|
+
return;
|
|
515
|
+
try {
|
|
516
|
+
if (existingRequests.total)
|
|
517
|
+
existingRequests.total.abort();
|
|
518
|
+
existingRequests.total = new AbortController();
|
|
519
|
+
const aggregate = primaryKeyField.value ? {
|
|
520
|
+
countDistinct: primaryKeyField.value.field
|
|
521
|
+
} : {
|
|
522
|
+
count: "*"
|
|
523
|
+
};
|
|
524
|
+
const response = await api.get(endpoint.value, {
|
|
525
|
+
params: {
|
|
526
|
+
aggregate
|
|
527
|
+
},
|
|
528
|
+
signal: existingRequests.total.signal
|
|
529
|
+
});
|
|
530
|
+
const count = primaryKeyField.value ? Number(response.data.data[0].countDistinct[primaryKeyField.value.field]) : Number(response.data.data[0].count);
|
|
531
|
+
existingRequests.total = null;
|
|
532
|
+
totalCount.value = count;
|
|
533
|
+
} catch (err) {
|
|
534
|
+
if (!axios.isCancel(err)) {
|
|
535
|
+
throw err;
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
async function getItemCount() {
|
|
540
|
+
if (!endpoint.value)
|
|
541
|
+
return;
|
|
542
|
+
try {
|
|
543
|
+
if (existingRequests.filter)
|
|
544
|
+
existingRequests.filter.abort();
|
|
545
|
+
existingRequests.filter = new AbortController();
|
|
546
|
+
const aggregate = primaryKeyField.value ? {
|
|
547
|
+
countDistinct: primaryKeyField.value.field
|
|
548
|
+
} : {
|
|
549
|
+
count: "*"
|
|
550
|
+
};
|
|
551
|
+
const response = await api.get(endpoint.value, {
|
|
552
|
+
params: {
|
|
553
|
+
filter: unref(filter),
|
|
554
|
+
search: unref(search),
|
|
555
|
+
aggregate
|
|
556
|
+
},
|
|
557
|
+
signal: existingRequests.filter.signal
|
|
558
|
+
});
|
|
559
|
+
const count = primaryKeyField.value ? Number(response.data.data[0].countDistinct[primaryKeyField.value.field]) : Number(response.data.data[0].count);
|
|
560
|
+
existingRequests.filter = null;
|
|
561
|
+
itemCount.value = count;
|
|
562
|
+
} catch (err) {
|
|
563
|
+
if (!axios.isCancel(err)) {
|
|
564
|
+
throw err;
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
// src/use-layout.ts
|
|
571
|
+
import { computed as computed6, defineComponent, reactive, toRefs } from "vue";
|
|
572
|
+
var NAME_SUFFIX = "wrapper";
|
|
573
|
+
var WRITABLE_PROPS = ["selection", "layoutOptions", "layoutQuery"];
|
|
574
|
+
function isWritableProp(prop) {
|
|
575
|
+
return WRITABLE_PROPS.includes(prop);
|
|
576
|
+
}
|
|
577
|
+
function createLayoutWrapper(layout) {
|
|
578
|
+
return defineComponent({
|
|
579
|
+
name: `${layout.id}-${NAME_SUFFIX}`,
|
|
580
|
+
props: {
|
|
581
|
+
collection: {
|
|
582
|
+
type: String,
|
|
583
|
+
required: true
|
|
584
|
+
},
|
|
585
|
+
selection: {
|
|
586
|
+
type: Array,
|
|
587
|
+
default: () => []
|
|
588
|
+
},
|
|
589
|
+
layoutOptions: {
|
|
590
|
+
type: Object,
|
|
591
|
+
default: () => ({})
|
|
592
|
+
},
|
|
593
|
+
layoutQuery: {
|
|
594
|
+
type: Object,
|
|
595
|
+
default: () => ({})
|
|
596
|
+
},
|
|
597
|
+
layoutProps: {
|
|
598
|
+
type: Object,
|
|
599
|
+
default: () => ({})
|
|
600
|
+
},
|
|
601
|
+
filter: {
|
|
602
|
+
type: Object,
|
|
603
|
+
default: null
|
|
604
|
+
},
|
|
605
|
+
filterUser: {
|
|
606
|
+
type: Object,
|
|
607
|
+
default: null
|
|
608
|
+
},
|
|
609
|
+
filterSystem: {
|
|
610
|
+
type: Object,
|
|
611
|
+
default: null
|
|
612
|
+
},
|
|
613
|
+
search: {
|
|
614
|
+
type: String,
|
|
615
|
+
default: null
|
|
616
|
+
},
|
|
617
|
+
showSelect: {
|
|
618
|
+
type: String,
|
|
619
|
+
default: "multiple"
|
|
620
|
+
},
|
|
621
|
+
selectMode: {
|
|
622
|
+
type: Boolean,
|
|
623
|
+
default: false
|
|
624
|
+
},
|
|
625
|
+
readonly: {
|
|
626
|
+
type: Boolean,
|
|
627
|
+
default: false
|
|
628
|
+
},
|
|
629
|
+
resetPreset: {
|
|
630
|
+
type: Function,
|
|
631
|
+
default: null
|
|
632
|
+
},
|
|
633
|
+
clearFilters: {
|
|
634
|
+
type: Function,
|
|
635
|
+
default: null
|
|
636
|
+
}
|
|
637
|
+
},
|
|
638
|
+
emits: WRITABLE_PROPS.map((prop) => `update:${prop}`),
|
|
639
|
+
setup(props, { emit }) {
|
|
640
|
+
const state = reactive({ ...layout.setup(props, { emit }), ...toRefs(props) });
|
|
641
|
+
for (const key in state) {
|
|
642
|
+
state[`onUpdate:${key}`] = (value) => {
|
|
643
|
+
if (isWritableProp(key)) {
|
|
644
|
+
emit(`update:${key}`, value);
|
|
645
|
+
} else if (!Object.keys(props).includes(key)) {
|
|
646
|
+
state[key] = value;
|
|
647
|
+
}
|
|
648
|
+
};
|
|
649
|
+
}
|
|
650
|
+
return { state };
|
|
651
|
+
},
|
|
652
|
+
render(ctx) {
|
|
653
|
+
return ctx.$slots.default !== void 0 ? ctx.$slots.default({ layoutState: ctx.state }) : null;
|
|
654
|
+
}
|
|
655
|
+
});
|
|
656
|
+
}
|
|
657
|
+
function useLayout(layoutId) {
|
|
658
|
+
const { layouts } = useExtensions();
|
|
659
|
+
const layoutWrappers = computed6(() => layouts.value.map((layout) => createLayoutWrapper(layout)));
|
|
660
|
+
const layoutWrapper = computed6(() => {
|
|
661
|
+
const layout = layoutWrappers.value.find((layout2) => layout2.name === `${layoutId.value}-${NAME_SUFFIX}`);
|
|
662
|
+
if (layout === void 0) {
|
|
663
|
+
return layoutWrappers.value.find((layout2) => layout2.name === `tabular-${NAME_SUFFIX}`);
|
|
664
|
+
}
|
|
665
|
+
return layout;
|
|
666
|
+
});
|
|
667
|
+
return { layoutWrapper };
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
// src/use-size-class.ts
|
|
671
|
+
import { computed as computed7 } from "vue";
|
|
672
|
+
var sizeProps = {
|
|
673
|
+
xSmall: {
|
|
674
|
+
type: Boolean,
|
|
675
|
+
default: false
|
|
676
|
+
},
|
|
677
|
+
small: {
|
|
678
|
+
type: Boolean,
|
|
679
|
+
default: false
|
|
680
|
+
},
|
|
681
|
+
large: {
|
|
682
|
+
type: Boolean,
|
|
683
|
+
default: false
|
|
684
|
+
},
|
|
685
|
+
xLarge: {
|
|
686
|
+
type: Boolean,
|
|
687
|
+
default: false
|
|
688
|
+
}
|
|
689
|
+
};
|
|
690
|
+
function useSizeClass(props) {
|
|
691
|
+
const sizeClass = computed7(() => {
|
|
692
|
+
if (props.xSmall)
|
|
693
|
+
return "x-small";
|
|
694
|
+
if (props.small)
|
|
695
|
+
return "small";
|
|
696
|
+
if (props.large)
|
|
697
|
+
return "large";
|
|
698
|
+
if (props.xLarge)
|
|
699
|
+
return "x-large";
|
|
700
|
+
return null;
|
|
701
|
+
});
|
|
702
|
+
return sizeClass;
|
|
703
|
+
}
|
|
704
|
+
|
|
705
|
+
// src/use-sync.ts
|
|
706
|
+
import { computed as computed8 } from "vue";
|
|
707
|
+
function useSync(props, key, emit) {
|
|
708
|
+
return computed8({
|
|
709
|
+
get() {
|
|
710
|
+
return props[key];
|
|
711
|
+
},
|
|
712
|
+
set(newVal) {
|
|
713
|
+
emit(`update:${key}`, newVal);
|
|
714
|
+
}
|
|
715
|
+
});
|
|
716
|
+
}
|
|
717
|
+
export {
|
|
718
|
+
sizeProps,
|
|
719
|
+
useApi,
|
|
720
|
+
useCollection,
|
|
721
|
+
useCustomSelection,
|
|
722
|
+
useCustomSelectionMultiple,
|
|
723
|
+
useElementSize,
|
|
724
|
+
useExtensions,
|
|
725
|
+
useFilterFields,
|
|
726
|
+
useGroupable,
|
|
727
|
+
useGroupableParent,
|
|
728
|
+
useItems,
|
|
729
|
+
useLayout,
|
|
730
|
+
useSizeClass,
|
|
731
|
+
useStores,
|
|
732
|
+
useSync
|
|
733
|
+
};
|