FieldCustomerWrapper.vue 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. <!-- Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/ -->
  2. <script setup lang="ts">
  3. import { markRaw } from 'vue'
  4. import type { SelectValue } from '#shared/components/CommonSelect/types.ts'
  5. import type { AutoCompleteOption } from '#shared/components/Form/fields/FieldAutocomplete/types.ts'
  6. import { AutocompleteSearchGenericDocument } from '#shared/components/Form/fields/FieldCustomer/graphql/queries/autocompleteSearch/generic.api.ts'
  7. import type { AutoCompleteCustomerOption } from '#shared/components/Form/fields/FieldCustomer/types.ts'
  8. import type { FormFieldContext } from '#shared/components/Form/types/field.ts'
  9. import type { User } from '#shared/graphql/types.ts'
  10. import type { ObjectLike } from '#shared/types/utils.ts'
  11. import FieldAutoCompleteInput from '../FieldAutoComplete/FieldAutoCompleteInput.vue'
  12. import { useAddUnknownValueAction } from '../FieldAutoComplete/useAddUnknownValueAction.ts'
  13. import FieldCustomerOptionIcon from './FieldCustomerOptionIcon.vue'
  14. import type { AutoCompleteProps } from '../FieldAutoComplete/types.ts'
  15. interface Props {
  16. context: FormFieldContext<
  17. AutoCompleteProps & {
  18. options?: AutoCompleteCustomerOption[]
  19. }
  20. >
  21. }
  22. const props = defineProps<Props>()
  23. const buildEntityOption = (entity: User) => {
  24. return {
  25. value: entity.internalId,
  26. label: entity.fullname || entity.phone || entity.login,
  27. heading: entity.organization?.name,
  28. user: entity,
  29. }
  30. }
  31. const { actions, onSearchInteractionUpdate } = useAddUnknownValueAction()
  32. Object.assign(props.context, {
  33. optionIconComponent: markRaw(FieldCustomerOptionIcon),
  34. initialOptionBuilder: (
  35. initialEntityObject: ObjectLike,
  36. value: SelectValue,
  37. context: Props['context'],
  38. ) => {
  39. if (!context.belongsToObjectField || !initialEntityObject) return null
  40. const belongsToObject = initialEntityObject[context.belongsToObjectField]
  41. if (!belongsToObject) return null
  42. return buildEntityOption(belongsToObject)
  43. },
  44. gqlQuery: AutocompleteSearchGenericDocument,
  45. additionalQueryParams: {
  46. onlyIn: ['User', 'Organization'],
  47. },
  48. autocompleteOptionsPreprocessor: (
  49. autocompleteOptions: (AutoCompleteCustomerOption & AutoCompleteOption)[],
  50. ) =>
  51. autocompleteOptions.map((autocompleteOption) => {
  52. if (
  53. !autocompleteOption.object ||
  54. autocompleteOption.object.__typename !== 'Organization'
  55. )
  56. return autocompleteOption
  57. autocompleteOption.disabled = true
  58. const heading = autocompleteOption.object.name
  59. autocompleteOption.children =
  60. autocompleteOption.object.members?.edges.map(
  61. (member) =>
  62. ({
  63. value: member.node.internalId,
  64. label:
  65. member.node.fullname ?? member.node.phone ?? member.node.login,
  66. heading,
  67. object: {
  68. ...member.node,
  69. __typename: 'User',
  70. },
  71. }) as AutoCompleteOption,
  72. ) || []
  73. return autocompleteOption
  74. }),
  75. actions,
  76. emptyInitialLabelText: __(
  77. 'Start typing to search or enter an email address…',
  78. ),
  79. })
  80. </script>
  81. <template>
  82. <FieldAutoCompleteInput
  83. :context="context"
  84. v-bind="$attrs"
  85. @search-interaction-update="onSearchInteractionUpdate"
  86. />
  87. </template>