import { ActionIcon, Group, Menu, Text, Tooltip, } from "@mantine/core"; import { IconArrowDown, IconChevronsDown, IconChevronsUp, IconDots, IconEye, IconEyeOff, IconFileExport, IconPlus, IconSettings, IconStar, IconStarFilled, IconTrash, } from "@tabler/icons-react"; import { useSpaceWatchStatusQuery, useWatchSpaceMutation, useUnwatchSpaceMutation, } from "@/features/space/queries/space-watcher-query.ts"; import classes from "./space-sidebar.module.css"; import React, { useRef } from "react"; import { useTreeMutation } from "@/features/page/tree/hooks/use-tree-mutation.ts"; import { Link, useParams } from "react-router-dom"; import clsx from "clsx"; import { useDisclosure } from "@mantine/hooks"; import SpaceSettingsModal from "@/features/space/components/settings-modal.tsx"; import { useGetSpaceBySlugQuery } from "@/features/space/queries/space-query.ts"; import SpaceTree, { SpaceTreeApi, } from "@/features/page/tree/components/space-tree.tsx"; import { useSpaceAbility } from "@/features/space/permissions/use-space-ability.ts"; import { SpaceCaslAction, SpaceCaslSubject, } from "@/features/space/permissions/permissions.type.ts"; import PageImportModal from "@/features/page/components/page-import-modal.tsx"; import { useTranslation } from "react-i18next"; import { SwitchSpace } from "./switch-space"; import ExportModal from "@/components/common/export-modal"; import { useFavoriteIds, useAddFavoriteMutation, useRemoveFavoriteMutation, } from "@/features/favorite/queries/favorite-query"; export function SpaceSidebar() { const { t } = useTranslation(); const [opened, { open: openSettings, close: closeSettings }] = useDisclosure(false); const { spaceSlug } = useParams(); const { data: space } = useGetSpaceBySlugQuery(spaceSlug); const spaceRules = space?.membership?.permissions; const spaceAbility = useSpaceAbility(spaceRules); const { handleCreate } = useTreeMutation(space?.id ?? ""); const treeRef = useRef(null); if (!space) { return <>; } function handleCreatePage() { handleCreate(null); } return ( <>
{t("Pages")} {spaceAbility.can( SpaceCaslAction.Manage, SpaceCaslSubject.Page, ) && ( )}
); } interface SpaceMenuProps { spaceId: string; canManagePages: boolean; onSpaceSettings: () => void; treeRef: React.RefObject; } function SpaceMenu({ spaceId, canManagePages, onSpaceSettings, treeRef, }: SpaceMenuProps) { const { t } = useTranslation(); const handleExpandAll = () => { // Fire-and-forget: expandAll already surfaces its own error notification. // The menu closes on click (consistent with Collapse all), so there is no // in-menu loading state to track here. treeRef.current?.expandAll(); }; const handleCollapseAll = () => { treeRef.current?.collapseAll(); }; const { spaceSlug } = useParams(); const [importOpened, { open: openImportModal, close: closeImportModal }] = useDisclosure(false); const [exportOpened, { open: openExportModal, close: closeExportModal }] = useDisclosure(false); const { data: watchStatus } = useSpaceWatchStatusQuery(spaceId); const watchMutation = useWatchSpaceMutation(); const unwatchMutation = useUnwatchSpaceMutation(); const isWatching = watchStatus?.watching ?? false; const favoriteIds = useFavoriteIds("space"); const addFavoriteMutation = useAddFavoriteMutation(); const removeFavoriteMutation = useRemoveFavoriteMutation(); const isFavorited = favoriteIds.has(spaceId); const handleToggleFavorite = () => { const params = { type: "space" as const, spaceId }; if (isFavorited) { removeFavoriteMutation.mutate(params); } else { addFavoriteMutation.mutate(params); } }; const handleToggleWatch = () => { if (isWatching) { unwatchMutation.mutate(spaceId); } else { watchMutation.mutate(spaceId); } }; return ( <> } > {t("Expand all")} } > {t("Collapse all")} ) : ( ) } > {isFavorited ? t("Remove from favorites") : t("Add to favorites")} : } > {isWatching ? t("Stop watching space") : t("Watch space")} {canManagePages && ( <> } > {t("Import pages")} } > {t("Export space")} } > {t("Space settings")} } > {t("Trash")} )} {canManagePages && ( <> )} ); }