Manually create a new document for second collection

This commit is contained in:
Jori Lallo 2017-07-17 23:30:16 -07:00
parent 63288227db
commit bbbf17c223
7 changed files with 115 additions and 60 deletions

View File

@ -26,7 +26,9 @@ class Collection {
/* Computed */
@computed get entryUrl(): string {
return this.type === 'atlas' ? this.documents[0].url : this.url;
return this.type === 'atlas' && this.documents.length > 0
? this.documents[0].url
: this.url;
}
/* Actions */

View File

@ -1,14 +1,20 @@
// @flow
import React from 'react';
import { observable } from 'mobx';
import { observer, inject } from 'mobx-react';
import { Redirect } from 'react-router';
import { Link } from 'react-router-dom';
import _ from 'lodash';
import styled from 'styled-components';
import { newDocumentUrl } from 'utils/routeHelpers';
import CollectionsStore from 'stores/CollectionsStore';
import CollectionStore from './CollectionStore';
import CenteredContent from 'components/CenteredContent';
import LoadingListPlaceholder from 'components/LoadingListPlaceholder';
import Button from 'components/Button';
import Flex from 'components/Flex';
import HelpText from 'components/HelpText';
type Props = {
collections: CollectionsStore,
@ -17,24 +23,66 @@ type Props = {
@observer class Collection extends React.Component {
props: Props;
store: CollectionStore;
constructor(props) {
super(props);
this.store = new CollectionStore();
}
collection: ?Collection;
@observable isFetching = true;
@observable redirectUrl;
componentDidMount = () => {
const { id } = this.props.match.params;
this.store.fetchCollection(id);
this.fetchDocument();
};
fetchDocument = async () => {
const { collections } = this.props;
const { id } = this.props.match.params;
// $FlowIssue not the correct type?
this.collection = await collections.getById(id);
if (!this.collection) this.redirectUrl = '/404';
if (this.collection && this.collection.documents.length > 0) {
this.redirectUrl = this.collection.documents[0].url;
}
this.isFetching = false;
};
renderNewDocument() {
return (
<NewDocumentContainer auto column justify="center">
<h1>Create a document</h1>
<HelpText>
Publish your first document to start building your collection.
</HelpText>
<Action>
<Link
to={// $FlowIssue stupid type
newDocumentUrl(this.collection)}
>
<Button>Create new document</Button>
</Link>
</Action>
</NewDocumentContainer>
);
}
render() {
return this.store.redirectUrl
? <Redirect to={this.store.redirectUrl} />
: <CenteredContent>
<LoadingListPlaceholder />
</CenteredContent>;
return (
<CenteredContent>
{this.redirectUrl && <Redirect to={this.redirectUrl} />}
{this.isFetching
? <LoadingListPlaceholder />
: this.renderNewDocument()}
</CenteredContent>
);
}
}
const NewDocumentContainer = styled(Flex)`
padding-top: 70px;
`;
const Action = styled(Flex)`
margin: 20px 0;
`;
export default inject('collections')(Collection);

View File

@ -1,31 +0,0 @@
// @flow
import { observable, action } from 'mobx';
import invariant from 'invariant';
import { client } from 'utils/ApiClient';
import { notFoundUrl } from 'utils/routeHelpers';
class CollectionStore {
@observable redirectUrl: ?string;
@observable isFetching = true;
/* Actions */
@action fetchCollection = async (id: string) => {
this.isFetching = true;
try {
const res = await client.get('/collections.info', { id });
invariant(res && res.data, 'Data should be available');
const { data } = res;
if (data.type === 'atlas') this.redirectUrl = data.documents[0].url;
else throw new Error('TODO code up non-atlas collections');
} catch (e) {
console.log(e);
this.redirectUrl = notFoundUrl();
}
this.isFetching = false;
};
}
export default CollectionStore;

View File

@ -49,8 +49,25 @@ class CollectionsStore {
}
};
getById = (id: string): ?Collection => {
return _.find(this.data, { id });
@action getById = async (id: string): Promise<?Collection> => {
let collection = _.find(this.data, { id });
if (!collection) {
try {
const res = await this.client.post('/collections.info', {
id,
});
invariant(res && res.data, 'Collection not available');
const { data } = res;
runInAction('CollectionsStore#getById', () => {
collection = new Collection(data);
this.add(collection);
});
} catch (e) {
// No-op
}
}
return collection;
};
@action add = (collection: Collection): void => {

View File

@ -1,5 +1,6 @@
// @flow
import Document from 'models/Document';
import Collection from 'models/Collection';
export function homeUrl(): string {
return '/dashboard';
@ -21,6 +22,10 @@ export function documentEditUrl(doc: Document): string {
return `${doc.url}/edit`;
}
export function newDocumentUrl(collection: Collection): string {
return `${collection.url}/new`;
}
export function searchUrl(query?: string): string {
if (query) return `/search/${query}`;
return `/search`;

View File

@ -39,19 +39,29 @@ const Collection = sequelize.define(
collection.urlId = collection.urlId || randomstring.generate(10);
},
afterCreate: async collection => {
const team = await collection.getTeam();
const collections = await team.getCollections();
// Don't auto-create for journal types, yet
if (collection.type !== 'atlas') return;
const document = await Document.create({
parentDocumentId: null,
atlasId: collection.id,
teamId: collection.teamId,
userId: collection.creatorId,
lastModifiedById: collection.creatorId,
createdById: collection.creatorId,
title: 'Introduction',
text: '# Introduction\n\nLets get started...',
});
collection.documentStructure = [document.toJSON()];
if (collections.length === 0) {
// Create intro document if first collection for team
const document = await Document.create({
parentDocumentId: null,
atlasId: collection.id,
teamId: collection.teamId,
userId: collection.creatorId,
lastModifiedById: collection.creatorId,
createdById: collection.creatorId,
title: 'Introduction',
text: '# Introduction\n\nLets get started...',
});
collection.documentStructure = [document.toJSON()];
} else {
// Let user create first document
collection.documentStructure = [];
}
await collection.save();
},
},
@ -65,6 +75,9 @@ Collection.associate = models => {
as: 'documents',
foreignKey: 'atlasId',
});
Collection.belongsTo(models.Team, {
as: 'team',
});
Collection.addScope('withRecentDocuments', {
include: [
{

View File

@ -1,3 +1,4 @@
// @flow
import { DataTypes, sequelize } from '../sequelize';
import Collection from './Collection';
@ -24,7 +25,7 @@ const Team = sequelize.define(
);
Team.associate = models => {
Team.hasMany(models.Collection, { as: 'atlases' });
Team.hasMany(models.Collection, { as: 'collections' });
Team.hasMany(models.Document, { as: 'documents' });
Team.hasMany(models.User, { as: 'users' });
};