diff --git a/app/components/DocumentMeta.js b/app/components/DocumentMeta.js index 88afc0b8..4f2366b8 100644 --- a/app/components/DocumentMeta.js +++ b/app/components/DocumentMeta.js @@ -1,39 +1,123 @@ // @flow -import { inject } from "mobx-react"; +import { inject, observer } from "mobx-react"; import * as React from "react"; +import { Link } from "react-router-dom"; import styled from "styled-components"; -import ViewsStore from "stores/ViewsStore"; +import AuthStore from "stores/AuthStore"; +import CollectionsStore from "stores/CollectionsStore"; import Document from "models/Document"; -import PublishingInfo from "components/PublishingInfo"; +import Breadcrumb from "components/Breadcrumb"; +import Flex from "components/Flex"; +import Time from "components/Time"; -type Props = {| - views: ViewsStore, +const Container = styled(Flex)` + color: ${(props) => props.theme.textTertiary}; + font-size: 13px; + white-space: nowrap; + overflow: hidden; +`; + +const Modified = styled.span` + color: ${(props) => + props.highlight ? props.theme.text : props.theme.textTertiary}; + font-weight: ${(props) => (props.highlight ? "600" : "400")}; +`; + +type Props = { + collections: CollectionsStore, + auth: AuthStore, + showCollection?: boolean, + showPublished?: boolean, document: Document, - isDraft: boolean, -|}; + children: React.Node, + to?: string, +}; -function DocumentMeta({ views, isDraft, document }: Props) { - const totalViews = views.countForDocument(document.id); +function DocumentMeta({ + auth, + collections, + showPublished, + showCollection, + document, + children, + to, + ...rest +}: Props) { + const { + modifiedSinceViewed, + updatedAt, + updatedBy, + createdAt, + publishedAt, + archivedAt, + deletedAt, + isDraft, + } = document; + + // Prevent meta information from displaying if updatedBy is not available. + // Currently the situation where this is true is rendering share links. + if (!updatedBy) { + return null; + } + + let content; + + if (deletedAt) { + content = ( + + deleted + ); + } else if (archivedAt) { + content = ( + + archived + ); + } else if (createdAt === updatedAt) { + content = ( + + created + ); + } else if (publishedAt && (publishedAt === updatedAt || showPublished)) { + content = ( + + published + ); + } else if (isDraft) { + content = ( + + saved + ); + } else { + content = ( + + updated + ); + } + + const collection = collections.get(document.collectionId); + const updatedByMe = auth.user && auth.user.id === updatedBy.id; return ( - - {totalViews && !isDraft ? ( - <> -  · Viewed{" "} - {totalViews === 1 ? "once" : `${totalViews} times`} - - ) : null} - + + {updatedByMe ? "You" : updatedBy.name}  + {to ? {content} : content} + {showCollection && collection && ( + +  in  + + + + + )} + {children} + ); } -const Meta = styled(PublishingInfo)` - margin: -12px 0 2em 0; - font-size: 14px; - - @media print { - display: none; - } -`; - -export default inject("views")(DocumentMeta); +export default inject("collections", "auth")(observer(DocumentMeta)); diff --git a/app/components/DocumentMetaWithViews.js b/app/components/DocumentMetaWithViews.js new file mode 100644 index 00000000..cde7cff5 --- /dev/null +++ b/app/components/DocumentMetaWithViews.js @@ -0,0 +1,48 @@ +// @flow +import { inject } from "mobx-react"; +import * as React from "react"; +import styled from "styled-components"; +import ViewsStore from "stores/ViewsStore"; +import Document from "models/Document"; +import DocumentMeta from "components/DocumentMeta"; + +type Props = {| + views: ViewsStore, + document: Document, + isDraft: boolean, + to?: string, +|}; + +function DocumentMetaWithViews({ views, to, isDraft, document }: Props) { + const totalViews = views.countForDocument(document.id); + + return ( + + {totalViews && !isDraft ? ( + <> +  · Viewed{" "} + {totalViews === 1 ? "once" : `${totalViews} times`} + + ) : null} + + ); +} + +const Meta = styled(DocumentMeta)` + margin: -12px 0 2em 0; + font-size: 14px; + + a { + color: inherit; + + &:hover { + text-decoration: underline; + } + } + + @media print { + display: none; + } +`; + +export default inject("views")(DocumentMetaWithViews); diff --git a/app/components/DocumentPreview/DocumentPreview.js b/app/components/DocumentPreview/DocumentPreview.js index 59a0e443..5a800d62 100644 --- a/app/components/DocumentPreview/DocumentPreview.js +++ b/app/components/DocumentPreview/DocumentPreview.js @@ -7,9 +7,9 @@ import styled, { withTheme } from "styled-components"; import Document from "models/Document"; import Badge from "components/Badge"; import Button from "components/Button"; +import DocumentMeta from "components/DocumentMeta"; import Flex from "components/Flex"; import Highlight from "components/Highlight"; -import PublishingInfo from "components/PublishingInfo"; import Tooltip from "components/Tooltip"; import DocumentMenu from "menus/DocumentMenu"; import { newDocumentUrl } from "utils/routeHelpers"; @@ -129,7 +129,7 @@ class DocumentPreview extends React.Component { processResult={this.replaceResultMarks} /> )} - {document.titleWithDefault} - + props.theme.textTertiary}; - font-size: 13px; - white-space: nowrap; - overflow: hidden; -`; - -const Modified = styled.span` - color: ${(props) => - props.highlight ? props.theme.text : props.theme.textTertiary}; - font-weight: ${(props) => (props.highlight ? "600" : "400")}; -`; - -type Props = { - collections: CollectionsStore, - auth: AuthStore, - showCollection?: boolean, - showPublished?: boolean, - document: Document, - children: React.Node, -}; - -function PublishingInfo({ - auth, - collections, - showPublished, - showCollection, - document, - children, - ...rest -}: Props) { - const { - modifiedSinceViewed, - updatedAt, - updatedBy, - createdAt, - publishedAt, - archivedAt, - deletedAt, - isDraft, - } = document; - - // Prevent meta information from displaying if updatedBy is not available. - // Currently the situation where this is true is rendering share links. - if (!updatedBy) { - return null; - } - - let content; - - if (deletedAt) { - content = ( - - deleted - ); - } else if (archivedAt) { - content = ( - - archived - ); - } else if (createdAt === updatedAt) { - content = ( - - created - ); - } else if (publishedAt && (publishedAt === updatedAt || showPublished)) { - content = ( - - published - ); - } else if (isDraft) { - content = ( - - saved - ); - } else { - content = ( - - updated - ); - } - - const collection = collections.get(document.collectionId); - const updatedByMe = auth.user && auth.user.id === updatedBy.id; - - return ( - - {updatedByMe ? "You" : updatedBy.name}  - {content} - {showCollection && collection && ( - -  in  - - - - - )} - {children} - - ); -} - -export default inject("collections", "auth")(observer(PublishingInfo)); diff --git a/app/scenes/Document/components/Editor.js b/app/scenes/Document/components/Editor.js index ae1aa722..1ea00a15 100644 --- a/app/scenes/Document/components/Editor.js +++ b/app/scenes/Document/components/Editor.js @@ -8,10 +8,11 @@ import styled from "styled-components"; import parseTitle from "shared/utils/parseTitle"; import Document from "models/Document"; import ClickablePadding from "components/ClickablePadding"; -import DocumentMeta from "components/DocumentMeta"; +import DocumentMetaWithViews from "components/DocumentMetaWithViews"; import Editor from "components/Editor"; import Flex from "components/Flex"; import HoverPreview from "components/HoverPreview"; +import { documentHistoryUrl } from "utils/routeHelpers"; type Props = { onChangeTitle: (event: SyntheticInputEvent<>) => void, @@ -88,7 +89,11 @@ class DocumentEditor extends React.Component { autoFocus={!title} maxLength={100} /> - + { > {document.title} {document.updatedBy && ( - + )} );