feat: Allow users to override team setting for seamless editing (#5772)

This commit is contained in:
Tom Moor
2023-09-04 19:19:43 -04:00
committed by GitHub
parent c376dc1011
commit 74860ed961
10 changed files with 97 additions and 61 deletions

View File

@@ -72,7 +72,7 @@ function DataLoader({ match, children }: Props) {
? documents.getSharedTree(document.id)
: undefined;
const isEditRoute = match.path === matchDocumentEdit;
const isEditing = isEditRoute || !!auth.team?.seamlessEditing;
const isEditing = isEditRoute || !auth.user?.separateEditMode;
const can = usePolicy(document?.id);
const location = useLocation<LocationState>();

View File

@@ -391,7 +391,7 @@ class DocumentScene extends React.Component<Props> {
render() {
const { document, revision, readOnly, abilities, auth, ui, shareId, t } =
this.props;
const team = auth.team;
const { team, user } = auth;
const isShare = !!shareId;
const embedsDisabled =
(team && team.documentEmbeds === false) || document.embedsDisabled;
@@ -463,7 +463,7 @@ class DocumentScene extends React.Component<Props> {
revision={revision}
shareId={shareId}
isDraft={document.isDraft}
isEditing={!readOnly && !team?.seamlessEditing}
isEditing={!readOnly && !!user?.separateEditMode}
isSaving={this.isSaving}
isPublishing={this.isPublishing}
publishingIsDisabled={

View File

@@ -85,7 +85,7 @@ function DocumentHeader({
const { ui, auth } = useStores();
const theme = useTheme();
const { resolvedTheme } = ui;
const { team } = auth;
const { team, user } = auth;
const isMobile = useMobile();
const isRevision = !!revision;
@@ -224,11 +224,11 @@ function DocumentHeader({
<>
<ObservingBanner />
{!isPublishing && isSaving && !team?.seamlessEditing && (
{!isPublishing && isSaving && user?.separateEditMode && (
<Status>{t("Saving")}</Status>
)}
{!isDeleted && !isRevision && <Collaborators document={document} />}
{(isEditing || team?.seamlessEditing) && !isTemplate && isNew && (
{(isEditing || !user?.separateEditMode) && !isTemplate && isNew && (
<Action>
<TemplatesMenu
document={document}
@@ -267,7 +267,7 @@ function DocumentHeader({
)}
{can.update &&
!isEditing &&
!team?.seamlessEditing &&
user?.separateEditMode &&
!isRevision &&
editAction}
{can.update &&

View File

@@ -18,19 +18,19 @@ function Features() {
const { t } = useTranslation();
const { showToast } = useToasts();
const handlePreferenceChange = async (
ev: React.ChangeEvent<HTMLInputElement>
) => {
const preferences = {
...team.preferences,
[ev.target.name]: ev.target.checked,
};
const handlePreferenceChange =
(inverted = false) =>
async (ev: React.ChangeEvent<HTMLInputElement>) => {
const preferences = {
...team.preferences,
[ev.target.name]: inverted ? !ev.target.checked : ev.target.checked,
};
await auth.updateTeam({ preferences });
showToast(t("Settings saved"), {
type: "success",
});
};
await auth.updateTeam({ preferences });
showToast(t("Settings saved"), {
type: "success",
});
};
return (
<Scene title={t("Features")} icon={<BeakerIcon />}>
@@ -43,16 +43,16 @@ function Features() {
</Text>
<SettingRow
name={TeamPreference.SeamlessEdit}
label={t("Seamless editing")}
label={t("Separate editing")}
description={t(
`When enabled documents are always editable for team members that have permission. When disabled there is a separate editing view.`
`When enabled documents have a separate editing mode by default instead of being always editable. This setting can be overridden by user preferences.`
)}
>
<Switch
id={TeamPreference.SeamlessEdit}
name={TeamPreference.SeamlessEdit}
checked={team.getPreference(TeamPreference.SeamlessEdit)}
onChange={handlePreferenceChange}
checked={!team.getPreference(TeamPreference.SeamlessEdit)}
onChange={handlePreferenceChange(true)}
/>
</SettingRow>
<SettingRow
@@ -66,7 +66,7 @@ function Features() {
id={TeamPreference.Commenting}
name={TeamPreference.Commenting}
checked={team.getPreference(TeamPreference.Commenting)}
onChange={handlePreferenceChange}
onChange={handlePreferenceChange(false)}
/>
</SettingRow>
</Scene>

View File

@@ -3,13 +3,14 @@ import { SettingsIcon } from "outline-icons";
import * as React from "react";
import { Trans, useTranslation } from "react-i18next";
import { languageOptions } from "@shared/i18n";
import { UserPreference } from "@shared/types";
import { TeamPreference, UserPreference } from "@shared/types";
import Button from "~/components/Button";
import Heading from "~/components/Heading";
import InputSelect from "~/components/InputSelect";
import Scene from "~/components/Scene";
import Switch from "~/components/Switch";
import Text from "~/components/Text";
import useCurrentTeam from "~/hooks/useCurrentTeam";
import useCurrentUser from "~/hooks/useCurrentUser";
import useStores from "~/hooks/useStores";
import useToasts from "~/hooks/useToasts";
@@ -21,21 +22,22 @@ function Preferences() {
const { showToast } = useToasts();
const { dialogs, auth } = useStores();
const user = useCurrentUser();
const team = useCurrentTeam();
const handlePreferenceChange = async (
ev: React.ChangeEvent<HTMLInputElement>
) => {
const preferences = {
...user.preferences,
[ev.target.name]: ev.target.checked,
const handlePreferenceChange =
(inverted = false) =>
async (ev: React.ChangeEvent<HTMLInputElement>) => {
const preferences = {
...user.preferences,
[ev.target.name]: inverted ? !ev.target.checked : ev.target.checked,
};
await auth.updateUser({ preferences });
showToast(t("Preferences saved"), {
type: "success",
});
};
await auth.updateUser({ preferences });
showToast(t("Preferences saved"), {
type: "success",
});
};
const handleLanguageChange = async (language: string) => {
await auth.updateUser({ language });
showToast(t("Preferences saved"), {
@@ -98,7 +100,7 @@ function Preferences() {
id={UserPreference.UseCursorPointer}
name={UserPreference.UseCursorPointer}
checked={user.getPreference(UserPreference.UseCursorPointer)}
onChange={handlePreferenceChange}
onChange={handlePreferenceChange(false)}
/>
</SettingRow>
<SettingRow
@@ -111,11 +113,30 @@ function Preferences() {
id={UserPreference.CodeBlockLineNumers}
name={UserPreference.CodeBlockLineNumers}
checked={user.getPreference(UserPreference.CodeBlockLineNumers)}
onChange={handlePreferenceChange}
onChange={handlePreferenceChange(false)}
/>
</SettingRow>
<Heading as="h2">{t("Behavior")}</Heading>
<SettingRow
name={UserPreference.SeamlessEdit}
label={t("Separate editing")}
description={t(
`When enabled documents have a separate editing mode, when disabled documents are always editable when you have permission.`
)}
>
<Switch
id={UserPreference.SeamlessEdit}
name={UserPreference.SeamlessEdit}
checked={
!user.getPreference(
UserPreference.SeamlessEdit,
team.getPreference(TeamPreference.SeamlessEdit)
)
}
onChange={handlePreferenceChange(true)}
/>
</SettingRow>
<SettingRow
border={false}
name={UserPreference.RememberLastPath}
@@ -128,7 +149,7 @@ function Preferences() {
id={UserPreference.RememberLastPath}
name={UserPreference.RememberLastPath}
checked={!!user.getPreference(UserPreference.RememberLastPath)}
onChange={handlePreferenceChange}
onChange={handlePreferenceChange(false)}
/>
</SettingRow>