feat: Allow users to override team setting for seamless editing (#5772)
This commit is contained in:
@@ -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>();
|
||||
|
||||
|
||||
@@ -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={
|
||||
|
||||
@@ -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 &&
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user