Centralize default user and team preferences. (#5172
Passing the fallback at each callpoint was dumb
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import { computed, observable } from "mobx";
|
||||
import { TeamPreferenceDefaults } from "@shared/constants";
|
||||
import { TeamPreference, TeamPreferences } from "@shared/types";
|
||||
import { stringToColor } from "@shared/utils/color";
|
||||
import BaseModel from "./BaseModel";
|
||||
@@ -88,22 +89,19 @@ class Team extends BaseModel {
|
||||
*/
|
||||
@computed
|
||||
get seamlessEditing(): boolean {
|
||||
return !!this.getPreference(TeamPreference.SeamlessEdit, true);
|
||||
return !!this.getPreference(TeamPreference.SeamlessEdit);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value for a specific preference key, or return the fallback if
|
||||
* none is set.
|
||||
* Returns the value of the provided preference.
|
||||
*
|
||||
* @param key The TeamPreference key to retrieve
|
||||
* @param fallback An optional fallback value, defaults to false.
|
||||
* @returns The value
|
||||
* @param preference The team preference to retrieve
|
||||
* @returns The preference value if set, else the default value
|
||||
*/
|
||||
getPreference<T extends keyof TeamPreferences>(
|
||||
key: T,
|
||||
fallback = false
|
||||
key: T
|
||||
): TeamPreferences[T] | false {
|
||||
return this.preferences?.[key] ?? fallback;
|
||||
return this.preferences?.[key] ?? TeamPreferenceDefaults[key] ?? false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -7,6 +7,7 @@ import { useLocation, Link, Redirect } from "react-router-dom";
|
||||
import styled from "styled-components";
|
||||
import { getCookie, setCookie } from "tiny-cookie";
|
||||
import { s } from "@shared/styles";
|
||||
import { UserPreference } from "@shared/types";
|
||||
import { parseDomain } from "@shared/utils/domains";
|
||||
import { Config } from "~/stores/AuthStore";
|
||||
import ButtonLarge from "~/components/ButtonLarge";
|
||||
@@ -61,7 +62,9 @@ function Login({ children }: Props) {
|
||||
const [error, setError] = React.useState(null);
|
||||
const [emailLinkSentTo, setEmailLinkSentTo] = React.useState("");
|
||||
const isCreate = location.pathname === "/create";
|
||||
const rememberLastPath = !!auth.user?.preferences?.rememberLastPath;
|
||||
const rememberLastPath = !!auth.user?.getPreference(
|
||||
UserPreference.RememberLastPath
|
||||
);
|
||||
const [lastVisitedPath] = useLastVisitedPath();
|
||||
|
||||
const handleReset = React.useCallback(() => {
|
||||
|
||||
@@ -53,7 +53,7 @@ function Features() {
|
||||
<Switch
|
||||
id={TeamPreference.SeamlessEdit}
|
||||
name={TeamPreference.SeamlessEdit}
|
||||
checked={team.getPreference(TeamPreference.SeamlessEdit, true)}
|
||||
checked={team.getPreference(TeamPreference.SeamlessEdit)}
|
||||
onChange={handlePreferenceChange}
|
||||
/>
|
||||
</SettingRow>
|
||||
@@ -71,7 +71,7 @@ function Features() {
|
||||
<Switch
|
||||
id={TeamPreference.Commenting}
|
||||
name={TeamPreference.Commenting}
|
||||
checked={team.getPreference(TeamPreference.Commenting, false)}
|
||||
checked={team.getPreference(TeamPreference.Commenting)}
|
||||
onChange={handlePreferenceChange}
|
||||
/>
|
||||
</SettingRow>
|
||||
@@ -86,7 +86,7 @@ function Features() {
|
||||
<Switch
|
||||
id={TeamPreference.PublicBranding}
|
||||
name={TeamPreference.PublicBranding}
|
||||
checked={team.getPreference(TeamPreference.PublicBranding, false)}
|
||||
checked={team.getPreference(TeamPreference.PublicBranding)}
|
||||
onChange={handlePreferenceChange}
|
||||
/>
|
||||
</SettingRow>
|
||||
|
||||
@@ -87,29 +87,29 @@ function Preferences() {
|
||||
/>
|
||||
</SettingRow>
|
||||
<SettingRow
|
||||
name="useCursorPointer"
|
||||
name={UserPreference.UseCursorPointer}
|
||||
label={t("Use pointer cursor")}
|
||||
description={t(
|
||||
"Show a hand cursor when hovering over interactive elements."
|
||||
)}
|
||||
>
|
||||
<Switch
|
||||
id="useCursorPointer"
|
||||
name="useCursorPointer"
|
||||
checked={user.getPreference(UserPreference.UseCursorPointer, true)}
|
||||
id={UserPreference.UseCursorPointer}
|
||||
name={UserPreference.UseCursorPointer}
|
||||
checked={user.getPreference(UserPreference.UseCursorPointer)}
|
||||
onChange={handlePreferenceChange}
|
||||
/>
|
||||
</SettingRow>
|
||||
<SettingRow
|
||||
name="codeBlockLineNumbers"
|
||||
name={UserPreference.CodeBlockLineNumers}
|
||||
label={t("Show line numbers")}
|
||||
description={t("Show line numbers on code blocks in documents.")}
|
||||
border={false}
|
||||
>
|
||||
<Switch
|
||||
id="codeBlockLineNumbers"
|
||||
name="codeBlockLineNumbers"
|
||||
checked={user.getPreference(UserPreference.CodeBlockLineNumers, true)}
|
||||
id={UserPreference.CodeBlockLineNumers}
|
||||
name={UserPreference.CodeBlockLineNumers}
|
||||
checked={user.getPreference(UserPreference.CodeBlockLineNumers)}
|
||||
onChange={handlePreferenceChange}
|
||||
/>
|
||||
</SettingRow>
|
||||
@@ -117,16 +117,16 @@ function Preferences() {
|
||||
<Heading as="h2">{t("Behavior")}</Heading>
|
||||
<SettingRow
|
||||
border={false}
|
||||
name="rememberLastPath"
|
||||
name={UserPreference.RememberLastPath}
|
||||
label={t("Remember previous location")}
|
||||
description={t(
|
||||
"Automatically return to the document you were last viewing when the app is re-opened."
|
||||
)}
|
||||
>
|
||||
<Switch
|
||||
id="rememberLastPath"
|
||||
name="rememberLastPath"
|
||||
checked={!!user.preferences?.rememberLastPath}
|
||||
id={UserPreference.RememberLastPath}
|
||||
name={UserPreference.RememberLastPath}
|
||||
checked={!!user.getPreference(UserPreference.RememberLastPath)}
|
||||
onChange={handlePreferenceChange}
|
||||
/>
|
||||
</SettingRow>
|
||||
|
||||
@@ -264,7 +264,7 @@ function Security() {
|
||||
>
|
||||
<Switch
|
||||
id={TeamPreference.ViewersCanExport}
|
||||
checked={team.getPreference(TeamPreference.ViewersCanExport, true)}
|
||||
checked={team.getPreference(TeamPreference.ViewersCanExport)}
|
||||
onChange={handlePreferenceChange}
|
||||
/>
|
||||
</SettingRow>
|
||||
|
||||
@@ -20,6 +20,7 @@ import {
|
||||
AllowNull,
|
||||
AfterUpdate,
|
||||
} from "sequelize-typescript";
|
||||
import { TeamPreferenceDefaults } from "@shared/constants";
|
||||
import {
|
||||
CollectionPermission,
|
||||
TeamPreference,
|
||||
@@ -196,14 +197,15 @@ class Team extends ParanoidModel {
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the passed preference value
|
||||
* Returns the value of the given preference.
|
||||
*
|
||||
* @param preference The user preference to retrieve
|
||||
* @param fallback An optional fallback value, defaults to false.
|
||||
* @returns The preference value if set, else undefined
|
||||
* @param preference The team preference to retrieve
|
||||
* @returns The preference value if set, else the default value
|
||||
*/
|
||||
public getPreference = (preference: TeamPreference, fallback = false) =>
|
||||
this.preferences?.[preference] ?? fallback;
|
||||
public getPreference = (preference: TeamPreference) =>
|
||||
this.preferences?.[preference] ??
|
||||
TeamPreferenceDefaults[preference] ??
|
||||
false;
|
||||
|
||||
provisionFirstCollection = async (userId: string) => {
|
||||
await this.sequelize!.transaction(async (transaction) => {
|
||||
|
||||
@@ -22,6 +22,7 @@ import {
|
||||
AllowNull,
|
||||
AfterUpdate,
|
||||
} from "sequelize-typescript";
|
||||
import { UserPreferenceDefaults } from "@shared/constants";
|
||||
import { languages } from "@shared/i18n";
|
||||
import type { NotificationSettings } from "@shared/types";
|
||||
import {
|
||||
@@ -354,14 +355,15 @@ class User extends ParanoidModel {
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the passed preference value
|
||||
* Returns the value of the givem preference
|
||||
*
|
||||
* @param preference The user preference to retrieve
|
||||
* @param fallback An optional fallback value, defaults to false.
|
||||
* @returns The preference value if set, else undefined
|
||||
* @returns The preference value if set, else the default value.
|
||||
*/
|
||||
public getPreference = (preference: UserPreference, fallback = false) =>
|
||||
this.preferences?.[preference] ?? fallback;
|
||||
public getPreference = (preference: UserPreference) =>
|
||||
this.preferences?.[preference] ??
|
||||
UserPreferenceDefaults[preference] ??
|
||||
false;
|
||||
|
||||
collectionIds = async (options = {}) => {
|
||||
const collectionStubs = await Collection.scope({
|
||||
|
||||
@@ -35,7 +35,7 @@ allow(User, "download", Document, (user, document) => {
|
||||
|
||||
if (
|
||||
user.isViewer &&
|
||||
!user.team.getPreference(TeamPreference.ViewersCanExport, true)
|
||||
!user.team.getPreference(TeamPreference.ViewersCanExport)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import { TeamPreference } from "@shared/types";
|
||||
import { Team } from "@server/models";
|
||||
|
||||
export default function presentPublicTeam(team: Team) {
|
||||
return {
|
||||
name: team.name,
|
||||
avatarUrl: team.avatarUrl,
|
||||
customTheme: team.preferences?.customTheme,
|
||||
customTheme: team.getPreference(TeamPreference.CustomTheme),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,3 +1,24 @@
|
||||
import {
|
||||
TeamPreference,
|
||||
TeamPreferences,
|
||||
UserPreference,
|
||||
UserPreferences,
|
||||
} from "./types";
|
||||
|
||||
export const USER_PRESENCE_INTERVAL = 5000;
|
||||
|
||||
export const MAX_AVATAR_DISPLAY = 6;
|
||||
|
||||
export const TeamPreferenceDefaults: TeamPreferences = {
|
||||
[TeamPreference.SeamlessEdit]: true,
|
||||
[TeamPreference.ViewersCanExport]: true,
|
||||
[TeamPreference.PublicBranding]: false,
|
||||
[TeamPreference.Commenting]: false,
|
||||
[TeamPreference.CustomTheme]: undefined,
|
||||
};
|
||||
|
||||
export const UserPreferenceDefaults: UserPreferences = {
|
||||
[UserPreference.RememberLastPath]: true,
|
||||
[UserPreference.UseCursorPointer]: true,
|
||||
[UserPreference.CodeBlockLineNumers]: true,
|
||||
};
|
||||
|
||||
@@ -107,6 +107,7 @@ export enum UserPreference {
|
||||
RememberLastPath = "rememberLastPath",
|
||||
/** If web-style hand pointer should be used on interactive elements. */
|
||||
UseCursorPointer = "useCursorPointer",
|
||||
/** Whether code blocks should show line numbers. */
|
||||
CodeBlockLineNumers = "codeBlockLineNumbers",
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user