TicketSimpleTable.vue 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. <!-- Copyright (C) 2012-2025 Zammad Foundation, https://zammad-foundation.org/ -->
  2. <script setup lang="ts">
  3. import { storeToRefs } from 'pinia'
  4. import { computed } from 'vue'
  5. import type { TicketById } from '#shared/entities/ticket/types.ts'
  6. import { useApplicationStore } from '#shared/stores/application.ts'
  7. import CommonSimpleTable from '#desktop/components/CommonTable/CommonSimpleTable.vue'
  8. import type {
  9. TableSimpleHeader,
  10. TableItem,
  11. } from '#desktop/components/CommonTable/types'
  12. import CommonTicketStateIndicatorIcon from '#desktop/components/CommonTicketStateIndicator/CommonTicketStateIndicatorIcon.vue'
  13. import type { TicketRelationAndRecentListItem } from '#desktop/pages/ticket/components/TicketDetailView/TicketSimpleTable/types.ts'
  14. interface Props {
  15. tickets: TicketRelationAndRecentListItem[]
  16. label: string
  17. selectedTicketId?: string
  18. }
  19. const emit = defineEmits<{
  20. 'click-ticket': [TicketRelationAndRecentListItem]
  21. }>()
  22. const { config } = storeToRefs(useApplicationStore())
  23. const headers: TableSimpleHeader[] = [
  24. { key: 'state', label: '', truncate: true, type: 'link' },
  25. {
  26. key: 'number',
  27. label: config.value.ticket_hook,
  28. type: 'link',
  29. truncate: true,
  30. },
  31. { key: 'title', label: __('Title'), truncate: true },
  32. { key: 'customer', label: __('Customer'), truncate: true },
  33. { key: 'group', label: __('Group'), truncate: true },
  34. { key: 'createdAt', label: __('Created at'), truncate: true },
  35. ]
  36. const props = defineProps<Props>()
  37. const items = computed<Array<TableItem>>(() =>
  38. props.tickets.map((ticket) => ({
  39. createdAt: ticket.createdAt,
  40. customer: ticket.organization?.name || ticket.customer?.fullname,
  41. group: ticket.group?.name,
  42. id: ticket.id,
  43. internalId: ticket.internalId,
  44. key: ticket.id,
  45. number: {
  46. link: `/tickets/${ticket.internalId}`,
  47. label: ticket.number,
  48. internal: true,
  49. },
  50. organization: ticket.organization,
  51. title: ticket.title,
  52. stateColorCode: ticket.stateColorCode,
  53. state: ticket.state,
  54. })),
  55. )
  56. const handleRowClick = (row: TableItem) => {
  57. const ticket = props.tickets.find((ticket) => ticket.id === row.id)
  58. emit('click-ticket', ticket!)
  59. }
  60. </script>
  61. <template>
  62. <section>
  63. <!-- TODO: Set needed props to disable infinite scrolling etc. -->
  64. <CommonSimpleTable
  65. ref="simple-table"
  66. class="w-full"
  67. :caption="label"
  68. show-caption
  69. :headers="headers"
  70. :items="items"
  71. :selected-row-id="selectedTicketId"
  72. @click-row="handleRowClick"
  73. >
  74. <template #column-cell-createdAt="{ item, isRowSelected }">
  75. <CommonDateTime
  76. class="-:text-gray-100 -:dark:text-neutral-400 group-hover:text-black group-focus-visible:text-white group-active:text-white group-hover:dark:text-white group-active:dark:text-white"
  77. :class="{ 'text-black dark:text-white': isRowSelected }"
  78. :date-time="item['createdAt'] as string"
  79. type="absolute"
  80. absolute-format="date"
  81. />
  82. </template>
  83. <template #column-cell-state="{ item, isRowSelected }">
  84. <CommonTicketStateIndicatorIcon
  85. class="shrink-0 group-hover:text-black group-focus-visible:text-white group-active:text-white group-hover:dark:text-white group-active:dark:text-white"
  86. :class="{
  87. 'ltr:text-black rtl:text-black dark:text-white': isRowSelected,
  88. }"
  89. :color-code="(item as TicketById).stateColorCode"
  90. :label="(item as TicketById).state.name"
  91. :aria-labelledby="(item as TicketById).id"
  92. icon-size="tiny"
  93. />
  94. </template>
  95. </CommonSimpleTable>
  96. </section>
  97. </template>