useArticleMeta.ts 3.7 KB

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