mirror of
https://github.com/outline/outline.git
synced 2025-12-20 18:19:43 -06:00
142 lines
3.9 KiB
TypeScript
142 lines
3.9 KiB
TypeScript
import { AnimatePresence } from "framer-motion";
|
|
import { observer } from "mobx-react";
|
|
import * as React from "react";
|
|
import {
|
|
Switch,
|
|
Route,
|
|
useLocation,
|
|
matchPath,
|
|
Redirect,
|
|
} from "react-router-dom";
|
|
import { TeamPreference } from "@shared/types";
|
|
import ErrorSuspended from "~/scenes/Errors/ErrorSuspended";
|
|
import Layout from "~/components/Layout";
|
|
import RegisterKeyDown from "~/components/RegisterKeyDown";
|
|
import Sidebar from "~/components/Sidebar";
|
|
import useCurrentTeam from "~/hooks/useCurrentTeam";
|
|
import { usePostLoginPath } from "~/hooks/useLastVisitedPath";
|
|
import usePolicy from "~/hooks/usePolicy";
|
|
import useStores from "~/hooks/useStores";
|
|
import history from "~/utils/history";
|
|
import lazyWithRetry from "~/utils/lazyWithRetry";
|
|
import {
|
|
searchPath,
|
|
newDocumentPath,
|
|
settingsPath,
|
|
matchDocumentHistory,
|
|
matchDocumentSlug as slug,
|
|
} from "~/utils/routeHelpers";
|
|
import { DocumentContextProvider } from "./DocumentContext";
|
|
import Fade from "./Fade";
|
|
import { PortalContext } from "./Portal";
|
|
import CommandBar from "./CommandBar";
|
|
|
|
const DocumentComments = lazyWithRetry(
|
|
() => import("~/scenes/Document/components/Comments/Comments")
|
|
);
|
|
const DocumentHistory = lazyWithRetry(
|
|
() => import("~/scenes/Document/components/History")
|
|
);
|
|
const SettingsSidebar = lazyWithRetry(
|
|
() => import("~/components/Sidebar/Settings")
|
|
);
|
|
|
|
type Props = {
|
|
children?: React.ReactNode;
|
|
};
|
|
|
|
const AuthenticatedLayout: React.FC = ({ children }: Props) => {
|
|
const { ui, auth } = useStores();
|
|
const location = useLocation();
|
|
const layoutRef = React.useRef<HTMLDivElement>(null);
|
|
const can = usePolicy(ui.activeDocumentId);
|
|
const canCollection = usePolicy(ui.activeCollectionId);
|
|
const team = useCurrentTeam();
|
|
const [spendPostLoginPath] = usePostLoginPath();
|
|
|
|
const goToSearch = (ev: KeyboardEvent) => {
|
|
if (!ev.metaKey && !ev.ctrlKey) {
|
|
ev.preventDefault();
|
|
ev.stopPropagation();
|
|
history.push(searchPath());
|
|
}
|
|
};
|
|
|
|
const goToNewDocument = (event: KeyboardEvent) => {
|
|
if (event.metaKey || event.altKey) {
|
|
return;
|
|
}
|
|
const { activeCollectionId } = ui;
|
|
if (!activeCollectionId || !canCollection.createDocument) {
|
|
return;
|
|
}
|
|
history.push(newDocumentPath(activeCollectionId));
|
|
};
|
|
|
|
if (auth.isSuspended) {
|
|
return <ErrorSuspended />;
|
|
}
|
|
|
|
const postLoginPath = spendPostLoginPath();
|
|
if (postLoginPath) {
|
|
return <Redirect to={postLoginPath} />;
|
|
}
|
|
|
|
const sidebar = (
|
|
<Fade>
|
|
<Switch>
|
|
<Route path={settingsPath()} component={SettingsSidebar} />
|
|
<Route component={Sidebar} />
|
|
</Switch>
|
|
</Fade>
|
|
);
|
|
|
|
const showHistory =
|
|
!!matchPath(location.pathname, {
|
|
path: matchDocumentHistory,
|
|
}) && can.listRevisions;
|
|
const showComments =
|
|
!showHistory &&
|
|
can.comment &&
|
|
ui.activeDocumentId &&
|
|
ui.commentsExpanded &&
|
|
!!team.getPreference(TeamPreference.Commenting);
|
|
|
|
const sidebarRight = (
|
|
<AnimatePresence
|
|
initial={false}
|
|
key={ui.activeDocumentId ? "active" : "inactive"}
|
|
>
|
|
{(showHistory || showComments) && (
|
|
<Route path={`/doc/${slug}`}>
|
|
<React.Suspense fallback={null}>
|
|
{showHistory && <DocumentHistory />}
|
|
{showComments && <DocumentComments />}
|
|
</React.Suspense>
|
|
</Route>
|
|
)}
|
|
</AnimatePresence>
|
|
);
|
|
|
|
return (
|
|
<DocumentContextProvider>
|
|
<PortalContext.Provider value={layoutRef.current}>
|
|
<Layout
|
|
title={team.name}
|
|
sidebar={sidebar}
|
|
sidebarRight={sidebarRight}
|
|
ref={layoutRef}
|
|
>
|
|
<RegisterKeyDown trigger="n" handler={goToNewDocument} />
|
|
<RegisterKeyDown trigger="t" handler={goToSearch} />
|
|
<RegisterKeyDown trigger="/" handler={goToSearch} />
|
|
{children}
|
|
<CommandBar />
|
|
</Layout>
|
|
</PortalContext.Provider>
|
|
</DocumentContextProvider>
|
|
);
|
|
};
|
|
|
|
export default observer(AuthenticatedLayout);
|