Skip to content

Commit

Permalink
feat(dashboard): add feature flags provider and hook (#7133)
Browse files Browse the repository at this point in the history
  • Loading branch information
ChmaraX authored Nov 28, 2024
1 parent cd6906d commit b26e1a7
Show file tree
Hide file tree
Showing 5 changed files with 724 additions and 735 deletions.
1 change: 1 addition & 0 deletions apps/dashboard/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
"@segment/analytics-next": "^1.73.0",
"@sentry/react": "^8.35.0",
"@tanstack/react-query": "^5.59.6",
"launchdarkly-react-client-sdk": "^3.3.2",
"@types/js-cookie": "^3.0.6",
"@uiw/codemirror-extensions-langs": "^4.23.6",
"@uiw/codemirror-theme-white": "^4.23.6",
Expand Down
38 changes: 38 additions & 0 deletions apps/dashboard/src/context/feature-flags-provider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { lazy, Suspense } from 'react';
import { asyncWithLDProvider } from 'launchdarkly-react-client-sdk';
import { LAUNCH_DARKLY_CLIENT_SIDE_ID } from '@/config';

const LD_CONFIG = {
clientSideID: LAUNCH_DARKLY_CLIENT_SIDE_ID,
reactOptions: {
useCamelCaseFlagKeys: false,
},
context: {
kind: 'user',
anonymous: true,
},
options: {
bootstrap: 'localStorage',
},
} as const;

const AsyncFeatureFlagsProvider = lazy(async () => {
if (!LAUNCH_DARKLY_CLIENT_SIDE_ID) {
return {
default: ({ children }: { children: React.ReactNode }) => <>{children}</>,
};
}

const LaunchDarklyProvider = await asyncWithLDProvider(LD_CONFIG);
return {
default: ({ children }: { children: React.ReactNode }) => <LaunchDarklyProvider>{children}</LaunchDarklyProvider>,
};
});

export function FeatureFlagsProvider({ children }: { children: React.ReactNode }) {
return (
<Suspense>
<AsyncFeatureFlagsProvider>{children}</AsyncFeatureFlagsProvider>
</Suspense>
);
}
23 changes: 23 additions & 0 deletions apps/dashboard/src/hooks/use-feature-flag.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { useFlags } from 'launchdarkly-react-client-sdk';
import { FeatureFlagsKeysEnum, prepareBooleanStringFeatureFlag } from '@novu/shared';
import { LAUNCH_DARKLY_CLIENT_SIDE_ID } from '../config';

function isLaunchDarklyEnabled() {
return !!LAUNCH_DARKLY_CLIENT_SIDE_ID;
}

export const useFeatureFlag = (key: FeatureFlagsKeysEnum, defaultValue = false): boolean => {
const flags = useFlags();

if (!isLaunchDarklyEnabled()) {
const envValue =
// Check if the feature flag is exported as an environment variable
import.meta.env[`VITE_${key}`] ??
// Then check process.env if process exists
(typeof process !== 'undefined' ? process?.env?.[key] : undefined);

return prepareBooleanStringFeatureFlag(envValue, defaultValue);
}

return flags[key] ?? defaultValue;
};
5 changes: 4 additions & 1 deletion apps/dashboard/src/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { EditWorkflowPage } from './pages/edit-workflow';
import { TestWorkflowPage } from './pages/test-workflow';
import { initializeSentry } from './utils/sentry';
import { overrideZodErrorMap } from './utils/validation';
import { FeatureFlagsProvider } from '@/context/feature-flags-provider';
import { EditStepTemplate } from '@/components/workflow-editor/steps/edit-step-template';
import { ConfigureWorkflow } from '@/components/workflow-editor/configure-workflow';
import { EditStep } from '@/components/workflow-editor/steps/edit-step';
Expand Down Expand Up @@ -105,6 +106,8 @@ const router = createBrowserRouter([

createRoot(document.getElementById('root')!).render(
<StrictMode>
<RouterProvider router={router} />
<FeatureFlagsProvider>
<RouterProvider router={router} />
</FeatureFlagsProvider>
</StrictMode>
);
Loading

0 comments on commit b26e1a7

Please sign in to comment.