Merge branch 'issue-739' of github.com:outline/outline
This commit is contained in:
23
app/components/ScrollToAnchor.js
Normal file
23
app/components/ScrollToAnchor.js
Normal file
@@ -0,0 +1,23 @@
|
||||
// @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);
|
||||
167
app/index.js
167
app/index.js
@@ -33,6 +33,7 @@ import Error404 from 'scenes/Error404';
|
||||
|
||||
import ErrorBoundary from 'components/ErrorBoundary';
|
||||
import ScrollToTop from 'components/ScrollToTop';
|
||||
import ScrollToAnchor from 'components/ScrollToAnchor';
|
||||
import Layout from 'components/Layout';
|
||||
import Auth from 'components/Auth';
|
||||
import RouteSidebarHidden from 'components/RouteSidebarHidden';
|
||||
@@ -62,84 +63,94 @@ if (element) {
|
||||
<Provider {...stores}>
|
||||
<Router>
|
||||
<ScrollToTop>
|
||||
<Switch>
|
||||
<Route exact path="/" component={Home} />
|
||||
<Route exact path="/share/:shareId" component={Document} />
|
||||
<Auth>
|
||||
<Layout>
|
||||
<Switch>
|
||||
<Route exact path="/dashboard" component={Dashboard} />
|
||||
<Route exact path="/starred" component={Starred} />
|
||||
<Route exact path="/drafts" component={Drafts} />
|
||||
<Route exact path="/settings" component={Settings} />
|
||||
<Route
|
||||
exact
|
||||
path="/settings/details"
|
||||
component={Details}
|
||||
/>
|
||||
<Route
|
||||
exact
|
||||
path="/settings/people"
|
||||
component={People}
|
||||
/>
|
||||
<Route
|
||||
exact
|
||||
path="/settings/shares"
|
||||
component={Shares}
|
||||
/>
|
||||
<Route
|
||||
exact
|
||||
path="/settings/tokens"
|
||||
component={Tokens}
|
||||
/>
|
||||
<Route
|
||||
exact
|
||||
path="/settings/integrations/slack"
|
||||
component={Slack}
|
||||
/>
|
||||
<Route
|
||||
exact
|
||||
path="/settings/export"
|
||||
component={Export}
|
||||
/>
|
||||
<Route
|
||||
exact
|
||||
path="/collections/:id"
|
||||
component={Collection}
|
||||
/>
|
||||
<Route
|
||||
exact
|
||||
path={`/d/${matchDocumentSlug}`}
|
||||
component={RedirectDocument}
|
||||
/>
|
||||
<Route
|
||||
exact
|
||||
path={`/doc/${matchDocumentSlug}`}
|
||||
component={Document}
|
||||
/>
|
||||
<Route
|
||||
exact
|
||||
path={`/doc/${matchDocumentSlug}/move`}
|
||||
component={Document}
|
||||
/>
|
||||
<Route exact path="/search" component={Search} />
|
||||
<Route exact path="/search/:query" component={Search} />
|
||||
<Route path="/404" component={Error404} />
|
||||
<RouteSidebarHidden
|
||||
exact
|
||||
path={`/doc/${matchDocumentSlug}/edit`}
|
||||
component={Document}
|
||||
/>
|
||||
<RouteSidebarHidden
|
||||
exact
|
||||
path="/collections/:id/new"
|
||||
component={DocumentNew}
|
||||
/>
|
||||
<Route component={notFoundSearch} />
|
||||
</Switch>
|
||||
</Layout>
|
||||
</Auth>
|
||||
</Switch>
|
||||
<ScrollToAnchor>
|
||||
<Switch>
|
||||
<Route exact path="/" component={Home} />
|
||||
<Route exact path="/share/:shareId" component={Document} />
|
||||
<Auth>
|
||||
<Layout>
|
||||
<Switch>
|
||||
<Route
|
||||
exact
|
||||
path="/dashboard"
|
||||
component={Dashboard}
|
||||
/>
|
||||
<Route exact path="/starred" component={Starred} />
|
||||
<Route exact path="/drafts" component={Drafts} />
|
||||
<Route exact path="/settings" component={Settings} />
|
||||
<Route
|
||||
exact
|
||||
path="/settings/details"
|
||||
component={Details}
|
||||
/>
|
||||
<Route
|
||||
exact
|
||||
path="/settings/people"
|
||||
component={People}
|
||||
/>
|
||||
<Route
|
||||
exact
|
||||
path="/settings/shares"
|
||||
component={Shares}
|
||||
/>
|
||||
<Route
|
||||
exact
|
||||
path="/settings/tokens"
|
||||
component={Tokens}
|
||||
/>
|
||||
<Route
|
||||
exact
|
||||
path="/settings/integrations/slack"
|
||||
component={Slack}
|
||||
/>
|
||||
<Route
|
||||
exact
|
||||
path="/settings/export"
|
||||
component={Export}
|
||||
/>
|
||||
<Route
|
||||
exact
|
||||
path="/collections/:id"
|
||||
component={Collection}
|
||||
/>
|
||||
<Route
|
||||
exact
|
||||
path={`/d/${matchDocumentSlug}`}
|
||||
component={RedirectDocument}
|
||||
/>
|
||||
<Route
|
||||
exact
|
||||
path={`/doc/${matchDocumentSlug}`}
|
||||
component={Document}
|
||||
/>
|
||||
<Route
|
||||
exact
|
||||
path={`/doc/${matchDocumentSlug}/move`}
|
||||
component={Document}
|
||||
/>
|
||||
<Route exact path="/search" component={Search} />
|
||||
<Route
|
||||
exact
|
||||
path="/search/:query"
|
||||
component={Search}
|
||||
/>
|
||||
<Route path="/404" component={Error404} />
|
||||
<RouteSidebarHidden
|
||||
exact
|
||||
path={`/doc/${matchDocumentSlug}/edit`}
|
||||
component={Document}
|
||||
/>
|
||||
<RouteSidebarHidden
|
||||
exact
|
||||
path="/collections/:id/new"
|
||||
component={DocumentNew}
|
||||
/>
|
||||
<Route component={notFoundSearch} />
|
||||
</Switch>
|
||||
</Layout>
|
||||
</Auth>
|
||||
</Switch>
|
||||
</ScrollToAnchor>
|
||||
</ScrollToTop>
|
||||
</Router>
|
||||
</Provider>
|
||||
|
||||
@@ -231,6 +231,12 @@ class DocumentScene extends React.Component<Props> {
|
||||
};
|
||||
|
||||
onClickLink = (href: string) => {
|
||||
// on page hash
|
||||
if (href[0] === '#') {
|
||||
window.location.href = href;
|
||||
return;
|
||||
}
|
||||
|
||||
if (isInternalUrl(href)) {
|
||||
// relative
|
||||
let navigateTo = href;
|
||||
@@ -239,7 +245,7 @@ class DocumentScene extends React.Component<Props> {
|
||||
if (href[0] !== '/') {
|
||||
try {
|
||||
const url = new URL(href);
|
||||
navigateTo = url.pathname;
|
||||
navigateTo = url.pathname + url.hash;
|
||||
} catch (err) {
|
||||
navigateTo = href;
|
||||
}
|
||||
@@ -251,6 +257,10 @@ class DocumentScene extends React.Component<Props> {
|
||||
}
|
||||
};
|
||||
|
||||
onShowToast = (message: string) => {
|
||||
this.props.ui.showToast(message, 'success');
|
||||
};
|
||||
|
||||
render() {
|
||||
const { location, match } = this.props;
|
||||
const Editor = this.editorComponent;
|
||||
@@ -328,6 +338,7 @@ class DocumentScene extends React.Component<Props> {
|
||||
onChange={this.onChange}
|
||||
onSave={this.onSave}
|
||||
onCancel={this.onDiscard}
|
||||
onShowToast={this.onShowToast}
|
||||
readOnly={!this.isEditing}
|
||||
toc
|
||||
/>
|
||||
|
||||
@@ -158,7 +158,7 @@
|
||||
"react-waypoint": "^7.3.1",
|
||||
"redis": "^2.6.2",
|
||||
"redis-lock": "^0.1.0",
|
||||
"rich-markdown-editor": "2.0.11",
|
||||
"rich-markdown-editor": "3.1.1",
|
||||
"safestart": "1.1.0",
|
||||
"sequelize": "4.28.6",
|
||||
"sequelize-cli": "^2.7.0",
|
||||
|
||||
@@ -8858,9 +8858,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@2.0.11:
|
||||
version "2.0.11"
|
||||
resolved "https://registry.yarnpkg.com/rich-markdown-editor/-/rich-markdown-editor-2.0.11.tgz#209fd57ad8f61244e09cbe167ba64fc2c3b37da6"
|
||||
rich-markdown-editor@3.1.1:
|
||||
version "3.1.1"
|
||||
resolved "https://registry.yarnpkg.com/rich-markdown-editor/-/rich-markdown-editor-3.1.1.tgz#ee97b3ca87836c960de0912b852df32c8054873d"
|
||||
dependencies:
|
||||
"@tommoor/slate-drop-or-paste-images" "^0.8.1"
|
||||
babel-plugin-transform-async-to-generator "^6.24.1"
|
||||
|
||||
Reference in New Issue
Block a user