diff --git a/app/components/DropToImport.js b/app/components/DropToImport.js index d5dcf5503..2d6693466 100644 --- a/app/components/DropToImport.js +++ b/app/components/DropToImport.js @@ -2,8 +2,8 @@ import * as React from 'react'; import { observable } from 'mobx'; import { observer, inject } from 'mobx-react'; +import { Redirect } from 'react-router-dom'; import { createGlobalStyle } from 'styled-components'; -import { omit } from 'lodash'; import invariant from 'invariant'; import importFile from 'utils/importFile'; import Dropzone from 'react-dropzone'; @@ -18,11 +18,11 @@ type Props = { rejectClassName?: string, documents: DocumentsStore, disabled: boolean, - history: Object, }; -const GlobalStyles = createGlobalStyle` +export const GlobalStyles = createGlobalStyle` .activeDropZone { + border-radius: 4px; background: ${props => props.theme.slateDark}; svg { fill: ${props => props.theme.white}; } } @@ -35,6 +35,7 @@ const GlobalStyles = createGlobalStyle` @observer class DropToImport extends React.Component { @observable isImporting: boolean = false; + @observable redirectTo: ?string; onDropAccepted = async (files = []) => { this.isImporting = true; @@ -59,7 +60,7 @@ class DropToImport extends React.Component { }); if (redirect) { - this.props.history.push(doc.url); + this.redirectTo = doc.url; } } } finally { @@ -68,16 +69,15 @@ class DropToImport extends React.Component { }; render() { - const props = omit( - this.props, - 'history', - 'documentId', - 'collectionId', - 'documents', - 'disabled', - 'menuOpen' - ); + const { + documentId, + collectionId, + documents, + disabled, + ...rest + } = this.props; + if (this.redirectTo) return ; if (this.props.disabled) return this.props.children; return ( @@ -88,9 +88,8 @@ class DropToImport extends React.Component { disableClick disablePreview multiple - {...props} + {...rest} > - {this.isImporting && } {this.props.children} diff --git a/app/components/Editor/Editor.js b/app/components/Editor/Editor.js index d21f3934e..2abba0e1e 100644 --- a/app/components/Editor/Editor.js +++ b/app/components/Editor/Editor.js @@ -1,5 +1,8 @@ // @flow import * as React from 'react'; +import { Redirect } from 'react-router-dom'; +import { observable } from 'mobx'; +import { observer } from 'mobx-react'; import RichMarkdownEditor from 'rich-markdown-editor'; import { uploadFile } from 'utils/uploadFile'; import isInternalUrl from 'utils/isInternalUrl'; @@ -11,11 +14,13 @@ type Props = { readOnly?: boolean, disableEmbeds?: boolean, forwardedRef: *, - history: *, ui: *, }; +@observer class Editor extends React.Component { + @observable redirectTo: ?string; + onUploadImage = async (file: File) => { const result = await uploadFile(file); return result.url; @@ -42,7 +47,7 @@ class Editor extends React.Component { } } - this.props.history.push(navigateTo); + this.redirectTo = navigateTo; } else { window.open(href, '_blank'); } @@ -69,6 +74,8 @@ class Editor extends React.Component { }; render() { + if (this.redirectTo) return ; + return ( { - @observable editorComponent; + @observable editorComponent: *; componentDidMount() { this.loadEditor(); @@ -63,4 +60,4 @@ const StyledOutline = styled(Outline)` } `; -export default inject('ui')(withRouter(InputRich)); +export default InputRich; diff --git a/app/components/Layout.js b/app/components/Layout.js index d8f223de5..afd724417 100644 --- a/app/components/Layout.js +++ b/app/components/Layout.js @@ -1,10 +1,10 @@ // @flow import * as React from 'react'; -import { Switch, Route, withRouter } from 'react-router-dom'; -import type { Location } from 'react-router-dom'; +import { Switch, Route, Redirect } from 'react-router-dom'; import { Helmet } from 'react-helmet'; import styled from 'styled-components'; import breakpoint from 'styled-components-breakpoint'; +import { observable } from 'mobx'; import { observer, inject } from 'mobx-react'; import keydown from 'react-keydown'; import Analytics from 'components/Analytics'; @@ -12,18 +12,16 @@ import Flex from 'shared/components/Flex'; import { documentEditUrl, homeUrl, searchUrl } from 'utils/routeHelpers'; import { LoadingIndicatorBar } from 'components/LoadingIndicator'; +import { GlobalStyles } from 'components/DropToImport'; import Sidebar from 'components/Sidebar'; import SettingsSidebar from 'components/Sidebar/Settings'; import Modals from 'components/Modals'; import ErrorSuspended from 'scenes/ErrorSuspended'; - import AuthStore from 'stores/AuthStore'; import UiStore from 'stores/UiStore'; import DocumentsStore from 'stores/DocumentsStore'; type Props = { - history: Object, - location: Location, documents: DocumentsStore, children?: ?React.Node, actions?: ?React.Node, @@ -36,17 +34,24 @@ type Props = { @observer class Layout extends React.Component { scrollable: ?HTMLDivElement; + @observable redirectTo: ?string; + + componentDidUpdate() { + if (this.redirectTo) { + this.redirectTo = undefined; + } + } @keydown(['/', 't', 'meta+k']) goToSearch(ev) { ev.preventDefault(); ev.stopPropagation(); - this.props.history.push(searchUrl()); + this.redirectTo = searchUrl(); } @keydown('d') goToDashboard() { - this.props.history.push(homeUrl()); + this.redirectTo = homeUrl(); } @keydown('e') @@ -56,7 +61,7 @@ class Layout extends React.Component { ev.preventDefault(); ev.stopPropagation(); - this.props.history.push(documentEditUrl(activeDocument)); + this.redirectTo = documentEditUrl(activeDocument); } @keydown('shift+/') @@ -70,6 +75,7 @@ class Layout extends React.Component { const showSidebar = auth.authenticated && user && team; if (auth.isSuspended) return ; + if (this.redirectTo) return ; return ( @@ -98,6 +104,7 @@ class Layout extends React.Component { + ); } @@ -122,4 +129,4 @@ const Content = styled(Flex)` `}; `; -export default withRouter(inject('auth', 'ui', 'documents')(Layout)); +export default inject('auth', 'ui', 'documents')(Layout); diff --git a/app/components/ScrollToAnchor.js b/app/components/ScrollToAnchor.js deleted file mode 100644 index 349ab8762..000000000 --- a/app/components/ScrollToAnchor.js +++ /dev/null @@ -1,23 +0,0 @@ -// @flow -import * as React from 'react'; -import { withRouter } from 'react-router-dom'; - -class ScrollToAnchor extends React.Component<*> { - componentDidUpdate(prevProps) { - if (this.props.location.hash === prevProps.location.hash) return; - if (window.location.hash === '') return; - - // Delay on timeout to ensure that the DOM is updated first - setImmediate(() => { - const id = window.location.hash.replace('#', ''); - const element = document.getElementById(id); - if (element) element.scrollIntoView(); - }); - } - - render() { - return this.props.children; - } -} - -export default withRouter(ScrollToAnchor); diff --git a/app/components/Sidebar/Main.js b/app/components/Sidebar/Main.js index ad72711e8..4ec967dcf 100644 --- a/app/components/Sidebar/Main.js +++ b/app/components/Sidebar/Main.js @@ -1,7 +1,5 @@ // @flow import * as React from 'react'; -import { withRouter } from 'react-router-dom'; -import type { Location } from 'react-router-dom'; import { observer, inject } from 'mobx-react'; import { HomeIcon, EditIcon, SearchIcon, StarredIcon } from 'outline-icons'; @@ -20,8 +18,6 @@ import DocumentsStore from 'stores/DocumentsStore'; import UiStore from 'stores/UiStore'; type Props = { - history: Object, - location: Location, auth: AuthStore, documents: DocumentsStore, ui: UiStore, @@ -93,11 +89,7 @@ class MainSidebar extends React.Component { />
- +
@@ -106,4 +98,4 @@ class MainSidebar extends React.Component { } } -export default withRouter(inject('documents', 'auth', 'ui')(MainSidebar)); +export default inject('documents', 'auth', 'ui')(MainSidebar); diff --git a/app/components/Sidebar/Sidebar.js b/app/components/Sidebar/Sidebar.js index 5668ccbbf..f20a07cc3 100644 --- a/app/components/Sidebar/Sidebar.js +++ b/app/components/Sidebar/Sidebar.js @@ -12,7 +12,6 @@ import UiStore from 'stores/UiStore'; type Props = { children: React.Node, - history: Object, location: Location, ui: UiStore, }; diff --git a/app/components/Sidebar/components/CollectionLink.js b/app/components/Sidebar/components/CollectionLink.js index 48b056da9..560e1d828 100644 --- a/app/components/Sidebar/components/CollectionLink.js +++ b/app/components/Sidebar/components/CollectionLink.js @@ -13,7 +13,6 @@ import DropToImport from 'components/DropToImport'; import Flex from 'shared/components/Flex'; type Props = { - history: Object, collection: Collection, ui: UiStore, activeDocument: ?Document, @@ -25,19 +24,12 @@ class CollectionLink extends React.Component { @observable menuOpen = false; render() { - const { - history, - collection, - activeDocument, - prefetchDocument, - ui, - } = this.props; + const { collection, activeDocument, prefetchDocument, ui } = this.props; const expanded = collection.id === ui.activeCollectionId; return ( @@ -62,7 +54,6 @@ class CollectionLink extends React.Component { exact={false} menu={ (this.menuOpen = true)} onClose={() => (this.menuOpen = false)} @@ -73,7 +64,6 @@ class CollectionLink extends React.Component { {collection.documents.map(document => ( { } } -export default inject('collections', 'ui', 'documents')(Collections); +export default inject('collections', 'ui', 'documents')( + withRouter(Collections) +); diff --git a/app/components/Sidebar/components/DocumentLink.js b/app/components/Sidebar/components/DocumentLink.js index 77c20be28..7ae36caf3 100644 --- a/app/components/Sidebar/components/DocumentLink.js +++ b/app/components/Sidebar/components/DocumentLink.js @@ -10,7 +10,6 @@ import { type NavigationNode } from 'types'; type Props = { document: NavigationNode, - history: Object, activeDocument: ?Document, activeDocumentRef?: (?HTMLElement) => *, prefetchDocument: (documentId: string) => Promise, @@ -34,7 +33,6 @@ class DocumentLink extends React.Component { activeDocumentRef, prefetchDocument, depth, - history, } = this.props; const isActiveDocument = @@ -55,11 +53,7 @@ class DocumentLink extends React.Component { ref={isActiveDocument ? activeDocumentRef : undefined} onMouseEnter={this.handleMouseEnter} > - + { {document.children.map(childDocument => ( { }; render() { - const { team } = this.props; + const { team, disabled } = this.props; + if (disabled) return null; return ( diff --git a/app/index.js b/app/index.js index b4336801b..10479c416 100644 --- a/app/index.js +++ b/app/index.js @@ -12,7 +12,6 @@ import 'shared/styles/prism.css'; import ErrorBoundary from 'components/ErrorBoundary'; import ScrollToTop from 'components/ScrollToTop'; -import ScrollToAnchor from 'components/ScrollToAnchor'; import Toasts from 'components/Toasts'; import Routes from './routes'; @@ -33,9 +32,7 @@ if (element) { - - - + diff --git a/app/menus/AccountMenu.js b/app/menus/AccountMenu.js index 464f292ea..ad3cda0b7 100644 --- a/app/menus/AccountMenu.js +++ b/app/menus/AccountMenu.js @@ -1,6 +1,7 @@ // @flow import * as React from 'react'; -import { withRouter } from 'react-router-dom'; +import { Redirect } from 'react-router-dom'; +import { observable } from 'mobx'; import { inject, observer } from 'mobx-react'; import UiStore from 'stores/UiStore'; import AuthStore from 'stores/AuthStore'; @@ -15,19 +16,24 @@ import { type Props = { label: React.Node, - history: Object, ui: UiStore, auth: AuthStore, }; @observer class AccountMenu extends React.Component { + @observable redirectTo: ?string; + + componentDidUpdate() { + this.redirectTo = undefined; + } + handleOpenKeyboardShortcuts = () => { this.props.ui.setActiveModal('keyboard-shortcuts'); }; handleOpenSettings = () => { - this.props.history.push('/settings'); + this.redirectTo = '/settings'; }; handleLogout = () => { @@ -35,6 +41,8 @@ class AccountMenu extends React.Component { }; render() { + if (this.redirectTo) return ; + return ( { } } -export default withRouter(inject('ui', 'auth')(AccountMenu)); +export default inject('ui', 'auth')(AccountMenu); diff --git a/app/menus/CollectionMenu.js b/app/menus/CollectionMenu.js index bf6bf1ecf..86d8e7a5c 100644 --- a/app/menus/CollectionMenu.js +++ b/app/menus/CollectionMenu.js @@ -2,6 +2,7 @@ import * as React from 'react'; import { observable } from 'mobx'; import { inject, observer } from 'mobx-react'; +import { Redirect } from 'react-router-dom'; import styled from 'styled-components'; import { MoreIcon } from 'outline-icons'; import Modal from 'components/Modal'; @@ -18,7 +19,6 @@ type Props = { label?: React.Node, onOpen?: () => *, onClose?: () => *, - history: Object, ui: UiStore, documents: DocumentsStore, collection: Collection, @@ -28,11 +28,16 @@ type Props = { class CollectionMenu extends React.Component { file: ?HTMLInputElement; @observable permissionsModalOpen: boolean = false; + @observable redirectTo: ?string; + + componentDidUpdate() { + this.redirectTo = undefined; + } onNewDocument = (ev: SyntheticEvent<*>) => { ev.preventDefault(); - const { collection, history } = this.props; - history.push(`${collection.url}/new`); + const { collection } = this.props; + this.redirectTo = `${collection.url}/new`; }; onImportDocument = (ev: SyntheticEvent<*>) => { @@ -51,7 +56,7 @@ class CollectionMenu extends React.Component { documents: this.props.documents, collectionId: this.props.collection.id, }); - this.props.history.push(document.url); + this.redirectTo = document.url; } catch (err) { this.props.ui.showToast(err.message); } @@ -85,6 +90,8 @@ class CollectionMenu extends React.Component { }; render() { + if (this.redirectTo) return ; + const { collection, label, onOpen, onClose } = this.props; return ( diff --git a/app/menus/DocumentMenu.js b/app/menus/DocumentMenu.js index 5f12ff506..ea66b0206 100644 --- a/app/menus/DocumentMenu.js +++ b/app/menus/DocumentMenu.js @@ -1,6 +1,7 @@ // @flow import * as React from 'react'; -import { withRouter } from 'react-router-dom'; +import { Redirect } from 'react-router-dom'; +import { observable } from 'mobx'; import { inject, observer } from 'mobx-react'; import { MoreIcon } from 'outline-icons'; @@ -14,7 +15,6 @@ type Props = { ui: UiStore, auth: AuthStore, label?: React.Node, - history: Object, document: Document, className: string, showPrint?: boolean, @@ -23,11 +23,17 @@ type Props = { @observer class DocumentMenu extends React.Component { + @observable redirectTo: ?string; + + componentDidUpdate() { + this.redirectTo = undefined; + } + handleNewChild = (ev: SyntheticEvent<*>) => { - const { history, document } = this.props; - history.push( - `${document.collection.url}/new?parentDocument=${document.id}` - ); + const { document } = this.props; + this.redirectTo = `${document.collection.url}/new?parentDocument=${ + document.id + }`; }; handleDelete = (ev: SyntheticEvent<*>) => { @@ -36,16 +42,16 @@ class DocumentMenu extends React.Component { }; handleDocumentHistory = () => { - this.props.history.push(documentHistoryUrl(this.props.document)); + this.redirectTo = documentHistoryUrl(this.props.document); }; handleMove = (ev: SyntheticEvent<*>) => { - this.props.history.push(documentMoveUrl(this.props.document)); + this.redirectTo = documentMoveUrl(this.props.document); }; handleDuplicate = async (ev: SyntheticEvent<*>) => { const duped = await this.props.document.duplicate(); - this.props.history.push(duped.url); + this.redirectTo = duped.url; }; handlePin = (ev: SyntheticEvent<*>) => { @@ -76,6 +82,8 @@ class DocumentMenu extends React.Component { }; render() { + if (this.redirectTo) return ; + const { document, label, className, showPrint, auth } = this.props; const canShareDocuments = auth.team && auth.team.sharing; @@ -136,4 +144,4 @@ class DocumentMenu extends React.Component { } } -export default withRouter(inject('ui', 'auth')(DocumentMenu)); +export default inject('ui', 'auth')(DocumentMenu); diff --git a/app/menus/NewChildDocumentMenu.js b/app/menus/NewChildDocumentMenu.js index 1a98c1152..f7ca9e1fb 100644 --- a/app/menus/NewChildDocumentMenu.js +++ b/app/menus/NewChildDocumentMenu.js @@ -1,6 +1,8 @@ // @flow import * as React from 'react'; -import { withRouter } from 'react-router-dom'; +import { Redirect } from 'react-router-dom'; +import { observable } from 'mobx'; +import { observer } from 'mobx-react'; import { MoreIcon } from 'outline-icons'; import { newDocumentUrl } from 'utils/routeHelpers'; @@ -9,25 +11,32 @@ import { DropdownMenu, DropdownMenuItem } from 'components/DropdownMenu'; type Props = { label?: React.Node, - history: Object, document: Document, }; +@observer class NewChildDocumentMenu extends React.Component { + @observable redirectTo: ?string; + + componentDidUpdate() { + this.redirectTo = undefined; + } + handleNewDocument = () => { - const { history, document } = this.props; - history.push(newDocumentUrl(document.collection)); + this.redirectTo = newDocumentUrl(this.props.document.collection); }; handleNewChild = () => { - const { history, document } = this.props; - history.push( - `${document.collection.url}/new?parentDocument=${document.id}` - ); + const { document } = this.props; + this.redirectTo = `${document.collection.url}/new?parentDocument=${ + document.id + }`; }; render() { - const { label, document, history, ...rest } = this.props; + if (this.redirectTo) return ; + + const { label, document, ...rest } = this.props; const { collection } = document; return ( @@ -45,4 +54,4 @@ class NewChildDocumentMenu extends React.Component { } } -export default withRouter(NewChildDocumentMenu); +export default NewChildDocumentMenu; diff --git a/app/menus/NewDocumentMenu.js b/app/menus/NewDocumentMenu.js index 5d5a64c23..d39a3e50b 100644 --- a/app/menus/NewDocumentMenu.js +++ b/app/menus/NewDocumentMenu.js @@ -1,7 +1,8 @@ // @flow import * as React from 'react'; -import { withRouter } from 'react-router-dom'; -import { inject } from 'mobx-react'; +import { observable } from 'mobx'; +import { inject, observer } from 'mobx-react'; +import { Redirect } from 'react-router-dom'; import { MoreIcon, CollectionIcon, PrivateCollectionIcon } from 'outline-icons'; import { newDocumentUrl } from 'utils/routeHelpers'; @@ -10,13 +11,19 @@ import { DropdownMenu, DropdownMenuItem } from 'components/DropdownMenu'; type Props = { label?: React.Node, - history: Object, collections: CollectionsStore, }; +@observer class NewDocumentMenu extends React.Component { + @observable redirectTo: ?string; + + componentDidUpdate() { + this.redirectTo = undefined; + } + handleNewDocument = collection => { - this.props.history.push(newDocumentUrl(collection)); + this.redirectTo = newDocumentUrl(collection); }; onOpen = () => { @@ -28,7 +35,9 @@ class NewDocumentMenu extends React.Component { }; render() { - const { collections, label, history, ...rest } = this.props; + if (this.redirectTo) return ; + + const { collections, label, ...rest } = this.props; return ( { } } -export default withRouter(inject('collections')(NewDocumentMenu)); +export default inject('collections')(NewDocumentMenu); diff --git a/app/menus/ShareMenu.js b/app/menus/ShareMenu.js index d2c147d13..fb78e7614 100644 --- a/app/menus/ShareMenu.js +++ b/app/menus/ShareMenu.js @@ -1,12 +1,12 @@ // @flow import * as React from 'react'; -import { withRouter } from 'react-router-dom'; -import { inject } from 'mobx-react'; +import { Redirect } from 'react-router-dom'; +import { inject, observer } from 'mobx-react'; +import { observable } from 'mobx'; import { MoreIcon } from 'outline-icons'; import CopyToClipboard from 'components/CopyToClipboard'; import { DropdownMenu, DropdownMenuItem } from 'components/DropdownMenu'; - import SharesStore from 'stores/SharesStore'; import UiStore from 'stores/UiStore'; import Share from 'models/Share'; @@ -15,16 +15,22 @@ type Props = { label?: React.Node, onOpen?: () => *, onClose: () => *, - history: Object, shares: SharesStore, ui: UiStore, share: Share, }; +@observer class ShareMenu extends React.Component { + @observable redirectTo: ?string; + + componentDidUpdate() { + this.redirectTo = undefined; + } + handleGoToDocument = (ev: SyntheticEvent<*>) => { ev.preventDefault(); - this.props.history.push(this.props.share.documentUrl); + this.redirectTo = this.props.share.documentUrl; }; handleRevoke = (ev: SyntheticEvent<*>) => { @@ -38,6 +44,8 @@ class ShareMenu extends React.Component { }; render() { + if (this.redirectTo) return ; + const { share, label, onOpen, onClose } = this.props; return ( @@ -61,4 +69,4 @@ class ShareMenu extends React.Component { } } -export default withRouter(inject('shares', 'ui')(ShareMenu)); +export default inject('shares', 'ui')(ShareMenu); diff --git a/app/scenes/Collection.js b/app/scenes/Collection.js index 526bb43db..dfe2c0078 100644 --- a/app/scenes/Collection.js +++ b/app/scenes/Collection.js @@ -2,7 +2,7 @@ import * as React from 'react'; import { observable } from 'mobx'; import { observer, inject } from 'mobx-react'; -import { withRouter, Link, Switch, Route } from 'react-router-dom'; +import { Redirect, Link, Switch, Route } from 'react-router-dom'; import styled from 'styled-components'; import { @@ -42,7 +42,6 @@ type Props = { ui: UiStore, documents: DocumentsStore, collections: CollectionsStore, - history: Object, match: Object, }; @@ -51,6 +50,7 @@ class CollectionScene extends React.Component { @observable collection: ?Collection; @observable isFetching: boolean = true; @observable permissionsModalOpen: boolean = false; + @observable redirectTo: ?string; componentDidMount() { this.loadContent(this.props.match.params.id); @@ -85,7 +85,7 @@ class CollectionScene extends React.Component { ev.preventDefault(); if (this.collection) { - this.props.history.push(`${this.collection.url}/new`); + this.redirectTo = `${this.collection.url}/new`; } }; @@ -102,10 +102,7 @@ class CollectionScene extends React.Component { return ( - + @@ -117,16 +114,11 @@ class CollectionScene extends React.Component { ); } - renderNotFound() { - return ; - } - render() { const { documents } = this.props; - if (!this.isFetching && !this.collection) { - return this.renderNotFound(); - } + if (this.redirectTo) return ; + if (!this.isFetching && !this.collection) return ; const pinnedDocuments = this.collection ? documents.pinnedInCollection(this.collection.id) @@ -296,6 +288,4 @@ const Wrapper = styled(Flex)` margin: 10px 0; `; -export default withRouter( - inject('collections', 'documents', 'ui')(CollectionScene) -); +export default inject('collections', 'documents', 'ui')(CollectionScene); diff --git a/app/scenes/Document/Document.js b/app/scenes/Document/Document.js index 9f6d49364..a62e2d330 100644 --- a/app/scenes/Document/Document.js +++ b/app/scenes/Document/Document.js @@ -41,6 +41,7 @@ import Revision from 'models/Revision'; import schema from './schema'; +let EditorImport; const AUTOSAVE_DELAY = 3000; const IS_DIRTY_DELAY = 500; const MARK_AS_VIEWED_AFTER = 3000; @@ -69,7 +70,7 @@ class DocumentScene extends React.Component { viewTimeout: TimeoutID; getEditorText: () => string; - @observable editorComponent; + @observable editorComponent = EditorImport; @observable document: ?Document; @observable revision: ?Revision; @observable newDocument: ?Document; @@ -167,10 +168,13 @@ class DocumentScene extends React.Component { } if (!this.revision) { - // Update url to match the current one - this.props.history.replace( - updateDocumentUrl(props.match.url, document.url) + const canonicalUrl = updateDocumentUrl( + props.match.url, + document.url ); + if (this.props.location.pathname !== canonicalUrl) { + this.props.history.replace(canonicalUrl); + } } } } else { @@ -181,8 +185,11 @@ class DocumentScene extends React.Component { }; loadEditor = async () => { - const EditorImport = await import('./components/Editor'); - this.editorComponent = EditorImport.default; + if (this.editorComponent) return; + + const Imported = await import('./components/Editor'); + EditorImport = Imported.default; + this.editorComponent = EditorImport; }; get isEditing() { @@ -357,7 +364,6 @@ class DocumentScene extends React.Component { isSaving={this.isSaving} isPublishing={this.isPublishing} savingIsDisabled={!document.allowSave} - history={this.props.history} onDiscard={this.onDiscard} onSave={this.onSave} /> @@ -376,7 +382,6 @@ class DocumentScene extends React.Component { onCancel={this.onDiscard} readOnly={!this.isEditing} toc={!revision} - history={this.props.history} ui={this.props.ui} schema={schema} /> diff --git a/app/scenes/Document/components/Header.js b/app/scenes/Document/components/Header.js index 83229d906..8996012d6 100644 --- a/app/scenes/Document/components/Header.js +++ b/app/scenes/Document/components/Header.js @@ -3,6 +3,7 @@ import * as React from 'react'; import { throttle } from 'lodash'; import { observable } from 'mobx'; import { observer, inject } from 'mobx-react'; +import { Redirect } from 'react-router-dom'; import styled from 'styled-components'; import breakpoint from 'styled-components-breakpoint'; import { NewDocumentIcon } from 'outline-icons'; @@ -33,7 +34,6 @@ type Props = { publish?: boolean, autosave?: boolean, }) => *, - history: Object, auth: AuthStore, }; @@ -41,6 +41,7 @@ type Props = { class Header extends React.Component { @observable isScrolled = false; @observable showShareModal = false; + @observable redirectTo: ?string; componentDidMount() { window.addEventListener('scroll', this.handleScroll); @@ -57,7 +58,7 @@ class Header extends React.Component { handleScroll = throttle(this.updateIsScrolled, 50); handleEdit = () => { - this.props.history.push(documentEditUrl(this.props.document)); + this.redirectTo = documentEditUrl(this.props.document); }; handleSave = () => { @@ -86,6 +87,8 @@ class Header extends React.Component { }; render() { + if (this.redirectTo) return ; + const { document, isEditing, diff --git a/package.json b/package.json index 9ecc7aa2d..184a3e826 100644 --- a/package.json +++ b/package.json @@ -157,7 +157,7 @@ "react-waypoint": "^7.3.1", "redis": "^2.6.2", "redis-lock": "^0.1.0", - "rich-markdown-editor": "^8.0.0", + "rich-markdown-editor": "^8.0.2", "safestart": "1.1.0", "sequelize": "4.28.6", "sequelize-cli": "^2.7.0", @@ -166,7 +166,7 @@ "string-hash": "^1.1.0", "string-replace-to-array": "^1.0.3", "style-loader": "^0.18.2", - "styled-components": "4.0.3", + "styled-components": "^4.1.3", "styled-components-breakpoint": "^1.0.1", "styled-components-grid": "^2.2.0", "styled-normalize": "^2.2.1", diff --git a/yarn.lock b/yarn.lock index aebec2045..39f0d6310 100644 --- a/yarn.lock +++ b/yarn.lock @@ -39,6 +39,12 @@ dependencies: "@babel/types" "7.0.0-beta.31" +"@babel/helper-module-imports@^7.0.0": + version "7.0.0" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.0.0.tgz#96081b7111e486da4d2cd971ad1a4fe216cc2e3d" + dependencies: + "@babel/types" "^7.0.0" + "@babel/template@7.0.0-beta.31": version "7.0.0-beta.31" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.0.0-beta.31.tgz#577bb29389f6c497c3e7d014617e7d6713f68bda" @@ -77,15 +83,19 @@ lodash "^4.17.10" to-fast-properties "^2.0.0" -"@emotion/is-prop-valid@^0.6.8": - version "0.6.8" - resolved "https://registry.yarnpkg.com/@emotion/is-prop-valid/-/is-prop-valid-0.6.8.tgz#68ad02831da41213a2089d2cab4e8ac8b30cbd85" +"@emotion/is-prop-valid@^0.7.3": + version "0.7.3" + resolved "https://registry.yarnpkg.com/@emotion/is-prop-valid/-/is-prop-valid-0.7.3.tgz#a6bf4fa5387cbba59d44e698a4680f481a8da6cc" dependencies: - "@emotion/memoize" "^0.6.6" + "@emotion/memoize" "0.7.1" -"@emotion/memoize@^0.6.6": - version "0.6.6" - resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.6.6.tgz#004b98298d04c7ca3b4f50ca2035d4f60d2eed1b" +"@emotion/memoize@0.7.1": + version "0.7.1" + resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.7.1.tgz#e93c13942592cf5ef01aa8297444dc192beee52f" + +"@emotion/unitless@^0.7.0": + version "0.7.3" + resolved "https://registry.yarnpkg.com/@emotion/unitless/-/unitless-0.7.3.tgz#6310a047f12d21a1036fb031317219892440416f" "@tommoor/remove-markdown@0.3.1": version "0.3.1" @@ -8803,9 +8813,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@^8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/rich-markdown-editor/-/rich-markdown-editor-8.0.0.tgz#d11a7b81e819bcef1680b60359b8761baeadbb01" +rich-markdown-editor@^8.0.2: + version "8.0.2" + resolved "https://registry.yarnpkg.com/rich-markdown-editor/-/rich-markdown-editor-8.0.2.tgz#b642d8c85794eca1df4e6026b2c07f66eb7445ad" dependencies: "@wikifactory/slate-edit-blockquote" "^0.7.1" "@wikifactory/slate-edit-code" "^0.16.0" @@ -8836,7 +8846,7 @@ rich-markdown-editor@^8.0.0: slate-react "^0.21.15" slate-schema-violations "^0.1.39" slugify "^1.3.0" - styled-components "4.0.3" + styled-components "^4.1.3" right-align@^0.1.1: version "0.1.3" @@ -9637,11 +9647,13 @@ styled-components-grid@^2.2.0: react-create-component-from-tag-prop "^1.4.0" styled-components-breakpoint "^2.0.2" -styled-components@4.0.3: - version "4.0.3" - resolved "https://registry.yarnpkg.com/styled-components/-/styled-components-4.0.3.tgz#6c1a95a93857aa613fdfc26ad40899217100d8c3" +styled-components@^4.1.3: + version "4.1.3" + resolved "https://registry.yarnpkg.com/styled-components/-/styled-components-4.1.3.tgz#4472447208e618b57e84deaaeb6acd34a5e0fe9b" dependencies: - "@emotion/is-prop-valid" "^0.6.8" + "@babel/helper-module-imports" "^7.0.0" + "@emotion/is-prop-valid" "^0.7.3" + "@emotion/unitless" "^0.7.0" babel-plugin-styled-components ">= 1" css-to-react-native "^2.2.2" memoize-one "^4.0.0"