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/emails` - React rendered email templates
|
||||
- `server/models` - Database models
|
||||
- `server/pages` - Server-side rendered public pages
|
||||
- `server/policies` - Authorization logic
|
||||
- `server/presenters` - API responses for database models
|
||||
- `server/test` - Test helps and support
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// @flow
|
||||
import styled from "styled-components";
|
||||
import breakpoint from "styled-components-breakpoint";
|
||||
import Flex from "shared/components/Flex";
|
||||
import Flex from "components/Flex";
|
||||
|
||||
export const Action = styled(Flex)`
|
||||
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
|
||||
import * as React from "react";
|
||||
import { observer, inject } from "mobx-react";
|
||||
import { Redirect } from "react-router-dom";
|
||||
import AuthStore from "stores/AuthStore";
|
||||
import LoadingIndicator from "components/LoadingIndicator";
|
||||
import { isCustomSubdomain } from "shared/utils/domains";
|
||||
|
@ -35,7 +36,7 @@ const Authenticated = observer(({ auth, children }: Props) => {
|
|||
}
|
||||
|
||||
auth.logout(true);
|
||||
return null;
|
||||
return <Redirect to="/" />;
|
||||
});
|
||||
|
||||
export default inject("auth")(Authenticated);
|
||||
|
|
|
@ -9,7 +9,7 @@ import { PadlockIcon, GoToIcon, MoreIcon } from "outline-icons";
|
|||
import Document from "models/Document";
|
||||
import CollectionsStore from "stores/CollectionsStore";
|
||||
import { collectionUrl } from "utils/routeHelpers";
|
||||
import Flex from "shared/components/Flex";
|
||||
import Flex from "components/Flex";
|
||||
import BreadcrumbMenu from "./BreadcrumbMenu";
|
||||
import CollectionIcon from "components/CollectionIcon";
|
||||
|
|
@ -5,7 +5,8 @@ import { darken, lighten } from "polished";
|
|||
import { ExpandedIcon } from "outline-icons";
|
||||
|
||||
const RealButton = styled.button`
|
||||
display: inline-block;
|
||||
display: ${props => (props.fullwidth ? "block" : "inline-block")};
|
||||
width: ${props => (props.fullwidth ? "100%" : "auto")};
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
|
@ -126,6 +127,7 @@ export type Props = {
|
|||
children?: React.Node,
|
||||
innerRef?: React.ElementRef<any>,
|
||||
disclosure?: boolean,
|
||||
fullwidth?: 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 RevisionsStore from "stores/RevisionsStore";
|
||||
|
||||
import Flex from "shared/components/Flex";
|
||||
import Flex from "components/Flex";
|
||||
import { ListPlaceholder } from "components/LoadingPlaceholder";
|
||||
import Revision from "./components/Revision";
|
||||
import { documentHistoryUrl } from "utils/routeHelpers";
|
||||
|
|
|
@ -5,8 +5,8 @@ import styled, { withTheme } from "styled-components";
|
|||
import format from "date-fns/format";
|
||||
import { MoreIcon } from "outline-icons";
|
||||
|
||||
import Flex from "shared/components/Flex";
|
||||
import Time from "shared/components/Time";
|
||||
import Flex from "components/Flex";
|
||||
import Time from "components/Time";
|
||||
import Avatar from "components/Avatar";
|
||||
import RevisionMenu from "menus/RevisionMenu";
|
||||
import Document from "models/Document";
|
||||
|
|
|
@ -4,7 +4,7 @@ import { observer } from "mobx-react";
|
|||
import { Link } from "react-router-dom";
|
||||
import { StarredIcon } from "outline-icons";
|
||||
import styled, { withTheme } from "styled-components";
|
||||
import Flex from "shared/components/Flex";
|
||||
import Flex from "components/Flex";
|
||||
import Badge from "components/Badge";
|
||||
import Tooltip from "components/Tooltip";
|
||||
import Highlight from "components/Highlight";
|
||||
|
|
|
@ -7,7 +7,7 @@ import { PortalWithState } from "react-portal";
|
|||
import { MoreIcon } from "outline-icons";
|
||||
import { rgba } from "polished";
|
||||
import styled from "styled-components";
|
||||
import Flex from "shared/components/Flex";
|
||||
import Flex from "components/Flex";
|
||||
import { fadeAndScaleIn } from "shared/styles/animations";
|
||||
import NudeButton from "components/NudeButton";
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
import * as React from "react";
|
||||
import { observer, inject } from "mobx-react";
|
||||
import styled, { withTheme } from "styled-components";
|
||||
import Flex from "shared/components/Flex";
|
||||
import Flex from "components/Flex";
|
||||
import Avatar from "components/Avatar";
|
||||
import User from "models/User";
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ import { observable } from "mobx";
|
|||
import { observer, inject } from "mobx-react";
|
||||
import { MAX_AVATAR_DISPLAY } from "shared/constants";
|
||||
import Modal from "components/Modal";
|
||||
import Flex from "shared/components/Flex";
|
||||
import Flex from "components/Flex";
|
||||
import Facepile from "components/Facepile";
|
||||
import GroupMembers from "scenes/GroupMembers";
|
||||
import ListItem from "components/List/Item";
|
||||
|
|
|
@ -27,7 +27,7 @@ import styled from "styled-components";
|
|||
import { LabelText } from "components/Input";
|
||||
import { DropdownMenu } from "components/DropdownMenu";
|
||||
import NudeButton from "components/NudeButton";
|
||||
import Flex from "shared/components/Flex";
|
||||
import Flex from "components/Flex";
|
||||
|
||||
export const icons = {
|
||||
collection: {
|
||||
|
|
|
@ -4,7 +4,7 @@ import { observer } from "mobx-react";
|
|||
import { observable } from "mobx";
|
||||
import styled from "styled-components";
|
||||
import VisuallyHidden from "components/VisuallyHidden";
|
||||
import Flex from "shared/components/Flex";
|
||||
import Flex from "components/Flex";
|
||||
|
||||
const RealTextarea = styled.textarea`
|
||||
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
|
||||
import * as React from "react";
|
||||
import { observer } from "mobx-react";
|
||||
import Flex from "shared/components/Flex";
|
||||
import Flex from "components/Flex";
|
||||
import styled from "styled-components";
|
||||
|
||||
type Props = {
|
||||
|
|
|
@ -8,7 +8,7 @@ import { observable } from "mobx";
|
|||
import { observer, inject } from "mobx-react";
|
||||
import keydown from "react-keydown";
|
||||
import Analytics from "components/Analytics";
|
||||
import Flex from "shared/components/Flex";
|
||||
import Flex from "components/Flex";
|
||||
import {
|
||||
homeUrl,
|
||||
searchUrl,
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// @flow
|
||||
import * as React from "react";
|
||||
import styled from "styled-components";
|
||||
import Flex from "shared/components/Flex";
|
||||
import Flex from "components/Flex";
|
||||
|
||||
type Props = {
|
||||
image?: React.Node,
|
||||
|
|
|
@ -4,7 +4,7 @@ import { times } from "lodash";
|
|||
import styled from "styled-components";
|
||||
import Mask from "components/Mask";
|
||||
import Fade from "components/Fade";
|
||||
import Flex from "shared/components/Flex";
|
||||
import Flex from "components/Flex";
|
||||
|
||||
type Props = {
|
||||
count?: number,
|
||||
|
|
|
@ -4,7 +4,7 @@ import { times } from "lodash";
|
|||
import styled from "styled-components";
|
||||
import Mask from "components/Mask";
|
||||
import Fade from "components/Fade";
|
||||
import Flex from "shared/components/Flex";
|
||||
import Flex from "components/Flex";
|
||||
|
||||
type Props = {
|
||||
count?: number,
|
||||
|
|
|
@ -3,7 +3,7 @@ import * as React from "react";
|
|||
import styled from "styled-components";
|
||||
import Mask from "components/Mask";
|
||||
import Fade from "components/Fade";
|
||||
import Flex from "shared/components/Flex";
|
||||
import Flex from "components/Flex";
|
||||
|
||||
export default function LoadingPlaceholder(props: Object) {
|
||||
return (
|
||||
|
|
|
@ -3,7 +3,7 @@ import * as React from "react";
|
|||
import styled from "styled-components";
|
||||
import { pulsate } from "shared/styles/animations";
|
||||
import { randomInteger } from "shared/random";
|
||||
import Flex from "shared/components/Flex";
|
||||
import Flex from "components/Flex";
|
||||
|
||||
type Props = {
|
||||
header?: boolean,
|
||||
|
|
|
@ -8,7 +8,7 @@ import { transparentize } from "polished";
|
|||
import { CloseIcon, BackIcon } from "outline-icons";
|
||||
import NudeButton from "components/NudeButton";
|
||||
import { fadeAndScaleIn } from "shared/styles/animations";
|
||||
import Flex from "shared/components/Flex";
|
||||
import Flex from "components/Flex";
|
||||
|
||||
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 styled from "styled-components";
|
||||
import { GoToIcon } from "outline-icons";
|
||||
import Flex from "shared/components/Flex";
|
||||
import Flex from "components/Flex";
|
||||
|
||||
import Document from "models/Document";
|
||||
import Collection from "models/Collection";
|
||||
|
|
|
@ -3,9 +3,9 @@ import * as React from "react";
|
|||
import { inject, observer } from "mobx-react";
|
||||
import styled from "styled-components";
|
||||
import Document from "models/Document";
|
||||
import Flex from "shared/components/Flex";
|
||||
import Time from "shared/components/Time";
|
||||
import Breadcrumb from "shared/components/Breadcrumb";
|
||||
import Flex from "components/Flex";
|
||||
import Time from "components/Time";
|
||||
import Breadcrumb from "components/Breadcrumb";
|
||||
import CollectionsStore from "stores/CollectionsStore";
|
||||
import AuthStore from "stores/AuthStore";
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ import {
|
|||
PlusIcon,
|
||||
} from "outline-icons";
|
||||
|
||||
import Flex from "shared/components/Flex";
|
||||
import Flex from "components/Flex";
|
||||
import Modal from "components/Modal";
|
||||
import Invite from "scenes/Invite";
|
||||
import AccountMenu from "menus/AccountMenu";
|
||||
|
|
|
@ -19,7 +19,7 @@ import {
|
|||
import ZapierIcon from "./icons/Zapier";
|
||||
import SlackIcon from "./icons/Slack";
|
||||
|
||||
import Flex from "shared/components/Flex";
|
||||
import Flex from "components/Flex";
|
||||
import Sidebar from "./Sidebar";
|
||||
import Scrollable from "components/Scrollable";
|
||||
import Section from "./components/Section";
|
||||
|
@ -54,7 +54,7 @@ class SettingsSidebar extends React.Component<Props> {
|
|||
<HeaderBlock
|
||||
subheading={
|
||||
<ReturnToApp align="center">
|
||||
<BackIcon /> Return to App
|
||||
<BackIcon color="currentColor" /> Return to App
|
||||
</ReturnToApp>
|
||||
}
|
||||
teamName={team.name}
|
||||
|
|
|
@ -7,7 +7,7 @@ import breakpoint from "styled-components-breakpoint";
|
|||
import { observer, inject } from "mobx-react";
|
||||
import { CloseIcon, MenuIcon } from "outline-icons";
|
||||
import Fade from "components/Fade";
|
||||
import Flex from "shared/components/Flex";
|
||||
import Flex from "components/Flex";
|
||||
import UiStore from "stores/UiStore";
|
||||
|
||||
let firstRender = true;
|
||||
|
|
|
@ -11,7 +11,7 @@ import SidebarLink from "./SidebarLink";
|
|||
import DocumentLink from "./DocumentLink";
|
||||
import CollectionIcon from "components/CollectionIcon";
|
||||
import DropToImport from "components/DropToImport";
|
||||
import Flex from "shared/components/Flex";
|
||||
import Flex from "components/Flex";
|
||||
|
||||
type Props = {
|
||||
collection: Collection,
|
||||
|
|
|
@ -3,7 +3,7 @@ import * as React from "react";
|
|||
import { observer, inject } from "mobx-react";
|
||||
import { withRouter, type RouterHistory } from "react-router-dom";
|
||||
import keydown from "react-keydown";
|
||||
import Flex from "shared/components/Flex";
|
||||
import Flex from "components/Flex";
|
||||
import { PlusIcon } from "outline-icons";
|
||||
import { newDocumentUrl } from "utils/routeHelpers";
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ import DropToImport from "components/DropToImport";
|
|||
import Fade from "components/Fade";
|
||||
import Collection from "models/Collection";
|
||||
import DocumentsStore from "stores/DocumentsStore";
|
||||
import Flex from "shared/components/Flex";
|
||||
import Flex from "components/Flex";
|
||||
import { type NavigationNode } from "types";
|
||||
|
||||
type Props = {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// @flow
|
||||
import Flex from "shared/components/Flex";
|
||||
import Flex from "components/Flex";
|
||||
import styled from "styled-components";
|
||||
|
||||
const Header = styled(Flex)`
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
import * as React from "react";
|
||||
import styled, { withTheme } from "styled-components";
|
||||
import { ExpandedIcon } from "outline-icons";
|
||||
import Flex from "shared/components/Flex";
|
||||
import TeamLogo from "shared/components/TeamLogo";
|
||||
import Flex from "components/Flex";
|
||||
import TeamLogo from "components/TeamLogo";
|
||||
|
||||
type Props = {
|
||||
teamName: string,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// @flow
|
||||
import styled from "styled-components";
|
||||
import Flex from "shared/components/Flex";
|
||||
import Flex from "components/Flex";
|
||||
|
||||
const Section = styled(Flex)`
|
||||
position: relative;
|
||||
|
|
|
@ -5,7 +5,7 @@ import { observer } from "mobx-react";
|
|||
import { withRouter, NavLink } from "react-router-dom";
|
||||
import { CollapsedIcon } from "outline-icons";
|
||||
import styled, { withTheme } from "styled-components";
|
||||
import Flex from "shared/components/Flex";
|
||||
import Flex from "components/Flex";
|
||||
|
||||
type Props = {
|
||||
to?: string | Object,
|
||||
|
|
|
@ -2,10 +2,10 @@
|
|||
import styled from "styled-components";
|
||||
|
||||
const TeamLogo = styled.img`
|
||||
width: 38px;
|
||||
width: auto;
|
||||
height: 38px;
|
||||
border-radius: 4px;
|
||||
background: ${props => props.theme.white};
|
||||
background: ${props => props.theme.background};
|
||||
border: 1px solid ${props => props.theme.divider};
|
||||
`;
|
||||
|
|
@ -7,7 +7,7 @@ import { SunIcon, MoonIcon } from "outline-icons";
|
|||
import styled from "styled-components";
|
||||
import UiStore from "stores/UiStore";
|
||||
import AuthStore from "stores/AuthStore";
|
||||
import Flex from "shared/components/Flex";
|
||||
import Flex from "components/Flex";
|
||||
import { DropdownMenu, DropdownMenuItem } from "components/DropdownMenu";
|
||||
import Modal from "components/Modal";
|
||||
import KeyboardShortcuts from "scenes/KeyboardShortcuts";
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// @flow
|
||||
import * as React from "react";
|
||||
import { Switch, Route, Redirect } from "react-router-dom";
|
||||
import Home from "scenes/Home";
|
||||
import Login from "scenes/Login";
|
||||
import Dashboard from "scenes/Dashboard";
|
||||
import Starred from "scenes/Starred";
|
||||
import Drafts from "scenes/Drafts";
|
||||
|
@ -38,7 +38,8 @@ const RedirectDocument = ({ match }: { match: Object }) => (
|
|||
export default function Routes() {
|
||||
return (
|
||||
<Switch>
|
||||
<Route exact path="/" component={Home} />
|
||||
<Route exact path="/" component={Login} />
|
||||
<Route exact path="/create" component={Login} />
|
||||
<Route exact path="/share/:shareId" component={KeyedDocument} />
|
||||
<Authenticated>
|
||||
<SocketProvider>
|
||||
|
|
|
@ -30,7 +30,7 @@ import HelpText from "components/HelpText";
|
|||
import DocumentList from "components/DocumentList";
|
||||
import Subheading from "components/Subheading";
|
||||
import PageTitle from "components/PageTitle";
|
||||
import Flex from "shared/components/Flex";
|
||||
import Flex from "components/Flex";
|
||||
import Modal from "components/Modal";
|
||||
import CollectionMembers from "scenes/CollectionMembers";
|
||||
import Tabs from "components/Tabs";
|
||||
|
|
|
@ -5,7 +5,7 @@ import { observable } from "mobx";
|
|||
import { inject, observer } from "mobx-react";
|
||||
import { homeUrl } from "utils/routeHelpers";
|
||||
import Button from "components/Button";
|
||||
import Flex from "shared/components/Flex";
|
||||
import Flex from "components/Flex";
|
||||
import HelpText from "components/HelpText";
|
||||
import Collection from "models/Collection";
|
||||
import CollectionsStore from "stores/CollectionsStore";
|
||||
|
|
|
@ -6,7 +6,7 @@ import Input from "components/Input";
|
|||
import InputRich from "components/InputRich";
|
||||
import Button from "components/Button";
|
||||
import Switch from "components/Switch";
|
||||
import Flex from "shared/components/Flex";
|
||||
import Flex from "components/Flex";
|
||||
import HelpText from "components/HelpText";
|
||||
import IconPicker from "components/IconPicker";
|
||||
import Collection from "models/Collection";
|
||||
|
|
|
@ -3,7 +3,7 @@ import * as React from "react";
|
|||
import { observable } from "mobx";
|
||||
import { inject, observer } from "mobx-react";
|
||||
import Button from "components/Button";
|
||||
import Flex from "shared/components/Flex";
|
||||
import Flex from "components/Flex";
|
||||
import HelpText from "components/HelpText";
|
||||
import Collection from "models/Collection";
|
||||
import AuthStore from "stores/AuthStore";
|
||||
|
|
|
@ -5,7 +5,7 @@ import { inject, observer } from "mobx-react";
|
|||
import { observable } from "mobx";
|
||||
import { debounce } from "lodash";
|
||||
import Button from "components/Button";
|
||||
import Flex from "shared/components/Flex";
|
||||
import Flex from "components/Flex";
|
||||
import HelpText from "components/HelpText";
|
||||
import Input from "components/Input";
|
||||
import Modal from "components/Modal";
|
||||
|
|
|
@ -3,7 +3,7 @@ import * as React from "react";
|
|||
import { inject, observer } from "mobx-react";
|
||||
import { observable } from "mobx";
|
||||
import { debounce } from "lodash";
|
||||
import Flex from "shared/components/Flex";
|
||||
import Flex from "components/Flex";
|
||||
import HelpText from "components/HelpText";
|
||||
import Input from "components/Input";
|
||||
import Modal from "components/Modal";
|
||||
|
|
|
@ -4,7 +4,7 @@ import { observable } from "mobx";
|
|||
import styled from "styled-components";
|
||||
import { inject, observer } from "mobx-react";
|
||||
import { PlusIcon } from "outline-icons";
|
||||
import Flex from "shared/components/Flex";
|
||||
import Flex from "components/Flex";
|
||||
import HelpText from "components/HelpText";
|
||||
import Subheading from "components/Subheading";
|
||||
import Button from "components/Button";
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
import * as React from "react";
|
||||
import styled from "styled-components";
|
||||
import Avatar from "components/Avatar";
|
||||
import Flex from "shared/components/Flex";
|
||||
import Time from "shared/components/Time";
|
||||
import Flex from "components/Flex";
|
||||
import Time from "components/Time";
|
||||
import Badge from "components/Badge";
|
||||
import Button from "components/Button";
|
||||
import InputSelect from "components/InputSelect";
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// @flow
|
||||
import * as React from "react";
|
||||
import { PlusIcon } from "outline-icons";
|
||||
import Time from "shared/components/Time";
|
||||
import Time from "components/Time";
|
||||
import Avatar from "components/Avatar";
|
||||
import Button from "components/Button";
|
||||
import Badge from "components/Badge";
|
||||
|
|
|
@ -10,7 +10,7 @@ import Input from "components/Input";
|
|||
import InputRich from "components/InputRich";
|
||||
import IconPicker, { icons } from "components/IconPicker";
|
||||
import HelpText from "components/HelpText";
|
||||
import Flex from "shared/components/Flex";
|
||||
import Flex from "components/Flex";
|
||||
|
||||
import Collection from "models/Collection";
|
||||
import CollectionsStore from "stores/CollectionsStore";
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// @flow
|
||||
import styled from "styled-components";
|
||||
import Flex from "shared/components/Flex";
|
||||
import Flex from "components/Flex";
|
||||
|
||||
const Container = styled(Flex)`
|
||||
position: relative;
|
||||
|
|
|
@ -8,7 +8,7 @@ import { observer, inject } from "mobx-react";
|
|||
import { Prompt, Route, withRouter } from "react-router-dom";
|
||||
import type { Location, RouterHistory } from "react-router-dom";
|
||||
import keydown from "react-keydown";
|
||||
import Flex from "shared/components/Flex";
|
||||
import Flex from "components/Flex";
|
||||
import {
|
||||
collectionUrl,
|
||||
documentMoveUrl,
|
||||
|
@ -29,9 +29,9 @@ import MarkAsViewed from "./MarkAsViewed";
|
|||
import ErrorBoundary from "components/ErrorBoundary";
|
||||
import LoadingIndicator from "components/LoadingIndicator";
|
||||
import PageTitle from "components/PageTitle";
|
||||
import Branding from "shared/components/Branding";
|
||||
import Notice from "shared/components/Notice";
|
||||
import Time from "shared/components/Time";
|
||||
import Branding from "components/Branding";
|
||||
import Notice from "components/Notice";
|
||||
import Time from "components/Time";
|
||||
|
||||
import UiStore from "stores/UiStore";
|
||||
import AuthStore from "stores/AuthStore";
|
||||
|
|
|
@ -12,7 +12,7 @@ import Modal from "components/Modal";
|
|||
import Input from "components/Input";
|
||||
import Labeled from "components/Labeled";
|
||||
import PathToDocument from "components/PathToDocument";
|
||||
import Flex from "shared/components/Flex";
|
||||
import Flex from "components/Flex";
|
||||
|
||||
import Document from "models/Document";
|
||||
import DocumentsStore from "stores/DocumentsStore";
|
||||
|
|
|
@ -5,7 +5,7 @@ import Textarea from "react-autosize-textarea";
|
|||
import { observer } from "mobx-react";
|
||||
import Editor from "components/Editor";
|
||||
import ClickablePadding from "components/ClickablePadding";
|
||||
import Flex from "shared/components/Flex";
|
||||
import Flex from "components/Flex";
|
||||
import parseTitle from "shared/utils/parseTitle";
|
||||
import Document from "models/Document";
|
||||
import DocumentMeta from "./DocumentMeta";
|
||||
|
|
|
@ -13,8 +13,8 @@ import AuthStore from "stores/AuthStore";
|
|||
import { documentEditUrl } from "utils/routeHelpers";
|
||||
import { meta } from "utils/keyboard";
|
||||
|
||||
import Flex from "shared/components/Flex";
|
||||
import Breadcrumb, { Slash } from "shared/components/Breadcrumb";
|
||||
import Flex from "components/Flex";
|
||||
import Breadcrumb, { Slash } from "components/Breadcrumb";
|
||||
import DocumentMenu from "menus/DocumentMenu";
|
||||
import NewChildDocumentMenu from "menus/NewChildDocumentMenu";
|
||||
import DocumentShare from "scenes/DocumentShare";
|
||||
|
|
|
@ -4,7 +4,7 @@ import { withRouter, type RouterHistory } from "react-router-dom";
|
|||
import { observable } from "mobx";
|
||||
import { inject, observer } from "mobx-react";
|
||||
import Button from "components/Button";
|
||||
import Flex from "shared/components/Flex";
|
||||
import Flex from "components/Flex";
|
||||
import HelpText from "components/HelpText";
|
||||
import Document from "models/Document";
|
||||
import DocumentsStore from "stores/DocumentsStore";
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
import * as React from "react";
|
||||
import { inject } from "mobx-react";
|
||||
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 LoadingPlaceholder from "components/LoadingPlaceholder";
|
||||
import DocumentsStore from "stores/DocumentsStore";
|
||||
|
|
|
@ -5,7 +5,7 @@ import { observable } from "mobx";
|
|||
import { inject, observer } from "mobx-react";
|
||||
import { groupSettings } from "shared/utils/routeHelpers";
|
||||
import Button from "components/Button";
|
||||
import Flex from "shared/components/Flex";
|
||||
import Flex from "components/Flex";
|
||||
import HelpText from "components/HelpText";
|
||||
import Group from "models/Group";
|
||||
import UiStore from "stores/UiStore";
|
||||
|
|
|
@ -6,7 +6,7 @@ import { inject, observer } from "mobx-react";
|
|||
import Button from "components/Button";
|
||||
import Input from "components/Input";
|
||||
import HelpText from "components/HelpText";
|
||||
import Flex from "shared/components/Flex";
|
||||
import Flex from "components/Flex";
|
||||
|
||||
import Group from "models/Group";
|
||||
import UiStore from "stores/UiStore";
|
||||
|
|
|
@ -3,7 +3,7 @@ import * as React from "react";
|
|||
import { inject, observer } from "mobx-react";
|
||||
import { observable } from "mobx";
|
||||
import { debounce } from "lodash";
|
||||
import Flex from "shared/components/Flex";
|
||||
import Flex from "components/Flex";
|
||||
import HelpText from "components/HelpText";
|
||||
import Input from "components/Input";
|
||||
import Modal from "components/Modal";
|
||||
|
|
|
@ -3,7 +3,7 @@ import * as React from "react";
|
|||
import { observable } from "mobx";
|
||||
import { inject, observer } from "mobx-react";
|
||||
import { PlusIcon } from "outline-icons";
|
||||
import Flex from "shared/components/Flex";
|
||||
import Flex from "components/Flex";
|
||||
import Empty from "components/Empty";
|
||||
import HelpText from "components/HelpText";
|
||||
import Subheading from "components/Subheading";
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
// @flow
|
||||
import * as React from "react";
|
||||
import Avatar from "components/Avatar";
|
||||
import Flex from "shared/components/Flex";
|
||||
import Time from "shared/components/Time";
|
||||
import Flex from "components/Flex";
|
||||
import Time from "components/Time";
|
||||
import Badge from "components/Badge";
|
||||
import Button from "components/Button";
|
||||
import ListItem from "components/List/Item";
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// @flow
|
||||
import * as React from "react";
|
||||
import { PlusIcon } from "outline-icons";
|
||||
import Time from "shared/components/Time";
|
||||
import Time from "components/Time";
|
||||
import Avatar from "components/Avatar";
|
||||
import Button from "components/Button";
|
||||
import Badge from "components/Badge";
|
||||
|
|
|
@ -8,7 +8,7 @@ import Input from "components/Input";
|
|||
import HelpText from "components/HelpText";
|
||||
import Modal from "components/Modal";
|
||||
import GroupMembers from "scenes/GroupMembers";
|
||||
import Flex from "shared/components/Flex";
|
||||
import Flex from "components/Flex";
|
||||
|
||||
import Group from "models/Group";
|
||||
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 { observable, action } from "mobx";
|
||||
import { inject, observer } from "mobx-react";
|
||||
import { CloseIcon } from "outline-icons";
|
||||
import { LinkIcon, CloseIcon } from "outline-icons";
|
||||
import styled from "styled-components";
|
||||
import Flex from "shared/components/Flex";
|
||||
import Flex from "components/Flex";
|
||||
import Button from "components/Button";
|
||||
import Input from "components/Input";
|
||||
import CopyToClipboard from "components/CopyToClipboard";
|
||||
import Checkbox from "components/Checkbox";
|
||||
import HelpText from "components/HelpText";
|
||||
import Tooltip from "components/Tooltip";
|
||||
import NudeButton from "components/NudeButton";
|
||||
|
@ -33,7 +32,6 @@ type Props = {
|
|||
type InviteRequest = {
|
||||
email: string,
|
||||
name: string,
|
||||
guest: boolean,
|
||||
};
|
||||
|
||||
@observer
|
||||
|
@ -42,9 +40,9 @@ class Invite extends React.Component<Props> {
|
|||
@observable linkCopied: boolean = false;
|
||||
@observable
|
||||
invites: InviteRequest[] = [
|
||||
{ email: "", name: "", guest: false },
|
||||
{ email: "", name: "", guest: false },
|
||||
{ email: "", name: "", guest: false },
|
||||
{ email: "", name: "" },
|
||||
{ email: "", name: "" },
|
||||
{ email: "", name: "" },
|
||||
];
|
||||
|
||||
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
|
||||
|
@ -106,8 +104,8 @@ class Invite extends React.Component<Props> {
|
|||
{team.guestSignin ? (
|
||||
<HelpText>
|
||||
Invite team members or guests to join your knowledge base. Team
|
||||
members can sign in with {team.signinMethods} and guests can use
|
||||
their email address.
|
||||
members can sign in with {team.signinMethods} or use their email
|
||||
address.
|
||||
</HelpText>
|
||||
) : (
|
||||
<HelpText>
|
||||
|
@ -116,22 +114,35 @@ class Invite extends React.Component<Props> {
|
|||
{can.update && (
|
||||
<React.Fragment>
|
||||
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>
|
||||
)}
|
||||
</HelpText>
|
||||
)}
|
||||
{team.subdomain && (
|
||||
<CopyBlock>
|
||||
Want a link to share directly with your team?
|
||||
<Flex>
|
||||
<Input type="text" value={team.url} readOnly flex />
|
||||
<Flex align="flex-end">
|
||||
<Input
|
||||
type="text"
|
||||
value={team.url}
|
||||
label="Want a link to share directly with your team?"
|
||||
readOnly
|
||||
flex
|
||||
/>
|
||||
<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"}
|
||||
</Button>
|
||||
</CopyToClipboard>
|
||||
</Flex>
|
||||
<p>
|
||||
<hr />
|
||||
</p>
|
||||
</CopyBlock>
|
||||
)}
|
||||
{this.invites.map((invite, index) => (
|
||||
|
@ -159,29 +170,6 @@ class Invite extends React.Component<Props> {
|
|||
required={!!invite.email}
|
||||
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 && (
|
||||
<Remove>
|
||||
<Tooltip tooltip="Remove invite" placement="top">
|
||||
|
@ -220,22 +208,8 @@ class Invite extends React.Component<Props> {
|
|||
}
|
||||
|
||||
const CopyBlock = styled("div")`
|
||||
margin: 2em 0;
|
||||
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")`
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
import * as React from "react";
|
||||
import styled from "styled-components";
|
||||
import Key from "components/Key";
|
||||
import Flex from "shared/components/Flex";
|
||||
import Flex from "components/Flex";
|
||||
import HelpText from "components/HelpText";
|
||||
import { meta } from "utils/keyboard";
|
||||
|
||||
|
|
|
@ -1,61 +1,55 @@
|
|||
// @flow
|
||||
import * as React from "react";
|
||||
import Notice from "../../../shared/components/Notice";
|
||||
import NoticeAlert from "components/NoticeAlert";
|
||||
|
||||
type Props = {
|
||||
notice?: string,
|
||||
};
|
||||
|
||||
export default function AuthNotices({ notice }: Props) {
|
||||
export default function Notices({ notice }: Props) {
|
||||
return (
|
||||
<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>
|
||||
<NoticeAlert>
|
||||
Sorry, Google sign in cannot be used with a personal email. Please try
|
||||
signing in with your company Google account.
|
||||
</Notice>
|
||||
signing in with your company GSuite account.
|
||||
</NoticeAlert>
|
||||
)}
|
||||
{notice === "hd-not-allowed" && (
|
||||
<Notice>
|
||||
<NoticeAlert>
|
||||
Sorry, your Google apps domain is not allowed. Please try again with
|
||||
an allowed company domain.
|
||||
</Notice>
|
||||
</NoticeAlert>
|
||||
)}
|
||||
{notice === "email-auth-required" && (
|
||||
<Notice>
|
||||
<NoticeAlert>
|
||||
Your account uses email sign-in, please sign-in with email to
|
||||
continue.
|
||||
</Notice>
|
||||
</NoticeAlert>
|
||||
)}
|
||||
{notice === "email-auth-ratelimit" && (
|
||||
<Notice>
|
||||
An email sign-in link was recently sent, please check your inbox and
|
||||
<NoticeAlert>
|
||||
An email sign-in link was recently sent, please check your inbox or
|
||||
try again in a few minutes.
|
||||
</Notice>
|
||||
</NoticeAlert>
|
||||
)}
|
||||
{notice === "auth-error" && (
|
||||
<Notice>
|
||||
<NoticeAlert>
|
||||
Authentication failed - we were unable to sign you in at this time.
|
||||
Please try again.
|
||||
</Notice>
|
||||
</NoticeAlert>
|
||||
)}
|
||||
{notice === "expired-token" && (
|
||||
<Notice>
|
||||
<NoticeAlert>
|
||||
Sorry, it looks like that sign-in link is no longer valid, please try
|
||||
requesting another.
|
||||
</Notice>
|
||||
</NoticeAlert>
|
||||
)}
|
||||
{notice === "suspended" && (
|
||||
<Notice>
|
||||
<NoticeAlert>
|
||||
Your Outline account has been suspended. To re-activate your account,
|
||||
please contact a team admin.
|
||||
</Notice>
|
||||
</NoticeAlert>
|
||||
)}
|
||||
</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 { meta } from "utils/keyboard";
|
||||
|
||||
import Flex from "shared/components/Flex";
|
||||
import Flex from "components/Flex";
|
||||
import Button from "components/Button";
|
||||
import Empty from "components/Empty";
|
||||
import Fade from "components/Fade";
|
||||
|
|
|
@ -3,7 +3,7 @@ import * as React from "react";
|
|||
import { CheckmarkIcon } from "outline-icons";
|
||||
import styled from "styled-components";
|
||||
import HelpText from "components/HelpText";
|
||||
import Flex from "shared/components/Flex";
|
||||
import Flex from "components/Flex";
|
||||
|
||||
type Props = {
|
||||
label: string,
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
import * as React from "react";
|
||||
import styled, { withTheme } from "styled-components";
|
||||
import { SearchIcon } from "outline-icons";
|
||||
import Flex from "shared/components/Flex";
|
||||
import Flex from "components/Flex";
|
||||
|
||||
type Props = {
|
||||
onChange: string => void,
|
||||
|
|
|
@ -12,7 +12,7 @@ import Button from "components/Button";
|
|||
import CenteredContent from "components/CenteredContent";
|
||||
import PageTitle from "components/PageTitle";
|
||||
import HelpText from "components/HelpText";
|
||||
import Flex from "shared/components/Flex";
|
||||
import Flex from "components/Flex";
|
||||
|
||||
type Props = {
|
||||
auth: AuthStore,
|
||||
|
|
|
@ -9,7 +9,7 @@ import HelpText from "components/HelpText";
|
|||
import Input from "components/Input";
|
||||
import Subheading from "components/Subheading";
|
||||
import NotificationListItem from "./components/NotificationListItem";
|
||||
import Notice from "shared/components/Notice";
|
||||
import Notice from "components/Notice";
|
||||
|
||||
import UiStore from "stores/UiStore";
|
||||
import AuthStore from "stores/AuthStore";
|
||||
|
|
|
@ -12,7 +12,7 @@ import Button from "components/Button";
|
|||
import CenteredContent from "components/CenteredContent";
|
||||
import PageTitle from "components/PageTitle";
|
||||
import UserDelete from "scenes/UserDelete";
|
||||
import Flex from "shared/components/Flex";
|
||||
import Flex from "components/Flex";
|
||||
|
||||
type Props = {
|
||||
auth: AuthStore,
|
||||
|
|
|
@ -60,8 +60,6 @@ class Security extends React.Component<Props> {
|
|||
}, 500);
|
||||
|
||||
render() {
|
||||
const { team } = this.props.auth;
|
||||
|
||||
return (
|
||||
<CenteredContent>
|
||||
<PageTitle title="Security" />
|
||||
|
@ -72,27 +70,25 @@ class Security extends React.Component<Props> {
|
|||
</HelpText>
|
||||
|
||||
<Checkbox
|
||||
label="Allow guest invites"
|
||||
label="Allow email authentication"
|
||||
name="guestSignin"
|
||||
checked={this.guestSignin}
|
||||
onChange={this.handleChange}
|
||||
note={`When enabled guests can be invited by email address and are able to signin without ${
|
||||
team ? team.signinMethods : "SSO"
|
||||
}`}
|
||||
note="When enabled, users can sign-in using their email address"
|
||||
/>
|
||||
<Checkbox
|
||||
label="Public document sharing"
|
||||
name="sharing"
|
||||
checked={this.sharing}
|
||||
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
|
||||
label="Rich service embeds"
|
||||
name="documentEmbeds"
|
||||
checked={this.documentEmbeds}
|
||||
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>
|
||||
);
|
||||
|
|
|
@ -12,7 +12,7 @@ import SlackButton from "./components/SlackButton";
|
|||
import CollectionsStore from "stores/CollectionsStore";
|
||||
import IntegrationsStore from "stores/IntegrationsStore";
|
||||
import AuthStore from "stores/AuthStore";
|
||||
import Notice from "shared/components/Notice";
|
||||
import Notice from "components/Notice";
|
||||
import getQueryVariable from "shared/utils/getQueryVariable";
|
||||
|
||||
type Props = {
|
||||
|
|
|
@ -3,7 +3,7 @@ import * as React from "react";
|
|||
import { Link } from "react-router-dom";
|
||||
import { capitalize } from "lodash";
|
||||
import styled from "styled-components";
|
||||
import Time from "shared/components/Time";
|
||||
import Time from "components/Time";
|
||||
import ListItem from "components/List/Item";
|
||||
import Avatar from "components/Avatar";
|
||||
import Event from "models/Event";
|
||||
|
|
|
@ -5,7 +5,7 @@ import { observer, inject } from "mobx-react";
|
|||
import styled from "styled-components";
|
||||
import Dropzone from "react-dropzone";
|
||||
import LoadingIndicator from "components/LoadingIndicator";
|
||||
import Flex from "shared/components/Flex";
|
||||
import Flex from "components/Flex";
|
||||
import Modal from "components/Modal";
|
||||
import Button from "components/Button";
|
||||
import AvatarEditor from "react-avatar-editor";
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
import * as React from "react";
|
||||
import ShareMenu from "menus/ShareMenu";
|
||||
import ListItem from "components/List/Item";
|
||||
import Time from "shared/components/Time";
|
||||
import Time from "components/Time";
|
||||
import Share from "models/Share";
|
||||
|
||||
type Props = {
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
import * as React from "react";
|
||||
import styled from "styled-components";
|
||||
import { slackAuth } from "shared/utils/routeHelpers";
|
||||
import SlackLogo from "shared/components/SlackLogo";
|
||||
import SlackLogo from "components/SlackLogo";
|
||||
import Button from "components/Button";
|
||||
|
||||
type Props = {
|
||||
|
|
|
@ -8,7 +8,7 @@ import Avatar from "components/Avatar";
|
|||
import Badge from "components/Badge";
|
||||
import UserProfile from "scenes/UserProfile";
|
||||
import ListItem from "components/List/Item";
|
||||
import Time from "shared/components/Time";
|
||||
import Time from "components/Time";
|
||||
import User from "models/User";
|
||||
|
||||
type Props = {
|
||||
|
|
|
@ -3,7 +3,7 @@ import * as React from "react";
|
|||
import { observable } from "mobx";
|
||||
import { inject, observer } from "mobx-react";
|
||||
import Button from "components/Button";
|
||||
import Flex from "shared/components/Flex";
|
||||
import Flex from "components/Flex";
|
||||
import HelpText from "components/HelpText";
|
||||
import Modal from "components/Modal";
|
||||
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 { withRouter, type RouterHistory } from "react-router-dom";
|
||||
import { EditIcon } from "outline-icons";
|
||||
import Flex from "shared/components/Flex";
|
||||
import Flex from "components/Flex";
|
||||
import HelpText from "components/HelpText";
|
||||
import Modal from "components/Modal";
|
||||
import Button from "components/Button";
|
||||
|
|
|
@ -10,13 +10,27 @@ import Team from "models/Team";
|
|||
|
||||
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 {
|
||||
@observable user: ?User;
|
||||
@observable team: ?Team;
|
||||
@observable token: ?string;
|
||||
@observable lastSignedIn: ?string;
|
||||
@observable isSaving: boolean = false;
|
||||
@observable isSuspended: boolean = false;
|
||||
@observable suspendedContactEmail: ?string;
|
||||
@observable config: ?Config;
|
||||
rootStore: RootStore;
|
||||
|
||||
constructor(rootStore: RootStore) {
|
||||
|
@ -32,8 +46,12 @@ export default class AuthStore {
|
|||
this.user = new User(data.user);
|
||||
this.team = new Team(data.team);
|
||||
this.token = getCookie("accessToken");
|
||||
this.lastSignedIn = getCookie("lastSignedIn");
|
||||
setImmediate(() => this.fetchConfig());
|
||||
|
||||
if (this.token) setImmediate(() => this.fetch());
|
||||
if (this.token) {
|
||||
setImmediate(() => this.fetch());
|
||||
}
|
||||
|
||||
autorun(() => {
|
||||
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
|
||||
fetch = async () => {
|
||||
try {
|
||||
|
@ -158,10 +183,16 @@ export default class AuthStore {
|
|||
})
|
||||
);
|
||||
|
||||
this.token = null;
|
||||
|
||||
// if this logout was forced from an authenticated route then
|
||||
// save the current path so we can go back there once signed in
|
||||
if (savePath) {
|
||||
setCookie("postLoginRedirectPath", window.location.pathname);
|
||||
const pathName = window.location.pathname;
|
||||
|
||||
if (pathName !== "/" && pathName !== "/create") {
|
||||
setCookie("postLoginRedirectPath", pathName);
|
||||
}
|
||||
}
|
||||
|
||||
// remove authentication token itself
|
||||
|
@ -178,8 +209,5 @@ export default class AuthStore {
|
|||
});
|
||||
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 modifiedPath;
|
||||
let urlToFetch;
|
||||
|
||||
if (method === "GET") {
|
||||
if (data) {
|
||||
|
@ -45,6 +46,12 @@ class ApiClient {
|
|||
body = data ? JSON.stringify(data) : undefined;
|
||||
}
|
||||
|
||||
if (path.match(/^http/)) {
|
||||
urlToFetch = modifiedPath || path;
|
||||
} else {
|
||||
urlToFetch = this.baseUrl + (modifiedPath || path);
|
||||
}
|
||||
|
||||
// Construct headers
|
||||
const headers = new Headers({
|
||||
Accept: "application/json",
|
||||
|
@ -60,7 +67,7 @@ class ApiClient {
|
|||
|
||||
let response;
|
||||
try {
|
||||
response = await fetch(this.baseUrl + (modifiedPath || path), {
|
||||
response = await fetch(urlToFetch, {
|
||||
method,
|
||||
body,
|
||||
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
|
||||
require('./init');
|
||||
require("./init");
|
||||
|
||||
if (
|
||||
!process.env.SECRET_KEY ||
|
||||
process.env.SECRET_KEY === 'generate_a_new_key'
|
||||
process.env.SECRET_KEY === "generate_a_new_key"
|
||||
) {
|
||||
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
|
||||
process.exit(1);
|
||||
|
@ -14,11 +14,11 @@ if (
|
|||
|
||||
if (process.env.AWS_ACCESS_KEY_ID) {
|
||||
[
|
||||
'AWS_REGION',
|
||||
'AWS_SECRET_ACCESS_KEY',
|
||||
'AWS_S3_UPLOAD_BUCKET_URL',
|
||||
'AWS_S3_UPLOAD_BUCKET_NAME',
|
||||
'AWS_S3_UPLOAD_MAX_SIZE',
|
||||
"AWS_REGION",
|
||||
"AWS_SECRET_ACCESS_KEY",
|
||||
"AWS_S3_UPLOAD_BUCKET_URL",
|
||||
"AWS_S3_UPLOAD_BUCKET_NAME",
|
||||
"AWS_S3_UPLOAD_MAX_SIZE",
|
||||
].forEach(key => {
|
||||
if (!process.env[key]) {
|
||||
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) {
|
||||
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
|
||||
process.exit(1);
|
||||
|
@ -48,7 +48,7 @@ if (!process.env.URL) {
|
|||
|
||||
if (!process.env.DATABASE_URL) {
|
||||
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
|
||||
process.exit(1);
|
||||
|
@ -56,7 +56,7 @@ if (!process.env.DATABASE_URL) {
|
|||
|
||||
if (!process.env.REDIS_URL) {
|
||||
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
|
||||
process.exit(1);
|
||||
|
@ -64,17 +64,17 @@ if (!process.env.REDIS_URL) {
|
|||
|
||||
if (!process.env.WEBSOCKETS_ENABLED) {
|
||||
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') {
|
||||
console.log('\n\x1b[33m%s\x1b[0m', 'Running Outline in production mode.');
|
||||
} else if (process.env.NODE_ENV === 'development') {
|
||||
if (process.env.NODE_ENV === "production") {
|
||||
console.log("\n\x1b[33m%s\x1b[0m", "Running Outline in production mode.");
|
||||
} else if (process.env.NODE_ENV === "development") {
|
||||
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"'
|
||||
);
|
||||
}
|
||||
|
||||
require('./server');
|
||||
require("./server");
|
||||
|
|
6
init.js
6
init.js
|
@ -1,4 +1,4 @@
|
|||
// @flow
|
||||
require('babel-core/register');
|
||||
require('babel-polyfill');
|
||||
require('dotenv').config({ silent: true });
|
||||
require("babel-core/register");
|
||||
require("babel-polyfill");
|
||||
require("dotenv").config({ silent: true });
|
||||
|
|
|
@ -155,7 +155,6 @@
|
|||
"string-replace-to-array": "^1.0.3",
|
||||
"styled-components": "^5.0.0",
|
||||
"styled-components-breakpoint": "^2.1.1",
|
||||
"styled-components-grid": "^2.2.1",
|
||||
"styled-normalize": "^8.0.4",
|
||||
"tiny-cookie": "^2.3.1",
|
||||
"tmp": "0.0.33",
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue