Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(web): user profile menu opt-in #6886

Merged
merged 13 commits into from
Nov 8, 2024
4 changes: 2 additions & 2 deletions apps/web/package.json
Original file line number Diff line number Diff line change
@@ -1,24 +1,24 @@
{
"name": "@novu/web",

Check warning on line 2 in apps/web/package.json

View workflow job for this annotation

GitHub Actions / Spell check

Unknown word (novu)
"version": "2.0.0",
"private": true,
"scripts": {
"start": "pnpm panda --watch & cross-env NODE_OPTIONS=--max_old_space_size=8192 DISABLE_ESLINT_PLUGIN=true PORT=4200 react-app-rewired start",
"prebuild": "rimraf build",
"build": "pnpm panda && cross-env NODE_OPTIONS=--max_old_space_size=4096 GENERATE_SOURCEMAP=false DISABLE_ESLINT_PLUGIN=true react-app-rewired --max_old_space_size=4096 build",
"build:web:for-dashboard": "pnpm panda && cross-env BUILD_PATH=../../apps/dashboard/legacy NODE_OPTIONS=--max_old_space_size=4096 GENERATE_SOURCEMAP=false DISABLE_ESLINT_PLUGIN=true PUBLIC_URL=/legacy/ react-app-rewired --max_old_space_size=4096 build && pnpm envsetup:dashboard",

Check warning on line 9 in apps/web/package.json

View workflow job for this annotation

GitHub Actions / Spell check

Unknown word (envsetup)
"build:test": "pnpm panda && cross-env REACT_APP_HUBSPOT_EMBED=44416662 REACT_APP_API_URL=http://127.0.0.1:1336 NODE_OPTIONS=--max_old_space_size=4096 GENERATE_SOURCEMAP=false DISABLE_ESLINT_PLUGIN=true react-app-rewired --max_old_space_size=4096 build",

Check warning on line 10 in apps/web/package.json

View workflow job for this annotation

GitHub Actions / Spell check

Unknown word (HUBSPOT)
"precommit": "lint-staged",
"docker:build": "docker buildx build --load -f ./Dockerfile -t novu-web ./../.. $DOCKER_BUILD_ARGUMENTS",

Check warning on line 12 in apps/web/package.json

View workflow job for this annotation

GitHub Actions / Spell check

Unknown word (buildx)

Check warning on line 12 in apps/web/package.json

View workflow job for this annotation

GitHub Actions / Spell check

Unknown word (novu)
"docker:build:depot": "depot build -f ./Dockerfile -t novu-web ./../.. --load",

Check warning on line 13 in apps/web/package.json

View workflow job for this annotation

GitHub Actions / Spell check

Unknown word (novu)
"envsetup:dashboard": "chmod +x ./env.sh && ./env.sh .env.dashboard && mv ./env-config.js ../../apps/dashboard/legacy/env-config.js && rm .env",

Check warning on line 14 in apps/web/package.json

View workflow job for this annotation

GitHub Actions / Spell check

Unknown word (envsetup)
"envsetup:docker": "chmod +x ./env.sh && ./env.sh && mv ./env-config.js ./build/env-config.js",

Check warning on line 15 in apps/web/package.json

View workflow job for this annotation

GitHub Actions / Spell check

Unknown word (envsetup)
"envsetup": "chmod +x ./env.sh && ./env.sh && mv env-config.js ./public/env-config.js",

Check warning on line 16 in apps/web/package.json

View workflow job for this annotation

GitHub Actions / Spell check

Unknown word (envsetup)
"start:static:build": "http-server build -p 4200 --proxy http://127.0.0.1:4200?",
"start:docker": "pnpm build && pnpm start:static:build",
"start:dev": "pnpm start",
"start:test": "http-server build -p 4200 --proxy http://127.0.0.1:4200?",
"start:test:e2e": "NOVU_ENTERPRISE=true REACT_APP_API_URL=http://127.0.0.1:1336 pnpm start",

Check warning on line 21 in apps/web/package.json

View workflow job for this annotation

GitHub Actions / Spell check

Unknown word (NOVU)
"test:e2e": "NOVU_ENTERPRISE=true playwright test",
"test:e2e:ui": "NOVU_ENTERPRISE=true playwright test --ui",
"test:e2e:debug": "NOVU_ENTERPRISE=true playwright test --debug",
Expand All @@ -36,7 +36,7 @@
"@babel/plugin-proposal-optional-chaining": "^7.20.7",
"@babel/plugin-transform-react-display-name": "^7.18.6",
"@babel/plugin-transform-runtime": "^7.23.2",
"@clerk/clerk-react": "^5.2.5",
"@clerk/clerk-react": "^5.15.1",
"@clerk/themes": "^2.1.10",
"@editorjs/editorjs": "^2.19.3",
"@editorjs/paragraph": "^2.8.0",
Expand Down Expand Up @@ -149,7 +149,7 @@
"@babel/preset-react": "^7.13.13",
"@babel/preset-typescript": "^7.13.0",
"@babel/runtime": "^7.20.13",
"@clerk/types": "^4.6.1",
"@clerk/types": "^4.30.0",
"@faker-js/faker": "^6.0.0",
"@novu/dal": "workspace:*",
"@novu/framework": "workspace:*",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,59 +2,37 @@ import { Card } from '@mantine/core';
import { css } from '@novu/novui/css';
import { Text, Title, Button, IconButton } from '@novu/novui';
import { IconOutlineClose } from '@novu/novui/icons';
import { useUser } from '@clerk/clerk-react';
import { FeatureFlagsKeysEnum, NewDashboardOptInStatusEnum } from '@novu/shared';
import { IS_SELF_HOSTED } from '../../../../config';
import { useFeatureFlag } from '../../../../hooks';
import { useNewDashboardOptIn } from '../../../../hooks/useNewDashboardOptIn';

export function NewDashboardOptInWidget() {
const { user } = useUser();
const { dismiss, optIn, status } = useNewDashboardOptIn();

const isNewDashboardEnabled = useFeatureFlag(FeatureFlagsKeysEnum.IS_NEW_DASHBOARD_ENABLED);

const isDismissed = user?.unsafeMetadata?.newDashboardOptInStatus === NewDashboardOptInStatusEnum.DISMISSED;
const isDismissed = status === NewDashboardOptInStatusEnum.DISMISSED;

if (IS_SELF_HOSTED || isDismissed || !isNewDashboardEnabled) {
return null;
}

const updateUserOptInStatus = (status: NewDashboardOptInStatusEnum) => {
if (!user) return;

user.update({
unsafeMetadata: {
...user.unsafeMetadata,
newDashboardOptInStatus: status,
},
});
};

function handleOptIn() {
const newDashboardUrl = process.env.NEW_DASHBOARD_URL;
if (!newDashboardUrl || !user) return;

updateUserOptInStatus(NewDashboardOptInStatusEnum.OPTED_IN);
window.location.href = newDashboardUrl;
}

function handleDismiss() {
updateUserOptInStatus(NewDashboardOptInStatusEnum.DISMISSED);
}

return (
<Card shadow="sm" className={styles.card}>
<div className={styles.content}>
<div className={styles.header}>
<Title className={styles.title}>
<span style={{ marginRight: '4px' }}>🎉</span> You're invited!
</Title>
<IconButton onClick={handleDismiss} Icon={IconOutlineClose} size="xs" />
<IconButton onClick={dismiss} Icon={IconOutlineClose} size="xs" />
</div>
<Text className={styles.text}>
We’d love to extend you the access for the new workflows dashboard that we’re building.
</Text>
</div>
<div className={styles.buttonContainer}>
<Button size="sm" variant="transparent" onClick={handleOptIn}>
<Button size="sm" variant="transparent" onClick={optIn}>
Take me there
</Button>
</div>
Expand Down
21 changes: 20 additions & 1 deletion apps/web/src/ee/clerk/components/UserProfileButton.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,25 @@
import { UserButton } from '@clerk/clerk-react';
import { IconBolt } from '@novu/novui/icons';
import { FeatureFlagsKeysEnum } from '@novu/shared';
import { ROUTES } from '../../../constants/routes';
import { useNewDashboardOptIn } from '../../../hooks/useNewDashboardOptIn';
import { useFeatureFlag } from '../../../hooks';

export function UserProfileButton() {
return <UserButton afterSignOutUrl={ROUTES.AUTH_LOGIN} userProfileUrl={ROUTES.MANAGE_ACCOUNT_USER_PROFILE} />;
const { optIn } = useNewDashboardOptIn();
const isNewDashboardEnabled = useFeatureFlag(FeatureFlagsKeysEnum.IS_NEW_DASHBOARD_ENABLED);

return (
<UserButton afterSignOutUrl={ROUTES.AUTH_LOGIN} userProfileUrl={ROUTES.MANAGE_ACCOUNT_USER_PROFILE}>
{isNewDashboardEnabled && (
<UserButton.MenuItems>
<UserButton.Action
label="Try out the new dashboard (beta)"
ChmaraX marked this conversation as resolved.
Show resolved Hide resolved
labelIcon={<IconBolt size="16" color="var(--nv-colors-typography-text-main)" />}
onClick={optIn}
/>
</UserButton.MenuItems>
)}
</UserButton>
);
}
7 changes: 7 additions & 0 deletions apps/web/src/ee/clerk/providers/ClerkProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,13 @@ const CLERK_MODAL_ELEMENT = {
borderStyle: 'none',
borderWidth: '0 !important',
},
userButtonPopoverCustomItemButton: {
fontWeight: 'var(--nv-font-weights-strong)',
lineHeight: 'var(--nv-line-heights-125)',
color: 'var(--nv-colors-typography-text-main)',
borderStyle: 'none',
borderWidth: '0 !important',
},
/*
* PLAT-146 this should be uncommented when the linked task is done
* button__manageAccount: {
Expand Down
41 changes: 41 additions & 0 deletions apps/web/src/hooks/useNewDashboardOptIn.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { useUser } from '@clerk/clerk-react';
import { NewDashboardOptInStatusEnum } from '@novu/shared';

export function useNewDashboardOptIn() {
const { user } = useUser();

const updateUserOptInStatus = (status: NewDashboardOptInStatusEnum) => {
if (!user) return;

user.update({
unsafeMetadata: {
...user.unsafeMetadata,
newDashboardOptInStatus: status,
},
});
};

const getCurrentOptInStatus = () => {
if (!user) return null;

return user.unsafeMetadata?.newDashboardOptInStatus || null;
};

const optIn = () => {
const newDashboardUrl = process.env.NEW_DASHBOARD_URL;
if (!newDashboardUrl) return;

updateUserOptInStatus(NewDashboardOptInStatusEnum.OPTED_IN);
window.location.href = newDashboardUrl;
};

const optOut = () => {
updateUserOptInStatus(NewDashboardOptInStatusEnum.OPTED_OUT);
};

const dismiss = () => {
updateUserOptInStatus(NewDashboardOptInStatusEnum.DISMISSED);
};

return { optIn, optOut, dismiss, status: getCurrentOptInStatus() };
}
80 changes: 63 additions & 17 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading