chore: Move to prettier standard double quotes (#1309)
This commit is contained in:
23
.eslintrc
23
.eslintrc
@ -6,7 +6,10 @@
|
|||||||
"plugin:import/warnings",
|
"plugin:import/warnings",
|
||||||
"plugin:flowtype/recommended"
|
"plugin:flowtype/recommended"
|
||||||
],
|
],
|
||||||
"plugins": ["prettier", "flowtype"],
|
"plugins": [
|
||||||
|
"prettier",
|
||||||
|
"flowtype"
|
||||||
|
],
|
||||||
"rules": {
|
"rules": {
|
||||||
"eqeqeq": 2,
|
"eqeqeq": 2,
|
||||||
"no-unused-vars": 2,
|
"no-unused-vars": 2,
|
||||||
@ -18,14 +21,19 @@
|
|||||||
"annotationStyle": "line"
|
"annotationStyle": "line"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"flowtype/space-after-type-colon": [2, "always"],
|
"flowtype/space-after-type-colon": [
|
||||||
"flowtype/space-before-type-colon": [2, "never"],
|
2,
|
||||||
|
"always"
|
||||||
|
],
|
||||||
|
"flowtype/space-before-type-colon": [
|
||||||
|
2,
|
||||||
|
"never"
|
||||||
|
],
|
||||||
"prettier/prettier": [
|
"prettier/prettier": [
|
||||||
"error",
|
"error",
|
||||||
{
|
{
|
||||||
"printWidth": 80,
|
"printWidth": 80,
|
||||||
"trailingComma": "es5",
|
"trailingComma": "es5"
|
||||||
"singleQuote": true
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@ -38,7 +46,10 @@
|
|||||||
},
|
},
|
||||||
"import/resolver": {
|
"import/resolver": {
|
||||||
"node": {
|
"node": {
|
||||||
"paths": ["app", "."]
|
"paths": [
|
||||||
|
"app",
|
||||||
|
"."
|
||||||
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"flowtype": {
|
"flowtype": {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import styled from 'styled-components';
|
import styled from "styled-components";
|
||||||
import breakpoint from 'styled-components-breakpoint';
|
import breakpoint from "styled-components-breakpoint";
|
||||||
import Flex from 'shared/components/Flex';
|
import Flex from "shared/components/Flex";
|
||||||
|
|
||||||
export const Action = styled(Flex)`
|
export const Action = styled(Flex)`
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
@ -40,7 +40,7 @@ const Actions = styled(Flex)`
|
|||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
${breakpoint('tablet')`
|
${breakpoint("tablet")`
|
||||||
left: auto;
|
left: auto;
|
||||||
padding: 24px;
|
padding: 24px;
|
||||||
`};
|
`};
|
||||||
|
@ -1,18 +1,18 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import * as React from 'react';
|
import * as React from "react";
|
||||||
import { observer } from 'mobx-react';
|
import { observer } from "mobx-react";
|
||||||
import Flex from 'shared/components/Flex';
|
import Flex from "shared/components/Flex";
|
||||||
import styled from 'styled-components';
|
import styled from "styled-components";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
children: React.Node,
|
children: React.Node,
|
||||||
type?: 'info' | 'success' | 'warning' | 'danger' | 'offline',
|
type?: "info" | "success" | "warning" | "danger" | "offline",
|
||||||
};
|
};
|
||||||
|
|
||||||
@observer
|
@observer
|
||||||
class Alert extends React.Component<Props> {
|
class Alert extends React.Component<Props> {
|
||||||
defaultProps = {
|
defaultProps = {
|
||||||
type: 'info',
|
type: "info",
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
// @flow
|
// @flow
|
||||||
/* global ga */
|
/* global ga */
|
||||||
import * as React from 'react';
|
import * as React from "react";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
children?: React.Node,
|
children?: React.Node,
|
||||||
@ -20,12 +20,12 @@ export default class Analytics extends React.Component<Props> {
|
|||||||
|
|
||||||
// $FlowIssue
|
// $FlowIssue
|
||||||
ga.l = +new Date();
|
ga.l = +new Date();
|
||||||
ga('create', process.env.GOOGLE_ANALYTICS_ID, 'auto');
|
ga("create", process.env.GOOGLE_ANALYTICS_ID, "auto");
|
||||||
ga('set', { dimension1: 'true' });
|
ga("set", { dimension1: "true" });
|
||||||
ga('send', 'pageview');
|
ga("send", "pageview");
|
||||||
|
|
||||||
const script = document.createElement('script');
|
const script = document.createElement("script");
|
||||||
script.src = 'https://www.google-analytics.com/analytics.js';
|
script.src = "https://www.google-analytics.com/analytics.js";
|
||||||
script.async = true;
|
script.async = true;
|
||||||
|
|
||||||
if (document.body) {
|
if (document.body) {
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
// @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 AuthStore from 'stores/AuthStore';
|
import AuthStore from "stores/AuthStore";
|
||||||
import LoadingIndicator from 'components/LoadingIndicator';
|
import LoadingIndicator from "components/LoadingIndicator";
|
||||||
import { isCustomSubdomain } from 'shared/utils/domains';
|
import { isCustomSubdomain } from "shared/utils/domains";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
auth: AuthStore,
|
auth: AuthStore,
|
||||||
@ -38,4 +38,4 @@ const Authenticated = observer(({ auth, children }: Props) => {
|
|||||||
return null;
|
return null;
|
||||||
});
|
});
|
||||||
|
|
||||||
export default inject('auth')(Authenticated);
|
export default inject("auth")(Authenticated);
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import * as React from 'react';
|
import * as React from "react";
|
||||||
import styled from 'styled-components';
|
import styled from "styled-components";
|
||||||
import { observable } from 'mobx';
|
import { observable } from "mobx";
|
||||||
import { observer } from 'mobx-react';
|
import { observer } from "mobx-react";
|
||||||
import placeholder from './placeholder.png';
|
import placeholder from "./placeholder.png";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
src: string,
|
src: string,
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import * as React from 'react';
|
import * as React from "react";
|
||||||
import { observable } from 'mobx';
|
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 distanceInWordsToNow from 'date-fns/distance_in_words_to_now';
|
import distanceInWordsToNow from "date-fns/distance_in_words_to_now";
|
||||||
import Avatar from 'components/Avatar';
|
import Avatar from "components/Avatar";
|
||||||
import Tooltip from 'components/Tooltip';
|
import Tooltip from "components/Tooltip";
|
||||||
import User from 'models/User';
|
import User from "models/User";
|
||||||
import UserProfile from 'scenes/UserProfile';
|
import UserProfile from "scenes/UserProfile";
|
||||||
import { EditIcon } from 'outline-icons';
|
import { EditIcon } from "outline-icons";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
user: User,
|
user: User,
|
||||||
@ -44,10 +44,10 @@ class AvatarWithPresence extends React.Component<Props> {
|
|||||||
<Tooltip
|
<Tooltip
|
||||||
tooltip={
|
tooltip={
|
||||||
<Centered>
|
<Centered>
|
||||||
<strong>{user.name}</strong> {isCurrentUser && '(You)'}
|
<strong>{user.name}</strong> {isCurrentUser && "(You)"}
|
||||||
<br />
|
<br />
|
||||||
{isPresent
|
{isPresent
|
||||||
? isEditing ? 'currently editing' : 'currently viewing'
|
? isEditing ? "currently editing" : "currently viewing"
|
||||||
: `viewed ${distanceInWordsToNow(new Date(lastViewedAt))} ago`}
|
: `viewed ${distanceInWordsToNow(new Date(lastViewedAt))} ago`}
|
||||||
</Centered>
|
</Centered>
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import Avatar from './Avatar';
|
import Avatar from "./Avatar";
|
||||||
import AvatarWithPresence from './AvatarWithPresence';
|
import AvatarWithPresence from "./AvatarWithPresence";
|
||||||
|
|
||||||
export { AvatarWithPresence };
|
export { AvatarWithPresence };
|
||||||
export default Avatar;
|
export default Avatar;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import styled from 'styled-components';
|
import styled from "styled-components";
|
||||||
|
|
||||||
const Badge = styled.span`
|
const Badge = styled.span`
|
||||||
margin-left: 10px;
|
margin-left: 10px;
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import * as React from 'react';
|
import * as React from "react";
|
||||||
import styled from 'styled-components';
|
import styled from "styled-components";
|
||||||
import { darken, lighten } from 'polished';
|
import { darken, lighten } from "polished";
|
||||||
import { ExpandedIcon } from 'outline-icons';
|
import { ExpandedIcon } from "outline-icons";
|
||||||
|
|
||||||
const RealButton = styled.button`
|
const RealButton = styled.button`
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
@ -54,10 +54,10 @@ const RealButton = styled.button`
|
|||||||
background: ${props.theme.buttonNeutralBackground};
|
background: ${props.theme.buttonNeutralBackground};
|
||||||
color: ${props.theme.buttonNeutralText};
|
color: ${props.theme.buttonNeutralText};
|
||||||
box-shadow: ${
|
box-shadow: ${
|
||||||
props.borderOnHover ? 'none' : 'rgba(0, 0, 0, 0.07) 0px 1px 2px'
|
props.borderOnHover ? "none" : "rgba(0, 0, 0, 0.07) 0px 1px 2px"
|
||||||
};
|
};
|
||||||
border: 1px solid ${
|
border: 1px solid ${
|
||||||
props.borderOnHover ? 'transparent' : props.theme.buttonNeutralBorder
|
props.borderOnHover ? "transparent" : props.theme.buttonNeutralBorder
|
||||||
};
|
};
|
||||||
|
|
||||||
svg {
|
svg {
|
||||||
@ -102,7 +102,7 @@ const Label = styled.span`
|
|||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
|
|
||||||
${props => props.hasIcon && 'padding-left: 4px;'};
|
${props => props.hasIcon && "padding-left: 4px;"};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const Inner = styled.span`
|
export const Inner = styled.span`
|
||||||
@ -113,8 +113,8 @@ export const Inner = styled.span`
|
|||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
||||||
${props => props.hasIcon && props.hasText && 'padding-left: 4px;'};
|
${props => props.hasIcon && props.hasText && "padding-left: 4px;"};
|
||||||
${props => props.hasIcon && !props.hasText && 'padding: 0 4px;'};
|
${props => props.hasIcon && !props.hasText && "padding: 0 4px;"};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export type Props = {
|
export type Props = {
|
||||||
@ -130,7 +130,7 @@ export type Props = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
function Button({
|
function Button({
|
||||||
type = 'text',
|
type = "text",
|
||||||
icon,
|
icon,
|
||||||
children,
|
children,
|
||||||
value,
|
value,
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import * as React from 'react';
|
import * as React from "react";
|
||||||
import styled from 'styled-components';
|
import styled from "styled-components";
|
||||||
import breakpoint from 'styled-components-breakpoint';
|
import breakpoint from "styled-components-breakpoint";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
children?: React.Node,
|
children?: React.Node,
|
||||||
@ -11,7 +11,7 @@ const Container = styled.div`
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
padding: 60px 20px;
|
padding: 60px 20px;
|
||||||
|
|
||||||
${breakpoint('tablet')`
|
${breakpoint("tablet")`
|
||||||
padding: 60px;
|
padding: 60px;
|
||||||
`};
|
`};
|
||||||
`;
|
`;
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import * as React from 'react';
|
import * as React from "react";
|
||||||
import styled from 'styled-components';
|
import styled from "styled-components";
|
||||||
import HelpText from 'components/HelpText';
|
import HelpText from "components/HelpText";
|
||||||
import VisuallyHidden from 'components/VisuallyHidden';
|
import VisuallyHidden from "components/VisuallyHidden";
|
||||||
|
|
||||||
export type Props = {
|
export type Props = {
|
||||||
checked?: boolean,
|
checked?: boolean,
|
||||||
@ -15,13 +15,13 @@ export type Props = {
|
|||||||
|
|
||||||
const LabelText = styled.span`
|
const LabelText = styled.span`
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
margin-left: ${props => (props.small ? '6px' : '10px')};
|
margin-left: ${props => (props.small ? "6px" : "10px")};
|
||||||
${props => (props.small ? `color: ${props.theme.textSecondary}` : '')};
|
${props => (props.small ? `color: ${props.theme.textSecondary}` : "")};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const Wrapper = styled.div`
|
const Wrapper = styled.div`
|
||||||
padding-bottom: 8px;
|
padding-bottom: 8px;
|
||||||
${props => (props.small ? 'font-size: 14px' : '')};
|
${props => (props.small ? "font-size: 14px" : "")};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const Label = styled.label`
|
const Label = styled.label`
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import styled from 'styled-components';
|
import styled from "styled-components";
|
||||||
|
|
||||||
const ClickablePadding = styled.div`
|
const ClickablePadding = styled.div`
|
||||||
min-height: 10em;
|
min-height: 10em;
|
||||||
cursor: ${({ onClick }) => (onClick ? 'text' : 'default')};
|
cursor: ${({ onClick }) => (onClick ? "text" : "default")};
|
||||||
${({ grow }) => grow && `flex-grow: 100;`};
|
${({ grow }) => grow && `flex-grow: 100;`};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
// @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 { sortBy, keyBy } from 'lodash';
|
import { sortBy, keyBy } from "lodash";
|
||||||
import { MAX_AVATAR_DISPLAY } from 'shared/constants';
|
import { MAX_AVATAR_DISPLAY } from "shared/constants";
|
||||||
|
|
||||||
import { AvatarWithPresence } from 'components/Avatar';
|
import { AvatarWithPresence } from "components/Avatar";
|
||||||
import Facepile from 'components/Facepile';
|
import Facepile from "components/Facepile";
|
||||||
import Document from 'models/Document';
|
import Document from "models/Document";
|
||||||
import ViewsStore from 'stores/ViewsStore';
|
import ViewsStore from "stores/ViewsStore";
|
||||||
import DocumentPresenceStore from 'stores/DocumentPresenceStore';
|
import DocumentPresenceStore from "stores/DocumentPresenceStore";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
views: ViewsStore,
|
views: ViewsStore,
|
||||||
@ -73,4 +73,4 @@ class Collaborators extends React.Component<Props> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default inject('views', 'presence')(Collaborators);
|
export default inject("views", "presence")(Collaborators);
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
// @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 { getLuminance } from 'polished';
|
import { getLuminance } from "polished";
|
||||||
import { PrivateCollectionIcon, CollectionIcon } from 'outline-icons';
|
import { PrivateCollectionIcon, CollectionIcon } from "outline-icons";
|
||||||
import Collection from 'models/Collection';
|
import Collection from "models/Collection";
|
||||||
import { icons } from 'components/IconPicker';
|
import { icons } from "components/IconPicker";
|
||||||
import UiStore from 'stores/UiStore';
|
import UiStore from "stores/UiStore";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
collection: Collection,
|
collection: Collection,
|
||||||
@ -18,18 +18,18 @@ function ResolvedCollectionIcon({ collection, expanded, size, ui }: Props) {
|
|||||||
// If the chosen icon color is very dark then we invert it in dark mode
|
// If the chosen icon color is very dark then we invert it in dark mode
|
||||||
// otherwise it will be impossible to see against the dark background.
|
// otherwise it will be impossible to see against the dark background.
|
||||||
const color =
|
const color =
|
||||||
ui.resolvedTheme === 'dark'
|
ui.resolvedTheme === "dark"
|
||||||
? getLuminance(collection.color) > 0.12
|
? getLuminance(collection.color) > 0.12
|
||||||
? collection.color
|
? collection.color
|
||||||
: 'currentColor'
|
: "currentColor"
|
||||||
: collection.color;
|
: collection.color;
|
||||||
|
|
||||||
if (collection.icon && collection.icon !== 'collection') {
|
if (collection.icon && collection.icon !== "collection") {
|
||||||
try {
|
try {
|
||||||
const Component = icons[collection.icon].component;
|
const Component = icons[collection.icon].component;
|
||||||
return <Component color={color} size={size} />;
|
return <Component color={color} size={size} />;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.warn('Failed to render custom icon ' + collection.icon);
|
console.warn("Failed to render custom icon " + collection.icon);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -42,4 +42,4 @@ function ResolvedCollectionIcon({ collection, expanded, size, ui }: Props) {
|
|||||||
return <CollectionIcon color={color} expanded={expanded} size={size} />;
|
return <CollectionIcon color={color} expanded={expanded} size={size} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default inject('ui')(observer(ResolvedCollectionIcon));
|
export default inject("ui")(observer(ResolvedCollectionIcon));
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import * as React from 'react';
|
import * as React from "react";
|
||||||
import copy from 'copy-to-clipboard';
|
import copy from "copy-to-clipboard";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
text: string,
|
text: string,
|
||||||
@ -19,7 +19,7 @@ class CopyToClipboard extends React.PureComponent<Props> {
|
|||||||
|
|
||||||
if (onCopy) onCopy();
|
if (onCopy) onCopy();
|
||||||
|
|
||||||
if (elem && elem.props && typeof elem.props.onClick === 'function') {
|
if (elem && elem.props && typeof elem.props.onClick === "function") {
|
||||||
elem.props.onClick(ev);
|
elem.props.onClick(ev);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -1,20 +1,20 @@
|
|||||||
// @flow
|
// @flow
|
||||||
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 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";
|
||||||
|
|
||||||
import { DEFAULT_PAGINATION_LIMIT } from 'stores/BaseStore';
|
import { DEFAULT_PAGINATION_LIMIT } from "stores/BaseStore";
|
||||||
import DocumentsStore from 'stores/DocumentsStore';
|
import DocumentsStore from "stores/DocumentsStore";
|
||||||
import RevisionsStore from 'stores/RevisionsStore';
|
import RevisionsStore from "stores/RevisionsStore";
|
||||||
|
|
||||||
import Flex from 'shared/components/Flex';
|
import Flex from "shared/components/Flex";
|
||||||
import { ListPlaceholder } from 'components/LoadingPlaceholder';
|
import { ListPlaceholder } from "components/LoadingPlaceholder";
|
||||||
import Revision from './components/Revision';
|
import Revision from "./components/Revision";
|
||||||
import { documentHistoryUrl } from 'utils/routeHelpers';
|
import { documentHistoryUrl } from "utils/routeHelpers";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
match: Object,
|
match: Object,
|
||||||
@ -146,4 +146,4 @@ const Sidebar = styled(Flex)`
|
|||||||
z-index: 1;
|
z-index: 1;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export default inject('documents', 'revisions')(DocumentHistory);
|
export default inject("documents", "revisions")(DocumentHistory);
|
||||||
|
@ -1,18 +1,18 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import * as React from 'react';
|
import * as React from "react";
|
||||||
import { NavLink } from 'react-router-dom';
|
import { NavLink } from "react-router-dom";
|
||||||
import styled, { withTheme } from 'styled-components';
|
import styled, { withTheme } from "styled-components";
|
||||||
import format from 'date-fns/format';
|
import format from "date-fns/format";
|
||||||
import { MoreIcon } from 'outline-icons';
|
import { MoreIcon } from "outline-icons";
|
||||||
|
|
||||||
import Flex from 'shared/components/Flex';
|
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 Document from "models/Document";
|
||||||
import Revision from 'models/Revision';
|
import Revision from "models/Revision";
|
||||||
|
|
||||||
import { documentHistoryUrl } from 'utils/routeHelpers';
|
import { documentHistoryUrl } from "utils/routeHelpers";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
theme: Object,
|
theme: Object,
|
||||||
@ -32,12 +32,12 @@ class RevisionListItem extends React.Component<Props> {
|
|||||||
activeStyle={{ background: theme.primary, color: theme.white }}
|
activeStyle={{ background: theme.primary, color: theme.white }}
|
||||||
>
|
>
|
||||||
<Author>
|
<Author>
|
||||||
<StyledAvatar src={revision.createdBy.avatarUrl} />{' '}
|
<StyledAvatar src={revision.createdBy.avatarUrl} />{" "}
|
||||||
{revision.createdBy.name}
|
{revision.createdBy.name}
|
||||||
</Author>
|
</Author>
|
||||||
<Meta>
|
<Meta>
|
||||||
<Time dateTime={revision.createdAt}>
|
<Time dateTime={revision.createdAt}>
|
||||||
{format(revision.createdAt, 'MMMM Do, YYYY h:mm a')}
|
{format(revision.createdAt, "MMMM Do, YYYY h:mm a")}
|
||||||
</Time>
|
</Time>
|
||||||
</Meta>
|
</Meta>
|
||||||
{showMenu && (
|
{showMenu && (
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import DocumentHistory from './DocumentHistory';
|
import DocumentHistory from "./DocumentHistory";
|
||||||
export default DocumentHistory;
|
export default DocumentHistory;
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import * as React from 'react';
|
import * as React from "react";
|
||||||
import Document from 'models/Document';
|
import Document from "models/Document";
|
||||||
import DocumentPreview from 'components/DocumentPreview';
|
import DocumentPreview from "components/DocumentPreview";
|
||||||
import ArrowKeyNavigation from 'boundless-arrow-key-navigation';
|
import ArrowKeyNavigation from "boundless-arrow-key-navigation";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
documents: Document[],
|
documents: Document[],
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import * as React from 'react';
|
import * as React from "react";
|
||||||
import { observer } from 'mobx-react';
|
import { observer } from "mobx-react";
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from "react-router-dom";
|
||||||
import { StarredIcon } from 'outline-icons';
|
import { StarredIcon } from "outline-icons";
|
||||||
import styled, { withTheme } from 'styled-components';
|
import styled, { withTheme } from "styled-components";
|
||||||
import Flex from 'shared/components/Flex';
|
import Flex from "shared/components/Flex";
|
||||||
import Badge from 'components/Badge';
|
import Badge from "components/Badge";
|
||||||
import Tooltip from 'components/Tooltip';
|
import Tooltip from "components/Tooltip";
|
||||||
import Highlight from 'components/Highlight';
|
import Highlight from "components/Highlight";
|
||||||
import PublishingInfo from 'components/PublishingInfo';
|
import PublishingInfo from "components/PublishingInfo";
|
||||||
import DocumentMenu from 'menus/DocumentMenu';
|
import DocumentMenu from "menus/DocumentMenu";
|
||||||
import Document from 'models/Document';
|
import Document from "models/Document";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
document: Document,
|
document: Document,
|
||||||
@ -26,7 +26,7 @@ const StyledStar = withTheme(styled(({ solid, theme, ...props }) => (
|
|||||||
<StarredIcon color={theme.text} {...props} />
|
<StarredIcon color={theme.text} {...props} />
|
||||||
))`
|
))`
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
opacity: ${props => (props.solid ? '1 !important' : 0)};
|
opacity: ${props => (props.solid ? "1 !important" : 0)};
|
||||||
transition: all 100ms ease-in-out;
|
transition: all 100ms ease-in-out;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
@ -82,8 +82,8 @@ const Heading = styled.h3`
|
|||||||
margin-bottom: 0.25em;
|
margin-bottom: 0.25em;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen,
|
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen,
|
||||||
Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
|
Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const Actions = styled(Flex)`
|
const Actions = styled(Flex)`
|
||||||
@ -124,7 +124,7 @@ class DocumentPreview extends React.Component<Props> {
|
|||||||
replaceResultMarks = (tag: string) => {
|
replaceResultMarks = (tag: string) => {
|
||||||
// don't use SEARCH_RESULT_REGEX here as it causes
|
// don't use SEARCH_RESULT_REGEX here as it causes
|
||||||
// an infinite loop to trigger a regex inside it's own callback
|
// an infinite loop to trigger a regex inside it's own callback
|
||||||
return tag.replace(/<b\b[^>]*>(.*?)<\/b>/gi, '$1');
|
return tag.replace(/<b\b[^>]*>(.*?)<\/b>/gi, "$1");
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
@ -152,7 +152,7 @@ class DocumentPreview extends React.Component<Props> {
|
|||||||
{...rest}
|
{...rest}
|
||||||
>
|
>
|
||||||
<Heading>
|
<Heading>
|
||||||
<Title text={document.title || 'Untitled'} highlight={highlight} />
|
<Title text={document.title || "Untitled"} highlight={highlight} />
|
||||||
{!document.isDraft &&
|
{!document.isDraft &&
|
||||||
!document.isArchived && (
|
!document.isArchived && (
|
||||||
<Actions>
|
<Actions>
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import DocumentPreview from './DocumentPreview';
|
import DocumentPreview from "./DocumentPreview";
|
||||||
export default DocumentPreview;
|
export default DocumentPreview;
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
// @flow
|
// @flow
|
||||||
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, type RouterHistory } 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";
|
||||||
import Dropzone from 'react-dropzone';
|
import Dropzone from "react-dropzone";
|
||||||
import DocumentsStore from 'stores/DocumentsStore';
|
import DocumentsStore from "stores/DocumentsStore";
|
||||||
import LoadingIndicator from 'components/LoadingIndicator';
|
import LoadingIndicator from "components/LoadingIndicator";
|
||||||
|
|
||||||
const EMPTY_OBJECT = {};
|
const EMPTY_OBJECT = {};
|
||||||
let importingLock = false;
|
let importingLock = false;
|
||||||
@ -56,7 +56,7 @@ class DropToImport extends React.Component<Props> {
|
|||||||
|
|
||||||
if (documentId && !collectionId) {
|
if (documentId && !collectionId) {
|
||||||
const document = await this.props.documents.fetch(documentId);
|
const document = await this.props.documents.fetch(documentId);
|
||||||
invariant(document, 'Document not available');
|
invariant(document, "Document not available");
|
||||||
collectionId = document.collectionId;
|
collectionId = document.collectionId;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -110,4 +110,4 @@ class DropToImport extends React.Component<Props> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default inject('documents')(withRouter(DropToImport));
|
export default inject("documents")(withRouter(DropToImport));
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import * as React from 'react';
|
import * as React from "react";
|
||||||
import invariant from 'invariant';
|
import invariant from "invariant";
|
||||||
import { observable } from 'mobx';
|
import { observable } from "mobx";
|
||||||
import { observer } from 'mobx-react';
|
import { observer } from "mobx-react";
|
||||||
import { PortalWithState } from 'react-portal';
|
import { PortalWithState } from "react-portal";
|
||||||
import { MoreIcon } from 'outline-icons';
|
import { MoreIcon } from "outline-icons";
|
||||||
import styled from 'styled-components';
|
import styled from "styled-components";
|
||||||
import Flex from 'shared/components/Flex';
|
import Flex from "shared/components/Flex";
|
||||||
import { fadeAndScaleIn } from 'shared/styles/animations';
|
import { fadeAndScaleIn } from "shared/styles/animations";
|
||||||
import NudeButton from 'components/NudeButton';
|
import NudeButton from "components/NudeButton";
|
||||||
|
|
||||||
let previousClosePortal;
|
let previousClosePortal;
|
||||||
let counter = 0;
|
let counter = 0;
|
||||||
@ -25,7 +25,7 @@ type Props = {
|
|||||||
className?: string,
|
className?: string,
|
||||||
hover?: boolean,
|
hover?: boolean,
|
||||||
style?: Object,
|
style?: Object,
|
||||||
position?: 'left' | 'right' | 'center',
|
position?: "left" | "right" | "center",
|
||||||
};
|
};
|
||||||
|
|
||||||
@observer
|
@observer
|
||||||
@ -37,7 +37,7 @@ class DropdownMenu extends React.Component<Props> {
|
|||||||
@observable bottom: ?number;
|
@observable bottom: ?number;
|
||||||
@observable right: ?number;
|
@observable right: ?number;
|
||||||
@observable left: ?number;
|
@observable left: ?number;
|
||||||
@observable position: 'left' | 'right' | 'center';
|
@observable position: "left" | "right" | "center";
|
||||||
@observable fixed: ?boolean;
|
@observable fixed: ?boolean;
|
||||||
@observable bodyRect: ClientRect;
|
@observable bodyRect: ClientRect;
|
||||||
@observable labelRect: ClientRect;
|
@observable labelRect: ClientRect;
|
||||||
@ -51,21 +51,21 @@ class DropdownMenu extends React.Component<Props> {
|
|||||||
return (ev: SyntheticMouseEvent<HTMLElement>) => {
|
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");
|
||||||
|
|
||||||
if (currentTarget instanceof HTMLDivElement) {
|
if (currentTarget instanceof HTMLDivElement) {
|
||||||
this.bodyRect = document.body.getBoundingClientRect();
|
this.bodyRect = document.body.getBoundingClientRect();
|
||||||
this.labelRect = currentTarget.getBoundingClientRect();
|
this.labelRect = currentTarget.getBoundingClientRect();
|
||||||
this.top = this.labelRect.bottom - this.bodyRect.top;
|
this.top = this.labelRect.bottom - this.bodyRect.top;
|
||||||
this.bottom = undefined;
|
this.bottom = undefined;
|
||||||
this.position = this.props.position || 'left';
|
this.position = this.props.position || "left";
|
||||||
|
|
||||||
if (currentTarget.parentElement) {
|
if (currentTarget.parentElement) {
|
||||||
const triggerParentStyle = getComputedStyle(
|
const triggerParentStyle = getComputedStyle(
|
||||||
currentTarget.parentElement
|
currentTarget.parentElement
|
||||||
);
|
);
|
||||||
|
|
||||||
if (triggerParentStyle.position === 'static') {
|
if (triggerParentStyle.position === "static") {
|
||||||
this.fixed = true;
|
this.fixed = true;
|
||||||
this.top = this.labelRect.bottom;
|
this.top = this.labelRect.bottom;
|
||||||
}
|
}
|
||||||
@ -84,10 +84,10 @@ class DropdownMenu extends React.Component<Props> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
initPosition() {
|
initPosition() {
|
||||||
if (this.position === 'left') {
|
if (this.position === "left") {
|
||||||
this.right =
|
this.right =
|
||||||
this.bodyRect.width - this.labelRect.left - this.labelRect.width;
|
this.bodyRect.width - this.labelRect.left - this.labelRect.width;
|
||||||
} else if (this.position === 'center') {
|
} else if (this.position === "center") {
|
||||||
this.left = this.labelRect.left + this.labelRect.width / 2;
|
this.left = this.labelRect.left + this.labelRect.width / 2;
|
||||||
} else {
|
} else {
|
||||||
this.left = this.labelRect.left;
|
this.left = this.labelRect.left;
|
||||||
@ -95,7 +95,7 @@ class DropdownMenu extends React.Component<Props> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onOpen = () => {
|
onOpen = () => {
|
||||||
if (typeof this.props.onOpen === 'function') {
|
if (typeof this.props.onOpen === "function") {
|
||||||
this.props.onOpen();
|
this.props.onOpen();
|
||||||
}
|
}
|
||||||
this.fitOnTheScreen();
|
this.fitOnTheScreen();
|
||||||
@ -114,18 +114,18 @@ class DropdownMenu extends React.Component<Props> {
|
|||||||
this.bottom = undefined;
|
this.bottom = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.position === 'left' || this.position === 'right') {
|
if (this.position === "left" || this.position === "right") {
|
||||||
const totalWidth =
|
const totalWidth =
|
||||||
Math.sign(this.position === 'left' ? -1 : 1) * el.offsetLeft +
|
Math.sign(this.position === "left" ? -1 : 1) * el.offsetLeft +
|
||||||
el.scrollWidth;
|
el.scrollWidth;
|
||||||
const isVisible = totalWidth < window.innerWidth;
|
const isVisible = totalWidth < window.innerWidth;
|
||||||
|
|
||||||
if (!isVisible) {
|
if (!isVisible) {
|
||||||
if (this.position === 'right') {
|
if (this.position === "right") {
|
||||||
this.position = 'left';
|
this.position = "left";
|
||||||
this.left = undefined;
|
this.left = undefined;
|
||||||
} else if (this.position === 'left') {
|
} else if (this.position === "left") {
|
||||||
this.position = 'right';
|
this.position = "right";
|
||||||
this.right = undefined;
|
this.right = undefined;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -177,7 +177,7 @@ class DropdownMenu extends React.Component<Props> {
|
|||||||
<NudeButton
|
<NudeButton
|
||||||
id={`${this.id}button`}
|
id={`${this.id}button`}
|
||||||
aria-haspopup="true"
|
aria-haspopup="true"
|
||||||
aria-expanded={isOpen ? 'true' : 'false'}
|
aria-expanded={isOpen ? "true" : "false"}
|
||||||
aria-controls={this.id}
|
aria-controls={this.id}
|
||||||
>
|
>
|
||||||
<MoreIcon />
|
<MoreIcon />
|
||||||
@ -201,7 +201,7 @@ class DropdownMenu extends React.Component<Props> {
|
|||||||
hover ? this.closeAfterTimeout(closePortal) : undefined
|
hover ? this.closeAfterTimeout(closePortal) : undefined
|
||||||
}
|
}
|
||||||
onClick={
|
onClick={
|
||||||
typeof children === 'function'
|
typeof children === "function"
|
||||||
? undefined
|
? undefined
|
||||||
: ev => {
|
: ev => {
|
||||||
ev.stopPropagation();
|
ev.stopPropagation();
|
||||||
@ -213,7 +213,7 @@ class DropdownMenu extends React.Component<Props> {
|
|||||||
aria-labelledby={`${this.id}button`}
|
aria-labelledby={`${this.id}button`}
|
||||||
role="menu"
|
role="menu"
|
||||||
>
|
>
|
||||||
{typeof children === 'function'
|
{typeof children === "function"
|
||||||
? children({ closePortal })
|
? children({ closePortal })
|
||||||
: children}
|
: children}
|
||||||
</Menu>
|
</Menu>
|
||||||
@ -228,35 +228,35 @@ class DropdownMenu extends React.Component<Props> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const Label = styled(Flex).attrs({
|
const Label = styled(Flex).attrs({
|
||||||
justify: 'center',
|
justify: "center",
|
||||||
align: 'center',
|
align: "center",
|
||||||
})`
|
})`
|
||||||
z-index: 1000;
|
z-index: 1000;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const Position = styled.div`
|
const Position = styled.div`
|
||||||
position: ${({ fixed }) => (fixed ? 'fixed' : 'absolute')};
|
position: ${({ fixed }) => (fixed ? "fixed" : "absolute")};
|
||||||
display: flex;
|
display: flex;
|
||||||
${({ left }) => (left !== undefined ? `left: ${left}px` : '')};
|
${({ left }) => (left !== undefined ? `left: ${left}px` : "")};
|
||||||
${({ right }) => (right !== undefined ? `right: ${right}px` : '')};
|
${({ right }) => (right !== undefined ? `right: ${right}px` : "")};
|
||||||
${({ top }) => (top !== undefined ? `top: ${top}px` : '')};
|
${({ top }) => (top !== undefined ? `top: ${top}px` : "")};
|
||||||
${({ bottom }) => (bottom !== undefined ? `bottom: ${bottom}px` : '')};
|
${({ bottom }) => (bottom !== undefined ? `bottom: ${bottom}px` : "")};
|
||||||
max-height: 75%;
|
max-height: 75%;
|
||||||
z-index: 1000;
|
z-index: 1000;
|
||||||
transform: ${props =>
|
transform: ${props =>
|
||||||
props.position === 'center' ? 'translateX(-50%)' : 'initial'};
|
props.position === "center" ? "translateX(-50%)" : "initial"};
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const Menu = styled.div`
|
const Menu = styled.div`
|
||||||
animation: ${fadeAndScaleIn} 200ms ease;
|
animation: ${fadeAndScaleIn} 200ms ease;
|
||||||
transform-origin: ${props => (props.left !== undefined ? '25%' : '75%')} 0;
|
transform-origin: ${props => (props.left !== undefined ? "25%" : "75%")} 0;
|
||||||
background: ${props => props.theme.menuBackground};
|
background: ${props => props.theme.menuBackground};
|
||||||
${props =>
|
${props =>
|
||||||
props.theme.menuBorder
|
props.theme.menuBorder
|
||||||
? `border: 1px solid ${props.theme.menuBorder}`
|
? `border: 1px solid ${props.theme.menuBorder}`
|
||||||
: ''};
|
: ""};
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
padding: 0.5em 0;
|
padding: 0.5em 0;
|
||||||
min-width: 180px;
|
min-width: 180px;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import * as React from 'react';
|
import * as React from "react";
|
||||||
import { CheckmarkIcon } from 'outline-icons';
|
import { CheckmarkIcon } from "outline-icons";
|
||||||
import styled from 'styled-components';
|
import styled from "styled-components";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
onClick?: (SyntheticEvent<>) => void | Promise<void>,
|
onClick?: (SyntheticEvent<>) => void | Promise<void>,
|
||||||
@ -28,7 +28,7 @@ const DropdownMenuItem = ({
|
|||||||
{selected !== undefined && (
|
{selected !== undefined && (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
<CheckmarkIcon
|
<CheckmarkIcon
|
||||||
color={selected === false ? 'transparent' : undefined}
|
color={selected === false ? "transparent" : undefined}
|
||||||
/>
|
/>
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
)}
|
)}
|
||||||
@ -57,12 +57,12 @@ const MenuItem = styled.a`
|
|||||||
}
|
}
|
||||||
|
|
||||||
svg {
|
svg {
|
||||||
opacity: ${props => (props.disabled ? '.5' : 1)};
|
opacity: ${props => (props.disabled ? ".5" : 1)};
|
||||||
}
|
}
|
||||||
|
|
||||||
${props =>
|
${props =>
|
||||||
props.disabled
|
props.disabled
|
||||||
? 'pointer-events: none;'
|
? "pointer-events: none;"
|
||||||
: `
|
: `
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
// @flow
|
// @flow
|
||||||
export { default as DropdownMenu } from './DropdownMenu';
|
export { default as DropdownMenu } from "./DropdownMenu";
|
||||||
export { default as DropdownMenuItem } from './DropdownMenuItem';
|
export { default as DropdownMenuItem } from "./DropdownMenuItem";
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import * as React from 'react';
|
import * as React from "react";
|
||||||
import { withRouter, type RouterHistory } from 'react-router-dom';
|
import { withRouter, type RouterHistory } from "react-router-dom";
|
||||||
import { observable } from 'mobx';
|
import { observable } from "mobx";
|
||||||
import { observer } from 'mobx-react';
|
import { observer } from "mobx-react";
|
||||||
import { lighten } from 'polished';
|
import { lighten } from "polished";
|
||||||
import styled, { withTheme } from 'styled-components';
|
import styled, { withTheme } from "styled-components";
|
||||||
import RichMarkdownEditor from 'rich-markdown-editor';
|
import RichMarkdownEditor from "rich-markdown-editor";
|
||||||
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 UiStore from "stores/UiStore";
|
||||||
import embeds from '../../embeds';
|
import embeds from "../../embeds";
|
||||||
|
|
||||||
const EMPTY_ARRAY = [];
|
const EMPTY_ARRAY = [];
|
||||||
|
|
||||||
@ -36,7 +36,7 @@ class Editor extends React.Component<Props> {
|
|||||||
|
|
||||||
onClickLink = (href: string) => {
|
onClickLink = (href: string) => {
|
||||||
// on page hash
|
// on page hash
|
||||||
if (href[0] === '#') {
|
if (href[0] === "#") {
|
||||||
window.location.href = href;
|
window.location.href = href;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -46,7 +46,7 @@ class Editor extends React.Component<Props> {
|
|||||||
let navigateTo = href;
|
let navigateTo = href;
|
||||||
|
|
||||||
// probably absolute
|
// probably absolute
|
||||||
if (href[0] !== '/') {
|
if (href[0] !== "/") {
|
||||||
try {
|
try {
|
||||||
const url = new URL(href);
|
const url = new URL(href);
|
||||||
navigateTo = url.pathname + url.hash;
|
navigateTo = url.pathname + url.hash;
|
||||||
@ -57,7 +57,7 @@ class Editor extends React.Component<Props> {
|
|||||||
|
|
||||||
this.props.history.push(navigateTo);
|
this.props.history.push(navigateTo);
|
||||||
} else {
|
} else {
|
||||||
window.open(href, '_blank');
|
window.open(href, "_blank");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import Editor from './Editor';
|
import Editor from "./Editor";
|
||||||
export default Editor;
|
export default Editor;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import * as React from 'react';
|
import * as React from "react";
|
||||||
import styled from 'styled-components';
|
import styled from "styled-components";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
children: React.Node,
|
children: React.Node,
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import * as React from 'react';
|
import * as React from "react";
|
||||||
import styled from 'styled-components';
|
import styled from "styled-components";
|
||||||
import { observer } from 'mobx-react';
|
import { observer } from "mobx-react";
|
||||||
import { observable } from 'mobx';
|
import { observable } from "mobx";
|
||||||
import HelpText from 'components/HelpText';
|
import HelpText from "components/HelpText";
|
||||||
import Button from 'components/Button';
|
import Button from "components/Button";
|
||||||
import CenteredContent from 'components/CenteredContent';
|
import CenteredContent from "components/CenteredContent";
|
||||||
import PageTitle from 'components/PageTitle';
|
import PageTitle from "components/PageTitle";
|
||||||
import { githubIssuesUrl } from '../../shared/utils/routeHelpers';
|
import { githubIssuesUrl } from "../../shared/utils/routeHelpers";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
children: React.Node,
|
children: React.Node,
|
||||||
@ -49,12 +49,12 @@ class ErrorBoundary extends React.Component<Props> {
|
|||||||
<h1>Something Unexpected Happened</h1>
|
<h1>Something Unexpected Happened</h1>
|
||||||
<HelpText>
|
<HelpText>
|
||||||
Sorry, an unrecoverable error occurred{isReported &&
|
Sorry, an unrecoverable error occurred{isReported &&
|
||||||
' – our engineers have been notified'}. Please try reloading the
|
" – our engineers have been notified"}. Please try reloading the
|
||||||
page, it may have been a temporary glitch.
|
page, it may have been a temporary glitch.
|
||||||
</HelpText>
|
</HelpText>
|
||||||
{this.showDetails && <Pre>{this.error.toString()}</Pre>}
|
{this.showDetails && <Pre>{this.error.toString()}</Pre>}
|
||||||
<p>
|
<p>
|
||||||
<Button onClick={this.handleReload}>Reload</Button>{' '}
|
<Button onClick={this.handleReload}>Reload</Button>{" "}
|
||||||
{this.showDetails ? (
|
{this.showDetails ? (
|
||||||
<Button onClick={this.handleReportBug} neutral>
|
<Button onClick={this.handleReportBug} neutral>
|
||||||
Report a Bug…
|
Report a Bug…
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
// @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 styled, { withTheme } from 'styled-components';
|
import styled, { withTheme } from "styled-components";
|
||||||
import Flex from 'shared/components/Flex';
|
import Flex from "shared/components/Flex";
|
||||||
import Avatar from 'components/Avatar';
|
import Avatar from "components/Avatar";
|
||||||
import User from 'models/User';
|
import User from "models/User";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
users: User[],
|
users: User[],
|
||||||
@ -73,4 +73,4 @@ const Avatars = styled(Flex)`
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export default inject('views', 'presence')(withTheme(Facepile));
|
export default inject("views", "presence")(withTheme(Facepile));
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import styled from 'styled-components';
|
import styled from "styled-components";
|
||||||
import { fadeIn } from 'shared/styles/animations';
|
import { fadeIn } from "shared/styles/animations";
|
||||||
|
|
||||||
const Fade = styled.span`
|
const Fade = styled.span`
|
||||||
animation: ${fadeIn} ${props => props.timing || '250ms'} ease-in-out;
|
animation: ${fadeIn} ${props => props.timing || "250ms"} ease-in-out;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export default Fade;
|
export default Fade;
|
||||||
|
@ -1,17 +1,17 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import * as React from 'react';
|
import * as React from "react";
|
||||||
import styled from 'styled-components';
|
import styled from "styled-components";
|
||||||
import { observable } from 'mobx';
|
import { observable } from "mobx";
|
||||||
import { observer, inject } from 'mobx-react';
|
import { observer, inject } from "mobx-react";
|
||||||
import { MAX_AVATAR_DISPLAY } from 'shared/constants';
|
import { MAX_AVATAR_DISPLAY } from "shared/constants";
|
||||||
import Modal from 'components/Modal';
|
import Modal from "components/Modal";
|
||||||
import Flex from 'shared/components/Flex';
|
import Flex from "shared/components/Flex";
|
||||||
import Facepile from 'components/Facepile';
|
import Facepile from "components/Facepile";
|
||||||
import GroupMembers from 'scenes/GroupMembers';
|
import GroupMembers from "scenes/GroupMembers";
|
||||||
import ListItem from 'components/List/Item';
|
import ListItem from "components/List/Item";
|
||||||
import Group from 'models/Group';
|
import Group from "models/Group";
|
||||||
import CollectionGroupMembership from 'models/CollectionGroupMembership';
|
import CollectionGroupMembership from "models/CollectionGroupMembership";
|
||||||
import GroupMembershipsStore from 'stores/GroupMembershipsStore';
|
import GroupMembershipsStore from "stores/GroupMembershipsStore";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
group: Group,
|
group: Group,
|
||||||
@ -53,7 +53,7 @@ class GroupListItem extends React.Component<Props> {
|
|||||||
}
|
}
|
||||||
subtitle={
|
subtitle={
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
{memberCount} member{memberCount === 1 ? '' : 's'}
|
{memberCount} member{memberCount === 1 ? "" : "s"}
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
}
|
}
|
||||||
actions={
|
actions={
|
||||||
@ -91,4 +91,4 @@ const Title = styled.span`
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export default inject('groupMemberships')(GroupListItem);
|
export default inject("groupMemberships")(GroupListItem);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import styled from 'styled-components';
|
import styled from "styled-components";
|
||||||
|
|
||||||
const Heading = styled.h1`
|
const Heading = styled.h1`
|
||||||
display: flex;
|
display: flex;
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import styled from 'styled-components';
|
import styled from "styled-components";
|
||||||
|
|
||||||
const HelpText = styled.p`
|
const HelpText = styled.p`
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
color: ${props => props.theme.textSecondary};
|
color: ${props => props.theme.textSecondary};
|
||||||
font-size: ${props => (props.small ? '13px' : 'inherit')};
|
font-size: ${props => (props.small ? "13px" : "inherit")};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export default HelpText;
|
export default HelpText;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import * as React from 'react';
|
import * as React from "react";
|
||||||
import replace from 'string-replace-to-array';
|
import replace from "string-replace-to-array";
|
||||||
import styled from 'styled-components';
|
import styled from "styled-components";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
highlight: ?string | RegExp,
|
highlight: ?string | RegExp,
|
||||||
@ -22,8 +22,8 @@ function Highlight({
|
|||||||
regex = highlight;
|
regex = highlight;
|
||||||
} else {
|
} else {
|
||||||
regex = new RegExp(
|
regex = new RegExp(
|
||||||
(highlight || '').replace(/[-\\^$*+?.()|[\]{}]/g, '\\$&'),
|
(highlight || "").replace(/[-\\^$*+?.()|[\]{}]/g, "\\$&"),
|
||||||
caseSensitive ? 'g' : 'gi'
|
caseSensitive ? "g" : "gi"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import * as React from 'react';
|
import * as React from "react";
|
||||||
import { observable } from 'mobx';
|
import { observable } from "mobx";
|
||||||
import { observer } from 'mobx-react';
|
import { observer } from "mobx-react";
|
||||||
import { TwitterPicker } from 'react-color';
|
import { TwitterPicker } from "react-color";
|
||||||
import {
|
import {
|
||||||
CollectionIcon,
|
CollectionIcon,
|
||||||
CoinsIcon,
|
CoinsIcon,
|
||||||
@ -22,99 +22,99 @@ import {
|
|||||||
QuestionMarkIcon,
|
QuestionMarkIcon,
|
||||||
SunIcon,
|
SunIcon,
|
||||||
VehicleIcon,
|
VehicleIcon,
|
||||||
} from 'outline-icons';
|
} from "outline-icons";
|
||||||
import styled from 'styled-components';
|
import styled from "styled-components";
|
||||||
import { LabelText } from 'components/Input';
|
import { LabelText } from "components/Input";
|
||||||
import { DropdownMenu } from 'components/DropdownMenu';
|
import { DropdownMenu } from "components/DropdownMenu";
|
||||||
import NudeButton from 'components/NudeButton';
|
import NudeButton from "components/NudeButton";
|
||||||
import Flex from 'shared/components/Flex';
|
import Flex from "shared/components/Flex";
|
||||||
|
|
||||||
export const icons = {
|
export const icons = {
|
||||||
collection: {
|
collection: {
|
||||||
component: CollectionIcon,
|
component: CollectionIcon,
|
||||||
keywords: 'collection',
|
keywords: "collection",
|
||||||
},
|
},
|
||||||
coins: {
|
coins: {
|
||||||
component: CoinsIcon,
|
component: CoinsIcon,
|
||||||
keywords: 'coins money finance sales income revenue cash',
|
keywords: "coins money finance sales income revenue cash",
|
||||||
},
|
},
|
||||||
academicCap: {
|
academicCap: {
|
||||||
component: AcademicCapIcon,
|
component: AcademicCapIcon,
|
||||||
keywords: 'learn teach lesson guide tutorial onboarding training',
|
keywords: "learn teach lesson guide tutorial onboarding training",
|
||||||
},
|
},
|
||||||
beaker: {
|
beaker: {
|
||||||
component: BeakerIcon,
|
component: BeakerIcon,
|
||||||
keywords: 'lab research experiment test',
|
keywords: "lab research experiment test",
|
||||||
},
|
},
|
||||||
buildingBlocks: {
|
buildingBlocks: {
|
||||||
component: BuildingBlocksIcon,
|
component: BuildingBlocksIcon,
|
||||||
keywords: 'app blocks product prototype',
|
keywords: "app blocks product prototype",
|
||||||
},
|
},
|
||||||
cloud: {
|
cloud: {
|
||||||
component: CloudIcon,
|
component: CloudIcon,
|
||||||
keywords: 'cloud service aws infrastructure',
|
keywords: "cloud service aws infrastructure",
|
||||||
},
|
},
|
||||||
code: {
|
code: {
|
||||||
component: CodeIcon,
|
component: CodeIcon,
|
||||||
keywords: 'developer api code development engineering programming',
|
keywords: "developer api code development engineering programming",
|
||||||
},
|
},
|
||||||
eye: {
|
eye: {
|
||||||
component: EyeIcon,
|
component: EyeIcon,
|
||||||
keywords: 'eye view',
|
keywords: "eye view",
|
||||||
},
|
},
|
||||||
leaf: {
|
leaf: {
|
||||||
component: LeafIcon,
|
component: LeafIcon,
|
||||||
keywords: 'leaf plant outdoors nature ecosystem climate',
|
keywords: "leaf plant outdoors nature ecosystem climate",
|
||||||
},
|
},
|
||||||
lightbulb: {
|
lightbulb: {
|
||||||
component: LightBulbIcon,
|
component: LightBulbIcon,
|
||||||
keywords: 'lightbulb idea',
|
keywords: "lightbulb idea",
|
||||||
},
|
},
|
||||||
moon: {
|
moon: {
|
||||||
component: MoonIcon,
|
component: MoonIcon,
|
||||||
keywords: 'night moon dark',
|
keywords: "night moon dark",
|
||||||
},
|
},
|
||||||
notepad: {
|
notepad: {
|
||||||
component: NotepadIcon,
|
component: NotepadIcon,
|
||||||
keywords: 'journal notepad write notes',
|
keywords: "journal notepad write notes",
|
||||||
},
|
},
|
||||||
padlock: {
|
padlock: {
|
||||||
component: PadlockIcon,
|
component: PadlockIcon,
|
||||||
keywords: 'padlock private security authentication authorization auth',
|
keywords: "padlock private security authentication authorization auth",
|
||||||
},
|
},
|
||||||
palette: {
|
palette: {
|
||||||
component: PaletteIcon,
|
component: PaletteIcon,
|
||||||
keywords: 'design palette art brand',
|
keywords: "design palette art brand",
|
||||||
},
|
},
|
||||||
pencil: {
|
pencil: {
|
||||||
component: EditIcon,
|
component: EditIcon,
|
||||||
keywords: 'copy writing post blog',
|
keywords: "copy writing post blog",
|
||||||
},
|
},
|
||||||
question: {
|
question: {
|
||||||
component: QuestionMarkIcon,
|
component: QuestionMarkIcon,
|
||||||
keywords: 'question help support faq',
|
keywords: "question help support faq",
|
||||||
},
|
},
|
||||||
sun: {
|
sun: {
|
||||||
component: SunIcon,
|
component: SunIcon,
|
||||||
keywords: 'day sun weather',
|
keywords: "day sun weather",
|
||||||
},
|
},
|
||||||
vehicle: {
|
vehicle: {
|
||||||
component: VehicleIcon,
|
component: VehicleIcon,
|
||||||
keywords: 'truck car travel transport',
|
keywords: "truck car travel transport",
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const colors = [
|
const colors = [
|
||||||
'#4E5C6E',
|
"#4E5C6E",
|
||||||
'#0366d6',
|
"#0366d6",
|
||||||
'#7F6BFF',
|
"#7F6BFF",
|
||||||
'#E76F51',
|
"#E76F51",
|
||||||
'#FC2D2D',
|
"#FC2D2D",
|
||||||
'#FFBE0B',
|
"#FFBE0B",
|
||||||
'#2A9D8F',
|
"#2A9D8F",
|
||||||
'#00D084',
|
"#00D084",
|
||||||
'#EE84F0',
|
"#EE84F0",
|
||||||
'#2F362F',
|
"#2F362F",
|
||||||
];
|
];
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
@ -134,11 +134,11 @@ class IconPicker extends React.Component<Props> {
|
|||||||
node: ?HTMLElement;
|
node: ?HTMLElement;
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
window.addEventListener('click', this.handleClickOutside);
|
window.addEventListener("click", this.handleClickOutside);
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
window.removeEventListener('click', this.handleClickOutside);
|
window.removeEventListener("click", this.handleClickOutside);
|
||||||
}
|
}
|
||||||
|
|
||||||
handleClose = () => {
|
handleClose = () => {
|
||||||
@ -163,7 +163,7 @@ class IconPicker extends React.Component<Props> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const Component = icons[this.props.icon || 'collection'].component;
|
const Component = icons[this.props.icon || "collection"].component;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Wrapper ref={ref => (this.node = ref)}>
|
<Wrapper ref={ref => (this.node = ref)}>
|
||||||
@ -230,7 +230,7 @@ const ColorPicker = styled(TwitterPicker)`
|
|||||||
background: transparent !important;
|
background: transparent !important;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const Wrapper = styled('div')`
|
const Wrapper = styled("div")`
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
position: relative;
|
position: relative;
|
||||||
`;
|
`;
|
||||||
|
@ -1,15 +1,15 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import * as React from 'react';
|
import * as React from "react";
|
||||||
import { observer } from 'mobx-react';
|
import { observer } from "mobx-react";
|
||||||
import { observable } from 'mobx';
|
import { observable } from "mobx";
|
||||||
import styled from 'styled-components';
|
import styled from "styled-components";
|
||||||
import VisuallyHidden from 'components/VisuallyHidden';
|
import VisuallyHidden from "components/VisuallyHidden";
|
||||||
import Flex from 'shared/components/Flex';
|
import Flex from "shared/components/Flex";
|
||||||
|
|
||||||
const RealTextarea = styled.textarea`
|
const RealTextarea = styled.textarea`
|
||||||
border: 0;
|
border: 0;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
padding: 8px 12px 8px ${props => (props.hasIcon ? '8px' : '12px')};
|
padding: 8px 12px 8px ${props => (props.hasIcon ? "8px" : "12px")};
|
||||||
outline: none;
|
outline: none;
|
||||||
background: none;
|
background: none;
|
||||||
color: ${props => props.theme.text};
|
color: ${props => props.theme.text};
|
||||||
@ -23,7 +23,7 @@ const RealTextarea = styled.textarea`
|
|||||||
const RealInput = styled.input`
|
const RealInput = styled.input`
|
||||||
border: 0;
|
border: 0;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
padding: 8px 12px 8px ${props => (props.hasIcon ? '8px' : '12px')};
|
padding: 8px 12px 8px ${props => (props.hasIcon ? "8px" : "12px")};
|
||||||
outline: none;
|
outline: none;
|
||||||
background: none;
|
background: none;
|
||||||
color: ${props => props.theme.text};
|
color: ${props => props.theme.text};
|
||||||
@ -40,10 +40,10 @@ const RealInput = styled.input`
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
const Wrapper = styled.div`
|
const Wrapper = styled.div`
|
||||||
flex: ${props => (props.flex ? '1' : '0')};
|
flex: ${props => (props.flex ? "1" : "0")};
|
||||||
max-width: ${props => (props.short ? '350px' : '100%')};
|
max-width: ${props => (props.short ? "350px" : "100%")};
|
||||||
min-height: ${({ minHeight }) => (minHeight ? `${minHeight}px` : '0')};
|
min-height: ${({ minHeight }) => (minHeight ? `${minHeight}px` : "0")};
|
||||||
max-height: ${({ maxHeight }) => (maxHeight ? `${maxHeight}px` : 'initial')};
|
max-height: ${({ maxHeight }) => (maxHeight ? `${maxHeight}px` : "initial")};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const IconWrapper = styled.span`
|
const IconWrapper = styled.span`
|
||||||
@ -56,13 +56,13 @@ const IconWrapper = styled.span`
|
|||||||
export const Outline = styled(Flex)`
|
export const Outline = styled(Flex)`
|
||||||
display: flex;
|
display: flex;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
margin: ${props => (props.margin !== undefined ? props.margin : '0 0 16px')};
|
margin: ${props => (props.margin !== undefined ? props.margin : "0 0 16px")};
|
||||||
color: inherit;
|
color: inherit;
|
||||||
border-width: 1px;
|
border-width: 1px;
|
||||||
border-style: solid;
|
border-style: solid;
|
||||||
border-color: ${props =>
|
border-color: ${props =>
|
||||||
props.hasError
|
props.hasError
|
||||||
? 'red'
|
? "red"
|
||||||
: props.focused
|
: props.focused
|
||||||
? props.theme.inputBorderFocused
|
? props.theme.inputBorderFocused
|
||||||
: props.theme.inputBorder};
|
: props.theme.inputBorder};
|
||||||
@ -118,7 +118,7 @@ class Input extends React.Component<Props> {
|
|||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {
|
const {
|
||||||
type = 'text',
|
type = "text",
|
||||||
icon,
|
icon,
|
||||||
label,
|
label,
|
||||||
margin,
|
margin,
|
||||||
@ -131,7 +131,7 @@ class Input extends React.Component<Props> {
|
|||||||
...rest
|
...rest
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
const InputComponent = type === 'textarea' ? RealTextarea : RealInput;
|
const InputComponent = type === "textarea" ? RealTextarea : RealInput;
|
||||||
const wrappedLabel = <LabelText>{label}</LabelText>;
|
const wrappedLabel = <LabelText>{label}</LabelText>;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -149,7 +149,7 @@ class Input extends React.Component<Props> {
|
|||||||
ref={ref => (this.input = ref)}
|
ref={ref => (this.input = ref)}
|
||||||
onBlur={this.handleBlur}
|
onBlur={this.handleBlur}
|
||||||
onFocus={this.handleFocus}
|
onFocus={this.handleFocus}
|
||||||
type={type === 'textarea' ? undefined : type}
|
type={type === "textarea" ? undefined : type}
|
||||||
hasIcon={!!icon}
|
hasIcon={!!icon}
|
||||||
{...rest}
|
{...rest}
|
||||||
/>
|
/>
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import * as React from 'react';
|
import * as React from "react";
|
||||||
import { observable } from 'mobx';
|
import { observable } from "mobx";
|
||||||
import { observer } from 'mobx-react';
|
import { observer } from "mobx-react";
|
||||||
import styled, { withTheme } from 'styled-components';
|
import styled, { withTheme } from "styled-components";
|
||||||
import { LabelText, Outline } from 'components/Input';
|
import { LabelText, Outline } from "components/Input";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
label: string,
|
label: string,
|
||||||
@ -31,7 +31,7 @@ class InputRich extends React.Component<Props> {
|
|||||||
|
|
||||||
loadEditor = async () => {
|
loadEditor = async () => {
|
||||||
try {
|
try {
|
||||||
const EditorImport = await import('./Editor');
|
const EditorImport = await import("./Editor");
|
||||||
this.editorComponent = EditorImport.default;
|
this.editorComponent = EditorImport.default;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
@ -64,7 +64,7 @@ class InputRich extends React.Component<Props> {
|
|||||||
{...rest}
|
{...rest}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
'Loading…'
|
"Loading…"
|
||||||
)}
|
)}
|
||||||
</StyledOutline>
|
</StyledOutline>
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
@ -74,8 +74,8 @@ class InputRich extends React.Component<Props> {
|
|||||||
|
|
||||||
const StyledOutline = styled(Outline)`
|
const StyledOutline = styled(Outline)`
|
||||||
padding: 8px 12px;
|
padding: 8px 12px;
|
||||||
min-height: ${({ minHeight }) => (minHeight ? `${minHeight}px` : '0')};
|
min-height: ${({ minHeight }) => (minHeight ? `${minHeight}px` : "0")};
|
||||||
max-height: ${({ maxHeight }) => (maxHeight ? `${maxHeight}px` : 'auto')};
|
max-height: ${({ maxHeight }) => (maxHeight ? `${maxHeight}px` : "auto")};
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
|
|
||||||
> * {
|
> * {
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import * as React from 'react';
|
import * as React from "react";
|
||||||
import keydown from 'react-keydown';
|
import keydown from "react-keydown";
|
||||||
import { observer } from 'mobx-react';
|
import { observer } from "mobx-react";
|
||||||
import { observable } from 'mobx';
|
import { observable } from "mobx";
|
||||||
import { withRouter, type RouterHistory } from 'react-router-dom';
|
import { withRouter, type RouterHistory } from "react-router-dom";
|
||||||
import styled, { withTheme } from 'styled-components';
|
import styled, { withTheme } from "styled-components";
|
||||||
import { SearchIcon } from 'outline-icons';
|
import { SearchIcon } from "outline-icons";
|
||||||
import { searchUrl } from 'utils/routeHelpers';
|
import { searchUrl } from "utils/routeHelpers";
|
||||||
import Input from './Input';
|
import Input from "./Input";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
history: RouterHistory,
|
history: RouterHistory,
|
||||||
@ -21,7 +21,7 @@ class InputSearch extends React.Component<Props> {
|
|||||||
input: ?Input;
|
input: ?Input;
|
||||||
@observable focused: boolean = false;
|
@observable focused: boolean = false;
|
||||||
|
|
||||||
@keydown('meta+f')
|
@keydown("meta+f")
|
||||||
focus(ev) {
|
focus(ev) {
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
|
|
||||||
@ -46,7 +46,7 @@ class InputSearch extends React.Component<Props> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { theme, placeholder = 'Search…' } = this.props;
|
const { theme, placeholder = "Search…" } = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<InputMaxWidth
|
<InputMaxWidth
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import * as React from 'react';
|
import * as React from "react";
|
||||||
import { observer } from 'mobx-react';
|
import { observer } from "mobx-react";
|
||||||
import { observable } from 'mobx';
|
import { observable } from "mobx";
|
||||||
import styled from 'styled-components';
|
import styled from "styled-components";
|
||||||
import VisuallyHidden from 'components/VisuallyHidden';
|
import VisuallyHidden from "components/VisuallyHidden";
|
||||||
import { Outline, LabelText } from './Input';
|
import { Outline, LabelText } from "./Input";
|
||||||
|
|
||||||
const Select = styled.select`
|
const Select = styled.select`
|
||||||
border: 0;
|
border: 0;
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import styled from 'styled-components';
|
import styled from "styled-components";
|
||||||
|
|
||||||
const Key = styled.kbd`
|
const Key = styled.kbd`
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
padding: 4px 6px;
|
padding: 4px 6px;
|
||||||
font: 11px 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, Courier,
|
font: 11px "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier,
|
||||||
monospace;
|
monospace;
|
||||||
line-height: 10px;
|
line-height: 10px;
|
||||||
color: ${props => props.theme.almostBlack};
|
color: ${props => props.theme.almostBlack};
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import * as React from 'react';
|
import * as React from "react";
|
||||||
import { observer } from 'mobx-react';
|
import { observer } from "mobx-react";
|
||||||
import Flex from 'shared/components/Flex';
|
import Flex from "shared/components/Flex";
|
||||||
import styled from 'styled-components';
|
import styled from "styled-components";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
label: React.Node | string,
|
label: React.Node | string,
|
||||||
|
@ -1,32 +1,32 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import * as React from 'react';
|
import * as React from "react";
|
||||||
import { Switch, Route, Redirect } from 'react-router-dom';
|
import { Switch, Route, Redirect } from "react-router-dom";
|
||||||
import { Helmet } from 'react-helmet';
|
import { Helmet } from "react-helmet";
|
||||||
import styled, { withTheme } from 'styled-components';
|
import styled, { withTheme } from "styled-components";
|
||||||
import breakpoint from 'styled-components-breakpoint';
|
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 keydown from 'react-keydown';
|
import keydown from "react-keydown";
|
||||||
import Analytics from 'components/Analytics';
|
import Analytics from "components/Analytics";
|
||||||
import Flex from 'shared/components/Flex';
|
import Flex from "shared/components/Flex";
|
||||||
import {
|
import {
|
||||||
homeUrl,
|
homeUrl,
|
||||||
searchUrl,
|
searchUrl,
|
||||||
matchDocumentSlug as slug,
|
matchDocumentSlug as slug,
|
||||||
} from 'utils/routeHelpers';
|
} from "utils/routeHelpers";
|
||||||
|
|
||||||
import { LoadingIndicatorBar } from 'components/LoadingIndicator';
|
import { LoadingIndicatorBar } from "components/LoadingIndicator";
|
||||||
import { GlobalStyles } from 'components/DropToImport';
|
import { GlobalStyles } from "components/DropToImport";
|
||||||
import Sidebar from 'components/Sidebar';
|
import Sidebar from "components/Sidebar";
|
||||||
import SettingsSidebar from 'components/Sidebar/Settings';
|
import SettingsSidebar from "components/Sidebar/Settings";
|
||||||
import Modals from 'components/Modals';
|
import Modals from "components/Modals";
|
||||||
import DocumentHistory from 'components/DocumentHistory';
|
import DocumentHistory from "components/DocumentHistory";
|
||||||
import Modal from 'components/Modal';
|
import Modal from "components/Modal";
|
||||||
import KeyboardShortcuts from 'scenes/KeyboardShortcuts';
|
import KeyboardShortcuts from "scenes/KeyboardShortcuts";
|
||||||
import ErrorSuspended from 'scenes/ErrorSuspended';
|
import ErrorSuspended from "scenes/ErrorSuspended";
|
||||||
import AuthStore from 'stores/AuthStore';
|
import AuthStore from "stores/AuthStore";
|
||||||
import UiStore from 'stores/UiStore';
|
import UiStore from "stores/UiStore";
|
||||||
import DocumentsStore from 'stores/DocumentsStore';
|
import DocumentsStore from "stores/DocumentsStore";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
documents: DocumentsStore,
|
documents: DocumentsStore,
|
||||||
@ -62,7 +62,7 @@ class Layout extends React.Component<Props> {
|
|||||||
window.document.body.style.background = this.props.theme.background;
|
window.document.body.style.background = this.props.theme.background;
|
||||||
}
|
}
|
||||||
|
|
||||||
@keydown('shift+/')
|
@keydown("shift+/")
|
||||||
handleOpenKeyboardShortcuts() {
|
handleOpenKeyboardShortcuts() {
|
||||||
if (this.props.ui.editMode) return;
|
if (this.props.ui.editMode) return;
|
||||||
this.keyboardShortcutsOpen = true;
|
this.keyboardShortcutsOpen = true;
|
||||||
@ -72,7 +72,7 @@ class Layout extends React.Component<Props> {
|
|||||||
this.keyboardShortcutsOpen = false;
|
this.keyboardShortcutsOpen = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
@keydown(['t', '/', 'meta+k'])
|
@keydown(["t", "/", "meta+k"])
|
||||||
goToSearch(ev) {
|
goToSearch(ev) {
|
||||||
if (this.props.ui.editMode) return;
|
if (this.props.ui.editMode) return;
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
@ -80,7 +80,7 @@ class Layout extends React.Component<Props> {
|
|||||||
this.redirectTo = searchUrl();
|
this.redirectTo = searchUrl();
|
||||||
}
|
}
|
||||||
|
|
||||||
@keydown('d')
|
@keydown("d")
|
||||||
goToDashboard() {
|
goToDashboard() {
|
||||||
if (this.props.ui.editMode) return;
|
if (this.props.ui.editMode) return;
|
||||||
this.redirectTo = homeUrl();
|
this.redirectTo = homeUrl();
|
||||||
@ -157,9 +157,9 @@ const Content = styled(Flex)`
|
|||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
${breakpoint('tablet')`
|
${breakpoint("tablet")`
|
||||||
margin-left: ${props => (props.editMode ? 0 : props.theme.sidebarWidth)};
|
margin-left: ${props => (props.editMode ? 0 : props.theme.sidebarWidth)};
|
||||||
`};
|
`};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export default inject('auth', 'ui', 'documents')(withTheme(Layout));
|
export default inject("auth", "ui", "documents")(withTheme(Layout));
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import * as React from 'react';
|
import * as React from "react";
|
||||||
import styled from 'styled-components';
|
import styled from "styled-components";
|
||||||
import Flex from 'shared/components/Flex';
|
import Flex from "shared/components/Flex";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
image?: React.Node,
|
image?: React.Node,
|
||||||
@ -16,7 +16,7 @@ const ListItem = ({ image, title, subtitle, actions }: Props) => {
|
|||||||
return (
|
return (
|
||||||
<Wrapper compact={compact}>
|
<Wrapper compact={compact}>
|
||||||
{image && <Image>{image}</Image>}
|
{image && <Image>{image}</Image>}
|
||||||
<Content align={compact ? 'center' : undefined} column={!compact}>
|
<Content align={compact ? "center" : undefined} column={!compact}>
|
||||||
<Heading>{title}</Heading>
|
<Heading>{title}</Heading>
|
||||||
{subtitle && <Subtitle>{subtitle}</Subtitle>}
|
{subtitle && <Subtitle>{subtitle}</Subtitle>}
|
||||||
</Content>
|
</Content>
|
||||||
@ -27,7 +27,7 @@ const ListItem = ({ image, title, subtitle, actions }: Props) => {
|
|||||||
|
|
||||||
const Wrapper = styled.li`
|
const Wrapper = styled.li`
|
||||||
display: flex;
|
display: flex;
|
||||||
padding: ${props => (props.compact ? '8px' : '12px')} 0;
|
padding: ${props => (props.compact ? "8px" : "12px")} 0;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
border-bottom: 1px solid ${props => props.theme.divider};
|
border-bottom: 1px solid ${props => props.theme.divider};
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import styled from 'styled-components';
|
import styled from "styled-components";
|
||||||
|
|
||||||
const List = styled.ol`
|
const List = styled.ol`
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import * as React from 'react';
|
import * as React from "react";
|
||||||
import { times } from 'lodash';
|
import { times } from "lodash";
|
||||||
import styled from 'styled-components';
|
import styled from "styled-components";
|
||||||
import Mask from 'components/Mask';
|
import Mask from "components/Mask";
|
||||||
import Fade from 'components/Fade';
|
import Fade from "components/Fade";
|
||||||
import Flex from 'shared/components/Flex';
|
import Flex from "shared/components/Flex";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
count?: number,
|
count?: number,
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import List from './List';
|
import List from "./List";
|
||||||
export default List;
|
export default List;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
// @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';
|
import UiStore from "stores/UiStore";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
ui: UiStore,
|
ui: UiStore,
|
||||||
@ -22,4 +22,4 @@ class LoadingIndicator extends React.Component<Props> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default inject('ui')(LoadingIndicator);
|
export default inject("ui")(LoadingIndicator);
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import * as React from 'react';
|
import * as React from "react";
|
||||||
import styled, { keyframes } from 'styled-components';
|
import styled, { keyframes } from "styled-components";
|
||||||
|
|
||||||
const LoadingIndicatorBar = () => {
|
const LoadingIndicatorBar = () => {
|
||||||
return (
|
return (
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import LoadingIndicator from './LoadingIndicator';
|
import LoadingIndicator from "./LoadingIndicator";
|
||||||
import LoadingIndicatorBar from './LoadingIndicatorBar';
|
import LoadingIndicatorBar from "./LoadingIndicatorBar";
|
||||||
export default LoadingIndicator;
|
export default LoadingIndicator;
|
||||||
export { LoadingIndicatorBar };
|
export { LoadingIndicatorBar };
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import * as React from 'react';
|
import * as React from "react";
|
||||||
import { times } from 'lodash';
|
import { times } from "lodash";
|
||||||
import styled from 'styled-components';
|
import styled from "styled-components";
|
||||||
import Mask from 'components/Mask';
|
import Mask from "components/Mask";
|
||||||
import Fade from 'components/Fade';
|
import Fade from "components/Fade";
|
||||||
import Flex from 'shared/components/Flex';
|
import Flex from "shared/components/Flex";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
count?: number,
|
count?: number,
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import * as React from 'react';
|
import * as React from "react";
|
||||||
import styled from 'styled-components';
|
import styled from "styled-components";
|
||||||
import Mask from 'components/Mask';
|
import Mask from "components/Mask";
|
||||||
import Fade from 'components/Fade';
|
import Fade from "components/Fade";
|
||||||
import Flex from 'shared/components/Flex';
|
import Flex from "shared/components/Flex";
|
||||||
|
|
||||||
export default function LoadingPlaceholder(props: Object) {
|
export default function LoadingPlaceholder(props: Object) {
|
||||||
return (
|
return (
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import LoadingPlaceholder from './LoadingPlaceholder';
|
import LoadingPlaceholder from "./LoadingPlaceholder";
|
||||||
import ListPlaceholder from './ListPlaceholder';
|
import ListPlaceholder from "./ListPlaceholder";
|
||||||
|
|
||||||
export default LoadingPlaceholder;
|
export default LoadingPlaceholder;
|
||||||
export { ListPlaceholder };
|
export { ListPlaceholder };
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import * as React from 'react';
|
import * as React from "react";
|
||||||
import styled from 'styled-components';
|
import styled from "styled-components";
|
||||||
import { pulsate } from 'shared/styles/animations';
|
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";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
header?: boolean,
|
header?: boolean,
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import * as React from 'react';
|
import * as React from "react";
|
||||||
import { observer } from 'mobx-react';
|
import { observer } from "mobx-react";
|
||||||
import styled, { createGlobalStyle } from 'styled-components';
|
import styled, { createGlobalStyle } from "styled-components";
|
||||||
import breakpoint from 'styled-components-breakpoint';
|
import breakpoint from "styled-components-breakpoint";
|
||||||
import ReactModal from 'react-modal';
|
import ReactModal from "react-modal";
|
||||||
import { transparentize } from 'polished';
|
import { transparentize } from "polished";
|
||||||
import { CloseIcon, BackIcon } from 'outline-icons';
|
import { CloseIcon, BackIcon } from "outline-icons";
|
||||||
import NudeButton from 'components/NudeButton';
|
import NudeButton from "components/NudeButton";
|
||||||
import { fadeAndScaleIn } from 'shared/styles/animations';
|
import { fadeAndScaleIn } from "shared/styles/animations";
|
||||||
import Flex from 'shared/components/Flex';
|
import Flex from "shared/components/Flex";
|
||||||
|
|
||||||
ReactModal.setAppElement('#root');
|
ReactModal.setAppElement("#root");
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
children?: React.Node,
|
children?: React.Node,
|
||||||
@ -26,7 +26,7 @@ const GlobalStyles = createGlobalStyle`
|
|||||||
z-index: 100;
|
z-index: 100;
|
||||||
}
|
}
|
||||||
|
|
||||||
${breakpoint('tablet')`
|
${breakpoint("tablet")`
|
||||||
.ReactModalPortal + .ReactModalPortal {
|
.ReactModalPortal + .ReactModalPortal {
|
||||||
.ReactModal__Overlay {
|
.ReactModal__Overlay {
|
||||||
margin-left: 12px;
|
margin-left: 12px;
|
||||||
@ -57,7 +57,7 @@ const GlobalStyles = createGlobalStyle`
|
|||||||
const Modal = ({
|
const Modal = ({
|
||||||
children,
|
children,
|
||||||
isOpen,
|
isOpen,
|
||||||
title = 'Untitled',
|
title = "Untitled",
|
||||||
onRequestClose,
|
onRequestClose,
|
||||||
...rest
|
...rest
|
||||||
}: Props) => {
|
}: Props) => {
|
||||||
@ -114,7 +114,7 @@ const StyledModal = styled(ReactModal)`
|
|||||||
padding: 8vh 2rem 2rem;
|
padding: 8vh 2rem 2rem;
|
||||||
outline: none;
|
outline: none;
|
||||||
|
|
||||||
${breakpoint('tablet')`
|
${breakpoint("tablet")`
|
||||||
padding-top: 13vh;
|
padding-top: 13vh;
|
||||||
`};
|
`};
|
||||||
`;
|
`;
|
||||||
@ -141,7 +141,7 @@ const Close = styled(NudeButton)`
|
|||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
${breakpoint('tablet')`
|
${breakpoint("tablet")`
|
||||||
display: none;
|
display: none;
|
||||||
`};
|
`};
|
||||||
`;
|
`;
|
||||||
@ -161,7 +161,7 @@ const Back = styled(NudeButton)`
|
|||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
${breakpoint('tablet')`
|
${breakpoint("tablet")`
|
||||||
display: flex;
|
display: flex;
|
||||||
`};
|
`};
|
||||||
`;
|
`;
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import * as React from 'react';
|
import * as React from "react";
|
||||||
import { observer } from 'mobx-react';
|
import { observer } from "mobx-react";
|
||||||
import BaseModal from 'components/Modal';
|
import BaseModal from "components/Modal";
|
||||||
import UiStore from 'stores/UiStore';
|
import UiStore from "stores/UiStore";
|
||||||
import CollectionNew from 'scenes/CollectionNew';
|
import CollectionNew from "scenes/CollectionNew";
|
||||||
import CollectionEdit from 'scenes/CollectionEdit';
|
import CollectionEdit from "scenes/CollectionEdit";
|
||||||
import CollectionDelete from 'scenes/CollectionDelete';
|
import CollectionDelete from "scenes/CollectionDelete";
|
||||||
import CollectionExport from 'scenes/CollectionExport';
|
import CollectionExport from "scenes/CollectionExport";
|
||||||
import DocumentDelete from 'scenes/DocumentDelete';
|
import DocumentDelete from "scenes/DocumentDelete";
|
||||||
import DocumentShare from 'scenes/DocumentShare';
|
import DocumentShare from "scenes/DocumentShare";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
ui: UiStore,
|
ui: UiStore,
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import * as React from 'react';
|
import * as React from "react";
|
||||||
import styled from 'styled-components';
|
import styled from "styled-components";
|
||||||
import { lighten } from 'polished';
|
import { lighten } from "polished";
|
||||||
|
|
||||||
const Button = styled.button`
|
const Button = styled.button`
|
||||||
width: 24px;
|
width: 24px;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import * as React from 'react';
|
import * as React from "react";
|
||||||
import { Helmet } from 'react-helmet';
|
import { Helmet } from "react-helmet";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
title: string,
|
title: string,
|
||||||
@ -13,7 +13,7 @@ const PageTitle = ({ title, favicon }: Props) => (
|
|||||||
<link
|
<link
|
||||||
rel="shortcut icon"
|
rel="shortcut icon"
|
||||||
type="image/png"
|
type="image/png"
|
||||||
href={favicon || '/favicon-32.png'}
|
href={favicon || "/favicon-32.png"}
|
||||||
sizes="32x32"
|
sizes="32x32"
|
||||||
/>
|
/>
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import * as React from 'react';
|
import * as React from "react";
|
||||||
import { observer } from 'mobx-react';
|
import { observer } from "mobx-react";
|
||||||
import Document from 'models/Document';
|
import Document from "models/Document";
|
||||||
import DocumentPreview from 'components/DocumentPreview';
|
import DocumentPreview from "components/DocumentPreview";
|
||||||
import PaginatedList from 'components/PaginatedList';
|
import PaginatedList from "components/PaginatedList";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
documents: Document[],
|
documents: Document[],
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import * as React from 'react';
|
import * as React from "react";
|
||||||
import { observable, action } from 'mobx';
|
import { observable, action } from "mobx";
|
||||||
import { observer } from 'mobx-react';
|
import { observer } from "mobx-react";
|
||||||
import { Waypoint } from 'react-waypoint';
|
import { Waypoint } from "react-waypoint";
|
||||||
import ArrowKeyNavigation from 'boundless-arrow-key-navigation';
|
import ArrowKeyNavigation from "boundless-arrow-key-navigation";
|
||||||
|
|
||||||
import { DEFAULT_PAGINATION_LIMIT } from 'stores/BaseStore';
|
import { DEFAULT_PAGINATION_LIMIT } from "stores/BaseStore";
|
||||||
import { ListPlaceholder } from 'components/LoadingPlaceholder';
|
import { ListPlaceholder } from "components/LoadingPlaceholder";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
fetch?: (options: ?Object) => Promise<void>,
|
fetch?: (options: ?Object) => Promise<void>,
|
||||||
|
@ -1,21 +1,21 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import * as React from 'react';
|
import * as React from "react";
|
||||||
import { observer } from 'mobx-react';
|
import { observer } from "mobx-react";
|
||||||
import styled from 'styled-components';
|
import styled from "styled-components";
|
||||||
import { GoToIcon } from 'outline-icons';
|
import { GoToIcon } from "outline-icons";
|
||||||
import Flex from 'shared/components/Flex';
|
import Flex from "shared/components/Flex";
|
||||||
|
|
||||||
import Document from 'models/Document';
|
import Document from "models/Document";
|
||||||
import Collection from 'models/Collection';
|
import Collection from "models/Collection";
|
||||||
import type { DocumentPath } from 'stores/CollectionsStore';
|
import type { DocumentPath } from "stores/CollectionsStore";
|
||||||
import CollectionIcon from 'components/CollectionIcon';
|
import CollectionIcon from "components/CollectionIcon";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
result: DocumentPath,
|
result: DocumentPath,
|
||||||
document?: ?Document,
|
document?: ?Document,
|
||||||
collection: ?Collection,
|
collection: ?Collection,
|
||||||
onSuccess?: () => void,
|
onSuccess?: () => void,
|
||||||
ref?: (?React.ElementRef<'div'>) => void,
|
ref?: (?React.ElementRef<"div">) => void,
|
||||||
};
|
};
|
||||||
|
|
||||||
@observer
|
@observer
|
||||||
@ -25,7 +25,7 @@ class PathToDocument extends React.Component<Props> {
|
|||||||
const { document, result, onSuccess } = this.props;
|
const { document, result, onSuccess } = this.props;
|
||||||
if (!document) return;
|
if (!document) return;
|
||||||
|
|
||||||
if (result.type === 'document') {
|
if (result.type === "document") {
|
||||||
await document.move(result.collectionId, result.id);
|
await document.move(result.collectionId, result.id);
|
||||||
} else {
|
} else {
|
||||||
await document.move(result.collectionId, null);
|
await document.move(result.collectionId, null);
|
||||||
@ -48,7 +48,7 @@ class PathToDocument extends React.Component<Props> {
|
|||||||
.reduce((prev, curr) => [prev, <StyledGoToIcon />, curr])}
|
.reduce((prev, curr) => [prev, <StyledGoToIcon />, curr])}
|
||||||
{document && (
|
{document && (
|
||||||
<Flex>
|
<Flex>
|
||||||
{' '}
|
{" "}
|
||||||
<StyledGoToIcon /> <Title>{document.title}</Title>
|
<StyledGoToIcon /> <Title>{document.title}</Title>
|
||||||
</Flex>
|
</Flex>
|
||||||
)}
|
)}
|
||||||
@ -77,7 +77,7 @@ const ResultWrapper = styled.div`
|
|||||||
cursor: default;
|
cursor: default;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const ResultWrapperLink = styled(ResultWrapper.withComponent('a'))`
|
const ResultWrapperLink = styled(ResultWrapper.withComponent("a"))`
|
||||||
margin: 0 -8px;
|
margin: 0 -8px;
|
||||||
padding: 8px 4px;
|
padding: 8px 4px;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import * as React from 'react';
|
import * as React from "react";
|
||||||
import BoundlessPopover from 'boundless-popover';
|
import BoundlessPopover from "boundless-popover";
|
||||||
import styled, { keyframes } from 'styled-components';
|
import styled, { keyframes } from "styled-components";
|
||||||
|
|
||||||
const fadeIn = keyframes`
|
const fadeIn = keyframes`
|
||||||
from {
|
from {
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
// @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 styled from 'styled-components';
|
import styled from "styled-components";
|
||||||
import Document from 'models/Document';
|
import Document from "models/Document";
|
||||||
import Flex from 'shared/components/Flex';
|
import Flex from "shared/components/Flex";
|
||||||
import Time from 'shared/components/Time';
|
import Time from "shared/components/Time";
|
||||||
import Breadcrumb from 'shared/components/Breadcrumb';
|
import Breadcrumb from "shared/components/Breadcrumb";
|
||||||
import CollectionsStore from 'stores/CollectionsStore';
|
import CollectionsStore from "stores/CollectionsStore";
|
||||||
import AuthStore from 'stores/AuthStore';
|
import AuthStore from "stores/AuthStore";
|
||||||
|
|
||||||
const Container = styled(Flex)`
|
const Container = styled(Flex)`
|
||||||
color: ${props => props.theme.textTertiary};
|
color: ${props => props.theme.textTertiary};
|
||||||
@ -19,7 +19,7 @@ const Container = styled(Flex)`
|
|||||||
const Modified = styled.span`
|
const Modified = styled.span`
|
||||||
color: ${props =>
|
color: ${props =>
|
||||||
props.highlight ? props.theme.text : props.theme.textTertiary};
|
props.highlight ? props.theme.text : props.theme.textTertiary};
|
||||||
font-weight: ${props => (props.highlight ? '600' : '400')};
|
font-weight: ${props => (props.highlight ? "600" : "400")};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
@ -102,7 +102,7 @@ function PublishingInfo({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Container align="center" {...rest}>
|
<Container align="center" {...rest}>
|
||||||
{updatedByMe ? 'You' : updatedBy.name}
|
{updatedByMe ? "You" : updatedBy.name}
|
||||||
{content}
|
{content}
|
||||||
{showCollection &&
|
{showCollection &&
|
||||||
collection && (
|
collection && (
|
||||||
@ -118,4 +118,4 @@ function PublishingInfo({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default inject('collections', 'auth')(observer(PublishingInfo));
|
export default inject("collections", "auth")(observer(PublishingInfo));
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
// @flow
|
// @flow
|
||||||
// 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';
|
import type { Location } from "react-router-dom";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
location: Location,
|
location: Location,
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import * as React from 'react';
|
import * as React from "react";
|
||||||
import { observable } from 'mobx';
|
import { observable } from "mobx";
|
||||||
import { observer } from 'mobx-react';
|
import { observer } from "mobx-react";
|
||||||
import styled from 'styled-components';
|
import styled from "styled-components";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
shadow?: boolean,
|
shadow?: boolean,
|
||||||
@ -32,7 +32,7 @@ const Wrapper = styled.div`
|
|||||||
overscroll-behavior: none;
|
overscroll-behavior: none;
|
||||||
-webkit-overflow-scrolling: touch;
|
-webkit-overflow-scrolling: touch;
|
||||||
box-shadow: ${props =>
|
box-shadow: ${props =>
|
||||||
props.shadow ? '0 1px inset rgba(0,0,0,.1)' : 'none'};
|
props.shadow ? "0 1px inset rgba(0,0,0,.1)" : "none"};
|
||||||
transition: all 250ms ease-in-out;
|
transition: all 250ms ease-in-out;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
@ -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 styled from 'styled-components';
|
import styled from "styled-components";
|
||||||
import {
|
import {
|
||||||
ArchiveIcon,
|
ArchiveIcon,
|
||||||
HomeIcon,
|
HomeIcon,
|
||||||
@ -10,25 +10,25 @@ import {
|
|||||||
StarredIcon,
|
StarredIcon,
|
||||||
TrashIcon,
|
TrashIcon,
|
||||||
PlusIcon,
|
PlusIcon,
|
||||||
} from 'outline-icons';
|
} from "outline-icons";
|
||||||
|
|
||||||
import Flex from 'shared/components/Flex';
|
import Flex from "shared/components/Flex";
|
||||||
import Modal from 'components/Modal';
|
import Modal from "components/Modal";
|
||||||
import Invite from 'scenes/Invite';
|
import Invite from "scenes/Invite";
|
||||||
import AccountMenu from 'menus/AccountMenu';
|
import AccountMenu from "menus/AccountMenu";
|
||||||
import Sidebar from './Sidebar';
|
import Sidebar from "./Sidebar";
|
||||||
import Scrollable from 'components/Scrollable';
|
import Scrollable from "components/Scrollable";
|
||||||
import Section from './components/Section';
|
import Section from "./components/Section";
|
||||||
import Collections from './components/Collections';
|
import Collections from "./components/Collections";
|
||||||
import SidebarLink from './components/SidebarLink';
|
import SidebarLink from "./components/SidebarLink";
|
||||||
import HeaderBlock from './components/HeaderBlock';
|
import HeaderBlock from "./components/HeaderBlock";
|
||||||
import Bubble from './components/Bubble';
|
import Bubble from "./components/Bubble";
|
||||||
|
|
||||||
import AuthStore from 'stores/AuthStore';
|
import AuthStore from "stores/AuthStore";
|
||||||
import DocumentsStore from 'stores/DocumentsStore';
|
import DocumentsStore from "stores/DocumentsStore";
|
||||||
import PoliciesStore from 'stores/PoliciesStore';
|
import PoliciesStore from "stores/PoliciesStore";
|
||||||
import UiStore from 'stores/UiStore';
|
import UiStore from "stores/UiStore";
|
||||||
import { observable } from 'mobx';
|
import { observable } from "mobx";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
auth: AuthStore,
|
auth: AuthStore,
|
||||||
@ -47,7 +47,7 @@ class MainSidebar extends React.Component<Props> {
|
|||||||
|
|
||||||
handleCreateCollection = (ev: SyntheticEvent<>) => {
|
handleCreateCollection = (ev: SyntheticEvent<>) => {
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
this.props.ui.setActiveModal('collection-new');
|
this.props.ui.setActiveModal("collection-new");
|
||||||
};
|
};
|
||||||
|
|
||||||
handleInviteModalOpen = (ev: SyntheticEvent<>) => {
|
handleInviteModalOpen = (ev: SyntheticEvent<>) => {
|
||||||
@ -90,7 +90,7 @@ class MainSidebar extends React.Component<Props> {
|
|||||||
/>
|
/>
|
||||||
<SidebarLink
|
<SidebarLink
|
||||||
to={{
|
to={{
|
||||||
pathname: '/search',
|
pathname: "/search",
|
||||||
state: { fromMenu: true },
|
state: { fromMenu: true },
|
||||||
}}
|
}}
|
||||||
icon={<SearchIcon color="currentColor" />}
|
icon={<SearchIcon color="currentColor" />}
|
||||||
@ -172,4 +172,4 @@ const Drafts = styled(Flex)`
|
|||||||
height: 24px;
|
height: 24px;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export default inject('documents', 'policies', 'auth', 'ui')(MainSidebar);
|
export default inject("documents", "policies", "auth", "ui")(MainSidebar);
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
// @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 type { RouterHistory } from "react-router-dom";
|
||||||
import styled from 'styled-components';
|
import styled from "styled-components";
|
||||||
import {
|
import {
|
||||||
DocumentIcon,
|
DocumentIcon,
|
||||||
EmailIcon,
|
EmailIcon,
|
||||||
@ -15,20 +15,20 @@ import {
|
|||||||
TeamIcon,
|
TeamIcon,
|
||||||
BulletedListIcon,
|
BulletedListIcon,
|
||||||
ExpandedIcon,
|
ExpandedIcon,
|
||||||
} from 'outline-icons';
|
} from "outline-icons";
|
||||||
import ZapierIcon from './icons/Zapier';
|
import ZapierIcon from "./icons/Zapier";
|
||||||
import SlackIcon from './icons/Slack';
|
import SlackIcon from "./icons/Slack";
|
||||||
|
|
||||||
import Flex from 'shared/components/Flex';
|
import Flex from "shared/components/Flex";
|
||||||
import Sidebar from './Sidebar';
|
import Sidebar from "./Sidebar";
|
||||||
import Scrollable from 'components/Scrollable';
|
import Scrollable from "components/Scrollable";
|
||||||
import Section from './components/Section';
|
import Section from "./components/Section";
|
||||||
import Header from './components/Header';
|
import Header from "./components/Header";
|
||||||
import SidebarLink from './components/SidebarLink';
|
import SidebarLink from "./components/SidebarLink";
|
||||||
import HeaderBlock from './components/HeaderBlock';
|
import HeaderBlock from "./components/HeaderBlock";
|
||||||
import Version from './components/Version';
|
import Version from "./components/Version";
|
||||||
import PoliciesStore from 'stores/PoliciesStore';
|
import PoliciesStore from "stores/PoliciesStore";
|
||||||
import AuthStore from 'stores/AuthStore';
|
import AuthStore from "stores/AuthStore";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
history: RouterHistory,
|
history: RouterHistory,
|
||||||
@ -39,7 +39,7 @@ type Props = {
|
|||||||
@observer
|
@observer
|
||||||
class SettingsSidebar extends React.Component<Props> {
|
class SettingsSidebar extends React.Component<Props> {
|
||||||
returnToDashboard = () => {
|
returnToDashboard = () => {
|
||||||
this.props.history.push('/');
|
this.props.history.push("/");
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
@ -146,7 +146,7 @@ class SettingsSidebar extends React.Component<Props> {
|
|||||||
</Section>
|
</Section>
|
||||||
)}
|
)}
|
||||||
{can.update &&
|
{can.update &&
|
||||||
process.env.DEPLOYMENT !== 'hosted' && (
|
process.env.DEPLOYMENT !== "hosted" && (
|
||||||
<Section>
|
<Section>
|
||||||
<Header>Installation</Header>
|
<Header>Installation</Header>
|
||||||
<Version />
|
<Version />
|
||||||
@ -168,4 +168,4 @@ const ReturnToApp = styled(Flex)`
|
|||||||
height: 16px;
|
height: 16px;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export default inject('auth', 'policies')(SettingsSidebar);
|
export default inject("auth", "policies")(SettingsSidebar);
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
// @flow
|
// @flow
|
||||||
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';
|
import type { Location } from "react-router-dom";
|
||||||
import styled from 'styled-components';
|
import styled from "styled-components";
|
||||||
import breakpoint from 'styled-components-breakpoint';
|
import breakpoint from "styled-components-breakpoint";
|
||||||
import { observer, inject } from 'mobx-react';
|
import { observer, inject } from "mobx-react";
|
||||||
import { CloseIcon, MenuIcon } from 'outline-icons';
|
import { CloseIcon, MenuIcon } from "outline-icons";
|
||||||
import Fade from 'components/Fade';
|
import Fade from "components/Fade";
|
||||||
import Flex from 'shared/components/Flex';
|
import Flex from "shared/components/Flex";
|
||||||
import UiStore from 'stores/UiStore';
|
import UiStore from "stores/UiStore";
|
||||||
|
|
||||||
let firstRender = true;
|
let firstRender = true;
|
||||||
|
|
||||||
@ -69,7 +69,7 @@ const Container = styled(Flex)`
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
background: ${props => props.theme.sidebarBackground};
|
background: ${props => props.theme.sidebarBackground};
|
||||||
transition: left 100ms ease-out, ${props => props.theme.backgroundTransition};
|
transition: left 100ms ease-out, ${props => props.theme.backgroundTransition};
|
||||||
margin-left: ${props => (props.mobileSidebarVisible ? 0 : '-100%')};
|
margin-left: ${props => (props.mobileSidebarVisible ? 0 : "-100%")};
|
||||||
z-index: 1000;
|
z-index: 1000;
|
||||||
|
|
||||||
@media print {
|
@media print {
|
||||||
@ -79,7 +79,7 @@ const Container = styled(Flex)`
|
|||||||
|
|
||||||
&:before,
|
&:before,
|
||||||
&:after {
|
&:after {
|
||||||
content: '';
|
content: "";
|
||||||
background: ${props => props.theme.sidebarBackground};
|
background: ${props => props.theme.sidebarBackground};
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: -50vh;
|
top: -50vh;
|
||||||
@ -93,7 +93,7 @@ const Container = styled(Flex)`
|
|||||||
bottom: -50vh;
|
bottom: -50vh;
|
||||||
}
|
}
|
||||||
|
|
||||||
${breakpoint('tablet')`
|
${breakpoint("tablet")`
|
||||||
left: ${props => (props.editMode ? `-${props.theme.sidebarWidth}` : 0)};
|
left: ${props => (props.editMode ? `-${props.theme.sidebarWidth}` : 0)};
|
||||||
width: ${props => props.theme.sidebarWidth};
|
width: ${props => props.theme.sidebarWidth};
|
||||||
margin: 0;
|
margin: 0;
|
||||||
@ -106,14 +106,14 @@ const Toggle = styled.a`
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
position: fixed;
|
position: fixed;
|
||||||
top: 0;
|
top: 0;
|
||||||
left: ${props => (props.mobileSidebarVisible ? 'auto' : 0)};
|
left: ${props => (props.mobileSidebarVisible ? "auto" : 0)};
|
||||||
right: ${props => (props.mobileSidebarVisible ? 0 : 'auto')};
|
right: ${props => (props.mobileSidebarVisible ? 0 : "auto")};
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
margin: 12px;
|
margin: 12px;
|
||||||
|
|
||||||
${breakpoint('tablet')`
|
${breakpoint("tablet")`
|
||||||
display: none;
|
display: none;
|
||||||
`};
|
`};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export default withRouter(inject('ui')(Sidebar));
|
export default withRouter(inject("ui")(Sidebar));
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import * as React from 'react';
|
import * as React from "react";
|
||||||
import styled from 'styled-components';
|
import styled from "styled-components";
|
||||||
import { bounceIn } from 'shared/styles/animations';
|
import { bounceIn } from "shared/styles/animations";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
count: number,
|
count: number,
|
||||||
@ -17,7 +17,7 @@ const Count = styled.div`
|
|||||||
color: ${props => props.theme.white};
|
color: ${props => props.theme.white};
|
||||||
background: ${props => props.theme.slateDark};
|
background: ${props => props.theme.slateDark};
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
font-feature-settings: 'tnum';
|
font-feature-settings: "tnum";
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
font-size: 9px;
|
font-size: 9px;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
|
@ -1,17 +1,17 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import * as React from 'react';
|
import * as React from "react";
|
||||||
import { observer } from 'mobx-react';
|
import { observer } from "mobx-react";
|
||||||
import { observable } from 'mobx';
|
import { observable } from "mobx";
|
||||||
import Collection from 'models/Collection';
|
import Collection from "models/Collection";
|
||||||
import Document from 'models/Document';
|
import Document from "models/Document";
|
||||||
import CollectionMenu from 'menus/CollectionMenu';
|
import CollectionMenu from "menus/CollectionMenu";
|
||||||
import UiStore from 'stores/UiStore';
|
import UiStore from "stores/UiStore";
|
||||||
import DocumentsStore from 'stores/DocumentsStore';
|
import DocumentsStore from "stores/DocumentsStore";
|
||||||
import SidebarLink from './SidebarLink';
|
import SidebarLink from "./SidebarLink";
|
||||||
import DocumentLink from './DocumentLink';
|
import DocumentLink from "./DocumentLink";
|
||||||
import CollectionIcon from 'components/CollectionIcon';
|
import CollectionIcon from "components/CollectionIcon";
|
||||||
import DropToImport from 'components/DropToImport';
|
import DropToImport from "components/DropToImport";
|
||||||
import Flex from 'shared/components/Flex';
|
import Flex from "shared/components/Flex";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
collection: Collection,
|
collection: Collection,
|
||||||
|
@ -1,22 +1,22 @@
|
|||||||
// @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, type RouterHistory } 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";
|
||||||
import { newDocumentUrl } from 'utils/routeHelpers';
|
import { newDocumentUrl } from "utils/routeHelpers";
|
||||||
|
|
||||||
import Header from './Header';
|
import Header from "./Header";
|
||||||
import SidebarLink from './SidebarLink';
|
import SidebarLink from "./SidebarLink";
|
||||||
import CollectionLink from './CollectionLink';
|
import CollectionLink from "./CollectionLink";
|
||||||
import CollectionsLoading from './CollectionsLoading';
|
import CollectionsLoading from "./CollectionsLoading";
|
||||||
import Fade from 'components/Fade';
|
import Fade from "components/Fade";
|
||||||
|
|
||||||
import CollectionsStore from 'stores/CollectionsStore';
|
import CollectionsStore from "stores/CollectionsStore";
|
||||||
import PoliciesStore from 'stores/PoliciesStore';
|
import PoliciesStore from "stores/PoliciesStore";
|
||||||
import UiStore from 'stores/UiStore';
|
import UiStore from "stores/UiStore";
|
||||||
import DocumentsStore from 'stores/DocumentsStore';
|
import DocumentsStore from "stores/DocumentsStore";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
history: RouterHistory,
|
history: RouterHistory,
|
||||||
@ -39,7 +39,7 @@ class Collections extends React.Component<Props> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@keydown('n')
|
@keydown("n")
|
||||||
goToNewDocument() {
|
goToNewDocument() {
|
||||||
if (this.props.ui.editMode) return;
|
if (this.props.ui.editMode) return;
|
||||||
|
|
||||||
@ -94,6 +94,6 @@ class Collections extends React.Component<Props> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default inject('collections', 'ui', 'documents', 'policies')(
|
export default inject("collections", "ui", "documents", "policies")(
|
||||||
withRouter(Collections)
|
withRouter(Collections)
|
||||||
);
|
);
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import * as React from 'react';
|
import * as React from "react";
|
||||||
import styled from 'styled-components';
|
import styled from "styled-components";
|
||||||
import Mask from 'components/Mask';
|
import Mask from "components/Mask";
|
||||||
|
|
||||||
function CollectionsLoading() {
|
function CollectionsLoading() {
|
||||||
return (
|
return (
|
||||||
|
@ -1,17 +1,17 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import * as React from 'react';
|
import * as React from "react";
|
||||||
import { observer } from 'mobx-react';
|
import { observer } from "mobx-react";
|
||||||
import { observable } from 'mobx';
|
import { observable } from "mobx";
|
||||||
import styled from 'styled-components';
|
import styled from "styled-components";
|
||||||
import Document from 'models/Document';
|
import Document from "models/Document";
|
||||||
import DocumentMenu from 'menus/DocumentMenu';
|
import DocumentMenu from "menus/DocumentMenu";
|
||||||
import SidebarLink from './SidebarLink';
|
import SidebarLink from "./SidebarLink";
|
||||||
import DropToImport from 'components/DropToImport';
|
import DropToImport from "components/DropToImport";
|
||||||
import Fade from 'components/Fade';
|
import Fade from "components/Fade";
|
||||||
import Collection from 'models/Collection';
|
import Collection from "models/Collection";
|
||||||
import DocumentsStore from 'stores/DocumentsStore';
|
import DocumentsStore from "stores/DocumentsStore";
|
||||||
import Flex from 'shared/components/Flex';
|
import Flex from "shared/components/Flex";
|
||||||
import { type NavigationNode } from 'types';
|
import { type NavigationNode } from "types";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
node: NavigationNode,
|
node: NavigationNode,
|
||||||
@ -96,7 +96,7 @@ class DocumentLink extends React.Component<Props> {
|
|||||||
state: { title: node.title },
|
state: { title: node.title },
|
||||||
}}
|
}}
|
||||||
expanded={showChildren ? true : undefined}
|
expanded={showChildren ? true : undefined}
|
||||||
label={node.title || 'Untitled'}
|
label={node.title || "Untitled"}
|
||||||
depth={depth}
|
depth={depth}
|
||||||
exact={false}
|
exact={false}
|
||||||
menuOpen={this.menuOpen}
|
menuOpen={this.menuOpen}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import Flex from 'shared/components/Flex';
|
import Flex from "shared/components/Flex";
|
||||||
import styled from 'styled-components';
|
import styled from "styled-components";
|
||||||
|
|
||||||
const Header = styled(Flex)`
|
const Header = styled(Flex)`
|
||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import * as React from 'react';
|
import * as React from "react";
|
||||||
import styled, { withTheme } from 'styled-components';
|
import styled, { withTheme } from "styled-components";
|
||||||
import { ExpandedIcon } from 'outline-icons';
|
import { ExpandedIcon } from "outline-icons";
|
||||||
import Flex from 'shared/components/Flex';
|
import Flex from "shared/components/Flex";
|
||||||
import TeamLogo from 'shared/components/TeamLogo';
|
import TeamLogo from "shared/components/TeamLogo";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
teamName: string,
|
teamName: string,
|
||||||
@ -26,7 +26,7 @@ function HeaderBlock({
|
|||||||
<TeamLogo alt={`${teamName} logo`} src={logoUrl} />
|
<TeamLogo alt={`${teamName} logo`} src={logoUrl} />
|
||||||
<Flex align="flex-start" column>
|
<Flex align="flex-start" column>
|
||||||
<TeamName showDisclosure>
|
<TeamName showDisclosure>
|
||||||
{teamName}{' '}
|
{teamName}{" "}
|
||||||
{showDisclosure && <StyledExpandedIcon color={theme.text} />}
|
{showDisclosure && <StyledExpandedIcon color={theme.text} />}
|
||||||
</TeamName>
|
</TeamName>
|
||||||
<Subheading>{subheading}</Subheading>
|
<Subheading>{subheading}</Subheading>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import styled from 'styled-components';
|
import styled from "styled-components";
|
||||||
import Flex from 'shared/components/Flex';
|
import Flex from "shared/components/Flex";
|
||||||
|
|
||||||
const Section = styled(Flex)`
|
const Section = styled(Flex)`
|
||||||
position: relative;
|
position: relative;
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import * as React from 'react';
|
import * as React from "react";
|
||||||
import { observable, action } from 'mobx';
|
import { observable, action } from "mobx";
|
||||||
import { observer } from 'mobx-react';
|
import { observer } from "mobx-react";
|
||||||
import { withRouter, NavLink } from 'react-router-dom';
|
import { withRouter, NavLink } from "react-router-dom";
|
||||||
import { CollapsedIcon } from 'outline-icons';
|
import { CollapsedIcon } from "outline-icons";
|
||||||
import styled, { withTheme } from 'styled-components';
|
import styled, { withTheme } from "styled-components";
|
||||||
import Flex from 'shared/components/Flex';
|
import Flex from "shared/components/Flex";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
to?: string | Object,
|
to?: string | Object,
|
||||||
@ -82,7 +82,7 @@ class SidebarLink extends React.Component<Props> {
|
|||||||
onClick={onClick}
|
onClick={onClick}
|
||||||
exact={exact !== false}
|
exact={exact !== false}
|
||||||
to={to}
|
to={to}
|
||||||
as={to ? undefined : href ? 'a' : 'div'}
|
as={to ? undefined : href ? "a" : "div"}
|
||||||
href={href}
|
href={href}
|
||||||
>
|
>
|
||||||
{icon && <IconWrapper>{icon}</IconWrapper>}
|
{icon && <IconWrapper>{icon}</IconWrapper>}
|
||||||
@ -108,7 +108,7 @@ const IconWrapper = styled.span`
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
const Action = styled.span`
|
const Action = styled.span`
|
||||||
display: ${props => (props.menuOpen ? 'inline' : 'none')};
|
display: ${props => (props.menuOpen ? "inline" : "none")};
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 4px;
|
top: 4px;
|
||||||
right: 4px;
|
right: 4px;
|
||||||
@ -168,7 +168,7 @@ const Disclosure = styled(CollapsedIcon)`
|
|||||||
position: absolute;
|
position: absolute;
|
||||||
left: -24px;
|
left: -24px;
|
||||||
|
|
||||||
${({ expanded }) => !expanded && 'transform: rotate(-90deg);'};
|
${({ expanded }) => !expanded && "transform: rotate(-90deg);"};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export default withRouter(withTheme(SidebarLink));
|
export default withRouter(withTheme(SidebarLink));
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import * as React from 'react';
|
import * as React from "react";
|
||||||
import styled from 'styled-components';
|
import styled from "styled-components";
|
||||||
import Badge from 'components/Badge';
|
import Badge from "components/Badge";
|
||||||
import SidebarLink from './SidebarLink';
|
import SidebarLink from "./SidebarLink";
|
||||||
import { version } from '../../../../package.json';
|
import { version } from "../../../../package.json";
|
||||||
|
|
||||||
export default function Version() {
|
export default function Version() {
|
||||||
// $FlowFixMe
|
// $FlowFixMe
|
||||||
@ -14,7 +14,7 @@ export default function Version() {
|
|||||||
async function loadReleases() {
|
async function loadReleases() {
|
||||||
let out = 0;
|
let out = 0;
|
||||||
const res = await fetch(
|
const res = await fetch(
|
||||||
'https://api.github.com/repos/outline/outline/releases'
|
"https://api.github.com/repos/outline/outline/releases"
|
||||||
);
|
);
|
||||||
const releases = await res.json();
|
const releases = await res.json();
|
||||||
for (const release of releases) {
|
for (const release of releases) {
|
||||||
@ -37,9 +37,9 @@ export default function Version() {
|
|||||||
<br />
|
<br />
|
||||||
<LilBadge>
|
<LilBadge>
|
||||||
{releasesBehind === 0
|
{releasesBehind === 0
|
||||||
? 'Up to date'
|
? "Up to date"
|
||||||
: `${releasesBehind} version${
|
: `${releasesBehind} version${
|
||||||
releasesBehind === 1 ? '' : 's'
|
releasesBehind === 1 ? "" : "s"
|
||||||
} behind`}
|
} behind`}
|
||||||
</LilBadge>
|
</LilBadge>
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import * as React from 'react';
|
import * as React from "react";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
color?: string,
|
color?: string,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function SlackIcon({ color = '#4E5C6E' }: Props) {
|
export default function SlackIcon({ color = "#4E5C6E" }: Props) {
|
||||||
return (
|
return (
|
||||||
<svg
|
<svg
|
||||||
fill={color}
|
fill={color}
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import * as React from 'react';
|
import * as React from "react";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
color?: string,
|
color?: string,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function ZapierIcon({ color = '#4E5C6E' }: Props) {
|
export default function ZapierIcon({ color = "#4E5C6E" }: Props) {
|
||||||
return (
|
return (
|
||||||
<svg
|
<svg
|
||||||
fill={color}
|
fill={color}
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import Sidebar from './Main';
|
import Sidebar from "./Main";
|
||||||
export default Sidebar;
|
export default Sidebar;
|
||||||
|
@ -1,18 +1,18 @@
|
|||||||
// @flow
|
// @flow
|
||||||
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 { find } from 'lodash';
|
import { find } from "lodash";
|
||||||
import io from 'socket.io-client';
|
import io from "socket.io-client";
|
||||||
import DocumentsStore from 'stores/DocumentsStore';
|
import DocumentsStore from "stores/DocumentsStore";
|
||||||
import CollectionsStore from 'stores/CollectionsStore';
|
import CollectionsStore from "stores/CollectionsStore";
|
||||||
import GroupsStore from 'stores/GroupsStore';
|
import GroupsStore from "stores/GroupsStore";
|
||||||
import MembershipsStore from 'stores/MembershipsStore';
|
import MembershipsStore from "stores/MembershipsStore";
|
||||||
import DocumentPresenceStore from 'stores/DocumentPresenceStore';
|
import DocumentPresenceStore from "stores/DocumentPresenceStore";
|
||||||
import PoliciesStore from 'stores/PoliciesStore';
|
import PoliciesStore from "stores/PoliciesStore";
|
||||||
import ViewsStore from 'stores/ViewsStore';
|
import ViewsStore from "stores/ViewsStore";
|
||||||
import AuthStore from 'stores/AuthStore';
|
import AuthStore from "stores/AuthStore";
|
||||||
import UiStore from 'stores/UiStore';
|
import UiStore from "stores/UiStore";
|
||||||
|
|
||||||
export const SocketContext: any = React.createContext();
|
export const SocketContext: any = React.createContext();
|
||||||
|
|
||||||
@ -37,7 +37,7 @@ class SocketProvider extends React.Component<Props> {
|
|||||||
if (!process.env.WEBSOCKETS_ENABLED) return;
|
if (!process.env.WEBSOCKETS_ENABLED) return;
|
||||||
|
|
||||||
this.socket = io(window.location.origin, {
|
this.socket = io(window.location.origin, {
|
||||||
path: '/realtime',
|
path: "/realtime",
|
||||||
});
|
});
|
||||||
this.socket.authenticated = false;
|
this.socket.authenticated = false;
|
||||||
|
|
||||||
@ -54,38 +54,38 @@ class SocketProvider extends React.Component<Props> {
|
|||||||
} = this.props;
|
} = this.props;
|
||||||
if (!auth.token) return;
|
if (!auth.token) return;
|
||||||
|
|
||||||
this.socket.on('connect', () => {
|
this.socket.on("connect", () => {
|
||||||
// immediately send current users token to the websocket backend where it
|
// immediately send current users token to the websocket backend where it
|
||||||
// is verified, if all goes well an 'authenticated' message will be
|
// is verified, if all goes well an 'authenticated' message will be
|
||||||
// received in response
|
// received in response
|
||||||
this.socket.emit('authentication', {
|
this.socket.emit("authentication", {
|
||||||
token: auth.token,
|
token: auth.token,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
this.socket.on('disconnect', () => {
|
this.socket.on("disconnect", () => {
|
||||||
// when the socket is disconnected we need to clear all presence state as
|
// when the socket is disconnected we need to clear all presence state as
|
||||||
// it's no longer reliable.
|
// it's no longer reliable.
|
||||||
presence.clear();
|
presence.clear();
|
||||||
});
|
});
|
||||||
|
|
||||||
this.socket.on('authenticated', () => {
|
this.socket.on("authenticated", () => {
|
||||||
this.socket.authenticated = true;
|
this.socket.authenticated = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
this.socket.on('unauthorized', err => {
|
this.socket.on("unauthorized", err => {
|
||||||
this.socket.authenticated = false;
|
this.socket.authenticated = false;
|
||||||
ui.showToast(err.message);
|
ui.showToast(err.message);
|
||||||
throw err;
|
throw err;
|
||||||
});
|
});
|
||||||
|
|
||||||
this.socket.on('entities', async event => {
|
this.socket.on("entities", async event => {
|
||||||
if (event.documentIds) {
|
if (event.documentIds) {
|
||||||
for (const documentDescriptor of event.documentIds) {
|
for (const documentDescriptor of event.documentIds) {
|
||||||
const documentId = documentDescriptor.id;
|
const documentId = documentDescriptor.id;
|
||||||
let document = documents.get(documentId) || {};
|
let document = documents.get(documentId) || {};
|
||||||
|
|
||||||
if (event.event === 'documents.delete') {
|
if (event.event === "documents.delete") {
|
||||||
const document = documents.get(documentId);
|
const document = documents.get(documentId);
|
||||||
if (document) {
|
if (document) {
|
||||||
document.deletedAt = documentDescriptor.updatedAt;
|
document.deletedAt = documentDescriptor.updatedAt;
|
||||||
@ -136,7 +136,7 @@ class SocketProvider extends React.Component<Props> {
|
|||||||
const collectionId = collectionDescriptor.id;
|
const collectionId = collectionDescriptor.id;
|
||||||
const collection = collections.get(collectionId) || {};
|
const collection = collections.get(collectionId) || {};
|
||||||
|
|
||||||
if (event.event === 'collections.delete') {
|
if (event.event === "collections.delete") {
|
||||||
documents.removeCollectionDocuments(collectionId);
|
documents.removeCollectionDocuments(collectionId);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -184,17 +184,17 @@ class SocketProvider extends React.Component<Props> {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
this.socket.on('documents.star', event => {
|
this.socket.on("documents.star", event => {
|
||||||
documents.starredIds.set(event.documentId, true);
|
documents.starredIds.set(event.documentId, true);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.socket.on('documents.unstar', event => {
|
this.socket.on("documents.unstar", event => {
|
||||||
documents.starredIds.set(event.documentId, false);
|
documents.starredIds.set(event.documentId, false);
|
||||||
});
|
});
|
||||||
|
|
||||||
// received when a user is given access to a collection
|
// received when a user is given access to a collection
|
||||||
// if the user is us then we go ahead and load the collection from API.
|
// if the user is us then we go ahead and load the collection from API.
|
||||||
this.socket.on('collections.add_user', event => {
|
this.socket.on("collections.add_user", event => {
|
||||||
if (auth.user && event.userId === auth.user.id) {
|
if (auth.user && event.userId === auth.user.id) {
|
||||||
collections.fetch(event.collectionId, { force: true });
|
collections.fetch(event.collectionId, { force: true });
|
||||||
}
|
}
|
||||||
@ -208,7 +208,7 @@ class SocketProvider extends React.Component<Props> {
|
|||||||
// received when a user is removed from having access to a collection
|
// received when a user is removed from having access to a collection
|
||||||
// to keep state in sync we must update our UI if the user is us,
|
// to keep state in sync we must update our UI if the user is us,
|
||||||
// or otherwise just remove any membership state we have for that user.
|
// or otherwise just remove any membership state we have for that user.
|
||||||
this.socket.on('collections.remove_user', event => {
|
this.socket.on("collections.remove_user", event => {
|
||||||
if (auth.user && event.userId === auth.user.id) {
|
if (auth.user && event.userId === auth.user.id) {
|
||||||
collections.remove(event.collectionId);
|
collections.remove(event.collectionId);
|
||||||
memberships.removeCollectionMemberships(event.collectionId);
|
memberships.removeCollectionMemberships(event.collectionId);
|
||||||
@ -220,32 +220,32 @@ class SocketProvider extends React.Component<Props> {
|
|||||||
|
|
||||||
// received a message from the API server that we should request
|
// received a message from the API server that we should request
|
||||||
// to join a specific room. Forward that to the ws server.
|
// to join a specific room. Forward that to the ws server.
|
||||||
this.socket.on('join', event => {
|
this.socket.on("join", event => {
|
||||||
this.socket.emit('join', event);
|
this.socket.emit("join", event);
|
||||||
});
|
});
|
||||||
|
|
||||||
// received a message from the API server that we should request
|
// received a message from the API server that we should request
|
||||||
// to leave a specific room. Forward that to the ws server.
|
// to leave a specific room. Forward that to the ws server.
|
||||||
this.socket.on('leave', event => {
|
this.socket.on("leave", event => {
|
||||||
this.socket.emit('leave', event);
|
this.socket.emit("leave", event);
|
||||||
});
|
});
|
||||||
|
|
||||||
// received whenever we join a document room, the payload includes
|
// received whenever we join a document room, the payload includes
|
||||||
// userIds that are present/viewing and those that are editing.
|
// userIds that are present/viewing and those that are editing.
|
||||||
this.socket.on('document.presence', event => {
|
this.socket.on("document.presence", event => {
|
||||||
presence.init(event.documentId, event.userIds, event.editingIds);
|
presence.init(event.documentId, event.userIds, event.editingIds);
|
||||||
});
|
});
|
||||||
|
|
||||||
// received whenever a new user joins a document room, aka they
|
// received whenever a new user joins a document room, aka they
|
||||||
// navigate to / start viewing a document
|
// navigate to / start viewing a document
|
||||||
this.socket.on('user.join', event => {
|
this.socket.on("user.join", event => {
|
||||||
presence.touch(event.documentId, event.userId, event.isEditing);
|
presence.touch(event.documentId, event.userId, event.isEditing);
|
||||||
views.touch(event.documentId, event.userId);
|
views.touch(event.documentId, event.userId);
|
||||||
});
|
});
|
||||||
|
|
||||||
// received whenever a new user leaves a document room, aka they
|
// received whenever a new user leaves a document room, aka they
|
||||||
// navigate away / stop viewing a document
|
// navigate away / stop viewing a document
|
||||||
this.socket.on('user.leave', event => {
|
this.socket.on("user.leave", event => {
|
||||||
presence.leave(event.documentId, event.userId);
|
presence.leave(event.documentId, event.userId);
|
||||||
views.touch(event.documentId, event.userId);
|
views.touch(event.documentId, event.userId);
|
||||||
});
|
});
|
||||||
@ -253,7 +253,7 @@ class SocketProvider extends React.Component<Props> {
|
|||||||
// received when another client in a document room wants to change
|
// received when another client in a document room wants to change
|
||||||
// or update it's presence. Currently the only property is whether
|
// or update it's presence. Currently the only property is whether
|
||||||
// the client is in editing state or not.
|
// the client is in editing state or not.
|
||||||
this.socket.on('user.presence', event => {
|
this.socket.on("user.presence", event => {
|
||||||
presence.touch(event.documentId, event.userId, event.isEditing);
|
presence.touch(event.documentId, event.userId, event.isEditing);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -275,13 +275,13 @@ class SocketProvider extends React.Component<Props> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default inject(
|
export default inject(
|
||||||
'auth',
|
"auth",
|
||||||
'ui',
|
"ui",
|
||||||
'documents',
|
"documents",
|
||||||
'collections',
|
"collections",
|
||||||
'groups',
|
"groups",
|
||||||
'memberships',
|
"memberships",
|
||||||
'presence',
|
"presence",
|
||||||
'policies',
|
"policies",
|
||||||
'views'
|
"views"
|
||||||
)(SocketProvider);
|
)(SocketProvider);
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import * as React from 'react';
|
import * as React from "react";
|
||||||
import styled from 'styled-components';
|
import styled from "styled-components";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
children: React.Node,
|
children: React.Node,
|
||||||
@ -13,7 +13,7 @@ const H3 = styled.h3`
|
|||||||
line-height: 1;
|
line-height: 1;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const Underline = styled('span')`
|
const Underline = styled("span")`
|
||||||
position: relative;
|
position: relative;
|
||||||
top: 1px;
|
top: 1px;
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import * as React from 'react';
|
import * as React from "react";
|
||||||
import styled from 'styled-components';
|
import styled from "styled-components";
|
||||||
import { LabelText } from 'components/Input';
|
import { LabelText } from "components/Input";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
width?: number,
|
width?: number,
|
||||||
@ -57,7 +57,7 @@ const Slider = styled.span`
|
|||||||
|
|
||||||
&:before {
|
&:before {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
content: '';
|
content: "";
|
||||||
height: ${props => props.height - 8}px;
|
height: ${props => props.height - 8}px;
|
||||||
width: ${props => props.height - 8}px;
|
width: ${props => props.height - 8}px;
|
||||||
left: 4px;
|
left: 4px;
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import * as React from 'react';
|
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";
|
||||||
import { lighten } from 'polished';
|
import { lighten } from "polished";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
theme: Object,
|
theme: Object,
|
||||||
@ -35,7 +35,7 @@ const StyledNavLink = styled(NavLink)`
|
|||||||
|
|
||||||
function Tab(props: 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}`,
|
||||||
color: props.theme.textSecondary,
|
color: props.theme.textSecondary,
|
||||||
};
|
};
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import styled from 'styled-components';
|
import styled from "styled-components";
|
||||||
|
|
||||||
const Tabs = styled.nav`
|
const Tabs = styled.nav`
|
||||||
border-bottom: 1px solid ${props => props.theme.divider};
|
border-bottom: 1px solid ${props => props.theme.divider};
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
// @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 { ThemeProvider } from 'styled-components';
|
import { ThemeProvider } from "styled-components";
|
||||||
import { dark, light } from 'shared/styles/theme';
|
import { dark, light } from "shared/styles/theme";
|
||||||
import GlobalStyles from 'shared/styles/globals';
|
import GlobalStyles from "shared/styles/globals";
|
||||||
import UiStore from 'stores/UiStore';
|
import UiStore from "stores/UiStore";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
ui: UiStore,
|
ui: UiStore,
|
||||||
@ -13,7 +13,7 @@ type Props = {
|
|||||||
|
|
||||||
function Theme({ children, ui }: Props) {
|
function Theme({ children, ui }: Props) {
|
||||||
return (
|
return (
|
||||||
<ThemeProvider theme={ui.resolvedTheme === 'dark' ? dark : light}>
|
<ThemeProvider theme={ui.resolvedTheme === "dark" ? dark : light}>
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
<GlobalStyles />
|
<GlobalStyles />
|
||||||
{children}
|
{children}
|
||||||
@ -22,4 +22,4 @@ function Theme({ children, ui }: Props) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default inject('ui')(observer(Theme));
|
export default inject("ui")(observer(Theme));
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
// @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 styled from 'styled-components';
|
import styled from "styled-components";
|
||||||
import Toast from './components/Toast';
|
import Toast from "./components/Toast";
|
||||||
import UiStore from '../../stores/UiStore';
|
import UiStore from "../../stores/UiStore";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
ui: UiStore,
|
ui: UiStore,
|
||||||
@ -37,4 +37,4 @@ const List = styled.ol`
|
|||||||
z-index: 1000;
|
z-index: 1000;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export default inject('ui')(Toasts);
|
export default inject("ui")(Toasts);
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import * as React from 'react';
|
import * as React from "react";
|
||||||
import styled from 'styled-components';
|
import styled from "styled-components";
|
||||||
import { darken } from 'polished';
|
import { darken } from "polished";
|
||||||
import { fadeAndScaleIn } from 'shared/styles/animations';
|
import { fadeAndScaleIn } from "shared/styles/animations";
|
||||||
import type { Toast as TToast } from '../../../types';
|
import type { Toast as TToast } from "../../../types";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
onRequestClose: () => void,
|
onRequestClose: () => void,
|
||||||
@ -33,7 +33,7 @@ class Toast extends React.Component<Props> {
|
|||||||
const { toast, onRequestClose } = this.props;
|
const { toast, onRequestClose } = this.props;
|
||||||
const { action } = toast;
|
const { action } = toast;
|
||||||
const message =
|
const message =
|
||||||
typeof toast.message === 'string'
|
typeof toast.message === "string"
|
||||||
? toast.message
|
? toast.message
|
||||||
: toast.message.toString();
|
: toast.message.toString();
|
||||||
|
|
||||||
@ -41,11 +41,11 @@ class Toast extends React.Component<Props> {
|
|||||||
<li>
|
<li>
|
||||||
<Container
|
<Container
|
||||||
onClick={action ? undefined : onRequestClose}
|
onClick={action ? undefined : onRequestClose}
|
||||||
type={toast.type || 'success'}
|
type={toast.type || "success"}
|
||||||
>
|
>
|
||||||
<Message>{message}</Message>
|
<Message>{message}</Message>
|
||||||
{action && (
|
{action && (
|
||||||
<Action type={toast.type || 'success'} onClick={action.onClick}>
|
<Action type={toast.type || "success"} onClick={action.onClick}>
|
||||||
{action.text}
|
{action.text}
|
||||||
</Action>
|
</Action>
|
||||||
)}
|
)}
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import Toasts from './Toasts';
|
import Toasts from "./Toasts";
|
||||||
export default Toasts;
|
export default Toasts;
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import * as React from 'react';
|
import * as React from "react";
|
||||||
import styled from 'styled-components';
|
import styled from "styled-components";
|
||||||
import Tippy from '@tippy.js/react';
|
import Tippy from "@tippy.js/react";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
tooltip: React.Node,
|
tooltip: React.Node,
|
||||||
shortcut?: React.Node,
|
shortcut?: React.Node,
|
||||||
placement?: 'top' | 'bottom' | 'left' | 'right',
|
placement?: "top" | "bottom" | "left" | "right",
|
||||||
children: React.Node,
|
children: React.Node,
|
||||||
delay?: number,
|
delay?: number,
|
||||||
className?: string,
|
className?: string,
|
||||||
@ -47,7 +47,7 @@ const Shortcut = styled.kbd`
|
|||||||
|
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
padding: 2px 4px;
|
padding: 2px 4px;
|
||||||
font: 10px 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, Courier,
|
font: 10px "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier,
|
||||||
monospace;
|
monospace;
|
||||||
line-height: 10px;
|
line-height: 10px;
|
||||||
color: ${props => props.theme.tooltipBackground};
|
color: ${props => props.theme.tooltipBackground};
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import styled from 'styled-components';
|
import styled from "styled-components";
|
||||||
|
|
||||||
const VisuallyHidden = styled('span')`
|
const VisuallyHidden = styled("span")`
|
||||||
position: absolute !important;
|
position: absolute !important;
|
||||||
height: 1px;
|
height: 1px;
|
||||||
width: 1px;
|
width: 1px;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import * as React from 'react';
|
import * as React from "react";
|
||||||
import Frame from './components/Frame';
|
import Frame from "./components/Frame";
|
||||||
|
|
||||||
type Props = {|
|
type Props = {|
|
||||||
attrs: {|
|
attrs: {|
|
||||||
@ -11,8 +11,8 @@ type Props = {|
|
|||||||
|
|
||||||
export default class Abstract extends React.Component<Props> {
|
export default class Abstract extends React.Component<Props> {
|
||||||
static ENABLED = [
|
static ENABLED = [
|
||||||
new RegExp('https?://share.(?:go)?abstract.com/(.*)$'),
|
new RegExp("https?://share.(?:go)?abstract.com/(.*)$"),
|
||||||
new RegExp('https?://app.(?:go)?abstract.com/(?:share|embed)/(.*)$'),
|
new RegExp("https?://app.(?:go)?abstract.com/(?:share|embed)/(.*)$"),
|
||||||
];
|
];
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
@ -1,58 +1,58 @@
|
|||||||
/* eslint-disable flowtype/require-valid-file-annotation */
|
/* eslint-disable flowtype/require-valid-file-annotation */
|
||||||
import Abstract from './Abstract';
|
import Abstract from "./Abstract";
|
||||||
|
|
||||||
describe('Abstract', () => {
|
describe("Abstract", () => {
|
||||||
const match = Abstract.ENABLED[0];
|
const match = Abstract.ENABLED[0];
|
||||||
const match2 = Abstract.ENABLED[1];
|
const match2 = Abstract.ENABLED[1];
|
||||||
test('to be enabled on share subdomain link', () => {
|
test("to be enabled on share subdomain link", () => {
|
||||||
expect(
|
expect(
|
||||||
'https://share.goabstract.com/aaec8bba-f473-4f64-96e7-bff41c70ff8a'.match(
|
"https://share.goabstract.com/aaec8bba-f473-4f64-96e7-bff41c70ff8a".match(
|
||||||
match
|
match
|
||||||
)
|
)
|
||||||
).toBeTruthy();
|
).toBeTruthy();
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
'https://share.abstract.com/aaec8bba-f473-4f64-96e7-bff41c70ff8a'.match(
|
"https://share.abstract.com/aaec8bba-f473-4f64-96e7-bff41c70ff8a".match(
|
||||||
match
|
match
|
||||||
)
|
)
|
||||||
).toBeTruthy();
|
).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('to be enabled on share link', () => {
|
test("to be enabled on share link", () => {
|
||||||
expect(
|
expect(
|
||||||
'https://app.goabstract.com/share/aaec8bba-f473-4f64-96e7-bff41c70ff8a'.match(
|
"https://app.goabstract.com/share/aaec8bba-f473-4f64-96e7-bff41c70ff8a".match(
|
||||||
match2
|
match2
|
||||||
)
|
)
|
||||||
).toBeTruthy();
|
).toBeTruthy();
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
'https://app.abstract.com/share/aaec8bba-f473-4f64-96e7-bff41c70ff8a'.match(
|
"https://app.abstract.com/share/aaec8bba-f473-4f64-96e7-bff41c70ff8a".match(
|
||||||
match2
|
match2
|
||||||
)
|
)
|
||||||
).toBeTruthy();
|
).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('to be enabled on embed link', () => {
|
test("to be enabled on embed link", () => {
|
||||||
expect(
|
expect(
|
||||||
'https://app.goabstract.com/embed/aaec8bba-f473-4f64-96e7-bff41c70ff8a'.match(
|
"https://app.goabstract.com/embed/aaec8bba-f473-4f64-96e7-bff41c70ff8a".match(
|
||||||
match2
|
match2
|
||||||
)
|
)
|
||||||
).toBeTruthy();
|
).toBeTruthy();
|
||||||
expect(
|
expect(
|
||||||
'https://app.abstract.com/embed/aaec8bba-f473-4f64-96e7-bff41c70ff8a'.match(
|
"https://app.abstract.com/embed/aaec8bba-f473-4f64-96e7-bff41c70ff8a".match(
|
||||||
match2
|
match2
|
||||||
)
|
)
|
||||||
).toBeTruthy();
|
).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('to not be enabled elsewhere', () => {
|
test("to not be enabled elsewhere", () => {
|
||||||
expect('https://abstract.com'.match(match)).toBe(null);
|
expect("https://abstract.com".match(match)).toBe(null);
|
||||||
expect('https://goabstract.com'.match(match)).toBe(null);
|
expect("https://goabstract.com".match(match)).toBe(null);
|
||||||
expect('https://app.goabstract.com'.match(match)).toBe(null);
|
expect("https://app.goabstract.com".match(match)).toBe(null);
|
||||||
expect('https://abstract.com/features'.match(match)).toBe(null);
|
expect("https://abstract.com/features".match(match)).toBe(null);
|
||||||
expect('https://app.abstract.com/home'.match(match)).toBe(null);
|
expect("https://app.abstract.com/home".match(match)).toBe(null);
|
||||||
expect('https://abstract.com/pricing'.match(match)).toBe(null);
|
expect("https://abstract.com/pricing".match(match)).toBe(null);
|
||||||
expect('https://goabstract.com/pricing'.match(match)).toBe(null);
|
expect("https://goabstract.com/pricing".match(match)).toBe(null);
|
||||||
expect('https://www.goabstract.com/pricing'.match(match)).toBe(null);
|
expect("https://www.goabstract.com/pricing".match(match)).toBe(null);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import * as React from 'react';
|
import * as React from "react";
|
||||||
import Frame from './components/Frame';
|
import Frame from "./components/Frame";
|
||||||
|
|
||||||
const URL_REGEX = new RegExp('https://airtable.com/(?:embed/)?(shr.*)$');
|
const URL_REGEX = new RegExp("https://airtable.com/(?:embed/)?(shr.*)$");
|
||||||
|
|
||||||
type Props = {|
|
type Props = {|
|
||||||
attrs: {|
|
attrs: {|
|
||||||
|
@ -1,21 +1,21 @@
|
|||||||
/* eslint-disable flowtype/require-valid-file-annotation */
|
/* eslint-disable flowtype/require-valid-file-annotation */
|
||||||
import Airtable from './Airtable';
|
import Airtable from "./Airtable";
|
||||||
|
|
||||||
describe('Airtable', () => {
|
describe("Airtable", () => {
|
||||||
const match = Airtable.ENABLED[0];
|
const match = Airtable.ENABLED[0];
|
||||||
test('to be enabled on share link', () => {
|
test("to be enabled on share link", () => {
|
||||||
expect('https://airtable.com/shrEoQs3erLnppMie'.match(match)).toBeTruthy();
|
expect("https://airtable.com/shrEoQs3erLnppMie".match(match)).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('to be enabled on embed link', () => {
|
test("to be enabled on embed link", () => {
|
||||||
expect(
|
expect(
|
||||||
'https://airtable.com/embed/shrEoQs3erLnppMie'.match(match)
|
"https://airtable.com/embed/shrEoQs3erLnppMie".match(match)
|
||||||
).toBeTruthy();
|
).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('to not be enabled elsewhere', () => {
|
test("to not be enabled elsewhere", () => {
|
||||||
expect('https://airtable.com'.match(match)).toBe(null);
|
expect("https://airtable.com".match(match)).toBe(null);
|
||||||
expect('https://airtable.com/features'.match(match)).toBe(null);
|
expect("https://airtable.com/features".match(match)).toBe(null);
|
||||||
expect('https://airtable.com/pricing'.match(match)).toBe(null);
|
expect("https://airtable.com/pricing".match(match)).toBe(null);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import * as React from 'react';
|
import * as React from "react";
|
||||||
import Frame from './components/Frame';
|
import Frame from "./components/Frame";
|
||||||
|
|
||||||
const URL_REGEX = new RegExp('^https://codepen.io/(.*?)/(pen|embed)/(.*)$');
|
const URL_REGEX = new RegExp("^https://codepen.io/(.*?)/(pen|embed)/(.*)$");
|
||||||
|
|
||||||
type Props = {|
|
type Props = {|
|
||||||
attrs: {|
|
attrs: {|
|
||||||
@ -15,7 +15,7 @@ export default class Codepen extends React.Component<Props> {
|
|||||||
static ENABLED = [URL_REGEX];
|
static ENABLED = [URL_REGEX];
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const normalizedUrl = this.props.attrs.href.replace(/\/pen\//, '/embed/');
|
const normalizedUrl = this.props.attrs.href.replace(/\/pen\//, "/embed/");
|
||||||
|
|
||||||
return <Frame src={normalizedUrl} title="Codepen Embed" />;
|
return <Frame src={normalizedUrl} title="Codepen Embed" />;
|
||||||
}
|
}
|
||||||
|
@ -1,22 +1,22 @@
|
|||||||
/* eslint-disable flowtype/require-valid-file-annotation */
|
/* eslint-disable flowtype/require-valid-file-annotation */
|
||||||
import Codepen from './Codepen';
|
import Codepen from "./Codepen";
|
||||||
|
|
||||||
describe('Codepen', () => {
|
describe("Codepen", () => {
|
||||||
const match = Codepen.ENABLED[0];
|
const match = Codepen.ENABLED[0];
|
||||||
test('to be enabled on pen link', () => {
|
test("to be enabled on pen link", () => {
|
||||||
expect(
|
expect(
|
||||||
'https://codepen.io/chriscoyier/pen/gfdDu'.match(match)
|
"https://codepen.io/chriscoyier/pen/gfdDu".match(match)
|
||||||
).toBeTruthy();
|
).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('to be enabled on embed link', () => {
|
test("to be enabled on embed link", () => {
|
||||||
expect(
|
expect(
|
||||||
'https://codepen.io/chriscoyier/embed/gfdDu'.match(match)
|
"https://codepen.io/chriscoyier/embed/gfdDu".match(match)
|
||||||
).toBeTruthy();
|
).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('to not be enabled elsewhere', () => {
|
test("to not be enabled elsewhere", () => {
|
||||||
expect('https://codepen.io'.match(match)).toBe(null);
|
expect("https://codepen.io".match(match)).toBe(null);
|
||||||
expect('https://codepen.io/chriscoyier'.match(match)).toBe(null);
|
expect("https://codepen.io/chriscoyier".match(match)).toBe(null);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import * as React from 'react';
|
import * as React from "react";
|
||||||
import Frame from './components/Frame';
|
import Frame from "./components/Frame";
|
||||||
|
|
||||||
const URL_REGEX = new RegExp(
|
const URL_REGEX = new RegExp(
|
||||||
'https://([w.-]+.)?figma.com/(file|proto)/([0-9a-zA-Z]{22,128})(?:/.*)?$'
|
"https://([w.-]+.)?figma.com/(file|proto)/([0-9a-zA-Z]{22,128})(?:/.*)?$"
|
||||||
);
|
);
|
||||||
|
|
||||||
type Props = {|
|
type Props = {|
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user