useDisplayObjectAttributes.ts 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. // Copyright (C) 2012-2025 Zammad Foundation, https://zammad-foundation.org/
  2. import { keyBy } from 'lodash-es'
  3. import { computed } from 'vue'
  4. import type { ObjectAttribute } from '#shared/entities/object-attributes/types/store.ts'
  5. import type { ObjectAttributeValue } from '#shared/graphql/types.ts'
  6. import type { ObjectLike } from '#shared/types/utils.ts'
  7. import { getLink, getValue, isEmpty } from './utils.ts'
  8. import type { AttributeDeclaration } from './types.ts'
  9. import type { Dictionary } from 'ts-essentials'
  10. import type { Component } from 'vue'
  11. interface BaseObjectAttributeDisplayOptions {
  12. object: ObjectLike
  13. }
  14. export interface ObjectAttributeDisplayOptions
  15. extends BaseObjectAttributeDisplayOptions {
  16. attribute: ObjectAttribute
  17. }
  18. export interface ObjectAttributesDisplayOptions
  19. extends BaseObjectAttributeDisplayOptions {
  20. skipAttributes?: string[]
  21. attributes: ObjectAttribute[]
  22. }
  23. export interface AttributeField {
  24. attribute: ObjectAttribute
  25. component: Component
  26. value: unknown
  27. link: Maybe<string>
  28. }
  29. const attributesDeclarations = import.meta.glob<AttributeDeclaration>(
  30. './attributes/Attribute*/index.ts',
  31. { eager: true, import: 'default' },
  32. )
  33. const definitionsByType = Object.values(attributesDeclarations).reduce(
  34. (acc, declaration) => {
  35. declaration.dataTypes.forEach((type) => {
  36. acc[type] = declaration.component
  37. })
  38. return acc
  39. },
  40. {} as Record<string, Component>,
  41. )
  42. export const useDisplayObjectAttribute = (
  43. options: ObjectAttributeDisplayOptions,
  44. ) => {
  45. const attributesObject = computed<Dictionary<ObjectAttributeValue>>(() => {
  46. return keyBy(options.object.objectAttributeValues || {}, 'attribute.name')
  47. })
  48. const field = computed<AttributeField>(() => {
  49. const { attribute, object } = options
  50. return {
  51. attribute,
  52. component: definitionsByType[attribute.dataType],
  53. value: getValue(
  54. attribute.name,
  55. object,
  56. attributesObject.value,
  57. attribute,
  58. ),
  59. link: getLink(attribute.name, attributesObject.value),
  60. }
  61. })
  62. return { field }
  63. }
  64. export const useDisplayObjectAttributes = (
  65. options: ObjectAttributesDisplayOptions,
  66. ) => {
  67. const attributesObject = computed<Dictionary<ObjectAttributeValue>>(() => {
  68. return keyBy(options.object.objectAttributeValues || {}, 'attribute.name')
  69. })
  70. const fields = computed<AttributeField[]>(() => {
  71. return options.attributes
  72. .filter((attribute) => !attribute.isStatic)
  73. .map((attribute) => ({
  74. attribute,
  75. component: definitionsByType[attribute.dataType],
  76. value: getValue(
  77. attribute.name,
  78. options.object,
  79. attributesObject.value,
  80. attribute,
  81. ),
  82. link: getLink(attribute.name, attributesObject.value),
  83. }))
  84. .filter(({ attribute, value, component }) => {
  85. if (!component) return false
  86. if (isEmpty(value)) {
  87. return false
  88. }
  89. return !options.skipAttributes?.includes(attribute.name)
  90. })
  91. })
  92. return {
  93. fields,
  94. }
  95. }