index.ts 2.3 KB

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