New login screen (#1331)
* wip * feat: first draft of auth.config * chore: auth methodS * chore: styling * styling, styling, styling * feat: Auth notices * chore: Remove server-rendered pages, move shared/components -> components * lint * cleanup * cleanup * fix: Remove unused component * fix: Ensure env variables in prod too * style tweaks * fix: Entering SSO email into login form fails fix: Tweak language around guest signin
This commit is contained in:
parent
75561079eb
commit
5cb04d7ac1
|
@ -126,7 +126,6 @@ Backend is driven by [Koa](http://koajs.com/) (API, web server), [Sequelize](htt
|
||||||
- `server/commands` - Domain logic, currently being refactored from /models
|
- `server/commands` - Domain logic, currently being refactored from /models
|
||||||
- `server/emails` - React rendered email templates
|
- `server/emails` - React rendered email templates
|
||||||
- `server/models` - Database models
|
- `server/models` - Database models
|
||||||
- `server/pages` - Server-side rendered public pages
|
|
||||||
- `server/policies` - Authorization logic
|
- `server/policies` - Authorization logic
|
||||||
- `server/presenters` - API responses for database models
|
- `server/presenters` - API responses for database models
|
||||||
- `server/test` - Test helps and support
|
- `server/test` - Test helps and support
|
||||||
|
|
|
@ -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 "components/Flex";
|
||||||
|
|
||||||
export const Action = styled(Flex)`
|
export const Action = styled(Flex)`
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
|
|
@ -1,36 +0,0 @@
|
||||||
// @flow
|
|
||||||
import * as React from "react";
|
|
||||||
import { observer } from "mobx-react";
|
|
||||||
import Flex from "shared/components/Flex";
|
|
||||||
import styled from "styled-components";
|
|
||||||
|
|
||||||
type Props = {
|
|
||||||
children: React.Node,
|
|
||||||
type?: "info" | "success" | "warning" | "danger" | "offline",
|
|
||||||
};
|
|
||||||
|
|
||||||
@observer
|
|
||||||
class Alert extends React.Component<Props> {
|
|
||||||
defaultProps = {
|
|
||||||
type: "info",
|
|
||||||
};
|
|
||||||
|
|
||||||
render() {
|
|
||||||
return (
|
|
||||||
<Container align="center" justify="center" type={this.props.type}>
|
|
||||||
{this.props.children}
|
|
||||||
</Container>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const Container = styled(Flex)`
|
|
||||||
height: $headerHeight;
|
|
||||||
color: ${props => props.theme.white};
|
|
||||||
font-size: 14px;
|
|
||||||
line-height: 1;
|
|
||||||
|
|
||||||
background-color: ${({ theme, type }) => theme.color[type]};
|
|
||||||
`;
|
|
||||||
|
|
||||||
export default Alert;
|
|
|
@ -1,6 +1,7 @@
|
||||||
// @flow
|
// @flow
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import { observer, inject } from "mobx-react";
|
import { observer, inject } from "mobx-react";
|
||||||
|
import { Redirect } from "react-router-dom";
|
||||||
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";
|
||||||
|
@ -35,7 +36,7 @@ const Authenticated = observer(({ auth, children }: Props) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
auth.logout(true);
|
auth.logout(true);
|
||||||
return null;
|
return <Redirect to="/" />;
|
||||||
});
|
});
|
||||||
|
|
||||||
export default inject("auth")(Authenticated);
|
export default inject("auth")(Authenticated);
|
||||||
|
|
|
@ -9,7 +9,7 @@ import { PadlockIcon, GoToIcon, MoreIcon } from "outline-icons";
|
||||||
import Document from "models/Document";
|
import Document from "models/Document";
|
||||||
import CollectionsStore from "stores/CollectionsStore";
|
import CollectionsStore from "stores/CollectionsStore";
|
||||||
import { collectionUrl } from "utils/routeHelpers";
|
import { collectionUrl } from "utils/routeHelpers";
|
||||||
import Flex from "shared/components/Flex";
|
import Flex from "components/Flex";
|
||||||
import BreadcrumbMenu from "./BreadcrumbMenu";
|
import BreadcrumbMenu from "./BreadcrumbMenu";
|
||||||
import CollectionIcon from "components/CollectionIcon";
|
import CollectionIcon from "components/CollectionIcon";
|
||||||
|
|
|
@ -5,7 +5,8 @@ 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: ${props => (props.fullwidth ? "block" : "inline-block")};
|
||||||
|
width: ${props => (props.fullwidth ? "100%" : "auto")};
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
border: 0;
|
border: 0;
|
||||||
|
@ -126,6 +127,7 @@ export type Props = {
|
||||||
children?: React.Node,
|
children?: React.Node,
|
||||||
innerRef?: React.ElementRef<any>,
|
innerRef?: React.ElementRef<any>,
|
||||||
disclosure?: boolean,
|
disclosure?: boolean,
|
||||||
|
fullwidth?: boolean,
|
||||||
borderOnHover?: boolean,
|
borderOnHover?: boolean,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
// @flow
|
||||||
|
import styled from "styled-components";
|
||||||
|
import Button, { Inner } from "./Button";
|
||||||
|
|
||||||
|
const ButtonLarge = styled(Button)`
|
||||||
|
height: 40px;
|
||||||
|
|
||||||
|
${Inner} {
|
||||||
|
padding: 4px 16px;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export default ButtonLarge;
|
|
@ -11,7 +11,7 @@ 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 "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";
|
||||||
|
|
|
@ -5,8 +5,8 @@ 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 "components/Flex";
|
||||||
import Time from "shared/components/Time";
|
import Time from "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";
|
||||||
|
|
|
@ -4,7 +4,7 @@ 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 "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";
|
||||||
|
|
|
@ -7,7 +7,7 @@ import { PortalWithState } from "react-portal";
|
||||||
import { MoreIcon } from "outline-icons";
|
import { MoreIcon } from "outline-icons";
|
||||||
import { rgba } from "polished";
|
import { rgba } from "polished";
|
||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
import Flex from "shared/components/Flex";
|
import Flex from "components/Flex";
|
||||||
import { fadeAndScaleIn } from "shared/styles/animations";
|
import { fadeAndScaleIn } from "shared/styles/animations";
|
||||||
import NudeButton from "components/NudeButton";
|
import NudeButton from "components/NudeButton";
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
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 "components/Flex";
|
||||||
import Avatar from "components/Avatar";
|
import Avatar from "components/Avatar";
|
||||||
import User from "models/User";
|
import User from "models/User";
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ 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 "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";
|
||||||
|
|
|
@ -27,7 +27,7 @@ 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 "components/Flex";
|
||||||
|
|
||||||
export const icons = {
|
export const icons = {
|
||||||
collection: {
|
collection: {
|
||||||
|
|
|
@ -4,7 +4,7 @@ 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 "components/Flex";
|
||||||
|
|
||||||
const RealTextarea = styled.textarea`
|
const RealTextarea = styled.textarea`
|
||||||
border: 0;
|
border: 0;
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
// @flow
|
||||||
|
import styled from "styled-components";
|
||||||
|
import Input from "./Input";
|
||||||
|
|
||||||
|
const InputLarge = styled(Input)`
|
||||||
|
height: 40px;
|
||||||
|
|
||||||
|
input {
|
||||||
|
height: 40px;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export default InputLarge;
|
|
@ -1,7 +1,7 @@
|
||||||
// @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 "components/Flex";
|
||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
|
|
|
@ -8,7 +8,7 @@ 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 "components/Flex";
|
||||||
import {
|
import {
|
||||||
homeUrl,
|
homeUrl,
|
||||||
searchUrl,
|
searchUrl,
|
||||||
|
|
|
@ -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 "components/Flex";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
image?: React.Node,
|
image?: React.Node,
|
||||||
|
|
|
@ -4,7 +4,7 @@ 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 "components/Flex";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
count?: number,
|
count?: number,
|
||||||
|
|
|
@ -4,7 +4,7 @@ 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 "components/Flex";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
count?: number,
|
count?: number,
|
||||||
|
|
|
@ -3,7 +3,7 @@ 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 "components/Flex";
|
||||||
|
|
||||||
export default function LoadingPlaceholder(props: Object) {
|
export default function LoadingPlaceholder(props: Object) {
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -3,7 +3,7 @@ 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 "components/Flex";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
header?: boolean,
|
header?: boolean,
|
||||||
|
|
|
@ -8,7 +8,7 @@ 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 "components/Flex";
|
||||||
|
|
||||||
ReactModal.setAppElement("#root");
|
ReactModal.setAppElement("#root");
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
// @flow
|
||||||
|
import styled from "styled-components";
|
||||||
|
|
||||||
|
const Notice = styled.p`
|
||||||
|
background: ${props => props.theme.sidebarBackground};
|
||||||
|
color: ${props => props.theme.sidebarText};
|
||||||
|
padding: 10px 12px;
|
||||||
|
border-radius: 4px;
|
||||||
|
position: relative;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export default Notice;
|
|
@ -0,0 +1,24 @@
|
||||||
|
// @flow
|
||||||
|
import * as React from "react";
|
||||||
|
import Notice from "components/Notice";
|
||||||
|
|
||||||
|
export default function AlertNotice({ children }: { children: React.Node }) {
|
||||||
|
return (
|
||||||
|
<Notice muted>
|
||||||
|
<svg
|
||||||
|
width="16"
|
||||||
|
height="16"
|
||||||
|
viewBox="0 0 16 16"
|
||||||
|
fill="none"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
style={{ position: "relative", top: "2px" }}
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M15.6676 11.5372L10.0155 1.14735C9.10744 -0.381434 6.89378 -0.383465 5.98447 1.14735L0.332715 11.5372C-0.595598 13.0994 0.528309 15.0776 2.34778 15.0776H13.652C15.47 15.0776 16.5959 13.101 15.6676 11.5372ZM8 13.2026C7.48319 13.2026 7.0625 12.7819 7.0625 12.2651C7.0625 11.7483 7.48319 11.3276 8 11.3276C8.51681 11.3276 8.9375 11.7483 8.9375 12.2651C8.9375 12.7819 8.51681 13.2026 8 13.2026ZM8.9375 9.45257C8.9375 9.96938 8.51681 10.3901 8 10.3901C7.48319 10.3901 7.0625 9.96938 7.0625 9.45257V4.76507C7.0625 4.24826 7.48319 3.82757 8 3.82757C8.51681 3.82757 8.9375 4.24826 8.9375 4.76507V9.45257Z"
|
||||||
|
fill="currentColor"
|
||||||
|
/>
|
||||||
|
</svg>{" "}
|
||||||
|
{children}
|
||||||
|
</Notice>
|
||||||
|
);
|
||||||
|
}
|
|
@ -3,7 +3,7 @@ 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 "components/Flex";
|
||||||
|
|
||||||
import Document from "models/Document";
|
import Document from "models/Document";
|
||||||
import Collection from "models/Collection";
|
import Collection from "models/Collection";
|
||||||
|
|
|
@ -3,9 +3,9 @@ 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 "components/Flex";
|
||||||
import Time from "shared/components/Time";
|
import Time from "components/Time";
|
||||||
import Breadcrumb from "shared/components/Breadcrumb";
|
import Breadcrumb from "components/Breadcrumb";
|
||||||
import CollectionsStore from "stores/CollectionsStore";
|
import CollectionsStore from "stores/CollectionsStore";
|
||||||
import AuthStore from "stores/AuthStore";
|
import AuthStore from "stores/AuthStore";
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,7 @@ import {
|
||||||
PlusIcon,
|
PlusIcon,
|
||||||
} from "outline-icons";
|
} from "outline-icons";
|
||||||
|
|
||||||
import Flex from "shared/components/Flex";
|
import Flex from "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";
|
||||||
|
|
|
@ -19,7 +19,7 @@ import {
|
||||||
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 "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";
|
||||||
|
@ -54,7 +54,7 @@ class SettingsSidebar extends React.Component<Props> {
|
||||||
<HeaderBlock
|
<HeaderBlock
|
||||||
subheading={
|
subheading={
|
||||||
<ReturnToApp align="center">
|
<ReturnToApp align="center">
|
||||||
<BackIcon /> Return to App
|
<BackIcon color="currentColor" /> Return to App
|
||||||
</ReturnToApp>
|
</ReturnToApp>
|
||||||
}
|
}
|
||||||
teamName={team.name}
|
teamName={team.name}
|
||||||
|
|
|
@ -7,7 +7,7 @@ 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 "components/Flex";
|
||||||
import UiStore from "stores/UiStore";
|
import UiStore from "stores/UiStore";
|
||||||
|
|
||||||
let firstRender = true;
|
let firstRender = true;
|
||||||
|
|
|
@ -11,7 +11,7 @@ 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 "components/Flex";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
collection: Collection,
|
collection: Collection,
|
||||||
|
|
|
@ -3,7 +3,7 @@ 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 "components/Flex";
|
||||||
import { PlusIcon } from "outline-icons";
|
import { PlusIcon } from "outline-icons";
|
||||||
import { newDocumentUrl } from "utils/routeHelpers";
|
import { newDocumentUrl } from "utils/routeHelpers";
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ 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 "components/Flex";
|
||||||
import { type NavigationNode } from "types";
|
import { type NavigationNode } from "types";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// @flow
|
// @flow
|
||||||
import Flex from "shared/components/Flex";
|
import Flex from "components/Flex";
|
||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
|
|
||||||
const Header = styled(Flex)`
|
const Header = styled(Flex)`
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
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 "components/Flex";
|
||||||
import TeamLogo from "shared/components/TeamLogo";
|
import TeamLogo from "components/TeamLogo";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
teamName: string,
|
teamName: string,
|
||||||
|
|
|
@ -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 "components/Flex";
|
||||||
|
|
||||||
const Section = styled(Flex)`
|
const Section = styled(Flex)`
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
|
@ -5,7 +5,7 @@ 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 "components/Flex";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
to?: string | Object,
|
to?: string | Object,
|
||||||
|
|
|
@ -2,10 +2,10 @@
|
||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
|
|
||||||
const TeamLogo = styled.img`
|
const TeamLogo = styled.img`
|
||||||
width: 38px;
|
width: auto;
|
||||||
height: 38px;
|
height: 38px;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
background: ${props => props.theme.white};
|
background: ${props => props.theme.background};
|
||||||
border: 1px solid ${props => props.theme.divider};
|
border: 1px solid ${props => props.theme.divider};
|
||||||
`;
|
`;
|
||||||
|
|
|
@ -7,7 +7,7 @@ import { SunIcon, MoonIcon } from "outline-icons";
|
||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
import UiStore from "stores/UiStore";
|
import UiStore from "stores/UiStore";
|
||||||
import AuthStore from "stores/AuthStore";
|
import AuthStore from "stores/AuthStore";
|
||||||
import Flex from "shared/components/Flex";
|
import Flex from "components/Flex";
|
||||||
import { DropdownMenu, DropdownMenuItem } from "components/DropdownMenu";
|
import { DropdownMenu, DropdownMenuItem } from "components/DropdownMenu";
|
||||||
import Modal from "components/Modal";
|
import Modal from "components/Modal";
|
||||||
import KeyboardShortcuts from "scenes/KeyboardShortcuts";
|
import KeyboardShortcuts from "scenes/KeyboardShortcuts";
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
// @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 Home from "scenes/Home";
|
import Login from "scenes/Login";
|
||||||
import Dashboard from "scenes/Dashboard";
|
import Dashboard from "scenes/Dashboard";
|
||||||
import Starred from "scenes/Starred";
|
import Starred from "scenes/Starred";
|
||||||
import Drafts from "scenes/Drafts";
|
import Drafts from "scenes/Drafts";
|
||||||
|
@ -38,7 +38,8 @@ const RedirectDocument = ({ match }: { match: Object }) => (
|
||||||
export default function Routes() {
|
export default function Routes() {
|
||||||
return (
|
return (
|
||||||
<Switch>
|
<Switch>
|
||||||
<Route exact path="/" component={Home} />
|
<Route exact path="/" component={Login} />
|
||||||
|
<Route exact path="/create" component={Login} />
|
||||||
<Route exact path="/share/:shareId" component={KeyedDocument} />
|
<Route exact path="/share/:shareId" component={KeyedDocument} />
|
||||||
<Authenticated>
|
<Authenticated>
|
||||||
<SocketProvider>
|
<SocketProvider>
|
||||||
|
|
|
@ -30,7 +30,7 @@ import HelpText from "components/HelpText";
|
||||||
import DocumentList from "components/DocumentList";
|
import DocumentList from "components/DocumentList";
|
||||||
import Subheading from "components/Subheading";
|
import Subheading from "components/Subheading";
|
||||||
import PageTitle from "components/PageTitle";
|
import PageTitle from "components/PageTitle";
|
||||||
import Flex from "shared/components/Flex";
|
import Flex from "components/Flex";
|
||||||
import Modal from "components/Modal";
|
import Modal from "components/Modal";
|
||||||
import CollectionMembers from "scenes/CollectionMembers";
|
import CollectionMembers from "scenes/CollectionMembers";
|
||||||
import Tabs from "components/Tabs";
|
import Tabs from "components/Tabs";
|
||||||
|
|
|
@ -5,7 +5,7 @@ import { observable } from "mobx";
|
||||||
import { inject, observer } from "mobx-react";
|
import { inject, observer } from "mobx-react";
|
||||||
import { homeUrl } from "utils/routeHelpers";
|
import { homeUrl } from "utils/routeHelpers";
|
||||||
import Button from "components/Button";
|
import Button from "components/Button";
|
||||||
import Flex from "shared/components/Flex";
|
import Flex from "components/Flex";
|
||||||
import HelpText from "components/HelpText";
|
import HelpText from "components/HelpText";
|
||||||
import Collection from "models/Collection";
|
import Collection from "models/Collection";
|
||||||
import CollectionsStore from "stores/CollectionsStore";
|
import CollectionsStore from "stores/CollectionsStore";
|
||||||
|
|
|
@ -6,7 +6,7 @@ import Input from "components/Input";
|
||||||
import InputRich from "components/InputRich";
|
import InputRich from "components/InputRich";
|
||||||
import Button from "components/Button";
|
import Button from "components/Button";
|
||||||
import Switch from "components/Switch";
|
import Switch from "components/Switch";
|
||||||
import Flex from "shared/components/Flex";
|
import Flex from "components/Flex";
|
||||||
import HelpText from "components/HelpText";
|
import HelpText from "components/HelpText";
|
||||||
import IconPicker from "components/IconPicker";
|
import IconPicker from "components/IconPicker";
|
||||||
import Collection from "models/Collection";
|
import Collection from "models/Collection";
|
||||||
|
|
|
@ -3,7 +3,7 @@ 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 Button from "components/Button";
|
import Button from "components/Button";
|
||||||
import Flex from "shared/components/Flex";
|
import Flex from "components/Flex";
|
||||||
import HelpText from "components/HelpText";
|
import HelpText from "components/HelpText";
|
||||||
import Collection from "models/Collection";
|
import Collection from "models/Collection";
|
||||||
import AuthStore from "stores/AuthStore";
|
import AuthStore from "stores/AuthStore";
|
||||||
|
|
|
@ -5,7 +5,7 @@ import { inject, observer } from "mobx-react";
|
||||||
import { observable } from "mobx";
|
import { observable } from "mobx";
|
||||||
import { debounce } from "lodash";
|
import { debounce } from "lodash";
|
||||||
import Button from "components/Button";
|
import Button from "components/Button";
|
||||||
import Flex from "shared/components/Flex";
|
import Flex from "components/Flex";
|
||||||
import HelpText from "components/HelpText";
|
import HelpText from "components/HelpText";
|
||||||
import Input from "components/Input";
|
import Input from "components/Input";
|
||||||
import Modal from "components/Modal";
|
import Modal from "components/Modal";
|
||||||
|
|
|
@ -3,7 +3,7 @@ import * as React from "react";
|
||||||
import { inject, observer } from "mobx-react";
|
import { inject, observer } from "mobx-react";
|
||||||
import { observable } from "mobx";
|
import { observable } from "mobx";
|
||||||
import { debounce } from "lodash";
|
import { debounce } from "lodash";
|
||||||
import Flex from "shared/components/Flex";
|
import Flex from "components/Flex";
|
||||||
import HelpText from "components/HelpText";
|
import HelpText from "components/HelpText";
|
||||||
import Input from "components/Input";
|
import Input from "components/Input";
|
||||||
import Modal from "components/Modal";
|
import Modal from "components/Modal";
|
||||||
|
|
|
@ -4,7 +4,7 @@ import { observable } from "mobx";
|
||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
import { inject, observer } from "mobx-react";
|
import { inject, observer } from "mobx-react";
|
||||||
import { PlusIcon } from "outline-icons";
|
import { PlusIcon } from "outline-icons";
|
||||||
import Flex from "shared/components/Flex";
|
import Flex from "components/Flex";
|
||||||
import HelpText from "components/HelpText";
|
import HelpText from "components/HelpText";
|
||||||
import Subheading from "components/Subheading";
|
import Subheading from "components/Subheading";
|
||||||
import Button from "components/Button";
|
import Button from "components/Button";
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
import Avatar from "components/Avatar";
|
import Avatar from "components/Avatar";
|
||||||
import Flex from "shared/components/Flex";
|
import Flex from "components/Flex";
|
||||||
import Time from "shared/components/Time";
|
import Time from "components/Time";
|
||||||
import Badge from "components/Badge";
|
import Badge from "components/Badge";
|
||||||
import Button from "components/Button";
|
import Button from "components/Button";
|
||||||
import InputSelect from "components/InputSelect";
|
import InputSelect from "components/InputSelect";
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
// @flow
|
// @flow
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import { PlusIcon } from "outline-icons";
|
import { PlusIcon } from "outline-icons";
|
||||||
import Time from "shared/components/Time";
|
import Time from "components/Time";
|
||||||
import Avatar from "components/Avatar";
|
import Avatar from "components/Avatar";
|
||||||
import Button from "components/Button";
|
import Button from "components/Button";
|
||||||
import Badge from "components/Badge";
|
import Badge from "components/Badge";
|
||||||
|
|
|
@ -10,7 +10,7 @@ import Input from "components/Input";
|
||||||
import InputRich from "components/InputRich";
|
import InputRich from "components/InputRich";
|
||||||
import IconPicker, { icons } from "components/IconPicker";
|
import IconPicker, { icons } from "components/IconPicker";
|
||||||
import HelpText from "components/HelpText";
|
import HelpText from "components/HelpText";
|
||||||
import Flex from "shared/components/Flex";
|
import Flex from "components/Flex";
|
||||||
|
|
||||||
import Collection from "models/Collection";
|
import Collection from "models/Collection";
|
||||||
import CollectionsStore from "stores/CollectionsStore";
|
import CollectionsStore from "stores/CollectionsStore";
|
||||||
|
|
|
@ -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 "components/Flex";
|
||||||
|
|
||||||
const Container = styled(Flex)`
|
const Container = styled(Flex)`
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
|
@ -8,7 +8,7 @@ import { observer, inject } from "mobx-react";
|
||||||
import { Prompt, Route, withRouter } from "react-router-dom";
|
import { Prompt, Route, withRouter } from "react-router-dom";
|
||||||
import type { Location, RouterHistory } from "react-router-dom";
|
import type { Location, RouterHistory } from "react-router-dom";
|
||||||
import keydown from "react-keydown";
|
import keydown from "react-keydown";
|
||||||
import Flex from "shared/components/Flex";
|
import Flex from "components/Flex";
|
||||||
import {
|
import {
|
||||||
collectionUrl,
|
collectionUrl,
|
||||||
documentMoveUrl,
|
documentMoveUrl,
|
||||||
|
@ -29,9 +29,9 @@ import MarkAsViewed from "./MarkAsViewed";
|
||||||
import ErrorBoundary from "components/ErrorBoundary";
|
import ErrorBoundary from "components/ErrorBoundary";
|
||||||
import LoadingIndicator from "components/LoadingIndicator";
|
import LoadingIndicator from "components/LoadingIndicator";
|
||||||
import PageTitle from "components/PageTitle";
|
import PageTitle from "components/PageTitle";
|
||||||
import Branding from "shared/components/Branding";
|
import Branding from "components/Branding";
|
||||||
import Notice from "shared/components/Notice";
|
import Notice from "components/Notice";
|
||||||
import Time from "shared/components/Time";
|
import Time from "components/Time";
|
||||||
|
|
||||||
import UiStore from "stores/UiStore";
|
import UiStore from "stores/UiStore";
|
||||||
import AuthStore from "stores/AuthStore";
|
import AuthStore from "stores/AuthStore";
|
||||||
|
|
|
@ -12,7 +12,7 @@ import Modal from "components/Modal";
|
||||||
import Input from "components/Input";
|
import Input from "components/Input";
|
||||||
import Labeled from "components/Labeled";
|
import Labeled from "components/Labeled";
|
||||||
import PathToDocument from "components/PathToDocument";
|
import PathToDocument from "components/PathToDocument";
|
||||||
import Flex from "shared/components/Flex";
|
import Flex from "components/Flex";
|
||||||
|
|
||||||
import Document from "models/Document";
|
import Document from "models/Document";
|
||||||
import DocumentsStore from "stores/DocumentsStore";
|
import DocumentsStore from "stores/DocumentsStore";
|
||||||
|
|
|
@ -5,7 +5,7 @@ import Textarea from "react-autosize-textarea";
|
||||||
import { observer } from "mobx-react";
|
import { observer } from "mobx-react";
|
||||||
import Editor from "components/Editor";
|
import Editor from "components/Editor";
|
||||||
import ClickablePadding from "components/ClickablePadding";
|
import ClickablePadding from "components/ClickablePadding";
|
||||||
import Flex from "shared/components/Flex";
|
import Flex from "components/Flex";
|
||||||
import parseTitle from "shared/utils/parseTitle";
|
import parseTitle from "shared/utils/parseTitle";
|
||||||
import Document from "models/Document";
|
import Document from "models/Document";
|
||||||
import DocumentMeta from "./DocumentMeta";
|
import DocumentMeta from "./DocumentMeta";
|
||||||
|
|
|
@ -13,8 +13,8 @@ import AuthStore from "stores/AuthStore";
|
||||||
import { documentEditUrl } from "utils/routeHelpers";
|
import { documentEditUrl } from "utils/routeHelpers";
|
||||||
import { meta } from "utils/keyboard";
|
import { meta } from "utils/keyboard";
|
||||||
|
|
||||||
import Flex from "shared/components/Flex";
|
import Flex from "components/Flex";
|
||||||
import Breadcrumb, { Slash } from "shared/components/Breadcrumb";
|
import Breadcrumb, { Slash } from "components/Breadcrumb";
|
||||||
import DocumentMenu from "menus/DocumentMenu";
|
import DocumentMenu from "menus/DocumentMenu";
|
||||||
import NewChildDocumentMenu from "menus/NewChildDocumentMenu";
|
import NewChildDocumentMenu from "menus/NewChildDocumentMenu";
|
||||||
import DocumentShare from "scenes/DocumentShare";
|
import DocumentShare from "scenes/DocumentShare";
|
||||||
|
|
|
@ -4,7 +4,7 @@ import { withRouter, type RouterHistory } from "react-router-dom";
|
||||||
import { observable } from "mobx";
|
import { observable } from "mobx";
|
||||||
import { inject, observer } from "mobx-react";
|
import { inject, observer } from "mobx-react";
|
||||||
import Button from "components/Button";
|
import Button from "components/Button";
|
||||||
import Flex from "shared/components/Flex";
|
import Flex from "components/Flex";
|
||||||
import HelpText from "components/HelpText";
|
import HelpText from "components/HelpText";
|
||||||
import Document from "models/Document";
|
import Document from "models/Document";
|
||||||
import DocumentsStore from "stores/DocumentsStore";
|
import DocumentsStore from "stores/DocumentsStore";
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import { inject } from "mobx-react";
|
import { inject } from "mobx-react";
|
||||||
import type { RouterHistory, Location } from "react-router-dom";
|
import type { RouterHistory, Location } from "react-router-dom";
|
||||||
import Flex from "shared/components/Flex";
|
import Flex from "components/Flex";
|
||||||
import CenteredContent from "components/CenteredContent";
|
import CenteredContent from "components/CenteredContent";
|
||||||
import LoadingPlaceholder from "components/LoadingPlaceholder";
|
import LoadingPlaceholder from "components/LoadingPlaceholder";
|
||||||
import DocumentsStore from "stores/DocumentsStore";
|
import DocumentsStore from "stores/DocumentsStore";
|
||||||
|
|
|
@ -5,7 +5,7 @@ import { observable } from "mobx";
|
||||||
import { inject, observer } from "mobx-react";
|
import { inject, observer } from "mobx-react";
|
||||||
import { groupSettings } from "shared/utils/routeHelpers";
|
import { groupSettings } from "shared/utils/routeHelpers";
|
||||||
import Button from "components/Button";
|
import Button from "components/Button";
|
||||||
import Flex from "shared/components/Flex";
|
import Flex from "components/Flex";
|
||||||
import HelpText from "components/HelpText";
|
import HelpText from "components/HelpText";
|
||||||
import Group from "models/Group";
|
import Group from "models/Group";
|
||||||
import UiStore from "stores/UiStore";
|
import UiStore from "stores/UiStore";
|
||||||
|
|
|
@ -6,7 +6,7 @@ import { inject, observer } from "mobx-react";
|
||||||
import Button from "components/Button";
|
import Button from "components/Button";
|
||||||
import Input from "components/Input";
|
import Input from "components/Input";
|
||||||
import HelpText from "components/HelpText";
|
import HelpText from "components/HelpText";
|
||||||
import Flex from "shared/components/Flex";
|
import Flex from "components/Flex";
|
||||||
|
|
||||||
import Group from "models/Group";
|
import Group from "models/Group";
|
||||||
import UiStore from "stores/UiStore";
|
import UiStore from "stores/UiStore";
|
||||||
|
|
|
@ -3,7 +3,7 @@ import * as React from "react";
|
||||||
import { inject, observer } from "mobx-react";
|
import { inject, observer } from "mobx-react";
|
||||||
import { observable } from "mobx";
|
import { observable } from "mobx";
|
||||||
import { debounce } from "lodash";
|
import { debounce } from "lodash";
|
||||||
import Flex from "shared/components/Flex";
|
import Flex from "components/Flex";
|
||||||
import HelpText from "components/HelpText";
|
import HelpText from "components/HelpText";
|
||||||
import Input from "components/Input";
|
import Input from "components/Input";
|
||||||
import Modal from "components/Modal";
|
import Modal from "components/Modal";
|
||||||
|
|
|
@ -3,7 +3,7 @@ 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 { PlusIcon } from "outline-icons";
|
import { PlusIcon } from "outline-icons";
|
||||||
import Flex from "shared/components/Flex";
|
import Flex from "components/Flex";
|
||||||
import Empty from "components/Empty";
|
import Empty from "components/Empty";
|
||||||
import HelpText from "components/HelpText";
|
import HelpText from "components/HelpText";
|
||||||
import Subheading from "components/Subheading";
|
import Subheading from "components/Subheading";
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
// @flow
|
// @flow
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import Avatar from "components/Avatar";
|
import Avatar from "components/Avatar";
|
||||||
import Flex from "shared/components/Flex";
|
import Flex from "components/Flex";
|
||||||
import Time from "shared/components/Time";
|
import Time from "components/Time";
|
||||||
import Badge from "components/Badge";
|
import Badge from "components/Badge";
|
||||||
import Button from "components/Button";
|
import Button from "components/Button";
|
||||||
import ListItem from "components/List/Item";
|
import ListItem from "components/List/Item";
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
// @flow
|
// @flow
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import { PlusIcon } from "outline-icons";
|
import { PlusIcon } from "outline-icons";
|
||||||
import Time from "shared/components/Time";
|
import Time from "components/Time";
|
||||||
import Avatar from "components/Avatar";
|
import Avatar from "components/Avatar";
|
||||||
import Button from "components/Button";
|
import Button from "components/Button";
|
||||||
import Badge from "components/Badge";
|
import Badge from "components/Badge";
|
||||||
|
|
|
@ -8,7 +8,7 @@ import Input from "components/Input";
|
||||||
import HelpText from "components/HelpText";
|
import HelpText from "components/HelpText";
|
||||||
import Modal from "components/Modal";
|
import Modal from "components/Modal";
|
||||||
import GroupMembers from "scenes/GroupMembers";
|
import GroupMembers from "scenes/GroupMembers";
|
||||||
import Flex from "shared/components/Flex";
|
import Flex from "components/Flex";
|
||||||
|
|
||||||
import Group from "models/Group";
|
import Group from "models/Group";
|
||||||
import GroupsStore from "stores/GroupsStore";
|
import GroupsStore from "stores/GroupsStore";
|
||||||
|
|
|
@ -1,17 +0,0 @@
|
||||||
// @flow
|
|
||||||
import * as React from "react";
|
|
||||||
import { observer, inject } from "mobx-react";
|
|
||||||
import { Redirect } from "react-router-dom";
|
|
||||||
import AuthStore from "stores/AuthStore";
|
|
||||||
|
|
||||||
type Props = {
|
|
||||||
auth: AuthStore,
|
|
||||||
};
|
|
||||||
|
|
||||||
const Home = observer(({ auth }: Props) => {
|
|
||||||
if (auth.authenticated) return <Redirect to="/home" />;
|
|
||||||
auth.logout(true);
|
|
||||||
return null;
|
|
||||||
});
|
|
||||||
|
|
||||||
export default inject("auth")(Home);
|
|
|
@ -3,13 +3,12 @@ import * as React from "react";
|
||||||
import { Link, withRouter, type RouterHistory } from "react-router-dom";
|
import { Link, withRouter, type RouterHistory } from "react-router-dom";
|
||||||
import { observable, action } from "mobx";
|
import { observable, action } from "mobx";
|
||||||
import { inject, observer } from "mobx-react";
|
import { inject, observer } from "mobx-react";
|
||||||
import { CloseIcon } from "outline-icons";
|
import { LinkIcon, CloseIcon } from "outline-icons";
|
||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
import Flex from "shared/components/Flex";
|
import Flex from "components/Flex";
|
||||||
import Button from "components/Button";
|
import Button from "components/Button";
|
||||||
import Input from "components/Input";
|
import Input from "components/Input";
|
||||||
import CopyToClipboard from "components/CopyToClipboard";
|
import CopyToClipboard from "components/CopyToClipboard";
|
||||||
import Checkbox from "components/Checkbox";
|
|
||||||
import HelpText from "components/HelpText";
|
import HelpText from "components/HelpText";
|
||||||
import Tooltip from "components/Tooltip";
|
import Tooltip from "components/Tooltip";
|
||||||
import NudeButton from "components/NudeButton";
|
import NudeButton from "components/NudeButton";
|
||||||
|
@ -33,7 +32,6 @@ type Props = {
|
||||||
type InviteRequest = {
|
type InviteRequest = {
|
||||||
email: string,
|
email: string,
|
||||||
name: string,
|
name: string,
|
||||||
guest: boolean,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
@observer
|
@observer
|
||||||
|
@ -42,9 +40,9 @@ class Invite extends React.Component<Props> {
|
||||||
@observable linkCopied: boolean = false;
|
@observable linkCopied: boolean = false;
|
||||||
@observable
|
@observable
|
||||||
invites: InviteRequest[] = [
|
invites: InviteRequest[] = [
|
||||||
{ email: "", name: "", guest: false },
|
{ email: "", name: "" },
|
||||||
{ email: "", name: "", guest: false },
|
{ email: "", name: "" },
|
||||||
{ email: "", name: "", guest: false },
|
{ email: "", name: "" },
|
||||||
];
|
];
|
||||||
|
|
||||||
handleSubmit = async (ev: SyntheticEvent<>) => {
|
handleSubmit = async (ev: SyntheticEvent<>) => {
|
||||||
|
@ -80,7 +78,7 @@ class Invite extends React.Component<Props> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.invites.push({ email: "", name: "", guest: false });
|
this.invites.push({ email: "", name: "" });
|
||||||
};
|
};
|
||||||
|
|
||||||
@action
|
@action
|
||||||
|
@ -106,8 +104,8 @@ class Invite extends React.Component<Props> {
|
||||||
{team.guestSignin ? (
|
{team.guestSignin ? (
|
||||||
<HelpText>
|
<HelpText>
|
||||||
Invite team members or guests to join your knowledge base. Team
|
Invite team members or guests to join your knowledge base. Team
|
||||||
members can sign in with {team.signinMethods} and guests can use
|
members can sign in with {team.signinMethods} or use their email
|
||||||
their email address.
|
address.
|
||||||
</HelpText>
|
</HelpText>
|
||||||
) : (
|
) : (
|
||||||
<HelpText>
|
<HelpText>
|
||||||
|
@ -116,22 +114,35 @@ class Invite extends React.Component<Props> {
|
||||||
{can.update && (
|
{can.update && (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
As an admin you can also{" "}
|
As an admin you can also{" "}
|
||||||
<Link to="/settings/security">enable guest invites</Link>.
|
<Link to="/settings/security">enable email sign-in</Link>.
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
)}
|
)}
|
||||||
</HelpText>
|
</HelpText>
|
||||||
)}
|
)}
|
||||||
{team.subdomain && (
|
{team.subdomain && (
|
||||||
<CopyBlock>
|
<CopyBlock>
|
||||||
Want a link to share directly with your team?
|
<Flex align="flex-end">
|
||||||
<Flex>
|
<Input
|
||||||
<Input type="text" value={team.url} readOnly flex />
|
type="text"
|
||||||
|
value={team.url}
|
||||||
|
label="Want a link to share directly with your team?"
|
||||||
|
readOnly
|
||||||
|
flex
|
||||||
|
/>
|
||||||
<CopyToClipboard text={team.url} onCopy={this.handleCopy}>
|
<CopyToClipboard text={team.url} onCopy={this.handleCopy}>
|
||||||
<Button type="button" neutral>
|
<Button
|
||||||
|
type="button"
|
||||||
|
icon={<LinkIcon />}
|
||||||
|
style={{ marginBottom: "16px" }}
|
||||||
|
neutral
|
||||||
|
>
|
||||||
{this.linkCopied ? "Link copied" : "Copy link"}
|
{this.linkCopied ? "Link copied" : "Copy link"}
|
||||||
</Button>
|
</Button>
|
||||||
</CopyToClipboard>
|
</CopyToClipboard>
|
||||||
</Flex>
|
</Flex>
|
||||||
|
<p>
|
||||||
|
<hr />
|
||||||
|
</p>
|
||||||
</CopyBlock>
|
</CopyBlock>
|
||||||
)}
|
)}
|
||||||
{this.invites.map((invite, index) => (
|
{this.invites.map((invite, index) => (
|
||||||
|
@ -159,29 +170,6 @@ class Invite extends React.Component<Props> {
|
||||||
required={!!invite.email}
|
required={!!invite.email}
|
||||||
flex
|
flex
|
||||||
/>
|
/>
|
||||||
{team.guestSignin && (
|
|
||||||
<React.Fragment>
|
|
||||||
|
|
||||||
<Tooltip
|
|
||||||
tooltip={
|
|
||||||
<span>
|
|
||||||
Guests can sign in with email and <br />do not require{" "}
|
|
||||||
{team.signinMethods} accounts
|
|
||||||
</span>
|
|
||||||
}
|
|
||||||
placement="top"
|
|
||||||
>
|
|
||||||
<Guest>
|
|
||||||
<Checkbox
|
|
||||||
name="guest"
|
|
||||||
label="Guest"
|
|
||||||
onChange={ev => this.handleGuestChange(ev, index)}
|
|
||||||
checked={invite.guest}
|
|
||||||
/>
|
|
||||||
</Guest>
|
|
||||||
</Tooltip>
|
|
||||||
</React.Fragment>
|
|
||||||
)}
|
|
||||||
{index !== 0 && (
|
{index !== 0 && (
|
||||||
<Remove>
|
<Remove>
|
||||||
<Tooltip tooltip="Remove invite" placement="top">
|
<Tooltip tooltip="Remove invite" placement="top">
|
||||||
|
@ -220,22 +208,8 @@ class Invite extends React.Component<Props> {
|
||||||
}
|
}
|
||||||
|
|
||||||
const CopyBlock = styled("div")`
|
const CopyBlock = styled("div")`
|
||||||
|
margin: 2em 0;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
background: ${props => props.theme.secondaryBackground};
|
|
||||||
padding: 8px 16px 4px;
|
|
||||||
border-radius: 8px;
|
|
||||||
margin-bottom: 24px;
|
|
||||||
|
|
||||||
input {
|
|
||||||
background: ${props => props.theme.background};
|
|
||||||
border-radius: 4px;
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
const Guest = styled("div")`
|
|
||||||
padding-top: 4px;
|
|
||||||
margin: 0 4px 16px;
|
|
||||||
align-self: flex-end;
|
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const Remove = styled("div")`
|
const Remove = styled("div")`
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
import Key from "components/Key";
|
import Key from "components/Key";
|
||||||
import Flex from "shared/components/Flex";
|
import Flex from "components/Flex";
|
||||||
import HelpText from "components/HelpText";
|
import HelpText from "components/HelpText";
|
||||||
import { meta } from "utils/keyboard";
|
import { meta } from "utils/keyboard";
|
||||||
|
|
||||||
|
|
|
@ -1,61 +1,55 @@
|
||||||
// @flow
|
// @flow
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import Notice from "../../../shared/components/Notice";
|
import NoticeAlert from "components/NoticeAlert";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
notice?: string,
|
notice?: string,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function AuthNotices({ notice }: Props) {
|
export default function Notices({ notice }: Props) {
|
||||||
return (
|
return (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
{notice === "guest-success" && (
|
|
||||||
<Notice>
|
|
||||||
A magic sign-in link has been sent to your email address, no password
|
|
||||||
needed.
|
|
||||||
</Notice>
|
|
||||||
)}
|
|
||||||
{notice === "google-hd" && (
|
{notice === "google-hd" && (
|
||||||
<Notice>
|
<NoticeAlert>
|
||||||
Sorry, Google sign in cannot be used with a personal email. Please try
|
Sorry, Google sign in cannot be used with a personal email. Please try
|
||||||
signing in with your company Google account.
|
signing in with your company GSuite account.
|
||||||
</Notice>
|
</NoticeAlert>
|
||||||
)}
|
)}
|
||||||
{notice === "hd-not-allowed" && (
|
{notice === "hd-not-allowed" && (
|
||||||
<Notice>
|
<NoticeAlert>
|
||||||
Sorry, your Google apps domain is not allowed. Please try again with
|
Sorry, your Google apps domain is not allowed. Please try again with
|
||||||
an allowed company domain.
|
an allowed company domain.
|
||||||
</Notice>
|
</NoticeAlert>
|
||||||
)}
|
)}
|
||||||
{notice === "email-auth-required" && (
|
{notice === "email-auth-required" && (
|
||||||
<Notice>
|
<NoticeAlert>
|
||||||
Your account uses email sign-in, please sign-in with email to
|
Your account uses email sign-in, please sign-in with email to
|
||||||
continue.
|
continue.
|
||||||
</Notice>
|
</NoticeAlert>
|
||||||
)}
|
)}
|
||||||
{notice === "email-auth-ratelimit" && (
|
{notice === "email-auth-ratelimit" && (
|
||||||
<Notice>
|
<NoticeAlert>
|
||||||
An email sign-in link was recently sent, please check your inbox and
|
An email sign-in link was recently sent, please check your inbox or
|
||||||
try again in a few minutes.
|
try again in a few minutes.
|
||||||
</Notice>
|
</NoticeAlert>
|
||||||
)}
|
)}
|
||||||
{notice === "auth-error" && (
|
{notice === "auth-error" && (
|
||||||
<Notice>
|
<NoticeAlert>
|
||||||
Authentication failed - we were unable to sign you in at this time.
|
Authentication failed - we were unable to sign you in at this time.
|
||||||
Please try again.
|
Please try again.
|
||||||
</Notice>
|
</NoticeAlert>
|
||||||
)}
|
)}
|
||||||
{notice === "expired-token" && (
|
{notice === "expired-token" && (
|
||||||
<Notice>
|
<NoticeAlert>
|
||||||
Sorry, it looks like that sign-in link is no longer valid, please try
|
Sorry, it looks like that sign-in link is no longer valid, please try
|
||||||
requesting another.
|
requesting another.
|
||||||
</Notice>
|
</NoticeAlert>
|
||||||
)}
|
)}
|
||||||
{notice === "suspended" && (
|
{notice === "suspended" && (
|
||||||
<Notice>
|
<NoticeAlert>
|
||||||
Your Outline account has been suspended. To re-activate your account,
|
Your Outline account has been suspended. To re-activate your account,
|
||||||
please contact a team admin.
|
please contact a team admin.
|
||||||
</Notice>
|
</NoticeAlert>
|
||||||
)}
|
)}
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
);
|
);
|
|
@ -0,0 +1,147 @@
|
||||||
|
// @flow
|
||||||
|
import * as React from "react";
|
||||||
|
import styled from "styled-components";
|
||||||
|
import { EmailIcon } from "outline-icons";
|
||||||
|
import { client } from "utils/ApiClient";
|
||||||
|
import ButtonLarge from "components/ButtonLarge";
|
||||||
|
import SlackLogo from "components/SlackLogo";
|
||||||
|
import GoogleLogo from "components/GoogleLogo";
|
||||||
|
import InputLarge from "components/InputLarge";
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
id: string,
|
||||||
|
name: string,
|
||||||
|
authUrl: string,
|
||||||
|
isCreate: boolean,
|
||||||
|
onEmailSuccess: (email: string) => void,
|
||||||
|
};
|
||||||
|
|
||||||
|
type State = {
|
||||||
|
showEmailSignin: boolean,
|
||||||
|
isSubmitting: boolean,
|
||||||
|
email: string,
|
||||||
|
};
|
||||||
|
|
||||||
|
class Service extends React.Component<Props, State> {
|
||||||
|
state = {
|
||||||
|
showEmailSignin: false,
|
||||||
|
isSubmitting: false,
|
||||||
|
email: "",
|
||||||
|
};
|
||||||
|
|
||||||
|
handleChangeEmail = (event: SyntheticInputEvent<HTMLInputElement>) => {
|
||||||
|
this.setState({ email: event.target.value });
|
||||||
|
};
|
||||||
|
|
||||||
|
handleSubmitEmail = async (event: SyntheticEvent<HTMLFormElement>) => {
|
||||||
|
event.preventDefault();
|
||||||
|
|
||||||
|
if (this.state.showEmailSignin && this.state.email) {
|
||||||
|
this.setState({ isSubmitting: true });
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await client.post(event.currentTarget.action, {
|
||||||
|
email: this.state.email,
|
||||||
|
});
|
||||||
|
if (response.redirect) {
|
||||||
|
window.location.href = response.redirect;
|
||||||
|
} else {
|
||||||
|
this.props.onEmailSuccess(this.state.email);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
this.setState({ isSubmitting: false });
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.setState({ showEmailSignin: true });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { isCreate, id, name, authUrl } = this.props;
|
||||||
|
|
||||||
|
if (id === "email") {
|
||||||
|
if (isCreate) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Wrapper key="email">
|
||||||
|
<Form
|
||||||
|
method="POST"
|
||||||
|
action="/auth/email"
|
||||||
|
onSubmit={this.handleSubmitEmail}
|
||||||
|
>
|
||||||
|
{this.state.showEmailSignin ? (
|
||||||
|
<React.Fragment>
|
||||||
|
<InputLarge
|
||||||
|
type="email"
|
||||||
|
name="email"
|
||||||
|
placeholder="me@domain.com"
|
||||||
|
value={this.state.email}
|
||||||
|
onChange={this.handleChangeEmail}
|
||||||
|
disabled={this.state.isSubmitting}
|
||||||
|
autoFocus
|
||||||
|
required
|
||||||
|
short
|
||||||
|
/>
|
||||||
|
<ButtonLarge type="submit" disabled={this.state.isSubmitting}>
|
||||||
|
Sign In →
|
||||||
|
</ButtonLarge>
|
||||||
|
</React.Fragment>
|
||||||
|
) : (
|
||||||
|
<ButtonLarge type="submit" icon={<EmailIcon />} fullwidth>
|
||||||
|
Continue with Email
|
||||||
|
</ButtonLarge>
|
||||||
|
)}
|
||||||
|
</Form>
|
||||||
|
</Wrapper>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const icon =
|
||||||
|
id === "slack" ? (
|
||||||
|
<Logo>
|
||||||
|
<SlackLogo size={16} />
|
||||||
|
</Logo>
|
||||||
|
) : id === "google" ? (
|
||||||
|
<Logo>
|
||||||
|
<GoogleLogo size={16} />
|
||||||
|
</Logo>
|
||||||
|
) : (
|
||||||
|
undefined
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Wrapper key={id}>
|
||||||
|
<ButtonLarge
|
||||||
|
onClick={() => (window.location.href = authUrl)}
|
||||||
|
icon={icon}
|
||||||
|
fullwidth
|
||||||
|
>
|
||||||
|
{isCreate ? "Sign up" : "Continue"} with {name}
|
||||||
|
</ButtonLarge>
|
||||||
|
</Wrapper>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const Logo = styled.div`
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: 24px;
|
||||||
|
height: 24px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const Wrapper = styled.div`
|
||||||
|
margin-bottom: 1em;
|
||||||
|
width: 100%;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const Form = styled.form`
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export default Service;
|
|
@ -0,0 +1,230 @@
|
||||||
|
// @flow
|
||||||
|
import * as React from "react";
|
||||||
|
import styled from "styled-components";
|
||||||
|
import { BackIcon, EmailIcon } from "outline-icons";
|
||||||
|
import { observer, inject } from "mobx-react";
|
||||||
|
import { Redirect } from "react-router-dom";
|
||||||
|
import { find } from "lodash";
|
||||||
|
import Flex from "components/Flex";
|
||||||
|
import TeamLogo from "components/TeamLogo";
|
||||||
|
import OutlineLogo from "components/OutlineLogo";
|
||||||
|
import Heading from "components/Heading";
|
||||||
|
import PageTitle from "components/PageTitle";
|
||||||
|
import ButtonLarge from "components/ButtonLarge";
|
||||||
|
import HelpText from "components/HelpText";
|
||||||
|
import Fade from "components/Fade";
|
||||||
|
import Service from "./Service";
|
||||||
|
import Notices from "./Notices";
|
||||||
|
import AuthStore from "stores/AuthStore";
|
||||||
|
import getQueryVariable from "shared/utils/getQueryVariable";
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
auth: AuthStore,
|
||||||
|
location: Object,
|
||||||
|
};
|
||||||
|
|
||||||
|
type State = {
|
||||||
|
emailLinkSentTo: string,
|
||||||
|
};
|
||||||
|
|
||||||
|
@observer
|
||||||
|
class Login extends React.Component<Props, State> {
|
||||||
|
state = {
|
||||||
|
emailLinkSentTo: "",
|
||||||
|
};
|
||||||
|
|
||||||
|
handleReset = () => {
|
||||||
|
this.setState({ emailLinkSentTo: "" });
|
||||||
|
};
|
||||||
|
|
||||||
|
handleEmailSuccess = email => {
|
||||||
|
this.setState({ emailLinkSentTo: email });
|
||||||
|
};
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { auth, location } = this.props;
|
||||||
|
const { config } = auth;
|
||||||
|
const isCreate = location.pathname === "/create";
|
||||||
|
|
||||||
|
if (auth.authenticated) {
|
||||||
|
return <Redirect to="/home" />;
|
||||||
|
}
|
||||||
|
|
||||||
|
// we're counting on the config request being fast
|
||||||
|
if (!config) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const hasMultipleServices = config.services.length > 1;
|
||||||
|
const defaultService = find(
|
||||||
|
config.services,
|
||||||
|
service => service.id === auth.lastSignedIn
|
||||||
|
);
|
||||||
|
|
||||||
|
const header =
|
||||||
|
process.env.DEPLOYMENT === "hosted" &&
|
||||||
|
(config.hostname ? (
|
||||||
|
<Back href={process.env.URL}>
|
||||||
|
<BackIcon color="currentColor" /> Back to home
|
||||||
|
</Back>
|
||||||
|
) : (
|
||||||
|
<Back href="https://www.getoutline.com">
|
||||||
|
<BackIcon color="currentColor" /> Back to website
|
||||||
|
</Back>
|
||||||
|
));
|
||||||
|
|
||||||
|
if (this.state.emailLinkSentTo) {
|
||||||
|
return (
|
||||||
|
<Background>
|
||||||
|
{header}
|
||||||
|
<Centered align="center" justify="center" column auto>
|
||||||
|
<PageTitle title="Check your email" />
|
||||||
|
<CheckEmailIcon size={38} color="currentColor" />
|
||||||
|
|
||||||
|
<Heading>Check your email</Heading>
|
||||||
|
<Note>
|
||||||
|
A magic sign-in link has been sent to the email{" "}
|
||||||
|
<em>{this.state.emailLinkSentTo}</em>, no password needed.
|
||||||
|
</Note>
|
||||||
|
<br />
|
||||||
|
<ButtonLarge onClick={this.handleReset} fullwidth neutral>
|
||||||
|
Back to login
|
||||||
|
</ButtonLarge>
|
||||||
|
</Centered>
|
||||||
|
</Background>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Background>
|
||||||
|
{header}
|
||||||
|
<Centered align="center" justify="center" column auto>
|
||||||
|
<PageTitle title="Login" />
|
||||||
|
<Logo>
|
||||||
|
{process.env.TEAM_LOGO && process.env.DEPLOYMENT !== "hosted" ? (
|
||||||
|
<TeamLogo src={process.env.TEAM_LOGO} />
|
||||||
|
) : (
|
||||||
|
<OutlineLogo size={38} fill="currentColor" />
|
||||||
|
)}
|
||||||
|
</Logo>
|
||||||
|
|
||||||
|
{isCreate ? (
|
||||||
|
<Heading>Create an account</Heading>
|
||||||
|
) : (
|
||||||
|
<Heading>Login to {config.name || "Outline"}</Heading>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<Notices notice={getQueryVariable("notice")} />
|
||||||
|
|
||||||
|
{defaultService && (
|
||||||
|
<React.Fragment key={defaultService.id}>
|
||||||
|
<Service
|
||||||
|
isCreate={isCreate}
|
||||||
|
onEmailSuccess={this.handleEmailSuccess}
|
||||||
|
{...defaultService}
|
||||||
|
/>
|
||||||
|
{hasMultipleServices && (
|
||||||
|
<React.Fragment>
|
||||||
|
<Note>
|
||||||
|
You signed in with {defaultService.name} last time.
|
||||||
|
</Note>
|
||||||
|
<Or />
|
||||||
|
</React.Fragment>
|
||||||
|
)}
|
||||||
|
</React.Fragment>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{config.services.map(service => {
|
||||||
|
if (service.id === auth.lastSignedIn) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Service
|
||||||
|
key={service.id}
|
||||||
|
isCreate={isCreate}
|
||||||
|
onEmailSuccess={this.handleEmailSuccess}
|
||||||
|
{...service}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</Centered>
|
||||||
|
</Background>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const CheckEmailIcon = styled(EmailIcon)`
|
||||||
|
margin-bottom: -1.5em;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const Background = styled(Fade)`
|
||||||
|
width: 100vw;
|
||||||
|
height: 100vh;
|
||||||
|
background: ${props => props.theme.background};
|
||||||
|
display: flex;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const Logo = styled.div`
|
||||||
|
margin-bottom: -1.5em;
|
||||||
|
height: 38px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const Note = styled(HelpText)`
|
||||||
|
text-align: center;
|
||||||
|
font-size: 14px;
|
||||||
|
|
||||||
|
em {
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const Back = styled.a`
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
color: inherit;
|
||||||
|
padding: 32px;
|
||||||
|
font-weight: 500;
|
||||||
|
position: absolute;
|
||||||
|
|
||||||
|
svg {
|
||||||
|
transition: transform 100ms ease-in-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
svg {
|
||||||
|
transform: translateX(-4px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const Or = styled.hr`
|
||||||
|
margin: 1em 0;
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
&:after {
|
||||||
|
content: "Or";
|
||||||
|
display: block;
|
||||||
|
position: absolute;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate3d(-50%, -50%, 0);
|
||||||
|
text-transform: uppercase;
|
||||||
|
font-size: 11px;
|
||||||
|
color: ${props => props.theme.textSecondary};
|
||||||
|
background: ${props => props.theme.background};
|
||||||
|
border-radius: 2px;
|
||||||
|
padding: 0 4px;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const Centered = styled(Flex)`
|
||||||
|
user-select: none;
|
||||||
|
width: 90vw;
|
||||||
|
height: 100%;
|
||||||
|
max-width: 320px;
|
||||||
|
margin: 0 auto;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export default inject("auth")(Login);
|
|
@ -19,7 +19,7 @@ import UsersStore from "stores/UsersStore";
|
||||||
import { newDocumentUrl, searchUrl } from "utils/routeHelpers";
|
import { newDocumentUrl, searchUrl } from "utils/routeHelpers";
|
||||||
import { meta } from "utils/keyboard";
|
import { meta } from "utils/keyboard";
|
||||||
|
|
||||||
import Flex from "shared/components/Flex";
|
import Flex from "components/Flex";
|
||||||
import Button from "components/Button";
|
import Button from "components/Button";
|
||||||
import Empty from "components/Empty";
|
import Empty from "components/Empty";
|
||||||
import Fade from "components/Fade";
|
import Fade from "components/Fade";
|
||||||
|
|
|
@ -3,7 +3,7 @@ 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";
|
||||||
import HelpText from "components/HelpText";
|
import HelpText from "components/HelpText";
|
||||||
import Flex from "shared/components/Flex";
|
import Flex from "components/Flex";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
label: string,
|
label: string,
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import styled, { withTheme } from "styled-components";
|
import styled, { withTheme } from "styled-components";
|
||||||
import { SearchIcon } from "outline-icons";
|
import { SearchIcon } from "outline-icons";
|
||||||
import Flex from "shared/components/Flex";
|
import Flex from "components/Flex";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
onChange: string => void,
|
onChange: string => void,
|
||||||
|
|
|
@ -12,7 +12,7 @@ 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 HelpText from "components/HelpText";
|
import HelpText from "components/HelpText";
|
||||||
import Flex from "shared/components/Flex";
|
import Flex from "components/Flex";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
auth: AuthStore,
|
auth: AuthStore,
|
||||||
|
|
|
@ -9,7 +9,7 @@ import HelpText from "components/HelpText";
|
||||||
import Input from "components/Input";
|
import Input from "components/Input";
|
||||||
import Subheading from "components/Subheading";
|
import Subheading from "components/Subheading";
|
||||||
import NotificationListItem from "./components/NotificationListItem";
|
import NotificationListItem from "./components/NotificationListItem";
|
||||||
import Notice from "shared/components/Notice";
|
import Notice from "components/Notice";
|
||||||
|
|
||||||
import UiStore from "stores/UiStore";
|
import UiStore from "stores/UiStore";
|
||||||
import AuthStore from "stores/AuthStore";
|
import AuthStore from "stores/AuthStore";
|
||||||
|
|
|
@ -12,7 +12,7 @@ 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 UserDelete from "scenes/UserDelete";
|
import UserDelete from "scenes/UserDelete";
|
||||||
import Flex from "shared/components/Flex";
|
import Flex from "components/Flex";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
auth: AuthStore,
|
auth: AuthStore,
|
||||||
|
|
|
@ -60,8 +60,6 @@ class Security extends React.Component<Props> {
|
||||||
}, 500);
|
}, 500);
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { team } = this.props.auth;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CenteredContent>
|
<CenteredContent>
|
||||||
<PageTitle title="Security" />
|
<PageTitle title="Security" />
|
||||||
|
@ -72,27 +70,25 @@ class Security extends React.Component<Props> {
|
||||||
</HelpText>
|
</HelpText>
|
||||||
|
|
||||||
<Checkbox
|
<Checkbox
|
||||||
label="Allow guest invites"
|
label="Allow email authentication"
|
||||||
name="guestSignin"
|
name="guestSignin"
|
||||||
checked={this.guestSignin}
|
checked={this.guestSignin}
|
||||||
onChange={this.handleChange}
|
onChange={this.handleChange}
|
||||||
note={`When enabled guests can be invited by email address and are able to signin without ${
|
note="When enabled, users can sign-in using their email address"
|
||||||
team ? team.signinMethods : "SSO"
|
|
||||||
}`}
|
|
||||||
/>
|
/>
|
||||||
<Checkbox
|
<Checkbox
|
||||||
label="Public document sharing"
|
label="Public document sharing"
|
||||||
name="sharing"
|
name="sharing"
|
||||||
checked={this.sharing}
|
checked={this.sharing}
|
||||||
onChange={this.handleChange}
|
onChange={this.handleChange}
|
||||||
note="When enabled documents can be shared publicly by any team member"
|
note="When enabled, documents can be shared publicly on the internet by any team member"
|
||||||
/>
|
/>
|
||||||
<Checkbox
|
<Checkbox
|
||||||
label="Rich service embeds"
|
label="Rich service embeds"
|
||||||
name="documentEmbeds"
|
name="documentEmbeds"
|
||||||
checked={this.documentEmbeds}
|
checked={this.documentEmbeds}
|
||||||
onChange={this.handleChange}
|
onChange={this.handleChange}
|
||||||
note="Convert links to supported services into rich embeds within your documents"
|
note="Links to supported services are shown as rich embeds within your documents"
|
||||||
/>
|
/>
|
||||||
</CenteredContent>
|
</CenteredContent>
|
||||||
);
|
);
|
||||||
|
|
|
@ -12,7 +12,7 @@ import SlackButton from "./components/SlackButton";
|
||||||
import CollectionsStore from "stores/CollectionsStore";
|
import CollectionsStore from "stores/CollectionsStore";
|
||||||
import IntegrationsStore from "stores/IntegrationsStore";
|
import IntegrationsStore from "stores/IntegrationsStore";
|
||||||
import AuthStore from "stores/AuthStore";
|
import AuthStore from "stores/AuthStore";
|
||||||
import Notice from "shared/components/Notice";
|
import Notice from "components/Notice";
|
||||||
import getQueryVariable from "shared/utils/getQueryVariable";
|
import getQueryVariable from "shared/utils/getQueryVariable";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
|
|
|
@ -3,7 +3,7 @@ import * as React from "react";
|
||||||
import { Link } from "react-router-dom";
|
import { Link } from "react-router-dom";
|
||||||
import { capitalize } from "lodash";
|
import { capitalize } from "lodash";
|
||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
import Time from "shared/components/Time";
|
import Time from "components/Time";
|
||||||
import ListItem from "components/List/Item";
|
import ListItem from "components/List/Item";
|
||||||
import Avatar from "components/Avatar";
|
import Avatar from "components/Avatar";
|
||||||
import Event from "models/Event";
|
import Event from "models/Event";
|
||||||
|
|
|
@ -5,7 +5,7 @@ import { observer, inject } from "mobx-react";
|
||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
import Dropzone from "react-dropzone";
|
import Dropzone from "react-dropzone";
|
||||||
import LoadingIndicator from "components/LoadingIndicator";
|
import LoadingIndicator from "components/LoadingIndicator";
|
||||||
import Flex from "shared/components/Flex";
|
import Flex from "components/Flex";
|
||||||
import Modal from "components/Modal";
|
import Modal from "components/Modal";
|
||||||
import Button from "components/Button";
|
import Button from "components/Button";
|
||||||
import AvatarEditor from "react-avatar-editor";
|
import AvatarEditor from "react-avatar-editor";
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import ShareMenu from "menus/ShareMenu";
|
import ShareMenu from "menus/ShareMenu";
|
||||||
import ListItem from "components/List/Item";
|
import ListItem from "components/List/Item";
|
||||||
import Time from "shared/components/Time";
|
import Time from "components/Time";
|
||||||
import Share from "models/Share";
|
import Share from "models/Share";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
import { slackAuth } from "shared/utils/routeHelpers";
|
import { slackAuth } from "shared/utils/routeHelpers";
|
||||||
import SlackLogo from "shared/components/SlackLogo";
|
import SlackLogo from "components/SlackLogo";
|
||||||
import Button from "components/Button";
|
import Button from "components/Button";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
|
|
|
@ -8,7 +8,7 @@ import Avatar from "components/Avatar";
|
||||||
import Badge from "components/Badge";
|
import Badge from "components/Badge";
|
||||||
import UserProfile from "scenes/UserProfile";
|
import UserProfile from "scenes/UserProfile";
|
||||||
import ListItem from "components/List/Item";
|
import ListItem from "components/List/Item";
|
||||||
import Time from "shared/components/Time";
|
import Time from "components/Time";
|
||||||
import User from "models/User";
|
import User from "models/User";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
|
|
|
@ -3,7 +3,7 @@ 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 Button from "components/Button";
|
import Button from "components/Button";
|
||||||
import Flex from "shared/components/Flex";
|
import Flex from "components/Flex";
|
||||||
import HelpText from "components/HelpText";
|
import HelpText from "components/HelpText";
|
||||||
import Modal from "components/Modal";
|
import Modal from "components/Modal";
|
||||||
import AuthStore from "stores/AuthStore";
|
import AuthStore from "stores/AuthStore";
|
||||||
|
|
|
@ -5,7 +5,7 @@ import distanceInWordsToNow from "date-fns/distance_in_words_to_now";
|
||||||
import { inject, observer } from "mobx-react";
|
import { inject, observer } from "mobx-react";
|
||||||
import { withRouter, type RouterHistory } from "react-router-dom";
|
import { withRouter, type RouterHistory } from "react-router-dom";
|
||||||
import { EditIcon } from "outline-icons";
|
import { EditIcon } from "outline-icons";
|
||||||
import Flex from "shared/components/Flex";
|
import Flex from "components/Flex";
|
||||||
import HelpText from "components/HelpText";
|
import HelpText from "components/HelpText";
|
||||||
import Modal from "components/Modal";
|
import Modal from "components/Modal";
|
||||||
import Button from "components/Button";
|
import Button from "components/Button";
|
||||||
|
|
|
@ -10,13 +10,27 @@ import Team from "models/Team";
|
||||||
|
|
||||||
const AUTH_STORE = "AUTH_STORE";
|
const AUTH_STORE = "AUTH_STORE";
|
||||||
|
|
||||||
|
type Service = {
|
||||||
|
id: string,
|
||||||
|
name: string,
|
||||||
|
authUrl: string,
|
||||||
|
};
|
||||||
|
|
||||||
|
type Config = {
|
||||||
|
name?: string,
|
||||||
|
hostname?: string,
|
||||||
|
services: Service[],
|
||||||
|
};
|
||||||
|
|
||||||
export default class AuthStore {
|
export default class AuthStore {
|
||||||
@observable user: ?User;
|
@observable user: ?User;
|
||||||
@observable team: ?Team;
|
@observable team: ?Team;
|
||||||
@observable token: ?string;
|
@observable token: ?string;
|
||||||
|
@observable lastSignedIn: ?string;
|
||||||
@observable isSaving: boolean = false;
|
@observable isSaving: boolean = false;
|
||||||
@observable isSuspended: boolean = false;
|
@observable isSuspended: boolean = false;
|
||||||
@observable suspendedContactEmail: ?string;
|
@observable suspendedContactEmail: ?string;
|
||||||
|
@observable config: ?Config;
|
||||||
rootStore: RootStore;
|
rootStore: RootStore;
|
||||||
|
|
||||||
constructor(rootStore: RootStore) {
|
constructor(rootStore: RootStore) {
|
||||||
|
@ -32,8 +46,12 @@ export default class AuthStore {
|
||||||
this.user = new User(data.user);
|
this.user = new User(data.user);
|
||||||
this.team = new Team(data.team);
|
this.team = new Team(data.team);
|
||||||
this.token = getCookie("accessToken");
|
this.token = getCookie("accessToken");
|
||||||
|
this.lastSignedIn = getCookie("lastSignedIn");
|
||||||
|
setImmediate(() => this.fetchConfig());
|
||||||
|
|
||||||
if (this.token) setImmediate(() => this.fetch());
|
if (this.token) {
|
||||||
|
setImmediate(() => this.fetch());
|
||||||
|
}
|
||||||
|
|
||||||
autorun(() => {
|
autorun(() => {
|
||||||
try {
|
try {
|
||||||
|
@ -63,6 +81,13 @@ export default class AuthStore {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@action
|
||||||
|
fetchConfig = async () => {
|
||||||
|
const res = await client.post("/auth.config");
|
||||||
|
invariant(res && res.data, "Config not available");
|
||||||
|
this.config = res.data;
|
||||||
|
};
|
||||||
|
|
||||||
@action
|
@action
|
||||||
fetch = async () => {
|
fetch = async () => {
|
||||||
try {
|
try {
|
||||||
|
@ -158,10 +183,16 @@ export default class AuthStore {
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
|
this.token = null;
|
||||||
|
|
||||||
// if this logout was forced from an authenticated route then
|
// if this logout was forced from an authenticated route then
|
||||||
// save the current path so we can go back there once signed in
|
// save the current path so we can go back there once signed in
|
||||||
if (savePath) {
|
if (savePath) {
|
||||||
setCookie("postLoginRedirectPath", window.location.pathname);
|
const pathName = window.location.pathname;
|
||||||
|
|
||||||
|
if (pathName !== "/" && pathName !== "/create") {
|
||||||
|
setCookie("postLoginRedirectPath", pathName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// remove authentication token itself
|
// remove authentication token itself
|
||||||
|
@ -178,8 +209,5 @@ export default class AuthStore {
|
||||||
});
|
});
|
||||||
this.team = null;
|
this.team = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// add a timestamp to force reload from server
|
|
||||||
window.location.href = `${BASE_URL}?done=${new Date().getTime()}`;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,6 +34,7 @@ class ApiClient {
|
||||||
) => {
|
) => {
|
||||||
let body;
|
let body;
|
||||||
let modifiedPath;
|
let modifiedPath;
|
||||||
|
let urlToFetch;
|
||||||
|
|
||||||
if (method === "GET") {
|
if (method === "GET") {
|
||||||
if (data) {
|
if (data) {
|
||||||
|
@ -45,6 +46,12 @@ class ApiClient {
|
||||||
body = data ? JSON.stringify(data) : undefined;
|
body = data ? JSON.stringify(data) : undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (path.match(/^http/)) {
|
||||||
|
urlToFetch = modifiedPath || path;
|
||||||
|
} else {
|
||||||
|
urlToFetch = this.baseUrl + (modifiedPath || path);
|
||||||
|
}
|
||||||
|
|
||||||
// Construct headers
|
// Construct headers
|
||||||
const headers = new Headers({
|
const headers = new Headers({
|
||||||
Accept: "application/json",
|
Accept: "application/json",
|
||||||
|
@ -60,7 +67,7 @@ class ApiClient {
|
||||||
|
|
||||||
let response;
|
let response;
|
||||||
try {
|
try {
|
||||||
response = await fetch(this.baseUrl + (modifiedPath || path), {
|
response = await fetch(urlToFetch, {
|
||||||
method,
|
method,
|
||||||
body,
|
body,
|
||||||
headers,
|
headers,
|
||||||
|
|
|
@ -1,144 +0,0 @@
|
||||||
// flow-typed signature: d7c6f4d4223c61be85becba99f8e5712
|
|
||||||
// flow-typed version: <<STUB>>/styled-components-grid_v^1.0.0-preview.15/flow_v0.71.0
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This is an autogenerated libdef stub for:
|
|
||||||
*
|
|
||||||
* 'styled-components-grid'
|
|
||||||
*
|
|
||||||
* Fill this stub out by replacing all the `any` types.
|
|
||||||
*
|
|
||||||
* Once filled out, we encourage you to share your work with the
|
|
||||||
* community by sending a pull request to:
|
|
||||||
* https://github.com/flowtype/flow-typed
|
|
||||||
*/
|
|
||||||
|
|
||||||
declare module 'styled-components-grid' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* We include stubs for each file inside this npm package in case you need to
|
|
||||||
* require those files directly. Feel free to delete any files that aren't
|
|
||||||
* needed.
|
|
||||||
*/
|
|
||||||
declare module 'styled-components-grid/dist/cjs/components/Grid' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module 'styled-components-grid/dist/cjs/components/GridUnit' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module 'styled-components-grid/dist/cjs/components/index' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module 'styled-components-grid/dist/cjs/index' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module 'styled-components-grid/dist/cjs/mixins/grid' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module 'styled-components-grid/dist/cjs/mixins/gridUnit' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module 'styled-components-grid/dist/cjs/mixins/index' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module 'styled-components-grid/dist/es/components/Grid' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module 'styled-components-grid/dist/es/components/GridUnit' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module 'styled-components-grid/dist/es/components/index' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module 'styled-components-grid/dist/es/index' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module 'styled-components-grid/dist/es/mixins/grid' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module 'styled-components-grid/dist/es/mixins/gridUnit' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module 'styled-components-grid/dist/es/mixins/index' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module 'styled-components-grid/dist/example/index' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module 'styled-components-grid/dist/styled-components-grid' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module 'styled-components-grid/dist/styled-components-grid.min' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Filename aliases
|
|
||||||
declare module 'styled-components-grid/dist/cjs/components/Grid.js' {
|
|
||||||
declare module.exports: $Exports<'styled-components-grid/dist/cjs/components/Grid'>;
|
|
||||||
}
|
|
||||||
declare module 'styled-components-grid/dist/cjs/components/GridUnit.js' {
|
|
||||||
declare module.exports: $Exports<'styled-components-grid/dist/cjs/components/GridUnit'>;
|
|
||||||
}
|
|
||||||
declare module 'styled-components-grid/dist/cjs/components/index.js' {
|
|
||||||
declare module.exports: $Exports<'styled-components-grid/dist/cjs/components/index'>;
|
|
||||||
}
|
|
||||||
declare module 'styled-components-grid/dist/cjs/index.js' {
|
|
||||||
declare module.exports: $Exports<'styled-components-grid/dist/cjs/index'>;
|
|
||||||
}
|
|
||||||
declare module 'styled-components-grid/dist/cjs/mixins/grid.js' {
|
|
||||||
declare module.exports: $Exports<'styled-components-grid/dist/cjs/mixins/grid'>;
|
|
||||||
}
|
|
||||||
declare module 'styled-components-grid/dist/cjs/mixins/gridUnit.js' {
|
|
||||||
declare module.exports: $Exports<'styled-components-grid/dist/cjs/mixins/gridUnit'>;
|
|
||||||
}
|
|
||||||
declare module 'styled-components-grid/dist/cjs/mixins/index.js' {
|
|
||||||
declare module.exports: $Exports<'styled-components-grid/dist/cjs/mixins/index'>;
|
|
||||||
}
|
|
||||||
declare module 'styled-components-grid/dist/es/components/Grid.js' {
|
|
||||||
declare module.exports: $Exports<'styled-components-grid/dist/es/components/Grid'>;
|
|
||||||
}
|
|
||||||
declare module 'styled-components-grid/dist/es/components/GridUnit.js' {
|
|
||||||
declare module.exports: $Exports<'styled-components-grid/dist/es/components/GridUnit'>;
|
|
||||||
}
|
|
||||||
declare module 'styled-components-grid/dist/es/components/index.js' {
|
|
||||||
declare module.exports: $Exports<'styled-components-grid/dist/es/components/index'>;
|
|
||||||
}
|
|
||||||
declare module 'styled-components-grid/dist/es/index.js' {
|
|
||||||
declare module.exports: $Exports<'styled-components-grid/dist/es/index'>;
|
|
||||||
}
|
|
||||||
declare module 'styled-components-grid/dist/es/mixins/grid.js' {
|
|
||||||
declare module.exports: $Exports<'styled-components-grid/dist/es/mixins/grid'>;
|
|
||||||
}
|
|
||||||
declare module 'styled-components-grid/dist/es/mixins/gridUnit.js' {
|
|
||||||
declare module.exports: $Exports<'styled-components-grid/dist/es/mixins/gridUnit'>;
|
|
||||||
}
|
|
||||||
declare module 'styled-components-grid/dist/es/mixins/index.js' {
|
|
||||||
declare module.exports: $Exports<'styled-components-grid/dist/es/mixins/index'>;
|
|
||||||
}
|
|
||||||
declare module 'styled-components-grid/dist/example/index.js' {
|
|
||||||
declare module.exports: $Exports<'styled-components-grid/dist/example/index'>;
|
|
||||||
}
|
|
||||||
declare module 'styled-components-grid/dist/styled-components-grid.js' {
|
|
||||||
declare module.exports: $Exports<'styled-components-grid/dist/styled-components-grid'>;
|
|
||||||
}
|
|
||||||
declare module 'styled-components-grid/dist/styled-components-grid.min.js' {
|
|
||||||
declare module.exports: $Exports<'styled-components-grid/dist/styled-components-grid.min'>;
|
|
||||||
}
|
|
34
index.js
34
index.js
|
@ -1,12 +1,12 @@
|
||||||
// @flow
|
// @flow
|
||||||
require('./init');
|
require("./init");
|
||||||
|
|
||||||
if (
|
if (
|
||||||
!process.env.SECRET_KEY ||
|
!process.env.SECRET_KEY ||
|
||||||
process.env.SECRET_KEY === 'generate_a_new_key'
|
process.env.SECRET_KEY === "generate_a_new_key"
|
||||||
) {
|
) {
|
||||||
console.error(
|
console.error(
|
||||||
'The SECRET_KEY env variable must be set with the output of `openssl rand -hex 32`'
|
"The SECRET_KEY env variable must be set with the output of `openssl rand -hex 32`"
|
||||||
);
|
);
|
||||||
// $FlowFixMe
|
// $FlowFixMe
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
|
@ -14,11 +14,11 @@ if (
|
||||||
|
|
||||||
if (process.env.AWS_ACCESS_KEY_ID) {
|
if (process.env.AWS_ACCESS_KEY_ID) {
|
||||||
[
|
[
|
||||||
'AWS_REGION',
|
"AWS_REGION",
|
||||||
'AWS_SECRET_ACCESS_KEY',
|
"AWS_SECRET_ACCESS_KEY",
|
||||||
'AWS_S3_UPLOAD_BUCKET_URL',
|
"AWS_S3_UPLOAD_BUCKET_URL",
|
||||||
'AWS_S3_UPLOAD_BUCKET_NAME',
|
"AWS_S3_UPLOAD_BUCKET_NAME",
|
||||||
'AWS_S3_UPLOAD_MAX_SIZE',
|
"AWS_S3_UPLOAD_MAX_SIZE",
|
||||||
].forEach(key => {
|
].forEach(key => {
|
||||||
if (!process.env[key]) {
|
if (!process.env[key]) {
|
||||||
console.error(`The ${key} env variable must be set when using AWS`);
|
console.error(`The ${key} env variable must be set when using AWS`);
|
||||||
|
@ -40,7 +40,7 @@ if (process.env.SLACK_KEY) {
|
||||||
|
|
||||||
if (!process.env.URL) {
|
if (!process.env.URL) {
|
||||||
console.error(
|
console.error(
|
||||||
'The URL env variable must be set to the externally accessible URL, e.g (https://www.getoutline.com)'
|
"The URL env variable must be set to the externally accessible URL, e.g (https://www.getoutline.com)"
|
||||||
);
|
);
|
||||||
// $FlowFixMe
|
// $FlowFixMe
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
|
@ -48,7 +48,7 @@ if (!process.env.URL) {
|
||||||
|
|
||||||
if (!process.env.DATABASE_URL) {
|
if (!process.env.DATABASE_URL) {
|
||||||
console.error(
|
console.error(
|
||||||
'The DATABASE_URL env variable must be set to the location of your postgres server, including authentication and port'
|
"The DATABASE_URL env variable must be set to the location of your postgres server, including authentication and port"
|
||||||
);
|
);
|
||||||
// $FlowFixMe
|
// $FlowFixMe
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
|
@ -56,7 +56,7 @@ if (!process.env.DATABASE_URL) {
|
||||||
|
|
||||||
if (!process.env.REDIS_URL) {
|
if (!process.env.REDIS_URL) {
|
||||||
console.error(
|
console.error(
|
||||||
'The REDIS_URL env variable must be set to the location of your redis server, including authentication and port'
|
"The REDIS_URL env variable must be set to the location of your redis server, including authentication and port"
|
||||||
);
|
);
|
||||||
// $FlowFixMe
|
// $FlowFixMe
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
|
@ -64,17 +64,17 @@ if (!process.env.REDIS_URL) {
|
||||||
|
|
||||||
if (!process.env.WEBSOCKETS_ENABLED) {
|
if (!process.env.WEBSOCKETS_ENABLED) {
|
||||||
console.log(
|
console.log(
|
||||||
'WARNING: Websockets are disabled. Set WEBSOCKETS_ENABLED env variable to true to enable'
|
"WARNING: Websockets are disabled. Set WEBSOCKETS_ENABLED env variable to true to enable"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (process.env.NODE_ENV === 'production') {
|
if (process.env.NODE_ENV === "production") {
|
||||||
console.log('\n\x1b[33m%s\x1b[0m', 'Running Outline in production mode.');
|
console.log("\n\x1b[33m%s\x1b[0m", "Running Outline in production mode.");
|
||||||
} else if (process.env.NODE_ENV === 'development') {
|
} else if (process.env.NODE_ENV === "development") {
|
||||||
console.log(
|
console.log(
|
||||||
'\n\x1b[33m%s\x1b[0m',
|
"\n\x1b[33m%s\x1b[0m",
|
||||||
'Running Outline in development mode with hot reloading. To run Outline in production mode set the NODE_ENV env variable to "production"'
|
'Running Outline in development mode with hot reloading. To run Outline in production mode set the NODE_ENV env variable to "production"'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
require('./server');
|
require("./server");
|
||||||
|
|
6
init.js
6
init.js
|
@ -1,4 +1,4 @@
|
||||||
// @flow
|
// @flow
|
||||||
require('babel-core/register');
|
require("babel-core/register");
|
||||||
require('babel-polyfill');
|
require("babel-polyfill");
|
||||||
require('dotenv').config({ silent: true });
|
require("dotenv").config({ silent: true });
|
||||||
|
|
|
@ -155,7 +155,6 @@
|
||||||
"string-replace-to-array": "^1.0.3",
|
"string-replace-to-array": "^1.0.3",
|
||||||
"styled-components": "^5.0.0",
|
"styled-components": "^5.0.0",
|
||||||
"styled-components-breakpoint": "^2.1.1",
|
"styled-components-breakpoint": "^2.1.1",
|
||||||
"styled-components-grid": "^2.2.1",
|
|
||||||
"styled-normalize": "^8.0.4",
|
"styled-normalize": "^8.0.4",
|
||||||
"tiny-cookie": "^2.3.1",
|
"tiny-cookie": "^2.3.1",
|
||||||
"tmp": "0.0.33",
|
"tmp": "0.0.33",
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue