Manually create a new document for second collection
This commit is contained in:
@ -26,7 +26,9 @@ class Collection {
|
|||||||
/* Computed */
|
/* Computed */
|
||||||
|
|
||||||
@computed get entryUrl(): string {
|
@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 */
|
/* Actions */
|
||||||
|
@ -1,14 +1,20 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import { observable } from 'mobx';
|
||||||
import { observer, inject } from 'mobx-react';
|
import { observer, inject } from 'mobx-react';
|
||||||
import { Redirect } from 'react-router';
|
import { Redirect } from 'react-router';
|
||||||
|
import { Link } from 'react-router-dom';
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
|
import styled from 'styled-components';
|
||||||
|
import { newDocumentUrl } from 'utils/routeHelpers';
|
||||||
|
|
||||||
import CollectionsStore from 'stores/CollectionsStore';
|
import CollectionsStore from 'stores/CollectionsStore';
|
||||||
import CollectionStore from './CollectionStore';
|
|
||||||
|
|
||||||
import CenteredContent from 'components/CenteredContent';
|
import CenteredContent from 'components/CenteredContent';
|
||||||
import LoadingListPlaceholder from 'components/LoadingListPlaceholder';
|
import LoadingListPlaceholder from 'components/LoadingListPlaceholder';
|
||||||
|
import Button from 'components/Button';
|
||||||
|
import Flex from 'components/Flex';
|
||||||
|
import HelpText from 'components/HelpText';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
collections: CollectionsStore,
|
collections: CollectionsStore,
|
||||||
@ -17,24 +23,66 @@ type Props = {
|
|||||||
|
|
||||||
@observer class Collection extends React.Component {
|
@observer class Collection extends React.Component {
|
||||||
props: Props;
|
props: Props;
|
||||||
store: CollectionStore;
|
collection: ?Collection;
|
||||||
|
@observable isFetching = true;
|
||||||
constructor(props) {
|
@observable redirectUrl;
|
||||||
super(props);
|
|
||||||
this.store = new CollectionStore();
|
|
||||||
}
|
|
||||||
|
|
||||||
componentDidMount = () => {
|
componentDidMount = () => {
|
||||||
const { id } = this.props.match.params;
|
this.fetchDocument();
|
||||||
this.store.fetchCollection(id);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
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() {
|
render() {
|
||||||
return this.store.redirectUrl
|
return (
|
||||||
? <Redirect to={this.store.redirectUrl} />
|
<CenteredContent>
|
||||||
: <CenteredContent>
|
{this.redirectUrl && <Redirect to={this.redirectUrl} />}
|
||||||
<LoadingListPlaceholder />
|
{this.isFetching
|
||||||
</CenteredContent>;
|
? <LoadingListPlaceholder />
|
||||||
|
: this.renderNewDocument()}
|
||||||
|
</CenteredContent>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const NewDocumentContainer = styled(Flex)`
|
||||||
|
padding-top: 70px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const Action = styled(Flex)`
|
||||||
|
margin: 20px 0;
|
||||||
|
`;
|
||||||
|
|
||||||
export default inject('collections')(Collection);
|
export default inject('collections')(Collection);
|
||||||
|
@ -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;
|
|
@ -49,8 +49,25 @@ class CollectionsStore {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
getById = (id: string): ?Collection => {
|
@action getById = async (id: string): Promise<?Collection> => {
|
||||||
return _.find(this.data, { id });
|
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 => {
|
@action add = (collection: Collection): void => {
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import Document from 'models/Document';
|
import Document from 'models/Document';
|
||||||
|
import Collection from 'models/Collection';
|
||||||
|
|
||||||
export function homeUrl(): string {
|
export function homeUrl(): string {
|
||||||
return '/dashboard';
|
return '/dashboard';
|
||||||
@ -21,6 +22,10 @@ export function documentEditUrl(doc: Document): string {
|
|||||||
return `${doc.url}/edit`;
|
return `${doc.url}/edit`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function newDocumentUrl(collection: Collection): string {
|
||||||
|
return `${collection.url}/new`;
|
||||||
|
}
|
||||||
|
|
||||||
export function searchUrl(query?: string): string {
|
export function searchUrl(query?: string): string {
|
||||||
if (query) return `/search/${query}`;
|
if (query) return `/search/${query}`;
|
||||||
return `/search`;
|
return `/search`;
|
||||||
|
@ -39,8 +39,14 @@ const Collection = sequelize.define(
|
|||||||
collection.urlId = collection.urlId || randomstring.generate(10);
|
collection.urlId = collection.urlId || randomstring.generate(10);
|
||||||
},
|
},
|
||||||
afterCreate: async collection => {
|
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;
|
if (collection.type !== 'atlas') return;
|
||||||
|
|
||||||
|
if (collections.length === 0) {
|
||||||
|
// Create intro document if first collection for team
|
||||||
const document = await Document.create({
|
const document = await Document.create({
|
||||||
parentDocumentId: null,
|
parentDocumentId: null,
|
||||||
atlasId: collection.id,
|
atlasId: collection.id,
|
||||||
@ -52,6 +58,10 @@ const Collection = sequelize.define(
|
|||||||
text: '# Introduction\n\nLets get started...',
|
text: '# Introduction\n\nLets get started...',
|
||||||
});
|
});
|
||||||
collection.documentStructure = [document.toJSON()];
|
collection.documentStructure = [document.toJSON()];
|
||||||
|
} else {
|
||||||
|
// Let user create first document
|
||||||
|
collection.documentStructure = [];
|
||||||
|
}
|
||||||
await collection.save();
|
await collection.save();
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -65,6 +75,9 @@ Collection.associate = models => {
|
|||||||
as: 'documents',
|
as: 'documents',
|
||||||
foreignKey: 'atlasId',
|
foreignKey: 'atlasId',
|
||||||
});
|
});
|
||||||
|
Collection.belongsTo(models.Team, {
|
||||||
|
as: 'team',
|
||||||
|
});
|
||||||
Collection.addScope('withRecentDocuments', {
|
Collection.addScope('withRecentDocuments', {
|
||||||
include: [
|
include: [
|
||||||
{
|
{
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
// @flow
|
||||||
import { DataTypes, sequelize } from '../sequelize';
|
import { DataTypes, sequelize } from '../sequelize';
|
||||||
import Collection from './Collection';
|
import Collection from './Collection';
|
||||||
|
|
||||||
@ -24,7 +25,7 @@ const Team = sequelize.define(
|
|||||||
);
|
);
|
||||||
|
|
||||||
Team.associate = models => {
|
Team.associate = models => {
|
||||||
Team.hasMany(models.Collection, { as: 'atlases' });
|
Team.hasMany(models.Collection, { as: 'collections' });
|
||||||
Team.hasMany(models.Document, { as: 'documents' });
|
Team.hasMany(models.Document, { as: 'documents' });
|
||||||
Team.hasMany(models.User, { as: 'users' });
|
Team.hasMany(models.User, { as: 'users' });
|
||||||
};
|
};
|
||||||
|
Reference in New Issue
Block a user