// @flow
import { observable } from "mobx";
import { observer, inject } from "mobx-react";
import { NewDocumentIcon, PlusIcon, PinIcon } from "outline-icons";
import * as React from "react";
import { withTranslation, Trans, type TFunction } from "react-i18next";
import { Redirect, Link, Switch, Route, type Match } from "react-router-dom";
import styled, { withTheme } from "styled-components";
import CollectionsStore from "stores/CollectionsStore";
import DocumentsStore from "stores/DocumentsStore";
import PoliciesStore from "stores/PoliciesStore";
import UiStore from "stores/UiStore";
import Collection from "models/Collection";
import CollectionEdit from "scenes/CollectionEdit";
import CollectionMembers from "scenes/CollectionMembers";
import Search from "scenes/Search";
import Actions, { Action, Separator } from "components/Actions";
import Button from "components/Button";
import CenteredContent from "components/CenteredContent";
import CollectionIcon from "components/CollectionIcon";
import DocumentList from "components/DocumentList";
import Editor from "components/Editor";
import Flex from "components/Flex";
import Heading from "components/Heading";
import HelpText from "components/HelpText";
import InputSearch from "components/InputSearch";
import { ListPlaceholder } from "components/LoadingPlaceholder";
import Mask from "components/Mask";
import Modal from "components/Modal";
import PageTitle from "components/PageTitle";
import PaginatedDocumentList from "components/PaginatedDocumentList";
import Subheading from "components/Subheading";
import Tab from "components/Tab";
import Tabs from "components/Tabs";
import Tooltip from "components/Tooltip";
import CollectionMenu from "menus/CollectionMenu";
import { type Theme } from "types";
import { AuthorizationError } from "utils/errors";
import { newDocumentUrl, collectionUrl } from "utils/routeHelpers";
type Props = {
ui: UiStore,
documents: DocumentsStore,
collections: CollectionsStore,
policies: PoliciesStore,
match: Match,
theme: Theme,
t: TFunction,
};
@observer
class CollectionScene extends React.Component {
@observable collection: ?Collection;
@observable isFetching: boolean = true;
@observable permissionsModalOpen: boolean = false;
@observable editModalOpen: boolean = false;
@observable redirectTo: ?string;
componentDidMount() {
const { id } = this.props.match.params;
if (id) {
this.loadContent(id);
}
}
componentDidUpdate(prevProps: Props) {
const { id } = this.props.match.params;
if (this.collection) {
const { collection } = this;
const policy = this.props.policies.get(collection.id);
if (!policy) {
this.loadContent(collection.id);
}
}
if (id && id !== prevProps.match.params.id) {
this.loadContent(id);
}
}
componentWillUnmount() {
this.props.ui.clearActiveCollection();
}
loadContent = async (id: string) => {
try {
const collection = await this.props.collections.fetch(id);
if (collection) {
this.props.ui.setActiveCollection(collection);
this.collection = collection;
await this.props.documents.fetchPinned({
collectionId: id,
});
}
} catch (error) {
if (error instanceof AuthorizationError) {
this.collection = null;
}
} finally {
this.isFetching = false;
}
};
onNewDocument = (ev: SyntheticEvent<>) => {
ev.preventDefault();
if (this.collection) {
this.redirectTo = newDocumentUrl(this.collection.id);
}
};
onPermissions = (ev: SyntheticEvent<>) => {
ev.preventDefault();
this.permissionsModalOpen = true;
};
handlePermissionsModalClose = () => {
this.permissionsModalOpen = false;
};
handleEditModalOpen = () => {
this.editModalOpen = true;
};
handleEditModalClose = () => {
this.editModalOpen = false;
};
renderActions() {
const { match, policies, t } = this.props;
const can = policies.abilities(match.params.id || "");
return (
{can.update && (
<>
}>
{t("New doc")}
>
)}
);
}
render() {
const { documents, theme, t } = this.props;
if (this.redirectTo) return ;
if (!this.isFetching && !this.collection) return ;
const pinnedDocuments = this.collection
? documents.pinnedInCollection(this.collection.id)
: [];
const hasPinnedDocuments = !!pinnedDocuments.length;
const collection = this.collection;
const collectionName = collection ? collection.name : "";
return (
{collection ? (
<>
{collection.isEmpty ? (
{{ collectionName }} doesn’t contain any
documents yet.
Get started by creating a new one!
}>
{t("Create a document")}
{collection.private && (
)}
) : (
<>
{" "}
{collection.name}
{collection.description && (
Loading…
}>
)}
{hasPinnedDocuments && (
<>
{t("Pinned")}
>
)}
{t("Recently updated")}
{t("Recently published")}
{t("Least recently updated")}
{t("A–Z")}
>
)}
{this.renderActions()}
>
) : (
<>
>
)}
);
}
}
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 Wrapper = styled(Flex)`
justify-content: center;
margin: 10px 0;
`;
export default withTranslation()(
inject(
"collections",
"policies",
"documents",
"ui"
)(withTheme(CollectionScene))
);