@drax/crud-vue 3.25.0 → 3.26.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "3.25.0",
6
+ "version": "3.26.0",
7
7
  "type": "module",
8
8
  "main": "./src/index.ts",
9
9
  "module": "./src/index.ts",
@@ -24,10 +24,10 @@
24
24
  "format": "prettier --write src/"
25
25
  },
26
26
  "dependencies": {
27
- "@drax/common-front": "^3.25.0",
27
+ "@drax/common-front": "^3.25.1",
28
28
  "@drax/crud-front": "^3.21.0",
29
- "@drax/crud-share": "^3.21.0",
30
- "@drax/media-vue": "^3.25.0"
29
+ "@drax/crud-share": "^3.26.0",
30
+ "@drax/media-vue": "^3.26.0"
31
31
  },
32
32
  "peerDependencies": {
33
33
  "pinia": "^3.0.4",
@@ -50,5 +50,5 @@
50
50
  "vue-tsc": "^3.2.4",
51
51
  "vuetify": "^3.11.8"
52
52
  },
53
- "gitHead": "e5a5d6869b9446e15e2942fdd5386207bf2867b2"
53
+ "gitHead": "482f91f51a9e783ac9131f557ace113f3b3404fa"
54
54
  }
@@ -265,7 +265,7 @@ async function generateSuggestions() {
265
265
  },
266
266
  currentValues: currentForm.value,
267
267
  fields: editableFields.value.map(normalizeField),
268
- }, {}) as CrudAiResponse
268
+ }, {timeout: 360000}) as CrudAiResponse
269
269
  } catch (e: any) {
270
270
  error.value = e?.message || 'No se pudo obtener una sugerencia de IA'
271
271
  response.value = null
@@ -10,7 +10,7 @@ import {useDisplay} from "vuetify"
10
10
  const {t, te} = useI18n()
11
11
  const valueModel = defineModel({type: Array, default: () => []});
12
12
 
13
- const {field, entity} = defineProps({
13
+ const {field, entity, readonly} = defineProps({
14
14
  entity: {type: Object as PropType<IEntityCrud>, required: true},
15
15
  field: {type: Object as PropType<IEntityCrudField>, required: true},
16
16
  readonly: {type: Boolean, default: false},
@@ -45,15 +45,22 @@ function addItem() {
45
45
  const item = newItem()
46
46
  valueModel.value.push(item);
47
47
  menuSelect(item, valueModel.value.length - 1)
48
+ emit('updateValue')
48
49
  }
49
50
 
50
51
  function removeItem(index: number) {
52
+ const removedItem = valueModel.value[index]
53
+
51
54
  if (indexSelected.value === index) {
52
- itemSelected.value = undefined
53
- indexSelected.value = undefined
55
+ valueModel.value.splice(index, 1);
56
+ syncSelectedItem(undefined)
57
+ emit('updateValue')
58
+ return
54
59
  }
55
- valueModel.value.splice(index, 1);
56
60
 
61
+ valueModel.value.splice(index, 1);
62
+ syncSelectedItem(itemSelected.value === removedItem ? undefined : itemSelected.value)
63
+ emit('updateValue')
57
64
  }
58
65
 
59
66
  const label = computed(() => {
@@ -81,10 +88,87 @@ const menuMaxHeight = computed(() => {
81
88
  return field.menuMaxHeight || '300px'
82
89
  })
83
90
 
84
- defineEmits(['updateValue'])
91
+ const emit = defineEmits(['updateValue'])
85
92
 
86
93
  const {xs} = useDisplay()
87
94
 
95
+ const dragIndex = ref<number | null>(null)
96
+ const dragOverIndex = ref<number | null>(null)
97
+
98
+ const isSortable = computed(() => {
99
+ return !readonly
100
+ })
101
+
102
+ function getItemTitle(index: number) {
103
+ //@ts-ignore
104
+ return valueModel.value[index]?.[field?.arrayObjectShowField ?? Object.keys(valueModel.value[index] as any)[0]]
105
+ }
106
+
107
+ function syncSelectedItem(item?: any) {
108
+ if (!item) {
109
+ itemSelected.value = undefined
110
+ indexSelected.value = undefined
111
+ return
112
+ }
113
+
114
+ const nextIndex = valueModel.value.findIndex(currentItem => currentItem === item)
115
+
116
+ if (nextIndex === -1) {
117
+ itemSelected.value = undefined
118
+ indexSelected.value = undefined
119
+ return
120
+ }
121
+
122
+ itemSelected.value = item
123
+ indexSelected.value = nextIndex
124
+ }
125
+
126
+ function reorderItems(fromIndex: number, toIndex: number) {
127
+ if (fromIndex === toIndex) {
128
+ return
129
+ }
130
+
131
+ const movedItem = valueModel.value[fromIndex]
132
+ const selectedItem = itemSelected.value
133
+
134
+ valueModel.value.splice(fromIndex, 1)
135
+ valueModel.value.splice(toIndex, 0, movedItem)
136
+
137
+ syncSelectedItem(selectedItem ?? movedItem)
138
+ emit('updateValue')
139
+ }
140
+
141
+ function onDragStart(index: number) {
142
+ if (!isSortable.value) {
143
+ return
144
+ }
145
+
146
+ dragIndex.value = index
147
+ dragOverIndex.value = index
148
+ }
149
+
150
+ function onDragEnter(index: number) {
151
+ if (!isSortable.value || dragIndex.value === null) {
152
+ return
153
+ }
154
+
155
+ dragOverIndex.value = index
156
+ }
157
+
158
+ function onDrop(index: number) {
159
+ if (!isSortable.value || dragIndex.value === null) {
160
+ return
161
+ }
162
+
163
+ reorderItems(dragIndex.value, index)
164
+ clearDragState()
165
+ }
166
+
167
+ function clearDragState() {
168
+ dragIndex.value = null
169
+ dragOverIndex.value = null
170
+ }
171
+
88
172
  </script>
89
173
 
90
174
  <template>
@@ -95,14 +179,19 @@ const {xs} = useDisplay()
95
179
  <!--ACCORDION-->
96
180
  <v-card-text v-if="field.arrayObjectUI === 'accordion' || xs">
97
181
  <v-expansion-panels>
98
- <v-expansion-panel v-for="(item,index) in valueModel" :key="index">
182
+ <v-expansion-panel v-for="(item,index) in valueModel" :key="index"
183
+ :class="{'crud-form-list--drag-over': dragOverIndex === index}"
184
+ :draggable="isSortable"
185
+ @dragstart="onDragStart(index)"
186
+ @dragenter.prevent="onDragEnter(index)"
187
+ @dragover.prevent
188
+ @drop.prevent="onDrop(index)"
189
+ @dragend="clearDragState">
99
190
 
100
191
  <v-expansion-panel-title>
192
+ <v-icon v-if="isSortable" class="mr-2" size="small">mdi-drag</v-icon>
101
193
  <v-chip class="mr-2" :color="hasError(index) ? 'red':'teal'">{{ index }}</v-chip>
102
- {{
103
- //@ts-ignore
104
- valueModel[index][field?.arrayObjectShowField ?? Object.keys(valueModel[index] as any)[0]]
105
- }}
194
+ {{ getItemTitle(index) }}
106
195
 
107
196
  <template v-slot:actions="{expanded}">
108
197
  <v-icon>{{ expanded ? "mdi-menu-down" : "mdi-menu-up" }}</v-icon>
@@ -169,12 +258,16 @@ const {xs} = useDisplay()
169
258
 
170
259
  <v-chip v-for="(item,index) in valueModel" :key="index"
171
260
  :value="index" @click="menuSelect(item, index)"
261
+ :draggable="isSortable"
262
+ :class="{'crud-form-list--drag-over': dragOverIndex === index}"
263
+ @dragstart="onDragStart(index)"
264
+ @dragenter.prevent="onDragEnter(index)"
265
+ @dragover.prevent
266
+ @drop.prevent="onDrop(index)"
267
+ @dragend="clearDragState"
172
268
  label class="pr-0" :color="indexSelected === index ? 'primary' : ''"
173
269
  >
174
- {{
175
- //@ts-ignore
176
- valueModel[index][field?.arrayObjectShowField ?? Object.keys(valueModel[index] as any)[0]] || (index)
177
- }}
270
+ {{ getItemTitle(index) || (index) }}
178
271
 
179
272
  <template v-slot:append>
180
273
  <v-btn variant="text" class="ml-2" density="compact"
@@ -227,9 +320,17 @@ const {xs} = useDisplay()
227
320
  <v-card-text>
228
321
  <v-list v-model="itemSelected" :style="{ maxHeight: menuMaxHeight, overflowY: 'auto' }">
229
322
  <v-list-item v-for="(item,index) in valueModel" :key="index" rounded="shaped"
323
+ :class="{'crud-form-list--drag-over': dragOverIndex === index}"
230
324
  :value="item" @click="menuSelect(item, index)"
325
+ :draggable="isSortable"
326
+ @dragstart="onDragStart(index)"
327
+ @dragenter.prevent="onDragEnter(index)"
328
+ @dragover.prevent
329
+ @drop.prevent="onDrop(index)"
330
+ @dragend="clearDragState"
231
331
  >
232
332
  <template v-slot:append>
333
+ <v-icon v-if="isSortable" size="small" class="mr-2">mdi-drag</v-icon>
233
334
  <v-btn size="x-small" variant="text" color="red" icon="mdi-delete"
234
335
  @click="removeItem(index)"
235
336
 
@@ -237,10 +338,7 @@ const {xs} = useDisplay()
237
338
  </template>
238
339
  <v-list-item-title>
239
340
  <v-chip class="mr-2" :color="hasError(index) ? 'red':'teal'">{{ index }}</v-chip>
240
- {{
241
- //@ts-ignore
242
- valueModel[index][field?.arrayObjectShowField ?? Object.keys(valueModel[index] as any)[0]]
243
- }}
341
+ {{ getItemTitle(index) }}
244
342
  </v-list-item-title>
245
343
  </v-list-item>
246
344
 
@@ -287,5 +385,8 @@ const {xs} = useDisplay()
287
385
  </template>
288
386
 
289
387
  <style scoped>
290
-
388
+ .crud-form-list--drag-over {
389
+ outline: 2px dashed rgb(var(--v-theme-primary));
390
+ outline-offset: 2px;
391
+ }
291
392
  </style>