PersonalSettingOverviewOrder.vue 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. <!-- Copyright (C) 2012-2025 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. organizationShared?: boolean | null
  12. outOfOffice?: boolean | null
  13. }
  14. const localValue = defineModel<OverviewItem[]>('modelValue')
  15. const dndEndCallback = (parent: HTMLElement) => {
  16. const parentData = parents.get(parent)
  17. if (!parentData) return
  18. localValue.value = cloneDeep(parentData.getValues(parent))
  19. }
  20. const dndParentElement = useTemplateRef('dnd-parent')
  21. const dndLocalValue = ref(localValue.value || [])
  22. watch(localValue, (newValue) => {
  23. if (isEqual(dndLocalValue.value, newValue)) return
  24. dndLocalValue.value = cloneDeep(newValue || [])
  25. })
  26. dragAndDrop({
  27. parent: dndParentElement as Ref<HTMLElement>,
  28. values: dndLocalValue,
  29. plugins: [
  30. startAndEndEventsDNDPlugin(undefined, dndEndCallback),
  31. animations(),
  32. ],
  33. dropZoneClass: 'opacity-0',
  34. touchDropZoneClass: 'opacity-0',
  35. })
  36. </script>
  37. <template>
  38. <div v-if="localValue" class="rounded-lg bg-blue-200 dark:bg-gray-700">
  39. <!-- :TODO if we add proper a11y support -->
  40. <!-- <span class="hidden" aria-live="assertive" >{{assistiveText}}</span>-->
  41. <span id="drag-and-drop-ticket-overviews" class="sr-only">
  42. {{ $t('Drag and drop to reorder ticket overview list items.') }}
  43. </span>
  44. <ul ref="dnd-parent" class="flex flex-col p-1">
  45. <li
  46. v-for="value in dndLocalValue"
  47. :key="value.id"
  48. class="draggable flex min-h-9 cursor-grab items-start gap-2.5 p-2.5 active:cursor-grabbing"
  49. draggable="true"
  50. aria-describedby="drag-and-drop-ticket-overviews"
  51. >
  52. <CommonIcon
  53. class="mt-1 shrink-0 fill-stone-200 dark:fill-neutral-500"
  54. name="grip-vertical"
  55. size="tiny"
  56. decorative
  57. />
  58. <div class="grow">
  59. <CommonLabel class="inline text-black dark:text-white">
  60. {{ $t(value.name) }}
  61. </CommonLabel>
  62. <CommonBadge
  63. v-if="value.organizationShared"
  64. variant="info"
  65. class="ms-1.5"
  66. >{{ $t('Only when shared organization member') }}</CommonBadge
  67. >
  68. <CommonBadge v-if="value.outOfOffice" variant="info" class="ms-1.5">{{
  69. $t('Only when out of office replacement')
  70. }}</CommonBadge>
  71. </div>
  72. </li>
  73. </ul>
  74. </div>
  75. </template>