atom-nuxt 1.0.156 → 1.2.2
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/module.cjs +5 -0
- package/dist/module.d.mts +1 -2
- package/dist/module.d.ts +22 -0
- package/dist/module.json +3 -3
- package/dist/runtime/components/AlertDisplay.vue +18 -11
- package/dist/runtime/components/CrudAddressSearchField.vue +35 -22
- package/dist/runtime/components/CrudApiSelectorField.vue +24 -11
- package/dist/runtime/components/CrudConfirmDialog.vue +17 -11
- package/dist/runtime/components/CrudErrorDisplay.vue +4 -3
- package/dist/runtime/components/CrudFilter.vue +46 -25
- package/dist/runtime/components/CrudFilterList.vue +6 -0
- package/dist/runtime/components/CrudFormDialog.vue +29 -12
- package/dist/runtime/components/CrudFormLoader.vue +121 -98
- package/dist/runtime/components/CrudListLoader.vue +28 -17
- package/dist/runtime/components/CrudPaginatedLoader.vue +112 -53
- package/dist/runtime/components/CrudUploadField.vue +28 -6
- package/dist/runtime/components/CrudUploadFieldSelection.vue +27 -19
- package/dist/types.d.mts +2 -4
- package/dist/types.d.ts +7 -0
- package/package.json +1 -1
- package/dist/runtime/components/AlertDisplay.vue.d.ts +0 -2
- package/dist/runtime/components/CrudAddressSearchField.vue.d.ts +0 -8
- package/dist/runtime/components/CrudApiSelectorField.vue.d.ts +0 -30
- package/dist/runtime/components/CrudConfirmDialog.vue.d.ts +0 -18
- package/dist/runtime/components/CrudErrorDisplay.vue.d.ts +0 -6
- package/dist/runtime/components/CrudFilter.vue.d.ts +0 -8
- package/dist/runtime/components/CrudFilterList.vue.d.ts +0 -5
- package/dist/runtime/components/CrudFormDialog.vue.d.ts +0 -31
- package/dist/runtime/components/CrudFormLoader.vue.d.ts +0 -41
- package/dist/runtime/components/CrudListLoader.vue.d.ts +0 -37
- package/dist/runtime/components/CrudPaginatedLoader.vue.d.ts +0 -72
- package/dist/runtime/components/CrudUploadField.vue.d.ts +0 -23
- package/dist/runtime/components/CrudUploadFieldSelection.vue.d.ts +0 -18
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
<script setup async>
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
2
|
+
import {useCrudApi} from "../composables/useCrudApi";
|
|
3
|
+
import {useCrudConverters} from "../composables/useCrudConverters";
|
|
4
|
+
import {usePreviousRoute} from "../composables/usePreviousRoute";
|
|
5
|
+
import {useRoute, useRouter} from '#app';
|
|
6
6
|
import CrudFilterList from "./CrudFilterList.vue";
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
7
|
+
import {computed, ref, watch, onMounted, onBeforeUnmount} from "vue";
|
|
8
|
+
import {useDebounceFn} from '@vueuse/core'
|
|
9
|
+
import {useListenerService} from "../composables/useListenerService";
|
|
10
10
|
import CrudFormDialog from "./CrudFormDialog.vue";
|
|
11
11
|
import CrudErrorDisplay from "./CrudErrorDisplay.vue";
|
|
12
|
-
|
|
12
|
+
|
|
13
|
+
const {parseQuery, stringifyQuery, cloneDeep} = useCrudConverters();
|
|
13
14
|
const props = defineProps({
|
|
14
15
|
fullScreenDialog: {
|
|
15
16
|
type: Boolean,
|
|
@@ -90,6 +91,13 @@ const props = defineProps({
|
|
|
90
91
|
return "Create item";
|
|
91
92
|
}
|
|
92
93
|
},
|
|
94
|
+
viewTitle: {
|
|
95
|
+
type: String,
|
|
96
|
+
required: false,
|
|
97
|
+
default() {
|
|
98
|
+
return "View item";
|
|
99
|
+
}
|
|
100
|
+
},
|
|
93
101
|
customFilters: {
|
|
94
102
|
type: Object,
|
|
95
103
|
required: false,
|
|
@@ -144,29 +152,40 @@ const {
|
|
|
144
152
|
hasExportErrors,
|
|
145
153
|
hasListErrors
|
|
146
154
|
} = useCrudApi(props.path, false, props.transformItem, props.transformItems);
|
|
155
|
+
|
|
147
156
|
perPage.value = props.perPage;
|
|
157
|
+
|
|
148
158
|
const route = useRoute();
|
|
149
159
|
const router = useRouter();
|
|
150
160
|
const previousRoute = usePreviousRoute();
|
|
151
|
-
|
|
152
|
-
const
|
|
161
|
+
|
|
162
|
+
const action = computed(() => route.query[(props.loaderKey ?? '') + 'action']);
|
|
163
|
+
const actionId = computed(() => route.query[(props.loaderKey ?? '') + 'actionId']);
|
|
164
|
+
|
|
153
165
|
const dialogOpen = computed({
|
|
154
|
-
get: () => !!(action.value === "create" || action.value === "update" && actionId.value || action.value === "delete" && actionId.value),
|
|
166
|
+
get: () => !!(action.value === "create" || (action.value === "update" && actionId.value) || (action.value === "delete" && actionId.value) || (action.value === "view" && actionId.value)),
|
|
155
167
|
set: (value) => {
|
|
156
168
|
if (!value) {
|
|
157
|
-
const hasBackState = router.options.history.state.back
|
|
158
|
-
|
|
159
|
-
console.log(
|
|
160
|
-
console.log(
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
169
|
+
const hasBackState = router.options.history.state.back
|
|
170
|
+
|
|
171
|
+
console.log('hasBackState', hasBackState)
|
|
172
|
+
console.log('previousRoute', previousRoute.value)
|
|
173
|
+
console.log('route', route)
|
|
174
|
+
|
|
175
|
+
const previousRouteName = previousRoute.value?.name
|
|
176
|
+
const currentRouteName = route.name
|
|
177
|
+
|
|
178
|
+
console.log('previousRouteName', previousRouteName)
|
|
179
|
+
console.log('currentRouteName', currentRouteName)
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
if (hasBackState && previousRouteName === currentRouteName) { // Only go back if there's a back state AND the previous route is the same
|
|
183
|
+
console.log('going back')
|
|
167
184
|
router.back();
|
|
168
185
|
} else {
|
|
169
|
-
|
|
186
|
+
// ✅ Clone the query object!
|
|
187
|
+
const currentQuery = {...route.query};
|
|
188
|
+
|
|
170
189
|
if (props.loaderKey) {
|
|
171
190
|
delete currentQuery[`${props.loaderKey}action`];
|
|
172
191
|
delete currentQuery[`${props.loaderKey}actionId`];
|
|
@@ -174,35 +193,40 @@ const dialogOpen = computed({
|
|
|
174
193
|
delete currentQuery.action;
|
|
175
194
|
delete currentQuery.actionId;
|
|
176
195
|
}
|
|
196
|
+
|
|
177
197
|
const finalRoute = {
|
|
178
198
|
path: route.path,
|
|
179
|
-
query: currentQuery
|
|
199
|
+
query: currentQuery,
|
|
180
200
|
};
|
|
181
201
|
router.replace(finalRoute);
|
|
182
202
|
}
|
|
183
203
|
}
|
|
184
204
|
}
|
|
185
205
|
});
|
|
206
|
+
|
|
207
|
+
|
|
186
208
|
const page = computed(() => props.loaderKey ? parseQuery(route.query[props.loaderKey])?.page ?? 1 : route.query.page ?? 1);
|
|
187
|
-
const filterValues = props.loaderKey ? ref({
|
|
188
|
-
const onQueryChange = (
|
|
209
|
+
const filterValues = props.loaderKey ? ref({...props.customFilters, ...parseQuery(route.query[props.loaderKey])} ?? props.customFilters) : ref({...props.customFilters, ...route.query});
|
|
210
|
+
const onQueryChange = (page) => {
|
|
189
211
|
console.error("QUERY CHANGED");
|
|
190
|
-
const newQuery = {}
|
|
212
|
+
const newQuery = {}
|
|
191
213
|
const existingQuery = parseQuery(route.query);
|
|
214
|
+
|
|
192
215
|
for (const key in filterValues.value) {
|
|
193
216
|
if (filterValues.value[key] !== null && filterValues.value[key] !== "") {
|
|
194
217
|
newQuery[key] = filterValues.value[key];
|
|
195
218
|
}
|
|
196
219
|
}
|
|
197
|
-
newQuery.page =
|
|
220
|
+
newQuery.page = page;
|
|
198
221
|
let finalQuery = {
|
|
199
|
-
...existingQuery
|
|
200
|
-
}
|
|
222
|
+
...existingQuery,
|
|
223
|
+
}
|
|
201
224
|
if (props.loaderKey) {
|
|
202
225
|
finalQuery[props.loaderKey] = stringifyQuery(newQuery);
|
|
203
226
|
} else {
|
|
204
227
|
finalQuery = newQuery;
|
|
205
228
|
}
|
|
229
|
+
//Delete action and actionId from query when filters or page change
|
|
206
230
|
if (props.loaderKey) {
|
|
207
231
|
delete finalQuery[`${props.loaderKey}action`];
|
|
208
232
|
delete finalQuery[`${props.loaderKey}actionId`];
|
|
@@ -211,59 +235,81 @@ const onQueryChange = (page2) => {
|
|
|
211
235
|
delete finalQuery.actionId;
|
|
212
236
|
}
|
|
213
237
|
console.error("Setting query", finalQuery);
|
|
214
|
-
router.replace({
|
|
215
|
-
}
|
|
238
|
+
router.replace({path: route.path, query: finalQuery, force: true})
|
|
239
|
+
}
|
|
216
240
|
watch(currentPage, (newVal, oldValue) => {
|
|
217
241
|
onQueryChange(currentPage.value);
|
|
218
242
|
});
|
|
219
243
|
watch(filterValues, (newVal, oldValue) => {
|
|
220
244
|
console.error("FILTERS CHANGED");
|
|
221
245
|
onQueryChange(1);
|
|
222
|
-
}, {
|
|
246
|
+
}, {deep: true});
|
|
247
|
+
|
|
248
|
+
|
|
223
249
|
watch(() => page, () => {
|
|
224
250
|
console.error("ROUTE CHANGED");
|
|
225
251
|
debouncedGet();
|
|
226
|
-
}, {
|
|
252
|
+
}, {deep: true});
|
|
227
253
|
watch(() => filterValues, () => {
|
|
228
254
|
console.error("ROUTE CHANGED");
|
|
229
255
|
debouncedGet();
|
|
230
|
-
}, {
|
|
256
|
+
}, {deep: true});
|
|
257
|
+
|
|
258
|
+
watch(() => props.customFilters, (newVal) => {
|
|
259
|
+
// Update filterValues when customFilters prop changes
|
|
260
|
+
filterValues.value = {...newVal, ...filterValues.value};
|
|
261
|
+
}, {deep: true});
|
|
262
|
+
|
|
231
263
|
const debouncedGet = useDebounceFn(() => {
|
|
232
264
|
console.error("DEBOUNCED GET");
|
|
233
265
|
getItems(Number.parseInt(page.value) ?? null, null, filterValues.value);
|
|
234
|
-
}, 200)
|
|
266
|
+
}, 200)
|
|
267
|
+
|
|
235
268
|
const updateForm = async (id) => {
|
|
236
|
-
const newQuery = {
|
|
269
|
+
const newQuery = {query: {...route.query}};
|
|
237
270
|
if (props.loaderKey) {
|
|
238
|
-
newQuery.query[(props.loaderKey ??
|
|
239
|
-
newQuery.query[(props.loaderKey ??
|
|
271
|
+
newQuery.query[(props.loaderKey ?? '') + 'action'] = "update";
|
|
272
|
+
newQuery.query[(props.loaderKey ?? '') + 'actionId'] = id;
|
|
240
273
|
} else {
|
|
241
274
|
newQuery.query.action = "update";
|
|
242
275
|
newQuery.query.actionId = id;
|
|
243
276
|
}
|
|
244
277
|
await router.push(newQuery);
|
|
245
|
-
}
|
|
278
|
+
}
|
|
246
279
|
const deleteForm = async (id) => {
|
|
247
|
-
|
|
280
|
+
|
|
281
|
+
const newQuery = {query: {...route.query}};
|
|
248
282
|
if (props.loaderKey) {
|
|
249
|
-
newQuery.query[(props.loaderKey ??
|
|
250
|
-
newQuery.query[(props.loaderKey ??
|
|
283
|
+
newQuery.query[(props.loaderKey ?? '') + 'action'] = "delete";
|
|
284
|
+
newQuery.query[(props.loaderKey ?? '') + 'actionId'] = id;
|
|
251
285
|
} else {
|
|
252
286
|
newQuery.query.action = "delete";
|
|
253
287
|
newQuery.query.actionId = id;
|
|
254
288
|
}
|
|
255
289
|
await router.push(newQuery);
|
|
256
|
-
}
|
|
290
|
+
}
|
|
291
|
+
const viewForm = async (id) => {
|
|
292
|
+
const newQuery = {query: {...route.query}};
|
|
293
|
+
if (props.loaderKey) {
|
|
294
|
+
newQuery.query[(props.loaderKey ?? '') + 'action'] = "view";
|
|
295
|
+
newQuery.query[(props.loaderKey ?? '') + 'actionId'] = id;
|
|
296
|
+
} else {
|
|
297
|
+
newQuery.query.action = "view";
|
|
298
|
+
newQuery.query.actionId = id;
|
|
299
|
+
}
|
|
300
|
+
await router.push(newQuery);
|
|
301
|
+
}
|
|
257
302
|
const createForm = () => {
|
|
258
303
|
item.value = props.initialItem ? cloneDeep(props.initialItem) : {};
|
|
259
|
-
const newQuery = {
|
|
304
|
+
const newQuery = {query: {...route.query}};
|
|
260
305
|
if (props.loaderKey) {
|
|
261
|
-
newQuery.query[(props.loaderKey ??
|
|
306
|
+
newQuery.query[(props.loaderKey ?? '') + 'action'] = "create";
|
|
262
307
|
} else {
|
|
263
308
|
newQuery.query.action = "create";
|
|
264
309
|
}
|
|
265
310
|
router.push(newQuery);
|
|
266
|
-
}
|
|
311
|
+
}
|
|
312
|
+
|
|
267
313
|
const saveAction = async () => {
|
|
268
314
|
formPending.value = true;
|
|
269
315
|
let itemToSave = JSON.parse(JSON.stringify(item.value));
|
|
@@ -294,12 +340,14 @@ const saveAction = async () => {
|
|
|
294
340
|
await getItems(Number.parseInt(page.value) ?? null, null, filterValues.value);
|
|
295
341
|
notify(savedPath + ":" + savedAction, savedItem);
|
|
296
342
|
}
|
|
297
|
-
}
|
|
343
|
+
}
|
|
344
|
+
|
|
298
345
|
if (props.await) {
|
|
299
346
|
await getItems(page.value ?? null, null, filterValues.value);
|
|
300
347
|
} else {
|
|
301
348
|
getItems(page.value ?? null, null, filterValues.value);
|
|
302
349
|
}
|
|
350
|
+
|
|
303
351
|
watch(action, (newVal, oldValue) => {
|
|
304
352
|
try {
|
|
305
353
|
if (action.value === "update" && actionId.value) {
|
|
@@ -308,30 +356,34 @@ watch(action, (newVal, oldValue) => {
|
|
|
308
356
|
item.value = props.initialItem ? cloneDeep(props.initialItem) : {};
|
|
309
357
|
} else if (action.value === "delete" && actionId.value) {
|
|
310
358
|
getItem(actionId.value);
|
|
359
|
+
} else if (action.value === "view" && actionId.value) {
|
|
360
|
+
getItem(actionId.value);
|
|
311
361
|
}
|
|
312
362
|
} catch (error) {
|
|
313
363
|
console.error("Error in actionId watcher:", error);
|
|
314
364
|
}
|
|
315
|
-
}, {
|
|
316
|
-
|
|
365
|
+
}, {immediate: true});
|
|
366
|
+
|
|
367
|
+
const {addListener, removeLocalListenersWithEvent, notify} = useListenerService();
|
|
317
368
|
onMounted(() => {
|
|
318
369
|
props.listeners.forEach((listener) => {
|
|
319
370
|
addListener(listener, (data) => {
|
|
320
371
|
getItems(Number.parseInt(page.value) ?? null, null, filterValues.value);
|
|
321
372
|
});
|
|
322
373
|
});
|
|
323
|
-
})
|
|
374
|
+
})
|
|
324
375
|
onBeforeUnmount(() => {
|
|
325
376
|
props.listeners.forEach((listener) => {
|
|
326
377
|
removeLocalListenersWithEvent(listener);
|
|
327
378
|
});
|
|
328
|
-
})
|
|
379
|
+
})
|
|
329
380
|
const exportAction = async () => {
|
|
330
381
|
await exportItems(filterValues.value);
|
|
331
382
|
if (!hasExportErrors.value) {
|
|
332
|
-
window.open(exportUrl.value,
|
|
383
|
+
window.open(exportUrl.value, '_blank');
|
|
333
384
|
}
|
|
334
|
-
}
|
|
385
|
+
}
|
|
386
|
+
|
|
335
387
|
</script>
|
|
336
388
|
|
|
337
389
|
<template>
|
|
@@ -344,6 +396,7 @@ const exportAction = async () => {
|
|
|
344
396
|
:pending="listPending"
|
|
345
397
|
:create-action="createForm"
|
|
346
398
|
:update-action="updateForm"
|
|
399
|
+
:view-action="viewForm"
|
|
347
400
|
:delete-action="deleteForm"
|
|
348
401
|
:form-pending="formPending"
|
|
349
402
|
:export-action="exportAction"
|
|
@@ -376,6 +429,7 @@ const exportAction = async () => {
|
|
|
376
429
|
:items="items"
|
|
377
430
|
:pending="listPending"
|
|
378
431
|
:update-action="updateForm"
|
|
432
|
+
:view-action="viewForm"
|
|
379
433
|
:delete-action="deleteForm"
|
|
380
434
|
:form-pending="formPending"
|
|
381
435
|
>
|
|
@@ -405,6 +459,7 @@ const exportAction = async () => {
|
|
|
405
459
|
:create-title="createTitle"
|
|
406
460
|
:update-title="updateTitle"
|
|
407
461
|
:delete-title="deleteTitle"
|
|
462
|
+
:view-title="viewTitle"
|
|
408
463
|
:save-action="saveAction"
|
|
409
464
|
:full-screen="fullScreenDialog"
|
|
410
465
|
>
|
|
@@ -419,3 +474,7 @@ const exportAction = async () => {
|
|
|
419
474
|
|
|
420
475
|
</div>
|
|
421
476
|
</template>
|
|
477
|
+
|
|
478
|
+
<style scoped>
|
|
479
|
+
|
|
480
|
+
</style>
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
<script setup>
|
|
2
|
-
import { ref, computed, watch } from
|
|
2
|
+
import { ref, computed, watch } from 'vue';
|
|
3
|
+
|
|
3
4
|
import { useCrudApi } from "../composables/useCrudApi";
|
|
4
5
|
import { useCrudConverters } from "../composables/useCrudConverters";
|
|
5
6
|
import CrudErrorDisplay from "../components/CrudErrorDisplay.vue";
|
|
6
7
|
import CrudListLoader from "./CrudListLoader.vue";
|
|
7
8
|
import CrudUploadFieldSelection from "./CrudUploadFieldSelection.vue";
|
|
9
|
+
|
|
8
10
|
const { toBase64, getFileType } = useCrudConverters();
|
|
11
|
+
|
|
9
12
|
const props = defineProps({
|
|
10
13
|
replaceable: {
|
|
11
14
|
type: Boolean,
|
|
@@ -30,11 +33,11 @@ const props = defineProps({
|
|
|
30
33
|
},
|
|
31
34
|
mimeKey: {
|
|
32
35
|
type: String,
|
|
33
|
-
default:
|
|
36
|
+
default: 'mimeType'
|
|
34
37
|
},
|
|
35
38
|
fileNameKey: {
|
|
36
39
|
type: String,
|
|
37
|
-
default:
|
|
40
|
+
default: 'fileName'
|
|
38
41
|
},
|
|
39
42
|
customFilters: {
|
|
40
43
|
type: Object,
|
|
@@ -49,29 +52,37 @@ const props = defineProps({
|
|
|
49
52
|
}
|
|
50
53
|
}
|
|
51
54
|
});
|
|
55
|
+
|
|
52
56
|
const model = defineModel();
|
|
57
|
+
|
|
53
58
|
const dialog = ref(false);
|
|
54
59
|
const filesToUpload = ref([]);
|
|
55
60
|
const fileToUpload = ref(null);
|
|
56
61
|
const searchValue = ref(null);
|
|
62
|
+
|
|
63
|
+
// Temporary selection used within the dialog
|
|
57
64
|
const tempModel = ref(null);
|
|
58
|
-
|
|
65
|
+
|
|
66
|
+
const cloneModel = () => props.multiple ? [...(model.value || [])] : model.value;
|
|
67
|
+
|
|
59
68
|
const finish = () => {
|
|
60
69
|
model.value = props.multiple ? [...tempModel.value] : tempModel.value;
|
|
61
70
|
dialog.value = false;
|
|
62
71
|
};
|
|
72
|
+
|
|
63
73
|
const onSelectImage = (item) => {
|
|
64
74
|
if (props.multiple) {
|
|
65
75
|
if (!tempModel.value) tempModel.value = [];
|
|
66
76
|
if (!tempModel.value.includes(item)) {
|
|
67
77
|
tempModel.value.push(item);
|
|
68
78
|
} else {
|
|
69
|
-
tempModel.value = tempModel.value.filter(
|
|
79
|
+
tempModel.value = tempModel.value.filter(i => i !== item);
|
|
70
80
|
}
|
|
71
81
|
} else {
|
|
72
82
|
tempModel.value = tempModel.value === item ? null : item;
|
|
73
83
|
}
|
|
74
84
|
};
|
|
85
|
+
|
|
75
86
|
const {
|
|
76
87
|
createItem: createUpload,
|
|
77
88
|
item: completedUpload,
|
|
@@ -81,6 +92,7 @@ const {
|
|
|
81
92
|
hasFormErrors: hasUploadErrors,
|
|
82
93
|
formErrors: uploadErrors
|
|
83
94
|
} = useCrudApi(props.path);
|
|
95
|
+
|
|
84
96
|
const processUploads = async () => {
|
|
85
97
|
uploadsLoading.value = true;
|
|
86
98
|
if (props.multiple) {
|
|
@@ -110,12 +122,14 @@ const processUploads = async () => {
|
|
|
110
122
|
}
|
|
111
123
|
}
|
|
112
124
|
uploadsLoading.value = false;
|
|
125
|
+
|
|
113
126
|
if (props.multiple) {
|
|
114
127
|
filesToUpload.value = [];
|
|
115
128
|
} else {
|
|
116
129
|
fileToUpload.value = null;
|
|
117
130
|
}
|
|
118
131
|
};
|
|
132
|
+
|
|
119
133
|
const selectionFilters = computed(() => {
|
|
120
134
|
let filters = {};
|
|
121
135
|
if (hasSelection.value) {
|
|
@@ -123,18 +137,21 @@ const selectionFilters = computed(() => {
|
|
|
123
137
|
}
|
|
124
138
|
return filters;
|
|
125
139
|
});
|
|
140
|
+
|
|
126
141
|
const hasSelection = computed(() => {
|
|
127
142
|
if (props.multiple) {
|
|
128
143
|
return model.value && model.value.length > 0;
|
|
129
144
|
} else {
|
|
130
|
-
return model.value && model.value !==
|
|
145
|
+
return model.value && model.value !== '' && (model.value.length > 0 || model.value > 0);
|
|
131
146
|
}
|
|
132
147
|
});
|
|
148
|
+
|
|
133
149
|
watch(() => dialog.value, (val) => {
|
|
134
150
|
if (val) {
|
|
135
151
|
tempModel.value = cloneModel();
|
|
136
152
|
}
|
|
137
153
|
});
|
|
154
|
+
|
|
138
155
|
watch(() => filesToUpload.value, () => {
|
|
139
156
|
if (filesToUpload.value.length > 0) {
|
|
140
157
|
processUploads();
|
|
@@ -309,3 +326,8 @@ watch(() => fileToUpload.value, () => {
|
|
|
309
326
|
</v-dialog>
|
|
310
327
|
</div>
|
|
311
328
|
</template>
|
|
329
|
+
|
|
330
|
+
|
|
331
|
+
<style scoped>
|
|
332
|
+
|
|
333
|
+
</style>
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
<script setup>
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import {computed, defineModel} from 'vue';
|
|
3
|
+
import {useCrudConverters} from '../composables/useCrudConverters';
|
|
4
|
+
|
|
4
5
|
const {
|
|
5
6
|
formatStringDate,
|
|
6
7
|
uploadToUrl,
|
|
7
8
|
mimeTypeToMdiIcon
|
|
8
9
|
} = useCrudConverters();
|
|
10
|
+
|
|
9
11
|
const props = defineProps({
|
|
10
12
|
item: {
|
|
11
13
|
type: Object,
|
|
@@ -13,11 +15,11 @@ const props = defineProps({
|
|
|
13
15
|
},
|
|
14
16
|
mimeKey: {
|
|
15
17
|
type: String,
|
|
16
|
-
default:
|
|
18
|
+
default: 'mimeType'
|
|
17
19
|
},
|
|
18
20
|
fileNameKey: {
|
|
19
21
|
type: String,
|
|
20
|
-
default:
|
|
22
|
+
default: 'fileName'
|
|
21
23
|
},
|
|
22
24
|
hideTitle: {
|
|
23
25
|
type: Boolean,
|
|
@@ -29,10 +31,13 @@ const props = defineProps({
|
|
|
29
31
|
}
|
|
30
32
|
}
|
|
31
33
|
});
|
|
34
|
+
|
|
32
35
|
const copyUrl = () => {
|
|
33
36
|
navigator.clipboard.writeText(displayUrl.value);
|
|
34
37
|
};
|
|
38
|
+
|
|
35
39
|
const model = defineModel();
|
|
40
|
+
|
|
36
41
|
const selected = computed(() => {
|
|
37
42
|
if (props.item === null) {
|
|
38
43
|
return false;
|
|
@@ -42,55 +47,58 @@ const selected = computed(() => {
|
|
|
42
47
|
}
|
|
43
48
|
return model.value === props.item.id;
|
|
44
49
|
});
|
|
50
|
+
|
|
45
51
|
const isVideo = computed(() => {
|
|
46
52
|
if (props.item) {
|
|
47
|
-
return props.item[props.mimeKey].includes(
|
|
53
|
+
return props.item[props.mimeKey].includes('video');
|
|
48
54
|
}
|
|
49
55
|
return false;
|
|
50
56
|
});
|
|
51
57
|
const isImage = computed(() => {
|
|
52
58
|
if (props.item) {
|
|
53
|
-
return props.item[props.mimeKey].includes(
|
|
59
|
+
return props.item[props.mimeKey].includes('image');
|
|
54
60
|
}
|
|
55
61
|
return false;
|
|
56
62
|
});
|
|
63
|
+
|
|
57
64
|
const url = computed(() => {
|
|
58
65
|
if (props.item) {
|
|
59
|
-
return uploadToUrl(props.item, isImage.value ?
|
|
66
|
+
return uploadToUrl(props.item, isImage.value ? 'thumbnail' : 'original');
|
|
60
67
|
}
|
|
61
68
|
return null;
|
|
62
69
|
});
|
|
63
70
|
const displayUrl = computed(() => {
|
|
64
71
|
if (props.item) {
|
|
65
|
-
return uploadToUrl(props.item, isImage.value ?
|
|
72
|
+
return uploadToUrl(props.item, isImage.value ? 'thumbnail' : 'original');
|
|
66
73
|
}
|
|
67
74
|
return null;
|
|
68
75
|
});
|
|
69
76
|
const downloadUrl = computed(() => {
|
|
70
77
|
if (props.item) {
|
|
71
|
-
return uploadToUrl(props.item,
|
|
78
|
+
return uploadToUrl(props.item, 'original');
|
|
72
79
|
}
|
|
73
80
|
return null;
|
|
74
81
|
});
|
|
75
82
|
const largeUrl = computed(() => {
|
|
76
83
|
if (props.item) {
|
|
77
|
-
return uploadToUrl(props.item,
|
|
84
|
+
return uploadToUrl(props.item, 'large');
|
|
78
85
|
}
|
|
79
86
|
return null;
|
|
80
87
|
});
|
|
88
|
+
|
|
81
89
|
const containerClasses = computed(() => {
|
|
82
90
|
return {
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
}
|
|
91
|
+
'pa-1': true,
|
|
92
|
+
'position-relative': true,
|
|
93
|
+
'cursor': true,
|
|
94
|
+
'd-flex': true,
|
|
95
|
+
'border': selected.value,
|
|
96
|
+
'border-primary': selected.value,
|
|
97
|
+
'shadow' : selected.value,
|
|
98
|
+
}
|
|
91
99
|
});
|
|
92
|
-
</script>
|
|
93
100
|
|
|
101
|
+
</script>
|
|
94
102
|
<template>
|
|
95
103
|
<div :class="containerClasses">
|
|
96
104
|
<div class="d-flex justify-center flex-fill align-center" v-bind="props">
|
package/dist/types.d.mts
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import type { NuxtModule } from '@nuxt/schema'
|
|
2
2
|
|
|
3
|
-
import type { default as Module } from './module.
|
|
3
|
+
import type { default as Module } from './module.js'
|
|
4
4
|
|
|
5
5
|
export type ModuleOptions = typeof Module extends NuxtModule<infer O> ? Partial<O> : Record<string, any>
|
|
6
6
|
|
|
7
|
-
export { default } from './module.
|
|
8
|
-
|
|
9
|
-
export { type AtomCrudModuleOptions, type azureAdB2COptions } from './module.mjs'
|
|
7
|
+
export { type AtomCrudModuleOptions, type azureAdB2COptions, default } from './module.js'
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { NuxtModule } from '@nuxt/schema'
|
|
2
|
+
|
|
3
|
+
import type { default as Module } from './module'
|
|
4
|
+
|
|
5
|
+
export type ModuleOptions = typeof Module extends NuxtModule<infer O> ? Partial<O> : Record<string, any>
|
|
6
|
+
|
|
7
|
+
export { type AtomCrudModuleOptions, type azureAdB2COptions, default } from './module'
|
package/package.json
CHANGED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
declare const _default: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
2
|
-
export default _default;
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
declare const _default: import("vue").DefineComponent<{}, {
|
|
2
|
-
hint: string;
|
|
3
|
-
label: string;
|
|
4
|
-
placeholder: string;
|
|
5
|
-
countries: unknown[];
|
|
6
|
-
$props: any;
|
|
7
|
-
}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
8
|
-
export default _default;
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
declare const _default: __VLS_WithSlots<typeof __VLS_component, __VLS_Slots>;
|
|
2
|
-
export default _default;
|
|
3
|
-
type __VLS_WithSlots<T, S> = T & (new () => {
|
|
4
|
-
$slots: S;
|
|
5
|
-
});
|
|
6
|
-
declare const __VLS_component: import("vue").DefineComponent<{}, {
|
|
7
|
-
path: string;
|
|
8
|
-
multiple: boolean;
|
|
9
|
-
endpointDisplayKey: string;
|
|
10
|
-
endpointFilterKey: string;
|
|
11
|
-
endpointResponseKey: string;
|
|
12
|
-
additionalFilters: Record<string, any>;
|
|
13
|
-
disableUpdate: boolean;
|
|
14
|
-
createBtnText: string;
|
|
15
|
-
updateBtnText: string;
|
|
16
|
-
$props: any;
|
|
17
|
-
}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
18
|
-
type __VLS_Slots = {
|
|
19
|
-
items?: ((props: {
|
|
20
|
-
items: any;
|
|
21
|
-
}) => any) | undefined;
|
|
22
|
-
} & {
|
|
23
|
-
action?: ((props: {
|
|
24
|
-
action: any;
|
|
25
|
-
}) => any) | undefined;
|
|
26
|
-
} & {
|
|
27
|
-
dialogListTitle?: ((props: {
|
|
28
|
-
item: any;
|
|
29
|
-
}) => any) | undefined;
|
|
30
|
-
};
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
declare const _default: __VLS_WithSlots<typeof __VLS_component, __VLS_Slots>;
|
|
2
|
-
export default _default;
|
|
3
|
-
type __VLS_WithSlots<T, S> = T & (new () => {
|
|
4
|
-
$slots: S;
|
|
5
|
-
});
|
|
6
|
-
declare const __VLS_component: import("vue").DefineComponent<{}, {
|
|
7
|
-
$emit: (event: "confirm", ...args: any[]) => void;
|
|
8
|
-
message: string;
|
|
9
|
-
title: string;
|
|
10
|
-
cancelText: string;
|
|
11
|
-
confirmText: string;
|
|
12
|
-
$props: any;
|
|
13
|
-
}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
14
|
-
type __VLS_Slots = {
|
|
15
|
-
default?: ((props: {
|
|
16
|
-
click: any;
|
|
17
|
-
}) => any) | undefined;
|
|
18
|
-
};
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
declare const _default: import("vue").DefineComponent<{}, {
|
|
2
|
-
errorKey: string;
|
|
3
|
-
errors?: Record<string, any> | undefined;
|
|
4
|
-
$props: any;
|
|
5
|
-
}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
6
|
-
export default _default;
|