Added: Recently published view to collection

Added: Infinite scroll to collection
This commit is contained in:
Tom Moor 2019-01-07 23:14:43 -08:00
parent 74515e0b19
commit e6e89dc243
10 changed files with 87 additions and 25 deletions

View File

@ -7,12 +7,14 @@ import ArrowKeyNavigation from 'boundless-arrow-key-navigation';
type Props = {
documents: Document[],
showCollection?: boolean,
showPublished?: boolean,
limit?: number,
};
export default function DocumentList({
limit,
showCollection,
showPublished,
documents,
}: Props) {
const items = limit ? documents.splice(0, limit) : documents;
@ -27,6 +29,7 @@ export default function DocumentList({
key={document.id}
document={document}
showCollection={showCollection}
showPublished={showPublished}
/>
))}
</ArrowKeyNavigation>

View File

@ -15,6 +15,7 @@ type Props = {
highlight?: ?string,
context?: ?string,
showCollection?: boolean,
showPublished?: boolean,
ref?: *,
};
@ -133,6 +134,7 @@ class DocumentPreview extends React.Component<Props> {
const {
document,
showCollection,
showPublished,
highlight,
context,
...rest
@ -173,6 +175,7 @@ class DocumentPreview extends React.Component<Props> {
<PublishingInfo
document={document}
collection={showCollection ? document.collection : undefined}
showPublished={showPublished}
/>
</DocumentLink>
);

View File

@ -19,11 +19,12 @@ const Modified = styled.span`
type Props = {
collection?: Collection,
showPublished?: boolean,
document: Document,
views?: number,
};
function PublishingInfo({ collection, document }: Props) {
function PublishingInfo({ collection, showPublished, document }: Props) {
const {
modifiedSinceViewed,
updatedAt,
@ -35,7 +36,7 @@ function PublishingInfo({ collection, document }: Props) {
return (
<Container align="center">
{publishedAt && neverUpdated ? (
{publishedAt && (neverUpdated || showPublished) ? (
<span>
{updatedBy.name} published <Time dateTime={publishedAt} /> ago
</span>
@ -48,7 +49,7 @@ function PublishingInfo({ collection, document }: Props) {
</span>
) : (
<Modified highlight={modifiedSinceViewed}>
&nbsp;modified <Time dateTime={updatedAt} /> ago
&nbsp;updated <Time dateTime={updatedAt} /> ago
</Modified>
)}
</React.Fragment>

View File

@ -11,6 +11,7 @@ import { ListPlaceholder } from 'components/LoadingPlaceholder';
type Props = {
showCollection?: boolean,
showPublished?: boolean,
documents: Document[],
fetch: (options: ?Object) => Promise<*>,
options?: Object,
@ -64,11 +65,15 @@ class PaginatedDocumentList extends React.Component<Props> {
};
render() {
const { showCollection, documents } = this.props;
const { showCollection, showPublished, documents } = this.props;
return this.isLoaded || documents.length ? (
<React.Fragment>
<DocumentList documents={documents} showCollection={showCollection} />
<DocumentList
documents={documents}
showCollection={showCollection}
showPublished={showPublished}
/>
{this.allowLoadMore && (
<Waypoint key={this.offset} onEnter={this.loadMoreResults} />
)}

View File

@ -59,6 +59,7 @@ class CollectionLink extends React.Component<Props> {
hideDisclosure
menuOpen={this.menuOpen}
label={collection.name}
exact={false}
menu={
<CollectionMenu
history={history}

View File

@ -68,6 +68,7 @@ export default function Routes() {
component={Zapier}
/>
<Route exact path="/settings/export" component={Export} />
<Route exact path="/collections/:id/:tab" component={Collection} />
<Route exact path="/collections/:id" component={Collection} />
<Route exact path={`/d/${slug}`} component={RedirectDocument} />
<Route

View File

@ -2,7 +2,8 @@
import * as React from 'react';
import { observable } from 'mobx';
import { observer, inject } from 'mobx-react';
import { withRouter, Link } from 'react-router-dom';
import { withRouter, Link, Switch, Route } from 'react-router-dom';
import styled from 'styled-components';
import {
CollectionIcon,
@ -12,7 +13,7 @@ import {
} from 'outline-icons';
import RichMarkdownEditor from 'rich-markdown-editor';
import { newDocumentUrl } from 'utils/routeHelpers';
import { newDocumentUrl, collectionUrl } from 'utils/routeHelpers';
import CollectionsStore from 'stores/CollectionsStore';
import DocumentsStore from 'stores/DocumentsStore';
import UiStore from 'stores/UiStore';
@ -33,6 +34,9 @@ import PageTitle from 'components/PageTitle';
import Flex from 'shared/components/Flex';
import Modal from 'components/Modal';
import CollectionPermissions from 'scenes/CollectionPermissions';
import Tabs from 'components/Tabs';
import Tab from 'components/Tab';
import PaginatedDocumentList from 'components/PaginatedDocumentList';
type Props = {
ui: UiStore,
@ -69,15 +73,9 @@ class CollectionScene extends React.Component<Props> {
this.props.ui.setActiveCollection(collection);
this.collection = collection;
await Promise.all([
this.props.documents.fetchRecentlyUpdated({
limit: 10,
collection: id,
}),
this.props.documents.fetchPinned({
collection: id,
}),
]);
await this.props.documents.fetchPinned({
collection: id,
});
}
this.isFetching = false;
@ -124,15 +122,14 @@ class CollectionScene extends React.Component<Props> {
}
render() {
const { documents } = this.props;
if (!this.isFetching && !this.collection) {
return this.renderNotFound();
}
const pinnedDocuments = this.collection
? this.props.documents.pinnedInCollection(this.collection.id)
: [];
const recentDocuments = this.collection
? this.props.documents.recentlyUpdatedInCollection(this.collection.id)
? documents.pinnedInCollection(this.collection.id)
: [];
const hasPinnedDocuments = !!pinnedDocuments.length;
const collection = this.collection;
@ -207,8 +204,36 @@ class CollectionScene extends React.Component<Props> {
</React.Fragment>
)}
<Subheading>Recently edited</Subheading>
<DocumentList documents={recentDocuments} limit={10} />
<Tabs>
<Tab to={collectionUrl(collection.id)} exact>
Recently updated
</Tab>
<Tab to={collectionUrl(collection.id, 'recent')} exact>
Recently published
</Tab>
</Tabs>
<Switch>
<Route path={collectionUrl(collection.id, 'recent')}>
<PaginatedDocumentList
key="recent"
documents={documents.recentlyPublishedInCollection(
collection.id
)}
fetch={documents.fetchRecentlyPublished}
options={{ collection: collection.id }}
showPublished
/>
</Route>
<Route path={collectionUrl(collection.id)}>
<PaginatedDocumentList
documents={documents.recentlyUpdatedInCollection(
collection.id
)}
fetch={documents.fetchRecentlyUpdated}
options={{ collection: collection.id }}
/>
</Route>
</Switch>
</React.Fragment>
)}

View File

@ -12,8 +12,8 @@ import CenteredContent from 'components/CenteredContent';
import PageTitle from 'components/PageTitle';
import Tabs from 'components/Tabs';
import Tab from 'components/Tab';
import TipInvite from 'components/TipInvite';
import PaginatedDocumentList from '../components/PaginatedDocumentList';
import TipInvite from 'components/TipInvite';
type Props = {
documents: DocumentsStore,

View File

@ -67,6 +67,18 @@ export default class DocumentsStore extends BaseStore<Document> {
);
}
recentlyPublishedInCollection(collectionId: string): Document[] {
return orderBy(
filter(
Array.from(this.data.values()),
document =>
document.collectionId === collectionId && !!document.publishedAt
),
'publishedAt',
'desc'
);
}
@computed
get starred(): Document[] {
return filter(this.orderedData, d => d.starred);
@ -126,6 +138,15 @@ export default class DocumentsStore extends BaseStore<Document> {
return data;
};
@action
fetchRecentlyPublished = async (options: ?PaginationParams): Promise<*> => {
return this.fetchNamedPage('list', {
sort: 'publishedAt',
direction: 'DESC',
...options,
});
};
@action
fetchRecentlyViewed = async (options: ?PaginationParams): Promise<*> => {
const data = await this.fetchNamedPage('viewed', options);

View File

@ -14,8 +14,10 @@ export function newCollectionUrl(): string {
return '/collections/new';
}
export function collectionUrl(collectionId: string): string {
return `/collections/${collectionId}`;
export function collectionUrl(collectionId: string, section: ?string): string {
const path = `/collections/${collectionId}`;
if (section) return `${path}/${section}`;
return path;
}
export function documentUrl(doc: Document): string {