Drag and Drop Import (#95)
* Drag and drop files into collection first pass * Allow import of sub documents Fix up UI styles * Import Loading indicator * Drag onto document to import
This commit is contained in:
108
frontend/components/DropToImport/DropToImport.js
Normal file
108
frontend/components/DropToImport/DropToImport.js
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
// @flow
|
||||||
|
import React, { Component } from 'react';
|
||||||
|
import { inject } from 'mobx-react';
|
||||||
|
import invariant from 'invariant';
|
||||||
|
import _ from 'lodash';
|
||||||
|
import Dropzone from 'react-dropzone';
|
||||||
|
import Document from 'models/Document';
|
||||||
|
import DocumentsStore from 'stores/DocumentsStore';
|
||||||
|
import LoadingIndicator from 'components/LoadingIndicator';
|
||||||
|
|
||||||
|
class DropToImport extends Component {
|
||||||
|
state: {
|
||||||
|
isImporting: boolean,
|
||||||
|
};
|
||||||
|
props: {
|
||||||
|
children?: React$Element<any>,
|
||||||
|
collectionId: string,
|
||||||
|
documentId?: string,
|
||||||
|
activeClassName?: string,
|
||||||
|
rejectClassName?: string,
|
||||||
|
documents: DocumentsStore,
|
||||||
|
history: Object,
|
||||||
|
};
|
||||||
|
state = {
|
||||||
|
isImporting: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
importFile = async ({ file, documentId, collectionId, redirect }) => {
|
||||||
|
const reader = new FileReader();
|
||||||
|
|
||||||
|
reader.onload = async ev => {
|
||||||
|
const text = ev.target.result;
|
||||||
|
let data = {
|
||||||
|
parentDocument: undefined,
|
||||||
|
collection: { id: collectionId },
|
||||||
|
text,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (documentId) {
|
||||||
|
data.parentDocument = {
|
||||||
|
id: documentId,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
let document = new Document(data);
|
||||||
|
document = await document.save();
|
||||||
|
this.props.documents.add(document);
|
||||||
|
|
||||||
|
if (redirect && this.props.history) {
|
||||||
|
this.props.history.push(document.url);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
reader.readAsText(file);
|
||||||
|
};
|
||||||
|
|
||||||
|
onDropAccepted = async (files = []) => {
|
||||||
|
this.setState({ isImporting: true });
|
||||||
|
|
||||||
|
try {
|
||||||
|
let collectionId = this.props.collectionId;
|
||||||
|
const documentId = this.props.documentId;
|
||||||
|
const redirect = files.length === 1;
|
||||||
|
|
||||||
|
if (documentId && !collectionId) {
|
||||||
|
const document = await this.props.documents.fetch(documentId);
|
||||||
|
invariant(document, 'Document not available');
|
||||||
|
collectionId = document.collection.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const file of files) {
|
||||||
|
await this.importFile({ file, documentId, collectionId, redirect });
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
// TODO: show error alert.
|
||||||
|
} finally {
|
||||||
|
this.setState({ isImporting: false });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const props = _.omit(
|
||||||
|
this.props,
|
||||||
|
'history',
|
||||||
|
'documentId',
|
||||||
|
'collectionId',
|
||||||
|
'documents'
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Dropzone
|
||||||
|
accept="text/markdown, text/plain"
|
||||||
|
onDropAccepted={this.onDropAccepted}
|
||||||
|
style={{}}
|
||||||
|
disableClick
|
||||||
|
disablePreview
|
||||||
|
multiple
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
<span>
|
||||||
|
{this.state.isImporting && <LoadingIndicator />}
|
||||||
|
{this.props.children}
|
||||||
|
</span>
|
||||||
|
</Dropzone>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default inject('documents')(DropToImport);
|
3
frontend/components/DropToImport/index.js
Normal file
3
frontend/components/DropToImport/index.js
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
// @flow
|
||||||
|
import DropToImport from './DropToImport';
|
||||||
|
export default DropToImport;
|
@ -7,11 +7,12 @@ import { observer, inject } from 'mobx-react';
|
|||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import keydown from 'react-keydown';
|
import keydown from 'react-keydown';
|
||||||
import Flex from 'components/Flex';
|
import Flex from 'components/Flex';
|
||||||
import { textColor } from 'styles/constants.scss';
|
import { color, layout } from 'styles/constants';
|
||||||
|
|
||||||
import DropdownMenu, { MenuItem } from 'components/DropdownMenu';
|
import DropdownMenu, { MenuItem } from 'components/DropdownMenu';
|
||||||
import { LoadingIndicatorBar } from 'components/LoadingIndicator';
|
import { LoadingIndicatorBar } from 'components/LoadingIndicator';
|
||||||
import Scrollable from 'components/Scrollable';
|
import Scrollable from 'components/Scrollable';
|
||||||
|
import Avatar from 'components/Avatar';
|
||||||
|
|
||||||
import SidebarCollection from './components/SidebarCollection';
|
import SidebarCollection from './components/SidebarCollection';
|
||||||
import SidebarCollectionList from './components/SidebarCollectionList';
|
import SidebarCollectionList from './components/SidebarCollectionList';
|
||||||
@ -115,8 +116,9 @@ type Props = {
|
|||||||
? <SidebarCollection
|
? <SidebarCollection
|
||||||
document={ui.activeDocument}
|
document={ui.activeDocument}
|
||||||
collection={ui.activeCollection}
|
collection={ui.activeCollection}
|
||||||
|
history={this.props.history}
|
||||||
/>
|
/>
|
||||||
: <SidebarCollectionList />}
|
: <SidebarCollectionList history={this.props.history} />}
|
||||||
</LinkSection>
|
</LinkSection>
|
||||||
</Scrollable>
|
</Scrollable>
|
||||||
</Flex>
|
</Flex>
|
||||||
@ -141,19 +143,13 @@ const LogoLink = styled(Link)`
|
|||||||
margin-top: 15px;
|
margin-top: 15px;
|
||||||
font-family: 'Atlas Grotesk';
|
font-family: 'Atlas Grotesk';
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
color: ${textColor};
|
color: ${color.text};
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const Avatar = styled.img`
|
|
||||||
width: 24px;
|
|
||||||
height: 24px;
|
|
||||||
border-radius: 50%;
|
|
||||||
`;
|
|
||||||
|
|
||||||
const MenuLink = styled(Link)`
|
const MenuLink = styled(Link)`
|
||||||
color: ${textColor};
|
color: ${color.text};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const Content = styled(Flex)`
|
const Content = styled(Flex)`
|
||||||
@ -162,13 +158,13 @@ const Content = styled(Flex)`
|
|||||||
top: 0;
|
top: 0;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
left: ${props => (props.editMode ? 0 : '250px')};
|
left: ${props => (props.editMode ? 0 : layout.sidebarWidth)};
|
||||||
transition: left 200ms ease-in-out;
|
transition: left 200ms ease-in-out;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const Sidebar = styled(Flex)`
|
const Sidebar = styled(Flex)`
|
||||||
width: 250px;
|
width: ${layout.sidebarWidth};
|
||||||
margin-left: ${props => (props.editMode ? '-250px' : 0)};
|
margin-left: ${props => (props.editMode ? `-${layout.sidebarWidth}` : 0)};
|
||||||
background: rgba(250, 251, 252, 0.71);
|
background: rgba(250, 251, 252, 0.71);
|
||||||
border-right: 1px solid #eceff3;
|
border-right: 1px solid #eceff3;
|
||||||
transition: margin-left 200ms ease-in-out;
|
transition: margin-left 200ms ease-in-out;
|
||||||
@ -176,12 +172,12 @@ const Sidebar = styled(Flex)`
|
|||||||
|
|
||||||
const Header = styled(Flex)`
|
const Header = styled(Flex)`
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
padding: 10px 20px;
|
padding: ${layout.padding};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const LinkSection = styled(Flex)`
|
const LinkSection = styled(Flex)`
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
padding: 10px 20px;
|
padding: 10px 0;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export default withRouter(inject('user', 'auth', 'ui', 'collections')(Layout));
|
export default withRouter(inject('user', 'auth', 'ui', 'collections')(Layout));
|
||||||
|
@ -2,8 +2,9 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import Flex from 'components/Flex';
|
import Flex from 'components/Flex';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
|
import { layout } from 'styles/constants';
|
||||||
import SidebarLink from '../SidebarLink';
|
import SidebarLink from '../SidebarLink';
|
||||||
|
import DropToImport from 'components/DropToImport';
|
||||||
|
|
||||||
import Collection from 'models/Collection';
|
import Collection from 'models/Collection';
|
||||||
import Document from 'models/Document';
|
import Document from 'models/Document';
|
||||||
@ -12,24 +13,39 @@ import type { NavigationNode } from 'types';
|
|||||||
type Props = {
|
type Props = {
|
||||||
collection: ?Collection,
|
collection: ?Collection,
|
||||||
document: ?Document,
|
document: ?Document,
|
||||||
|
history: Object,
|
||||||
|
};
|
||||||
|
|
||||||
|
const activeStyle = {
|
||||||
|
color: '#000',
|
||||||
|
background: '#E1E1E1',
|
||||||
};
|
};
|
||||||
|
|
||||||
class SidebarCollection extends React.Component {
|
class SidebarCollection extends React.Component {
|
||||||
props: Props;
|
props: Props;
|
||||||
|
|
||||||
renderDocuments(documentList: Array<NavigationNode>) {
|
renderDocuments(documentList: Array<NavigationNode>, depth = 0) {
|
||||||
const { document } = this.props;
|
const { document, history } = this.props;
|
||||||
|
const canDropToImport = depth === 0;
|
||||||
|
|
||||||
if (document) {
|
if (document) {
|
||||||
return documentList.map(doc => (
|
return documentList.map(doc => (
|
||||||
<Flex column key={doc.id}>
|
<Flex column key={doc.id}>
|
||||||
<SidebarLink key={doc.id} to={doc.url}>
|
{canDropToImport &&
|
||||||
{doc.title}
|
<DropToImport
|
||||||
</SidebarLink>
|
history={history}
|
||||||
|
documentId={doc.id}
|
||||||
|
activeStyle={activeStyle}
|
||||||
|
>
|
||||||
|
<SidebarLink to={doc.url}>{doc.title}</SidebarLink>
|
||||||
|
</DropToImport>}
|
||||||
|
{!canDropToImport &&
|
||||||
|
<SidebarLink to={doc.url}>{doc.title}</SidebarLink>}
|
||||||
|
|
||||||
{(document.pathToDocument.includes(doc.id) ||
|
{(document.pathToDocument.includes(doc.id) ||
|
||||||
document.id === doc.id) &&
|
document.id === doc.id) &&
|
||||||
<Children column>
|
<Children column>
|
||||||
{doc.children && this.renderDocuments(doc.children)}
|
{doc.children && this.renderDocuments(doc.children, depth + 1)}
|
||||||
</Children>}
|
</Children>}
|
||||||
</Flex>
|
</Flex>
|
||||||
));
|
));
|
||||||
@ -57,6 +73,7 @@ const Header = styled(Flex)`
|
|||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
color: #9FA6AB;
|
color: #9FA6AB;
|
||||||
letter-spacing: 0.04em;
|
letter-spacing: 0.04em;
|
||||||
|
padding: 0 ${layout.hpadding};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const Children = styled(Flex)`
|
const Children = styled(Flex)`
|
||||||
|
@ -3,23 +3,37 @@ import React from 'react';
|
|||||||
import { observer, inject } from 'mobx-react';
|
import { observer, inject } from 'mobx-react';
|
||||||
import Flex from 'components/Flex';
|
import Flex from 'components/Flex';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
|
import { layout } from 'styles/constants';
|
||||||
|
|
||||||
import SidebarLink from '../SidebarLink';
|
import SidebarLink from '../SidebarLink';
|
||||||
|
import DropToImport from 'components/DropToImport';
|
||||||
|
|
||||||
import CollectionsStore from 'stores/CollectionsStore';
|
import CollectionsStore from 'stores/CollectionsStore';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
|
history: Object,
|
||||||
collections: CollectionsStore,
|
collections: CollectionsStore,
|
||||||
};
|
};
|
||||||
|
|
||||||
const SidebarCollectionList = observer(({ collections }: Props) => {
|
const activeStyle = {
|
||||||
|
color: '#000',
|
||||||
|
background: '#E1E1E1',
|
||||||
|
};
|
||||||
|
|
||||||
|
const SidebarCollectionList = observer(({ history, collections }: Props) => {
|
||||||
return (
|
return (
|
||||||
<Flex column>
|
<Flex column>
|
||||||
<Header>Collections</Header>
|
<Header>Collections</Header>
|
||||||
{collections.data.map(collection => (
|
{collections.data.map(collection => (
|
||||||
|
<DropToImport
|
||||||
|
history={history}
|
||||||
|
collectionId={collection.id}
|
||||||
|
activeStyle={activeStyle}
|
||||||
|
>
|
||||||
<SidebarLink key={collection.id} to={collection.url}>
|
<SidebarLink key={collection.id} to={collection.url}>
|
||||||
{collection.name}
|
{collection.name}
|
||||||
</SidebarLink>
|
</SidebarLink>
|
||||||
|
</DropToImport>
|
||||||
))}
|
))}
|
||||||
</Flex>
|
</Flex>
|
||||||
);
|
);
|
||||||
@ -31,6 +45,7 @@ const Header = styled(Flex)`
|
|||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
color: #9FA6AB;
|
color: #9FA6AB;
|
||||||
letter-spacing: 0.04em;
|
letter-spacing: 0.04em;
|
||||||
|
padding: 0 ${layout.hpadding};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export default inject('collections')(SidebarCollectionList);
|
export default inject('collections')(SidebarCollectionList);
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { NavLink } from 'react-router-dom';
|
import { NavLink } from 'react-router-dom';
|
||||||
import Flex from 'components/Flex';
|
import { layout, color } from 'styles/constants';
|
||||||
|
import { darken } from 'polished';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
|
|
||||||
const activeStyle = {
|
const activeStyle = {
|
||||||
@ -9,18 +10,16 @@ const activeStyle = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
function SidebarLink(props: Object) {
|
function SidebarLink(props: Object) {
|
||||||
return (
|
return <StyledNavLink exact {...props} activeStyle={activeStyle} />;
|
||||||
<LinkContainer>
|
|
||||||
<NavLink exact {...props} activeStyle={activeStyle} />
|
|
||||||
</LinkContainer>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const LinkContainer = styled(Flex)`
|
const StyledNavLink = styled(NavLink)`
|
||||||
padding: 5px 0;
|
display: block;
|
||||||
|
padding: 5px ${layout.hpadding};
|
||||||
|
color: ${color.slateDark};
|
||||||
|
|
||||||
a {
|
&:hover {
|
||||||
color: #848484;
|
color: ${darken(0.1, color.slateDark)};
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@ import type { User } from 'types';
|
|||||||
import Collection from './Collection';
|
import Collection from './Collection';
|
||||||
|
|
||||||
const parseHeader = text => {
|
const parseHeader = text => {
|
||||||
const firstLine = text.split(/\r?\n/)[0];
|
const firstLine = text.trim().split(/\r?\n/)[0];
|
||||||
return firstLine.replace(/^#/, '').trim();
|
return firstLine.replace(/^#/, '').trim();
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -20,7 +20,7 @@ class Document {
|
|||||||
errors: ErrorsStore;
|
errors: ErrorsStore;
|
||||||
|
|
||||||
collaborators: Array<User>;
|
collaborators: Array<User>;
|
||||||
collection: Collection;
|
collection: $Shape<Collection>;
|
||||||
createdAt: string;
|
createdAt: string;
|
||||||
createdBy: User;
|
createdBy: User;
|
||||||
html: string;
|
html: string;
|
||||||
@ -113,7 +113,7 @@ class Document {
|
|||||||
};
|
};
|
||||||
|
|
||||||
@action save = async () => {
|
@action save = async () => {
|
||||||
if (this.isSaving) return;
|
if (this.isSaving) return this;
|
||||||
this.isSaving = true;
|
this.isSaving = true;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -125,11 +125,16 @@ class Document {
|
|||||||
text: this.text,
|
text: this.text,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
res = await client.post('/documents.create', {
|
const data = {
|
||||||
|
parentDocument: undefined,
|
||||||
collection: this.collection.id,
|
collection: this.collection.id,
|
||||||
title: this.title,
|
title: this.title,
|
||||||
text: this.text,
|
text: this.text,
|
||||||
});
|
};
|
||||||
|
if (this.parentDocument) {
|
||||||
|
data.parentDocument = this.parentDocument.id;
|
||||||
|
}
|
||||||
|
res = await client.post('/documents.create', data);
|
||||||
}
|
}
|
||||||
|
|
||||||
invariant(res && res.data, 'Data should be available');
|
invariant(res && res.data, 'Data should be available');
|
||||||
|
@ -5,12 +5,14 @@ import styled from 'styled-components';
|
|||||||
import { observer, inject } from 'mobx-react';
|
import { observer, inject } from 'mobx-react';
|
||||||
import { withRouter, Prompt } from 'react-router';
|
import { withRouter, Prompt } from 'react-router';
|
||||||
import Flex from 'components/Flex';
|
import Flex from 'components/Flex';
|
||||||
|
import { layout } from 'styles/constants';
|
||||||
|
|
||||||
import Document from 'models/Document';
|
import Document from 'models/Document';
|
||||||
import UiStore from 'stores/UiStore';
|
import UiStore from 'stores/UiStore';
|
||||||
import DocumentsStore from 'stores/DocumentsStore';
|
import DocumentsStore from 'stores/DocumentsStore';
|
||||||
import Menu from './components/Menu';
|
import Menu from './components/Menu';
|
||||||
import Editor from 'components/Editor';
|
import Editor from 'components/Editor';
|
||||||
|
import DropToImport from 'components/DropToImport';
|
||||||
import { HeaderAction, SaveAction } from 'components/Layout';
|
import { HeaderAction, SaveAction } from 'components/Layout';
|
||||||
import LoadingIndicator from 'components/LoadingIndicator';
|
import LoadingIndicator from 'components/LoadingIndicator';
|
||||||
import PublishingInfo from 'components/PublishingInfo';
|
import PublishingInfo from 'components/PublishingInfo';
|
||||||
@ -39,6 +41,7 @@ type Props = {
|
|||||||
newDocument?: Document,
|
newDocument?: Document,
|
||||||
};
|
};
|
||||||
state = {
|
state = {
|
||||||
|
isDragging: false,
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
newDocument: undefined,
|
newDocument: undefined,
|
||||||
};
|
};
|
||||||
@ -125,6 +128,14 @@ type Props = {
|
|||||||
this.props.history.goBack();
|
this.props.history.goBack();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
onStartDragging = () => {
|
||||||
|
this.setState({ isDragging: true });
|
||||||
|
};
|
||||||
|
|
||||||
|
onStopDragging = () => {
|
||||||
|
this.setState({ isDragging: false });
|
||||||
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const isNew = this.props.newDocument;
|
const isNew = this.props.newDocument;
|
||||||
const isEditing = this.props.match.params.edit || isNew;
|
const isEditing = this.props.match.params.edit || isNew;
|
||||||
@ -133,6 +144,10 @@ type Props = {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Container column auto>
|
<Container column auto>
|
||||||
|
{this.state.isDragging &&
|
||||||
|
<DropHere align="center" justify="center">
|
||||||
|
Drop files here to import into Atlas.
|
||||||
|
</DropHere>}
|
||||||
{titleText && <PageTitle title={titleText} />}
|
{titleText && <PageTitle title={titleText} />}
|
||||||
{this.state.isLoading && <LoadingIndicator />}
|
{this.state.isLoading && <LoadingIndicator />}
|
||||||
{isFetching &&
|
{isFetching &&
|
||||||
@ -141,6 +156,13 @@ type Props = {
|
|||||||
</CenteredContent>}
|
</CenteredContent>}
|
||||||
{!isFetching &&
|
{!isFetching &&
|
||||||
this.document &&
|
this.document &&
|
||||||
|
<DropToImport
|
||||||
|
documentId={this.document.id}
|
||||||
|
history={this.props.history}
|
||||||
|
onDragEnter={this.onStartDragging}
|
||||||
|
onDragLeave={this.onStopDragging}
|
||||||
|
onDrop={this.onStopDragging}
|
||||||
|
>
|
||||||
<PagePadding justify="center" auto>
|
<PagePadding justify="center" auto>
|
||||||
<Prompt
|
<Prompt
|
||||||
when={this.document.hasPendingChanges}
|
when={this.document.hasPendingChanges}
|
||||||
@ -188,19 +210,32 @@ type Props = {
|
|||||||
{!isEditing && <Menu document={this.document} />}
|
{!isEditing && <Menu document={this.document} />}
|
||||||
</Flex>
|
</Flex>
|
||||||
</Meta>
|
</Meta>
|
||||||
</PagePadding>}
|
</PagePadding>
|
||||||
|
</DropToImport>}
|
||||||
</Container>
|
</Container>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const DropHere = styled(Flex)`
|
||||||
|
pointer-events: none;
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: ${layout.sidebarWidth};
|
||||||
|
bottom: 0;
|
||||||
|
right: 0;
|
||||||
|
text-align: center;
|
||||||
|
background: rgba(255,255,255,.9);
|
||||||
|
z-index: 1;
|
||||||
|
`;
|
||||||
|
|
||||||
const Meta = styled(Flex)`
|
const Meta = styled(Flex)`
|
||||||
justify-content: ${props => (props.readOnly ? 'space-between' : 'flex-end')};
|
justify-content: ${props => (props.readOnly ? 'space-between' : 'flex-end')};
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
padding: 10px 20px;
|
padding: ${layout.padding};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const Container = styled(Flex)`
|
const Container = styled(Flex)`
|
||||||
|
@ -50,10 +50,14 @@ class DocumentsStore {
|
|||||||
const res = await client.post('/documents.info', { id });
|
const res = await client.post('/documents.info', { id });
|
||||||
invariant(res && res.data, 'Document not available');
|
invariant(res && res.data, 'Document not available');
|
||||||
const { data } = res;
|
const { data } = res;
|
||||||
|
const document = new Document(data);
|
||||||
|
|
||||||
runInAction('DocumentsStore#fetch', () => {
|
runInAction('DocumentsStore#fetch', () => {
|
||||||
this.data.set(data.id, new Document(data));
|
this.data.set(data.id, document);
|
||||||
this.isLoaded = true;
|
this.isLoaded = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
return document;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.errors.add('Failed to load documents');
|
this.errors.add('Failed to load documents');
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,14 @@
|
|||||||
// @flow
|
// @flow
|
||||||
|
|
||||||
|
export const layout = {
|
||||||
|
padding: '1.5vw 1.875vw',
|
||||||
|
vpadding: '1.5vw',
|
||||||
|
hpadding: '1.875vw',
|
||||||
|
sidebarWidth: '22%',
|
||||||
|
sidebarMinWidth: '250px',
|
||||||
|
sidebarMaxWidth: '350px',
|
||||||
|
};
|
||||||
|
|
||||||
export const size = {
|
export const size = {
|
||||||
tiny: '2px',
|
tiny: '2px',
|
||||||
small: '4px',
|
small: '4px',
|
||||||
@ -28,6 +37,8 @@ export const fontWeight = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const color = {
|
export const color = {
|
||||||
|
text: '#171B35',
|
||||||
|
|
||||||
/* Brand */
|
/* Brand */
|
||||||
primary: '#73DF7B',
|
primary: '#73DF7B',
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user