diff --git a/app/components/Sidebar/components/CollectionLink.js b/app/components/Sidebar/components/CollectionLink.js new file mode 100644 index 00000000..9cf95290 --- /dev/null +++ b/app/components/Sidebar/components/CollectionLink.js @@ -0,0 +1,95 @@ +// @flow +import * as React from 'react'; +import { observer } from 'mobx-react'; +import { observable } from 'mobx'; +import { CollectionIcon } from 'outline-icons'; +import styled from 'styled-components'; +import Collection from 'models/Collection'; +import Document from 'models/Document'; +import CollectionMenu from 'menus/CollectionMenu'; +import UiStore from 'stores/UiStore'; +import SidebarLink from './SidebarLink'; +import DocumentLink from './DocumentLink'; +import DropToImport from 'components/DropToImport'; +import Flex from 'shared/components/Flex'; + +type Props = { + history: Object, + collection: Collection, + ui: UiStore, + activeDocument: ?Document, + prefetchDocument: (id: string) => Promise, +}; + +@observer +class CollectionLink extends React.Component { + @observable menuOpen = false; + + render() { + const { + history, + collection, + activeDocument, + prefetchDocument, + ui, + } = this.props; + const expanded = collection.id === ui.activeCollectionId; + + return ( + + } + iconColor={collection.color} + expand={expanded} + hideExpandToggle + expandedContent={ + + {collection.documents.map(document => ( + + ))} + + } + menu={ + (this.menuOpen = true)} + onClose={() => (this.menuOpen = false)} + /> + } + > + + {collection.name} + + + + ); + } +} + +const CollectionName = styled(Flex)` + padding: 0 0 4px; +`; + +const CollectionChildren = styled(Flex)` + margin-top: -4px; + margin-left: 36px; + padding-bottom: 4px; +`; + +export default CollectionLink; diff --git a/app/components/Sidebar/components/Collections.js b/app/components/Sidebar/components/Collections.js index 3d753e99..07af42fe 100644 --- a/app/components/Sidebar/components/Collections.js +++ b/app/components/Sidebar/components/Collections.js @@ -1,24 +1,17 @@ // @flow import * as React from 'react'; -import { observable } from 'mobx'; import { observer, inject } from 'mobx-react'; import type { Location } from 'react-router-dom'; import Flex from 'shared/components/Flex'; -import styled from 'styled-components'; -import { color } from 'shared/styles/constants'; -import { PlusIcon, CollectionIcon } from 'outline-icons'; +import { PlusIcon } from 'outline-icons'; import Header from './Header'; import SidebarLink from './SidebarLink'; -import DropToImport from 'components/DropToImport'; -import CollectionMenu from 'menus/CollectionMenu'; +import CollectionLink from './CollectionLink'; import CollectionsStore from 'stores/CollectionsStore'; import UiStore from 'stores/UiStore'; -import Document from 'models/Document'; -import Collection from 'models/Collection'; import DocumentsStore from 'stores/DocumentsStore'; -import { type NavigationNode } from 'types'; type Props = { history: Object, @@ -62,201 +55,4 @@ class Collections extends React.Component { } } -type CollectionLinkProps = { - history: Object, - collection: Collection, - ui: UiStore, - activeDocument: ?Document, - prefetchDocument: (id: string) => Promise, -}; - -@observer -class CollectionLink extends React.Component<*> { - props: CollectionLinkProps; - - @observable menuOpen = false; - - renderDocuments() { - const { - history, - collection, - activeDocument, - prefetchDocument, - } = this.props; - - return ( - - {collection.documents.map(document => ( - - ))} - - ); - } - - render() { - const { history, collection, ui } = this.props; - const expanded = collection.id === ui.activeCollectionId; - - return ( - - } - iconColor={collection.color} - expandedContent={this.renderDocuments()} - hideExpandToggle - expand={expanded} - > - - {collection.name} - - - - (this.menuOpen = true)} - onClose={() => (this.menuOpen = false)} - /> - - - ); - } -} - -type DocumentLinkProps = { - document: NavigationNode, - history: Object, - activeDocument: ?Document, - activeDocumentRef: HTMLElement => void, - prefetchDocument: (documentId: string) => void, - depth: number, -}; - -const DocumentLink = observer( - ({ - document, - activeDocument, - activeDocumentRef, - prefetchDocument, - depth, - history, - }: DocumentLinkProps) => { - const isActiveDocument = - activeDocument && activeDocument.id === document.id; - const showChildren = !!( - activeDocument && - (activeDocument.pathToDocument - .map(entry => entry.id) - .includes(document.id) || - isActiveDocument) - ); - - const handleMouseEnter = (event: SyntheticEvent<*>) => { - event.stopPropagation(); - event.preventDefault(); - prefetchDocument(document.id); - }; - - return ( - - - - {document.children.map(childDocument => ( - - ))} - - ) : ( - undefined - ) - } - > - {document.title} - - - - ); - } -); - -const CollectionName = styled(Flex)` - padding: 0 0 4px; -`; - -const CollectionAction = styled.span` - position: absolute; - right: 0; - top: 0; - color: ${color.slate}; - svg { - opacity: 0.75; - } - - &:hover { - svg { - opacity: 1; - } - } -`; - -const StyledDropToImport = styled(DropToImport)` - position: relative; - - ${CollectionAction} { - display: ${props => (props.menuOpen ? 'inline' : 'none')}; - } - - &:hover { - ${CollectionAction} { - display: inline; - } - } -`; - -const CollectionChildren = styled(Flex)` - margin-top: -4px; - margin-left: 36px; - padding-bottom: 4px; -`; - -const DocumentChildren = styled(Flex)` - margin-top: -4px; - margin-left: 12px; -`; - export default inject('collections', 'ui', 'documents')(Collections); diff --git a/app/components/Sidebar/components/DocumentLink.js b/app/components/Sidebar/components/DocumentLink.js new file mode 100644 index 00000000..235c6688 --- /dev/null +++ b/app/components/Sidebar/components/DocumentLink.js @@ -0,0 +1,99 @@ +// @flow +import * as React from 'react'; +import { observer } from 'mobx-react'; +import styled from 'styled-components'; +import Document from 'models/Document'; +import DocumentMenu from 'menus/DocumentMenu'; +import SidebarLink from './SidebarLink'; +import DropToImport from 'components/DropToImport'; +import Flex from 'shared/components/Flex'; +import { type NavigationNode } from 'types'; + +type Props = { + document: NavigationNode, + history: Object, + activeDocument: ?Document, + activeDocumentRef?: HTMLElement => void, + prefetchDocument: (documentId: string) => Promise, + depth: number, +}; + +@observer +class DocumentLink extends React.Component { + handleMouseEnter = (ev: SyntheticEvent<*>) => { + const { document, prefetchDocument } = this.props; + + ev.stopPropagation(); + ev.preventDefault(); + prefetchDocument(document.id); + }; + + render() { + const { + document, + activeDocument, + activeDocumentRef, + prefetchDocument, + depth, + history, + } = this.props; + + const isActiveDocument = + activeDocument && activeDocument.id === document.id; + const showChildren = !!( + activeDocument && + (activeDocument.pathToDocument + .map(entry => entry.id) + .includes(document.id) || + isActiveDocument) + ); + + return ( + + + + {document.children.map(childDocument => ( + + ))} + + ) : ( + undefined + ) + } + menu={} + > + {document.title} + + + + ); + } +} + +const DocumentChildren = styled(Flex)` + margin-top: -4px; + margin-left: 12px; +`; + +export default DocumentLink; diff --git a/app/components/Sidebar/components/SidebarLink.js b/app/components/Sidebar/components/SidebarLink.js index e53e3200..4533b776 100644 --- a/app/components/Sidebar/components/SidebarLink.js +++ b/app/components/Sidebar/components/SidebarLink.js @@ -52,6 +52,7 @@ type Props = { icon?: React.Node, expand?: boolean, expandedContent?: React.Node, + menu?: React.Node, hideExpandToggle?: boolean, iconColor?: string, active?: boolean, @@ -90,13 +91,14 @@ class SidebarLink extends React.Component { expandedContent, expand, active, + menu, hideExpandToggle, } = this.props; const Component = to ? StyledNavLink : StyledDiv; const showExpandIcon = expandedContent && !hideExpandToggle; return ( - + { {/* Collection */ expand && hideExpandToggle && expandedContent} {/* Document */ this.expanded && !hideExpandToggle && expandedContent} - + {menu && {menu}} + ); } } +const Action = styled.span` + position: absolute; + right: 0; + top: 0; + color: ${color.slate}; + svg { + opacity: 0.75; + } + + &:hover { + svg { + opacity: 1; + } + } +`; + +const Wrapper = styled(Flex)` + position: relative; + + > ${Action} { + display: ${props => (props.menuOpen ? 'inline' : 'none')}; + } + + &:hover { + > ${Action} { + display: inline; + } + } +`; + const Content = styled.div` width: 100%; `; diff --git a/app/menus/DocumentMenu.js b/app/menus/DocumentMenu.js index 5d76b771..6e06365d 100644 --- a/app/menus/DocumentMenu.js +++ b/app/menus/DocumentMenu.js @@ -15,6 +15,7 @@ type Props = { history: Object, document: Document, className: string, + showPrint?: boolean, }; @observer @@ -56,7 +57,7 @@ class DocumentMenu extends React.Component { }; render() { - const { document, label, className } = this.props; + const { document, label, className, showPrint } = this.props; const isDraft = !document.publishedAt; return ( @@ -84,7 +85,7 @@ class DocumentMenu extends React.Component { onClick={this.handleNewChild} title="Create a new child document for the current document" > - New child + New child document Move… @@ -94,7 +95,9 @@ class DocumentMenu extends React.Component { Download - Print + {showPrint && ( + Print + )} ); } diff --git a/app/scenes/Document/components/Actions.js b/app/scenes/Document/components/Actions.js index 000c79f0..b72fa748 100644 --- a/app/scenes/Document/components/Actions.js +++ b/app/scenes/Document/components/Actions.js @@ -98,7 +98,7 @@ class DocumentActions extends React.Component { )} {!isEditing && ( - + )} {!isEditing &&