From 30c20d79676b61e03d681d03fef8906d6153c126 Mon Sep 17 00:00:00 2001 From: Austin Turner Date: Mon, 3 Feb 2025 18:44:41 -0700 Subject: [PATCH] Allow opting out of record sync --- apps/api/src/app/controllers/user.controller.ts | 3 ++- .../app/controllers/web-extension.controller.ts | 2 +- apps/api/src/app/db/user.db.ts | 13 ++++++++----- .../src/app/components/billing/Billing.tsx | 2 +- .../src/app/components/core/AppInitializer.tsx | 8 ++++++-- .../src/app/components/settings/Settings.tsx | 17 +++++++++++------ libs/api-config/src/lib/env-config.ts | 1 + libs/auth/types/src/lib/auth-types.ts | 1 + .../shared/ui-app-state/src/lib/ui-app-state.ts | 1 + libs/shared/ui-core/src/app/HeaderNavbar.tsx | 12 +++++++----- libs/types/src/lib/types.ts | 1 + .../migration.sql | 2 ++ prisma/schema.prisma | 1 + 13 files changed, 43 insertions(+), 21 deletions(-) create mode 100644 prisma/migrations/20250204003847_add_record_sync_toggle/migration.sql diff --git a/apps/api/src/app/controllers/user.controller.ts b/apps/api/src/app/controllers/user.controller.ts index 212c4549..f6a758f1 100644 --- a/apps/api/src/app/controllers/user.controller.ts +++ b/apps/api/src/app/controllers/user.controller.ts @@ -102,7 +102,8 @@ export const routeDefinition = { name: z.string().min(1).max(255).trim().optional(), preferences: z .object({ - skipFrontdoorLogin: z.boolean(), + skipFrontdoorLogin: z.boolean().optional(), + recordSyncEnabled: z.boolean().optional(), }) .optional(), }), diff --git a/apps/api/src/app/controllers/web-extension.controller.ts b/apps/api/src/app/controllers/web-extension.controller.ts index ec412c4e..e3a3edc3 100644 --- a/apps/api/src/app/controllers/web-extension.controller.ts +++ b/apps/api/src/app/controllers/web-extension.controller.ts @@ -113,7 +113,7 @@ const initSession = createRoute(routeDefinition.initSession.validators, async ({ name: user.name, emailVerified: user.emailVerified, picture: user.picture, - preferences: { skipFrontdoorLogin: false }, + preferences: { skipFrontdoorLogin: false, recordSyncEnabled: true }, billingAccount: user.billingAccount, entitlements: { chromeExtension: true, diff --git a/apps/api/src/app/db/user.db.ts b/apps/api/src/app/db/user.db.ts index 5385bac0..c021bdc2 100644 --- a/apps/api/src/app/db/user.db.ts +++ b/apps/api/src/app/db/user.db.ts @@ -153,22 +153,25 @@ export const checkUserEntitlement = ({ export async function updateUser( user: UserProfileSession, - data: { name?: string; preferences?: { skipFrontdoorLogin: boolean } } + data: { name?: string; preferences?: { skipFrontdoorLogin?: boolean; recordSyncEnabled?: boolean } } ): Promise { try { const existingUser = await prisma.user.findUniqueOrThrow({ where: { id: user.id }, - select: { id: true, name: true, preferences: { select: { skipFrontdoorLogin: true } } }, + select: { id: true, name: true, preferences: { select: { skipFrontdoorLogin: true, recordSyncEnabled: true } } }, }); - const skipFrontdoorLogin = data.preferences?.skipFrontdoorLogin ?? (existingUser?.preferences?.skipFrontdoorLogin || false); + // PATCH update + const skipFrontdoorLogin = data.preferences?.skipFrontdoorLogin ?? existingUser?.preferences?.skipFrontdoorLogin ?? false; + const recordSyncEnabled = data.preferences?.recordSyncEnabled ?? existingUser?.preferences?.recordSyncEnabled ?? true; + const updatedUser = await prisma.user.update({ where: { id: user.id }, data: { name: data.name ?? existingUser.name, preferences: { upsert: { - create: { skipFrontdoorLogin }, - update: { skipFrontdoorLogin }, + create: { skipFrontdoorLogin, recordSyncEnabled }, + update: { skipFrontdoorLogin, recordSyncEnabled }, }, }, }, diff --git a/apps/jetstream/src/app/components/billing/Billing.tsx b/apps/jetstream/src/app/components/billing/Billing.tsx index 467f5ccd..3c37a39b 100644 --- a/apps/jetstream/src/app/components/billing/Billing.tsx +++ b/apps/jetstream/src/app/components/billing/Billing.tsx @@ -114,7 +114,7 @@ export const Billing = () => { ) : (
-

Professional plan includes

+

Upgrading to a Jetstream Professional plan includes

  • Access to the{' '} diff --git a/apps/jetstream/src/app/components/core/AppInitializer.tsx b/apps/jetstream/src/app/components/core/AppInitializer.tsx index 9b5f2cbd..55fc6ec9 100644 --- a/apps/jetstream/src/app/components/core/AppInitializer.tsx +++ b/apps/jetstream/src/app/components/core/AppInitializer.tsx @@ -1,7 +1,7 @@ /* eslint-disable no-restricted-globals */ import { logger } from '@jetstream/shared/client-logger'; import { HTTP } from '@jetstream/shared/constants'; -import { checkHeartbeat, initSocket, registerMiddleware } from '@jetstream/shared/data'; +import { checkHeartbeat, disconnectSocket, initSocket, registerMiddleware } from '@jetstream/shared/data'; import { useObservable, useRollbar } from '@jetstream/shared/ui-utils'; import { Announcement, ApplicationCookie, SalesforceOrgUi, UserProfileUi } from '@jetstream/types'; import { initDexieDb, useAmplitude, usePageViews } from '@jetstream/ui-core'; @@ -41,7 +41,9 @@ export const AppInitializer: FunctionComponent = ({ onAnnou const appCookie = useRecoilValue(fromAppState.applicationCookieState); const [orgs, setOrgs] = useRecoilState(fromAppState.salesforceOrgsState); const invalidOrg = useObservable(orgConnectionError$); - const recordSyncEnabled = useRecoilValue(fromAppState.userProfileEntitlementState('recordSync')); + + const recordSyncEntitlementEnabled = useRecoilValue(fromAppState.userProfileEntitlementState('recordSync')); + const recordSyncEnabled = recordSyncEntitlementEnabled && userProfile.preferences.recordSyncEnabled; useEffect(() => { console.log( @@ -67,6 +69,8 @@ APP VERSION ${version} useEffect(() => { if (recordSyncEnabled) { initSocket(); + } else { + disconnectSocket(); } initDexieDb({ recordSyncEnabled }).catch((ex) => { logger.error('[DB] Error initializing db', ex); diff --git a/apps/jetstream/src/app/components/settings/Settings.tsx b/apps/jetstream/src/app/components/settings/Settings.tsx index 8bbb46db..00b1cb2d 100644 --- a/apps/jetstream/src/app/components/settings/Settings.tsx +++ b/apps/jetstream/src/app/components/settings/Settings.tsx @@ -102,6 +102,12 @@ export const Settings = () => { handleSave(_modifiedUser); } + function handleRecordSyncChange(recordSyncEnabled: boolean) { + const _modifiedUser = { ...modifiedUser, preferences: { recordSyncEnabled } } as UserProfileUiWithIdentities; + setModifiedUser(_modifiedUser); + handleSave(_modifiedUser); + } + async function handleDelete(reason: string) { /** * FUTURE: @@ -163,7 +169,7 @@ export const Settings = () => {

    General Settings

    { {recordSyncEnabled && (

    Data Sync

    - {/* FIXME: add option for user to opt-out of this behavior (e.g. user preference?) */} - {/* setRecordSyncEnabled(value)} - /> */} + onChange={handleRecordSyncChange} + />