From 919bca676981e1c2d38f298d3edc5c68603f2722 Mon Sep 17 00:00:00 2001 From: Tom Moor Date: Sun, 18 Nov 2018 01:13:28 -0800 Subject: [PATCH 1/6] Collections got descriptions now --- app/components/InputRich.js | 38 ++++++++++++++++++++++++ app/models/Collection.js | 15 +--------- app/scenes/Collection.js | 8 +++++ app/scenes/CollectionEdit.js | 27 ++++++++++++++--- app/scenes/Document/components/Editor.js | 32 ++------------------ app/scenes/Document/schema.js | 35 ++++++++++++++++++++++ server/api/collections.js | 3 +- 7 files changed, 110 insertions(+), 48 deletions(-) create mode 100644 app/components/InputRich.js create mode 100644 app/scenes/Document/schema.js diff --git a/app/components/InputRich.js b/app/components/InputRich.js new file mode 100644 index 000000000..d2b08843c --- /dev/null +++ b/app/components/InputRich.js @@ -0,0 +1,38 @@ +// @flow +import * as React from 'react'; +import styled from 'styled-components'; +import RichMarkdownEditor from 'rich-markdown-editor'; +import { LabelText, Outline } from 'components/Input'; + +type Props = { + label: string, + minHeight?: number, + maxHeight?: number, +}; + +export default function InputRich({ + label, + minHeight, + maxHeight, + ...rest +}: Props) { + return ( + + {label} + + + + + ); +} + +const StyledOutline = styled(Outline)` + padding: 8px 12px; + min-height: ${({ minHeight }) => (minHeight ? `${minHeight}px` : '0')}; + max-height: ${({ maxHeight }) => (maxHeight ? `${maxHeight}px` : 'auto')}; + overflow: scroll; + + > * { + display: block; + } +`; diff --git a/app/models/Collection.js b/app/models/Collection.js index 625bb87ba..9a005e56a 100644 --- a/app/models/Collection.js +++ b/app/models/Collection.js @@ -12,10 +12,9 @@ import type { NavigationNode } from 'types'; class Collection extends BaseModel { isSaving: boolean = false; ui: UiStore; - data: Object; createdAt: string; - description: ?string; + description: string; id: string; name: string; color: string; @@ -24,15 +23,6 @@ class Collection extends BaseModel { updatedAt: string; url: string; - /* Computed */ - - @computed - get entryUrl(): string { - return this.type === 'atlas' && this.documents.length > 0 - ? this.documents[0].url - : this.url; - } - @computed get isEmpty(): boolean { return this.documents.length === 0; @@ -66,8 +56,6 @@ class Collection extends BaseModel { travelDocuments(this.documents); } - /* Actions */ - @action fetch = async () => { try { @@ -138,7 +126,6 @@ class Collection extends BaseModel { @action updateData(data: Object = {}) { - this.data = data; extendObservable(this, data); } diff --git a/app/scenes/Collection.js b/app/scenes/Collection.js index 99cd8e2da..cc6720efe 100644 --- a/app/scenes/Collection.js +++ b/app/scenes/Collection.js @@ -5,6 +5,7 @@ import { observer, inject } from 'mobx-react'; import { withRouter, Link } from 'react-router-dom'; import styled from 'styled-components'; import { CollectionIcon, NewDocumentIcon, PinIcon } from 'outline-icons'; +import RichMarkdownEditor from 'rich-markdown-editor'; import { newDocumentUrl } from 'utils/routeHelpers'; import CollectionsStore from 'stores/CollectionsStore'; @@ -157,6 +158,13 @@ class CollectionScene extends React.Component { />{' '} {this.collection.name} + {this.collection.description && ( + + )} {hasPinnedDocuments && ( diff --git a/app/scenes/CollectionEdit.js b/app/scenes/CollectionEdit.js index 6ae01f237..c68720982 100644 --- a/app/scenes/CollectionEdit.js +++ b/app/scenes/CollectionEdit.js @@ -3,8 +3,9 @@ import * as React from 'react'; import { withRouter } from 'react-router-dom'; import { observable } from 'mobx'; import { inject, observer } from 'mobx-react'; -import Button from 'components/Button'; import Input from 'components/Input'; +import InputRich from 'components/InputRich'; +import Button from 'components/Button'; import Flex from 'shared/components/Flex'; import HelpText from 'components/HelpText'; import ColorPicker from 'components/ColorPicker'; @@ -19,18 +20,24 @@ type Props = { @observer class CollectionEdit extends React.Component { @observable name: string; + @observable description: string = ''; @observable color: string = ''; @observable isSaving: boolean; componentWillMount() { this.name = this.props.collection.name; + this.description = this.props.collection.description; } handleSubmit = async (ev: SyntheticEvent<*>) => { ev.preventDefault(); this.isSaving = true; - this.props.collection.updateData({ name: this.name, color: this.color }); + this.props.collection.updateData({ + name: this.name, + description: this.description, + color: this.color, + }); const success = await this.props.collection.save(); if (success) { @@ -40,6 +47,10 @@ class CollectionEdit extends React.Component { this.isSaving = false; }; + handleDescriptionChange = getValue => { + this.description = getValue(); + }; + handleNameChange = (ev: SyntheticInputEvent<*>) => { this.name = ev.target.value; }; @@ -53,8 +64,8 @@ class CollectionEdit extends React.Component {
- You can edit a collection’s name at any time, however doing so might - confuse your team mates. + You can edit a collection’s details at any time, however doing so + might confuse your team mates. { required autoFocus /> + { - switch (reason) { - case 'child_type_invalid': { - return change.setNodeByKey( - child.key, - index === 0 ? 'heading1' : 'paragraph' - ); - } - case 'child_required': { - const block = Block.create(index === 0 ? 'heading1' : 'paragraph'); - return change.insertNodeByKey(node.key, index, block); - } - default: - } -}; - class Editor extends React.Component { editor: *; diff --git a/app/scenes/Document/schema.js b/app/scenes/Document/schema.js new file mode 100644 index 000000000..64a3be4d3 --- /dev/null +++ b/app/scenes/Document/schema.js @@ -0,0 +1,35 @@ +// @flow +import { cloneDeep } from 'lodash'; +import { Block, Change, Node, Mark } from 'slate'; +import { schema as originalSchema } from 'rich-markdown-editor'; + +const schema = cloneDeep(originalSchema); + +// add rules to the schema to ensure the first node is a heading +schema.document.nodes.unshift({ types: ['heading1'], min: 1, max: 1 }); +schema.document.normalize = ( + change: Change, + reason: string, + { + node, + child, + mark, + index, + }: { node: Node, mark?: Mark, child: Node, index: number } +) => { + switch (reason) { + case 'child_type_invalid': { + return change.setNodeByKey( + child.key, + index === 0 ? 'heading1' : 'paragraph' + ); + } + case 'child_required': { + const block = Block.create(index === 0 ? 'heading1' : 'paragraph'); + return change.insertNodeByKey(node.key, index, block); + } + default: + } +}; + +export default schema; diff --git a/server/api/collections.js b/server/api/collections.js index a15942674..9812f0700 100644 --- a/server/api/collections.js +++ b/server/api/collections.js @@ -77,7 +77,7 @@ router.post('collections.exportAll', auth(), async ctx => { }); router.post('collections.update', auth(), async ctx => { - const { id, name, color } = ctx.body; + const { id, name, description, color } = ctx.body; ctx.assertPresent(name, 'name is required'); if (color) ctx.assertHexColor(color, 'Invalid hex value (please use format #FFFFFF)'); @@ -86,6 +86,7 @@ router.post('collections.update', auth(), async ctx => { authorize(ctx.state.user, 'update', collection); collection.name = name; + collection.description = description; collection.color = color; await collection.save(); From c308a2378fc119638ea8faa3ddd635ab534f11a9 Mon Sep 17 00:00:00 2001 From: Tom Moor Date: Sun, 18 Nov 2018 11:14:26 -0800 Subject: [PATCH 2/6] stash --- .../Document => }/components/Editor.js | 60 ++++++++++++++++--- app/components/InputRich.js | 49 ++++++++++----- app/scenes/CollectionEdit.js | 2 +- app/scenes/Document/Document.js | 48 ++------------- server/models/Team.js | 2 +- 5 files changed, 94 insertions(+), 67 deletions(-) rename app/{scenes/Document => }/components/Editor.js (59%) diff --git a/app/scenes/Document/components/Editor.js b/app/components/Editor.js similarity index 59% rename from app/scenes/Document/components/Editor.js rename to app/components/Editor.js index aec86e854..26b2002aa 100644 --- a/app/scenes/Document/components/Editor.js +++ b/app/components/Editor.js @@ -4,13 +4,17 @@ import styled from 'styled-components'; import { Text } from 'slate'; import RichMarkdownEditor, { Placeholder } from 'rich-markdown-editor'; import ClickablePadding from 'components/ClickablePadding'; -import schema from '../schema'; +import { uploadFile } from 'utils/uploadFile'; +import isInternalUrl from 'utils/isInternalUrl'; type Props = { titlePlaceholder?: string, bodyPlaceholder?: string, defaultValue?: string, - readOnly: boolean, + readOnly?: boolean, + expandToFit?: boolean, + history: *, + ui: *, }; class Editor extends React.Component { @@ -34,6 +38,42 @@ class Editor extends React.Component { if (this.editor) this.editor.focusAtEnd(); }; + onUploadImage = async (file: File) => { + const result = await uploadFile(file); + return result.url; + }; + + onClickLink = (href: string) => { + // on page hash + if (href[0] === '#') { + window.location.href = href; + return; + } + + if (isInternalUrl(href)) { + // relative + let navigateTo = href; + + // probably absolute + if (href[0] !== '/') { + try { + const url = new URL(href); + navigateTo = url.pathname + url.hash; + } catch (err) { + navigateTo = href; + } + } + + this.props.history.push(navigateTo); + } else { + window.open(href, '_blank'); + } + }; + + onShowToast = (message: string) => { + this.props.ui.showToast(message, 'success'); + }; + renderPlaceholder = (props: *) => { const { editor, node } = props; @@ -52,20 +92,24 @@ class Editor extends React.Component { }; render() { - const { readOnly } = this.props; + const { readOnly, expandToFit } = this.props; return ( - + {expandToFit && ( + + )} ); } diff --git a/app/components/InputRich.js b/app/components/InputRich.js index d2b08843c..5d7b6dcd6 100644 --- a/app/components/InputRich.js +++ b/app/components/InputRich.js @@ -1,29 +1,46 @@ // @flow import * as React from 'react'; +import { observable } from 'mobx'; +import { observer, inject } from 'mobx-react'; +import { withRouter } from 'react-router-dom'; import styled from 'styled-components'; -import RichMarkdownEditor from 'rich-markdown-editor'; import { LabelText, Outline } from 'components/Input'; type Props = { label: string, minHeight?: number, maxHeight?: number, + readOnly?: boolean, + history: *, + ui: *, }; -export default function InputRich({ - label, - minHeight, - maxHeight, - ...rest -}: Props) { - return ( - - {label} - - - - - ); +@observer +class InputRich extends React.Component { + @observable editorComponent; + + componentDidMount() { + this.loadEditor(); + } + + loadEditor = async () => { + const EditorImport = await import('./Editor'); + this.editorComponent = EditorImport.default; + }; + + render() { + const { label, minHeight, maxHeight, ...rest } = this.props; + const Editor = this.editorComponent; + + return ( + + {label} + + {Editor && } + + + ); + } } const StyledOutline = styled(Outline)` @@ -36,3 +53,5 @@ const StyledOutline = styled(Outline)` display: block; } `; + +export default inject('ui')(withRouter(InputRich)); diff --git a/app/scenes/CollectionEdit.js b/app/scenes/CollectionEdit.js index c68720982..cf1d4d87f 100644 --- a/app/scenes/CollectionEdit.js +++ b/app/scenes/CollectionEdit.js @@ -65,7 +65,7 @@ class CollectionEdit extends React.Component { You can edit a collection’s details at any time, however doing so - might confuse your team mates. + often might confuse your team mates. { }; loadEditor = async () => { - const EditorImport = await import('./components/Editor'); + const EditorImport = await import('components/Editor'); this.editorComponent = EditorImport.default; }; @@ -259,11 +258,6 @@ class DocumentScene extends React.Component { this.props.history.push(url); }; - onUploadImage = async (file: File) => { - const result = await uploadFile(file); - return result.url; - }; - onSearchLink = async (term: string) => { const results = await this.props.documents.search(term); @@ -273,37 +267,6 @@ class DocumentScene extends React.Component { })); }; - onClickLink = (href: string) => { - // on page hash - if (href[0] === '#') { - window.location.href = href; - return; - } - - if (isInternalUrl(href)) { - // relative - let navigateTo = href; - - // probably absolute - if (href[0] !== '/') { - try { - const url = new URL(href); - navigateTo = url.pathname + url.hash; - } catch (err) { - navigateTo = href; - } - } - - this.props.history.push(navigateTo); - } else { - window.open(href, '_blank'); - } - }; - - onShowToast = (message: string) => { - this.props.ui.showToast(message, 'success'); - }; - render() { const { location, match } = this.props; const Editor = this.editorComponent; @@ -386,17 +349,18 @@ class DocumentScene extends React.Component { bodyPlaceholder="…the rest is your canvas" defaultValue={revision ? revision.text : document.text} pretitle={document.emoji} - uploadImage={this.onUploadImage} onImageUploadStart={this.onImageUploadStart} onImageUploadStop={this.onImageUploadStop} onSearchLink={this.onSearchLink} - onClickLink={this.onClickLink} onChange={this.onChange} onSave={this.onSave} onCancel={this.onDiscard} - onShowToast={this.onShowToast} readOnly={!this.isEditing} toc={!revision} + history={this.props.history} + ui={this.props.ui} + schema={schema} + expandToFit /> diff --git a/server/models/Team.js b/server/models/Team.js index fdecf2f3c..d4e1868c4 100644 --- a/server/models/Team.js +++ b/server/models/Team.js @@ -109,7 +109,7 @@ Team.prototype.provisionSubdomain = async function(subdomain) { Team.prototype.provisionFirstCollection = async function(userId) { return await Collection.create({ name: 'General', - description: 'Your first Collection', + description: '', type: 'atlas', teamId: this.id, creatorId: userId, From cd1956b971592e904f652ab6f7e1ec4527120483 Mon Sep 17 00:00:00 2001 From: Tom Moor Date: Sun, 18 Nov 2018 18:28:22 -0800 Subject: [PATCH 3/6] Split editor --- app/components/Editor.js | 88 ++--------------------- app/scenes/Document/Document.js | 3 +- app/scenes/Document/components/Editor.js | 91 ++++++++++++++++++++++++ 3 files changed, 99 insertions(+), 83 deletions(-) create mode 100644 app/scenes/Document/components/Editor.js diff --git a/app/components/Editor.js b/app/components/Editor.js index 26b2002aa..adf0e72b3 100644 --- a/app/components/Editor.js +++ b/app/components/Editor.js @@ -1,9 +1,6 @@ // @flow import * as React from 'react'; -import styled from 'styled-components'; -import { Text } from 'slate'; -import RichMarkdownEditor, { Placeholder } from 'rich-markdown-editor'; -import ClickablePadding from 'components/ClickablePadding'; +import RichMarkdownEditor from 'rich-markdown-editor'; import { uploadFile } from 'utils/uploadFile'; import isInternalUrl from 'utils/isInternalUrl'; @@ -18,26 +15,6 @@ type Props = { }; class Editor extends React.Component { - editor: *; - - componentDidMount() { - if (!this.props.defaultValue) { - this.focusAtStart(); - } - } - - setEditorRef = (ref: RichMarkdownEditor) => { - this.editor = ref; - }; - - focusAtStart = () => { - if (this.editor) this.editor.focusAtStart(); - }; - - focusAtEnd = () => { - if (this.editor) this.editor.focusAtEnd(); - }; - onUploadImage = async (file: File) => { const result = await uploadFile(file); return result.url; @@ -74,67 +51,16 @@ class Editor extends React.Component { this.props.ui.showToast(message, 'success'); }; - renderPlaceholder = (props: *) => { - const { editor, node } = props; - - if (editor.state.isComposing) return; - if (node.object !== 'block') return; - if (!Text.isTextList(node.nodes)) return; - if (node.text !== '') return; - - const index = editor.value.document.getBlocks().indexOf(node); - if (index > 1) return; - - const text = - index === 0 ? this.props.titlePlaceholder : this.props.bodyPlaceholder; - - return {editor.props.readOnly ? '' : text}; - }; - render() { - const { readOnly, expandToFit } = this.props; - return ( - - - {expandToFit && ( - - )} - + ); } } -// additional styles account for placeholder nodes not always re-rendering -const StyledEditor = styled(RichMarkdownEditor)` - display: flex; - flex: 0; - - ${Placeholder} { - visibility: hidden; - } - - h1:first-of-type { - ${Placeholder} { - visibility: visible; - } - } - - p:nth-child(2):last-child { - ${Placeholder} { - visibility: visible; - } - } -`; - export default Editor; diff --git a/app/scenes/Document/Document.js b/app/scenes/Document/Document.js index 786b46580..46bffb4fb 100644 --- a/app/scenes/Document/Document.js +++ b/app/scenes/Document/Document.js @@ -172,7 +172,7 @@ class DocumentScene extends React.Component { }; loadEditor = async () => { - const EditorImport = await import('components/Editor'); + const EditorImport = await import('./components/Editor'); this.editorComponent = EditorImport.default; }; @@ -360,7 +360,6 @@ class DocumentScene extends React.Component { history={this.props.history} ui={this.props.ui} schema={schema} - expandToFit /> diff --git a/app/scenes/Document/components/Editor.js b/app/scenes/Document/components/Editor.js new file mode 100644 index 000000000..c5cc85b24 --- /dev/null +++ b/app/scenes/Document/components/Editor.js @@ -0,0 +1,91 @@ +// @flow +import * as React from 'react'; +import styled from 'styled-components'; +import { Text } from 'slate'; +import { Placeholder } from 'rich-markdown-editor'; +import Editor from 'components/Editor'; +import ClickablePadding from 'components/ClickablePadding'; + +type Props = { + titlePlaceholder?: string, + bodyPlaceholder?: string, + defaultValue?: string, + readOnly?: boolean, +}; + +class DocumentEditor extends React.Component { + editor: *; + + componentDidMount() { + if (!this.props.defaultValue) { + this.focusAtStart(); + } + } + + focusAtStart = () => { + if (this.editor) this.editor.focusAtStart(); + }; + + focusAtEnd = () => { + if (this.editor) this.editor.focusAtEnd(); + }; + + renderPlaceholder = (props: *) => { + const { editor, node } = props; + + if (editor.state.isComposing) return; + if (node.object !== 'block') return; + if (!Text.isTextList(node.nodes)) return; + if (node.text !== '') return; + + const index = editor.value.document.getBlocks().indexOf(node); + if (index > 1) return; + + const text = + index === 0 ? this.props.titlePlaceholder : this.props.bodyPlaceholder; + + return {editor.props.readOnly ? '' : text}; + }; + + render() { + const { readOnly } = this.props; + + return ( + + (this.editor = ref)} + renderPlaceholder={this.renderPlaceholder} + {...this.props} + /> + + + ); + } +} + +// additional styles account for placeholder nodes not always re-rendering +const StyledEditor = styled(Editor)` + display: flex; + flex: 0; + + ${Placeholder} { + visibility: hidden; + } + + h1:first-of-type { + ${Placeholder} { + visibility: visible; + } + } + + p:nth-child(2):last-child { + ${Placeholder} { + visibility: visible; + } + } +`; + +export default DocumentEditor; From 032d843f5bf5d2b3bcfe3160a1115251d277661a Mon Sep 17 00:00:00 2001 From: Tom Moor Date: Sun, 18 Nov 2018 18:43:11 -0800 Subject: [PATCH 4/6] Fix isInternalUrl for subdomain support Refactor / reduce plumbing --- app/components/{Actions => }/Actions.js | 0 app/components/Actions/index.js | 4 ---- app/components/{Alert => }/Alert.js | 0 app/components/Alert/index.js | 3 --- app/components/{Button => }/Button.js | 0 app/components/Button/index.js | 3 --- .../{CenteredContent => }/CenteredContent.js | 0 app/components/CenteredContent/index.js | 3 --- .../{Collaborators => }/Collaborators.js | 0 app/components/Collaborators/index.js | 3 --- .../{ColorPicker => }/ColorPicker.js | 0 app/components/ColorPicker/index.js | 3 --- .../{CopyToClipboard => }/CopyToClipboard.js | 0 app/components/CopyToClipboard/index.js | 3 --- app/components/{Divider => }/Divider.js | 0 app/components/Divider/index.js | 3 --- .../{DropToImport => }/DropToImport.js | 0 app/components/DropToImport/index.js | 3 --- app/components/Editor.js | 1 - app/components/{Empty => }/Empty.js | 0 app/components/Empty/index.js | 3 --- app/components/{Fade => }/Fade.js | 0 app/components/Fade/index.js | 3 --- app/components/{HelpText => }/HelpText.js | 0 app/components/HelpText/index.js | 3 --- app/components/{Highlight => }/Highlight.js | 0 app/components/Highlight/index.js | 3 --- app/components/{Input => }/Input.js | 0 app/components/Input/index.js | 4 ---- app/components/{Key/key.js => Key.js} | 0 app/components/Key/index.js | 3 --- app/components/{Labeled => }/Labeled.js | 0 app/components/Labeled/index.js | 4 ---- app/components/{Layout => }/Layout.js | 0 app/components/Layout/index.js | 3 --- app/components/{Modal => }/Modal.js | 0 app/components/Modal/index.js | 3 --- app/components/{Modals => }/Modals.js | 0 app/components/Modals/index.js | 3 --- app/components/{PageTitle => }/PageTitle.js | 0 app/components/PageTitle/index.js | 3 --- app/components/{Popover => }/Popover.js | 0 app/components/Popover/index.js | 4 ---- .../RouteSidebarHidden.js | 0 app/components/RouteSidebarHidden/index.js | 3 --- app/components/{Scrollable => }/Scrollable.js | 0 app/components/Scrollable/index.js | 3 --- app/components/Subheading/Subheading.js | 15 --------------- app/components/Subheading/index.js | 3 --- .../{Tooltip/index.js => Tooltip.js} | 0 app/utils/isInternalUrl.js | 19 +++++++++++++------ 51 files changed, 13 insertions(+), 98 deletions(-) rename app/components/{Actions => }/Actions.js (100%) delete mode 100644 app/components/Actions/index.js rename app/components/{Alert => }/Alert.js (100%) delete mode 100644 app/components/Alert/index.js rename app/components/{Button => }/Button.js (100%) delete mode 100644 app/components/Button/index.js rename app/components/{CenteredContent => }/CenteredContent.js (100%) delete mode 100644 app/components/CenteredContent/index.js rename app/components/{Collaborators => }/Collaborators.js (100%) delete mode 100644 app/components/Collaborators/index.js rename app/components/{ColorPicker => }/ColorPicker.js (100%) delete mode 100644 app/components/ColorPicker/index.js rename app/components/{CopyToClipboard => }/CopyToClipboard.js (100%) delete mode 100644 app/components/CopyToClipboard/index.js rename app/components/{Divider => }/Divider.js (100%) delete mode 100644 app/components/Divider/index.js rename app/components/{DropToImport => }/DropToImport.js (100%) delete mode 100644 app/components/DropToImport/index.js rename app/components/{Empty => }/Empty.js (100%) delete mode 100644 app/components/Empty/index.js rename app/components/{Fade => }/Fade.js (100%) delete mode 100644 app/components/Fade/index.js rename app/components/{HelpText => }/HelpText.js (100%) delete mode 100644 app/components/HelpText/index.js rename app/components/{Highlight => }/Highlight.js (100%) delete mode 100644 app/components/Highlight/index.js rename app/components/{Input => }/Input.js (100%) delete mode 100644 app/components/Input/index.js rename app/components/{Key/key.js => Key.js} (100%) delete mode 100644 app/components/Key/index.js rename app/components/{Labeled => }/Labeled.js (100%) delete mode 100644 app/components/Labeled/index.js rename app/components/{Layout => }/Layout.js (100%) delete mode 100644 app/components/Layout/index.js rename app/components/{Modal => }/Modal.js (100%) delete mode 100644 app/components/Modal/index.js rename app/components/{Modals => }/Modals.js (100%) delete mode 100644 app/components/Modals/index.js rename app/components/{PageTitle => }/PageTitle.js (100%) delete mode 100644 app/components/PageTitle/index.js rename app/components/{Popover => }/Popover.js (100%) delete mode 100644 app/components/Popover/index.js rename app/components/{RouteSidebarHidden => }/RouteSidebarHidden.js (100%) delete mode 100644 app/components/RouteSidebarHidden/index.js rename app/components/{Scrollable => }/Scrollable.js (100%) delete mode 100644 app/components/Scrollable/index.js delete mode 100644 app/components/Subheading/Subheading.js delete mode 100644 app/components/Subheading/index.js rename app/components/{Tooltip/index.js => Tooltip.js} (100%) diff --git a/app/components/Actions/Actions.js b/app/components/Actions.js similarity index 100% rename from app/components/Actions/Actions.js rename to app/components/Actions.js diff --git a/app/components/Actions/index.js b/app/components/Actions/index.js deleted file mode 100644 index 71c56fa85..000000000 --- a/app/components/Actions/index.js +++ /dev/null @@ -1,4 +0,0 @@ -// @flow -import Actions from './Actions'; -export { Action, Separator } from './Actions'; -export default Actions; diff --git a/app/components/Alert/Alert.js b/app/components/Alert.js similarity index 100% rename from app/components/Alert/Alert.js rename to app/components/Alert.js diff --git a/app/components/Alert/index.js b/app/components/Alert/index.js deleted file mode 100644 index 7c95883ce..000000000 --- a/app/components/Alert/index.js +++ /dev/null @@ -1,3 +0,0 @@ -// @flow -import Alert from './Alert'; -export default Alert; diff --git a/app/components/Button/Button.js b/app/components/Button.js similarity index 100% rename from app/components/Button/Button.js rename to app/components/Button.js diff --git a/app/components/Button/index.js b/app/components/Button/index.js deleted file mode 100644 index 70118ffe8..000000000 --- a/app/components/Button/index.js +++ /dev/null @@ -1,3 +0,0 @@ -// @flow -import Button from './Button'; -export default Button; diff --git a/app/components/CenteredContent/CenteredContent.js b/app/components/CenteredContent.js similarity index 100% rename from app/components/CenteredContent/CenteredContent.js rename to app/components/CenteredContent.js diff --git a/app/components/CenteredContent/index.js b/app/components/CenteredContent/index.js deleted file mode 100644 index a9c4ec1db..000000000 --- a/app/components/CenteredContent/index.js +++ /dev/null @@ -1,3 +0,0 @@ -// @flow -import CenteredContent from './CenteredContent'; -export default CenteredContent; diff --git a/app/components/Collaborators/Collaborators.js b/app/components/Collaborators.js similarity index 100% rename from app/components/Collaborators/Collaborators.js rename to app/components/Collaborators.js diff --git a/app/components/Collaborators/index.js b/app/components/Collaborators/index.js deleted file mode 100644 index 68cac4de5..000000000 --- a/app/components/Collaborators/index.js +++ /dev/null @@ -1,3 +0,0 @@ -// @flow -import Collaborators from './Collaborators'; -export default Collaborators; diff --git a/app/components/ColorPicker/ColorPicker.js b/app/components/ColorPicker.js similarity index 100% rename from app/components/ColorPicker/ColorPicker.js rename to app/components/ColorPicker.js diff --git a/app/components/ColorPicker/index.js b/app/components/ColorPicker/index.js deleted file mode 100644 index 84f7ebb8d..000000000 --- a/app/components/ColorPicker/index.js +++ /dev/null @@ -1,3 +0,0 @@ -// @flow -import ColorPicker from './ColorPicker'; -export default ColorPicker; diff --git a/app/components/CopyToClipboard/CopyToClipboard.js b/app/components/CopyToClipboard.js similarity index 100% rename from app/components/CopyToClipboard/CopyToClipboard.js rename to app/components/CopyToClipboard.js diff --git a/app/components/CopyToClipboard/index.js b/app/components/CopyToClipboard/index.js deleted file mode 100644 index 4d0c0539a..000000000 --- a/app/components/CopyToClipboard/index.js +++ /dev/null @@ -1,3 +0,0 @@ -// @flow -import CopyToClipboard from './CopyToClipboard'; -export default CopyToClipboard; diff --git a/app/components/Divider/Divider.js b/app/components/Divider.js similarity index 100% rename from app/components/Divider/Divider.js rename to app/components/Divider.js diff --git a/app/components/Divider/index.js b/app/components/Divider/index.js deleted file mode 100644 index 6d4a0889a..000000000 --- a/app/components/Divider/index.js +++ /dev/null @@ -1,3 +0,0 @@ -// @flow -import Divider from './Divider'; -export default Divider; diff --git a/app/components/DropToImport/DropToImport.js b/app/components/DropToImport.js similarity index 100% rename from app/components/DropToImport/DropToImport.js rename to app/components/DropToImport.js diff --git a/app/components/DropToImport/index.js b/app/components/DropToImport/index.js deleted file mode 100644 index a95a2a44d..000000000 --- a/app/components/DropToImport/index.js +++ /dev/null @@ -1,3 +0,0 @@ -// @flow -import DropToImport from './DropToImport'; -export default DropToImport; diff --git a/app/components/Editor.js b/app/components/Editor.js index adf0e72b3..b26e27026 100644 --- a/app/components/Editor.js +++ b/app/components/Editor.js @@ -9,7 +9,6 @@ type Props = { bodyPlaceholder?: string, defaultValue?: string, readOnly?: boolean, - expandToFit?: boolean, history: *, ui: *, }; diff --git a/app/components/Empty/Empty.js b/app/components/Empty.js similarity index 100% rename from app/components/Empty/Empty.js rename to app/components/Empty.js diff --git a/app/components/Empty/index.js b/app/components/Empty/index.js deleted file mode 100644 index 5c3c3a071..000000000 --- a/app/components/Empty/index.js +++ /dev/null @@ -1,3 +0,0 @@ -// @flow -import Empty from './Empty'; -export default Empty; diff --git a/app/components/Fade/Fade.js b/app/components/Fade.js similarity index 100% rename from app/components/Fade/Fade.js rename to app/components/Fade.js diff --git a/app/components/Fade/index.js b/app/components/Fade/index.js deleted file mode 100644 index fd1199888..000000000 --- a/app/components/Fade/index.js +++ /dev/null @@ -1,3 +0,0 @@ -// @flow -import Fade from './Fade'; -export default Fade; diff --git a/app/components/HelpText/HelpText.js b/app/components/HelpText.js similarity index 100% rename from app/components/HelpText/HelpText.js rename to app/components/HelpText.js diff --git a/app/components/HelpText/index.js b/app/components/HelpText/index.js deleted file mode 100644 index 968c478b8..000000000 --- a/app/components/HelpText/index.js +++ /dev/null @@ -1,3 +0,0 @@ -// @flow -import HelpText from './HelpText'; -export default HelpText; diff --git a/app/components/Highlight/Highlight.js b/app/components/Highlight.js similarity index 100% rename from app/components/Highlight/Highlight.js rename to app/components/Highlight.js diff --git a/app/components/Highlight/index.js b/app/components/Highlight/index.js deleted file mode 100644 index 99f319532..000000000 --- a/app/components/Highlight/index.js +++ /dev/null @@ -1,3 +0,0 @@ -// @flow -import Highlight from './Highlight'; -export default Highlight; diff --git a/app/components/Input/Input.js b/app/components/Input.js similarity index 100% rename from app/components/Input/Input.js rename to app/components/Input.js diff --git a/app/components/Input/index.js b/app/components/Input/index.js deleted file mode 100644 index e9b21f08b..000000000 --- a/app/components/Input/index.js +++ /dev/null @@ -1,4 +0,0 @@ -// @flow -import Input, { LabelText, Outline } from './Input'; -export default Input; -export { LabelText, Outline }; diff --git a/app/components/Key/key.js b/app/components/Key.js similarity index 100% rename from app/components/Key/key.js rename to app/components/Key.js diff --git a/app/components/Key/index.js b/app/components/Key/index.js deleted file mode 100644 index efe24263a..000000000 --- a/app/components/Key/index.js +++ /dev/null @@ -1,3 +0,0 @@ -// @flow -import Key from './key'; -export default Key; diff --git a/app/components/Labeled/Labeled.js b/app/components/Labeled.js similarity index 100% rename from app/components/Labeled/Labeled.js rename to app/components/Labeled.js diff --git a/app/components/Labeled/index.js b/app/components/Labeled/index.js deleted file mode 100644 index c68dffece..000000000 --- a/app/components/Labeled/index.js +++ /dev/null @@ -1,4 +0,0 @@ -// @flow -import Labeled, { Label } from './Labeled'; -export default Labeled; -export { Label }; diff --git a/app/components/Layout/Layout.js b/app/components/Layout.js similarity index 100% rename from app/components/Layout/Layout.js rename to app/components/Layout.js diff --git a/app/components/Layout/index.js b/app/components/Layout/index.js deleted file mode 100644 index 62fb061d0..000000000 --- a/app/components/Layout/index.js +++ /dev/null @@ -1,3 +0,0 @@ -// @flow -import Layout from './Layout'; -export default Layout; diff --git a/app/components/Modal/Modal.js b/app/components/Modal.js similarity index 100% rename from app/components/Modal/Modal.js rename to app/components/Modal.js diff --git a/app/components/Modal/index.js b/app/components/Modal/index.js deleted file mode 100644 index 907593356..000000000 --- a/app/components/Modal/index.js +++ /dev/null @@ -1,3 +0,0 @@ -// @flow -import Modal from './Modal'; -export default Modal; diff --git a/app/components/Modals/Modals.js b/app/components/Modals.js similarity index 100% rename from app/components/Modals/Modals.js rename to app/components/Modals.js diff --git a/app/components/Modals/index.js b/app/components/Modals/index.js deleted file mode 100644 index df1b93027..000000000 --- a/app/components/Modals/index.js +++ /dev/null @@ -1,3 +0,0 @@ -// @flow -import Modals from './Modals'; -export default Modals; diff --git a/app/components/PageTitle/PageTitle.js b/app/components/PageTitle.js similarity index 100% rename from app/components/PageTitle/PageTitle.js rename to app/components/PageTitle.js diff --git a/app/components/PageTitle/index.js b/app/components/PageTitle/index.js deleted file mode 100644 index f9286c54d..000000000 --- a/app/components/PageTitle/index.js +++ /dev/null @@ -1,3 +0,0 @@ -// @flow -import PageTitle from './PageTitle'; -export default PageTitle; diff --git a/app/components/Popover/Popover.js b/app/components/Popover.js similarity index 100% rename from app/components/Popover/Popover.js rename to app/components/Popover.js diff --git a/app/components/Popover/index.js b/app/components/Popover/index.js deleted file mode 100644 index 7fee10fdb..000000000 --- a/app/components/Popover/index.js +++ /dev/null @@ -1,4 +0,0 @@ -// @flow -import Popover from './Popover'; -export { Preset } from './Popover'; -export default Popover; diff --git a/app/components/RouteSidebarHidden/RouteSidebarHidden.js b/app/components/RouteSidebarHidden.js similarity index 100% rename from app/components/RouteSidebarHidden/RouteSidebarHidden.js rename to app/components/RouteSidebarHidden.js diff --git a/app/components/RouteSidebarHidden/index.js b/app/components/RouteSidebarHidden/index.js deleted file mode 100644 index 0a92e652c..000000000 --- a/app/components/RouteSidebarHidden/index.js +++ /dev/null @@ -1,3 +0,0 @@ -// @flow -import RouteSidebarHidden from './RouteSidebarHidden'; -export default RouteSidebarHidden; diff --git a/app/components/Scrollable/Scrollable.js b/app/components/Scrollable.js similarity index 100% rename from app/components/Scrollable/Scrollable.js rename to app/components/Scrollable.js diff --git a/app/components/Scrollable/index.js b/app/components/Scrollable/index.js deleted file mode 100644 index 1b6d57523..000000000 --- a/app/components/Scrollable/index.js +++ /dev/null @@ -1,3 +0,0 @@ -// @flow -import Scrollable from './Scrollable'; -export default Scrollable; diff --git a/app/components/Subheading/Subheading.js b/app/components/Subheading/Subheading.js deleted file mode 100644 index fdc716489..000000000 --- a/app/components/Subheading/Subheading.js +++ /dev/null @@ -1,15 +0,0 @@ -// @flow -import styled from 'styled-components'; - -const Subheading = styled.h3` - font-size: 11px; - font-weight: 500; - text-transform: uppercase; - color: #9fa6ab; - letter-spacing: 0.04em; - border-bottom: 1px solid #ddd; - padding-bottom: 10px; - margin-top: 30px; -`; - -export default Subheading; diff --git a/app/components/Subheading/index.js b/app/components/Subheading/index.js deleted file mode 100644 index d0f6a76e7..000000000 --- a/app/components/Subheading/index.js +++ /dev/null @@ -1,3 +0,0 @@ -// @flow -import Subheading from './Subheading'; -export default Subheading; diff --git a/app/components/Tooltip/index.js b/app/components/Tooltip.js similarity index 100% rename from app/components/Tooltip/index.js rename to app/components/Tooltip.js diff --git a/app/utils/isInternalUrl.js b/app/utils/isInternalUrl.js index 4f1924235..48e36e338 100644 --- a/app/utils/isInternalUrl.js +++ b/app/utils/isInternalUrl.js @@ -1,12 +1,19 @@ // @flow +import parseDomain from 'parse-domain'; + export default function isInternalUrl(href: string) { if (href[0] === '/') return true; - try { - const outline = new URL(BASE_URL); - const parsed = new URL(href); - return parsed.hostname === outline.hostname; - } catch (err) { - return false; + const outline = parseDomain(BASE_URL); + const parsed = parseDomain(href); + if ( + parsed && + outline && + parsed.domain === outline.domain && + parsed.tld === outline.tld + ) { + return true; } + + return false; } From 8208a6128ad677c1270a522c7d66435523ff592b Mon Sep 17 00:00:00 2001 From: Tom Moor Date: Sun, 18 Nov 2018 18:59:09 -0800 Subject: [PATCH 5/6] Upgrade RME - z-index fix --- package.json | 2 +- yarn.lock | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 1c204b7f0..a7973fce6 100644 --- a/package.json +++ b/package.json @@ -161,7 +161,7 @@ "react-waypoint": "^7.3.1", "redis": "^2.6.2", "redis-lock": "^0.1.0", - "rich-markdown-editor": "^6.0.2", + "rich-markdown-editor": "^6.0.3", "safestart": "1.1.0", "sequelize": "4.28.6", "sequelize-cli": "^2.7.0", diff --git a/yarn.lock b/yarn.lock index b68908d73..555611b9e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8985,9 +8985,9 @@ retry-axios@0.3.2, retry-axios@^0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/retry-axios/-/retry-axios-0.3.2.tgz#5757c80f585b4cc4c4986aa2ffd47a60c6d35e13" -rich-markdown-editor@^6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/rich-markdown-editor/-/rich-markdown-editor-6.0.2.tgz#580a86eba738a258e16bcbfef383adca781bbdba" +rich-markdown-editor@^6.0.3: + version "6.0.3" + resolved "https://registry.yarnpkg.com/rich-markdown-editor/-/rich-markdown-editor-6.0.3.tgz#8000cc6c97c376845471bfb4e7897fab38afab9c" dependencies: "@tommoor/slate-drop-or-paste-images" "^0.8.1" babel-plugin-transform-async-to-generator "^6.24.1" From 45445606b4ba1c67e59afd497c255af36243d011 Mon Sep 17 00:00:00 2001 From: Tom Moor Date: Sun, 18 Nov 2018 21:27:50 -0800 Subject: [PATCH 6/6] Improve loading state --- app/components/Input.js | 2 ++ app/components/InputRich.js | 17 +++++++++++++---- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/app/components/Input.js b/app/components/Input.js index d4d06fbc1..a414c7c75 100644 --- a/app/components/Input.js +++ b/app/components/Input.js @@ -31,6 +31,8 @@ const RealInput = styled.input` const Wrapper = styled.div` max-width: ${props => (props.short ? '350px' : '100%')}; + min-height: ${({ minHeight }) => (minHeight ? `${minHeight}px` : '0')}; + max-height: ${({ maxHeight }) => (maxHeight ? `${maxHeight}px` : 'auto')}; `; export const Outline = styled(Flex)` diff --git a/app/components/InputRich.js b/app/components/InputRich.js index 5d7b6dcd6..244199795 100644 --- a/app/components/InputRich.js +++ b/app/components/InputRich.js @@ -4,7 +4,7 @@ import { observable } from 'mobx'; import { observer, inject } from 'mobx-react'; import { withRouter } from 'react-router-dom'; import styled from 'styled-components'; -import { LabelText, Outline } from 'components/Input'; +import Input, { LabelText, Outline } from 'components/Input'; type Props = { label: string, @@ -35,9 +35,18 @@ class InputRich extends React.Component { return ( {label} - - {Editor && } - + {Editor ? ( + + + + ) : ( + + )} ); }