2021-08-23 07:37:28 +00:00
|
|
|
// @flow
|
|
|
|
import { observer } from "mobx-react";
|
|
|
|
import * as React from "react";
|
|
|
|
import { useEffect, useState } from "react";
|
2021-08-25 06:30:55 +00:00
|
|
|
import { useTranslation } from "react-i18next";
|
2021-08-23 07:37:28 +00:00
|
|
|
import styled from "styled-components";
|
|
|
|
import Fade from "components/Fade";
|
|
|
|
import useStores from "../../../hooks/useStores";
|
|
|
|
import Disclosure from "./Disclosure";
|
2021-08-25 06:30:55 +00:00
|
|
|
import EditableTitle from "./EditableTitle";
|
2021-08-23 07:37:28 +00:00
|
|
|
import SidebarLink from "./SidebarLink";
|
|
|
|
import useBoolean from "hooks/useBoolean";
|
|
|
|
import DocumentMenu from "menus/DocumentMenu";
|
|
|
|
|
|
|
|
type Props = {|
|
|
|
|
depth: number,
|
|
|
|
title: string,
|
|
|
|
to: string,
|
|
|
|
documentId: string,
|
|
|
|
collectionId: string,
|
|
|
|
|};
|
|
|
|
|
|
|
|
function StarredLink({ depth, title, to, documentId, collectionId }: Props) {
|
2021-08-25 06:30:55 +00:00
|
|
|
const { t } = useTranslation();
|
|
|
|
const { collections, documents, policies } = useStores();
|
2021-08-23 07:37:28 +00:00
|
|
|
const collection = collections.get(collectionId);
|
|
|
|
const document = documents.get(documentId);
|
|
|
|
const [expanded, setExpanded] = useState(false);
|
|
|
|
const [menuOpen, handleMenuOpen, handleMenuClose] = useBoolean();
|
2021-08-25 06:30:55 +00:00
|
|
|
const canUpdate = policies.abilities(documentId).update;
|
2021-08-23 07:37:28 +00:00
|
|
|
|
|
|
|
const childDocuments = collection
|
|
|
|
? collection.getDocumentChildren(documentId)
|
|
|
|
: [];
|
|
|
|
|
|
|
|
const hasChildDocuments = childDocuments.length > 0;
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
async function load() {
|
|
|
|
if (!document) {
|
|
|
|
await documents.fetch(documentId);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
load();
|
|
|
|
}, [collection, collectionId, collections, document, documentId, documents]);
|
|
|
|
|
|
|
|
const handleDisclosureClick = React.useCallback((ev: SyntheticEvent<>) => {
|
|
|
|
ev.preventDefault();
|
|
|
|
ev.stopPropagation();
|
|
|
|
setExpanded((prevExpanded) => !prevExpanded);
|
|
|
|
}, []);
|
|
|
|
|
2021-08-25 06:30:55 +00:00
|
|
|
const handleTitleChange = React.useCallback(
|
|
|
|
async (title: string) => {
|
|
|
|
if (!document) return;
|
|
|
|
|
|
|
|
await documents.update({
|
|
|
|
id: document.id,
|
|
|
|
lastRevision: document.revision,
|
|
|
|
text: document.text,
|
|
|
|
title,
|
|
|
|
});
|
|
|
|
},
|
|
|
|
[documents, document]
|
|
|
|
);
|
|
|
|
|
2021-08-23 07:37:28 +00:00
|
|
|
return (
|
|
|
|
<>
|
|
|
|
<Relative>
|
|
|
|
<SidebarLink
|
|
|
|
depth={depth}
|
|
|
|
to={to}
|
|
|
|
label={
|
|
|
|
<>
|
|
|
|
{hasChildDocuments && (
|
|
|
|
<Disclosure
|
|
|
|
expanded={expanded}
|
|
|
|
onClick={handleDisclosureClick}
|
|
|
|
/>
|
|
|
|
)}
|
2021-08-25 06:30:55 +00:00
|
|
|
<EditableTitle
|
|
|
|
title={title || t("Untitled")}
|
|
|
|
onSubmit={handleTitleChange}
|
|
|
|
canUpdate={canUpdate}
|
|
|
|
/>
|
2021-08-23 07:37:28 +00:00
|
|
|
</>
|
|
|
|
}
|
|
|
|
exact={false}
|
|
|
|
showActions={menuOpen}
|
|
|
|
menu={
|
|
|
|
document ? (
|
|
|
|
<Fade>
|
|
|
|
<DocumentMenu
|
|
|
|
document={document}
|
|
|
|
onOpen={handleMenuOpen}
|
|
|
|
onClose={handleMenuClose}
|
|
|
|
/>
|
|
|
|
</Fade>
|
|
|
|
) : undefined
|
|
|
|
}
|
|
|
|
/>
|
|
|
|
</Relative>
|
|
|
|
{expanded &&
|
|
|
|
childDocuments.map((childDocument) => (
|
|
|
|
<ObserveredStarredLink
|
|
|
|
key={childDocument.id}
|
|
|
|
depth={depth + 1}
|
|
|
|
title={childDocument.title}
|
|
|
|
to={childDocument.url}
|
|
|
|
documentId={childDocument.id}
|
|
|
|
collectionId={collectionId}
|
|
|
|
/>
|
|
|
|
))}
|
|
|
|
</>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
const Relative = styled.div`
|
|
|
|
position: relative;
|
|
|
|
`;
|
|
|
|
|
|
|
|
const ObserveredStarredLink = observer(StarredLink);
|
|
|
|
|
|
|
|
export default ObserveredStarredLink;
|