Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 50 additions & 0 deletions src/Hub.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { useQuery } from '@tanstack/react-query';
import { IntegrationPicker } from './modules/integration-picker/IntegrationPicker';
import { FeatureFlagProvider } from './shared/contexts/featureFlagContext';
import { getSettings } from './shared/queries';
import { HubModes } from './types/types';

interface HubProps {
mode: HubModes;
token: string;
apiUrl: string;
dashboardUrl: string;
height: string;
onSuccess?: () => void;
onClose?: () => void;
onCancel?: () => void;
accountId?: string;
}
export const Hub = ({
mode,
token,
apiUrl,
dashboardUrl,
height,
onSuccess,
onClose,
onCancel,
accountId,
}: HubProps) => {
const { data: settings } = useQuery({
queryKey: ['settings'],
queryFn: () => getSettings(apiUrl, token),
});

return (
<FeatureFlagProvider featureFlags={settings?.enabled_features ?? []}>
{mode === 'integration-picker' && (
<IntegrationPicker
token={token}
baseUrl={apiUrl}
dashboardUrl={dashboardUrl}
height={height}
onSuccess={onSuccess}
onClose={onClose}
onCancel={onCancel}
accountId={accountId}
/>
)}
</FeatureFlagProvider>
);
};
24 changes: 12 additions & 12 deletions src/StackOneHub.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
} from '@stackone/malachite';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { useEffect } from 'react';
import { Hub } from './Hub';
import { CsvImporter } from './modules/csv-importer.tsx/CsvImporter';
import { IntegrationPicker } from './modules/integration-picker/IntegrationPicker';
import ErrorContainer from './shared/components/error';
Expand Down Expand Up @@ -119,18 +120,17 @@ export const StackOneHub: React.FC<StackOneHubProps> = ({
}
>
<QueryClientProvider client={queryClient}>
{mode === 'integration-picker' && (
<IntegrationPicker
token={token}
baseUrl={apiUrl}
dashboardUrl={dashboardUrl}
height={height}
onSuccess={onSuccess}
onClose={onClose}
onCancel={onCancel}
accountId={accountId}
/>
)}
<Hub
mode={mode}
token={token}
apiUrl={apiUrl}
dashboardUrl={dashboardUrl}
height={height}
onSuccess={onSuccess}
accountId={accountId}
onClose={onClose}
onCancel={onCancel}
/>
</QueryClientProvider>
</ErrorBoundary>
</MalachiteContext>
Expand Down
33 changes: 19 additions & 14 deletions src/modules/integration-picker/IntegrationPicker.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Card } from '@stackone/malachite';
import useFeatureFlags from '../../shared/hooks/useFeatureFlags';
import { IntegrationPickerContent } from './components/IntegrationPickerContent';
import CardFooter from './components/cardFooter';
import CardTitle from './components/cardTitle';
Expand All @@ -23,6 +24,8 @@ export const IntegrationPicker: React.FC<IntegrationPickerProps> = ({
onSuccess,
dashboardUrl,
}) => {
const isHubLinkAccountReleaseEnabled = useFeatureFlags('hub_link_account_release');

const {
// Data
hubData,
Expand Down Expand Up @@ -73,20 +76,22 @@ export const IntegrationPicker: React.FC<IntegrationPickerProps> = ({
}
height={height}
>
<IntegrationPickerContent
isLoading={isLoading}
hasError={hasError}
connectionState={connectionState}
selectedIntegration={selectedIntegration}
connectorData={connectorData?.config ?? null}
hubData={hubData ?? null}
fields={fields}
guide={guide}
errorHubData={errorHubData}
errorConnectorData={errorConnectorData}
onSelect={setSelectedIntegration}
onChange={setFormData}
/>
{isHubLinkAccountReleaseEnabled && (
<IntegrationPickerContent
isLoading={isLoading}
hasError={hasError}
connectionState={connectionState}
selectedIntegration={selectedIntegration}
connectorData={connectorData?.config ?? null}
hubData={hubData ?? null}
fields={fields}
guide={guide}
errorHubData={errorHubData}
errorConnectorData={errorConnectorData}
onSelect={setSelectedIntegration}
onChange={setFormData}
/>
)}
</Card>
);
};
26 changes: 26 additions & 0 deletions src/shared/contexts/featureFlagContext.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { createContext, useMemo } from 'react';
import { FeatureFlag } from '../types/featureFlags';

export const FeatureFlagContext = createContext<{ featureFlags: FeatureFlag[] }>({
featureFlags: [],
});
Comment thread
adefreitas marked this conversation as resolved.

export const FeatureFlagProvider = ({
featureFlags,
children,
}: {
featureFlags: FeatureFlag[];
children: React.ReactNode;
}) => {
const memoizedContextValue = useMemo(
() => ({
featureFlags,
}),
[featureFlags],
);
return (
<FeatureFlagContext.Provider value={memoizedContextValue}>
{children}
</FeatureFlagContext.Provider>
);
};
24 changes: 24 additions & 0 deletions src/shared/hooks/useFeatureFlags.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { useContext } from 'react';
import { FeatureFlagContext } from '../contexts/featureFlagContext';
import { FeatureFlag } from '../types/featureFlags';

const isFeatureEnabled = ({
featureFlags,
featureFlag,
}: { featureFlags: FeatureFlag[]; featureFlag: FeatureFlag }): boolean => {
return featureFlags.includes(featureFlag);
};

export const useFeatureFlags = (featureFlag: FeatureFlag): boolean => {
const { featureFlags } = useContext(FeatureFlagContext);
if (!featureFlags) {
throw new Error('useFeatureFlags must be used within a FeatureFlagProvider');
}
Comment thread
adefreitas marked this conversation as resolved.

return isFeatureEnabled({
featureFlags,
featureFlag,
});
};

export default useFeatureFlags;
12 changes: 12 additions & 0 deletions src/shared/queries.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { getRequest } from './httpClient';
import { FeatureFlag } from './types/featureFlags';

export const getSettings = async (baseUrl: string, token: string) => {
return await getRequest<{ enabled_features: FeatureFlag[] }>({
url: `${baseUrl}/hub/settings`,
headers: {
'Content-Type': 'application/json',
'x-hub-session-token': token,
},
});
};
1 change: 1 addition & 0 deletions src/shared/types/featureFlags.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export type FeatureFlag = 'hub_link_account_release';
Loading