refactor: flow typing (#1012)

* fix: padding

* fix: Minor button alignment issues

* feat: Add icon to invite people button

* WIP
This commit is contained in:
Tom Moor
2019-08-08 23:09:09 -07:00
committed by GitHub
parent 7b2eea0009
commit d024d31f66
64 changed files with 207 additions and 144 deletions

View File

@ -2,7 +2,11 @@
/* global ga */ /* global ga */
import * as React from 'react'; import * as React from 'react';
export default class Analytics extends React.Component<*> { type Props = {
children?: React.Node,
};
export default class Analytics extends React.Component<Props> {
componentDidMount() { componentDidMount() {
if (!process.env.GOOGLE_ANALYTICS_ID) return; if (!process.env.GOOGLE_ANALYTICS_ID) return;

View File

@ -66,14 +66,14 @@ class ColorPicker extends React.Component<Props> {
}; };
@action @action
focusOnCustomColor = (event: SyntheticEvent<*>) => { focusOnCustomColor = (event: SyntheticEvent<>) => {
this.selectedColor = ''; this.selectedColor = '';
this.customColorSelected = true; this.customColorSelected = true;
this.fireCallback(); this.fireCallback();
}; };
@action @action
setCustomColor = (event: SyntheticEvent<*>) => { setCustomColor = (event: SyntheticEvent<HTMLElement>) => {
let target = event.target; let target = event.target;
if (target instanceof HTMLInputElement) { if (target instanceof HTMLInputElement) {
const color = target.value; const color = target.value;

View File

@ -5,12 +5,12 @@ import copy from 'copy-to-clipboard';
type Props = { type Props = {
text: string, text: string,
children?: React.Node, children?: React.Node,
onClick?: () => *, onClick?: () => void,
onCopy: () => *, onCopy: () => void,
}; };
class CopyToClipboard extends React.PureComponent<Props> { class CopyToClipboard extends React.PureComponent<Props> {
onClick = (ev: SyntheticEvent<*>) => { onClick = (ev: SyntheticEvent<>) => {
const { text, onCopy, children } = this.props; const { text, onCopy, children } = this.props;
const elem = React.Children.only(children); const elem = React.Children.only(children);
copy(text, { copy(text, {

View File

@ -2,6 +2,7 @@
import * as React from 'react'; import * as React from 'react';
import { observable, action } from 'mobx'; import { observable, action } from 'mobx';
import { observer, inject } from 'mobx-react'; import { observer, inject } from 'mobx-react';
import type { RouterHistory } from 'react-router-dom';
import styled from 'styled-components'; import styled from 'styled-components';
import Waypoint from 'react-waypoint'; import Waypoint from 'react-waypoint';
import ArrowKeyNavigation from 'boundless-arrow-key-navigation'; import ArrowKeyNavigation from 'boundless-arrow-key-navigation';
@ -20,7 +21,7 @@ type Props = {
match: Object, match: Object,
documents: DocumentsStore, documents: DocumentsStore,
revisions: RevisionsStore, revisions: RevisionsStore,
history: Object, history: RouterHistory,
}; };
@observer @observer

View File

@ -9,10 +9,19 @@ import Flex from 'shared/components/Flex';
import Time from 'shared/components/Time'; import Time from 'shared/components/Time';
import Avatar from 'components/Avatar'; import Avatar from 'components/Avatar';
import RevisionMenu from 'menus/RevisionMenu'; import RevisionMenu from 'menus/RevisionMenu';
import Document from 'models/Document';
import Revision from 'models/Revision';
import { documentHistoryUrl } from 'utils/routeHelpers'; import { documentHistoryUrl } from 'utils/routeHelpers';
class Revision extends React.Component<*> { type Props = {
theme: Object,
showMenu: () => void,
document: Document,
revision: Revision,
};
class RevisionListItem extends React.Component<Props> {
render() { render() {
const { revision, document, showMenu, theme } = this.props; const { revision, document, showMenu, theme } = this.props;
@ -74,4 +83,4 @@ const Meta = styled.p`
padding: 0; padding: 0;
`; `;
export default withTheme(Revision); export default withTheme(RevisionListItem);

View File

@ -17,7 +17,6 @@ type Props = {
showCollection?: boolean, showCollection?: boolean,
showPublished?: boolean, showPublished?: boolean,
showPin?: boolean, showPin?: boolean,
ref?: *,
}; };
const StyledStar = withTheme(styled(({ solid, theme, ...props }) => ( const StyledStar = withTheme(styled(({ solid, theme, ...props }) => (
@ -107,13 +106,13 @@ const SEARCH_RESULT_REGEX = /<b\b[^>]*>(.*?)<\/b>/gi;
@observer @observer
class DocumentPreview extends React.Component<Props> { class DocumentPreview extends React.Component<Props> {
star = (ev: SyntheticEvent<*>) => { star = (ev: SyntheticEvent<>) => {
ev.preventDefault(); ev.preventDefault();
ev.stopPropagation(); ev.stopPropagation();
this.props.document.star(); this.props.document.star();
}; };
unstar = (ev: SyntheticEvent<*>) => { unstar = (ev: SyntheticEvent<>) => {
ev.preventDefault(); ev.preventDefault();
ev.stopPropagation(); ev.stopPropagation();
this.props.document.unstar(); this.props.document.unstar();

View File

@ -2,7 +2,7 @@
import * as React from 'react'; import * as React from 'react';
import { observable } from 'mobx'; import { observable } from 'mobx';
import { observer, inject } from 'mobx-react'; import { observer, inject } from 'mobx-react';
import { withRouter } from 'react-router-dom'; import { withRouter, type RouterHistory } from 'react-router-dom';
import { createGlobalStyle } from 'styled-components'; import { createGlobalStyle } from 'styled-components';
import invariant from 'invariant'; import invariant from 'invariant';
import importFile from 'utils/importFile'; import importFile from 'utils/importFile';
@ -22,7 +22,7 @@ type Props = {
disabled: boolean, disabled: boolean,
location: Object, location: Object,
match: Object, match: Object,
history: Object, history: RouterHistory,
staticContext: Object, staticContext: Object,
}; };

View File

@ -31,10 +31,10 @@ class DropdownMenu extends React.Component<Props> {
@observable left: number; @observable left: number;
handleOpen = ( handleOpen = (
openPortal: (SyntheticEvent<*>) => void, openPortal: (SyntheticEvent<>) => void,
closePortal: () => void closePortal: () => void
) => { ) => {
return (ev: SyntheticMouseEvent<*>) => { return (ev: SyntheticMouseEvent<HTMLElement>) => {
ev.preventDefault(); ev.preventDefault();
const currentTarget = ev.currentTarget; const currentTarget = ev.currentTarget;
invariant(document.body, 'why you not here'); invariant(document.body, 'why you not here');

View File

@ -3,7 +3,7 @@ import * as React from 'react';
import styled from 'styled-components'; import styled from 'styled-components';
type Props = { type Props = {
onClick?: (SyntheticEvent<*>) => *, onClick?: (SyntheticEvent<>) => void | Promise<void>,
children?: React.Node, children?: React.Node,
disabled?: boolean, disabled?: boolean,
}; };

View File

@ -10,6 +10,7 @@ import Placeholder from 'rich-markdown-editor/lib/components/Placeholder';
import { uploadFile } from 'utils/uploadFile'; import { uploadFile } from 'utils/uploadFile';
import isInternalUrl from 'utils/isInternalUrl'; import isInternalUrl from 'utils/isInternalUrl';
import Tooltip from 'components/Tooltip'; import Tooltip from 'components/Tooltip';
import UiStore from 'stores/UiStore';
import Embed from './Embed'; import Embed from './Embed';
import embeds from '../../embeds'; import embeds from '../../embeds';
@ -17,8 +18,8 @@ type Props = {
defaultValue?: string, defaultValue?: string,
readOnly?: boolean, readOnly?: boolean,
disableEmbeds?: boolean, disableEmbeds?: boolean,
forwardedRef: *, forwardedRef: React.Ref<RichMarkdownEditor>,
ui: *, ui: UiStore,
}; };
@observer @observer

View File

@ -14,7 +14,7 @@ type Props = {
@observer @observer
class InputRich extends React.Component<Props> { class InputRich extends React.Component<Props> {
@observable editorComponent: *; @observable editorComponent: React.ComponentType<any>;
@observable focused: boolean = false; @observable focused: boolean = false;
componentDidMount() { componentDidMount() {

View File

@ -1,9 +1,14 @@
// @flow // @flow
import * as React from 'react'; import * as React from 'react';
import { inject, observer } from 'mobx-react'; import { inject, observer } from 'mobx-react';
import UiStore from 'stores/UiStore';
type Props = {
ui: UiStore,
};
@observer @observer
class LoadingIndicator extends React.Component<*> { class LoadingIndicator extends React.Component<Props> {
componentDidMount() { componentDidMount() {
this.props.ui.enableProgressBar(); this.props.ui.enableProgressBar();
} }

View File

@ -5,7 +5,12 @@ import { pulsate } from 'shared/styles/animations';
import { randomInteger } from 'shared/random'; import { randomInteger } from 'shared/random';
import Flex from 'shared/components/Flex'; import Flex from 'shared/components/Flex';
class Mask extends React.Component<*> { type Props = {
header?: boolean,
height?: number,
};
class Mask extends React.Component<Props> {
width: number; width: number;
shouldComponentUpdate() { shouldComponentUpdate() {

View File

@ -15,7 +15,7 @@ type Props = {
children?: React.Node, children?: React.Node,
isOpen: boolean, isOpen: boolean,
title?: string, title?: string,
onRequestClose: () => *, onRequestClose: () => void,
}; };
const GlobalStyles = createGlobalStyle` const GlobalStyles = createGlobalStyle`

View File

@ -11,7 +11,7 @@ import { ListPlaceholder } from 'components/LoadingPlaceholder';
type Props = { type Props = {
documents: Document[], documents: Document[],
fetch: (options: ?Object) => Promise<*>, fetch: (options: ?Object) => Promise<void>,
options?: Object, options?: Object,
heading?: React.Node, heading?: React.Node,
empty?: React.Node, empty?: React.Node,

View File

@ -14,12 +14,12 @@ type Props = {
document?: ?Document, document?: ?Document,
collection: ?Collection, collection: ?Collection,
onSuccess?: () => void, onSuccess?: () => void,
ref?: *, ref?: (?React.ElementRef<'div'>) => void,
}; };
@observer @observer
class PathToDocument extends React.Component<Props> { class PathToDocument extends React.Component<Props> {
handleClick = async (ev: SyntheticEvent<*>) => { handleClick = async (ev: SyntheticEvent<>) => {
ev.preventDefault(); ev.preventDefault();
const { document, result, onSuccess } = this.props; const { document, result, onSuccess } = this.props;
if (!document) return; if (!document) return;

View File

@ -6,7 +6,7 @@ import UiStore from 'stores/UiStore';
type Props = { type Props = {
ui: UiStore, ui: UiStore,
component: *, component: React.ComponentType<any>,
}; };
class RouteSidebarHidden extends React.Component<Props> { class RouteSidebarHidden extends React.Component<Props> {

View File

@ -2,8 +2,14 @@
// based on: https://reacttraining.com/react-router/web/guides/scroll-restoration // based on: https://reacttraining.com/react-router/web/guides/scroll-restoration
import * as React from 'react'; import * as React from 'react';
import { withRouter } from 'react-router-dom'; import { withRouter } from 'react-router-dom';
import type { Location } from 'react-router-dom';
class ScrollToTop extends React.Component<*> { type Props = {
location: Location,
children: React.Node,
};
class ScrollToTop extends React.Component<Props> {
componentDidUpdate(prevProps) { componentDidUpdate(prevProps) {
if (this.props.location.pathname === prevProps.location.pathname) return; if (this.props.location.pathname === prevProps.location.pathname) return;

View File

@ -12,7 +12,7 @@ type Props = {
class Scrollable extends React.Component<Props> { class Scrollable extends React.Component<Props> {
@observable shadow: boolean = false; @observable shadow: boolean = false;
handleScroll = (ev: SyntheticMouseEvent<*>) => { handleScroll = (ev: SyntheticMouseEvent<HTMLDivElement>) => {
this.shadow = !!(this.props.shadow && ev.currentTarget.scrollTop > 0); this.shadow = !!(this.props.shadow && ev.currentTarget.scrollTop > 0);
}; };

View File

@ -1,6 +1,7 @@
// @flow // @flow
import * as React from 'react'; import * as React from 'react';
import { observer, inject } from 'mobx-react'; import { observer, inject } from 'mobx-react';
import type { RouterHistory } from 'react-router-dom';
import { import {
DocumentIcon, DocumentIcon,
EmailIcon, EmailIcon,
@ -25,7 +26,7 @@ import HeaderBlock from './components/HeaderBlock';
import AuthStore from 'stores/AuthStore'; import AuthStore from 'stores/AuthStore';
type Props = { type Props = {
history: Object, history: RouterHistory,
auth: AuthStore, auth: AuthStore,
}; };

View File

@ -18,7 +18,7 @@ type Props = {
ui: UiStore, ui: UiStore,
documents: DocumentsStore, documents: DocumentsStore,
activeDocument: ?Document, activeDocument: ?Document,
prefetchDocument: (id: string) => *, prefetchDocument: (id: string) => Promise<void>,
}; };
@observer @observer

View File

@ -1,7 +1,7 @@
// @flow // @flow
import * as React from 'react'; import * as React from 'react';
import { observer, inject } from 'mobx-react'; import { observer, inject } from 'mobx-react';
import { withRouter } from 'react-router-dom'; import { withRouter, type RouterHistory } from 'react-router-dom';
import keydown from 'react-keydown'; import keydown from 'react-keydown';
import Flex from 'shared/components/Flex'; import Flex from 'shared/components/Flex';
import { PlusIcon } from 'outline-icons'; import { PlusIcon } from 'outline-icons';
@ -17,7 +17,7 @@ import UiStore from 'stores/UiStore';
import DocumentsStore from 'stores/DocumentsStore'; import DocumentsStore from 'stores/DocumentsStore';
type Props = { type Props = {
history: Object, history: RouterHistory,
collections: CollectionsStore, collections: CollectionsStore,
documents: DocumentsStore, documents: DocumentsStore,
onCreateCollection: () => void, onCreateCollection: () => void,

View File

@ -18,7 +18,7 @@ type Props = {
documents: DocumentsStore, documents: DocumentsStore,
collection?: Collection, collection?: Collection,
activeDocument: ?Document, activeDocument: ?Document,
activeDocumentRef?: (?HTMLElement) => *, activeDocumentRef?: (?HTMLElement) => void,
prefetchDocument: (documentId: string) => Promise<void>, prefetchDocument: (documentId: string) => Promise<void>,
depth: number, depth: number,
}; };
@ -27,7 +27,7 @@ type Props = {
class DocumentLink extends React.Component<Props> { class DocumentLink extends React.Component<Props> {
@observable menuOpen = false; @observable menuOpen = false;
handleMouseEnter = (ev: SyntheticEvent<*>) => { handleMouseEnter = (ev: SyntheticEvent<>) => {
const { node, prefetchDocument } = this.props; const { node, prefetchDocument } = this.props;
ev.stopPropagation(); ev.stopPropagation();

View File

@ -9,7 +9,7 @@ import Flex from 'shared/components/Flex';
type Props = { type Props = {
to?: string | Object, to?: string | Object,
onClick?: (SyntheticEvent<*>) => *, onClick?: (SyntheticEvent<>) => void,
children?: React.Node, children?: React.Node,
icon?: React.Node, icon?: React.Node,
expanded?: boolean, expanded?: boolean,
@ -43,7 +43,7 @@ class SidebarLink extends React.Component<Props> {
} }
@action @action
handleClick = (ev: SyntheticEvent<*>) => { handleClick = (ev: SyntheticEvent<>) => {
ev.preventDefault(); ev.preventDefault();
ev.stopPropagation(); ev.stopPropagation();
this.expanded = !this.expanded; this.expanded = !this.expanded;

View File

@ -1,7 +1,7 @@
// @flow // @flow
import * as React from 'react'; import * as React from 'react';
export default function SlackIcon(props: *) { export default function SlackIcon() {
return ( return (
<svg <svg
fill="#4E5C6E" fill="#4E5C6E"
@ -9,7 +9,6 @@ export default function SlackIcon(props: *) {
height="24px" height="24px"
viewBox="0 0 24 24" viewBox="0 0 24 24"
version="1.1" version="1.1"
{...props}
> >
<path d="M7.36156352,14.1107492 C7.36156352,15.0358306 6.60586319,15.7915309 5.68078176,15.7915309 C4.75570033,15.7915309 4,15.0358306 4,14.1107492 C4,13.1856678 4.75570033,12.4299674 5.68078176,12.4299674 L7.36156352,12.4299674 L7.36156352,14.1107492 Z M8.20846906,14.1107492 C8.20846906,13.1856678 8.96416938,12.4299674 9.88925081,12.4299674 C10.8143322,12.4299674 11.5700326,13.1856678 11.5700326,14.1107492 L11.5700326,18.3192182 C11.5700326,19.2442997 10.8143322,20 9.88925081,20 C8.96416938,20 8.20846906,19.2442997 8.20846906,18.3192182 C8.20846906,18.3192182 8.20846906,14.1107492 8.20846906,14.1107492 Z M9.88925081,7.36156352 C8.96416938,7.36156352 8.20846906,6.60586319 8.20846906,5.68078176 C8.20846906,4.75570033 8.96416938,4 9.88925081,4 C10.8143322,4 11.5700326,4.75570033 11.5700326,5.68078176 L11.5700326,7.36156352 L9.88925081,7.36156352 Z M9.88925081,8.20846906 C10.8143322,8.20846906 11.5700326,8.96416938 11.5700326,9.88925081 C11.5700326,10.8143322 10.8143322,11.5700326 9.88925081,11.5700326 L5.68078176,11.5700326 C4.75570033,11.5700326 4,10.8143322 4,9.88925081 C4,8.96416938 4.75570033,8.20846906 5.68078176,8.20846906 C5.68078176,8.20846906 9.88925081,8.20846906 9.88925081,8.20846906 Z M16.6384365,9.88925081 C16.6384365,8.96416938 17.3941368,8.20846906 18.3192182,8.20846906 C19.2442997,8.20846906 20,8.96416938 20,9.88925081 C20,10.8143322 19.2442997,11.5700326 18.3192182,11.5700326 L16.6384365,11.5700326 L16.6384365,9.88925081 Z M15.7915309,9.88925081 C15.7915309,10.8143322 15.0358306,11.5700326 14.1107492,11.5700326 C13.1856678,11.5700326 12.4299674,10.8143322 12.4299674,9.88925081 L12.4299674,5.68078176 C12.4299674,4.75570033 13.1856678,4 14.1107492,4 C15.0358306,4 15.7915309,4.75570033 15.7915309,5.68078176 L15.7915309,9.88925081 Z M14.1107492,16.6384365 C15.0358306,16.6384365 15.7915309,17.3941368 15.7915309,18.3192182 C15.7915309,19.2442997 15.0358306,20 14.1107492,20 C13.1856678,20 12.4299674,19.2442997 12.4299674,18.3192182 L12.4299674,16.6384365 L14.1107492,16.6384365 Z M14.1107492,15.7915309 C13.1856678,15.7915309 12.4299674,15.0358306 12.4299674,14.1107492 C12.4299674,13.1856678 13.1856678,12.4299674 14.1107492,12.4299674 L18.3192182,12.4299674 C19.2442997,12.4299674 20,13.1856678 20,14.1107492 C20,15.0358306 19.2442997,15.7915309 18.3192182,15.7915309 L14.1107492,15.7915309 Z" /> <path d="M7.36156352,14.1107492 C7.36156352,15.0358306 6.60586319,15.7915309 5.68078176,15.7915309 C4.75570033,15.7915309 4,15.0358306 4,14.1107492 C4,13.1856678 4.75570033,12.4299674 5.68078176,12.4299674 L7.36156352,12.4299674 L7.36156352,14.1107492 Z M8.20846906,14.1107492 C8.20846906,13.1856678 8.96416938,12.4299674 9.88925081,12.4299674 C10.8143322,12.4299674 11.5700326,13.1856678 11.5700326,14.1107492 L11.5700326,18.3192182 C11.5700326,19.2442997 10.8143322,20 9.88925081,20 C8.96416938,20 8.20846906,19.2442997 8.20846906,18.3192182 C8.20846906,18.3192182 8.20846906,14.1107492 8.20846906,14.1107492 Z M9.88925081,7.36156352 C8.96416938,7.36156352 8.20846906,6.60586319 8.20846906,5.68078176 C8.20846906,4.75570033 8.96416938,4 9.88925081,4 C10.8143322,4 11.5700326,4.75570033 11.5700326,5.68078176 L11.5700326,7.36156352 L9.88925081,7.36156352 Z M9.88925081,8.20846906 C10.8143322,8.20846906 11.5700326,8.96416938 11.5700326,9.88925081 C11.5700326,10.8143322 10.8143322,11.5700326 9.88925081,11.5700326 L5.68078176,11.5700326 C4.75570033,11.5700326 4,10.8143322 4,9.88925081 C4,8.96416938 4.75570033,8.20846906 5.68078176,8.20846906 C5.68078176,8.20846906 9.88925081,8.20846906 9.88925081,8.20846906 Z M16.6384365,9.88925081 C16.6384365,8.96416938 17.3941368,8.20846906 18.3192182,8.20846906 C19.2442997,8.20846906 20,8.96416938 20,9.88925081 C20,10.8143322 19.2442997,11.5700326 18.3192182,11.5700326 L16.6384365,11.5700326 L16.6384365,9.88925081 Z M15.7915309,9.88925081 C15.7915309,10.8143322 15.0358306,11.5700326 14.1107492,11.5700326 C13.1856678,11.5700326 12.4299674,10.8143322 12.4299674,9.88925081 L12.4299674,5.68078176 C12.4299674,4.75570033 13.1856678,4 14.1107492,4 C15.0358306,4 15.7915309,4.75570033 15.7915309,5.68078176 L15.7915309,9.88925081 Z M14.1107492,16.6384365 C15.0358306,16.6384365 15.7915309,17.3941368 15.7915309,18.3192182 C15.7915309,19.2442997 15.0358306,20 14.1107492,20 C13.1856678,20 12.4299674,19.2442997 12.4299674,18.3192182 L12.4299674,16.6384365 L14.1107492,16.6384365 Z M14.1107492,15.7915309 C13.1856678,15.7915309 12.4299674,15.0358306 12.4299674,14.1107492 C12.4299674,13.1856678 13.1856678,12.4299674 14.1107492,12.4299674 L18.3192182,12.4299674 C19.2442997,12.4299674 20,13.1856678 20,14.1107492 C20,15.0358306 19.2442997,15.7915309 18.3192182,15.7915309 L14.1107492,15.7915309 Z" />
</svg> </svg>

View File

@ -1,7 +1,7 @@
// @flow // @flow
import * as React from 'react'; import * as React from 'react';
export default function ZapierIcon(props: *) { export default function ZapierIcon() {
return ( return (
<svg <svg
fill="#4E5C6E" fill="#4E5C6E"
@ -9,7 +9,6 @@ export default function ZapierIcon(props: *) {
height="24px" height="24px"
viewBox="0 0 24 24" viewBox="0 0 24 24"
version="1.1" version="1.1"
{...props}
> >
<path d="M14,12.00348 C13.9996,12.59796 13.89092,13.16708 13.6928,13.69244 C13.16752,13.89072 12.59816,13.99964 12.00344,14.00004 L11.99656,14.00004 C11.40216,13.99964 10.83296,13.89104 10.30768,13.69284 C10.10952,13.16764 10.0004,12.59828 10,12.00364 L10,11.99672 C10.0004,11.40224 10.10928,10.83312 10.30712,10.3078 C10.83264,10.10964 11.40192,10.0006 11.99656,10.0002 L12.00344,10.0002 C12.59816,10.0006 13.16752,10.10964 13.69276,10.3078 C13.89076,10.83316 13.99956,11.40228 13.99996,11.99676 L13.99996,12.00368 L13.99996,12.0036 L14,12.00348 Z M19.8888,10.66668 L15.21896,10.66668 L18.52096,7.36468 C18.2617173,7.00059444 17.9725547,6.65876921 17.65648,6.34276 L17.65632,6.34244 C17.340564,6.02673022 16.9990638,5.73786527 16.63536,5.47884 L13.33336,8.78084 L13.33336,4.11128 C12.894135,4.03747693 12.4495423,4.00025584 12.00416,4 L11.99568,4 C11.5503533,4.00023789 11.1058145,4.03743219 10.66664,4.1112 L10.66664,8.78108 L7.36464,5.47908 C7.00075543,5.7381962 6.65910565,6.02719699 6.34324,6.34308 L6.34204,6.34416 C6.02660762,6.65978768 5.73799769,7.00112635 5.4792,7.36464 L8.7812,10.66664 L4.1112,10.66664 C4.1112,10.66664 4.00016,11.54384 4,11.99704 L4,12.00284 C4.00016664,12.4487002 4.03736113,12.8937765 4.1112,13.33348 L8.78104,13.33348 L5.47904,16.63548 C5.99830995,17.3645251 6.63559493,18.0018101 7.36464,18.52108 L10.66664,15.21916 L10.66664,19.8888 C11.1053956,19.962476 11.5495017,19.9996699 11.9944,20 L12.00584,20 C12.4506842,19.999644 12.8947349,19.9624502 13.33344,19.8888 L13.33344,15.21892 L16.63544,18.52092 C16.9992044,18.2618792 17.3407586,17.972987 17.65656,17.65724 L17.65736,17.65664 C17.9730579,17.3408301 18.2619218,16.9992911 18.52096,16.63556 L15.21896,13.33348 L19.8888,13.33348 C19.9624671,12.8947771 19.999661,12.4507249 20,12.00588 L20,11.9944 C19.999644,11.5495558 19.9624502,11.1055051 19.8888,10.6668 L19.8888,10.66668 Z" /> <path d="M14,12.00348 C13.9996,12.59796 13.89092,13.16708 13.6928,13.69244 C13.16752,13.89072 12.59816,13.99964 12.00344,14.00004 L11.99656,14.00004 C11.40216,13.99964 10.83296,13.89104 10.30768,13.69284 C10.10952,13.16764 10.0004,12.59828 10,12.00364 L10,11.99672 C10.0004,11.40224 10.10928,10.83312 10.30712,10.3078 C10.83264,10.10964 11.40192,10.0006 11.99656,10.0002 L12.00344,10.0002 C12.59816,10.0006 13.16752,10.10964 13.69276,10.3078 C13.89076,10.83316 13.99956,11.40228 13.99996,11.99676 L13.99996,12.00368 L13.99996,12.0036 L14,12.00348 Z M19.8888,10.66668 L15.21896,10.66668 L18.52096,7.36468 C18.2617173,7.00059444 17.9725547,6.65876921 17.65648,6.34276 L17.65632,6.34244 C17.340564,6.02673022 16.9990638,5.73786527 16.63536,5.47884 L13.33336,8.78084 L13.33336,4.11128 C12.894135,4.03747693 12.4495423,4.00025584 12.00416,4 L11.99568,4 C11.5503533,4.00023789 11.1058145,4.03743219 10.66664,4.1112 L10.66664,8.78108 L7.36464,5.47908 C7.00075543,5.7381962 6.65910565,6.02719699 6.34324,6.34308 L6.34204,6.34416 C6.02660762,6.65978768 5.73799769,7.00112635 5.4792,7.36464 L8.7812,10.66664 L4.1112,10.66664 C4.1112,10.66664 4.00016,11.54384 4,11.99704 L4,12.00284 C4.00016664,12.4487002 4.03736113,12.8937765 4.1112,13.33348 L8.78104,13.33348 L5.47904,16.63548 C5.99830995,17.3645251 6.63559493,18.0018101 7.36464,18.52108 L10.66664,15.21916 L10.66664,19.8888 C11.1053956,19.962476 11.5495017,19.9996699 11.9944,20 L12.00584,20 C12.4506842,19.999644 12.8947349,19.9624502 13.33344,19.8888 L13.33344,15.21892 L16.63544,18.52092 C16.9992044,18.2618792 17.3407586,17.972987 17.65656,17.65724 L17.65736,17.65664 C17.9730579,17.3408301 18.2619218,16.9992911 18.52096,16.63556 L15.21896,13.33348 L19.8888,13.33348 C19.9624671,12.8947771 19.999661,12.4507249 20,12.00588 L20,11.9944 C19.999644,11.5495558 19.9624502,11.1055051 19.8888,10.6668 L19.8888,10.66668 Z" />
</svg> </svg>

View File

@ -3,6 +3,10 @@ import * as React from 'react';
import styled, { withTheme } from 'styled-components'; import styled, { withTheme } from 'styled-components';
import { NavLink } from 'react-router-dom'; import { NavLink } from 'react-router-dom';
type Props = {
theme: Object,
};
const StyledNavLink = styled(NavLink)` const StyledNavLink = styled(NavLink)`
position: relative; position: relative;
top: 1px; top: 1px;
@ -21,7 +25,7 @@ const StyledNavLink = styled(NavLink)`
} }
`; `;
function Tab(props: *) { function Tab(props: Props) {
const activeStyle = { const activeStyle = {
paddingBottom: '5px', paddingBottom: '5px',
borderBottom: `3px solid ${props.theme.textSecondary}`, borderBottom: `3px solid ${props.theme.textSecondary}`,

View File

@ -2,7 +2,7 @@
import * as React from 'react'; import * as React from 'react';
import { observable } from 'mobx'; import { observable } from 'mobx';
import { inject, observer } from 'mobx-react'; import { inject, observer } from 'mobx-react';
import { withRouter } from 'react-router-dom'; import { withRouter, type RouterHistory } from 'react-router-dom';
import styled from 'styled-components'; import styled from 'styled-components';
import { MoreIcon } from 'outline-icons'; import { MoreIcon } from 'outline-icons';
import Modal from 'components/Modal'; import Modal from 'components/Modal';
@ -22,7 +22,7 @@ type Props = {
ui: UiStore, ui: UiStore,
documents: DocumentsStore, documents: DocumentsStore,
collection: Collection, collection: Collection,
history: Object, history: RouterHistory,
onOpen?: () => void, onOpen?: () => void,
onClose?: () => void, onClose?: () => void,
}; };
@ -33,20 +33,20 @@ class CollectionMenu extends React.Component<Props> {
@observable permissionsModalOpen: boolean = false; @observable permissionsModalOpen: boolean = false;
@observable redirectTo: ?string; @observable redirectTo: ?string;
onNewDocument = (ev: SyntheticEvent<*>) => { onNewDocument = (ev: SyntheticEvent<>) => {
ev.preventDefault(); ev.preventDefault();
const { collection } = this.props; const { collection } = this.props;
this.props.history.push(newDocumentUrl(collection.id)); this.props.history.push(newDocumentUrl(collection.id));
}; };
onImportDocument = (ev: SyntheticEvent<*>) => { onImportDocument = (ev: SyntheticEvent<>) => {
ev.preventDefault(); ev.preventDefault();
// simulate a click on the file upload input element // simulate a click on the file upload input element
if (this.file) this.file.click(); if (this.file) this.file.click();
}; };
onFilePicked = async (ev: SyntheticEvent<*>) => { onFilePicked = async (ev: SyntheticEvent<>) => {
const files = getDataTransferFiles(ev); const files = getDataTransferFiles(ev);
try { try {
@ -61,25 +61,25 @@ class CollectionMenu extends React.Component<Props> {
} }
}; };
onEdit = (ev: SyntheticEvent<*>) => { onEdit = (ev: SyntheticEvent<>) => {
ev.preventDefault(); ev.preventDefault();
const { collection } = this.props; const { collection } = this.props;
this.props.ui.setActiveModal('collection-edit', { collection }); this.props.ui.setActiveModal('collection-edit', { collection });
}; };
onDelete = (ev: SyntheticEvent<*>) => { onDelete = (ev: SyntheticEvent<>) => {
ev.preventDefault(); ev.preventDefault();
const { collection } = this.props; const { collection } = this.props;
this.props.ui.setActiveModal('collection-delete', { collection }); this.props.ui.setActiveModal('collection-delete', { collection });
}; };
onExport = (ev: SyntheticEvent<*>) => { onExport = (ev: SyntheticEvent<>) => {
ev.preventDefault(); ev.preventDefault();
const { collection } = this.props; const { collection } = this.props;
this.props.ui.setActiveModal('collection-export', { collection }); this.props.ui.setActiveModal('collection-export', { collection });
}; };
onPermissions = (ev: SyntheticEvent<*>) => { onPermissions = (ev: SyntheticEvent<>) => {
ev.preventDefault(); ev.preventDefault();
this.permissionsModalOpen = true; this.permissionsModalOpen = true;
}; };

View File

@ -40,12 +40,12 @@ class DocumentMenu extends React.Component<Props> {
this.redirectTo = undefined; this.redirectTo = undefined;
} }
handleNewChild = (ev: SyntheticEvent<*>) => { handleNewChild = (ev: SyntheticEvent<>) => {
const { document } = this.props; const { document } = this.props;
this.redirectTo = newDocumentUrl(document.collectionId, document.id); this.redirectTo = newDocumentUrl(document.collectionId, document.id);
}; };
handleDelete = (ev: SyntheticEvent<*>) => { handleDelete = (ev: SyntheticEvent<>) => {
const { document } = this.props; const { document } = this.props;
this.props.ui.setActiveModal('document-delete', { document }); this.props.ui.setActiveModal('document-delete', { document });
}; };
@ -54,15 +54,15 @@ class DocumentMenu extends React.Component<Props> {
this.redirectTo = documentHistoryUrl(this.props.document); this.redirectTo = documentHistoryUrl(this.props.document);
}; };
handleMove = (ev: SyntheticEvent<*>) => { handleMove = (ev: SyntheticEvent<>) => {
this.redirectTo = documentMoveUrl(this.props.document); this.redirectTo = documentMoveUrl(this.props.document);
}; };
handleEdit = (ev: SyntheticEvent<*>) => { handleEdit = (ev: SyntheticEvent<>) => {
this.redirectTo = documentEditUrl(this.props.document); this.redirectTo = documentEditUrl(this.props.document);
}; };
handleDuplicate = async (ev: SyntheticEvent<*>) => { handleDuplicate = async (ev: SyntheticEvent<>) => {
const duped = await this.props.document.duplicate(); const duped = await this.props.document.duplicate();
// when duplicating, go straight to the duplicated document content // when duplicating, go straight to the duplicated document content
@ -70,37 +70,37 @@ class DocumentMenu extends React.Component<Props> {
this.props.ui.showToast('Document duplicated'); this.props.ui.showToast('Document duplicated');
}; };
handleArchive = async (ev: SyntheticEvent<*>) => { handleArchive = async (ev: SyntheticEvent<>) => {
await this.props.document.archive(); await this.props.document.archive();
this.props.ui.showToast('Document archived'); this.props.ui.showToast('Document archived');
}; };
handleRestore = async (ev: SyntheticEvent<*>) => { handleRestore = async (ev: SyntheticEvent<>) => {
await this.props.document.restore(); await this.props.document.restore();
this.props.ui.showToast('Document restored'); this.props.ui.showToast('Document restored');
}; };
handlePin = (ev: SyntheticEvent<*>) => { handlePin = (ev: SyntheticEvent<>) => {
this.props.document.pin(); this.props.document.pin();
}; };
handleUnpin = (ev: SyntheticEvent<*>) => { handleUnpin = (ev: SyntheticEvent<>) => {
this.props.document.unpin(); this.props.document.unpin();
}; };
handleStar = (ev: SyntheticEvent<*>) => { handleStar = (ev: SyntheticEvent<>) => {
this.props.document.star(); this.props.document.star();
}; };
handleUnstar = (ev: SyntheticEvent<*>) => { handleUnstar = (ev: SyntheticEvent<>) => {
this.props.document.unstar(); this.props.document.unstar();
}; };
handleExport = (ev: SyntheticEvent<*>) => { handleExport = (ev: SyntheticEvent<>) => {
this.props.document.download(); this.props.document.download();
}; };
handleShareLink = async (ev: SyntheticEvent<*>) => { handleShareLink = async (ev: SyntheticEvent<>) => {
const { document } = this.props; const { document } = this.props;
if (!document.shareUrl) await document.share(); if (!document.shareUrl) await document.share();

View File

@ -1,6 +1,6 @@
// @flow // @flow
import * as React from 'react'; import * as React from 'react';
import { withRouter } from 'react-router-dom'; import { withRouter, type RouterHistory } from 'react-router-dom';
import { inject } from 'mobx-react'; import { inject } from 'mobx-react';
import { MoreIcon } from 'outline-icons'; import { MoreIcon } from 'outline-icons';
@ -13,9 +13,9 @@ import UiStore from 'stores/UiStore';
type Props = { type Props = {
label?: React.Node, label?: React.Node,
onOpen?: () => *, onOpen?: () => void,
onClose: () => *, onClose: () => void,
history: Object, history: RouterHistory,
document: Document, document: Document,
revision: Revision, revision: Revision,
className?: string, className?: string,
@ -23,7 +23,7 @@ type Props = {
}; };
class RevisionMenu extends React.Component<Props> { class RevisionMenu extends React.Component<Props> {
handleRestore = async (ev: SyntheticEvent<*>) => { handleRestore = async (ev: SyntheticEvent<>) => {
ev.preventDefault(); ev.preventDefault();
await this.props.document.restore(this.props.revision); await this.props.document.restore(this.props.revision);
this.props.ui.showToast('Document restored'); this.props.ui.showToast('Document restored');

View File

@ -13,8 +13,8 @@ import Share from 'models/Share';
type Props = { type Props = {
label?: React.Node, label?: React.Node,
onOpen?: () => *, onOpen?: () => void,
onClose: () => *, onClose: () => void,
shares: SharesStore, shares: SharesStore,
ui: UiStore, ui: UiStore,
share: Share, share: Share,
@ -28,12 +28,12 @@ class ShareMenu extends React.Component<Props> {
this.redirectTo = undefined; this.redirectTo = undefined;
} }
handleGoToDocument = (ev: SyntheticEvent<*>) => { handleGoToDocument = (ev: SyntheticEvent<>) => {
ev.preventDefault(); ev.preventDefault();
this.redirectTo = this.props.share.documentUrl; this.redirectTo = this.props.share.documentUrl;
}; };
handleRevoke = (ev: SyntheticEvent<*>) => { handleRevoke = (ev: SyntheticEvent<>) => {
ev.preventDefault(); ev.preventDefault();
this.props.shares.revoke(this.props.share); this.props.shares.revoke(this.props.share);
this.props.ui.showToast('Share link revoked'); this.props.ui.showToast('Share link revoked');

View File

@ -14,7 +14,7 @@ type Props = {
@observer @observer
class UserMenu extends React.Component<Props> { class UserMenu extends React.Component<Props> {
handlePromote = (ev: SyntheticEvent<*>) => { handlePromote = (ev: SyntheticEvent<>) => {
ev.preventDefault(); ev.preventDefault();
const { user, users } = this.props; const { user, users } = this.props;
if ( if (
@ -29,7 +29,7 @@ class UserMenu extends React.Component<Props> {
users.promote(user); users.promote(user);
}; };
handleDemote = (ev: SyntheticEvent<*>) => { handleDemote = (ev: SyntheticEvent<>) => {
ev.preventDefault(); ev.preventDefault();
const { user, users } = this.props; const { user, users } = this.props;
if (!window.confirm(`Are you want to make ${user.name} a member?`)) { if (!window.confirm(`Are you want to make ${user.name} a member?`)) {
@ -38,7 +38,7 @@ class UserMenu extends React.Component<Props> {
users.demote(user); users.demote(user);
}; };
handleSuspend = (ev: SyntheticEvent<*>) => { handleSuspend = (ev: SyntheticEvent<>) => {
ev.preventDefault(); ev.preventDefault();
const { user, users } = this.props; const { user, users } = this.props;
if ( if (
@ -51,7 +51,7 @@ class UserMenu extends React.Component<Props> {
users.suspend(user); users.suspend(user);
}; };
handleActivate = (ev: SyntheticEvent<*>) => { handleActivate = (ev: SyntheticEvent<>) => {
ev.preventDefault(); ev.preventDefault();
const { user, users } = this.props; const { user, users } = this.props;
users.activate(user); users.activate(user);

View File

@ -7,13 +7,13 @@ import unescape from 'shared/utils/unescape';
import BaseModel from 'models/BaseModel'; import BaseModel from 'models/BaseModel';
import Revision from 'models/Revision'; import Revision from 'models/Revision';
import User from 'models/User'; import User from 'models/User';
import DocumentsStore from 'stores/DocumentsStore';
type SaveOptions = { publish?: boolean, done?: boolean, autosave?: boolean }; type SaveOptions = { publish?: boolean, done?: boolean, autosave?: boolean };
export default class Document extends BaseModel { export default class Document extends BaseModel {
isSaving: boolean; isSaving: boolean;
ui: *; store: DocumentsStore;
store: *;
collaborators: User[]; collaborators: User[];
collectionId: string; collectionId: string;
@ -37,7 +37,7 @@ export default class Document extends BaseModel {
shareUrl: ?string; shareUrl: ?string;
revision: number; revision: number;
constructor(data?: Object = {}, store: *) { constructor(data?: Object = {}, store: DocumentsStore) {
super(data, store); super(data, store);
this.updateTitle(); this.updateTitle();
} }
@ -54,7 +54,7 @@ export default class Document extends BaseModel {
@computed @computed
get isStarred(): boolean { get isStarred(): boolean {
return this.store.starredIds.get(this.id); return !!this.store.starredIds.get(this.id);
} }
@computed @computed
@ -90,7 +90,7 @@ export default class Document extends BaseModel {
return this.store.archive(this); return this.store.archive(this);
}; };
restore = (revision: ?Revision) => { restore = (revision: Revision) => {
return this.store.restore(this, revision); return this.store.restore(this, revision);
}; };

View File

@ -83,7 +83,7 @@ class CollectionScene extends React.Component<Props> {
this.isFetching = false; this.isFetching = false;
}; };
onNewDocument = (ev: SyntheticEvent<*>) => { onNewDocument = (ev: SyntheticEvent<>) => {
ev.preventDefault(); ev.preventDefault();
if (this.collection) { if (this.collection) {
@ -91,7 +91,7 @@ class CollectionScene extends React.Component<Props> {
} }
}; };
onPermissions = (ev: SyntheticEvent<*>) => { onPermissions = (ev: SyntheticEvent<>) => {
ev.preventDefault(); ev.preventDefault();
this.permissionsModalOpen = true; this.permissionsModalOpen = true;
}; };

View File

@ -1,6 +1,6 @@
// @flow // @flow
import * as React from 'react'; import * as React from 'react';
import { withRouter } from 'react-router-dom'; import { withRouter, type RouterHistory } from 'react-router-dom';
import { observable } from 'mobx'; import { observable } from 'mobx';
import { inject, observer } from 'mobx-react'; import { inject, observer } from 'mobx-react';
import { homeUrl } from 'utils/routeHelpers'; import { homeUrl } from 'utils/routeHelpers';
@ -12,7 +12,7 @@ import CollectionsStore from 'stores/CollectionsStore';
import UiStore from 'stores/UiStore'; import UiStore from 'stores/UiStore';
type Props = { type Props = {
history: Object, history: RouterHistory,
collection: Collection, collection: Collection,
collections: CollectionsStore, collections: CollectionsStore,
ui: UiStore, ui: UiStore,
@ -23,7 +23,7 @@ type Props = {
class CollectionDelete extends React.Component<Props> { class CollectionDelete extends React.Component<Props> {
@observable isDeleting: boolean; @observable isDeleting: boolean;
handleSubmit = async (ev: SyntheticEvent<*>) => { handleSubmit = async (ev: SyntheticEvent<>) => {
ev.preventDefault(); ev.preventDefault();
this.isDeleting = true; this.isDeleting = true;

View File

@ -1,6 +1,6 @@
// @flow // @flow
import * as React from 'react'; import * as React from 'react';
import { withRouter } from 'react-router-dom'; import { withRouter, type RouterHistory } from 'react-router-dom';
import { observable } from 'mobx'; import { observable } from 'mobx';
import { inject, observer } from 'mobx-react'; import { inject, observer } from 'mobx-react';
import Input from 'components/Input'; import Input from 'components/Input';
@ -13,7 +13,7 @@ import Collection from 'models/Collection';
import UiStore from 'stores/UiStore'; import UiStore from 'stores/UiStore';
type Props = { type Props = {
history: Object, history: RouterHistory,
collection: Collection, collection: Collection,
ui: UiStore, ui: UiStore,
onSubmit: () => void, onSubmit: () => void,
@ -31,7 +31,7 @@ class CollectionEdit extends React.Component<Props> {
this.description = this.props.collection.description; this.description = this.props.collection.description;
} }
handleSubmit = async (ev: SyntheticEvent<*>) => { handleSubmit = async (ev: SyntheticEvent<>) => {
ev.preventDefault(); ev.preventDefault();
this.isSaving = true; this.isSaving = true;

View File

@ -20,7 +20,7 @@ type Props = {
class CollectionExport extends React.Component<Props> { class CollectionExport extends React.Component<Props> {
@observable isLoading: boolean = false; @observable isLoading: boolean = false;
handleSubmit = async (ev: SyntheticEvent<*>) => { handleSubmit = async (ev: SyntheticEvent<>) => {
ev.preventDefault(); ev.preventDefault();
this.isLoading = true; this.isLoading = true;

View File

@ -1,6 +1,6 @@
// @flow // @flow
import * as React from 'react'; import * as React from 'react';
import { withRouter } from 'react-router-dom'; import { withRouter, type RouterHistory } from 'react-router-dom';
import { observable } from 'mobx'; import { observable } from 'mobx';
import { inject, observer } from 'mobx-react'; import { inject, observer } from 'mobx-react';
import Button from 'components/Button'; import Button from 'components/Button';
@ -15,7 +15,7 @@ import CollectionsStore from 'stores/CollectionsStore';
import UiStore from 'stores/UiStore'; import UiStore from 'stores/UiStore';
type Props = { type Props = {
history: Object, history: RouterHistory,
ui: UiStore, ui: UiStore,
collections: CollectionsStore, collections: CollectionsStore,
onSubmit: () => void, onSubmit: () => void,
@ -29,7 +29,7 @@ class CollectionNew extends React.Component<Props> {
@observable private: boolean = false; @observable private: boolean = false;
@observable isSaving: boolean; @observable isSaving: boolean;
handleSubmit = async (ev: SyntheticEvent<*>) => { handleSubmit = async (ev: SyntheticEvent<>) => {
ev.preventDefault(); ev.preventDefault();
this.isSaving = true; this.isSaving = true;
const collection = new Collection( const collection = new Collection(

View File

@ -12,7 +12,7 @@ import { DropdownMenu, DropdownMenuItem } from 'components/DropdownMenu';
type Props = { type Props = {
user: User, user: User,
showRemove: boolean, showRemove: boolean,
onRemove: () => *, onRemove: () => void,
}; };
const MemberListItem = ({ user, onRemove, showRemove }: Props) => { const MemberListItem = ({ user, onRemove, showRemove }: Props) => {

View File

@ -8,7 +8,7 @@ import User from 'models/User';
type Props = { type Props = {
user: User, user: User,
showAdd: boolean, showAdd: boolean,
onAdd: () => *, onAdd: () => void,
}; };
const UserListItem = ({ user, onAdd, showAdd }: Props) => { const UserListItem = ({ user, onAdd, showAdd }: Props) => {

View File

@ -6,7 +6,7 @@ import breakpoint from 'styled-components-breakpoint';
import { observable } from 'mobx'; import { observable } from 'mobx';
import { observer, inject } from 'mobx-react'; import { observer, inject } from 'mobx-react';
import { Prompt, Route, withRouter } from 'react-router-dom'; import { Prompt, Route, withRouter } from 'react-router-dom';
import type { Location } from 'react-router-dom'; import type { Location, RouterHistory } from 'react-router-dom';
import keydown from 'react-keydown'; import keydown from 'react-keydown';
import Flex from 'shared/components/Flex'; import Flex from 'shared/components/Flex';
import { import {
@ -59,7 +59,7 @@ Are you sure you want to discard them?
type Props = { type Props = {
match: Object, match: Object,
history: Object, history: RouterHistory,
location: Location, location: Location,
documents: DocumentsStore, documents: DocumentsStore,
revisions: RevisionsStore, revisions: RevisionsStore,

View File

@ -10,7 +10,6 @@ type Props = {
document: Document, document: Document,
anchor: string, anchor: string,
showCollection?: boolean, showCollection?: boolean,
ref?: *,
}; };
const DocumentLink = styled(Link)` const DocumentLink = styled(Link)`

View File

@ -26,12 +26,12 @@ type Props = {
documents: DocumentsStore, documents: DocumentsStore,
collections: CollectionsStore, collections: CollectionsStore,
ui: UiStore, ui: UiStore,
onRequestClose: *, onRequestClose: () => void,
}; };
@observer @observer
class DocumentMove extends React.Component<Props> { class DocumentMove extends React.Component<Props> {
firstDocument: *; firstDocument: ?PathToDocument;
@observable searchTerm: ?string; @observable searchTerm: ?string;
@observable isSaving: boolean; @observable isSaving: boolean;

View File

@ -10,7 +10,7 @@ type Props = {
}; };
class DocumentEditor extends React.Component<Props> { class DocumentEditor extends React.Component<Props> {
editor: *; editor: ?Editor;
componentDidMount() { componentDidMount() {
if (!this.props.defaultValue) { if (!this.props.defaultValue) {

View File

@ -32,12 +32,12 @@ type Props = {
isPublishing: boolean, isPublishing: boolean,
publishingIsDisabled: boolean, publishingIsDisabled: boolean,
savingIsDisabled: boolean, savingIsDisabled: boolean,
onDiscard: () => *, onDiscard: () => void,
onSave: ({ onSave: ({
done?: boolean, done?: boolean,
publish?: boolean, publish?: boolean,
autosave?: boolean, autosave?: boolean,
}) => *, }) => void,
auth: AuthStore, auth: AuthStore,
}; };
@ -73,7 +73,7 @@ class Header extends React.Component<Props> {
this.props.onSave({ done: true, publish: true }); this.props.onSave({ done: true, publish: true });
}; };
handleShareLink = async (ev: SyntheticEvent<*>) => { handleShareLink = async (ev: SyntheticEvent<>) => {
const { document } = this.props; const { document } = this.props;
if (!document.shareUrl) await document.share(); if (!document.shareUrl) await document.share();
this.showShareModal = true; this.showShareModal = true;

View File

@ -1,6 +1,6 @@
// @flow // @flow
import * as React from 'react'; import * as React from 'react';
import { withRouter } from 'react-router-dom'; import { withRouter, type RouterHistory } from 'react-router-dom';
import { observable } from 'mobx'; import { observable } from 'mobx';
import { inject, observer } from 'mobx-react'; import { inject, observer } from 'mobx-react';
import Button from 'components/Button'; import Button from 'components/Button';
@ -12,7 +12,7 @@ import UiStore from 'stores/UiStore';
import { collectionUrl } from 'utils/routeHelpers'; import { collectionUrl } from 'utils/routeHelpers';
type Props = { type Props = {
history: Object, history: RouterHistory,
document: Document, document: Document,
documents: DocumentsStore, documents: DocumentsStore,
ui: UiStore, ui: UiStore,
@ -23,7 +23,7 @@ type Props = {
class DocumentDelete extends React.Component<Props> { class DocumentDelete extends React.Component<Props> {
@observable isDeleting: boolean; @observable isDeleting: boolean;
handleSubmit = async (ev: SyntheticEvent<*>) => { handleSubmit = async (ev: SyntheticEvent<>) => {
ev.preventDefault(); ev.preventDefault();
this.isDeleting = true; this.isDeleting = true;

View File

@ -11,7 +11,7 @@ import Document from 'models/Document';
type Props = { type Props = {
document?: Document, document?: Document,
onSubmit: () => *, onSubmit: () => void,
}; };
@observer @observer

View File

@ -1,6 +1,6 @@
// @flow // @flow
import * as React from 'react'; import * as React from 'react';
import { withRouter } from 'react-router-dom'; import { withRouter, type RouterHistory } from 'react-router-dom';
import { observable } from 'mobx'; import { observable } from 'mobx';
import { inject, observer } from 'mobx-react'; import { inject, observer } from 'mobx-react';
import { CloseIcon } from 'outline-icons'; import { CloseIcon } from 'outline-icons';
@ -21,7 +21,7 @@ const MAX_INVITES = 20;
type Props = { type Props = {
auth: AuthStore, auth: AuthStore,
users: UsersStore, users: UsersStore,
history: Object, history: RouterHistory,
ui: UiStore, ui: UiStore,
onSubmit: () => void, onSubmit: () => void,
}; };
@ -37,7 +37,7 @@ class Invite extends React.Component<Props> {
{ email: '', name: '' }, { email: '', name: '' },
]; ];
handleSubmit = async (ev: SyntheticEvent<*>) => { handleSubmit = async (ev: SyntheticEvent<>) => {
ev.preventDefault(); ev.preventDefault();
this.isSaving = true; this.isSaving = true;

View File

@ -4,6 +4,7 @@ import ReactDOM from 'react-dom';
import keydown from 'react-keydown'; import keydown from 'react-keydown';
import Waypoint from 'react-waypoint'; import Waypoint from 'react-waypoint';
import { withRouter, Link } from 'react-router-dom'; import { withRouter, Link } from 'react-router-dom';
import type { Location, RouterHistory } from 'react-router-dom';
import { observable, action } from 'mobx'; import { observable, action } from 'mobx';
import { observer, inject } from 'mobx-react'; import { observer, inject } from 'mobx-react';
import { debounce } from 'lodash'; import { debounce } from 'lodash';
@ -32,9 +33,9 @@ import UserFilter from './components/UserFilter';
import DateFilter from './components/DateFilter'; import DateFilter from './components/DateFilter';
type Props = { type Props = {
history: Object, history: RouterHistory,
match: Object, match: Object,
location: Object, location: Location,
documents: DocumentsStore, documents: DocumentsStore,
users: UsersStore, users: UsersStore,
notFound: ?boolean, notFound: ?boolean,

View File

@ -5,18 +5,18 @@ import { SearchIcon } from 'outline-icons';
import Flex from 'shared/components/Flex'; import Flex from 'shared/components/Flex';
type Props = { type Props = {
onChange: string => *, onChange: string => void,
theme: Object, theme: Object,
}; };
class SearchField extends React.Component<Props> { class SearchField extends React.Component<Props> {
input: ?HTMLInputElement; input: ?HTMLInputElement;
handleChange = (ev: SyntheticEvent<*>) => { handleChange = (ev: SyntheticEvent<HTMLInputElement>) => {
this.props.onChange(ev.currentTarget.value ? ev.currentTarget.value : ''); this.props.onChange(ev.currentTarget.value ? ev.currentTarget.value : '');
}; };
focusInput = (ev: SyntheticEvent<*>) => { focusInput = (ev: SyntheticEvent<>) => {
if (this.input) this.input.focus(); if (this.input) this.input.focus();
}; };

View File

@ -40,7 +40,7 @@ class Details extends React.Component<Props> {
clearTimeout(this.timeout); clearTimeout(this.timeout);
} }
handleSubmit = async (ev: SyntheticEvent<*>) => { handleSubmit = async (ev: SyntheticEvent<>) => {
ev.preventDefault(); ev.preventDefault();
try { try {

View File

@ -22,7 +22,7 @@ class Export extends React.Component<Props> {
@observable isLoading: boolean = false; @observable isLoading: boolean = false;
@observable isExporting: boolean = false; @observable isExporting: boolean = false;
handleSubmit = async (ev: SyntheticEvent<*>) => { handleSubmit = async (ev: SyntheticEvent<>) => {
ev.preventDefault(); ev.preventDefault();
this.isLoading = true; this.isLoading = true;

View File

@ -59,7 +59,7 @@ class Notifications extends React.Component<Props> {
this.props.notificationSettings.fetchPage(); this.props.notificationSettings.fetchPage();
} }
handleChange = async (ev: SyntheticInputEvent<*>) => { handleChange = async (ev: SyntheticInputEvent<>) => {
const { notificationSettings } = this.props; const { notificationSettings } = this.props;
const setting = notificationSettings.getByEvent(ev.target.name); const setting = notificationSettings.getByEvent(ev.target.name);

View File

@ -38,7 +38,7 @@ class Profile extends React.Component<Props> {
clearTimeout(this.timeout); clearTimeout(this.timeout);
} }
handleSubmit = async (ev: SyntheticEvent<*>) => { handleSubmit = async (ev: SyntheticEvent<>) => {
ev.preventDefault(); ev.preventDefault();
await this.props.auth.updateUser({ await this.props.auth.updateUser({

View File

@ -28,7 +28,7 @@ class Tokens extends React.Component<Props> {
this.name = ev.target.value; this.name = ev.target.value;
}; };
handleSubmit = async (ev: SyntheticEvent<*>) => { handleSubmit = async (ev: SyntheticEvent<>) => {
ev.preventDefault(); ev.preventDefault();
await this.props.apiKeys.create({ name: this.name }); await this.props.apiKeys.create({ name: this.name });
this.name = ''; this.name = '';

View File

@ -4,7 +4,6 @@ import { observable } from 'mobx';
import { observer } from 'mobx-react'; import { observer } from 'mobx-react';
import styled from 'styled-components'; import styled from 'styled-components';
import Dropzone from 'react-dropzone'; import Dropzone from 'react-dropzone';
import LoadingIndicator from 'components/LoadingIndicator'; import LoadingIndicator from 'components/LoadingIndicator';
import Flex from 'shared/components/Flex'; import Flex from 'shared/components/Flex';
import Modal from 'components/Modal'; import Modal from 'components/Modal';
@ -14,8 +13,8 @@ import { uploadFile, dataUrlToBlob } from 'utils/uploadFile';
type Props = { type Props = {
children?: React.Node, children?: React.Node,
onSuccess: string => *, onSuccess: string => void | Promise<void>,
onError: string => *, onError: string => void,
submitText: string, submitText: string,
borderRadius: number, borderRadius: number,
}; };

View File

@ -9,7 +9,7 @@ type Props = {
event: string, event: string,
description: string, description: string,
disabled: boolean, disabled: boolean,
onChange: *, onChange: (ev: SyntheticInputEvent<>) => void | Promise<void>,
}; };
const NotificationListItem = ({ const NotificationListItem = ({

View File

@ -6,7 +6,7 @@ import ApiKey from 'models/ApiKey';
type Props = { type Props = {
token: ApiKey, token: ApiKey,
onDelete: (tokenId: string) => *, onDelete: (tokenId: string) => void,
}; };
const TokenListItem = ({ token, onDelete }: Props) => { const TokenListItem = ({ token, onDelete }: Props) => {

View File

@ -10,14 +10,14 @@ import AuthStore from 'stores/AuthStore';
type Props = { type Props = {
auth: AuthStore, auth: AuthStore,
onRequestClose: () => *, onRequestClose: () => void,
}; };
@observer @observer
class UserDelete extends React.Component<Props> { class UserDelete extends React.Component<Props> {
@observable isDeleting: boolean; @observable isDeleting: boolean;
handleSubmit = async (ev: SyntheticEvent<*>) => { handleSubmit = async (ev: SyntheticEvent<>) => {
ev.preventDefault(); ev.preventDefault();
this.isDeleting = true; this.isDeleting = true;

View File

@ -3,7 +3,7 @@ import * as React from 'react';
import styled from 'styled-components'; import styled from 'styled-components';
import distanceInWordsToNow from 'date-fns/distance_in_words_to_now'; import distanceInWordsToNow from 'date-fns/distance_in_words_to_now';
import { inject, observer } from 'mobx-react'; import { inject, observer } from 'mobx-react';
import { withRouter } from 'react-router-dom'; import { withRouter, type RouterHistory } from 'react-router-dom';
import { EditIcon } from 'outline-icons'; import { EditIcon } from 'outline-icons';
import Flex from 'shared/components/Flex'; import Flex from 'shared/components/Flex';
import HelpText from 'components/HelpText'; import HelpText from 'components/HelpText';
@ -22,8 +22,8 @@ type Props = {
user: User, user: User,
auth: AuthStore, auth: AuthStore,
documents: DocumentsStore, documents: DocumentsStore,
history: Object, history: RouterHistory,
onRequestClose: () => *, onRequestClose: () => void,
}; };
@observer @observer

View File

@ -49,7 +49,7 @@ export default class DocumentsStore extends BaseStore<Document> {
return orderBy(this.all, 'updatedAt', 'desc'); return orderBy(this.all, 'updatedAt', 'desc');
} }
createdByUser(userId: string): * { createdByUser(userId: string): Document[] {
return orderBy( return orderBy(
filter(this.all, d => d.createdBy.id === userId), filter(this.all, d => d.createdBy.id === userId),
'updatedAt', 'updatedAt',
@ -387,7 +387,12 @@ export default class DocumentsStore extends BaseStore<Document> {
} }
@action @action
async update(params: *) { async update(params: {
id: string,
title: string,
text: string,
lastRevision: number,
}) {
const document = await super.update(params); const document = await super.update(params);
// Because the collection object contains the url and title // Because the collection object contains the url and title

View File

@ -1,5 +1,5 @@
// @flow // @flow
export default function getDataTransferFiles(event: SyntheticEvent<*>): File[] { export default function getDataTransferFiles(event: SyntheticEvent<>): File[] {
let dataTransferItemsList = []; let dataTransferItemsList = [];
// $FlowFixMe // $FlowFixMe

View File

@ -1,9 +1,10 @@
// @flow // @flow
import Document from '../models/Document'; import Document from 'models/Document';
import DocumentsStore from 'stores/DocumentsStore';
type Options = { type Options = {
file: File, file: File,
documents: *, documents: DocumentsStore,
collectionId: string, collectionId: string,
documentId?: string, documentId?: string,
}; };

View File

@ -1,11 +1,36 @@
// @flow // @flow
import { sortBy } from 'lodash'; import { deburr } from 'lodash';
import naturalSort from 'natural-sort'; import naturalSort from 'natural-sort';
export default (sortableArray: *, key: string): * => { type NaturalSortOptions = {
if (!sortableArray) return []; caseSensitive?: boolean,
direction?: 'asc' | 'desc',
let keys = sortableArray.map(object => object[key]);
keys.sort(naturalSort());
return sortBy(sortableArray, object => keys.indexOf(object[key]));
}; };
const sorter = naturalSort();
function getSortByField<T: Object>(
item: T,
keyOrCallback: string | (T => string)
) {
if (typeof keyOrCallback === 'string') {
return deburr(item[keyOrCallback]);
}
return keyOrCallback(item);
}
function naturalSortBy<T>(
items: T[],
key: string | (T => string),
sortOptions?: NaturalSortOptions
): T[] {
if (!items) return [];
const sort = sortOptions ? naturalSort(sortOptions) : sorter;
return items.sort((a: any, b: any): -1 | 0 | 1 =>
sort(getSortByField(a, key), getSortByField(b, key))
);
}
export default naturalSortBy;