Files
outline/app/scenes/DocumentMove.tsx
Tom Moor d8b4fef554 feat: Collection admins (#5273
* Split permissions for reading documents from updating collection

* fix: Admins should have collection read permission, tests

* tsc

* Add admin option to permission selector

* Combine publish and create permissions, update -> createDocuments where appropriate

* Plural -> singular

* wip

* Quick version of collection structure loading, will revisit

* Remove documentIds method

* stash

* fixing tests to account for admin creation

* Add self-hosted migration

* fix: Allow groups to have admin permission

* Prefetch collection documents

* fix: Document explorer (move/publish) not working with async documents

* fix: Cannot re-parent document to collection by drag and drop

* fix: Cannot drag to import into collection item without admin permission

* Remove unused isEditor getter
2023-04-30 06:38:47 -07:00

130 lines
3.4 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { flatten } from "lodash";
import { observer } from "mobx-react";
import * as React from "react";
import { useTranslation, Trans } from "react-i18next";
import styled from "styled-components";
import { ellipsis } from "@shared/styles";
import { NavigationNode } from "@shared/types";
import Document from "~/models/Document";
import Button from "~/components/Button";
import DocumentExplorer from "~/components/DocumentExplorer";
import Flex from "~/components/Flex";
import Text from "~/components/Text";
import useCollectionTrees from "~/hooks/useCollectionTrees";
import useStores from "~/hooks/useStores";
import useToasts from "~/hooks/useToasts";
import { flattenTree } from "~/utils/tree";
type Props = {
document: Document;
};
function DocumentMove({ document }: Props) {
const { dialogs } = useStores();
const { showToast } = useToasts();
const { t } = useTranslation();
const collectionTrees = useCollectionTrees();
const [selectedPath, selectPath] = React.useState<NavigationNode | null>(
null
);
const items = React.useMemo(() => {
// Filter out the document itself and its existing parent doc, if any.
const nodes = flatten(collectionTrees.map(flattenTree)).filter(
(node) => node.id !== document.id && node.id !== document.parentDocumentId
);
// If the document we're moving is a template, only show collections as
// move targets.
if (document.isTemplate) {
return nodes
.filter((node) => node.type === "collection")
.map((node) => ({ ...node, children: [] }));
}
return nodes;
}, [
collectionTrees,
document.id,
document.parentDocumentId,
document.isTemplate,
]);
const move = async () => {
if (!selectedPath) {
showToast(t("Select a location to move"), {
type: "info",
});
return;
}
try {
const { type, id: parentDocumentId } = selectedPath;
const collectionId = selectedPath.collectionId as string;
if (type === "document") {
await document.move(collectionId, parentDocumentId);
} else {
await document.move(collectionId);
}
showToast(t("Document moved"), {
type: "success",
});
dialogs.closeAllModals();
} catch (err) {
showToast(t("Couldnt move the document, try again?"), {
type: "error",
});
}
};
return (
<FlexContainer column>
<DocumentExplorer items={items} onSubmit={move} onSelect={selectPath} />
<Footer justify="space-between" align="center" gap={8}>
<StyledText type="secondary">
{selectedPath ? (
<Trans
defaults="Move to <em>{{ location }}</em>"
values={{
location: selectedPath.title,
}}
components={{
em: <strong />,
}}
/>
) : (
t("Select a location to move")
)}
</StyledText>
<Button disabled={!selectedPath} onClick={move}>
{t("Move")}
</Button>
</Footer>
</FlexContainer>
);
}
const FlexContainer = styled(Flex)`
margin-left: -24px;
margin-right: -24px;
margin-bottom: -24px;
outline: none;
`;
const Footer = styled(Flex)`
height: 64px;
border-top: 1px solid ${(props) => props.theme.horizontalRule};
padding-left: 24px;
padding-right: 24px;
`;
const StyledText = styled(Text)`
${ellipsis()}
margin-bottom: 0;
`;
export default observer(DocumentMove);