diff --git a/app/components/Breadcrumb.js b/app/components/Breadcrumb.js index f567a75e..79466dc4 100644 --- a/app/components/Breadcrumb.js +++ b/app/components/Breadcrumb.js @@ -1,11 +1,13 @@ // @flow import { observer, inject } from "mobx-react"; import { - PadlockIcon, + ArchiveIcon, + EditIcon, GoToIcon, MoreIcon, + PadlockIcon, ShapesIcon, - EditIcon, + TrashIcon, } from "outline-icons"; import * as React from "react"; import { Link } from "react-router-dom"; @@ -25,11 +27,73 @@ type Props = { onlyText: boolean, }; -const Breadcrumb = observer(({ document, collections, onlyText }: Props) => { - const collection = collections.get(document.collectionId); - if (!collection) return
; +function Icon({ document }) { + if (document.isDeleted) { + return ( + <> + + +   + Trash + + + + ); + } + if (document.isArchived) { + return ( + <> + + +   + Archive + + + + ); + } + if (document.isDraft) { + return ( + <> + + +   + Drafts + + + + ); + } + if (document.isTemplate) { + return ( + <> + + +   + Templates + + + + ); + } + return null; +} - const path = collection.pathToDocument(document).slice(0, -1); +const Breadcrumb = observer(({ document, collections, onlyText }: Props) => { + let collection = collections.get(document.collectionId); + if (!collection) { + if (!document.deletedAt) return
; + + collection = { + id: document.collectionId, + name: "Deleted Collection", + color: "currentColor", + }; + } + + const path = collection.pathToDocument + ? collection.pathToDocument(document).slice(0, -1) + : []; if (onlyText === true) { return ( @@ -50,34 +114,13 @@ const Breadcrumb = observer(({ document, collections, onlyText }: Props) => { ); } - const isTemplate = document.isTemplate; - const isDraft = !document.publishedAt && !isTemplate; const isNestedDocument = path.length > 1; const lastPath = path.length ? path[path.length - 1] : undefined; const menuPath = isNestedDocument ? path.slice(0, -1) : []; return ( - {isTemplate && ( - <> - - -   - Templates - - - - )} - {isDraft && ( - <> - - -   - Drafts - - - - )} +   diff --git a/app/components/CollectionIcon.js b/app/components/CollectionIcon.js index 3d1e4fda..3efe7ebb 100644 --- a/app/components/CollectionIcon.js +++ b/app/components/CollectionIcon.js @@ -18,7 +18,7 @@ function ResolvedCollectionIcon({ collection, expanded, size, ui }: Props) { // If the chosen icon color is very dark then we invert it in dark mode // otherwise it will be impossible to see against the dark background. const color = - ui.resolvedTheme === "dark" + ui.resolvedTheme === "dark" && collection.color !== "currentColor" ? getLuminance(collection.color) > 0.12 ? collection.color : "currentColor" diff --git a/app/menus/DocumentMenu.js b/app/menus/DocumentMenu.js index 7bd7a00c..d7eb6539 100644 --- a/app/menus/DocumentMenu.js +++ b/app/menus/DocumentMenu.js @@ -11,7 +11,12 @@ import Document from "models/Document"; import DocumentDelete from "scenes/DocumentDelete"; import DocumentShare from "scenes/DocumentShare"; import DocumentTemplatize from "scenes/DocumentTemplatize"; -import { DropdownMenu, DropdownMenuItem } from "components/DropdownMenu"; +import CollectionIcon from "components/CollectionIcon"; +import { + DropdownMenu, + DropdownMenuItem, + Header, +} from "components/DropdownMenu"; import Modal from "components/Modal"; import { documentHistoryUrl, @@ -100,8 +105,11 @@ class DocumentMenu extends React.Component { this.props.ui.showToast("Document archived"); }; - handleRestore = async (ev: SyntheticEvent<>) => { - await this.props.document.restore(); + handleRestore = async ( + ev: SyntheticEvent<>, + options?: { collectionId: string } + ) => { + await this.props.document.restore(options); this.props.ui.showToast("Document restored"); }; @@ -154,6 +162,7 @@ class DocumentMenu extends React.Component { showPrint, showPin, auth, + collections, onOpen, onClose, } = this.props; @@ -161,6 +170,7 @@ class DocumentMenu extends React.Component { const can = policies.abilities(document.id); const canShareDocuments = can.share && auth.team && auth.team.sharing; const canViewHistory = can.read && !can.restore; + const collection = collections.get(document.collectionId); return ( <> @@ -170,11 +180,45 @@ class DocumentMenu extends React.Component { onOpen={onOpen} onClose={onClose} > - {(can.unarchive || can.restore) && ( + {can.unarchive && ( Restore )} + {can.restore && + (collection ? ( + + Restore + + ) : ( + Restore…} + style={{ + left: -170, + position: "relative", + top: -40, + }} + hover + > +
Choose a collection
+ {collections.orderedData.map((collection) => { + const can = policies.abilities(collection.id); + + return ( + + this.handleRestore(ev, { collectionId: collection.id }) + } + disabled={!can.update} + > + +  {collection.name} + + ); + })} +
+ ))} {showPin && (document.pinned ? can.unpin && ( diff --git a/app/menus/RevisionMenu.js b/app/menus/RevisionMenu.js index 0f4578ee..888ee0eb 100644 --- a/app/menus/RevisionMenu.js +++ b/app/menus/RevisionMenu.js @@ -24,7 +24,7 @@ type Props = { class RevisionMenu extends React.Component { handleRestore = async (ev: SyntheticEvent<>) => { ev.preventDefault(); - await this.props.document.restore(this.props.revision); + await this.props.document.restore({ revisionId: this.props.revision.id }); this.props.ui.showToast("Document restored"); this.props.history.push(this.props.document.url); }; diff --git a/app/models/Document.js b/app/models/Document.js index 86d3fb71..7538fe92 100644 --- a/app/models/Document.js +++ b/app/models/Document.js @@ -6,7 +6,6 @@ import parseTitle from "shared/utils/parseTitle"; import unescape from "shared/utils/unescape"; import DocumentsStore from "stores/DocumentsStore"; import BaseModel from "models/BaseModel"; -import Revision from "models/Revision"; import User from "models/User"; type SaveOptions = { @@ -141,8 +140,8 @@ export default class Document extends BaseModel { return this.store.archive(this); }; - restore = (revision: Revision) => { - return this.store.restore(this, revision); + restore = (options) => { + return this.store.restore(this, options); }; unpublish = () => { diff --git a/app/scenes/CollectionDelete.js b/app/scenes/CollectionDelete.js index 098a4ab3..44c26294 100644 --- a/app/scenes/CollectionDelete.js +++ b/app/scenes/CollectionDelete.js @@ -46,8 +46,9 @@ class CollectionDelete extends React.Component {
Are you sure about that? Deleting the{" "} - {collection.name} collection is permanent and will - also delete all of the documents within it, so be extra careful. + {collection.name} collection is permanent and + cannot be restored, however documents within will be moved to the + trash.