/** * Copyright (c) 2023-present Plane Software, Inc. and contributors * SPDX-License-Identifier: AGPL-3.0-only * See the LICENSE file for details. */ import { useState } from "react"; import { observer } from "mobx-react"; import { MoreHorizontalOutline } from "@makeplane/propel/icons"; // ui import { EUserPermissions, EUserPermissionsLevel } from "@plane/constants"; import { useTranslation } from "@plane/i18n"; import { IconButton } from "@plane/propel/icon-button"; import { TOAST_TYPE, setToast } from "@plane/propel/toast"; import type { TContextMenuItem } from "@plane/ui"; import { ContextMenu, CustomMenu } from "@plane/ui"; import { copyUrlToClipboard, cn } from "@plane/utils"; // hooks import { useCycleMenuItems } from "@/components/common/quick-actions-helper"; import { useCycle } from "@/hooks/store/use-cycle"; import { useUserPermissions } from "@/hooks/store/user"; import { useAppRouter } from "@/hooks/use-app-router"; // local imports import { ArchiveCycleModal } from "./archived-cycles/modal"; import { CycleDeleteModal } from "./delete-modal"; import { CycleCreateUpdateModal } from "./modal"; type Props = { parentRef: React.RefObject; cycleId: string; projectId: string; workspaceSlug: string; customClassName?: string; }; export const CycleQuickActions = observer(function CycleQuickActions(props: Props) { const { parentRef, cycleId, projectId, workspaceSlug, customClassName } = props; // router const router = useAppRouter(); // states const [updateModal, setUpdateModal] = useState(false); const [archiveCycleModal, setArchiveCycleModal] = useState(false); const [deleteModal, setDeleteModal] = useState(false); // store hooks const { allowPermissions } = useUserPermissions(); const { getCycleById, restoreCycle } = useCycle(); const { t } = useTranslation(); // derived values const cycleDetails = getCycleById(cycleId); // auth const isEditingAllowed = allowPermissions( [EUserPermissions.ADMIN, EUserPermissions.MEMBER], EUserPermissionsLevel.PROJECT, workspaceSlug, projectId ); const cycleLink = `${workspaceSlug}/projects/${projectId}/cycles/${cycleId}`; const handleCopyText = () => copyUrlToClipboard(cycleLink).then(() => { setToast({ type: TOAST_TYPE.SUCCESS, title: t("common.link_copied"), message: t("common.link_copied_to_clipboard"), }); }); const handleOpenInNewTab = () => window.open(`/${cycleLink}`, "_blank"); const handleRestoreCycle = async () => await restoreCycle(workspaceSlug, projectId, cycleId) .then(() => { setToast({ type: TOAST_TYPE.SUCCESS, title: t("project_cycles.action.restore.success.title"), message: t("project_cycles.action.restore.success.description"), }); router.push(`/${workspaceSlug}/projects/${projectId}/archives/cycles`); }) .catch(() => { setToast({ type: TOAST_TYPE.ERROR, title: t("project_cycles.action.restore.failed.title"), message: t("project_cycles.action.restore.failed.description"), }); }); const menuResult = useCycleMenuItems({ cycleDetails: cycleDetails ?? undefined, workspaceSlug, projectId, cycleId, isEditingAllowed, handleEdit: () => setUpdateModal(true), handleArchive: () => setArchiveCycleModal(true), handleRestore: handleRestoreCycle, handleDelete: () => setDeleteModal(true), handleCopyLink: handleCopyText, handleOpenInNewTab, }); const MENU_ITEMS: TContextMenuItem[] = Array.isArray(menuResult) ? menuResult : menuResult.items; const additionalModals = Array.isArray(menuResult) ? null : menuResult.modals; const CONTEXT_MENU_ITEMS = MENU_ITEMS.map(function CONTEXT_MENU_ITEMS(item) { return { ...item, action: () => { item.action(); }, }; }); return ( <> {cycleDetails && (
setUpdateModal(false)} workspaceSlug={workspaceSlug} projectId={projectId} /> setArchiveCycleModal(false)} /> setDeleteModal(false)} workspaceSlug={workspaceSlug} projectId={projectId} /> {additionalModals}
)} } placement="bottom-end" closeOnSelect maxHeight="lg" buttonClassName={customClassName} > {MENU_ITEMS.map((item) => { if (item.shouldRender === false) return null; return ( { item.action(); }} className={cn( "flex items-center gap-2", { "text-placeholder": item.disabled, }, item.className )} disabled={item.disabled} > {item.icon && }
{item.title}
{item.description && (

{item.description}

)}
); })}
); });