zammad/zammad

View on GitHub
app/frontend/shared/entities/ticket-article/action/plugins/articleDelete.ts

Summary

Maintainability
A
0 mins
Test Coverage
// Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/

import { useConfirmation } from '#shared/composables/useConfirmation.ts'
import type { TicketArticle } from '#shared/entities/ticket/types.ts'
import { useTicketArticleDeleteMutation } from '#shared/entities/ticket-article/graphql/mutations/delete.api.ts'
import { MutationHandler } from '#shared/server/apollo/handler/index.ts'
import { useSessionStore } from '#shared/stores/session.ts'

import type { TicketArticleActionPlugin, TicketArticleAction } from './types.ts'

const deleteAction = async (article: TicketArticle) => {
  const { waitForConfirmation } = useConfirmation()

  const confirmed = await waitForConfirmation(
    __('Are you sure to remove this article?'),
  )

  if (!confirmed) return

  const mutation = new MutationHandler(
    useTicketArticleDeleteMutation({
      variables: { articleId: article.id },
    }),
    { errorNotificationMessage: __('The article could not be deleted.') },
  )

  mutation.send()
}

const hasDeleteTimeframe = (deleteTimeframe: number) =>
  deleteTimeframe && deleteTimeframe > 0

const secondsToDelete = (article: TicketArticle, deleteTimeframe: number) => {
  if (!hasDeleteTimeframe(deleteTimeframe)) return 0

  const now = new Date().getTime()
  const createdAt = new Date(article.createdAt).getTime()
  const secondsSinceCreated = (now - createdAt) / 1000

  if (secondsSinceCreated > deleteTimeframe) return 0

  return deleteTimeframe - secondsSinceCreated
}

const isDeletable = (article: TicketArticle, deleteTimeframe: number) => {
  const session = useSessionStore()

  if (article.author?.id !== session.userId) return false

  if (article.type?.communication && !article.internal) return false

  if (
    hasDeleteTimeframe(deleteTimeframe) &&
    !secondsToDelete(article, deleteTimeframe)
  )
    return false

  return true
}

const actionPlugin: TicketArticleActionPlugin = {
  order: 999,

  addActions(ticket, article, { onDispose, recalculate, config }) {
    const deleteTimeframe =
      config.ui_ticket_zoom_article_delete_timeframe as number

    if (!isDeletable(article, deleteTimeframe)) return []

    const seconds = secondsToDelete(article, deleteTimeframe)

    if (seconds) {
      const timeout = window.setTimeout(() => {
        recalculate()
      }, seconds * 1_000)

      onDispose(() => {
        window.clearTimeout(timeout)
      })
    }

    const action: TicketArticleAction = {
      apps: ['mobile'],
      label: __('Delete Article'),
      name: 'articleDelete',
      icon: 'trash',
      perform: () => deleteAction(article),
      view: {
        agent: ['change'],
      },
    }

    return [action]
  },
}

export default actionPlugin