index.ts 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. // Copyright (C) 2012-2023 Zammad Foundation, https://zammad-foundation.org/
  2. import type { TicketArticle, TicketById } from '@shared/entities/ticket/types'
  3. import { getTicketView } from '@shared/entities/ticket/utils/getTicketView'
  4. import { useApplicationStore } from '@shared/stores/application'
  5. import type { AppName } from '@shared/types/app'
  6. import type {
  7. TicketTypeAddOptions,
  8. TicketActionAddOptions,
  9. TicketArticleActionPlugin,
  10. TicketViewPolicyMap,
  11. AppSpecificTicketArticleType,
  12. } from './types'
  13. const pluginsModules = import.meta.glob<TicketArticleActionPlugin>(
  14. ['./*.ts', '!./initialize.ts', '!./types.ts', '!./__tests__/**/*.ts'],
  15. {
  16. eager: true,
  17. import: 'default',
  18. },
  19. )
  20. export const articleActionPlugins = Object.values(pluginsModules).sort(
  21. (p1, p2) => p1.order - p2.order,
  22. )
  23. const createFilter = (options: TicketTypeAddOptions, app: AppName) => {
  24. return (object: { view: TicketViewPolicyMap; apps: AppName[] }) => {
  25. if (!object.apps.includes(app)) return false
  26. const view = object.view[options.view.ticketView]
  27. if (!view || !view.length) return false
  28. if (view.includes('read')) return true
  29. if (options.view.isTicketEditable && view.includes('change')) return true
  30. return false
  31. }
  32. }
  33. export const createArticleActions = (
  34. ticket: TicketById,
  35. article: TicketArticle,
  36. app: AppName,
  37. _options: Pick<TicketActionAddOptions, 'onDispose' | 'recalculate'>,
  38. ) => {
  39. const application = useApplicationStore()
  40. const options = {
  41. ..._options,
  42. view: getTicketView(ticket),
  43. config: application.config,
  44. }
  45. const filterByView = createFilter(options, app)
  46. return articleActionPlugins
  47. .map((p) => p.addActions?.(ticket, article, options) || [])
  48. .flat()
  49. .filter(filterByView)
  50. }
  51. export const createArticleTypes = (
  52. ticket: TicketById,
  53. app: AppName,
  54. ): AppSpecificTicketArticleType[] => {
  55. const application = useApplicationStore()
  56. const options: TicketTypeAddOptions = {
  57. view: getTicketView(ticket),
  58. config: application.config,
  59. }
  60. const filterByView = createFilter(options, app)
  61. return (
  62. articleActionPlugins
  63. .map((p) => p.addTypes?.(ticket, options) || [])
  64. .flat()
  65. .filter(filterByView)
  66. // eslint-disable-next-line @typescript-eslint/no-unused-vars
  67. .map(({ apps, ...type }) => ({
  68. ...type,
  69. icon: type.icon[app],
  70. }))
  71. )
  72. }