feat: Clicking the last updated time should open document history sidebar

Ref #1285
This commit is contained in:
Tom Moor 2020-08-11 21:01:03 -07:00
parent 7abe375b3e
commit 810dc5a061
7 changed files with 172 additions and 155 deletions

View File

@ -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 = (
<span>
deleted <Time dateTime={deletedAt} /> ago
</span>
);
} else if (archivedAt) {
content = (
<span>
archived <Time dateTime={archivedAt} /> ago
</span>
);
} else if (createdAt === updatedAt) {
content = (
<span>
created <Time dateTime={updatedAt} /> ago
</span>
);
} else if (publishedAt && (publishedAt === updatedAt || showPublished)) {
content = (
<span>
published <Time dateTime={publishedAt} /> ago
</span>
);
} else if (isDraft) {
content = (
<span>
saved <Time dateTime={updatedAt} /> ago
</span>
);
} else {
content = (
<Modified highlight={modifiedSinceViewed}>
updated <Time dateTime={updatedAt} /> ago
</Modified>
);
}
const collection = collections.get(document.collectionId);
const updatedByMe = auth.user && auth.user.id === updatedBy.id;
return (
<Meta document={document}>
{totalViews && !isDraft ? (
<>
&nbsp;&middot; Viewed{" "}
{totalViews === 1 ? "once" : `${totalViews} times`}
</>
) : null}
</Meta>
<Container align="center" {...rest}>
{updatedByMe ? "You" : updatedBy.name}&nbsp;
{to ? <Link to={to}>{content}</Link> : content}
{showCollection && collection && (
<span>
&nbsp;in&nbsp;
<strong>
<Breadcrumb document={document} onlyText />
</strong>
</span>
)}
{children}
</Container>
);
}
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));

View File

@ -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 (
<Meta document={document} to={to}>
{totalViews && !isDraft ? (
<>
&nbsp;&middot; Viewed{" "}
{totalViews === 1 ? "once" : `${totalViews} times`}
</>
) : null}
</Meta>
);
}
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);

View File

@ -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<Props> {
processResult={this.replaceResultMarks}
/>
)}
<PublishingInfo
<DocumentMeta
document={document}
showCollection={showCollection}
showPublished={showPublished}

View File

@ -5,7 +5,7 @@ import { Link } from "react-router-dom";
import styled from "styled-components";
import { parseDocumentSlugFromUrl } from "shared/utils/parseDocumentIds";
import DocumentsStore from "stores/DocumentsStore";
import DocumentMeta from "components/DocumentMeta";
import DocumentMetaWithViews from "components/DocumentMetaWithViews";
import Editor from "components/Editor";
type Props = {
@ -27,7 +27,7 @@ function HoverPreviewDocument({ url, documents, children }: Props) {
return children(
<Content to={document.url}>
<Heading>{document.titleWithDefault}</Heading>
<DocumentMeta isDraft={document.isDraft} document={document} />
<DocumentMetaWithViews isDraft={document.isDraft} document={document} />
<Editor
key={document.id}

View File

@ -1,120 +0,0 @@
// @flow
import { inject, observer } from "mobx-react";
import * as React from "react";
import styled from "styled-components";
import AuthStore from "stores/AuthStore";
import CollectionsStore from "stores/CollectionsStore";
import Document from "models/Document";
import Breadcrumb from "components/Breadcrumb";
import Flex from "components/Flex";
import Time from "components/Time";
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,
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 = (
<span>
deleted <Time dateTime={deletedAt} /> ago
</span>
);
} else if (archivedAt) {
content = (
<span>
archived <Time dateTime={archivedAt} /> ago
</span>
);
} else if (createdAt === updatedAt) {
content = (
<span>
created <Time dateTime={updatedAt} /> ago
</span>
);
} else if (publishedAt && (publishedAt === updatedAt || showPublished)) {
content = (
<span>
published <Time dateTime={publishedAt} /> ago
</span>
);
} else if (isDraft) {
content = (
<span>
saved <Time dateTime={updatedAt} /> ago
</span>
);
} else {
content = (
<Modified highlight={modifiedSinceViewed}>
updated <Time dateTime={updatedAt} /> ago
</Modified>
);
}
const collection = collections.get(document.collectionId);
const updatedByMe = auth.user && auth.user.id === updatedBy.id;
return (
<Container align="center" {...rest}>
{updatedByMe ? "You" : updatedBy.name}&nbsp;
{content}
{showCollection && collection && (
<span>
&nbsp;in&nbsp;
<strong>
<Breadcrumb document={document} onlyText />
</strong>
</span>
)}
{children}
</Container>
);
}
export default inject("collections", "auth")(observer(PublishingInfo));

View File

@ -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<Props> {
autoFocus={!title}
maxLength={100}
/>
<DocumentMeta isDraft={isDraft} document={document} />
<DocumentMetaWithViews
isDraft={isDraft}
document={document}
to={documentHistoryUrl(document)}
/>
<Editor
ref={this.editor}
autoFocus={title && !this.props.defaultValue}

View File

@ -4,7 +4,7 @@ import * as React from "react";
import { Link } from "react-router-dom";
import styled from "styled-components";
import Document from "models/Document";
import PublishingInfo from "components/PublishingInfo";
import DocumentMeta from "components/DocumentMeta";
import type { NavigationNode } from "types";
type Props = {
@ -60,7 +60,7 @@ class ReferenceListItem extends React.Component<Props> {
>
<Title>{document.title}</Title>
{document.updatedBy && (
<PublishingInfo document={document} showCollection={showCollection} />
<DocumentMeta document={document} showCollection={showCollection} />
)}
</DocumentLink>
);