articleDelete.ts 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. // Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/
  2. import { useConfirmation } from '#shared/composables/useConfirmation.ts'
  3. import type { TicketArticle } from '#shared/entities/ticket/types.ts'
  4. import { useTicketArticleDeleteMutation } from '#shared/entities/ticket-article/graphql/mutations/delete.api.ts'
  5. import { MutationHandler } from '#shared/server/apollo/handler/index.ts'
  6. import { useSessionStore } from '#shared/stores/session.ts'
  7. import type { TicketArticleActionPlugin, TicketArticleAction } from './types.ts'
  8. const deleteAction = async (article: TicketArticle) => {
  9. const { waitForConfirmation } = useConfirmation()
  10. const confirmed = await waitForConfirmation(
  11. __('Are you sure to remove this article?'),
  12. )
  13. if (!confirmed) return
  14. const mutation = new MutationHandler(
  15. useTicketArticleDeleteMutation({
  16. variables: { articleId: article.id },
  17. }),
  18. { errorNotificationMessage: __('The article could not be deleted.') },
  19. )
  20. mutation.send()
  21. }
  22. const hasDeleteTimeframe = (deleteTimeframe: number) =>
  23. deleteTimeframe && deleteTimeframe > 0
  24. const secondsToDelete = (article: TicketArticle, deleteTimeframe: number) => {
  25. if (!hasDeleteTimeframe(deleteTimeframe)) return 0
  26. const now = new Date().getTime()
  27. const createdAt = new Date(article.createdAt).getTime()
  28. const secondsSinceCreated = (now - createdAt) / 1000
  29. if (secondsSinceCreated > deleteTimeframe) return 0
  30. return deleteTimeframe - secondsSinceCreated
  31. }
  32. const isDeletable = (article: TicketArticle, deleteTimeframe: number) => {
  33. const session = useSessionStore()
  34. if (article.author?.id !== session.userId) return false
  35. if (article.type?.communication && !article.internal) return false
  36. if (
  37. hasDeleteTimeframe(deleteTimeframe) &&
  38. !secondsToDelete(article, deleteTimeframe)
  39. )
  40. return false
  41. return true
  42. }
  43. const actionPlugin: TicketArticleActionPlugin = {
  44. order: 999,
  45. addActions(ticket, article, { onDispose, recalculate, config }) {
  46. const deleteTimeframe =
  47. config.ui_ticket_zoom_article_delete_timeframe as number
  48. if (!isDeletable(article, deleteTimeframe)) return []
  49. const seconds = secondsToDelete(article, deleteTimeframe)
  50. if (seconds) {
  51. const timeout = window.setTimeout(() => {
  52. recalculate()
  53. }, seconds * 1_000)
  54. onDispose(() => {
  55. window.clearTimeout(timeout)
  56. })
  57. }
  58. const action: TicketArticleAction = {
  59. apps: ['mobile', 'desktop'],
  60. label: __('Delete Article'),
  61. name: 'articleDelete',
  62. icon: 'trash',
  63. perform: () => deleteAction(article),
  64. view: {
  65. agent: ['change'],
  66. },
  67. }
  68. return [action]
  69. },
  70. }
  71. export default actionPlugin