useArticleMeta.ts 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. // Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/
  2. import { computed, type Ref } from 'vue'
  3. import CommonDateTime from '#shared/components/CommonDateTime/CommonDateTime.vue'
  4. import type { TicketArticle } from '#shared/entities/ticket/types.ts'
  5. import { lookupArticlePlugin } from '#desktop/pages/ticket/components/TicketDetailView/article-type/index.ts'
  6. import ArticleMetaFieldAddress from '#desktop/pages/ticket/components/TicketDetailView/ArticleMeta/ArticleMetaAddress.vue'
  7. import type { ChannelMetaField } from '#desktop/pages/ticket/components/TicketDetailView/ArticleMeta/types.ts'
  8. const getNestedProperty = (article: TicketArticle, nestedKeys: string[]) => {
  9. return nestedKeys.reduce((accumulator, currentKey) => {
  10. if (accumulator && typeof accumulator === 'object') {
  11. return accumulator[currentKey as keyof typeof article]
  12. }
  13. return undefined
  14. }, article)
  15. }
  16. const addNewFields = (
  17. fields: ChannelMetaField[],
  18. article: Ref<TicketArticle>,
  19. ) => {
  20. const plugin = lookupArticlePlugin(article.value.type?.name as string)
  21. if (!plugin?.additionalFields?.length) return fields
  22. plugin.additionalFields.forEach((field) => {
  23. const nestedKeys = field.name.split('.')
  24. const fieldValue = getNestedProperty(article.value, nestedKeys)
  25. if (field.show !== undefined && !field.show?.(article)) return fields
  26. if (fieldValue)
  27. fields.push({
  28. label: field.label || (article.value.type?.name as string),
  29. name: field.name,
  30. component: field.component,
  31. order: field.order,
  32. value: fieldValue,
  33. })
  34. })
  35. return fields
  36. }
  37. export const useArticleMeta = (article: Ref<TicketArticle>) => {
  38. const links = computed(() => article.value.preferences?.links || [])
  39. const fields = computed(() => {
  40. const plugin = lookupArticlePlugin(article.value.type?.name as string)
  41. const base = [
  42. {
  43. label: __('Created at'),
  44. name: 'created_at',
  45. component: CommonDateTime,
  46. props: {
  47. class: 'text-sm',
  48. dateTime: article.value.createdAt,
  49. type: 'absolute',
  50. },
  51. order: 100,
  52. },
  53. {
  54. label: __('From'),
  55. name: 'from',
  56. component: ArticleMetaFieldAddress,
  57. props: {
  58. type: 'from',
  59. },
  60. show: () =>
  61. !!(article.value.from?.parsed?.[0]?.name || article.value.from?.raw),
  62. order: 200,
  63. },
  64. {
  65. label: __('To'),
  66. name: 'to',
  67. component: ArticleMetaFieldAddress,
  68. props: {
  69. type: 'to',
  70. },
  71. show: () =>
  72. !!(article.value.to?.parsed?.[0]?.name || article.value.to?.raw),
  73. order: 300,
  74. },
  75. {
  76. label: __('CC'),
  77. name: 'cc',
  78. component: ArticleMetaFieldAddress,
  79. props: {
  80. type: 'cc',
  81. },
  82. show: () =>
  83. !!(article.value.cc?.parsed?.[0]?.name || article.value.cc?.raw),
  84. order: 350,
  85. },
  86. {
  87. label: __('Channel'),
  88. name: 'channel',
  89. value: plugin?.name,
  90. icon: plugin?.icon,
  91. links: article.value.preferences?.links,
  92. component: plugin?.channel?.component,
  93. order: 400,
  94. },
  95. ]
  96. return addNewFields(base as ChannelMetaField[], article)
  97. .filter((field) => (field.show ? field.show(article.value) : true))
  98. .sort((a, b) => a.order - b.order)
  99. })
  100. return { fields, links }
  101. }