PersonalSettingOverviewOrder.vue 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. <!-- Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/ -->
  2. <script setup lang="ts">
  3. import { animations, parents } from '@formkit/drag-and-drop'
  4. import { dragAndDrop } from '@formkit/drag-and-drop/vue'
  5. import { cloneDeep, isEqual } from 'lodash-es'
  6. import { ref, watch, useTemplateRef, type Ref } from 'vue'
  7. import { startAndEndEventsDNDPlugin } from '#shared/utils/startAndEndEventsDNDPlugin.ts'
  8. export interface OverviewItem {
  9. id: string
  10. name: string
  11. }
  12. const localValue = defineModel<OverviewItem[]>('modelValue')
  13. const dndEndCallback = (parent: HTMLElement) => {
  14. const parentData = parents.get(parent)
  15. if (!parentData) return
  16. localValue.value = cloneDeep(parentData.getValues(parent))
  17. }
  18. const dndParentElement = useTemplateRef('dnd-parent')
  19. const dndLocalValue = ref(localValue.value || [])
  20. watch(localValue, (newValue) => {
  21. if (isEqual(dndLocalValue.value, newValue)) return
  22. dndLocalValue.value = cloneDeep(newValue || [])
  23. })
  24. dragAndDrop({
  25. parent: dndParentElement as Ref<HTMLElement>,
  26. values: dndLocalValue,
  27. plugins: [
  28. startAndEndEventsDNDPlugin(undefined, dndEndCallback),
  29. animations(),
  30. ],
  31. dropZoneClass: 'opacity-0',
  32. touchDropZoneClass: 'opacity-0',
  33. })
  34. </script>
  35. <template>
  36. <div v-if="localValue" class="rounded-lg bg-blue-200 dark:bg-gray-700">
  37. <!-- :TODO if we add proper a11y support -->
  38. <!-- <span class="hidden" aria-live="assertive" >{{assistiveText}}</span>-->
  39. <span id="drag-and-drop-ticket-overviews" class="sr-only">
  40. {{ $t('Drag and drop to reorder ticket overview list items.') }}
  41. </span>
  42. <ul ref="dnd-parent" class="flex flex-col p-1">
  43. <li
  44. v-for="value in dndLocalValue"
  45. :key="value.id"
  46. class="draggable flex min-h-9 cursor-grab items-start gap-2.5 p-2.5 active:cursor-grabbing"
  47. draggable="true"
  48. aria-describedby="drag-and-drop-ticket-overviews"
  49. >
  50. <CommonIcon
  51. class="fill-stone-200 dark:fill-neutral-500"
  52. name="grip-vertical"
  53. size="tiny"
  54. />
  55. <CommonLabel class="w-full text-black dark:text-white">
  56. {{ $t(value.name) }}
  57. </CommonLabel>
  58. </li>
  59. </ul>
  60. </div>
  61. </template>