@bildvitta/quasar-ui-asteroid 3.17.0-beta.2 → 3.17.0-beta.21

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.
Files changed (51) hide show
  1. package/package.json +2 -2
  2. package/src/assets/sounds/nave-notification.mp3 +0 -0
  3. package/src/components/actions/QasActions.vue +1 -1
  4. package/src/components/app-menu/QasAppMenu.vue +6 -1
  5. package/src/components/avatar/QasAvatar.vue +7 -8
  6. package/src/components/board-generator/QasBoardGenerator.vue +407 -40
  7. package/src/components/board-generator/QasBoardGenerator.yml +53 -12
  8. package/src/components/btn-dropdown/QasBtnDropdown.vue +14 -1
  9. package/src/components/card/QasCard.vue +13 -4
  10. package/src/components/chart-view/QasChartView.vue +44 -20
  11. package/src/components/chart-view/QasChartView.yml +10 -0
  12. package/src/components/checkbox/QasCheckbox.vue +30 -9
  13. package/src/components/checkbox/QasCheckbox.yml +5 -0
  14. package/src/components/copy/QasCopy.vue +12 -2
  15. package/src/components/copy/QasCopy.yml +8 -0
  16. package/src/components/date-time-input/QasDateTimeInput.vue +1 -1
  17. package/src/components/dialog/QasDialog.vue +3 -3
  18. package/src/components/expansion-item/QasExpansionItem.vue +120 -34
  19. package/src/components/expansion-item/QasExpansionItem.yml +38 -5
  20. package/src/components/filters/QasFilters.vue +1 -1
  21. package/src/components/filters/private/PvFiltersButton.vue +1 -1
  22. package/src/components/form-generator/QasFormGenerator.vue +39 -27
  23. package/src/components/form-generator/QasFormGenerator.yml +3 -0
  24. package/src/components/grabbable/QasGrabbable.vue +14 -6
  25. package/src/components/grabbable/QasGrabbable.yml +4 -0
  26. package/src/components/grid-generator/QasGridGenerator.vue +67 -34
  27. package/src/components/grid-generator/QasGridGenerator.yml +15 -0
  28. package/src/components/header/QasHeader.vue +58 -12
  29. package/src/components/header/QasHeader.yml +5 -0
  30. package/src/components/infinite-scroll/QasInfiniteScroll.vue +16 -17
  31. package/src/components/infinite-scroll/QasInfiniteScroll.yml +7 -0
  32. package/src/components/list-items/QasListItems.vue +28 -4
  33. package/src/components/list-items/QasListItems.yml +10 -0
  34. package/src/components/list-view/QasListView.vue +17 -5
  35. package/src/components/list-view/QasListView.yml +9 -0
  36. package/src/components/nested-fields/QasNestedFields.vue +91 -36
  37. package/src/components/nested-fields/QasNestedFields.yml +23 -0
  38. package/src/components/radio/QasRadio.vue +24 -5
  39. package/src/components/radio/QasRadio.yml +6 -0
  40. package/src/components/select/QasSelect.vue +129 -5
  41. package/src/components/select/QasSelect.yml +11 -0
  42. package/src/components/stepper-form-view/QasStepperFormView.yml +1 -1
  43. package/src/components/table-generator/QasTableGenerator.vue +10 -1
  44. package/src/components/text-truncate/QasTextTruncate.vue +11 -4
  45. package/src/components/text-truncate/QasTextTruncate.yml +4 -0
  46. package/src/composables/private/use-generator.js +3 -9
  47. package/src/composables/use-notifications.js +14 -0
  48. package/src/css/components/field.scss +13 -6
  49. package/src/css/components/item.scss +5 -1
  50. package/src/enums/Spacing.js +33 -0
  51. package/src/helpers/set-scroll-on-grab.js +9 -1
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@bildvitta/quasar-ui-asteroid",
3
3
  "description": "Asteroid",
4
- "version": "3.17.0-beta.2",
4
+ "version": "3.17.0-beta.21",
5
5
  "author": "Bild & Vitta <systemteam@bild.com.br>",
6
6
  "license": "MIT",
7
7
  "main": "dist/asteroid.cjs.min.js",
@@ -54,7 +54,7 @@
54
54
  "lodash-es": "^4.17.21",
55
55
  "pica": "^9.0.1",
56
56
  "signature_pad": "^4.1.5",
57
- "sortablejs": "^1.15.0"
57
+ "sortablejs": "^1.15.3"
58
58
  },
59
59
  "browserslist": [
60
60
  "defaults"
@@ -72,7 +72,7 @@ const classes = computed(() => {
72
72
  const columnClasses = computed(() => {
73
73
  if (props.useEqualWidth) return 'col-12 col-sm-6'
74
74
 
75
- return props.useFullWidth ? 'col-12' : 'col-12 col-sm-auto'
75
+ return props.useFullWidth ? 'full-width' : 'col-12 col-sm-auto'
76
76
  })
77
77
 
78
78
  const hasPrimarySlot = computed(() => !!slots.primary)
@@ -58,7 +58,9 @@
58
58
  </div>
59
59
  </div>
60
60
 
61
- <q-item v-else :key="index" :active="isActive(menuItem)" active-class="q-router-link--active" class="qas-app-menu__item" :to="getRouterRedirect(menuItem)">
61
+ <!-- quando tem children vazio, não deve mostrar label do item, e a label do item
62
+ não tem "to", então validar se tem "to" para mostrar o item -->
63
+ <q-item v-else-if="menuItem.to" :key="index" :active="isActive(menuItem)" active-class="q-router-link--active" class="qas-app-menu__item" :to="getRouterRedirect(menuItem)">
62
64
  <q-item-section v-if="menuItem.icon" avatar>
63
65
  <q-icon :name="menuItem.icon" />
64
66
  </q-item-section>
@@ -276,6 +278,9 @@ function hasSeparator (index) {
276
278
  }
277
279
 
278
280
  function isActive ({ to }) {
281
+ // quando o children vem vazio, "to" é "undefined", então precisa ser feito esta trativa.
282
+ if (!to) return false
283
+
279
284
  const currentPath = getNormalizedPath(router.currentRoute.value.path)
280
285
  const itemPath = typeof to === 'string' ? getNormalizedPath(to) : getPathFromObject(to)
281
286
 
@@ -19,12 +19,7 @@ defineOptions({
19
19
  const props = defineProps({
20
20
  color: {
21
21
  type: String,
22
- default: AvatarColors.Primary,
23
- validator: value => {
24
- const availableColors = Object.values(AvatarColors)
25
-
26
- return availableColors.includes(value)
27
- }
22
+ default: AvatarColors.Primary
28
23
  },
29
24
 
30
25
  size: {
@@ -42,6 +37,11 @@ const props = defineProps({
42
37
  type: String
43
38
  },
44
39
 
40
+ textColor: {
41
+ default: '',
42
+ type: String
43
+ },
44
+
45
45
  title: {
46
46
  default: '',
47
47
  type: String
@@ -62,7 +62,6 @@ const attributes = computed(() => {
62
62
  rounded,
63
63
  square,
64
64
  fontSize,
65
- textColor,
66
65
  ...attributes
67
66
  } = attrs
68
67
 
@@ -76,7 +75,7 @@ const attributes = computed(() => {
76
75
  return {
77
76
  size: props.size,
78
77
  color: props.color,
79
- textColor: colors[props.color],
78
+ textColor: colors[props.color] || props.textColor,
80
79
  ...attributes
81
80
  }
82
81
  })
@@ -1,39 +1,40 @@
1
1
  <template>
2
- <qas-grabbable class="qas-board-generator" use-scroll-bar>
2
+ <qas-grabbable class="qas-board-generator" v-bind="grabbableProps">
3
3
  <div class="no-wrap q-col-gutter-sm q-px-xl row">
4
4
  <div v-for="(header, index) in headers" :key="index" class="q-mr-sm">
5
- <qas-box class="q-mb-md">
6
- <slot :fields="getFieldsByHeader(header)" :header="header" name="header-column" />
5
+ <qas-box class="q-mb-md" v-bind="headerBoxProps">
6
+ <slot :fields="getFieldsByHeader(header)" :header="header" :index="index" name="header-column" />
7
7
  </qas-box>
8
8
 
9
- <div ref="columnContainer" class="qas-board-generator__column secondary-scroll" :style="containerStyle">
10
- <slot v-for="item in getItemsByHeader(header)" :fields="getFieldsByHeader(header)" :item="item" name="column-item" />
9
+ <div ref="columnContainer" class="qas-board-generator__column secondary-scroll" :data-header-key="getKeyByHeader(header)" :style="containerStyle">
10
+ <div v-for="item in getItemsByHeader(header)" :id="item[props.itemIdKey]" :key="item[props.itemIdKey]" class="qas-board-generator__item">
11
+ <slot :column-index="index" :fields="getFieldsByHeader(header)" :item="item" name="column-item" />
12
+ </div>
11
13
 
12
- <div class="full-width justify-center q-mb-md q-mt-sm row">
14
+ <div class="full-width justify-center row">
13
15
  <qas-btn v-if="hasSeeMore(header)" icon="sym_r_add" label="Ver mais" :use-label-on-small-screen="false" variant="tertiary" @click="fetchColumn(header)" />
14
16
 
15
- <q-spinner v-if="columnsLoading[getKeyByHeader(header)]" color="grey-4" size="3em" />
16
-
17
- <qas-empty-result-text v-if="hasEmptyResultText(header)" />
17
+ <q-spinner v-if="columnsLoading[getKeyByHeader(header)]" class="q-mb-md" color="grey-4" size="3em" />
18
18
  </div>
19
+
20
+ <qas-empty-result-text v-if="hasEmptyResultText(header)" />
19
21
  </div>
20
22
  </div>
21
23
  </div>
24
+
25
+ <qas-dialog v-model="showConfirmDialog" v-bind="defaultConfirmDialogProps" />
22
26
  </qas-grabbable>
23
27
  </template>
24
28
 
25
29
  <script setup>
26
- import { ref, watch, computed, onMounted, markRaw, inject } from 'vue'
27
- import promiseHandler from '../../helpers/promise-handler'
30
+ import QasDialog from '../dialog/QasDialog.vue'
28
31
 
29
- defineOptions({ name: 'QasBoardGenerator' })
32
+ import { ref, watch, computed, onUnmounted, markRaw, inject, onMounted } from 'vue'
33
+ import promiseHandler from '../../helpers/promise-handler'
30
34
 
31
- const columnContainer = ref(null)
32
- const columnsPagination = ref({})
33
- const columnsLoading = ref({})
34
- const columnsFieldsModel = ref({})
35
+ import Sortable from 'sortablejs'
35
36
 
36
- const axios = inject('axios')
37
+ defineOptions({ name: 'QasBoardGenerator' })
37
38
 
38
39
  const props = defineProps({
39
40
  headers: {
@@ -46,6 +47,11 @@ const props = defineProps({
46
47
  default: () => ({})
47
48
  },
48
49
 
50
+ headerBoxProps: {
51
+ type: Object,
52
+ default: () => ({})
53
+ },
54
+
49
55
  columnIdKey: {
50
56
  type: String,
51
57
  required: true
@@ -61,11 +67,21 @@ const props = defineProps({
61
67
  required: true
62
68
  },
63
69
 
70
+ confirmDialogProps: {
71
+ type: Object,
72
+ default: () => ({})
73
+ },
74
+
64
75
  height: {
65
76
  type: String,
66
77
  default: ''
67
78
  },
68
79
 
80
+ itemIdKey: {
81
+ type: String,
82
+ default: ''
83
+ },
84
+
69
85
  limitPerColumn: {
70
86
  type: Number,
71
87
  default: 12
@@ -76,11 +92,34 @@ const props = defineProps({
76
92
  default: '300px'
77
93
  },
78
94
 
95
+ sortableConfig: {
96
+ type: Object,
97
+ default: () => ({})
98
+ },
99
+
79
100
  useMarkRaw: {
80
101
  type: Boolean,
81
102
  default: true
82
103
  },
83
104
 
105
+ useDragAndDropX: {
106
+ type: Boolean
107
+ },
108
+
109
+ useDragAndDropY: {
110
+ type: Boolean
111
+ },
112
+
113
+ updatePositionUrl: {
114
+ type: String,
115
+ default: ''
116
+ },
117
+
118
+ updatePositionParams: {
119
+ type: Object,
120
+ default: () => ({})
121
+ },
122
+
84
123
  lazyLoadingFieldsKeys: {
85
124
  type: Array,
86
125
  default: () => []
@@ -92,28 +131,93 @@ const emit = defineEmits([
92
131
  'fetch-column-success',
93
132
  'fetch-column-error',
94
133
  'fetch-columns-success',
95
- 'fetch-columns-error'
134
+ 'fetch-columns-error',
135
+ 'update-success'
96
136
  ])
97
137
 
138
+ defineExpose({ fetchColumns, fetchColumn, reset })
139
+
140
+ // Inject
141
+ const axios = inject('axios')
142
+
143
+ const isFetchSuccessHeader = inject('isFetchListSucceeded', false)
144
+
145
+ const isInsideListView = inject('isListView', false)
146
+
147
+ // Refs
148
+ const columnContainer = ref(null)
149
+ const columnsPagination = ref({})
150
+ const columnsLoading = ref({})
151
+ const columnsFieldsModel = ref({})
152
+ const showConfirmDialog = ref(false)
153
+ const isDragging = ref(false)
154
+ const isLoadingUpdatePosition = ref(false)
155
+
156
+ /**
157
+ * Instâncias do sortable, que são utilizadas para realizar o destroy ao sair da página
158
+ */
159
+ const sortableInstances = ref([])
160
+
161
+ /**
162
+ * Callbacks que recebe o event de movimentação
163
+ */
164
+ const onCancelDrop = ref(() => {})
165
+ const onConfirmDrop = ref(() => {})
166
+
167
+ /**
168
+ * Variável auxiliar que controla quando estou atualizando o header em caso de drag and drop
169
+ */
170
+ const isUpdatingPosition = ref(false)
171
+
172
+ // Consts
173
+ const hasDragAndDrop = !!props.useDragAndDropX || !!props.useDragAndDropY
174
+
175
+ const grabbableProps = {
176
+ useScrollBar: true,
177
+
178
+ ...(hasDragAndDrop && {
179
+ cancelMouseDownTarget: 'qas-board-generator__item'
180
+ })
181
+ }
182
+
183
+ // Watchers
184
+ watch(
185
+ () => isFetchSuccessHeader.value,
186
+ value => {
187
+ /**
188
+ * isFetchSuccessHeader é uma variavel que pego do listView por inject/provide, no qual caso eu faça request do header e dê sucesso, eu chamo as demais funções.
189
+ * Valido se não houve sucesso na requisição do header ou se não é uma atualização de posição, para assim não bater novamente nas colunas apenas no header.
190
+ */
191
+ if (!value || isUpdatingPosition.value) return
192
+
193
+ fetchColumnsValues()
194
+ }
195
+ )
196
+
98
197
  watch(
99
198
  () => props.headers,
100
199
  () => {
101
- reset()
102
- setColumnHeightContainer()
103
- setColumnsPagination()
104
- fetchColumns()
200
+ if (isUpdatingPosition.value) return
201
+
202
+ isUpdatingPosition.value = false
105
203
  }
106
204
  )
107
205
 
108
206
  watch(columnContainer, setColumnHeightContainer)
109
207
 
208
+ // Lifecycles
110
209
  onMounted(() => {
111
- setColumnsPagination()
112
- fetchColumns()
210
+ /**
211
+ * Caso eu use o listView (valor pego por provide), a request é feito pelo watch quando se ocorre o sucesso do `fetchList`
212
+ */
213
+ if (isInsideListView) return
214
+
215
+ fetchColumnsValues()
113
216
  })
114
217
 
115
- defineExpose({ fetchColumns, fetchColumn, reset })
218
+ onUnmounted(destroySortable)
116
219
 
220
+ // Computeds
117
221
  const columnsResultsModel = computed({
118
222
  get () {
119
223
  return props.results
@@ -124,10 +228,32 @@ const columnsResultsModel = computed({
124
228
  }
125
229
  })
126
230
 
127
- const hasColumnsLength = computed(() => Object.keys(columnsResultsModel.value).length)
231
+ const hasColumnsLength = computed(() => !!Object.keys(columnsResultsModel.value).length)
128
232
 
129
233
  const containerStyle = computed(() => `width: ${props.columnWidth};`)
130
234
 
235
+ const hasConfirmDialogProps = computed(() => !!Object.keys(props.confirmDialogProps).length)
236
+
237
+ const defaultConfirmDialogProps = computed(() => {
238
+ const defaultProps = {
239
+ ok: {
240
+ label: 'Confirmar',
241
+ onClick: onConfirmDrop.value,
242
+ loading: isLoadingUpdatePosition.value
243
+ },
244
+
245
+ cancel: {
246
+ onClick: onCancelDrop.value
247
+ }
248
+ }
249
+
250
+ return {
251
+ ...props.confirmDialogProps,
252
+ ...defaultProps
253
+ }
254
+ })
255
+
256
+ // functions
131
257
  /*
132
258
  * Setar o tamanho do container do board, onde deverá ser a altura passada via prop, ou o default será ocupar o maximo
133
259
  * de espaço que ele conseguir considerando a altura do container em relação ao topo.
@@ -157,6 +283,8 @@ async function fetchColumns () {
157
283
  }
158
284
 
159
285
  emit('fetch-columns-success')
286
+
287
+ if (hasDragAndDrop) handleElementsList()
160
288
  }
161
289
 
162
290
  /*
@@ -189,22 +317,25 @@ async function fetchColumn (header) {
189
317
  throw error
190
318
  }
191
319
 
192
- /*
193
- * exemplo de como columnsResultsModel irá ficar:
194
- *
195
- * {
196
- * '2024-02-15': [...],
197
- * '2024-02-16': [...]
198
- * }
199
- *
200
- * onde cada item do objeto é uma coluna no board. O mesmo vale para "columnsFieldsModel", "columnsLoading" e
201
- * "columnPagination", organizando os fields, loadings e o controle de paginação por chave identificadora do header.
202
- */
320
+ const newValues = response.data?.results || []
321
+ const resultsModel = columnsResultsModel.value[headerKey] || []
322
+
203
323
  const newColumnValues = [
204
- ...columnsResultsModel.value[headerKey] || [],
205
- ...response.data?.results || []
324
+ ...resultsModel,
325
+ ...newValues
206
326
  ]
207
327
 
328
+ /**
329
+ * exemplo de como columnsResultsModel irá ficar:
330
+ *
331
+ * {
332
+ * '2024-02-15': [...],
333
+ * '2024-02-16': [...]
334
+ * }
335
+ *
336
+ * onde cada item do objeto é uma coluna no board. O mesmo vale para "columnsFieldsModel", "columnsLoading" e
337
+ * "columnPagination", organizando os fields, loadings e o controle de paginação por chave identificadora do header.
338
+ */
208
339
  columnsResultsModel.value[headerKey] = props.useMarkRaw ? markRaw(newColumnValues) : newColumnValues
209
340
 
210
341
  /*
@@ -293,8 +424,24 @@ function setColumnsPagination () {
293
424
  })
294
425
  }
295
426
 
427
+ function fetchColumnsValues () {
428
+ reset()
429
+ setColumnHeightContainer()
430
+ setColumnsPagination()
431
+ fetchColumns()
432
+ }
433
+
434
+ /**
435
+ * Descricao:
436
+ * Exibe o texto quando:
437
+ * - Nao esta carregando a coluna
438
+ * - Nao tem itens na coluna
439
+ * - Nao estou fazendo o drag and drop
440
+ *
441
+ * @param {Object} header
442
+ */
296
443
  function hasEmptyResultText (header) {
297
- return !columnsLoading.value[getKeyByHeader(header)] && !getItemsByHeader(header)?.length
444
+ return !columnsLoading.value[getKeyByHeader(header)] && !getItemsByHeader(header)?.length && !isDragging.value
298
445
  }
299
446
 
300
447
  /*
@@ -319,6 +466,221 @@ function getFieldsByHeader (header) {
319
466
 
320
467
  return columnsFieldsModel.value[headerKey] || {}
321
468
  }
469
+
470
+ /**
471
+ * Loopa todos os itens da coluna com base no ref para pegar o elemento HTML e setar e instaciar o sortable.
472
+ */
473
+ function handleElementsList () {
474
+ columnContainer.value.forEach((element, index) => {
475
+ const sortable = setSortable(element, index)
476
+
477
+ sortableInstances.value.push(sortable)
478
+ })
479
+ }
480
+
481
+ /**
482
+ * Descricao:
483
+ * Seta a instancia do sortable, no qual varia de acordo com as props passadas.
484
+ *
485
+ * @param {HTMLElement} element
486
+ * @param {Number} index
487
+ */
488
+ function setSortable (element, index) {
489
+ const defaultSortableConfig = {
490
+ animation: 500,
491
+ swapThreshold: 1,
492
+ delay: 50,
493
+ delayOnTouchOnly: true,
494
+ emptyInsertThreshold: 0
495
+ }
496
+
497
+ /**
498
+ * Caso seja apenas drag and drop no eixo Y
499
+ */
500
+ const useOnlyDragAndDropY = !!props.useDragAndDropY && !props.useDragAndDropX
501
+
502
+ const sortable = new Sortable(element, {
503
+ sort: props.useDragAndDropY,
504
+
505
+ ...defaultSortableConfig,
506
+
507
+ ...props.sortableConfig,
508
+
509
+ group: useOnlyDragAndDropY ? `column-${index}` : 'shared',
510
+
511
+ direction: useOnlyDragAndDropY ? 'vertical' : 'horizontal',
512
+
513
+ onStart: toggleIsDragging,
514
+
515
+ onAdd: event => onDropCard(event),
516
+
517
+ ...(props.useDragAndDropY && {
518
+ onSort: event => onDropCard(event)
519
+ })
520
+ })
521
+
522
+ return sortable
523
+ }
524
+
525
+ function toggleIsDragging () {
526
+ isDragging.value = !isDragging.value
527
+ }
528
+
529
+ function onDropCard (event) {
530
+ onCancelDrop.value = () => cancelDrop(event)
531
+
532
+ onConfirmDrop.value = () => confirmDrop(event)
533
+
534
+ hasConfirmDialogProps.value
535
+ ? openConfirmDialog()
536
+ : confirmDrop(event)
537
+ }
538
+
539
+ function openConfirmDialog () {
540
+ showConfirmDialog.value = true
541
+ }
542
+
543
+ function closeConfirmDialog () {
544
+ showConfirmDialog.value = false
545
+ }
546
+
547
+ /**
548
+ * @param {event} event
549
+ */
550
+ function cancelDrop (event) {
551
+ /**
552
+ * Insere na posição antiga que pertencia (event.oldIndex) dentro do seu antigo pai (event.from)
553
+ */
554
+ if (props.useDragAndDropX) event.from.insertBefore(event.item, event.from.children[event.oldIndex])
555
+
556
+ if (props.useDragAndDropY) {
557
+ const oldIndex = event.oldIndex
558
+
559
+ /**
560
+ * Se oldIndex for 0, o targetIndex deverá ser 0, pois isso indica que se o item é o primeiro da lista, ele não será movido para outra posição.
561
+ *
562
+ * Caso o oldIndex for diferente, devo incrementar 1 para adicionar, pois isso permite que o item seja inserido logo após sua posição original.
563
+ */
564
+ const targetIndex = oldIndex === 0 ? oldIndex : oldIndex + 1
565
+
566
+ /**
567
+ * Verifica se o índice alvo é válido, caso contrário, define como o final
568
+ */
569
+ const insertBeforeElement = targetIndex < event.from.children.length
570
+ ? event.from.children[targetIndex]
571
+ : null
572
+
573
+ event.from.insertBefore(event.item, insertBeforeElement)
574
+ }
575
+
576
+ if (hasConfirmDialogProps.value) closeConfirmDialog()
577
+
578
+ toggleIsDragging()
579
+ }
580
+
581
+ function confirmDrop (event) {
582
+ const { from, to, item: { id: itemId } } = event
583
+
584
+ const { headerKey: newHeaderKey } = to.dataset
585
+ const { headerKey: oldHeaderKey } = from.dataset
586
+
587
+ updatePosition({ newHeaderKey, oldHeaderKey, itemId, event })
588
+ }
589
+
590
+ /**
591
+ *
592
+ * @param {{
593
+ * headerKey: string,
594
+ * itemId: string
595
+ * }}
596
+ */
597
+ function removeItemFromList ({ headerKey, itemId }) {
598
+ /**
599
+ * Coluna referente ao model de resultado
600
+ */
601
+ const columnItemList = columnsResultsModel.value[headerKey]
602
+
603
+ /**
604
+ * Busca o item com base em seu ID na lista de itens da coluna
605
+ */
606
+ const itemIndex = columnItemList.findIndex(itemContent => itemContent[props.itemIdKey] === itemId)
607
+
608
+ /**
609
+ * Remove o item da listagem com base no index, sendo que preciso subtrair 1 para pegar o index correto
610
+ */
611
+ columnItemList.splice(itemIndex, 1)
612
+
613
+ /**
614
+ * Remove o item do count da coluna para não mostrar o botão de "Ver mais¨.
615
+ */
616
+ columnsPagination.value[headerKey].count -= 1
617
+ }
618
+
619
+ /**
620
+ * Descricao:
621
+ * Metodo que realiza a request de update
622
+ *
623
+ * @param {{
624
+ * newHeaderKey: string - ID da coluna de destino,
625
+ * oldHeaderKey: string - ID da antiga coluna,
626
+ * itemId: string - ID do meu item a ser movimento,
627
+ * event: event
628
+ * }}
629
+ */
630
+ async function updatePosition ({ newHeaderKey, oldHeaderKey, itemId, event }) {
631
+ const params = {
632
+ [props.columnIdKey]: newHeaderKey,
633
+ ...(props.useDragAndDropY && { newIndex: event.newIndex }),
634
+ ...props.updatePositionParams
635
+ }
636
+
637
+ const { data, error } = await promiseHandler(
638
+ axios.patch(`${props.updatePositionUrl}/${itemId}/update-position`, params),
639
+ {
640
+ errorMessage: 'Ocorreu um erro ao atualizar a posição de seu item.',
641
+ useLoading: false,
642
+ onLoading: value => {
643
+ isLoadingUpdatePosition.value = value
644
+
645
+ columnsLoading.value[newHeaderKey] = value
646
+ }
647
+ }
648
+ )
649
+
650
+ if (error) {
651
+ onCancelDrop.value()
652
+
653
+ return
654
+ }
655
+
656
+ removeItemFromList({ headerKey: oldHeaderKey, itemId })
657
+
658
+ setItemList({ headerKey: newHeaderKey, data: data.data, index: event.newIndex })
659
+
660
+ isUpdatingPosition.value = true
661
+
662
+ toggleIsDragging()
663
+
664
+ closeConfirmDialog()
665
+
666
+ emit('update-success')
667
+ }
668
+
669
+ function setItemList ({ headerKey, data, index }) {
670
+ /**
671
+ * Coluna referente ao model de resultado
672
+ */
673
+ const columnItemList = columnsResultsModel.value[headerKey]
674
+
675
+ /**
676
+ * Adiciona o item na posição do event escolhido.
677
+ */
678
+ columnItemList.splice(index, 0, data.result)
679
+ }
680
+
681
+ function destroySortable () {
682
+ sortableInstances.value.forEach(sortable => sortable.destroy())
683
+ }
322
684
  </script>
323
685
 
324
686
  <style lang="scss">
@@ -341,5 +703,10 @@ function getFieldsByHeader (header) {
341
703
  display: none;
342
704
  }
343
705
  }
706
+
707
+ // 60px é o valor do padding definido no container da column.
708
+ &__column-items {
709
+ height: calc(100% - 60px);
710
+ }
344
711
  }
345
712
  </style>