import { ActionIcon, Group, Menu, Text, Tooltip, UnstyledButton, } from "@mantine/core"; import { IconArrowDown, IconDots, IconEye, IconEyeOff, IconFileExport, IconHome, IconPlus, IconSearch, IconSettings, IconStar, IconStarFilled, IconTemplate, 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 from "react"; import { useAtom } from "jotai"; import { useTreeMutation } from "@/features/page/tree/hooks/use-tree-mutation.ts"; import { Link, useLocation, 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 { getSpaceUrl } from "@/lib/config.ts"; import SpaceTree 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"; import { mobileSidebarAtom } from "@/components/layouts/global/hooks/atoms/sidebar-atom.ts"; import { useToggleSidebar } from "@/components/layouts/global/hooks/hooks/use-toggle-sidebar.ts"; import { searchSpotlight } from "@/features/search/constants"; const TemplatePickerModal = React.lazy( () => import("@/ee/template/components/template-picker-modal"), ); import { useHasFeature } from "@/ee/hooks/use-feature"; import { useUpgradeLabel } from "@/ee/hooks/use-upgrade-label"; import { Feature } from "@/ee/features"; import { ErrorBoundary } from "react-error-boundary"; export function SpaceSidebar() { const { t } = useTranslation(); const location = useLocation(); const [opened, { open: openSettings, close: closeSettings }] = useDisclosure(false); const [mobileSidebarOpened] = useAtom(mobileSidebarAtom); const toggleMobileSidebar = useToggleSidebar(mobileSidebarAtom); const { spaceSlug } = useParams(); const { data: space } = useGetSpaceBySlugQuery(spaceSlug); const spaceRules = space?.membership?.permissions; const spaceAbility = useSpaceAbility(spaceRules); const { handleCreate } = useTreeMutation(space?.id ?? ""); if (!space) { return <>; } function handleCreatePage() { handleCreate(null); } return ( <>
{t("Overview")}
{t("Search")}
{t("Space settings")}
{spaceAbility.can( SpaceCaslAction.Manage, SpaceCaslSubject.Page, ) && ( { handleCreatePage(); if (mobileSidebarOpened) { toggleMobileSidebar(); } }} >
{t("New page")}
)}
{t("Pages")} {spaceAbility.can( SpaceCaslAction.Manage, SpaceCaslSubject.Page, ) && ( )}
); } interface SpaceMenuProps { spaceId: string; canManagePages: boolean; onSpaceSettings: () => void; } function SpaceMenu({ spaceId, canManagePages, onSpaceSettings, }: SpaceMenuProps) { const { t } = useTranslation(); const { spaceSlug } = useParams(); const [importOpened, { open: openImportModal, close: closeImportModal }] = useDisclosure(false); const [exportOpened, { open: openExportModal, close: closeExportModal }] = useDisclosure(false); const [ templatePickerOpened, { open: openTemplatePicker, close: closeTemplatePicker }, ] = useDisclosure(false); const hasTemplates = useHasFeature(Feature.TEMPLATES); const upgradeLabel = useUpgradeLabel(); 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 ( <> ) : ( ) } > {isFavorited ? t("Remove from favorites") : t("Add to favorites")} : } > {isWatching ? t("Stop watching space") : t("Watch space")} {canManagePages && ( <> } data-disabled={!hasTemplates || undefined} aria-disabled={!hasTemplates || undefined} > {t("Templates")} )} {canManagePages && ( <> } > {t("Import pages")} } > {t("Export space")} } > {t("Space settings")} } > {t("Trash")} )} {canManagePages && ( <> )} {hasTemplates && templatePickerOpened && ( null}> )} ); }