import { observer } from "mobx-react"; import { NewDocumentIcon, PlusIcon, PinIcon, MoreIcon } from "outline-icons"; import * as React from "react"; import Dropzone from "react-dropzone"; import { useTranslation, Trans } from "react-i18next"; import { useParams, Redirect, Link, Switch, Route, useHistory, useRouteMatch, } from "react-router-dom"; import styled, { css } from "styled-components"; import Collection from "~/models/Collection"; import CollectionPermissions from "~/scenes/CollectionPermissions"; import Search from "~/scenes/Search"; import { Action, Separator } from "~/components/Actions"; import Badge from "~/components/Badge"; import Button from "~/components/Button"; import CenteredContent from "~/components/CenteredContent"; import CollectionDescription from "~/components/CollectionDescription"; import CollectionIcon from "~/components/CollectionIcon"; import DocumentList from "~/components/DocumentList"; import Flex from "~/components/Flex"; import Heading from "~/components/Heading"; import HelpText from "~/components/HelpText"; import InputSearchPage from "~/components/InputSearchPage"; import PlaceholderList from "~/components/List/Placeholder"; import LoadingIndicator from "~/components/LoadingIndicator"; import Modal from "~/components/Modal"; import PaginatedDocumentList from "~/components/PaginatedDocumentList"; import PlaceholderText from "~/components/PlaceholderText"; import Scene from "~/components/Scene"; import Subheading from "~/components/Subheading"; import Tab from "~/components/Tab"; import Tabs from "~/components/Tabs"; import Tooltip from "~/components/Tooltip"; import { editCollection } from "~/actions/definitions/collections"; import useBoolean from "~/hooks/useBoolean"; import useCommandBarActions from "~/hooks/useCommandBarActions"; import useCurrentTeam from "~/hooks/useCurrentTeam"; import useImportDocument from "~/hooks/useImportDocument"; import useStores from "~/hooks/useStores"; import useToasts from "~/hooks/useToasts"; import CollectionMenu from "~/menus/CollectionMenu"; import { newDocumentPath, collectionUrl, updateCollectionUrl, } from "~/utils/routeHelpers"; function CollectionScene() { const params = useParams<{ id?: string }>(); const history = useHistory(); const match = useRouteMatch(); const { t } = useTranslation(); const { documents, policies, collections, ui } = useStores(); const { showToast } = useToasts(); const team = useCurrentTeam(); const [isFetching, setFetching] = React.useState(false); const [error, setError] = React.useState(); const [ permissionsModalOpen, handlePermissionsModalOpen, handlePermissionsModalClose, ] = useBoolean(); const id = params.id || ""; const collection: Collection | null | undefined = collections.getByUrl(id) || collections.get(id); const can = policies.abilities(collection?.id || ""); const canUser = policies.abilities(team.id); const { handleFiles, isImporting } = useImportDocument(collection?.id || ""); React.useEffect(() => { if (collection) { const canonicalUrl = updateCollectionUrl(match.url, collection); if (match.url !== canonicalUrl) { history.replace(canonicalUrl); } } }, [collection, history, id, match.url]); React.useEffect(() => { if (collection) { ui.setActiveCollection(collection); } }, [ui, collection]); React.useEffect(() => { setError(undefined); if (collection) { documents.fetchPinned({ collectionId: collection.id, }); } }, [documents, collection]); React.useEffect(() => { async function load() { if ((!can || !collection) && !error && !isFetching) { try { setError(undefined); setFetching(true); await collections.fetch(id); } catch (err) { setError(err); } finally { setFetching(false); } } } load(); }, [collections, isFetching, collection, error, id, can]); useCommandBarActions([editCollection]); const handleRejection = React.useCallback(() => { showToast( t("Document not supported – try Markdown, Plain text, HTML, or Word"), { type: "error", } ); }, [t, showToast]); if (!collection && error) { return ; } const pinnedDocuments = collection ? documents.pinnedInCollection(collection.id) : []; const collectionName = collection ? collection.name : ""; const hasPinnedDocuments = !!pinnedDocuments.length; return collection ? (   {collection.name} } actions={ <> {can.update && ( <> )} ( )}    ) : ( <> {" "} {collection.name}{" "} {!collection.permission && ( {t("Private")} )} {hasPinnedDocuments && ( <> {" "} {t("Pinned")} )} {t("Documents")} {t("Recently updated")} {t("Recently published")} {t("Least recently updated")} {t("A–Z")} )} {t("Drop documents to import")} )} ) : ( ); } const DropMessage = styled(HelpText)` opacity: 0; pointer-events: none; `; const DropzoneContainer = styled.div<{ isDragActive?: boolean }>` outline-color: transparent !important; min-height: calc(100% - 56px); position: relative; ${({ isDragActive, theme }) => isDragActive && css` &:after { display: block; content: ""; position: absolute; top: 24px; right: 24px; bottom: 24px; left: 24px; background: ${theme.background}; border-radius: 8px; border: 1px dashed ${theme.divider}; z-index: 1; } ${DropMessage} { opacity: 1; z-index: 2; position: absolute; text-align: center; top: 50%; left: 50%; transform: translateX(-50%); } `} `; const Centered = styled(Flex)` text-align: center; margin: 40vh auto 0; max-width: 380px; transform: translateY(-50%); `; const TinyPinIcon = styled(PinIcon)` position: relative; top: 4px; opacity: 0.8; `; const Empty = styled(Flex)` justify-content: center; margin: 10px 0; `; export default observer(CollectionScene);