Move template management to settings (#5811)

This commit is contained in:
Tom Moor
2023-09-10 15:46:12 -04:00
committed by GitHub
parent ac068c0c07
commit 0856f5f6ae
32 changed files with 432 additions and 267 deletions

View File

@@ -12,7 +12,7 @@ import { MenuInternalLink } from "~/types";
import {
archivePath,
collectionPath,
templatesPath,
settingsPath,
trashPath,
} from "~/utils/routeHelpers";
import EmojiIcon from "./Icons/EmojiIcon";
@@ -44,12 +44,12 @@ function useCategory(document: Document): MenuInternalLink | null {
};
}
if (document.isTemplate) {
if (document.template) {
return {
type: "route",
icon: <ShapesIcon />,
title: t("Templates"),
to: templatesPath(),
to: settingsPath("templates"),
};
}

View File

@@ -1,5 +1,4 @@
import { observer } from "mobx-react";
import { PlusIcon } from "outline-icons";
import * as React from "react";
import { useTranslation } from "react-i18next";
import { Link } from "react-router-dom";
@@ -9,7 +8,6 @@ import breakpoint from "styled-components-breakpoint";
import { s } from "@shared/styles";
import Document from "~/models/Document";
import Badge from "~/components/Badge";
import Button from "~/components/Button";
import DocumentMeta from "~/components/DocumentMeta";
import EventBoundary from "~/components/EventBoundary";
import Flex from "~/components/Flex";
@@ -18,12 +16,10 @@ import NudeButton from "~/components/NudeButton";
import StarButton, { AnimatedStar } from "~/components/Star";
import Tooltip from "~/components/Tooltip";
import useBoolean from "~/hooks/useBoolean";
import useCurrentTeam from "~/hooks/useCurrentTeam";
import useCurrentUser from "~/hooks/useCurrentUser";
import usePolicy from "~/hooks/usePolicy";
import DocumentMenu from "~/menus/DocumentMenu";
import { hover } from "~/styles";
import { newDocumentPath } from "~/utils/routeHelpers";
import { documentPath } from "~/utils/routeHelpers";
import EmojiIcon from "./Icons/EmojiIcon";
type Props = {
@@ -52,7 +48,6 @@ function DocumentListItem(
) {
const { t } = useTranslation();
const user = useCurrentUser();
const team = useCurrentTeam();
const [menuOpen, handleMenuOpen, handleMenuClose] = useBoolean();
const {
@@ -72,8 +67,6 @@ function DocumentListItem(
!!document.title.toLowerCase().includes(highlight.toLowerCase());
const canStar =
!document.isDraft && !document.isArchived && !document.isTemplate;
const can = usePolicy(team);
const canCollection = usePolicy(document.collectionId);
return (
<CompositeItem
@@ -84,7 +77,7 @@ function DocumentListItem(
$isStarred={document.isStarred}
$menuOpen={menuOpen}
to={{
pathname: document.url,
pathname: documentPath(document),
state: {
title: document.titleWithDefault,
},
@@ -142,25 +135,6 @@ function DocumentListItem(
/>
</Content>
<Actions>
{document.isTemplate &&
!document.isArchived &&
!document.isDeleted &&
can.createDocument &&
canCollection.update && (
<>
<Button
as={Link}
to={newDocumentPath(document.collectionId, {
templateId: document.id,
})}
icon={<PlusIcon />}
neutral
>
{t("New doc")}
</Button>
&nbsp;
</>
)}
<DocumentMenu
document={document}
showPin={showPin}

View File

@@ -1,4 +1,4 @@
import { LocationDescriptor } from "history";
import { LocationDescriptor, LocationDescriptorObject } from "history";
import * as React from "react";
import { match, NavLink, Route } from "react-router-dom";
@@ -9,10 +9,20 @@ type Props = React.ComponentProps<typeof NavLink> & {
[x: string]: string | undefined;
}>
| boolean
| null
| null,
location: LocationDescriptorObject
) => React.ReactNode;
/**
* If true, the tab will only be active if the path matches exactly.
*/
exact?: boolean;
/**
* CSS properties to apply to the link when it is active.
*/
activeStyle?: React.CSSProperties;
/**
* The path to match against the current location.
*/
to: LocationDescriptor;
};
@@ -25,7 +35,10 @@ function NavLinkWithChildrenFunc(
{({ match, location }) => (
<NavLink {...rest} to={to} exact={exact} ref={ref}>
{children
? children(rest.isActive ? rest.isActive(match, location) : match)
? children(
rest.isActive ? rest.isActive(match, location) : match,
location
)
: null}
</NavLink>
)}

View File

@@ -1,11 +1,5 @@
import { observer } from "mobx-react";
import {
EditIcon,
SearchIcon,
ShapesIcon,
HomeIcon,
SidebarIcon,
} from "outline-icons";
import { EditIcon, SearchIcon, HomeIcon, SidebarIcon } from "outline-icons";
import * as React from "react";
import { DndProvider } from "react-dnd";
import { HTML5Backend } from "react-dnd-html5-backend";
@@ -21,12 +15,7 @@ import usePolicy from "~/hooks/usePolicy";
import useStores from "~/hooks/useStores";
import OrganizationMenu from "~/menus/OrganizationMenu";
import { metaDisplay } from "~/utils/keyboard";
import {
homePath,
draftsPath,
templatesPath,
searchPath,
} from "~/utils/routeHelpers";
import { homePath, draftsPath, searchPath } from "~/utils/routeHelpers";
import TeamLogo from "../TeamLogo";
import Tooltip from "../Tooltip";
import Sidebar from "./Sidebar";
@@ -52,7 +41,6 @@ function AppSidebar() {
React.useEffect(() => {
if (!user.isViewer) {
void documents.fetchDrafts();
void documents.fetchTemplates();
}
}, [documents, user.isViewer]);
@@ -138,19 +126,6 @@ function AppSidebar() {
<Section>
{can.createDocument && (
<>
<SidebarLink
to={templatesPath()}
icon={<ShapesIcon />}
exact={false}
label={t("Templates")}
active={
documents.active
? documents.active.isTemplate &&
!documents.active.isDeleted &&
!documents.active.isArchived
: undefined
}
/>
<ArchiveLink />
<TrashLink />
</>

View File

@@ -3,7 +3,7 @@ import { observer } from "mobx-react";
import { BackIcon, SidebarIcon } from "outline-icons";
import * as React from "react";
import { useTranslation } from "react-i18next";
import { useHistory } from "react-router-dom";
import { useHistory, useLocation } from "react-router-dom";
import styled from "styled-components";
import Flex from "~/components/Flex";
import Scrollable from "~/components/Scrollable";
@@ -11,6 +11,7 @@ import useSettingsConfig from "~/hooks/useSettingsConfig";
import useStores from "~/hooks/useStores";
import isCloudHosted from "~/utils/isCloudHosted";
import { metaDisplay } from "~/utils/keyboard";
import { settingsPath } from "~/utils/routeHelpers";
import Tooltip from "../Tooltip";
import Sidebar from "./Sidebar";
import Header from "./components/Header";
@@ -25,6 +26,7 @@ function SettingsSidebar() {
const { ui } = useStores();
const { t } = useTranslation();
const history = useHistory();
const location = useLocation();
const configs = useSettingsConfig();
const groupedConfig = groupBy(configs, "group");
@@ -62,6 +64,11 @@ function SettingsSidebar() {
<SidebarLink
key={item.path}
to={item.path}
active={
item.path !== settingsPath()
? location.pathname.startsWith(item.path)
: undefined
}
icon={<item.icon />}
label={item.name}
/>

View File

@@ -1,4 +1,7 @@
import { m } from "framer-motion";
import { LocationDescriptor } from "history";
import isEqual from "lodash/isEqual";
import queryString from "query-string";
import * as React from "react";
import styled, { useTheme } from "styled-components";
import { s } from "@shared/styles";
@@ -6,8 +9,19 @@ import NavLink from "~/components/NavLink";
import { hover } from "~/styles";
type Props = Omit<React.ComponentProps<typeof NavLink>, "children"> & {
to: string;
/**
* The path to match against the current location.
*/
to: LocationDescriptor;
/**
* If true, the tab will only be active if the path matches exactly.
*/
exact?: boolean;
/**
* If true, the tab will only be active if the query string matches exactly.
* By default query string parameters are ignored for location mathing.
*/
exactQueryString?: boolean;
children?: React.ReactNode;
};
@@ -45,24 +59,38 @@ const transition = {
damping: 30,
};
const Tab: React.FC<Props> = ({ children, ...rest }: Props) => {
const Tab: React.FC<Props> = ({
children,
exact,
exactQueryString,
...rest
}: Props) => {
const theme = useTheme();
const activeStyle = {
color: theme.textSecondary,
};
return (
<TabLink {...rest} activeStyle={activeStyle}>
{(match) => (
<TabLink
{...rest}
exact={exact || exactQueryString}
activeStyle={activeStyle}
>
{(match, location) => (
<>
{children}
{match && (
<Active
layoutId="underline"
initial={false}
transition={transition}
/>
)}
{match &&
(!exactQueryString ||
isEqual(
queryString.parse(location.search ?? ""),
queryString.parse(rest.to.search as string)
)) && (
<Active
layoutId="underline"
initial={false}
transition={transition}
/>
)}
</>
)}
</TabLink>