@adminforth/bulk-ai-flow 1.8.0 → 1.8.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/build.log +2 -2
- package/custom/ImageGenerationCarousel.vue +6 -6
- package/custom/VisionAction.vue +33 -73
- package/custom/VisionTable.vue +30 -24
- package/dist/custom/ImageGenerationCarousel.vue +6 -6
- package/dist/custom/VisionAction.vue +33 -73
- package/dist/custom/VisionTable.vue +30 -24
- package/dist/index.js +7 -3
- package/index.ts +6 -2
- package/package.json +1 -1
package/build.log
CHANGED
|
@@ -11,5 +11,5 @@ custom/package-lock.json
|
|
|
11
11
|
custom/package.json
|
|
12
12
|
custom/tsconfig.json
|
|
13
13
|
|
|
14
|
-
sent
|
|
15
|
-
total size is
|
|
14
|
+
sent 179,998 bytes received 134 bytes 360,264.00 bytes/sec
|
|
15
|
+
total size is 179,465 speedup is 1.00
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
|
|
2
2
|
<template>
|
|
3
3
|
<!-- Main modal -->
|
|
4
|
-
<div tabindex="-1" class="
|
|
5
|
-
<div class="relative p-4 w-
|
|
4
|
+
<div tabindex="-1" class="fixed inset-0 z-10 flex justify-center items-center dark:bg-gray-900/50 overflow-y-auto">
|
|
5
|
+
<div class="relative p-4 w-full max-w-[1600px] max-h-[90vh] ">
|
|
6
6
|
<!-- Modal content -->
|
|
7
7
|
<div class="relative bg-white rounded-lg shadow-xl dark:bg-gray-700">
|
|
8
8
|
<!-- Modal header -->
|
|
@@ -95,20 +95,20 @@
|
|
|
95
95
|
</div>
|
|
96
96
|
|
|
97
97
|
|
|
98
|
-
<div id="gallery" class="relative w-full" data-carousel="static">
|
|
98
|
+
<div id="gallery" class="relative w-full min-w-0" data-carousel="static">
|
|
99
99
|
<!-- Carousel wrapper -->
|
|
100
100
|
<div class="relative h-56 overflow-hidden rounded-lg md:h-[calc(100vh-400px)]">
|
|
101
101
|
<!-- Item 1 -->
|
|
102
102
|
<div
|
|
103
103
|
v-for="(img, index) in images"
|
|
104
104
|
:key="index"
|
|
105
|
+
class="flex items-center justify-center w-full h-full"
|
|
105
106
|
:class="[
|
|
106
|
-
index === 0 ? 'block' : 'hidden'
|
|
107
|
-
'duration-700 ease-in-out'
|
|
107
|
+
index === 0 ? 'block' : 'hidden'
|
|
108
108
|
]"
|
|
109
109
|
data-carousel-item
|
|
110
110
|
>
|
|
111
|
-
<img :src="img" class="
|
|
111
|
+
<img :src="img" class="max-w-full max-h-full object-contain"
|
|
112
112
|
:alt="`Generated image ${index + 1}`"
|
|
113
113
|
/>
|
|
114
114
|
</div>
|
package/custom/VisionAction.vue
CHANGED
|
@@ -5,61 +5,38 @@
|
|
|
5
5
|
</div>
|
|
6
6
|
<p class="text-justify max-h-[18px] truncate max-w-[60vw] md:max-w-none">{{ props.meta.actionName }}</p>
|
|
7
7
|
</div>
|
|
8
|
-
<Dialog
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
:carouselSaveImages="carouselSaveImages"
|
|
41
|
-
:carouselImageIndex="carouselImageIndex"
|
|
42
|
-
/>
|
|
43
|
-
</div>
|
|
44
|
-
<div class="flex w-full flex-col md:flex-row items-stretch md:items-end justify-end gap-3 md:gap-4">
|
|
45
|
-
<div class="h-full text-red-600 font-semibold flex items-center justify-center md:mb-2">
|
|
46
|
-
<p v-if="isError === true">{{ errorMessage }}</p>
|
|
47
|
-
</div>
|
|
48
|
-
<button type="button" class="w-full md:w-auto py-2.5 px-5 text-sm font-medium text-gray-900 focus:outline-none bg-white rounded-lg border border-gray-200 hover:bg-gray-100 hover:text-blue-700 focus:z-10 focus:ring-4 focus:ring-gray-100 dark:focus:ring-gray-700 dark:bg-gray-800 dark:text-gray-400 dark:border-gray-600 dark:hover:text-white dark:hover:bg-gray-700"
|
|
49
|
-
@click="closeDialog"
|
|
50
|
-
>
|
|
51
|
-
{{'Cancel'}}
|
|
52
|
-
</button>
|
|
53
|
-
<Button
|
|
54
|
-
class="w-full md:w-64"
|
|
55
|
-
@click="saveData"
|
|
56
|
-
:disabled="isLoading || checkedCount < 1 || isCriticalError || isFetchingRecords"
|
|
57
|
-
:loader="isLoading"
|
|
58
|
-
>
|
|
59
|
-
{{ checkedCount > 1 ? 'Save fields' : 'Save field' }}
|
|
60
|
-
</Button>
|
|
61
|
-
</div>
|
|
62
|
-
</div>
|
|
8
|
+
<Dialog
|
|
9
|
+
ref="confirmDialog"
|
|
10
|
+
header="Bulk AI Flow"
|
|
11
|
+
class="!max-w-full w-full lg:w-[1600px] !lg:max-w-[1600px]"
|
|
12
|
+
:buttons="[
|
|
13
|
+
{ label: checkedCount > 1 ? 'Save fields' : 'Save field', options: { disabled: isLoading || checkedCount < 1 || isCriticalError || isFetchingRecords, loader: isLoading, class: 'w-fit sm:w-40' }, onclick: (dialog) => { saveData(); dialog.hide(); } },
|
|
14
|
+
{ label: 'Cancel', onclick: (dialog) => dialog.hide() },
|
|
15
|
+
]"
|
|
16
|
+
>
|
|
17
|
+
<div class="bulk-vision-table flex flex-col items-center max-w-[1560px] md:max-h-[90vh] gap-3 md:gap-4 w-full h-full overflow-y-auto">
|
|
18
|
+
<div v-if="records && props.checkboxes.length" class="w-full overflow-x-auto">
|
|
19
|
+
<VisionTable
|
|
20
|
+
:checkbox="props.checkboxes"
|
|
21
|
+
:records="records"
|
|
22
|
+
:meta="props.meta"
|
|
23
|
+
:images="images"
|
|
24
|
+
:tableHeaders="tableHeaders"
|
|
25
|
+
:tableColumns="tableColumns"
|
|
26
|
+
:customFieldNames="customFieldNames"
|
|
27
|
+
:tableColumnsIndexes="tableColumnsIndexes"
|
|
28
|
+
:selected="selected"
|
|
29
|
+
:isAiResponseReceivedAnalize="isAiResponseReceivedAnalize"
|
|
30
|
+
:isAiResponseReceivedImage="isAiResponseReceivedImage"
|
|
31
|
+
:primaryKey="primaryKey"
|
|
32
|
+
:openGenerationCarousel="openGenerationCarousel"
|
|
33
|
+
@error="handleTableError"
|
|
34
|
+
:carouselSaveImages="carouselSaveImages"
|
|
35
|
+
:carouselImageIndex="carouselImageIndex"
|
|
36
|
+
/>
|
|
37
|
+
</div>
|
|
38
|
+
<div class="text-red-600 flex items-center w-full">
|
|
39
|
+
<p v-if="isError === true">{{ errorMessage }}</p>
|
|
63
40
|
</div>
|
|
64
41
|
</div>
|
|
65
42
|
</Dialog>
|
|
@@ -167,24 +144,6 @@ watch(selected, (val) => {
|
|
|
167
144
|
checkedCount.value = val.filter(item => item.isChecked === true).length;
|
|
168
145
|
}, { deep: true });
|
|
169
146
|
|
|
170
|
-
const closeDialog = () => {
|
|
171
|
-
confirmDialog.value.close();
|
|
172
|
-
isAiResponseReceivedAnalize.value = [];
|
|
173
|
-
isAiResponseReceivedImage.value = [];
|
|
174
|
-
|
|
175
|
-
records.value = [];
|
|
176
|
-
images.value = [];
|
|
177
|
-
selected.value = [];
|
|
178
|
-
tableColumns.value = [];
|
|
179
|
-
tableColumnsIndexes.value = [];
|
|
180
|
-
isError.value = false;
|
|
181
|
-
isCriticalError.value = false;
|
|
182
|
-
isImageGenerationError.value = false;
|
|
183
|
-
errorMessage.value = '';
|
|
184
|
-
carouselSaveImages.value = [];
|
|
185
|
-
carouselImageIndex.value = [];
|
|
186
|
-
}
|
|
187
|
-
|
|
188
147
|
function fillCarouselSaveImages() {
|
|
189
148
|
for (const item of selected.value) {
|
|
190
149
|
const tempItem: any = {};
|
|
@@ -200,6 +159,7 @@ function fillCarouselSaveImages() {
|
|
|
200
159
|
}
|
|
201
160
|
}
|
|
202
161
|
|
|
162
|
+
|
|
203
163
|
function formatLabel(str) {
|
|
204
164
|
return str
|
|
205
165
|
.split('_')
|
package/custom/VisionTable.vue
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div>
|
|
3
2
|
<Table
|
|
4
3
|
:columns="tableHeaders"
|
|
5
4
|
:data="tableColumns"
|
|
6
|
-
:pageSize="
|
|
5
|
+
:pageSize="6"
|
|
7
6
|
>
|
|
8
7
|
<!-- HEADER TEMPLATE -->
|
|
9
8
|
<template #header:checkboxes="{ item }">
|
|
@@ -28,18 +27,22 @@
|
|
|
28
27
|
@click="zoomImage(image)"
|
|
29
28
|
/>
|
|
30
29
|
</div>
|
|
30
|
+
</div>
|
|
31
|
+
<transition name="fade">
|
|
31
32
|
<div
|
|
32
33
|
v-if="zoomedImage"
|
|
33
34
|
class="fixed inset-0 z-50 flex items-center justify-center bg-black/60"
|
|
34
35
|
@click.self="closeZoom"
|
|
35
36
|
>
|
|
36
|
-
<
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
37
|
+
<transition name="zoom">
|
|
38
|
+
<img
|
|
39
|
+
v-if="zoomedImage"
|
|
40
|
+
:src="zoomedImage"
|
|
41
|
+
class="max-w-full max-h-full rounded-lg object-contain cursor-grab z-75"
|
|
42
|
+
/>
|
|
43
|
+
</transition>
|
|
41
44
|
</div>
|
|
42
|
-
</
|
|
45
|
+
</transition>
|
|
43
46
|
</div>
|
|
44
47
|
</template>
|
|
45
48
|
<!-- CUSTOM FIELD TEMPLATES -->
|
|
@@ -114,12 +117,10 @@
|
|
|
114
117
|
</div>
|
|
115
118
|
</template>
|
|
116
119
|
</Table>
|
|
117
|
-
</div>
|
|
118
120
|
</template>
|
|
119
121
|
|
|
120
122
|
<script lang="ts" setup>
|
|
121
|
-
import { ref
|
|
122
|
-
import mediumZoom from 'medium-zoom'
|
|
123
|
+
import { ref } from 'vue'
|
|
123
124
|
import { Select, Input, Textarea, Table, Checkbox, Skeleton, Toggle } from '@/afcl'
|
|
124
125
|
import GenerationCarousel from './ImageGenerationCarousel.vue'
|
|
125
126
|
|
|
@@ -143,7 +144,6 @@ const emit = defineEmits(['error']);
|
|
|
143
144
|
|
|
144
145
|
|
|
145
146
|
const zoomedImage = ref(null)
|
|
146
|
-
const zoomedImg = ref(null)
|
|
147
147
|
|
|
148
148
|
|
|
149
149
|
function zoomImage(img) {
|
|
@@ -154,17 +154,6 @@ function closeZoom() {
|
|
|
154
154
|
zoomedImage.value = null
|
|
155
155
|
}
|
|
156
156
|
|
|
157
|
-
watch(zoomedImage, async (val) => {
|
|
158
|
-
await nextTick()
|
|
159
|
-
if (val && zoomedImg.value) {
|
|
160
|
-
mediumZoom(zoomedImg.value, {
|
|
161
|
-
margin: 24,
|
|
162
|
-
background: 'rgba(0, 0, 0, 0.9)',
|
|
163
|
-
scrollOffset: 150
|
|
164
|
-
}).show()
|
|
165
|
-
}
|
|
166
|
-
})
|
|
167
|
-
|
|
168
157
|
function isInColumnEnum(key: string): boolean {
|
|
169
158
|
const colEnum = props.meta.columnEnums?.find(c => c.name === key);
|
|
170
159
|
if (!colEnum) {
|
|
@@ -201,4 +190,21 @@ function updateActiveIndex(newIndex: number, id: any, fieldName: string) {
|
|
|
201
190
|
props.carouselImageIndex[props.tableColumnsIndexes.findIndex(el => el[props.primaryKey] === id)][fieldName] = newIndex;
|
|
202
191
|
}
|
|
203
192
|
|
|
204
|
-
</script>
|
|
193
|
+
</script>
|
|
194
|
+
|
|
195
|
+
<style scoped>
|
|
196
|
+
.fade-enter-active, .fade-leave-active {
|
|
197
|
+
transition: opacity 0.2s ease;
|
|
198
|
+
}
|
|
199
|
+
.fade-enter-from, .fade-leave-to {
|
|
200
|
+
opacity: 0;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
.zoom-enter-active, .zoom-leave-active {
|
|
204
|
+
transition: transform 0.2s ease, opacity 0.2s ease;
|
|
205
|
+
}
|
|
206
|
+
.zoom-enter-from, .zoom-leave-to {
|
|
207
|
+
transform: scale(0.95);
|
|
208
|
+
opacity: 0;
|
|
209
|
+
}
|
|
210
|
+
</style>
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
|
|
2
2
|
<template>
|
|
3
3
|
<!-- Main modal -->
|
|
4
|
-
<div tabindex="-1" class="
|
|
5
|
-
<div class="relative p-4 w-
|
|
4
|
+
<div tabindex="-1" class="fixed inset-0 z-10 flex justify-center items-center dark:bg-gray-900/50 overflow-y-auto">
|
|
5
|
+
<div class="relative p-4 w-full max-w-[1600px] max-h-[90vh] ">
|
|
6
6
|
<!-- Modal content -->
|
|
7
7
|
<div class="relative bg-white rounded-lg shadow-xl dark:bg-gray-700">
|
|
8
8
|
<!-- Modal header -->
|
|
@@ -95,20 +95,20 @@
|
|
|
95
95
|
</div>
|
|
96
96
|
|
|
97
97
|
|
|
98
|
-
<div id="gallery" class="relative w-full" data-carousel="static">
|
|
98
|
+
<div id="gallery" class="relative w-full min-w-0" data-carousel="static">
|
|
99
99
|
<!-- Carousel wrapper -->
|
|
100
100
|
<div class="relative h-56 overflow-hidden rounded-lg md:h-[calc(100vh-400px)]">
|
|
101
101
|
<!-- Item 1 -->
|
|
102
102
|
<div
|
|
103
103
|
v-for="(img, index) in images"
|
|
104
104
|
:key="index"
|
|
105
|
+
class="flex items-center justify-center w-full h-full"
|
|
105
106
|
:class="[
|
|
106
|
-
index === 0 ? 'block' : 'hidden'
|
|
107
|
-
'duration-700 ease-in-out'
|
|
107
|
+
index === 0 ? 'block' : 'hidden'
|
|
108
108
|
]"
|
|
109
109
|
data-carousel-item
|
|
110
110
|
>
|
|
111
|
-
<img :src="img" class="
|
|
111
|
+
<img :src="img" class="max-w-full max-h-full object-contain"
|
|
112
112
|
:alt="`Generated image ${index + 1}`"
|
|
113
113
|
/>
|
|
114
114
|
</div>
|
|
@@ -5,61 +5,38 @@
|
|
|
5
5
|
</div>
|
|
6
6
|
<p class="text-justify max-h-[18px] truncate max-w-[60vw] md:max-w-none">{{ props.meta.actionName }}</p>
|
|
7
7
|
</div>
|
|
8
|
-
<Dialog
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
:carouselSaveImages="carouselSaveImages"
|
|
41
|
-
:carouselImageIndex="carouselImageIndex"
|
|
42
|
-
/>
|
|
43
|
-
</div>
|
|
44
|
-
<div class="flex w-full flex-col md:flex-row items-stretch md:items-end justify-end gap-3 md:gap-4">
|
|
45
|
-
<div class="h-full text-red-600 font-semibold flex items-center justify-center md:mb-2">
|
|
46
|
-
<p v-if="isError === true">{{ errorMessage }}</p>
|
|
47
|
-
</div>
|
|
48
|
-
<button type="button" class="w-full md:w-auto py-2.5 px-5 text-sm font-medium text-gray-900 focus:outline-none bg-white rounded-lg border border-gray-200 hover:bg-gray-100 hover:text-blue-700 focus:z-10 focus:ring-4 focus:ring-gray-100 dark:focus:ring-gray-700 dark:bg-gray-800 dark:text-gray-400 dark:border-gray-600 dark:hover:text-white dark:hover:bg-gray-700"
|
|
49
|
-
@click="closeDialog"
|
|
50
|
-
>
|
|
51
|
-
{{'Cancel'}}
|
|
52
|
-
</button>
|
|
53
|
-
<Button
|
|
54
|
-
class="w-full md:w-64"
|
|
55
|
-
@click="saveData"
|
|
56
|
-
:disabled="isLoading || checkedCount < 1 || isCriticalError || isFetchingRecords"
|
|
57
|
-
:loader="isLoading"
|
|
58
|
-
>
|
|
59
|
-
{{ checkedCount > 1 ? 'Save fields' : 'Save field' }}
|
|
60
|
-
</Button>
|
|
61
|
-
</div>
|
|
62
|
-
</div>
|
|
8
|
+
<Dialog
|
|
9
|
+
ref="confirmDialog"
|
|
10
|
+
header="Bulk AI Flow"
|
|
11
|
+
class="!max-w-full w-full lg:w-[1600px] !lg:max-w-[1600px]"
|
|
12
|
+
:buttons="[
|
|
13
|
+
{ label: checkedCount > 1 ? 'Save fields' : 'Save field', options: { disabled: isLoading || checkedCount < 1 || isCriticalError || isFetchingRecords, loader: isLoading, class: 'w-fit sm:w-40' }, onclick: (dialog) => { saveData(); dialog.hide(); } },
|
|
14
|
+
{ label: 'Cancel', onclick: (dialog) => dialog.hide() },
|
|
15
|
+
]"
|
|
16
|
+
>
|
|
17
|
+
<div class="bulk-vision-table flex flex-col items-center max-w-[1560px] md:max-h-[90vh] gap-3 md:gap-4 w-full h-full overflow-y-auto">
|
|
18
|
+
<div v-if="records && props.checkboxes.length" class="w-full overflow-x-auto">
|
|
19
|
+
<VisionTable
|
|
20
|
+
:checkbox="props.checkboxes"
|
|
21
|
+
:records="records"
|
|
22
|
+
:meta="props.meta"
|
|
23
|
+
:images="images"
|
|
24
|
+
:tableHeaders="tableHeaders"
|
|
25
|
+
:tableColumns="tableColumns"
|
|
26
|
+
:customFieldNames="customFieldNames"
|
|
27
|
+
:tableColumnsIndexes="tableColumnsIndexes"
|
|
28
|
+
:selected="selected"
|
|
29
|
+
:isAiResponseReceivedAnalize="isAiResponseReceivedAnalize"
|
|
30
|
+
:isAiResponseReceivedImage="isAiResponseReceivedImage"
|
|
31
|
+
:primaryKey="primaryKey"
|
|
32
|
+
:openGenerationCarousel="openGenerationCarousel"
|
|
33
|
+
@error="handleTableError"
|
|
34
|
+
:carouselSaveImages="carouselSaveImages"
|
|
35
|
+
:carouselImageIndex="carouselImageIndex"
|
|
36
|
+
/>
|
|
37
|
+
</div>
|
|
38
|
+
<div class="text-red-600 flex items-center w-full">
|
|
39
|
+
<p v-if="isError === true">{{ errorMessage }}</p>
|
|
63
40
|
</div>
|
|
64
41
|
</div>
|
|
65
42
|
</Dialog>
|
|
@@ -167,24 +144,6 @@ watch(selected, (val) => {
|
|
|
167
144
|
checkedCount.value = val.filter(item => item.isChecked === true).length;
|
|
168
145
|
}, { deep: true });
|
|
169
146
|
|
|
170
|
-
const closeDialog = () => {
|
|
171
|
-
confirmDialog.value.close();
|
|
172
|
-
isAiResponseReceivedAnalize.value = [];
|
|
173
|
-
isAiResponseReceivedImage.value = [];
|
|
174
|
-
|
|
175
|
-
records.value = [];
|
|
176
|
-
images.value = [];
|
|
177
|
-
selected.value = [];
|
|
178
|
-
tableColumns.value = [];
|
|
179
|
-
tableColumnsIndexes.value = [];
|
|
180
|
-
isError.value = false;
|
|
181
|
-
isCriticalError.value = false;
|
|
182
|
-
isImageGenerationError.value = false;
|
|
183
|
-
errorMessage.value = '';
|
|
184
|
-
carouselSaveImages.value = [];
|
|
185
|
-
carouselImageIndex.value = [];
|
|
186
|
-
}
|
|
187
|
-
|
|
188
147
|
function fillCarouselSaveImages() {
|
|
189
148
|
for (const item of selected.value) {
|
|
190
149
|
const tempItem: any = {};
|
|
@@ -200,6 +159,7 @@ function fillCarouselSaveImages() {
|
|
|
200
159
|
}
|
|
201
160
|
}
|
|
202
161
|
|
|
162
|
+
|
|
203
163
|
function formatLabel(str) {
|
|
204
164
|
return str
|
|
205
165
|
.split('_')
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div>
|
|
3
2
|
<Table
|
|
4
3
|
:columns="tableHeaders"
|
|
5
4
|
:data="tableColumns"
|
|
6
|
-
:pageSize="
|
|
5
|
+
:pageSize="6"
|
|
7
6
|
>
|
|
8
7
|
<!-- HEADER TEMPLATE -->
|
|
9
8
|
<template #header:checkboxes="{ item }">
|
|
@@ -28,18 +27,22 @@
|
|
|
28
27
|
@click="zoomImage(image)"
|
|
29
28
|
/>
|
|
30
29
|
</div>
|
|
30
|
+
</div>
|
|
31
|
+
<transition name="fade">
|
|
31
32
|
<div
|
|
32
33
|
v-if="zoomedImage"
|
|
33
34
|
class="fixed inset-0 z-50 flex items-center justify-center bg-black/60"
|
|
34
35
|
@click.self="closeZoom"
|
|
35
36
|
>
|
|
36
|
-
<
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
37
|
+
<transition name="zoom">
|
|
38
|
+
<img
|
|
39
|
+
v-if="zoomedImage"
|
|
40
|
+
:src="zoomedImage"
|
|
41
|
+
class="max-w-full max-h-full rounded-lg object-contain cursor-grab z-75"
|
|
42
|
+
/>
|
|
43
|
+
</transition>
|
|
41
44
|
</div>
|
|
42
|
-
</
|
|
45
|
+
</transition>
|
|
43
46
|
</div>
|
|
44
47
|
</template>
|
|
45
48
|
<!-- CUSTOM FIELD TEMPLATES -->
|
|
@@ -114,12 +117,10 @@
|
|
|
114
117
|
</div>
|
|
115
118
|
</template>
|
|
116
119
|
</Table>
|
|
117
|
-
</div>
|
|
118
120
|
</template>
|
|
119
121
|
|
|
120
122
|
<script lang="ts" setup>
|
|
121
|
-
import { ref
|
|
122
|
-
import mediumZoom from 'medium-zoom'
|
|
123
|
+
import { ref } from 'vue'
|
|
123
124
|
import { Select, Input, Textarea, Table, Checkbox, Skeleton, Toggle } from '@/afcl'
|
|
124
125
|
import GenerationCarousel from './ImageGenerationCarousel.vue'
|
|
125
126
|
|
|
@@ -143,7 +144,6 @@ const emit = defineEmits(['error']);
|
|
|
143
144
|
|
|
144
145
|
|
|
145
146
|
const zoomedImage = ref(null)
|
|
146
|
-
const zoomedImg = ref(null)
|
|
147
147
|
|
|
148
148
|
|
|
149
149
|
function zoomImage(img) {
|
|
@@ -154,17 +154,6 @@ function closeZoom() {
|
|
|
154
154
|
zoomedImage.value = null
|
|
155
155
|
}
|
|
156
156
|
|
|
157
|
-
watch(zoomedImage, async (val) => {
|
|
158
|
-
await nextTick()
|
|
159
|
-
if (val && zoomedImg.value) {
|
|
160
|
-
mediumZoom(zoomedImg.value, {
|
|
161
|
-
margin: 24,
|
|
162
|
-
background: 'rgba(0, 0, 0, 0.9)',
|
|
163
|
-
scrollOffset: 150
|
|
164
|
-
}).show()
|
|
165
|
-
}
|
|
166
|
-
})
|
|
167
|
-
|
|
168
157
|
function isInColumnEnum(key: string): boolean {
|
|
169
158
|
const colEnum = props.meta.columnEnums?.find(c => c.name === key);
|
|
170
159
|
if (!colEnum) {
|
|
@@ -201,4 +190,21 @@ function updateActiveIndex(newIndex: number, id: any, fieldName: string) {
|
|
|
201
190
|
props.carouselImageIndex[props.tableColumnsIndexes.findIndex(el => el[props.primaryKey] === id)][fieldName] = newIndex;
|
|
202
191
|
}
|
|
203
192
|
|
|
204
|
-
</script>
|
|
193
|
+
</script>
|
|
194
|
+
|
|
195
|
+
<style scoped>
|
|
196
|
+
.fade-enter-active, .fade-leave-active {
|
|
197
|
+
transition: opacity 0.2s ease;
|
|
198
|
+
}
|
|
199
|
+
.fade-enter-from, .fade-leave-to {
|
|
200
|
+
opacity: 0;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
.zoom-enter-active, .zoom-leave-active {
|
|
204
|
+
transition: transform 0.2s ease, opacity 0.2s ease;
|
|
205
|
+
}
|
|
206
|
+
.zoom-enter-from, .zoom-leave-to {
|
|
207
|
+
transform: scale(0.95);
|
|
208
|
+
opacity: 0;
|
|
209
|
+
}
|
|
210
|
+
</style>
|
package/dist/index.js
CHANGED
|
@@ -96,9 +96,7 @@ export default class BulkAiFlowPlugin extends AdminForthPlugin {
|
|
|
96
96
|
for (const [key, value] of Object.entries(this.options.generateImages)) {
|
|
97
97
|
const plugin = adminforth.activatedPlugins.find(p => p.resourceConfig.resourceId === this.resourceConfig.resourceId &&
|
|
98
98
|
p.pluginOptions.pathColumnName === key);
|
|
99
|
-
|
|
100
|
-
outputImagesPluginInstanceIds[key] = plugin.pluginInstanceId;
|
|
101
|
-
}
|
|
99
|
+
outputImagesPluginInstanceIds[key] = plugin.pluginInstanceId;
|
|
102
100
|
}
|
|
103
101
|
}
|
|
104
102
|
const outputFields = Object.assign(Object.assign(Object.assign({}, this.options.fillFieldsFromImages), this.options.fillPlainFields), (this.options.generateImages || {}));
|
|
@@ -174,6 +172,12 @@ export default class BulkAiFlowPlugin extends AdminForthPlugin {
|
|
|
174
172
|
if (!plugin) {
|
|
175
173
|
throw new Error(`Plugin for attachment field '${key}' not found in resource '${this.resourceConfig.resourceId}', please check if Upload Plugin is installed on the field ${key}`);
|
|
176
174
|
}
|
|
175
|
+
if (!plugin.pluginOptions || !plugin.pluginOptions.storageAdapter) {
|
|
176
|
+
throw new Error(`Upload Plugin for attachment field '${key}' in resource '${this.resourceConfig.resourceId}' is missing a storageAdapter configuration.`);
|
|
177
|
+
}
|
|
178
|
+
if (typeof plugin.pluginOptions.storageAdapter.objectCanBeAccesedPublicly !== 'function') {
|
|
179
|
+
throw new Error(`Upload Plugin for attachment field '${key}' in resource '${this.resourceConfig.resourceId}' uses a storage adapter without 'objectCanBeAccesedPublicly' method.`);
|
|
180
|
+
}
|
|
177
181
|
if (!plugin.pluginOptions.storageAdapter.objectCanBeAccesedPublicly()) {
|
|
178
182
|
throw new Error(`Upload Plugin for attachment field '${key}' in resource '${this.resourceConfig.resourceId}'
|
|
179
183
|
uses adapter which is not configured to store objects in public way, so it will produce only signed private URLs which can not be used in HTML text of blog posts.
|
package/index.ts
CHANGED
|
@@ -112,9 +112,7 @@ export default class BulkAiFlowPlugin extends AdminForthPlugin {
|
|
|
112
112
|
p.resourceConfig!.resourceId === this.resourceConfig.resourceId &&
|
|
113
113
|
p.pluginOptions.pathColumnName === key
|
|
114
114
|
);
|
|
115
|
-
if (plugin && plugin.pluginOptions.storageAdapter.objectCanBeAccesedPublicly()) {
|
|
116
115
|
outputImagesPluginInstanceIds[key] = plugin.pluginInstanceId;
|
|
117
|
-
}
|
|
118
116
|
}
|
|
119
117
|
}
|
|
120
118
|
|
|
@@ -203,6 +201,12 @@ export default class BulkAiFlowPlugin extends AdminForthPlugin {
|
|
|
203
201
|
if (!plugin) {
|
|
204
202
|
throw new Error(`Plugin for attachment field '${key}' not found in resource '${this.resourceConfig.resourceId}', please check if Upload Plugin is installed on the field ${key}`);
|
|
205
203
|
}
|
|
204
|
+
if (!plugin.pluginOptions || !plugin.pluginOptions.storageAdapter) {
|
|
205
|
+
throw new Error(`Upload Plugin for attachment field '${key}' in resource '${this.resourceConfig.resourceId}' is missing a storageAdapter configuration.`);
|
|
206
|
+
}
|
|
207
|
+
if (typeof plugin.pluginOptions.storageAdapter.objectCanBeAccesedPublicly !== 'function') {
|
|
208
|
+
throw new Error(`Upload Plugin for attachment field '${key}' in resource '${this.resourceConfig.resourceId}' uses a storage adapter without 'objectCanBeAccesedPublicly' method.`);
|
|
209
|
+
}
|
|
206
210
|
if (!plugin.pluginOptions.storageAdapter.objectCanBeAccesedPublicly()) {
|
|
207
211
|
throw new Error(`Upload Plugin for attachment field '${key}' in resource '${this.resourceConfig.resourceId}'
|
|
208
212
|
uses adapter which is not configured to store objects in public way, so it will produce only signed private URLs which can not be used in HTML text of blog posts.
|