chore: Move settings screens to Scene component (#2092)
* chore: Convert groups and people settings screens to Scene/functional * chore: ImportExport to Scene component * Remaining settings scenes
This commit is contained in:
@@ -1,12 +1,12 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import { Switch } from "react-router-dom";
|
import { Switch } from "react-router-dom";
|
||||||
import Settings from "scenes/Settings";
|
|
||||||
import Details from "scenes/Settings/Details";
|
import Details from "scenes/Settings/Details";
|
||||||
import Groups from "scenes/Settings/Groups";
|
import Groups from "scenes/Settings/Groups";
|
||||||
import ImportExport from "scenes/Settings/ImportExport";
|
import ImportExport from "scenes/Settings/ImportExport";
|
||||||
import Notifications from "scenes/Settings/Notifications";
|
import Notifications from "scenes/Settings/Notifications";
|
||||||
import People from "scenes/Settings/People";
|
import People from "scenes/Settings/People";
|
||||||
|
import Profile from "scenes/Settings/Profile";
|
||||||
import Security from "scenes/Settings/Security";
|
import Security from "scenes/Settings/Security";
|
||||||
import Shares from "scenes/Settings/Shares";
|
import Shares from "scenes/Settings/Shares";
|
||||||
import Slack from "scenes/Settings/Slack";
|
import Slack from "scenes/Settings/Slack";
|
||||||
@@ -17,7 +17,7 @@ import Route from "components/ProfiledRoute";
|
|||||||
export default function SettingsRoutes() {
|
export default function SettingsRoutes() {
|
||||||
return (
|
return (
|
||||||
<Switch>
|
<Switch>
|
||||||
<Route exact path="/settings" component={Settings} />
|
<Route exact path="/settings" component={Profile} />
|
||||||
<Route exact path="/settings/details" component={Details} />
|
<Route exact path="/settings/details" component={Details} />
|
||||||
<Route exact path="/settings/security" component={Security} />
|
<Route exact path="/settings/security" component={Security} />
|
||||||
<Route exact path="/settings/people" component={People} />
|
<Route exact path="/settings/people" component={People} />
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import { observable } from "mobx";
|
import { observable } from "mobx";
|
||||||
import { observer, inject } from "mobx-react";
|
import { observer, inject } from "mobx-react";
|
||||||
|
import { TeamIcon } from "outline-icons";
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
|
|
||||||
import AuthStore from "stores/AuthStore";
|
import AuthStore from "stores/AuthStore";
|
||||||
import UiStore from "stores/UiStore";
|
import UiStore from "stores/UiStore";
|
||||||
import Button from "components/Button";
|
import Button from "components/Button";
|
||||||
import CenteredContent from "components/CenteredContent";
|
|
||||||
import Flex from "components/Flex";
|
import Flex from "components/Flex";
|
||||||
|
import Heading from "components/Heading";
|
||||||
import HelpText from "components/HelpText";
|
import HelpText from "components/HelpText";
|
||||||
import Input, { LabelText } from "components/Input";
|
import Input, { LabelText } from "components/Input";
|
||||||
import PageTitle from "components/PageTitle";
|
import Scene from "components/Scene";
|
||||||
import ImageUpload from "./components/ImageUpload";
|
import ImageUpload from "./components/ImageUpload";
|
||||||
import env from "env";
|
import env from "env";
|
||||||
|
|
||||||
@@ -85,9 +85,8 @@ class Details extends React.Component<Props> {
|
|||||||
const avatarUrl = this.avatarUrl || team.avatarUrl;
|
const avatarUrl = this.avatarUrl || team.avatarUrl;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CenteredContent>
|
<Scene title="Details" icon={<TeamIcon color="currentColor" />}>
|
||||||
<PageTitle title="Details" />
|
<Heading>Details</Heading>
|
||||||
<h1>Details</h1>
|
|
||||||
<HelpText>
|
<HelpText>
|
||||||
These details affect the way that your Outline appears to everyone on
|
These details affect the way that your Outline appears to everyone on
|
||||||
the team.
|
the team.
|
||||||
@@ -143,7 +142,7 @@ class Details extends React.Component<Props> {
|
|||||||
{isSaving ? "Saving…" : "Save"}
|
{isSaving ? "Saving…" : "Save"}
|
||||||
</Button>
|
</Button>
|
||||||
</form>
|
</form>
|
||||||
</CenteredContent>
|
</Scene>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,73 +0,0 @@
|
|||||||
// @flow
|
|
||||||
import { observable } from "mobx";
|
|
||||||
import { observer, inject } from "mobx-react";
|
|
||||||
import * as React from "react";
|
|
||||||
import AuthStore from "stores/AuthStore";
|
|
||||||
import CollectionsStore from "stores/CollectionsStore";
|
|
||||||
import UiStore from "stores/UiStore";
|
|
||||||
|
|
||||||
import Button from "components/Button";
|
|
||||||
import CenteredContent from "components/CenteredContent";
|
|
||||||
import HelpText from "components/HelpText";
|
|
||||||
import PageTitle from "components/PageTitle";
|
|
||||||
|
|
||||||
type Props = {
|
|
||||||
auth: AuthStore,
|
|
||||||
collections: CollectionsStore,
|
|
||||||
ui: UiStore,
|
|
||||||
};
|
|
||||||
|
|
||||||
@observer
|
|
||||||
class Export extends React.Component<Props> {
|
|
||||||
@observable isLoading: boolean = false;
|
|
||||||
@observable isExporting: boolean = false;
|
|
||||||
|
|
||||||
handleSubmit = async (ev: SyntheticEvent<>) => {
|
|
||||||
ev.preventDefault();
|
|
||||||
this.isLoading = true;
|
|
||||||
|
|
||||||
try {
|
|
||||||
await this.props.collections.export();
|
|
||||||
this.isExporting = true;
|
|
||||||
this.props.ui.showToast("Export in progress…", { type: "info" });
|
|
||||||
} finally {
|
|
||||||
this.isLoading = false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const { auth } = this.props;
|
|
||||||
if (!auth.user) return null;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<CenteredContent>
|
|
||||||
<PageTitle title="Export Data" />
|
|
||||||
<h1>Export Data</h1>
|
|
||||||
<HelpText>
|
|
||||||
Exporting your team’s documents may take a little time depending on
|
|
||||||
the size of your knowledge base. Consider exporting a single document
|
|
||||||
or collection instead.
|
|
||||||
</HelpText>
|
|
||||||
<HelpText>
|
|
||||||
Still want to export everything in your wiki? We’ll put together a zip
|
|
||||||
file of your collections and documents in Markdown format and email it
|
|
||||||
to <strong>{auth.user.email}</strong>.
|
|
||||||
</HelpText>
|
|
||||||
<Button
|
|
||||||
type="submit"
|
|
||||||
onClick={this.handleSubmit}
|
|
||||||
disabled={this.isLoading || this.isExporting}
|
|
||||||
primary
|
|
||||||
>
|
|
||||||
{this.isExporting
|
|
||||||
? "Export Requested"
|
|
||||||
: this.isLoading
|
|
||||||
? "Requesting Export…"
|
|
||||||
: "Export All Data"}
|
|
||||||
</Button>
|
|
||||||
</CenteredContent>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default inject("auth", "ui", "collections")(Export);
|
|
||||||
@@ -1,114 +1,83 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import invariant from "invariant";
|
import { observer } from "mobx-react";
|
||||||
import { observable } from "mobx";
|
import { PlusIcon, GroupIcon } from "outline-icons";
|
||||||
import { observer, inject } from "mobx-react";
|
|
||||||
import { PlusIcon } from "outline-icons";
|
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import { type Match } from "react-router-dom";
|
import { useTranslation, Trans } from "react-i18next";
|
||||||
|
|
||||||
import AuthStore from "stores/AuthStore";
|
|
||||||
import GroupsStore from "stores/GroupsStore";
|
|
||||||
import PoliciesStore from "stores/PoliciesStore";
|
|
||||||
import GroupNew from "scenes/GroupNew";
|
import GroupNew from "scenes/GroupNew";
|
||||||
import Button from "components/Button";
|
import Button from "components/Button";
|
||||||
import CenteredContent from "components/CenteredContent";
|
|
||||||
import Empty from "components/Empty";
|
import Empty from "components/Empty";
|
||||||
import GroupListItem from "components/GroupListItem";
|
import GroupListItem from "components/GroupListItem";
|
||||||
|
import Heading from "components/Heading";
|
||||||
import HelpText from "components/HelpText";
|
import HelpText from "components/HelpText";
|
||||||
import List from "components/List";
|
|
||||||
import { ListPlaceholder } from "components/LoadingPlaceholder";
|
|
||||||
import Modal from "components/Modal";
|
import Modal from "components/Modal";
|
||||||
import PageTitle from "components/PageTitle";
|
import PaginatedList from "components/PaginatedList";
|
||||||
import Tab from "components/Tab";
|
import Scene from "components/Scene";
|
||||||
import Tabs from "components/Tabs";
|
import Subheading from "components/Subheading";
|
||||||
|
import useCurrentTeam from "hooks/useCurrentTeam";
|
||||||
|
import useStores from "hooks/useStores";
|
||||||
import GroupMenu from "menus/GroupMenu";
|
import GroupMenu from "menus/GroupMenu";
|
||||||
|
|
||||||
type Props = {
|
function Groups() {
|
||||||
auth: AuthStore,
|
const { t } = useTranslation();
|
||||||
groups: GroupsStore,
|
const { policies, groups } = useStores();
|
||||||
policies: PoliciesStore,
|
const team = useCurrentTeam();
|
||||||
match: Match,
|
const can = policies.abilities(team.id);
|
||||||
};
|
const [newGroupModalOpen, setNewGroupModalOpen] = React.useState(false);
|
||||||
|
|
||||||
@observer
|
const handleNewGroupModalOpen = React.useCallback(() => {
|
||||||
class Groups extends React.Component<Props> {
|
setNewGroupModalOpen(true);
|
||||||
@observable newGroupModalOpen: boolean = false;
|
}, []);
|
||||||
|
|
||||||
componentDidMount() {
|
const handleNewGroupModalClose = React.useCallback(() => {
|
||||||
this.props.groups.fetchPage({ limit: 100 });
|
setNewGroupModalOpen(false);
|
||||||
}
|
}, []);
|
||||||
|
|
||||||
handleNewGroupModalOpen = () => {
|
return (
|
||||||
this.newGroupModalOpen = true;
|
<Scene title={t("Groups")} icon={<GroupIcon color="currentColor" />}>
|
||||||
};
|
<Heading>{t("Groups")}</Heading>
|
||||||
|
<HelpText>
|
||||||
handleNewGroupModalClose = () => {
|
<Trans>
|
||||||
this.newGroupModalOpen = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const { auth, policies, groups } = this.props;
|
|
||||||
const currentUser = auth.user;
|
|
||||||
const team = auth.team;
|
|
||||||
|
|
||||||
invariant(currentUser, "User should exist");
|
|
||||||
invariant(team, "Team should exist");
|
|
||||||
|
|
||||||
const showLoading = groups.isFetching && !groups.orderedData.length;
|
|
||||||
const showEmpty = groups.isLoaded && !groups.orderedData.length;
|
|
||||||
const can = policies.abilities(team.id);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<CenteredContent>
|
|
||||||
<PageTitle title="People" />
|
|
||||||
<h1>Groups</h1>
|
|
||||||
<HelpText>
|
|
||||||
Groups can be used to organize and manage the people on your team.
|
Groups can be used to organize and manage the people on your team.
|
||||||
</HelpText>
|
</Trans>
|
||||||
|
</HelpText>
|
||||||
|
|
||||||
{can.createGroup && (
|
{can.createGroup && (
|
||||||
<Button
|
<Button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={this.handleNewGroupModalOpen}
|
onClick={handleNewGroupModalOpen}
|
||||||
icon={<PlusIcon />}
|
icon={<PlusIcon />}
|
||||||
neutral
|
neutral
|
||||||
>
|
|
||||||
New group…
|
|
||||||
</Button>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<Tabs>
|
|
||||||
<Tab to="/settings/groups" exact>
|
|
||||||
All Groups
|
|
||||||
</Tab>
|
|
||||||
</Tabs>
|
|
||||||
|
|
||||||
<List>
|
|
||||||
{groups.orderedData.map((group) => (
|
|
||||||
<GroupListItem
|
|
||||||
key={group.id}
|
|
||||||
group={group}
|
|
||||||
renderActions={({ openMembersModal }) => (
|
|
||||||
<GroupMenu group={group} onMembers={openMembersModal} />
|
|
||||||
)}
|
|
||||||
showFacepile
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
</List>
|
|
||||||
|
|
||||||
{showEmpty && <Empty>No groups to see here.</Empty>}
|
|
||||||
{showLoading && <ListPlaceholder count={5} />}
|
|
||||||
|
|
||||||
<Modal
|
|
||||||
title="Create a group"
|
|
||||||
onRequestClose={this.handleNewGroupModalClose}
|
|
||||||
isOpen={this.newGroupModalOpen}
|
|
||||||
>
|
>
|
||||||
<GroupNew onSubmit={this.handleNewGroupModalClose} />
|
{`${t("New group")}…`}
|
||||||
</Modal>
|
</Button>
|
||||||
</CenteredContent>
|
)}
|
||||||
);
|
|
||||||
}
|
<Subheading>{t("All groups")}</Subheading>
|
||||||
|
<PaginatedList
|
||||||
|
items={groups.orderedData}
|
||||||
|
empty={<Empty>{t("No groups have been created yet")}</Empty>}
|
||||||
|
fetch={groups.fetchPage}
|
||||||
|
renderItem={(item) => (
|
||||||
|
<GroupListItem
|
||||||
|
key={item.id}
|
||||||
|
group={item}
|
||||||
|
renderActions={({ openMembersModal }) => (
|
||||||
|
<GroupMenu group={item} onMembers={openMembersModal} />
|
||||||
|
)}
|
||||||
|
showFacepile
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Modal
|
||||||
|
title={t("Create a group")}
|
||||||
|
onRequestClose={handleNewGroupModalClose}
|
||||||
|
isOpen={newGroupModalOpen}
|
||||||
|
>
|
||||||
|
<GroupNew onSubmit={handleNewGroupModalClose} />
|
||||||
|
</Modal>
|
||||||
|
</Scene>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default inject("auth", "groups", "policies")(Groups);
|
export default observer(Groups);
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import invariant from "invariant";
|
import invariant from "invariant";
|
||||||
import { observer } from "mobx-react";
|
import { observer } from "mobx-react";
|
||||||
import { CollectionIcon } from "outline-icons";
|
import { CollectionIcon, DocumentIcon } from "outline-icons";
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import { useTranslation, Trans } from "react-i18next";
|
import { useTranslation, Trans } from "react-i18next";
|
||||||
import { VisuallyHidden } from "reakit/VisuallyHidden";
|
import { VisuallyHidden } from "reakit/VisuallyHidden";
|
||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
import { parseOutlineExport } from "shared/utils/zip";
|
import { parseOutlineExport } from "shared/utils/zip";
|
||||||
import Button from "components/Button";
|
import Button from "components/Button";
|
||||||
import CenteredContent from "components/CenteredContent";
|
import Heading from "components/Heading";
|
||||||
import HelpText from "components/HelpText";
|
import HelpText from "components/HelpText";
|
||||||
import Notice from "components/Notice";
|
import Notice from "components/Notice";
|
||||||
import PageTitle from "components/PageTitle";
|
import Scene from "components/Scene";
|
||||||
import useCurrentUser from "hooks/useCurrentUser";
|
import useCurrentUser from "hooks/useCurrentUser";
|
||||||
import useStores from "hooks/useStores";
|
import useStores from "hooks/useStores";
|
||||||
import getDataTransferFiles from "utils/getDataTransferFiles";
|
import getDataTransferFiles from "utils/getDataTransferFiles";
|
||||||
@@ -107,9 +107,11 @@ function ImportExport() {
|
|||||||
const isImportable = hasCollections && hasDocuments;
|
const isImportable = hasCollections && hasDocuments;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CenteredContent>
|
<Scene
|
||||||
<PageTitle title={`${t("Import")} / ${t("Export")}`} />
|
title={`${t("Import")} / ${t("Export")}`}
|
||||||
<h1>{t("Import")}</h1>
|
icon={<DocumentIcon color="currentColor" />}
|
||||||
|
>
|
||||||
|
<Heading>{t("Import")}</Heading>
|
||||||
<HelpText>
|
<HelpText>
|
||||||
<Trans>
|
<Trans>
|
||||||
It is possible to import a zip file of folders and Markdown files
|
It is possible to import a zip file of folders and Markdown files
|
||||||
@@ -176,7 +178,7 @@ function ImportExport() {
|
|||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<h1>{t("Export")}</h1>
|
<Heading>{t("Export")}</Heading>
|
||||||
<HelpText>
|
<HelpText>
|
||||||
<Trans
|
<Trans
|
||||||
defaults="A full export might take some time, consider exporting a single document or collection if possible. We’ll put together a zip of all your documents in Markdown format and email it to <em>{{ userEmail }}</em>."
|
defaults="A full export might take some time, consider exporting a single document or collection if possible. We’ll put together a zip of all your documents in Markdown format and email it to <em>{{ userEmail }}</em>."
|
||||||
@@ -196,7 +198,7 @@ function ImportExport() {
|
|||||||
? `${t("Requesting Export")}…`
|
? `${t("Requesting Export")}…`
|
||||||
: t("Export Data")}
|
: t("Export Data")}
|
||||||
</Button>
|
</Button>
|
||||||
</CenteredContent>
|
</Scene>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,16 +1,17 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import { debounce } from "lodash";
|
import { debounce } from "lodash";
|
||||||
import { observer, inject } from "mobx-react";
|
import { observer, inject } from "mobx-react";
|
||||||
|
import { EmailIcon } from "outline-icons";
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
import AuthStore from "stores/AuthStore";
|
import AuthStore from "stores/AuthStore";
|
||||||
import NotificationSettingsStore from "stores/NotificationSettingsStore";
|
import NotificationSettingsStore from "stores/NotificationSettingsStore";
|
||||||
import UiStore from "stores/UiStore";
|
import UiStore from "stores/UiStore";
|
||||||
import CenteredContent from "components/CenteredContent";
|
import Heading from "components/Heading";
|
||||||
import HelpText from "components/HelpText";
|
import HelpText from "components/HelpText";
|
||||||
import Input from "components/Input";
|
import Input from "components/Input";
|
||||||
import Notice from "components/Notice";
|
import Notice from "components/Notice";
|
||||||
import PageTitle from "components/PageTitle";
|
import Scene from "components/Scene";
|
||||||
import Subheading from "components/Subheading";
|
import Subheading from "components/Subheading";
|
||||||
|
|
||||||
import NotificationListItem from "./components/NotificationListItem";
|
import NotificationListItem from "./components/NotificationListItem";
|
||||||
@@ -85,16 +86,13 @@ class Notifications extends React.Component<Props> {
|
|||||||
if (!team || !user) return null;
|
if (!team || !user) return null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CenteredContent>
|
<Scene title="Notifications" icon={<EmailIcon color="currentColor" />}>
|
||||||
{showSuccessNotice && (
|
{showSuccessNotice && (
|
||||||
<Notice>
|
<Notice>
|
||||||
Unsubscription successful. Your notification settings were updated
|
Unsubscription successful. Your notification settings were updated
|
||||||
</Notice>
|
</Notice>
|
||||||
)}
|
)}
|
||||||
|
<Heading>Notifications</Heading>
|
||||||
<PageTitle title="Notifications" />
|
|
||||||
<h1>Notifications</h1>
|
|
||||||
|
|
||||||
<HelpText>
|
<HelpText>
|
||||||
Manage when and where you receive email notifications from Outline.
|
Manage when and where you receive email notifications from Outline.
|
||||||
Your email address can be updated in your SSO provider.
|
Your email address can be updated in your SSO provider.
|
||||||
@@ -127,7 +125,7 @@ class Notifications extends React.Component<Props> {
|
|||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</CenteredContent>
|
</Scene>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
import invariant from "invariant";
|
import invariant from "invariant";
|
||||||
import { observable } from "mobx";
|
import { observable } from "mobx";
|
||||||
import { observer, inject } from "mobx-react";
|
import { observer, inject } from "mobx-react";
|
||||||
import { PlusIcon } from "outline-icons";
|
import { PlusIcon, UserIcon } from "outline-icons";
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import { withTranslation, type TFunction, Trans } from "react-i18next";
|
import { withTranslation, type TFunction, Trans } from "react-i18next";
|
||||||
import { type Match } from "react-router-dom";
|
import { type Match } from "react-router-dom";
|
||||||
@@ -12,15 +12,14 @@ import UsersStore from "stores/UsersStore";
|
|||||||
import Invite from "scenes/Invite";
|
import Invite from "scenes/Invite";
|
||||||
import Bubble from "components/Bubble";
|
import Bubble from "components/Bubble";
|
||||||
import Button from "components/Button";
|
import Button from "components/Button";
|
||||||
import CenteredContent from "components/CenteredContent";
|
|
||||||
import Empty from "components/Empty";
|
import Empty from "components/Empty";
|
||||||
|
import Heading from "components/Heading";
|
||||||
import HelpText from "components/HelpText";
|
import HelpText from "components/HelpText";
|
||||||
import Modal from "components/Modal";
|
import Modal from "components/Modal";
|
||||||
import PageTitle from "components/PageTitle";
|
|
||||||
import PaginatedList from "components/PaginatedList";
|
import PaginatedList from "components/PaginatedList";
|
||||||
|
import Scene from "components/Scene";
|
||||||
import Tab from "components/Tab";
|
import Tab from "components/Tab";
|
||||||
import Tabs, { Separator } from "components/Tabs";
|
import Tabs, { Separator } from "components/Tabs";
|
||||||
|
|
||||||
import UserListItem from "./components/UserListItem";
|
import UserListItem from "./components/UserListItem";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
@@ -79,9 +78,8 @@ class People extends React.Component<Props> {
|
|||||||
const { counts } = this.props.users;
|
const { counts } = this.props.users;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CenteredContent>
|
<Scene title={t("People")} icon={<UserIcon color="currentColor" />}>
|
||||||
<PageTitle title={t("People")} />
|
<Heading>{t("People")}</Heading>
|
||||||
<h1>{t("People")}</h1>
|
|
||||||
<HelpText>
|
<HelpText>
|
||||||
<Trans>
|
<Trans>
|
||||||
Everyone that has signed into Outline appears here. It’s possible
|
Everyone that has signed into Outline appears here. It’s possible
|
||||||
@@ -151,7 +149,7 @@ class People extends React.Component<Props> {
|
|||||||
<Invite onSubmit={this.handleInviteModalClose} />
|
<Invite onSubmit={this.handleInviteModalClose} />
|
||||||
</Modal>
|
</Modal>
|
||||||
)}
|
)}
|
||||||
</CenteredContent>
|
</Scene>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,21 +1,21 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import { observable } from "mobx";
|
import { observable } from "mobx";
|
||||||
import { observer, inject } from "mobx-react";
|
import { observer, inject } from "mobx-react";
|
||||||
|
import { ProfileIcon } from "outline-icons";
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import { Trans, withTranslation, type TFunction } from "react-i18next";
|
import { Trans, withTranslation, type TFunction } from "react-i18next";
|
||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
import { languageOptions } from "shared/i18n";
|
import { languageOptions } from "shared/i18n";
|
||||||
|
|
||||||
import AuthStore from "stores/AuthStore";
|
import AuthStore from "stores/AuthStore";
|
||||||
import UiStore from "stores/UiStore";
|
import UiStore from "stores/UiStore";
|
||||||
import UserDelete from "scenes/UserDelete";
|
import UserDelete from "scenes/UserDelete";
|
||||||
import Button from "components/Button";
|
import Button from "components/Button";
|
||||||
import CenteredContent from "components/CenteredContent";
|
|
||||||
import Flex from "components/Flex";
|
import Flex from "components/Flex";
|
||||||
|
import Heading from "components/Heading";
|
||||||
import HelpText from "components/HelpText";
|
import HelpText from "components/HelpText";
|
||||||
import Input, { LabelText } from "components/Input";
|
import Input, { LabelText } from "components/Input";
|
||||||
import InputSelect from "components/InputSelect";
|
import InputSelect from "components/InputSelect";
|
||||||
import PageTitle from "components/PageTitle";
|
import Scene from "components/Scene";
|
||||||
import ImageUpload from "./components/ImageUpload";
|
import ImageUpload from "./components/ImageUpload";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
@@ -99,9 +99,8 @@ class Profile extends React.Component<Props> {
|
|||||||
const avatarUrl = this.avatarUrl || user.avatarUrl;
|
const avatarUrl = this.avatarUrl || user.avatarUrl;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CenteredContent>
|
<Scene title={t("Profile")} icon={<ProfileIcon color="currentColor" />}>
|
||||||
<PageTitle title={t("Profile")} />
|
<Heading>{t("Profile")}</Heading>
|
||||||
<h1>{t("Profile")}</h1>
|
|
||||||
<ProfilePicture column>
|
<ProfilePicture column>
|
||||||
<LabelText>{t("Photo")}</LabelText>
|
<LabelText>{t("Photo")}</LabelText>
|
||||||
<AvatarContainer>
|
<AvatarContainer>
|
||||||
@@ -168,7 +167,7 @@ class Profile extends React.Component<Props> {
|
|||||||
{this.showDeleteModal && (
|
{this.showDeleteModal && (
|
||||||
<UserDelete onRequestClose={this.toggleDeleteAccount} />
|
<UserDelete onRequestClose={this.toggleDeleteAccount} />
|
||||||
)}
|
)}
|
||||||
</CenteredContent>
|
</Scene>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,14 +2,14 @@
|
|||||||
import { debounce } from "lodash";
|
import { debounce } from "lodash";
|
||||||
import { observable } from "mobx";
|
import { observable } from "mobx";
|
||||||
import { observer, inject } from "mobx-react";
|
import { observer, inject } from "mobx-react";
|
||||||
|
import { PadlockIcon } from "outline-icons";
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
|
|
||||||
import AuthStore from "stores/AuthStore";
|
import AuthStore from "stores/AuthStore";
|
||||||
import UiStore from "stores/UiStore";
|
import UiStore from "stores/UiStore";
|
||||||
import CenteredContent from "components/CenteredContent";
|
|
||||||
import Checkbox from "components/Checkbox";
|
import Checkbox from "components/Checkbox";
|
||||||
|
import Heading from "components/Heading";
|
||||||
import HelpText from "components/HelpText";
|
import HelpText from "components/HelpText";
|
||||||
import PageTitle from "components/PageTitle";
|
import Scene from "components/Scene";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
auth: AuthStore,
|
auth: AuthStore,
|
||||||
@@ -61,9 +61,8 @@ class Security extends React.Component<Props> {
|
|||||||
|
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<CenteredContent>
|
<Scene title="Security" icon={<PadlockIcon color="currentColor" />}>
|
||||||
<PageTitle title="Security" />
|
<Heading>Security</Heading>
|
||||||
<h1>Security</h1>
|
|
||||||
<HelpText>
|
<HelpText>
|
||||||
Settings that impact the access, security, and content of your
|
Settings that impact the access, security, and content of your
|
||||||
knowledge base.
|
knowledge base.
|
||||||
@@ -90,7 +89,7 @@ class Security extends React.Component<Props> {
|
|||||||
onChange={this.handleChange}
|
onChange={this.handleChange}
|
||||||
note="Links to supported services are shown as rich embeds within your documents"
|
note="Links to supported services are shown as rich embeds within your documents"
|
||||||
/>
|
/>
|
||||||
</CenteredContent>
|
</Scene>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,14 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import { observer } from "mobx-react";
|
import { observer } from "mobx-react";
|
||||||
|
import { LinkIcon } from "outline-icons";
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import { useTranslation, Trans } from "react-i18next";
|
import { useTranslation, Trans } from "react-i18next";
|
||||||
import { Link } from "react-router-dom";
|
import { Link } from "react-router-dom";
|
||||||
import CenteredContent from "components/CenteredContent";
|
|
||||||
import Empty from "components/Empty";
|
import Empty from "components/Empty";
|
||||||
|
import Heading from "components/Heading";
|
||||||
import HelpText from "components/HelpText";
|
import HelpText from "components/HelpText";
|
||||||
import PageTitle from "components/PageTitle";
|
|
||||||
import PaginatedList from "components/PaginatedList";
|
import PaginatedList from "components/PaginatedList";
|
||||||
|
import Scene from "components/Scene";
|
||||||
import Subheading from "components/Subheading";
|
import Subheading from "components/Subheading";
|
||||||
import ShareListItem from "./components/ShareListItem";
|
import ShareListItem from "./components/ShareListItem";
|
||||||
import useCurrentTeam from "hooks/useCurrentTeam";
|
import useCurrentTeam from "hooks/useCurrentTeam";
|
||||||
@@ -21,9 +22,8 @@ function Shares() {
|
|||||||
const can = policies.abilities(team.id);
|
const can = policies.abilities(team.id);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CenteredContent>
|
<Scene title={t("Share Links")} icon={<LinkIcon color="currentColor" />}>
|
||||||
<PageTitle title={t("Share Links")} />
|
<Heading>{t("Share Links")}</Heading>
|
||||||
<h1>{t("Share Links")}</h1>
|
|
||||||
<HelpText>
|
<HelpText>
|
||||||
<Trans>
|
<Trans>
|
||||||
Documents that have been shared are listed below. Anyone that has the
|
Documents that have been shared are listed below. Anyone that has the
|
||||||
@@ -49,7 +49,7 @@ function Shares() {
|
|||||||
fetch={shares.fetchPage}
|
fetch={shares.fetchPage}
|
||||||
renderItem={(item) => <ShareListItem key={item.id} share={item} />}
|
renderItem={(item) => <ShareListItem key={item.id} share={item} />}
|
||||||
/>
|
/>
|
||||||
</CenteredContent>
|
</Scene>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,16 +1,16 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import { observable } from "mobx";
|
import { observable } from "mobx";
|
||||||
import { observer, inject } from "mobx-react";
|
import { observer, inject } from "mobx-react";
|
||||||
|
import { CodeIcon } from "outline-icons";
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import ApiKeysStore from "stores/ApiKeysStore";
|
import ApiKeysStore from "stores/ApiKeysStore";
|
||||||
import UiStore from "stores/UiStore";
|
import UiStore from "stores/UiStore";
|
||||||
|
|
||||||
import Button from "components/Button";
|
import Button from "components/Button";
|
||||||
import CenteredContent from "components/CenteredContent";
|
import Heading from "components/Heading";
|
||||||
import HelpText from "components/HelpText";
|
import HelpText from "components/HelpText";
|
||||||
import Input from "components/Input";
|
import Input from "components/Input";
|
||||||
import List from "components/List";
|
import List from "components/List";
|
||||||
import PageTitle from "components/PageTitle";
|
import Scene from "components/Scene";
|
||||||
import TokenListItem from "./components/TokenListItem";
|
import TokenListItem from "./components/TokenListItem";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
@@ -45,10 +45,8 @@ class Tokens extends React.Component<Props> {
|
|||||||
const hasApiKeys = apiKeys.orderedData.length > 0;
|
const hasApiKeys = apiKeys.orderedData.length > 0;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CenteredContent>
|
<Scene title="API Tokens" icon={<CodeIcon color="currentColor" />}>
|
||||||
<PageTitle title="API Tokens" />
|
<Heading>API Tokens</Heading>
|
||||||
<h1>API Tokens</h1>
|
|
||||||
|
|
||||||
<HelpText>
|
<HelpText>
|
||||||
You can create an unlimited amount of personal tokens to authenticate
|
You can create an unlimited amount of personal tokens to authenticate
|
||||||
with the API. For more details about the API take a look at the{" "}
|
with the API. For more details about the API take a look at the{" "}
|
||||||
@@ -83,7 +81,7 @@ class Tokens extends React.Component<Props> {
|
|||||||
disabled={apiKeys.isSaving}
|
disabled={apiKeys.isSaving}
|
||||||
/>
|
/>
|
||||||
</form>
|
</form>
|
||||||
</CenteredContent>
|
</Scene>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import Button from "components/Button";
|
import Button from "components/Button";
|
||||||
import CenteredContent from "components/CenteredContent";
|
import Heading from "components/Heading";
|
||||||
import HelpText from "components/HelpText";
|
import HelpText from "components/HelpText";
|
||||||
import PageTitle from "components/PageTitle";
|
import Scene from "components/Scene";
|
||||||
|
import ZapierIcon from "components/ZapierIcon";
|
||||||
|
|
||||||
function Zapier() {
|
function Zapier() {
|
||||||
return (
|
return (
|
||||||
<CenteredContent>
|
<Scene title="Zapier" icon={<ZapierIcon color="currentColor" />}>
|
||||||
<PageTitle title="Zapier" />
|
<Heading>Zapier</Heading>
|
||||||
<h1>Zapier</h1>
|
|
||||||
<HelpText>
|
<HelpText>
|
||||||
Zapier is a platform that allows Outline to easily integrate with
|
Zapier is a platform that allows Outline to easily integrate with
|
||||||
thousands of other business tools. Head over to Zapier to setup a "Zap"
|
thousands of other business tools. Head over to Zapier to setup a "Zap"
|
||||||
@@ -24,7 +24,7 @@ function Zapier() {
|
|||||||
Open Zapier →
|
Open Zapier →
|
||||||
</Button>
|
</Button>
|
||||||
</p>
|
</p>
|
||||||
</CenteredContent>
|
</Scene>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +0,0 @@
|
|||||||
// @flow
|
|
||||||
import Profile from "./Profile";
|
|
||||||
export default Profile;
|
|
||||||
@@ -361,6 +361,10 @@
|
|||||||
"by {{ name }}": "by {{ name }}",
|
"by {{ name }}": "by {{ name }}",
|
||||||
"Last accessed": "Last accessed",
|
"Last accessed": "Last accessed",
|
||||||
"Add to Slack": "Add to Slack",
|
"Add to Slack": "Add to Slack",
|
||||||
|
"Groups can be used to organize and manage the people on your team.": "Groups can be used to organize and manage the people on your team.",
|
||||||
|
"New group": "New group",
|
||||||
|
"All groups": "All groups",
|
||||||
|
"No groups have been created yet": "No groups have been created yet",
|
||||||
"Import started": "Import started",
|
"Import started": "Import started",
|
||||||
"Export in progress…": "Export in progress…",
|
"Export in progress…": "Export in progress…",
|
||||||
"It is possible to import a zip file of folders and Markdown files previously exported from an Outline instance. Support will soon be added for importing from other services.": "It is possible to import a zip file of folders and Markdown files previously exported from an Outline instance. Support will soon be added for importing from other services.",
|
"It is possible to import a zip file of folders and Markdown files previously exported from an Outline instance. Support will soon be added for importing from other services.": "It is possible to import a zip file of folders and Markdown files previously exported from an Outline instance. Support will soon be added for importing from other services.",
|
||||||
|
|||||||
Reference in New Issue
Block a user