Fix prettier integration, format (#31)

* Fix prettier integration, format

* Reformat again
This commit is contained in:
Tom Moor
2017-04-27 21:48:13 -07:00
committed by GitHub
parent 51fade7439
commit 2095b3a874
74 changed files with 823 additions and 808 deletions

View File

@@ -1,23 +1,16 @@
{
"extends": [
"airbnb",
"prettier",
"prettier/react"
],
"parser": "babel-eslint",
"extends": ["react-app", "plugin:import/errors", "plugin:import/warnings"],
"plugins": [
"prettier"
],
"rules": {
"arrow-body-style":[0, "as-needed"], // fix `this` shortcut on ES6 classes
"react/jsx-no-bind": 0, // Makes difficult to pass args to prop functions
"react/jsx-curly-spacing": [2, "always", {"spacing": {
"objectLiterals": "never"
}}], // Spaces inside curlies, except prop={{}}
"react/prefer-stateless-function": 0, // Don't prefer stateless components
"no-else-return": 0,
"new-cap": 0,
"no-param-reassign": 0,
no-unused-vars: ["error", {
"argsIgnorePattern": "^_",
}],
"import/order": "warn",
// Prettier automatically uses the least amount of parens possible, so this
// does more harm than good.
"no-mixed-operators": "off",
// Enforce that code is formatted with prettier.
"prettier/prettier": ["error", {"trailingComma": "es5", "singleQuote": true}]
},
"settings" : {
"import/resolver": {
@@ -34,7 +27,6 @@
SLACK_KEY: true,
SLACK_REDIRECT_URI: true,
DEPLOYMENT: true,
afterAll: true
},
}

View File

@@ -1,9 +1,8 @@
import React, { PropTypes } from 'react';
import { Flex } from 'reflexbox';
import styles from './Alert.scss';
import classNames from 'classnames/bind';
import styles from './Alert.scss';
const cx = classNames.bind(styles);
class Alert extends React.Component {
@@ -12,9 +11,8 @@ class Alert extends React.Component {
danger: PropTypes.bool,
warning: PropTypes.bool,
success: PropTypes.bool,
info: PropTypes.bool,
offline: PropTypes.bool,
}
};
render() {
let alertType;
@@ -25,7 +23,11 @@ class Alert extends React.Component {
if (!alertType) alertType = 'info'; // default
return (
<Flex align="center" justify="center" className={ cx(styles.container, styles[alertType]) }>
<Flex
align="center"
justify="center"
className={cx(styles.container, styles[alertType])}
>
{this.props.children}
</Flex>
);

View File

@@ -8,29 +8,29 @@ import styles from './AtlasPreview.scss';
// import classNames from 'classnames/bind';
// const cx = classNames.bind(styles);
@observer
class AtlasPreview extends React.Component {
@observer class AtlasPreview extends React.Component {
static propTypes = {
data: React.PropTypes.object.isRequired,
}
};
render() {
const data = this.props.data;
return (
<div className={styles.container}>
<h2><Link to={ data.url } className={ styles.atlasLink }>{ data.name }</Link></h2>
{ data.recentDocuments.length > 0 ?
data.recentDocuments.map(document => {
return (
<DocumentLink document={ document } key={ document.id } />
);
<h2>
<Link to={data.url} className={styles.atlasLink}>{data.name}</Link>
</h2>
{data.recentDocuments.length > 0
? data.recentDocuments.map(document => {
return <DocumentLink document={document} key={document.id} />;
})
: (
<div className={ styles.description }>
No documents. Why not <Link to={ `${data.url}/new` }>create one</Link>?
</div>
) }
: <div className={styles.description}>
No documents. Why not
{' '}
<Link to={`${data.url}/new`}>create one</Link>
?
</div>}
</div>
);
}

View File

@@ -1,16 +1,18 @@
import React from 'react';
import { observer } from "mobx-react"
import { observer } from 'mobx-react';
import moment from 'moment';
import Link from 'react-router/lib/Link';
import styles from './DocumentLink.scss';
const DocumentLink = observer((props) => {
const DocumentLink = observer(props => {
return (
<Link to={props.document.url} className={styles.link}>
<h3 className={styles.title}>{props.document.title}</h3>
<span className={ styles.timestamp }>{ moment(props.document.updatedAt).fromNow() }</span>
<span className={styles.timestamp}>
{moment(props.document.updatedAt).fromNow()}
</span>
</Link>
);
});

View File

@@ -7,9 +7,12 @@ const cx = classNames.bind(styles);
import { randomInteger } from 'utils/random';
const randomValues = Array.from(new Array(5), () => `${randomInteger(85, 100)}%`);
const randomValues = Array.from(
new Array(5),
() => `${randomInteger(85, 100)}%`
);
export default (_props) => {
export default _props => {
return (
<ReactCSSTransitionGroup
transitionName="fadeIn"
@@ -25,19 +28,19 @@ export default (_props) => {
<div
className={cx(styles.mask, styles.header)}
style={{ width: randomValues[0] }}
>&nbsp;</div>
/>
<div
className={cx(styles.mask, styles.bodyText)}
style={{ width: randomValues[1] }}
>&nbsp;</div>
/>
<div
className={cx(styles.mask, styles.bodyText)}
style={{ width: randomValues[2] }}
>&nbsp;</div>
/>
<div
className={cx(styles.mask, styles.bodyText)}
style={{ width: randomValues[3] }}
>&nbsp;</div>
/>
</div>
</div>
</ReactCSSTransitionGroup>

View File

@@ -2,7 +2,7 @@ import React from 'react';
import styles from './CenteredContent.scss';
const CenteredContent = (props) => {
const CenteredContent = props => {
const style = {
maxWidth: props.maxWidth,
...props.style,

View File

@@ -2,10 +2,8 @@ import React from 'react';
import styles from './Divider.scss';
const Divider = (props) => {
return(
<div className={ styles.divider }><span></span></div>
);
const Divider = props => {
return <div className={styles.divider}><span /></div>;
};
export default Divider;

View File

@@ -7,11 +7,10 @@ import DocumentHtml from './components/DocumentHtml';
import styles from './Document.scss';
@observer
class Document extends React.Component {
@observer class Document extends React.Component {
static propTypes = {
document: PropTypes.object.isRequired,
}
};
render() {
return (

View File

@@ -4,19 +4,18 @@ import { observer } from 'mobx-react';
import styles from './DocumentHtml.scss';
@observer
class DocumentHtml extends React.Component {
@observer class DocumentHtml extends React.Component {
static propTypes = {
html: PropTypes.string.isRequired,
}
};
componentDidMount = () => {
this.setExternalLinks();
}
};
componentDidUpdate = () => {
this.setExternalLinks();
}
};
setExternalLinks = () => {
const links = ReactDOM.findDOMNode(this).querySelectorAll('a');
@@ -25,7 +24,7 @@ class DocumentHtml extends React.Component {
link.target = '_blank'; // eslint-disable-line no-param-reassign
}
});
}
};
render() {
return (

View File

@@ -2,6 +2,4 @@ import Document from './Document';
import DocumentHtml from './components/DocumentHtml';
export default Document;
export {
DocumentHtml,
};
export { DocumentHtml };

View File

@@ -8,12 +8,13 @@ import styles from './DocumentList.scss';
class DocumentList extends React.Component {
static propTypes = {
documents: React.PropTypes.arrayOf(React.PropTypes.object),
}
};
render() {
return (
<div>
{ this.props.documents && this.props.documents.map((document) => {
{this.props.documents &&
this.props.documents.map(document => {
return (
<div>
<DocumentPreview document={document} />
@@ -24,6 +25,6 @@ class DocumentList extends React.Component {
</div>
);
}
};
}
export default DocumentList;

View File

@@ -10,7 +10,7 @@ import styles from './DocumentPreview.scss';
class Document extends React.Component {
static propTypes = {
document: React.PropTypes.object.isRequired,
}
};
render() {
return (
@@ -23,20 +23,16 @@ class Document extends React.Component {
collaborators={toJS(this.props.document.collaborators)}
/>
<Link
to={ this.props.document.url }
className={ styles.title }
>
<Link to={this.props.document.url} className={styles.title}>
<h2>{this.props.document.title}</h2>
</Link>
<div dangerouslySetInnerHTML={{ __html: this.props.document.preview }} />
<div
dangerouslySetInnerHTML={{ __html: this.props.document.preview }}
/>
<div>
<Link
to={ this.props.document.url }
className={ styles.continueLink }
>
<Link to={this.props.document.url} className={styles.continueLink}>
Continue reading...
</Link>
</div>

View File

@@ -10,14 +10,13 @@ class MenuItem extends React.Component {
} else {
this.props.onClick();
}
}
};
render() {
return (
<div
className={ styles.menuItem }
onClick={ this.onClick }
>{ this.props.children }</div>
<div className={styles.menuItem} onClick={this.onClick}>
{this.props.children}
</div>
);
}
}
@@ -34,23 +33,23 @@ class DropdownMenu extends React.Component {
static propTypes = {
label: React.PropTypes.node.isRequired,
children: React.PropTypes.node.isRequired,
}
};
state = {
menuVisible: false,
}
};
onMouseEnter = () => {
this.setState({ menuVisible: true });
}
};
onMouseLeave = () => {
this.setState({ menuVisible: false });
}
};
onClick = () => {
this.setState({ menuVisible: !this.state.menuVisible });
}
};
render() {
return (
@@ -63,17 +62,15 @@ class DropdownMenu extends React.Component {
{this.props.label}
</div>
{ this.state.menuVisible ? (
<div className={ styles.menu }>
{this.state.menuVisible
? <div className={styles.menu}>
{this.props.children}
</div>
) : null }
: null}
</div>
);
}
};
}
export default DropdownMenu;
export {
MenuItem,
}
export { MenuItem };

View File

@@ -2,13 +2,8 @@ import React from 'react';
import styles from './MoreIcon.scss';
const MoreIcon = (props) => {
return (
<img
src={ require("./assets/more.svg") }
className={ styles.icon }
/>
);
const MoreIcon = props => {
return <img src={require('./assets/more.svg')} className={styles.icon} />;
};
export default MoreIcon;

View File

@@ -1,7 +1,4 @@
import DropdownMenu, { MenuItem } from './DropdownMenu';
import MoreIcon from './components/MoreIcon';
export default DropdownMenu;
export {
MenuItem,
MoreIcon,
};
export { MenuItem, MoreIcon };

View File

@@ -2,12 +2,11 @@ import React from 'react';
import styles from './HeaderAction.scss';
const HeaderAction = (props) => {
const HeaderAction = props => {
return (
<div
onClick={ props.onClick }
className={ styles.container }
>{ props.children }</div>
<div onClick={props.onClick} className={styles.container}>
{props.children}
</div>
);
};

View File

@@ -1,20 +1,19 @@
import React from 'react';
import { observer } from 'mobx-react';
@observer
class SaveAction extends React.Component {
@observer class SaveAction extends React.Component {
static propTypes = {
onClick: React.PropTypes.func.isRequired,
disabled: React.PropTypes.bool,
isNew: React.PropTypes.bool,
}
};
onClick = (event) => {
onClick = event => {
if (this.props.disabled) return;
event.preventDefault();
this.props.onClick();
}
};
render() {
const { disabled, isNew } = this.props;

View File

@@ -10,7 +10,7 @@ class Title extends React.Component {
children: React.PropTypes.string,
truncate: React.PropTypes.number,
placeholder: React.PropTypes.string,
}
};
render() {
let title;
@@ -28,7 +28,7 @@ class Title extends React.Component {
return (
<span>
{ title && (<span>&nbsp;/&nbsp;</span>) }
{title && <span>&nbsp;/&nbsp;</span>}
<span
title={this.props.children}
className={cx(styles.title, { untitled: usePlaceholder })}

View File

@@ -5,8 +5,4 @@ import SaveAction from './components/SaveAction';
export default Layout;
export {
Title,
HeaderAction,
SaveAction,
};
export { Title, HeaderAction, SaveAction };

View File

@@ -2,10 +2,10 @@ import React from 'react';
import styles from './LoadingIndicator.scss';
const LoadingIndicator = (props) => {
const LoadingIndicator = props => {
return (
<div className={styles.loading}>
<div className={ styles.loader }></div>
<div className={styles.loader} />
</div>
);
};

View File

@@ -14,8 +14,7 @@ import './codemirror.scss';
import { client } from 'utils/ApiClient';
@observer
class MarkdownEditor extends React.Component {
@observer class MarkdownEditor extends React.Component {
static propTypes = {
text: React.PropTypes.string,
onChange: React.PropTypes.func.isRequired,
@@ -27,15 +26,15 @@ class MarkdownEditor extends React.Component {
// re-render to help with CodeMirror focus issues
preview: React.PropTypes.bool,
toggleUploadingIndicator: React.PropTypes.func,
}
};
onChange = (newText) => {
onChange = newText => {
if (newText !== this.props.text) {
this.props.onChange(newText);
}
}
};
onDropAccepted = (files) => {
onDropAccepted = files => {
const file = files[0];
const editor = this.getEditorInstance();
@@ -56,7 +55,8 @@ class MarkdownEditor extends React.Component {
}
editor.setCursor(newCursorPositionLine, 0);
client.post('/user.s3Upload', {
client
.post('/user.s3Upload', {
kind: file.type,
size: file.size,
filename: file.name,
@@ -100,23 +100,23 @@ class MarkdownEditor extends React.Component {
.catch(_err => {
this.props.toggleUploadingIndicator();
});
}
};
onPaddingTopClick = () => {
const cm = this.getEditorInstance();
cm.setCursor(0, 0);
cm.focus();
}
};
onPaddingBottomClick = () => {
const cm = this.getEditorInstance();
cm.setCursor(cm.lineCount(), 0);
cm.focus();
}
};
getEditorInstance = () => {
return this.refs.editor.getCodeMirror();
}
};
render = () => {
const options = {
@@ -163,7 +163,7 @@ class MarkdownEditor extends React.Component {
<ClickablePadding onClick={this.onPaddingBottomClick} />
</Dropzone>
);
}
};
}
export default MarkdownEditor;

View File

@@ -2,13 +2,8 @@ import React from 'react';
import styles from './ClickablePadding.scss';
const ClickablePadding = (props) => {
return (
<div
className={ styles.container }
onClick={ props.onClick }
>&nbsp;</div>
)
const ClickablePadding = props => {
return <div className={styles.container} onClick={props.onClick}>&nbsp;</div>;
};
ClickablePadding.propTypes = {

View File

@@ -11,7 +11,7 @@ class Offline extends React.Component {
state = {
offline: !navigator.onLine,
}
};
getChildContext() {
return {
@@ -22,7 +22,7 @@ class Offline extends React.Component {
componentDidMount = () => {
window.addEventListener('offline', this.handleConnectionState);
window.addEventListener('online', this.handleConnectionState);
}
};
componentWillUnmount = () => {
window.removeEventListener('offline', this.handleConnectionState);
@@ -33,7 +33,7 @@ class Offline extends React.Component {
this.setState({
offline: !navigator.onLine,
});
}
};
render() {
return React.Children.only(this.props.children);

View File

@@ -1,7 +1,4 @@
import Offline from './Offline';
import injectOffline from './injectOffline';
export {
Offline,
injectOffline,
}
export { Offline, injectOffline };

View File

@@ -1,6 +1,6 @@
import React from 'react';
const injectOffline = (WrappedComponent) => {
const injectOffline = WrappedComponent => {
return class OfflineWrapper extends React.Component {
static contextTypes = {
offline: React.PropTypes.bool,
@@ -11,7 +11,7 @@ const injectOffline = (WrappedComponent) => {
offline: this.context.offline,
};
return (<WrappedComponent { ...this.props } { ...newProps } />);
return <WrappedComponent {...this.props} {...newProps} />;
}
};
};

View File

@@ -33,15 +33,19 @@ class PublishingInfo extends React.Component {
))}
</Flex>
<span className={styles.userName}>
{ this.props.createdBy.name } published { moment(this.props.createdAt).fromNow() }
{ this.props.createdAt !== this.props.updatedAt ? (
<span>
{this.props.createdBy.name}
{' '}
published
{' '}
{moment(this.props.createdAt).fromNow()}
{this.props.createdAt !== this.props.updatedAt
? <span>
&nbsp;and&nbsp;
{this.props.createdBy.id !== this.props.updatedBy.id &&
` ${this.props.updatedBy.name} `}
modified {moment(this.props.updatedAt).fromNow()}
</span>
) : null }
: null}
</span>
</Flex>
);

View File

@@ -6,45 +6,50 @@ import classNames from 'classnames/bind';
const cx = classNames.bind(styles);
class Node extends React.Component {
displayName: 'UITreeNode'
displayName: 'UITreeNode';
renderCollapse = () => {
var index = this.props.index;
const index = this.props.index;
if (index.children && index.children.length) {
var collapsed = index.node.collapsed;
const collapsed = index.node.collapsed;
return (
<span
className={cx(styles.collapse, collapsed ? styles.caretRight : styles.caretDown)}
onMouseDown={function(e) {e.stopPropagation()}}
className={cx(
styles.collapse,
collapsed ? styles.caretRight : styles.caretDown
)}
onMouseDown={function(e) {
e.stopPropagation();
}}
onClick={this.handleCollapse}
>
<img src={ require("./assets/chevron.svg") } />
<img src={require('./assets/chevron.svg')} />
</span>
);
}
return null;
}
};
renderChildren = () => {
var index = this.props.index;
var tree = this.props.tree;
var dragging = this.props.dragging;
const index = this.props.index;
const tree = this.props.tree;
const dragging = this.props.dragging;
if (index.children && index.children.length) {
var childrenStyles = {};
const childrenStyles = {};
if (!this.props.rootNode) {
if (index.node.collapsed) childrenStyles.display = 'none';
childrenStyles['paddingLeft'] = this.props.paddingLeft + 'px';
childrenStyles.paddingLeft = `${this.props.paddingLeft}px`;
}
return (
<div className={styles.children} style={childrenStyles}>
{index.children.map((child) => {
var childIndex = tree.getIndex(child);
{index.children.map(child => {
const childIndex = tree.getIndex(child);
return (
<Node
tree={tree}
@@ -63,18 +68,18 @@ class Node extends React.Component {
}
return null;
}
};
isModifying = () => {
return this.props.allowUpdates && !this.props.rootNode;
}
};
onClick = () => {
const index = this.props.index;
const node = index.node;
if (!this.isModifying()) history.push(node.url);
}
};
render() {
const tree = this.props.tree;
@@ -84,14 +89,21 @@ class Node extends React.Component {
const style = {};
return (
<div className={cx(styles.node, {
<div
className={cx(styles.node, {
placeholder: index.id === dragging,
rootNode: this.props.rootNode,
})} style={style}>
})}
style={style}
>
<div
className={styles.inner}
ref="inner"
onMouseDown={this.props.rootNode || !this.props.allowUpdates ? (e) => e.stopPropagation() : this.handleMouseDown}
onMouseDown={
this.props.rootNode || !this.props.allowUpdates
? e => e.stopPropagation()
: this.handleMouseDown
}
>
{!this.props.rootNode && this.renderCollapse()}
<span
@@ -109,20 +121,20 @@ class Node extends React.Component {
);
}
handleCollapse = (e) => {
handleCollapse = e => {
e.stopPropagation();
var nodeId = this.props.index.id;
const nodeId = this.props.index.id;
if (this.props.onCollapse) this.props.onCollapse(nodeId);
}
};
handleMouseDown = (e) => {
var nodeId = this.props.index.id;
var dom = this.refs.inner;
handleMouseDown = e => {
const nodeId = this.props.index.id;
const dom = this.refs.inner;
if (this.props.onDragStart) {
this.props.onDragStart(nodeId, dom, e);
}
}
};
}
module.exports = Node;

View File

@@ -1,11 +1,11 @@
var Tree = require('js-tree');
var proto = Tree.prototype;
const Tree = require('js-tree');
const proto = Tree.prototype;
proto.updateNodesPosition = function() {
var top = 1;
var left = 1;
var root = this.getIndex(1);
var self = this;
let top = 1;
let left = 1;
const root = this.getIndex(1);
const self = this;
root.top = top++;
root.left = left++;
@@ -15,9 +15,9 @@ proto.updateNodesPosition = function() {
}
function walk(children, parent, left, collapsed) {
var height = 1;
children.forEach(function(id) {
var node = self.getIndex(id);
let height = 1;
children.forEach(id => {
const node = self.getIndex(id);
if (collapsed) {
node.top = null;
node.left = null;
@@ -27,7 +27,12 @@ proto.updateNodesPosition = function() {
}
if (node.children && node.children.length) {
height += walk(node.children, node, left+1, collapsed || node.node.collapsed);
height += walk(
node.children,
node,
left + 1,
collapsed || node.node.collapsed
);
} else {
node.height = 1;
height += 1;
@@ -43,8 +48,8 @@ proto.updateNodesPosition = function() {
proto.move = function(fromId, toId, placement) {
if (fromId === toId || toId === 1) return;
var obj = this.remove(fromId);
var index = null;
const obj = this.remove(fromId);
let index = null;
if (placement === 'before') index = this.insertBefore(obj, toId);
else if (placement === 'after') index = this.insertAfter(obj, toId);
@@ -57,8 +62,8 @@ proto.move = function(fromId, toId, placement) {
};
proto.getNodeByTop = function(top) {
var indexes = this.indexes;
for(var id in indexes) {
const indexes = this.indexes;
for (const id in indexes) {
if (indexes.hasOwnProperty(id)) {
if (indexes[id].top === top) return indexes[id];
}

View File

@@ -1,6 +1,6 @@
var React = require('react');
var Tree = require('./Tree');
var Node = require('./Node');
const React = require('react');
const Tree = require('./Tree');
const Node = require('./Node');
import styles from './Tree.scss';
@@ -16,7 +16,7 @@ module.exports = React.createClass({
getDefaultProps() {
return {
paddingLeft: 20
paddingLeft: 20,
};
},
@@ -30,33 +30,33 @@ module.exports = React.createClass({
},
init(props) {
var tree = new Tree(props.tree);
const tree = new Tree(props.tree);
tree.isNodeCollapsed = props.isNodeCollapsed;
tree.changeNodeCollapsed = props.changeNodeCollapsed;
tree.updateNodesPosition();
return {
tree: tree,
tree,
dragging: {
id: null,
x: null,
y: null,
w: null,
h: null
}
h: null,
},
};
},
getDraggingDom() {
var tree = this.state.tree;
var dragging = this.state.dragging;
const tree = this.state.tree;
const dragging = this.state.dragging;
if (dragging && dragging.id) {
var draggingIndex = tree.getIndex(dragging.id);
var draggingStyles = {
const draggingIndex = tree.getIndex(dragging.id);
const draggingStyles = {
top: dragging.y,
left: dragging.x,
width: dragging.w
width: dragging.w,
};
return (
@@ -75,9 +75,9 @@ module.exports = React.createClass({
},
render() {
var tree = this.state.tree;
var dragging = this.state.dragging;
var draggingDom = this.getDraggingDom();
const tree = this.state.tree;
const dragging = this.state.dragging;
const draggingDom = this.getDraggingDom();
return (
<div className={styles.tree}>
@@ -99,11 +99,11 @@ module.exports = React.createClass({
dragStart(id, dom, e) {
this.dragging = {
id: id,
id,
w: dom.offsetWidth,
h: dom.offsetHeight,
x: dom.offsetLeft,
y: dom.offsetTop
y: dom.offsetTop,
};
this._startX = dom.offsetLeft;
@@ -120,40 +120,42 @@ module.exports = React.createClass({
drag(e) {
if (this._start) {
this.setState({
dragging: this.dragging
dragging: this.dragging,
});
this._start = false;
}
var tree = this.state.tree;
var dragging = this.state.dragging;
var paddingLeft = this.props.paddingLeft;
var newIndex = null;
var index = tree.getIndex(dragging.id);
var collapsed = index.node.collapsed;
const tree = this.state.tree;
const dragging = this.state.dragging;
const paddingLeft = this.props.paddingLeft;
let newIndex = null;
let index = tree.getIndex(dragging.id);
const collapsed = index.node.collapsed;
var _startX = this._startX;
var _startY = this._startY;
var _offsetX = this._offsetX;
var _offsetY = this._offsetY;
const _startX = this._startX;
const _startY = this._startY;
const _offsetX = this._offsetX;
const _offsetY = this._offsetY;
var pos = {
const pos = {
x: _startX + e.clientX - _offsetX,
y: _startY + e.clientY - _offsetY
y: _startY + e.clientY - _offsetY,
};
dragging.x = pos.x;
dragging.y = pos.y;
var diffX = dragging.x - paddingLeft/2 - (index.left-2) * paddingLeft;
var diffY = dragging.y - dragging.h/2 - (index.top-2) * dragging.h;
const diffX = dragging.x - paddingLeft / 2 - (index.left - 2) * paddingLeft;
const diffY = dragging.y - dragging.h / 2 - (index.top - 2) * dragging.h;
if(diffX < 0) { // left
if (diffX < 0) {
// left
if (index.parent && !index.next) {
newIndex = tree.move(index.id, index.parent, 'after');
}
} else if(diffX > paddingLeft) { // right
} else if (diffX > paddingLeft) {
// right
if (index.prev) {
var prevNode = tree.getIndex(index.prev).node;
const prevNode = tree.getIndex(index.prev).node;
if (!prevNode.collapsed && !prevNode.leaf) {
newIndex = tree.move(index.id, index.prev, 'append');
}
@@ -166,10 +168,12 @@ module.exports = React.createClass({
dragging.id = newIndex.id;
}
if(diffY < 0) { // up
var above = tree.getNodeByTop(index.top-1);
if (diffY < 0) {
// up
const above = tree.getNodeByTop(index.top - 1);
newIndex = tree.move(index.id, above.id, 'before');
} else if(diffY > dragging.h) { // down
} else if (diffY > dragging.h) {
// down
if (index.next) {
var below = tree.getIndex(index.next);
if (below.children && below.children.length && !below.node.collapsed) {
@@ -195,8 +199,8 @@ module.exports = React.createClass({
}
this.setState({
tree: tree,
dragging: dragging
tree,
dragging,
});
},
@@ -207,8 +211,8 @@ module.exports = React.createClass({
x: null,
y: null,
w: null,
h: null
}
h: null,
},
});
this.change(this.state.tree);
@@ -222,14 +226,14 @@ module.exports = React.createClass({
},
toggleCollapse(nodeId) {
var tree = this.state.tree;
var index = tree.getIndex(nodeId);
var node = index.node;
const tree = this.state.tree;
const index = tree.getIndex(nodeId);
const node = index.node;
node.collapsed = !node.collapsed;
tree.updateNodesPosition();
this.setState({
tree: tree
tree,
});
if (this.props.onCollapse) this.props.onCollapse(node.id, node.collapsed);

View File

@@ -1,7 +1,7 @@
let constants;
constants = {
API_USER_AGENT: `Atlas`,
API_USER_AGENT: 'Atlas',
API_BASE_URL: '/api',
};

View File

@@ -46,7 +46,7 @@ function requireAuth(nextState, replace) {
}
}
render((
render(
<div style={{ display: 'flex', flex: 1, height: '100%' }}>
<Provider {...stores}>
<Offline>
@@ -54,16 +54,32 @@ render((
<Route path="/" component={Application}>
<IndexRoute component={Home} />
<Route path="/dashboard" component={ Dashboard } onEnter={ requireAuth } />
<Route path="/collections/:id" component={ Atlas } onEnter={ requireAuth } />
<Route
path="/dashboard"
component={Dashboard}
onEnter={requireAuth}
/>
<Route
path="/collections/:id"
component={Atlas}
onEnter={requireAuth}
/>
<Route
path="/collections/:id/new"
component={DocumentEdit}
onEnter={requireAuth}
newDocument
/>
<Route path="/d/:id" component={ DocumentScene } onEnter={ requireAuth } />
<Route path="/d/:id/edit" component={ DocumentEdit } onEnter={ requireAuth } />
<Route
path="/d/:id"
component={DocumentScene}
onEnter={requireAuth}
/>
<Route
path="/d/:id/edit"
component={DocumentEdit}
onEnter={requireAuth}
/>
<Route
path="/d/:id/new"
component={DocumentEdit}
@@ -72,7 +88,11 @@ render((
/>
<Route path="/search" component={Search} onEnter={requireAuth} />
<Route path="/settings" component={ Settings } onEnter={ requireAuth } />
<Route
path="/settings"
component={Settings}
onEnter={requireAuth}
/>
<Route path="/auth/slack" component={SlackAuth} />
<Route
@@ -96,7 +116,6 @@ render((
content={flatpages.api}
/>
<Route path="/404" component={Error404} />
<Route path="*" component={Search} sceneType="notFound" />
</Route>
@@ -104,5 +123,6 @@ render((
</Offline>
</Provider>
{__DEV__ && <DevTools position={{ bottom: 0, right: 0 }} />}
</div>
), document.getElementById('root'));
</div>,
document.getElementById('root')
);

View File

@@ -22,7 +22,7 @@ import styles from './Atlas.scss';
class Atlas extends React.Component {
static propTypes = {
params: PropTypes.object.isRequired,
}
};
componentDidMount = () => {
const { id } = this.props.params;
@@ -32,21 +32,21 @@ class Atlas extends React.Component {
browserHistory.replace(data.navigationTree.url);
}
});
}
};
componentWillReceiveProps = (nextProps) => {
componentWillReceiveProps = nextProps => {
const key = nextProps.keydown.event;
if (key) {
if (key.key === 'c') {
_.defer(this.onCreate);
}
}
}
};
onCreate = (event) => {
onCreate = event => {
if (event) event.preventDefault();
browserHistory.push(`${store.collection.url}/new`);
}
};
render() {
const collection = store.collection;
@@ -70,11 +70,7 @@ class Atlas extends React.Component {
}
return (
<Layout
actions={ actions }
title={ title }
titleText={ titleText }
>
<Layout actions={actions} title={title} titleText={titleText}>
<CenteredContent>
<ReactCSSTransitionGroup
transitionName="fadeIn"
@@ -83,10 +79,9 @@ class Atlas extends React.Component {
transitionEnterTimeout={0}
transitionLeaveTimeout={0}
>
{ store.isFetching ? (
<AtlasPreviewLoading />
) : (
<div className={ styles.container }>
{store.isFetching
? <AtlasPreviewLoading />
: <div className={styles.container}>
<div className={styles.atlasDetails}>
<h2>{collection.name}</h2>
<blockquote>
@@ -96,9 +91,11 @@ class Atlas extends React.Component {
<Divider />
<DocumentList documents={ collection.recentDocuments } preview />
</div>
) }
<DocumentList
documents={collection.recentDocuments}
preview
/>
</div>}
</ReactCSSTransitionGroup>
</CenteredContent>
</Layout>

View File

@@ -18,10 +18,10 @@ const store = new class AtlasStore {
this.collection = data;
successCallback(data);
} catch (e) {
console.error("Something went wrong");
console.error('Something went wrong');
}
this.isFetching = false;
}
};
}();
export default store;

View File

@@ -18,7 +18,7 @@ class DashboardStore {
runInAction('fetchCollections', () => {
this.collections = data;
this.pagination = pagination;
data.forEach((collection) => cacheResponse(collection.recentDocuments));
data.forEach(collection => cacheResponse(collection.recentDocuments));
});
// If only one collection, visit it automatically
@@ -29,7 +29,7 @@ class DashboardStore {
console.error('Something went wrong');
}
this.isFetching = false;
}
};
constructor(options) {
this.team = options.team;

View File

@@ -3,9 +3,7 @@ import { observer } from 'mobx-react';
import { browserHistory, withRouter } from 'react-router';
import keydown from 'react-keydown';
import DocumentEditStore, {
DOCUMENT_EDIT_SETTINGS,
} from './DocumentEditStore';
import DocumentEditStore, { DOCUMENT_EDIT_SETTINGS } from './DocumentEditStore';
import Switch from 'components/Switch';
import Layout, { Title, HeaderAction, SaveAction } from 'components/Layout';
@@ -20,9 +18,13 @@ const DISREGARD_CHANGES = `You have unsaved changes.
Are you sure you want to disgard them?`;
@keydown([
'cmd+enter', 'ctrl+enter',
'cmd+esc', 'ctrl+esc',
'cmd+shift+p', 'ctrl+shift+p'])
'cmd+enter',
'ctrl+enter',
'cmd+esc',
'ctrl+esc',
'cmd+shift+p',
'ctrl+shift+p',
])
@withRouter
@observer
class DocumentEdit extends Component {
@@ -30,7 +32,7 @@ class DocumentEdit extends Component {
route: React.PropTypes.object.isRequired,
router: React.PropTypes.object.isRequired,
params: React.PropTypes.object,
}
};
constructor(props) {
super(props);
@@ -41,7 +43,7 @@ class DocumentEdit extends Component {
state = {
scrollTop: 0,
}
};
componentDidMount = () => {
if (this.props.route.newDocument) {
@@ -58,8 +60,7 @@ class DocumentEdit extends Component {
}
// Load editor async
EditorLoader()
.then(({ Editor }) => {
EditorLoader().then(({ Editor }) => {
this.setState({ Editor });
});
@@ -70,9 +71,9 @@ class DocumentEdit extends Component {
}
return null;
});
}
};
componentWillReceiveProps = (nextProps) => {
componentWillReceiveProps = nextProps => {
const key = nextProps.keydown.event;
if (key) {
@@ -91,7 +92,7 @@ class DocumentEdit extends Component {
this.store.togglePreview();
}
}
}
};
onSave = () => {
// if (this.props.title.length === 0) {
@@ -103,20 +104,20 @@ class DocumentEdit extends Component {
} else {
this.store.updateDocument();
}
}
};
onCancel = () => {
browserHistory.goBack();
}
};
onScroll = (scrollTop) => {
onScroll = scrollTop => {
this.setState({
scrollTop,
});
}
};
render() {
let title = (
const title = (
<Title
truncate={60}
placeholder={!this.store.isFetching && 'Untitled document'}
@@ -125,8 +126,9 @@ class DocumentEdit extends Component {
</Title>
);
let titleText = this.store.title;
let isNew = this.props.route.newDocument || this.props.route.newChildDocument;
const titleText = this.store.title;
const isNew =
this.props.route.newDocument || this.props.route.newChildDocument;
const actions = (
<Flex>
@@ -157,20 +159,18 @@ class DocumentEdit extends Component {
loading={this.store.isSaving || this.store.isUploading}
search={false}
>
{ (this.store.isFetching || !('Editor' in this.state)) ? (
<CenteredContent>
{this.store.isFetching || !('Editor' in this.state)
? <CenteredContent>
<AtlasPreviewLoading />
</CenteredContent>
) : (
<this.state.Editor
: <this.state.Editor
store={this.store}
scrollTop={this.state.scrollTop}
onScroll={this.onScroll}
onSave={this.onSave}
onCancel={this.onCancel}
togglePreview={this.togglePreview}
/>
) }
/>}
</Layout>
);
}

View File

@@ -5,7 +5,7 @@ import emojify from 'utils/emojify';
const DOCUMENT_EDIT_SETTINGS = 'DOCUMENT_EDIT_SETTINGS';
const parseHeader = (text) => {
const parseHeader = text => {
const firstLine = text.split(/\r?\n/)[0];
if (firstLine) {
const match = firstLine.match(/^#+ +(.*)$/);
@@ -40,9 +40,13 @@ class DocumentEditStore {
this.isFetching = true;
try {
const data = await client.get('/documents.info', {
const data = await client.get(
'/documents.info',
{
id: this.documentId,
}, { cache: true });
},
{ cache: true }
);
if (this.newChildDocument) {
this.parentDocument = data.data;
} else {
@@ -54,7 +58,7 @@ class DocumentEditStore {
console.error('Something went wrong');
}
this.isFetching = false;
}
};
@action saveDocument = async () => {
if (this.isSaving) return;
@@ -62,12 +66,16 @@ class DocumentEditStore {
this.isSaving = true;
try {
const data = await client.post('/documents.create', {
const data = await client.post(
'/documents.create',
{
parentDocument: this.parentDocument && this.parentDocument.id,
collection: this.collectionId || this.parentDocument.collection.id,
title: this.title || 'Untitled document',
text: this.text,
}, { cache: true });
},
{ cache: true }
);
const { url } = data.data;
this.hasPendingChanges = false;
@@ -76,7 +84,7 @@ class DocumentEditStore {
console.error('Something went wrong');
}
this.isSaving = false;
}
};
@action updateDocument = async () => {
if (this.isSaving) return;
@@ -84,11 +92,15 @@ class DocumentEditStore {
this.isSaving = true;
try {
const data = await client.post('/documents.update', {
const data = await client.post(
'/documents.update',
{
id: this.documentId,
title: this.title || 'Untitled document',
text: this.text,
}, { cache: true });
},
{ cache: true }
);
const { url } = data.data;
this.hasPendingChanges = false;
@@ -97,35 +109,35 @@ class DocumentEditStore {
console.error('Something went wrong');
}
this.isSaving = false;
}
};
@action updateText = (text) => {
@action updateText = text => {
this.text = text;
this.title = parseHeader(text);
this.hasPendingChanges = true;
}
};
@action updateTitle = (title) => {
@action updateTitle = title => {
this.title = title;
}
};
@action replaceText = (args) => {
@action replaceText = args => {
this.text = this.text.replace(args.original, args.new);
this.hasPendingChanges = true;
}
};
@action togglePreview = () => {
this.preview = !this.preview;
}
};
@action reset = () => {
this.title = 'Lets start with a title';
this.text = '# Lets start with a title\n\nAnd continue from there...';
}
};
@action toggleUploadingIndicator = () => {
this.isUploading = !this.isUploading;
}
};
// Generic
@@ -133,7 +145,7 @@ class DocumentEditStore {
localStorage[DOCUMENT_EDIT_SETTINGS] = JSON.stringify({
preview: toJS(this.preview),
});
}
};
constructor(settings) {
// Rehydrate settings
@@ -148,6 +160,4 @@ class DocumentEditStore {
}
export default DocumentEditStore;
export {
DOCUMENT_EDIT_SETTINGS,
};
export { DOCUMENT_EDIT_SETTINGS };

View File

@@ -8,15 +8,12 @@ import EditorPane from './EditorPane';
import styles from '../DocumentEdit.scss';
const Editor = observer((props) => {
const Editor = observer(props => {
const store = props.store;
return (
<div className={styles.container}>
<EditorPane
fullWidth={ !store.preview }
onScroll={ props.onScroll }
>
<EditorPane fullWidth={!store.preview} onScroll={props.onScroll}>
<MarkdownEditor
onChange={store.updateText}
text={store.text}
@@ -28,13 +25,11 @@ const Editor = observer((props) => {
toggleUploadingIndicator={store.toggleUploadingIndicator}
/>
</EditorPane>
{ store.preview ? (
<EditorPane
scrollTop={ props.scrollTop }
>
{store.preview
? <EditorPane scrollTop={props.scrollTop}>
<Preview html={convertToMarkdown(store.text)} />
</EditorPane>
) : null }
: null}
</div>
);
});

View File

@@ -10,32 +10,31 @@ class EditorPane extends React.Component {
onScroll: React.PropTypes.func.isRequired,
scrollTop: React.PropTypes.number,
fullWidth: React.PropTypes.bool,
}
componentWillReceiveProps = (nextProps) => {
};
componentWillReceiveProps = nextProps => {
if (nextProps.scrollTop) {
this.scrollToPosition(nextProps.scrollTop)
}
this.scrollToPosition(nextProps.scrollTop);
}
};
componentDidMount = () => {
this.refs.pane.addEventListener('scroll', this.handleScroll);
}
};
componentWillUnmount = () => {
this.refs.pane.removeEventListener('scroll', this.handleScroll);
}
};
handleScroll = (e) => {
handleScroll = e => {
setTimeout(() => {
const element = this.refs.pane;
const contentEl = this.refs.content;
this.props.onScroll(element.scrollTop / contentEl.offsetHeight);
}, 50);
}
};
scrollToPosition = (percentage) => {
scrollToPosition = percentage => {
const contentEl = this.refs.content;
// Push to edges
@@ -43,7 +42,7 @@ class EditorPane extends React.Component {
if (percentage > 0.99) percentage = 100;
this.refs.pane.scrollTop = percentage * contentEl.offsetHeight;
}
};
render() {
return (
@@ -57,6 +56,6 @@ class EditorPane extends React.Component {
</div>
);
}
};
}
export default EditorPane;

View File

@@ -6,7 +6,7 @@ import styles from './Preview.scss';
import classNames from 'classnames/bind';
const cx = classNames.bind(styles);
const Preview = (props) => {
const Preview = props => {
return (
<div className={cx(styles.container)}>
<DocumentHtml html={props.html} />

View File

@@ -1,5 +1,12 @@
import _ from 'lodash';
import { observable, action, computed, runInAction, toJS, autorunAsync } from 'mobx';
import {
observable,
action,
computed,
runInAction,
toJS,
autorunAsync,
} from 'mobx';
import { client } from 'utils/ApiClient';
import { browserHistory } from 'react-router';
@@ -19,15 +26,14 @@ class DocumentSceneStore {
/* Computed */
@computed get isCollection() {
return this.document &&
this.document.collection.type === 'atlas';
return this.document && this.document.collection.type === 'atlas';
}
@computed get collectionTree() {
if (!this.document || this.document.collection.type !== 'atlas') return;
const tree = this.document.collection.navigationTree;
const collapseNodes = (node) => {
const collapseNodes = node => {
node.collapsed = this.collapsedNodes.includes(node.id);
node.children = node.children.map(childNode => {
return collapseNodes(childNode);
@@ -69,7 +75,7 @@ class DocumentSceneStore {
}
this.isFetching = false;
this.updatingContent = false;
}
};
@action deleteDocument = async () => {
this.isFetching = true;
@@ -81,9 +87,9 @@ class DocumentSceneStore {
console.error('Something went wrong');
}
this.isFetching = false;
}
};
@action updateNavigationTree = async (tree) => {
@action updateNavigationTree = async tree => {
// Only update when tree changes
if (_.isEqual(toJS(tree), toJS(this.document.collection.navigationTree))) {
return true;
@@ -104,15 +110,15 @@ class DocumentSceneStore {
console.error('Something went wrong');
}
this.updatingStructure = false;
}
};
@action onNodeCollapse = (nodeId) => {
@action onNodeCollapse = nodeId => {
if (_.indexOf(this.collapsedNodes, nodeId) >= 0) {
this.collapsedNodes = _.without(this.collapsedNodes, nodeId);
} else {
this.collapsedNodes.push(nodeId);
}
}
};
// General
@@ -120,7 +126,7 @@ class DocumentSceneStore {
localStorage[DOCUMENT_PREFERENCES] = JSON.stringify({
collapsedNodes: toJS(this.collapsedNodes),
});
}
};
constructor(settings, options) {
// Rehydrate settings
@@ -136,6 +142,4 @@ class DocumentSceneStore {
}
export default DocumentSceneStore;
export {
DOCUMENT_PREFERENCES,
};
export { DOCUMENT_PREFERENCES };

View File

@@ -12,8 +12,7 @@ const cx = classNames.bind(styles);
import SidebarStore from './SidebarStore';
@observer
class Sidebar extends React.Component {
@observer class Sidebar extends React.Component {
static store;
static propTypes = {
@@ -22,7 +21,7 @@ class Sidebar extends React.Component {
navigationTree: PropTypes.object.isRequired,
onNavigationUpdate: PropTypes.func.isRequired,
onNodeCollapse: PropTypes.func.isRequired,
}
};
constructor(props) {
super(props);
@@ -30,15 +29,15 @@ class Sidebar extends React.Component {
this.store = new SidebarStore();
}
toggleEdit = (e) => {
toggleEdit = e => {
e.preventDefault();
this.store.toggleEdit();
}
};
render() {
return (
<Flex>
{ this.props.open && (
{this.props.open &&
<Flex column className={cx(styles.sidebar)}>
<Flex auto className={cx(styles.content)}>
<Tree
@@ -50,11 +49,10 @@ class Sidebar extends React.Component {
/>
</Flex>
<Flex auto className={styles.actions}>
{ this.store.isEditing && (
{this.store.isEditing &&
<span className={styles.action}>
Drag & drop to organize <Separator />&nbsp;
</span>
) }
</span>}
<span
role="button"
onClick={this.toggleEdit}
@@ -63,15 +61,14 @@ class Sidebar extends React.Component {
{!this.store.isEditing ? 'Organize documents' : 'Done'}
</span>
</Flex>
</Flex>
) }
</Flex>}
<div
onClick={this.props.onToggle}
className={cx(styles.sidebarToggle, { active: this.store.isEditing })}
title="Toggle sidebar (Cmd+/)"
>
<img
src={ require("assets/icons/menu.svg") }
src={require('assets/icons/menu.svg')}
className={styles.menuIcon}
alt="Menu"
/>

View File

@@ -7,7 +7,7 @@ class SidebarStore {
@action toggleEdit = () => {
this.isEditing = !this.isEditing;
}
};
}
export default SidebarStore;

View File

@@ -6,7 +6,7 @@ class Separator extends React.Component {
render() {
return (
<span className={styles.separator}>
&middot;
·
</span>
);
}

View File

@@ -7,9 +7,7 @@ import CenteredContent from 'components/CenteredContent';
class Error404 extends React.Component {
render() {
return (
<Layout
titleText="Not Found"
>
<Layout titleText="Not Found">
<CenteredContent>
<h1>Not Found</h1>

View File

@@ -7,13 +7,13 @@ import CenteredContent from 'components/CenteredContent';
class ErrorAuth extends React.Component {
render() {
return (
<Layout
titleText="Not Found"
>
<Layout titleText="Not Found">
<CenteredContent>
<h1>Authentication failed</h1>
<p>We were unable to log you in. <Link to="/">Please try again.</Link></p>
<p>
We were unable to log you in. <Link to="/">Please try again.</Link>
</p>
</CenteredContent>
</Layout>
);

View File

@@ -7,21 +7,16 @@ import { DocumentHtml } from 'components/Document';
import { convertToMarkdown } from 'utils/markdown';
@observer
class Flatpage extends React.Component {
@observer class Flatpage extends React.Component {
static propTypes = {
route: PropTypes.object,
}
};
render() {
const { title, content } = this.props.route;
return (
<Layout
title={ <Title>{ title }</Title> }
titleText={ title }
search={ false }
>
<Layout title={<Title>{title}</Title>} titleText={title} search={false}>
<CenteredContent>
<DocumentHtml html={convertToMarkdown(content)} />
</CenteredContent>

View File

@@ -1,25 +1,43 @@
import React from 'react';
import { Frame } from 'react-keyframes';
let frames = [];
const p = (node) => frames.push(node);
const E = (props) => {
return (<Frame duration={props.duration || 300} component='div'>{ props.children }</Frame>);
const frames = [];
const p = node => frames.push(node);
const E = props => {
return (
<Frame duration={props.duration || 300} component="div">
{props.children}
</Frame>
);
};
const line1 = (<p>Hi there,</p>);
const line2 = (<p>We're excited to share what were building.</p>);
const line3 = (<p>We <strong>**love**</strong> Markdown,</p>);
const line4 = (<p>but we also get that it's not for everyone.</p>);
const line5 = (<p>Together with you,</p>);
const line6 = (<p>we want to build the best place to</p>);
const line7 = (<p>share ideas,</p>);
const line8 = (<p>tell stories,</p>);
const line9 = (<p>and build knowledge.</p>);
const line10 = (<p>We're just getting started.</p>);
const line11 = (<p>Welcome to Atlas.</p>);
const line1 = <p>Hi there,</p>;
const line2 = <p>We're excited to share what were building.</p>;
const line3 = <p>We <strong>**love**</strong> Markdown,</p>;
const line4 = <p>but we also get that it's not for everyone.</p>;
const line5 = <p>Together with you,</p>;
const line6 = <p>we want to build the best place to</p>;
const line7 = <p>share ideas,</p>;
const line8 = <p>tell stories,</p>;
const line9 = <p>and build knowledge.</p>;
const line10 = <p>We're just getting started.</p>;
const line11 = <p>Welcome to Atlas.</p>;
p(<E>{line1}{line2}{line3}{line4}{line5}{line6}{line7}{line8}{line9}{line10}{line11}</E>);
p(
<E>
{line1}
{line2}
{line3}
{line4}
{line5}
{line6}
{line7}
{line8}
{line9}
{line10}
{line11}
</E>
);
// Hmms leaving this here for now, would be nice to something

View File

@@ -12,12 +12,11 @@ import styles from './Search.scss';
import SearchStore from './SearchStore';
@observer
class Search extends React.Component {
@observer class Search extends React.Component {
static propTypes = {
route: PropTypes.object.isRequired,
routeParams: PropTypes.object.isRequired,
}
};
constructor(props) {
super(props);
@@ -31,7 +30,7 @@ class Search extends React.Component {
searchTerm = searchTerm.split(/[\s-]+/gi).join(' ');
this.store.search(searchTerm);
}
}
};
get viewNotFound() {
const { sceneType } = this.props.route;
@@ -39,7 +38,7 @@ class Search extends React.Component {
}
render() {
const search = _.debounce((searchTerm) => {
const search = _.debounce(searchTerm => {
this.store.search(searchTerm);
}, 250);
const title = (
@@ -56,13 +55,12 @@ class Search extends React.Component {
loading={this.store.isFetching}
>
<CenteredContent>
{ this.viewNotFound && (
{this.viewNotFound &&
<div>
<h1>Not Found</h1>
<p>We're unable to find the page you're accessing.</p>
<hr />
</div>
) }
</div>}
<Flex column auto>
<Flex auto>
@@ -76,8 +74,11 @@ class Search extends React.Component {
onChange={search}
/>
</Flex>
{ this.store.documents && this.store.documents.map((document) => {
return (<DocumentPreview key={ document.id } document={ document } />);
{this.store.documents &&
this.store.documents.map(document => {
return (
<DocumentPreview key={document.id} document={document} />
);
})}
</Flex>
</CenteredContent>

View File

@@ -11,7 +11,7 @@ class SearchStore {
/* Actions */
@action search = async (query) => {
@action search = async query => {
this.searchTerm = query;
this.isFetching = true;
@@ -24,14 +24,14 @@ class SearchStore {
this.pagination = pagination;
});
} catch (e) {
console.error("Something went wrong");
console.error('Something went wrong');
}
} else {
this.documents = null;
}
this.isFetching = false;
}
};
}
export default SearchStore;

View File

@@ -3,15 +3,14 @@ import { observer } from 'mobx-react';
import styles from './SearchField.scss';
@observer
class SearchField extends React.Component {
@observer class SearchField extends React.Component {
static propTypes = {
onChange: PropTypes.func,
}
};
onChange = (event) => {
onChange = event => {
this.props.onChange(event.currentTarget.value);
}
};
render() {
return (

View File

@@ -12,8 +12,7 @@ import styles from './Settings.scss';
import SettingsStore from './SettingsStore';
@observer
class Settings extends React.Component {
@observer class Settings extends React.Component {
static store;
constructor(props) {
@@ -21,10 +20,10 @@ class Settings extends React.Component {
this.store = new SettingsStore();
}
onKeyCreate = (e) => {
onKeyCreate = e => {
e.preventDefault();
this.store.createApiKey();
}
};
render() {
const title = (
@@ -43,7 +42,7 @@ class Settings extends React.Component {
loading={this.store.isFetching}
>
<CenteredContent>
{ showSlackSettings && (
{showSlackSettings &&
<div className={styles.section}>
<h2 className={styles.sectionHeader}>Slack</h2>
<p>
@@ -55,10 +54,15 @@ class Settings extends React.Component {
scopes={['commands']}
redirectUri={`${URL}/auth/slack/commands`}
>
<img alt="Add to Slack" height="40" width="139" src="https://platform.slack-edge.com/img/add_to_slack.png" srcSet="https://platform.slack-edge.com/img/add_to_slack.png 1x, https://platform.slack-edge.com/img/add_to_slack@2x.png 2x" />
<img
alt="Add to Slack"
height="40"
width="139"
src="https://platform.slack-edge.com/img/add_to_slack.png"
srcSet="https://platform.slack-edge.com/img/add_to_slack.png 1x, https://platform.slack-edge.com/img/add_to_slack@2x.png 2x"
/>
</SlackAuthLink>
</div>
) }
</div>}
<div className={styles.section}>
<h2 className={styles.sectionHeader}>API access</h2>
@@ -67,7 +71,7 @@ class Settings extends React.Component {
Learn more in <a href>API documentation</a>.
</p>
{ this.store.apiKeys && (
{this.store.apiKeys &&
<table className={styles.apiKeyTable}>
{this.store.apiKeys.map(key => (
<ApiKeyRow
@@ -77,8 +81,7 @@ class Settings extends React.Component {
onDelete={this.store.deleteApiKey}
/>
))}
</table>
) }
</table>}
<div>
<InlineForm

View File

@@ -17,10 +17,10 @@ class SearchStore {
this.apiKeys = data;
});
} catch (e) {
console.error("Something went wrong");
console.error('Something went wrong');
}
this.isFetching = false;
}
};
@action createApiKey = async () => {
this.isFetching = true;
@@ -35,12 +35,12 @@ class SearchStore {
this.keyName = '';
});
} catch (e) {
console.error("Something went wrong");
console.error('Something went wrong');
}
this.isFetching = false;
}
};
@action deleteApiKey = async (id) => {
@action deleteApiKey = async id => {
this.isFetching = true;
try {
@@ -51,14 +51,14 @@ class SearchStore {
this.fetchApiKeys();
});
} catch (e) {
console.error("Something went wrong");
console.error('Something went wrong');
}
this.isFetching = false;
}
};
@action setKeyName = (value) => {
@action setKeyName = value => {
this.keyName = value.target.value;
}
};
constructor() {
this.fetchApiKeys();

View File

@@ -10,26 +10,21 @@ class ApiKeyRow extends React.Component {
name: PropTypes.string.isRequired,
secret: PropTypes.string.isRequired,
onDelete: PropTypes.func.isRequired,
}
};
state = {
disabled: false,
}
};
onClick = () => {
this.props.onDelete(this.props.id);
this.setState({ disabled: true });
}
};
render() {
const {
name,
secret,
} = this.props;
const { name, secret } = this.props;
const {
disabled,
} = this.state;
const { disabled } = this.state;
return (
<tr>
@@ -40,7 +35,9 @@ class ApiKeyRow extends React.Component {
role="button"
onClick={this.onClick}
className={cx(styles.deleteAction, { disabled })}
>Delete</span>
>
Delete
</span>
</td>
</tr>
);

View File

@@ -31,7 +31,6 @@ class SlackAuth extends React.Component {
browserHistory.replace('/dashboard');
} catch (e) {
browserHistory.push('/auth-error');
return;
}
} else {
// Regular Slack authentication

View File

@@ -1,6 +1,6 @@
export default (type, ...argNames) => {
return function(...args) {
let action = { type };
const action = { type };
argNames.forEach((arg, index) => {
action[argNames[index]] = args[index];
});

View File

@@ -1,5 +1,5 @@
{
"name": "BeautifulAtlas",
"name": "Atlas",
"private": true,
"main": "index.js",
"scripts": {
@@ -10,7 +10,6 @@
"start": "node index.js",
"dev": "cross-env NODE_ENV=development DEBUG=sql,cache,presenters ./node_modules/.bin/nodemon --watch server index.js",
"lint": "eslint frontend",
"prettier": "prettier --single-quote --trailing-comma es5 --write frontend/**/*.js server/**/*.js",
"deploy": "git push heroku master",
"heroku-postbuild": "npm run build && npm run sequelize db:migrate",
"sequelize": "./node_modules/.bin/sequelize",
@@ -21,7 +20,7 @@
},
"lint-staged": {
"*.js": [
"yarn prettier",
"eslint --fix",
"git add"
]
},
@@ -51,7 +50,7 @@
]
},
"engines": {
"node": "6.x"
"node": ">= 7.6"
},
"repository": {
"type": "git",
@@ -79,10 +78,12 @@
"dotenv": "^4.0.0",
"emoji-name-map": "1.1.2",
"eslint": "^3.19.0",
"eslint-config-airbnb": "^14.1.0",
"eslint-config-react-app": "^0.6.2",
"eslint-import-resolver-webpack": "^0.3.1",
"eslint-plugin-flowtype": "^2.32.1",
"eslint-plugin-import": "^2.2.0",
"eslint-plugin-jsx-a11y": "^4.0.0",
"eslint-plugin-prettier": "^2.0.1",
"eslint-plugin-react": "^6.10.3",
"exports-loader": "0.6.3",
"extract-text-webpack-plugin": "1.0.1",
@@ -155,8 +156,6 @@
"devDependencies": {
"babel-jest": "^15.0.0",
"enzyme": "^2.4.1",
"eslint-config-prettier": "^1.7.0",
"eslint-plugin-prettier": "^2.0.1",
"fetch-test-server": "^1.1.0",
"identity-obj-proxy": "^3.0.0",
"ignore-loader": "0.1.1",

View File

@@ -2640,21 +2640,9 @@ escope@^3.6.0:
esrecurse "^4.1.0"
estraverse "^4.1.1"
eslint-config-airbnb-base@^11.1.0:
version "11.1.3"
resolved "https://registry.yarnpkg.com/eslint-config-airbnb-base/-/eslint-config-airbnb-base-11.1.3.tgz#0e8db71514fa36b977fbcf977c01edcf863e0cf0"
eslint-config-airbnb@^14.1.0:
version "14.1.0"
resolved "https://registry.yarnpkg.com/eslint-config-airbnb/-/eslint-config-airbnb-14.1.0.tgz#355d290040bbf8e00bf8b4b19f4b70cbe7c2317f"
dependencies:
eslint-config-airbnb-base "^11.1.0"
eslint-config-prettier@^1.7.0:
version "1.7.0"
resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-1.7.0.tgz#cda3ce22df1e852daa9370f1f3446e8b8a02ce44"
dependencies:
get-stdin "^5.0.1"
eslint-config-react-app@^0.6.2:
version "0.6.2"
resolved "https://registry.yarnpkg.com/eslint-config-react-app/-/eslint-config-react-app-0.6.2.tgz#ee535cbaaf9e3576ea16b99afe720353d8730ec0"
eslint-import-resolver-node@^0.2.0:
version "0.2.3"
@@ -2684,6 +2672,12 @@ eslint-module-utils@^2.0.0:
debug "2.2.0"
pkg-dir "^1.0.0"
eslint-plugin-flowtype@^2.32.1:
version "2.32.1"
resolved "https://registry.yarnpkg.com/eslint-plugin-flowtype/-/eslint-plugin-flowtype-2.32.1.tgz#bbee185dedf97e5f63ec975cdcddd199bd2a2501"
dependencies:
lodash "^4.15.0"
eslint-plugin-import@^2.2.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.2.0.tgz#72ba306fad305d67c4816348a4699a4229ac8b4e"
@@ -3230,7 +3224,7 @@ get-caller-file@^1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.2.tgz#f702e63127e7e231c160a80c1554acb70d5047e5"
get-stdin@5.0.1, get-stdin@^5.0.1:
get-stdin@5.0.1:
version "5.0.1"
resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-5.0.1.tgz#122e161591e21ff4c52530305693f20e6393a398"
@@ -5259,7 +5253,7 @@ lodash@4.12.0:
version "4.12.0"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.12.0.tgz#2bd6dc46a040f59e686c972ed21d93dc59053258"
lodash@^4.0.0, lodash@^4.1.0, lodash@^4.10.0, lodash@^4.11.1, lodash@^4.13.1, lodash@^4.17.2, lodash@^4.17.4, lodash@^4.2.0, lodash@^4.3.0, lodash@^4.6.1:
lodash@^4.0.0, lodash@^4.1.0, lodash@^4.10.0, lodash@^4.11.1, lodash@^4.13.1, lodash@^4.15.0, lodash@^4.17.2, lodash@^4.17.4, lodash@^4.2.0, lodash@^4.3.0, lodash@^4.6.1:
version "4.17.4"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae"