Merge branch 'main' into feat/mass-import

This commit is contained in:
Tom Moor
2021-02-09 20:46:57 -08:00
committed by GitHub
42 changed files with 663 additions and 295 deletions

View File

@@ -230,7 +230,7 @@ class CollectionScene extends React.Component<Props> {
)}
</Wrapper>
<Modal
title={t("Collection permissions")}
title={t("Collection members")}
onRequestClose={this.handlePermissionsModalClose}
isOpen={this.permissionsModalOpen}
>

View File

@@ -3,6 +3,7 @@ import { observable } from "mobx";
import { inject, observer } from "mobx-react";
import * as React from "react";
import { withTranslation, Trans, type TFunction } from "react-i18next";
import AuthStore from "stores/AuthStore";
import UiStore from "stores/UiStore";
import Collection from "models/Collection";
import Button from "components/Button";
@@ -17,6 +18,7 @@ import Switch from "components/Switch";
type Props = {
collection: Collection,
ui: UiStore,
auth: AuthStore,
onSubmit: () => void,
t: TFunction,
};
@@ -24,6 +26,7 @@ type Props = {
@observer
class CollectionEdit extends React.Component<Props> {
@observable name: string = this.props.collection.name;
@observable sharing: boolean = this.props.collection.sharing;
@observable description: string = this.props.collection.description;
@observable icon: string = this.props.collection.icon;
@observable color: string = this.props.collection.color || "#4E5C6E";
@@ -44,6 +47,7 @@ class CollectionEdit extends React.Component<Props> {
icon: this.icon,
color: this.color,
private: this.private,
sharing: this.sharing,
sort: this.sort,
});
this.props.onSubmit();
@@ -82,8 +86,13 @@ class CollectionEdit extends React.Component<Props> {
this.private = ev.target.checked;
};
handleSharingChange = (ev: SyntheticInputEvent<*>) => {
this.sharing = ev.target.checked;
};
render() {
const { t } = this.props;
const { auth, t } = this.props;
const teamSharingEnabled = !!auth.team && auth.team.sharing;
return (
<Flex column>
@@ -140,6 +149,25 @@ class CollectionEdit extends React.Component<Props> {
A private collection will only be visible to invited team members.
</Trans>
</HelpText>
<Switch
id="sharing"
label={t("Public document sharing")}
onChange={this.handleSharingChange}
checked={this.sharing && teamSharingEnabled}
disabled={!teamSharingEnabled}
/>
<HelpText>
{teamSharingEnabled ? (
<Trans>
When enabled, documents can be shared publicly on the internet.
</Trans>
) : (
<Trans>
Public sharing is currently disabled in the team security
settings.
</Trans>
)}
</HelpText>
<Button
type="submit"
disabled={this.isSaving || !this.props.collection.name}
@@ -152,4 +180,6 @@ class CollectionEdit extends React.Component<Props> {
}
}
export default withTranslation()<CollectionEdit>(inject("ui")(CollectionEdit));
export default withTranslation()<CollectionEdit>(
inject("ui", "auth")(CollectionEdit)
);

View File

@@ -3,8 +3,9 @@ import { intersection } from "lodash";
import { observable } from "mobx";
import { inject, observer } from "mobx-react";
import * as React from "react";
import { withTranslation, type TFunction } from "react-i18next";
import { withTranslation, type TFunction, Trans } from "react-i18next";
import { withRouter, type RouterHistory } from "react-router-dom";
import AuthStore from "stores/AuthStore";
import CollectionsStore from "stores/CollectionsStore";
import UiStore from "stores/UiStore";
import Collection from "models/Collection";
@@ -18,6 +19,7 @@ import Switch from "components/Switch";
type Props = {
history: RouterHistory,
auth: AuthStore,
ui: UiStore,
collections: CollectionsStore,
onSubmit: () => void,
@@ -30,6 +32,7 @@ class CollectionNew extends React.Component<Props> {
@observable description: string = "";
@observable icon: string = "";
@observable color: string = "#4E5C6E";
@observable sharing: boolean = true;
@observable private: boolean = false;
@observable isSaving: boolean;
hasOpenedIconPicker: boolean = false;
@@ -41,6 +44,7 @@ class CollectionNew extends React.Component<Props> {
{
name: this.name,
description: this.description,
sharing: this.sharing,
icon: this.icon,
color: this.color,
private: this.private,
@@ -59,7 +63,7 @@ class CollectionNew extends React.Component<Props> {
}
};
handleNameChange = (ev: SyntheticInputEvent<*>) => {
handleNameChange = (ev: SyntheticInputEvent<HTMLInputElement>) => {
this.name = ev.target.value;
// If the user hasn't picked an icon yet, go ahead and suggest one based on
@@ -90,24 +94,31 @@ class CollectionNew extends React.Component<Props> {
this.description = getValue();
};
handlePrivateChange = (ev: SyntheticInputEvent<*>) => {
handlePrivateChange = (ev: SyntheticInputEvent<HTMLInputElement>) => {
this.private = ev.target.checked;
};
handleSharingChange = (ev: SyntheticInputEvent<HTMLInputElement>) => {
this.sharing = ev.target.checked;
};
handleChange = (color: string, icon: string) => {
this.color = color;
this.icon = icon;
};
render() {
const { t } = this.props;
const { t, auth } = this.props;
const teamSharingEnabled = !!auth.team && auth.team.sharing;
return (
<form onSubmit={this.handleSubmit}>
<HelpText>
{t(
"Collections are for grouping your knowledge base. They work best when organized around a topic or internal team — Product or Engineering for example."
)}
<Trans>
Collections are for grouping your knowledge base. They work best
when organized around a topic or internal team Product or
Engineering for example.
</Trans>
</HelpText>
<Flex>
<Input
@@ -142,10 +153,25 @@ class CollectionNew extends React.Component<Props> {
checked={this.private}
/>
<HelpText>
{t(
"A private collection will only be visible to invited team members."
)}
<Trans>
A private collection will only be visible to invited team members.
</Trans>
</HelpText>
{teamSharingEnabled && (
<>
<Switch
id="sharing"
label={t("Public document sharing")}
onChange={this.handleSharingChange}
checked={this.sharing}
/>
<HelpText>
<Trans>
When enabled, documents can be shared publicly on the internet.
</Trans>
</HelpText>
</>
)}
<Button type="submit" disabled={this.isSaving || !this.name}>
{this.isSaving ? `${t("Creating")}` : t("Create")}
@@ -156,5 +182,5 @@ class CollectionNew extends React.Component<Props> {
}
export default withTranslation()<CollectionNew>(
inject("collections", "ui")(withRouter(CollectionNew))
inject("collections", "ui", "auth")(withRouter(CollectionNew))
);

View File

@@ -126,7 +126,7 @@ class Header extends React.Component<Props> {
const isNew = document.isNew;
const isTemplate = document.isTemplate;
const can = policies.abilities(document.id);
const canShareDocuments = auth.team && auth.team.sharing && can.share;
const canShareDocument = auth.team && auth.team.sharing && can.share;
const canToggleEmbeds = auth.team && auth.team.documentEmbeds;
const canEdit = can.update && !isEditing;
@@ -200,7 +200,7 @@ class Header extends React.Component<Props> {
<TemplatesMenu document={document} />
</Action>
)}
{!isEditing && canShareDocuments && (
{!isEditing && canShareDocument && (
<Action>
<Tooltip
tooltip={

View File

@@ -4,12 +4,13 @@ import { observable } from "mobx";
import { observer, inject } from "mobx-react";
import { PlusIcon } from "outline-icons";
import * as React from "react";
import { withTranslation, type TFunction, Trans } from "react-i18next";
import { type Match } from "react-router-dom";
import AuthStore from "stores/AuthStore";
import PoliciesStore from "stores/PoliciesStore";
import UsersStore from "stores/UsersStore";
import Invite from "scenes/Invite";
import Bubble from "components/Bubble";
import Button from "components/Button";
import CenteredContent from "components/CenteredContent";
import Empty from "components/Empty";
@@ -27,12 +28,20 @@ type Props = {
users: UsersStore,
policies: PoliciesStore,
match: Match,
t: TFunction,
};
@observer
class People extends React.Component<Props> {
@observable inviteModalOpen: boolean = false;
componentDidMount() {
const { team } = this.props.auth;
if (team) {
this.props.users.fetchCounts(team.id);
}
}
handleInviteModalOpen = () => {
this.inviteModalOpen = true;
};
@@ -46,7 +55,7 @@ class People extends React.Component<Props> {
};
render() {
const { auth, policies, match } = this.props;
const { auth, policies, match, t } = this.props;
const { filter } = match.params;
const currentUser = auth.user;
const team = auth.team;
@@ -65,15 +74,18 @@ class People extends React.Component<Props> {
}
const can = policies.abilities(team.id);
const { counts } = this.props.users;
return (
<CenteredContent>
<PageTitle title="People" />
<h1>People</h1>
<PageTitle title={t("People")} />
<h1>{t("People")}</h1>
<HelpText>
Everyone that has signed into Outline appears here. Its possible that
there are other users who have access through {team.signinMethods} but
havent signed in yet.
<Trans>
Everyone that has signed into Outline appears here. Its possible
that there are other users who have access through{" "}
{team.signinMethods} but havent signed in yet.
</Trans>
</HelpText>
<Button
type="button"
@@ -84,37 +96,36 @@ class People extends React.Component<Props> {
icon={<PlusIcon />}
neutral
>
Invite people
{t("Invite people")}
</Button>
<Tabs>
<Tab to="/settings/people" exact>
Active
{t("Active")} <Bubble count={counts.active} />
</Tab>
<Tab to="/settings/people/admins" exact>
Admins
{t("Admins")} <Bubble count={counts.admins} />
</Tab>
{can.update && (
<Tab to="/settings/people/suspended" exact>
Suspended
{t("Suspended")} <Bubble count={counts.suspended} />
</Tab>
)}
<Tab to="/settings/people/all" exact>
Everyone
{t("Everyone")} <Bubble count={counts.all - counts.invited} />
</Tab>
{can.invite && (
<>
<Separator />
<Tab to="/settings/people/invited" exact>
Invited
{t("Invited")} <Bubble count={counts.invited} />
</Tab>
</>
)}
</Tabs>
<PaginatedList
items={users}
empty={<Empty>No people to see here.</Empty>}
empty={<Empty>{t("No people to see here.")}</Empty>}
fetch={this.fetchPage}
renderItem={(item) => (
<UserListItem
@@ -126,7 +137,7 @@ class People extends React.Component<Props> {
/>
<Modal
title="Invite people"
title={t("Invite people")}
onRequestClose={this.handleInviteModalClose}
isOpen={this.inviteModalOpen}
>
@@ -137,4 +148,8 @@ class People extends React.Component<Props> {
}
}
export default inject("auth", "users", "policies")(People);
export default inject(
"auth",
"users",
"policies"
)(withTranslation()<People>(People));