feat: Child document references (#1054)

* feat: Child document references

* refactor: naming

* lint: flow
This commit is contained in:
Tom Moor
2019-10-08 08:01:30 -07:00
committed by GitHub
parent 927e0b3fb8
commit 24231053af
7 changed files with 122 additions and 66 deletions

View File

@@ -51,31 +51,31 @@ function PublishingInfo({
if (deletedAt) {
content = (
<span>
&nbsp;deleted <Time dateTime={deletedAt} /> ago
deleted <Time dateTime={deletedAt} /> ago
</span>
);
} else if (archivedAt) {
content = (
<span>
&nbsp;archived <Time dateTime={archivedAt} /> ago
archived <Time dateTime={archivedAt} /> ago
</span>
);
} else if (publishedAt && (neverUpdated || showPublished)) {
content = (
<span>
&nbsp;published <Time dateTime={publishedAt} /> ago
published <Time dateTime={publishedAt} /> ago
</span>
);
} else if (isDraft) {
content = (
<span>
&nbsp;saved <Time dateTime={updatedAt} /> ago
saved <Time dateTime={updatedAt} /> ago
</span>
);
} else {
content = (
<Modified highlight={modifiedSinceViewed}>
&nbsp;updated <Time dateTime={updatedAt} /> ago
updated <Time dateTime={updatedAt} /> ago
</Modified>
);
}
@@ -84,7 +84,7 @@ function PublishingInfo({
return (
<Container align="center">
{updatedBy.name}
{updatedBy.name}&nbsp;
{content}
{showCollection &&
collection && (

View File

@@ -60,6 +60,25 @@ export default class Collection extends BaseModel {
travelDocuments(this.documents);
}
getDocumentChildren(documentId: string): NavigationNode[] {
let result = [];
const traveler = nodes => {
nodes.forEach(childNode => {
if (childNode.id === documentId) {
result = childNode.children;
return;
}
return traveler(childNode.children);
});
};
if (this.documents) {
traveler(this.documents);
}
return result;
}
pathToDocument(document: Document) {
let path;
const traveler = (nodes, previousPath) => {

View File

@@ -23,7 +23,7 @@ import Header from './components/Header';
import DocumentMove from './components/DocumentMove';
import Branding from './components/Branding';
import KeyboardShortcuts from './components/KeyboardShortcuts';
import Backlinks from './components/Backlinks';
import References from './components/References';
import ErrorBoundary from 'components/ErrorBoundary';
import LoadingPlaceholder from 'components/LoadingPlaceholder';
import LoadingIndicator from 'components/LoadingIndicator';
@@ -415,12 +415,7 @@ class DocumentScene extends React.Component<Props> {
schema={schema}
/>
{!this.isEditing &&
!isShare && (
<Backlinks
documents={this.props.documents}
document={document}
/>
)}
!isShare && <References document={document} />}
</MaxWidth>
</Container>
</Container>

View File

@@ -1,46 +0,0 @@
// @flow
import * as React from 'react';
import { observer } from 'mobx-react';
import Fade from 'components/Fade';
import Subheading from 'components/Subheading';
import DocumentsStore from 'stores/DocumentsStore';
import Document from 'models/Document';
import Backlink from './Backlink';
type Props = {
document: Document,
documents: DocumentsStore,
};
@observer
class Backlinks extends React.Component<Props> {
componentDidMount() {
this.props.documents.fetchBacklinks(this.props.document.id);
}
render() {
const { documents, document } = this.props;
const backlinks = documents.getBacklinedDocuments(document.id);
const showBacklinks = !!backlinks.length;
return (
showBacklinks && (
<Fade>
<Subheading>Referenced By</Subheading>
{backlinks.map(backlinkedDocument => (
<Backlink
anchor={document.urlId}
key={backlinkedDocument.id}
document={backlinkedDocument}
showCollection={
backlinkedDocument.collectionId !== document.collectionId
}
/>
))}
</Fade>
)
);
}
}
export default Backlinks;

View File

@@ -5,10 +5,11 @@ import { Link } from 'react-router-dom';
import styled from 'styled-components';
import PublishingInfo from 'components/PublishingInfo';
import Document from 'models/Document';
import type { NavigationNode } from 'types';
type Props = {
document: Document,
anchor: string,
document: Document | NavigationNode,
anchor?: string,
showCollection?: boolean,
};
@@ -43,7 +44,7 @@ const Title = styled.h3`
`;
@observer
class Backlink extends React.Component<Props> {
class ReferenceListItem extends React.Component<Props> {
render() {
const { document, showCollection, anchor, ...rest } = this.props;
@@ -51,16 +52,18 @@ class Backlink extends React.Component<Props> {
<DocumentLink
to={{
pathname: document.url,
hash: `d-${anchor}`,
hash: anchor ? `d-${anchor}` : undefined,
state: { title: document.title },
}}
{...rest}
>
<Title>{document.title}</Title>
<PublishingInfo document={document} showCollection={showCollection} />
{document.updatedBy && (
<PublishingInfo document={document} showCollection={showCollection} />
)}
</DocumentLink>
);
}
}
export default Backlink;
export default ReferenceListItem;

View File

@@ -0,0 +1,83 @@
// @flow
import * as React from 'react';
import { observer, inject } from 'mobx-react';
import { withRouter, type Location } from 'react-router-dom';
import Fade from 'components/Fade';
import Tabs from 'components/Tabs';
import Tab from 'components/Tab';
import DocumentsStore from 'stores/DocumentsStore';
import CollectionsStore from 'stores/CollectionsStore';
import Document from 'models/Document';
import ReferenceListItem from './ReferenceListItem';
type Props = {
document: Document,
documents: DocumentsStore,
collections: CollectionsStore,
location: Location,
};
@observer
class References extends React.Component<Props> {
componentDidMount() {
this.props.documents.fetchBacklinks(this.props.document.id);
}
render() {
const { documents, collections, document } = this.props;
const backlinks = documents.getBacklinedDocuments(document.id);
const collection = collections.get(document.collectionId);
const children = collection
? collection.getDocumentChildren(document.id)
: [];
const showBacklinks = !!backlinks.length;
const showChildren = !!children.length;
const isBacklinksTab =
this.props.location.hash === '#backlinks' || !showChildren;
return (
(showBacklinks || showChildren) && (
<Fade>
<Tabs>
{showChildren && (
<Tab to="#children" isActive={() => !isBacklinksTab}>
Child documents
</Tab>
)}
{showBacklinks && (
<Tab to="#backlinks" isActive={() => isBacklinksTab}>
References
</Tab>
)}
</Tabs>
{isBacklinksTab
? backlinks.map(backlinkedDocument => (
<ReferenceListItem
anchor={document.urlId}
key={backlinkedDocument.id}
document={backlinkedDocument}
showCollection={
backlinkedDocument.collectionId !== document.collectionId
}
/>
))
: children.map(node => {
// If we have the document in the store already then use it to get the extra
// contextual info, otherwise the collection node will do (only has title and id)
const document = documents.get(node.id);
return (
<ReferenceListItem
key={node.id}
document={document || node}
showCollection={false}
/>
);
})}
</Fade>
)
);
}
}
export default withRouter(inject('documents', 'collections')(References));

View File

@@ -128,7 +128,9 @@ class Search extends React.Component<Props> {
};
handleNewDoc = () => {
this.props.history.push(newDocumentUrl(this.collectionId));
if (this.collectionId) {
this.props.history.push(newDocumentUrl(this.collectionId));
}
};
get includeArchived() {