diff --git a/frontend/src/component/common/ResponsiveButton/ResponsiveButton.tsx b/frontend/src/component/common/ResponsiveButton/ResponsiveButton.tsx index a6fad58c43..c3416bcf69 100644 --- a/frontend/src/component/common/ResponsiveButton/ResponsiveButton.tsx +++ b/frontend/src/component/common/ResponsiveButton/ResponsiveButton.tsx @@ -4,6 +4,8 @@ import { ConditionallyRender } from 'component/common/ConditionallyRender/Condit import PermissionButton from 'component/common/PermissionButton/PermissionButton'; import PermissionIconButton from 'component/common/PermissionIconButton/PermissionIconButton'; import type { ITooltipResolverProps } from '../TooltipResolver/TooltipResolver'; +import type { OverridableStringUnion } from '@mui/types'; +import type { ButtonPropsVariantOverrides } from '@mui/material/Button/Button'; interface IResponsiveButtonProps { Icon: React.ElementType; @@ -15,6 +17,10 @@ interface IResponsiveButtonProps { projectId?: string; environmentId?: string; maxWidth: string; + variant?: OverridableStringUnion< + 'text' | 'outlined' | 'contained', + ButtonPropsVariantOverrides + >; className?: string; children?: React.ReactNode; } @@ -29,6 +35,7 @@ const ResponsiveButton: React.FC = ({ environmentId, projectId, endIcon, + variant, ...rest }) => { const smallScreen = useMediaQuery(`(max-width:${maxWidth})`); @@ -55,7 +62,7 @@ const ResponsiveButton: React.FC = ({ permission={permission} projectId={projectId} color='primary' - variant='contained' + variant={variant} disabled={disabled} environmentId={environmentId} endIcon={endIcon} diff --git a/frontend/src/component/project/Project/PaginatedProjectFeatureToggles/ProjectFeatureToggles.tsx b/frontend/src/component/project/Project/PaginatedProjectFeatureToggles/ProjectFeatureToggles.tsx index 967a5f2eea..606d707504 100644 --- a/frontend/src/component/project/Project/PaginatedProjectFeatureToggles/ProjectFeatureToggles.tsx +++ b/frontend/src/component/project/Project/PaginatedProjectFeatureToggles/ProjectFeatureToggles.tsx @@ -114,6 +114,11 @@ export const ProjectFeatureToggles = ({ const isPlaceholder = Boolean(initialLoad || (loading && total)); + const onboardingStarted = + onboardingUIEnabled && project.onboardingStatus.status !== 'onboarded'; + const hasMultipleFeaturesOrNotOnboarding = + (total !== undefined && total > 1) || !onboardingStarted; + const columns = useMemo( () => [ columnHelper.display({ @@ -399,10 +404,7 @@ export const ProjectFeatureToggles = ({ return ( } /> - { - setTableState({ query }); - }} - dataToExport={data} - environmentsToExport={environments} - actions={ - ({ - header: environment, - id: formatEnvironmentColumnId( - environment, - ), - isVisible: - columnVisibility[ - formatEnvironmentColumnId( - environment, - ) - ], - })), - ]} - onToggle={onToggleColumnVisibility} + { + setTableState({ query }); + }} + dataToExport={data} + environmentsToExport={environments} + actions={ + ({ + header: environment, + id: formatEnvironmentColumnId( + environment, + ), + isVisible: + columnVisibility[ + formatEnvironmentColumnId( + environment, + ) + ], + }), + ), + ]} + onToggle={onToggleColumnVisibility} + /> + } /> } - /> + bodyClass='noop' + style={{ cursor: 'inherit' }} + > +
+ + + + + + } + /> + {rowActionsDialogs} + + {featureToggleModals} +
+
} - bodyClass='noop' - style={{ cursor: 'inherit' }} - > -
- - - - - - } - /> - {rowActionsDialogs} - - {featureToggleModals} - - {'feature' in project.onboardingStatus ? ( - { - setConnectSdkOpen(false); - }} - project={projectId} - environments={environments} - feature={project.onboardingStatus.feature} - /> - ) : null} -
- + /> + {'feature' in project.onboardingStatus ? ( + { + setConnectSdkOpen(false); + }} + project={projectId} + environments={environments} + feature={project.onboardingStatus.feature} + /> + ) : null} ; +} + const StyledResponsiveButton = styled(ResponsiveButton)(() => ({ whiteSpace: 'nowrap', })); -export const FlagCreationButton: FC = () => { +export const FlagCreationButton = ({ + variant, + text = 'New feature flag', +}: IFlagCreationButtonProps) => { const [searchParams] = useSearchParams(); const projectId = useRequiredPathParam('projectId'); const showCreateDialog = Boolean(searchParams.get('create')); @@ -56,10 +69,11 @@ export const FlagCreationButton: FC = () => { Icon={Add} projectId={projectId} disabled={loading} + variant={variant} permission={CREATE_FEATURE} data-testid='NAVIGATE_TO_CREATE_FEATURE' > - New feature flag + {text} ({ borderRadius: '20%', })); -const StyledLink = styled(Link)({ +const FlagLink = styled(Link)({ fontWeight: 'bold', textDecoration: 'none', display: 'flex', justifyContent: 'center', }); +const ExistingFlagContainer = styled('div')(({ theme }) => ({ + display: 'flex', + flexDirection: 'column', + gap: theme.spacing(3), + height: '100%', +})); + +const FlagCreationContainer = styled('div')(({ theme }) => ({ + marginTop: 'auto', +})); + export const WelcomeToProject = ({ projectId, setConnectSdkOpen, @@ -119,7 +130,9 @@ export const WelcomeToProject = ({ Connect an SDK - We have not detected any connected SDKs on this project. + Your project is not yet connected to any SDK. In order + to start using your feature flag connect an SDK to the + project. { @@ -150,13 +163,12 @@ const CreateFlag = () => {
The project currently holds no feature toggles.
Create a feature flag to get started.
- + ); }; const ExistingFlag = ({ featureId, projectId }: IExistingFlagsProps) => { - const theme = useTheme(); const { feature } = useFeature(projectId, featureId); const { featureTypes } = useFeatureTypes(); const IconComponent = getFeatureTypeIcons(feature.type); @@ -166,7 +178,7 @@ const ExistingFlag = ({ featureId, projectId }: IExistingFlagsProps) => { const typeTitle = `${typeName || feature.type} flag`; return ( - <> + Create a feature flag @@ -177,16 +189,21 @@ const ExistingFlag = ({ featureId, projectId }: IExistingFlagsProps) => { - {feature.name} - + + + view flag + - - Your project is not yet connected to any SDK. In order to start - using your feature flag connect an SDK to the project. - - + + + + ); }; diff --git a/src/lib/features/onboarding/onboarding-read-model.ts b/src/lib/features/onboarding/onboarding-read-model.ts index a124e520c3..285407389c 100644 --- a/src/lib/features/onboarding/onboarding-read-model.ts +++ b/src/lib/features/onboarding/onboarding-read-model.ts @@ -86,6 +86,7 @@ export class OnboardingReadModel implements IOnboardingReadModel { const feature = await this.db('features') .select('name') .where('project', projectId) + .where('archived_at', null) .first(); if (!feature) {