diff --git a/src/atoms/projectScope/user.ts b/src/atoms/projectScope/user.ts index 62bcc175..5c03281e 100644 --- a/src/atoms/projectScope/user.ts +++ b/src/atoms/projectScope/user.ts @@ -30,6 +30,12 @@ export const themeOverriddenAtom = atomWithStorage( false ); +/** User's default table settings (affecting saving and popup behavior) */ +export const defaultTableSettingsAtom = atom((get) => { + const userSettings = get(userSettingsAtom); + return userSettings.defaultTableSettings; +}); + /** Customized base theme based on project and user settings */ export const customizedThemesAtom = atom((get) => { const publicSettings = get(publicSettingsAtom); diff --git a/src/components/Settings/UserSettings/TableSettings.tsx b/src/components/Settings/UserSettings/TableSettings.tsx new file mode 100644 index 00000000..6c4bfcb9 --- /dev/null +++ b/src/components/Settings/UserSettings/TableSettings.tsx @@ -0,0 +1,103 @@ +import { merge } from "lodash-es"; +import { IUserSettingsChildProps } from "@src/pages/Settings/UserSettingsPage"; + +import { + FormControl, + FormControlLabel, + Divider, + Checkbox, + Collapse, +} from "@mui/material"; + +export default function TableSettings({ + settings, + updateSettings, +}: IUserSettingsChildProps) { + return ( + <> + + { + updateSettings({ + defaultTableSettings: merge(settings.defaultTableSettings, { + saveSortsPopupDisabled: e.target.checked, + }), + }); + }} + /> + } + label="Disable popup - to save sorting changes to the team" + style={{ marginLeft: -11, marginBottom: 13 }} + /> + + { + updateSettings({ + defaultTableSettings: merge(settings.defaultTableSettings, { + automaticallyApplySorts: e.target.checked, + }), + }); + }} + /> + } + label="Automatically apply sorting changes to all users" + style={{ marginLeft: 20, marginBottom: 10, marginTop: -13 }} + /> + + + + + { + updateSettings({ + defaultTableSettings: merge(settings.defaultTableSettings, { + saveColumnSizingPopupDisabled: e.target.checked, + }), + }); + }} + /> + } + label="Disable popup - to save column width changes to the team" + style={{ marginLeft: -11, marginTop: 13 }} + /> + + { + updateSettings({ + defaultTableSettings: merge(settings.defaultTableSettings, { + automaticallyApplyColumnSizing: e.target.checked, + }), + }); + }} + /> + } + label="Automatically apply column width changes to all users" + style={{ marginLeft: 20 }} + /> + + + + ); +} diff --git a/src/components/Table/ColumnHeader/useSaveTableSorts.tsx b/src/components/Table/ColumnHeader/useSaveTableSorts.tsx index c0c239ed..76efdbef 100644 --- a/src/components/Table/ColumnHeader/useSaveTableSorts.tsx +++ b/src/components/Table/ColumnHeader/useSaveTableSorts.tsx @@ -1,5 +1,5 @@ import { useCallback, useState } from "react"; -import { useAtom } from "jotai"; +import { useAtom, useAtomValue } from "jotai"; import { SnackbarKey, useSnackbar } from "notistack"; import LoadingButton from "@mui/lab/LoadingButton"; @@ -11,17 +11,25 @@ import { tableScope, updateTableSchemaAtom, } from "@src/atoms/tableScope"; -import { projectScope, updateUserSettingsAtom } from "@src/atoms/projectScope"; +import { + defaultTableSettingsAtom, + projectScope, + updateUserSettingsAtom, +} from "@src/atoms/projectScope"; import { TableSort } from "@src/types/table"; function useSaveTableSorts(canEditColumns: boolean) { const [updateTableSchema] = useAtom(updateTableSchemaAtom, tableScope); const [updateUserSettings] = useAtom(updateUserSettingsAtom, projectScope); const [tableId] = useAtom(tableIdAtom, tableScope); + const defaultTableSettings = useAtomValue( + defaultTableSettingsAtom, + projectScope + ); const { enqueueSnackbar, closeSnackbar } = useSnackbar(); const [snackbarId, setSnackbarId] = useState(null); - // Offer to save when table sorts changes + // Offer to save when table sorts changes, depending on user settings const trigger = useCallback( (sorts: TableSort[]) => { if (!updateTableSchema) throw new Error("Cannot update table schema"); @@ -33,6 +41,15 @@ function useSaveTableSorts(canEditColumns: boolean) { }); } if (!canEditColumns) return; + // If the user has disabled the popup, return early + if (defaultTableSettings?.saveSortsPopupDisabled) { + // If the user has `automaticallyApplySorts` set to true, apply the sorting before returning + if (defaultTableSettings?.automaticallyApplySorts) { + const updateTable = async () => await updateTableSchema({ sorts }); + updateTable(); + } + return; + } if (snackbarId) { closeSnackbar(snackbarId); } @@ -43,7 +60,7 @@ function useSaveTableSorts(canEditColumns: boolean) { updateTable={async () => await updateTableSchema({ sorts })} /> ), - anchorOrigin: { horizontal: "center", vertical: "top" }, + anchorOrigin: { horizontal: "left", vertical: "bottom" }, }) ); @@ -57,6 +74,7 @@ function useSaveTableSorts(canEditColumns: boolean) { tableId, closeSnackbar, updateTableSchema, + defaultTableSettings, ] ); diff --git a/src/components/Table/useSaveColumnSizing.tsx b/src/components/Table/useSaveColumnSizing.tsx index af1a6e37..b0c1d55c 100644 --- a/src/components/Table/useSaveColumnSizing.tsx +++ b/src/components/Table/useSaveColumnSizing.tsx @@ -1,5 +1,5 @@ import { useEffect, useState } from "react"; -import { useSetAtom } from "jotai"; +import { useAtomValue, useSetAtom } from "jotai"; import { useSnackbar } from "notistack"; import { useDebounce } from "use-debounce"; import { isEqual, isEmpty } from "lodash-es"; @@ -13,6 +13,10 @@ import { updateColumnAtom, IUpdateColumnOptions, } from "@src/atoms/tableScope"; +import { + defaultTableSettingsAtom, + projectScope, +} from "@src/atoms/projectScope"; import { DEBOUNCE_DELAY } from "./Table"; import { ColumnSizingState } from "@tanstack/react-table"; @@ -26,14 +30,31 @@ export function useSaveColumnSizing( ) { const { enqueueSnackbar, closeSnackbar } = useSnackbar(); const updateColumn = useSetAtom(updateColumnAtom, tableScope); + const defaultTableSettings = useAtomValue( + defaultTableSettingsAtom, + projectScope + ); // Debounce for saving to schema const [debouncedColumnSizing] = useDebounce(columnSizing, DEBOUNCE_DELAY, { equalityFn: isEqual, }); - // Offer to save when column sizing changes + // Offer to save when column sizing changes, depending on user settings useEffect(() => { if (!canEditColumns || isEmpty(debouncedColumnSizing)) return; + // If the user has disabled the popup, return early + if (defaultTableSettings?.saveColumnSizingPopupDisabled) { + // If the user has `automaticallyApplyColumnSizing` set to true, apply the column width before returning + if (defaultTableSettings?.automaticallyApplyColumnSizing) { + const updateTable = async () => { + for (const [key, value] of Object.entries(debouncedColumnSizing)) { + await updateColumn({ key, config: { width: value } }); + } + }; + updateTable(); + } + return; + } const snackbarId = enqueueSnackbar("Save column sizes for all users?", { action: ( @@ -42,7 +63,7 @@ export function useSaveColumnSizing( updateColumn={updateColumn} /> ), - anchorOrigin: { horizontal: "center", vertical: "top" }, + anchorOrigin: { horizontal: "left", vertical: "bottom" }, }); return () => closeSnackbar(snackbarId); @@ -52,6 +73,7 @@ export function useSaveColumnSizing( enqueueSnackbar, closeSnackbar, updateColumn, + defaultTableSettings, ]); return null; diff --git a/src/pages/Settings/UserSettingsPage.tsx b/src/pages/Settings/UserSettingsPage.tsx index 1981157f..83b30e78 100644 --- a/src/pages/Settings/UserSettingsPage.tsx +++ b/src/pages/Settings/UserSettingsPage.tsx @@ -9,6 +9,7 @@ import SettingsSkeleton from "@src/components/Settings/SettingsSkeleton"; import SettingsSection from "@src/components/Settings/SettingsSection"; import Account from "@src/components/Settings/UserSettings/Account"; import Theme from "@src/components/Settings/UserSettings/Theme"; +import TableSettings from "@src/components/Settings/UserSettings/TableSettings"; import Personalization from "@src/components/Settings/UserSettings/Personalization"; import { @@ -57,6 +58,7 @@ export default function UserSettingsPage() { const sections = [ { title: "Account", Component: Account, props: childProps }, { title: "Theme", Component: Theme, props: childProps }, + { title: "Table Settings", Component: TableSettings, props: childProps }, { title: "Personalization", Component: Personalization, props: childProps }, ]; diff --git a/src/types/settings.d.ts b/src/types/settings.d.ts index 334df8b9..0c5321d1 100644 --- a/src/types/settings.d.ts +++ b/src/types/settings.d.ts @@ -50,7 +50,14 @@ export type UserSettings = Partial<{ theme: Record<"base" | "light" | "dark", ThemeOptions>; favoriteTables: string[]; - /** Stores user overrides */ + /** Stores default user settings for all tables */ + defaultTableSettings: Partial<{ + saveSortsPopupDisabled: boolean; + automaticallyApplySorts: boolean; + saveColumnSizingPopupDisabled: boolean; + automaticallyApplyColumnSizing: boolean; + }>; + /** Stores table-specific user overrides */ tables: Record< string, Partial<{