app/frontend/shared/entities/ticket-article/action/plugins/index.ts
// Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/
import type {
TicketArticle,
TicketById,
} from '#shared/entities/ticket/types.ts'
import { getTicketView } from '#shared/entities/ticket/utils/getTicketView.ts'
import { useApplicationStore } from '#shared/stores/application.ts'
import type { AppName } from '#shared/types/app.ts'
import type {
TicketTypeAddOptions,
TicketActionAddOptions,
TicketArticleActionPlugin,
TicketViewPolicyMap,
AppSpecificTicketArticleType,
} from './types.ts'
const pluginsModules = import.meta.glob<TicketArticleActionPlugin>(
['./*.ts', '!./initialize.ts', '!./types.ts', '!./__tests__/**/*.ts'],
{
eager: true,
import: 'default',
},
)
export const articleActionPlugins = Object.values(pluginsModules).sort(
(p1, p2) => p1.order - p2.order,
)
const createFilter = (options: TicketTypeAddOptions, app: AppName) => {
return (object: { view: TicketViewPolicyMap; apps: AppName[] }) => {
if (!object.apps.includes(app)) return false
const view = object.view[options.view.ticketView]
if (!view || !view.length) return false
if (view.includes('read')) return true
if (options.view.isTicketEditable && view.includes('change')) return true
return false
}
}
export const createArticleActions = (
ticket: TicketById,
article: TicketArticle,
app: AppName,
_options: Pick<TicketActionAddOptions, 'onDispose' | 'recalculate'>,
) => {
const application = useApplicationStore()
const options = {
..._options,
view: getTicketView(ticket),
config: application.config,
}
const filterByView = createFilter(options, app)
return articleActionPlugins
.map((p) => p.addActions?.(ticket, article, options) || [])
.flat()
.filter(filterByView)
}
export const createArticleTypes = (
ticket: TicketById,
app: AppName,
): AppSpecificTicketArticleType[] => {
const application = useApplicationStore()
const options: TicketTypeAddOptions = {
view: getTicketView(ticket),
config: application.config,
}
const filterByView = createFilter(options, app)
return (
articleActionPlugins
.map((p) => p.addTypes?.(ticket, options) || [])
.flat()
.filter(filterByView)
// eslint-disable-next-line @typescript-eslint/no-unused-vars
.map(({ apps, ...type }) => ({
...type,
icon: type.icon,
}))
)
}