mirror of
https://github.com/Unleash/unleash.git
synced 2025-07-12 13:48:35 +02:00
feat: welcome to project onboarding status rendering (#8076)

This commit is contained in:
parent
896707f7d5
commit
f41a688edb
@ -28,6 +28,7 @@ const setupApi = () => {
|
|||||||
testServerRoute(server, '/api/admin/ui-config', {
|
testServerRoute(server, '/api/admin/ui-config', {
|
||||||
flags: {
|
flags: {
|
||||||
flagCreator: true,
|
flagCreator: true,
|
||||||
|
onboardingUI: true,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
testServerRoute(server, '/api/admin/tags', {
|
testServerRoute(server, '/api/admin/tags', {
|
||||||
@ -162,3 +163,49 @@ test.skip('filters by flag author', async () => {
|
|||||||
|
|
||||||
expect(window.location.href).toContain('createdBy=IS%3A1');
|
expect(window.location.href).toContain('createdBy=IS%3A1');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('Project is onboarded', async () => {
|
||||||
|
const projectId = 'default';
|
||||||
|
setupApi();
|
||||||
|
testServerRoute(server, '/api/admin/projects/default/overview', {
|
||||||
|
onboardingStatus: {
|
||||||
|
status: 'onboarded',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
render(
|
||||||
|
<Routes>
|
||||||
|
<Route
|
||||||
|
path={'/projects/:projectId'}
|
||||||
|
element={<ProjectFeatureToggles environments={[]} />}
|
||||||
|
/>
|
||||||
|
</Routes>,
|
||||||
|
{
|
||||||
|
route: `/projects/${projectId}`,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
expect(
|
||||||
|
screen.queryByText('Welcome to your project'),
|
||||||
|
).not.toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Project is not onboarded', async () => {
|
||||||
|
const projectId = 'default';
|
||||||
|
setupApi();
|
||||||
|
testServerRoute(server, '/api/admin/projects/default/overview', {
|
||||||
|
onboardingStatus: {
|
||||||
|
status: 'onboarding-started',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
render(
|
||||||
|
<Routes>
|
||||||
|
<Route
|
||||||
|
path={'/projects/:projectId'}
|
||||||
|
element={<ProjectFeatureToggles environments={[]} />}
|
||||||
|
/>
|
||||||
|
</Routes>,
|
||||||
|
{
|
||||||
|
route: `/projects/${projectId}`,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
await screen.findByText('Welcome to your project');
|
||||||
|
});
|
||||||
|
@ -42,6 +42,7 @@ import { AvatarCell } from './AvatarCell';
|
|||||||
import { ProjectOnboarding } from './ProjectOnboarding/ProjectOnboarding';
|
import { ProjectOnboarding } from './ProjectOnboarding/ProjectOnboarding';
|
||||||
import { useUiFlag } from 'hooks/useUiFlag';
|
import { useUiFlag } from 'hooks/useUiFlag';
|
||||||
import { styled } from '@mui/material';
|
import { styled } from '@mui/material';
|
||||||
|
import useProjectOverview from 'hooks/api/getters/useProjectOverview/useProjectOverview';
|
||||||
import { ConnectSdkDialog } from '../../../onboarding/ConnectSdkDialog';
|
import { ConnectSdkDialog } from '../../../onboarding/ConnectSdkDialog';
|
||||||
|
|
||||||
interface IPaginatedProjectFeatureTogglesProps {
|
interface IPaginatedProjectFeatureTogglesProps {
|
||||||
@ -65,6 +66,7 @@ export const ProjectFeatureToggles = ({
|
|||||||
}: IPaginatedProjectFeatureTogglesProps) => {
|
}: IPaginatedProjectFeatureTogglesProps) => {
|
||||||
const onboardingUIEnabled = useUiFlag('onboardingUI');
|
const onboardingUIEnabled = useUiFlag('onboardingUI');
|
||||||
const projectId = useRequiredPathParam('projectId');
|
const projectId = useRequiredPathParam('projectId');
|
||||||
|
const { project } = useProjectOverview(projectId);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
features,
|
features,
|
||||||
@ -396,7 +398,10 @@ export const ProjectFeatureToggles = ({
|
|||||||
return (
|
return (
|
||||||
<Container>
|
<Container>
|
||||||
<ConditionallyRender
|
<ConditionallyRender
|
||||||
condition={onboardingUIEnabled}
|
condition={
|
||||||
|
onboardingUIEnabled &&
|
||||||
|
project.onboardingStatus.status !== 'onboarded'
|
||||||
|
}
|
||||||
show={<ProjectOnboarding projectId={projectId} />}
|
show={<ProjectOnboarding projectId={projectId} />}
|
||||||
/>
|
/>
|
||||||
<PageContent
|
<PageContent
|
||||||
|
@ -0,0 +1,52 @@
|
|||||||
|
import { render } from 'utils/testRenderer';
|
||||||
|
import { Route, Routes } from 'react-router-dom';
|
||||||
|
import { testServerRoute, testServerSetup } from 'utils/testServer';
|
||||||
|
import { WelcomeToProject } from './WelcomeToProject';
|
||||||
|
import { screen } from '@testing-library/react';
|
||||||
|
|
||||||
|
const server = testServerSetup();
|
||||||
|
|
||||||
|
test('Project can start onboarding', async () => {
|
||||||
|
const projectId = 'default';
|
||||||
|
testServerRoute(server, '/api/admin/projects/default/overview', {
|
||||||
|
onboarding: {
|
||||||
|
onboardingStatus: 'onboarding-started',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
render(
|
||||||
|
<Routes>
|
||||||
|
<Route
|
||||||
|
path={'/projects/:projectId'}
|
||||||
|
element={<WelcomeToProject projectId={projectId} />}
|
||||||
|
/>
|
||||||
|
</Routes>,
|
||||||
|
{
|
||||||
|
route: `/projects/${projectId}`,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
await screen.findByText('The project currently holds no feature toggles.');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Project can connect SDK', async () => {
|
||||||
|
const projectId = 'default';
|
||||||
|
testServerRoute(server, '/api/admin/projects/default/overview', {
|
||||||
|
onboardingStatus: {
|
||||||
|
status: 'first-flag-created',
|
||||||
|
feature: 'default-feature',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
render(
|
||||||
|
<Routes>
|
||||||
|
<Route
|
||||||
|
path={'/projects/:projectId'}
|
||||||
|
element={<WelcomeToProject projectId={projectId} />}
|
||||||
|
/>
|
||||||
|
</Routes>,
|
||||||
|
{
|
||||||
|
route: `/projects/${projectId}`,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
await screen.findByText(
|
||||||
|
'Your project is not yet connected to any SDK. In order to start using your feature flag connect an SDK to the project.',
|
||||||
|
);
|
||||||
|
});
|
@ -1,13 +1,24 @@
|
|||||||
import { styled, Typography } from '@mui/material';
|
import { styled, Typography, useTheme } from '@mui/material';
|
||||||
import Add from '@mui/icons-material/Add';
|
import Add from '@mui/icons-material/Add';
|
||||||
import { CREATE_FEATURE } from 'component/providers/AccessProvider/permissions';
|
import { CREATE_FEATURE } from 'component/providers/AccessProvider/permissions';
|
||||||
import { FlagCreationButton } from '../ProjectFeatureTogglesHeader/ProjectFeatureTogglesHeader';
|
import { FlagCreationButton } from '../ProjectFeatureTogglesHeader/ProjectFeatureTogglesHeader';
|
||||||
import ResponsiveButton from 'component/common/ResponsiveButton/ResponsiveButton';
|
import ResponsiveButton from 'component/common/ResponsiveButton/ResponsiveButton';
|
||||||
|
import useProjectOverview from 'hooks/api/getters/useProjectOverview/useProjectOverview';
|
||||||
|
import { useFeature } from 'hooks/api/getters/useFeature/useFeature';
|
||||||
|
import { getFeatureTypeIcons } from 'utils/getFeatureTypeIcons';
|
||||||
|
import { Link } from 'react-router-dom';
|
||||||
|
import { HtmlTooltip } from 'component/common/HtmlTooltip/HtmlTooltip';
|
||||||
|
import useFeatureTypes from 'hooks/api/getters/useFeatureTypes/useFeatureTypes';
|
||||||
|
|
||||||
interface IWelcomeToProjectProps {
|
interface IWelcomeToProjectProps {
|
||||||
projectId: string;
|
projectId: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface IExistingFlagsProps {
|
||||||
|
featureId: string;
|
||||||
|
projectId: string;
|
||||||
|
}
|
||||||
|
|
||||||
const Container = styled('div')(({ theme }) => ({
|
const Container = styled('div')(({ theme }) => ({
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
flexDirection: 'column',
|
flexDirection: 'column',
|
||||||
@ -44,7 +55,7 @@ const TitleContainer = styled('div')(({ theme }) => ({
|
|||||||
fontWeight: 'bold',
|
fontWeight: 'bold',
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const CircleContainer = styled('span')(({ theme }) => ({
|
const NeutralCircleContainer = styled('span')(({ theme }) => ({
|
||||||
width: '28px',
|
width: '28px',
|
||||||
height: '28px',
|
height: '28px',
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
@ -54,7 +65,27 @@ const CircleContainer = styled('span')(({ theme }) => ({
|
|||||||
borderRadius: '50%',
|
borderRadius: '50%',
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
const MainCircleContainer = styled(NeutralCircleContainer)(({ theme }) => ({
|
||||||
|
backgroundColor: theme.palette.primary.main,
|
||||||
|
color: theme.palette.background.paper,
|
||||||
|
}));
|
||||||
|
|
||||||
|
const TypeCircleContainer = styled(MainCircleContainer)(({ theme }) => ({
|
||||||
|
borderRadius: '20%',
|
||||||
|
}));
|
||||||
|
|
||||||
|
const StyledLink = styled(Link)({
|
||||||
|
fontWeight: 'bold',
|
||||||
|
textDecoration: 'none',
|
||||||
|
display: 'flex',
|
||||||
|
justifyContent: 'center',
|
||||||
|
});
|
||||||
|
|
||||||
export const WelcomeToProject = ({ projectId }: IWelcomeToProjectProps) => {
|
export const WelcomeToProject = ({ projectId }: IWelcomeToProjectProps) => {
|
||||||
|
const { project } = useProjectOverview(projectId);
|
||||||
|
const isFirstFlagCreated =
|
||||||
|
project.onboardingStatus.status === 'first-flag-created';
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Container>
|
<Container>
|
||||||
<TitleBox>
|
<TitleBox>
|
||||||
@ -67,21 +98,19 @@ export const WelcomeToProject = ({ projectId }: IWelcomeToProjectProps) => {
|
|||||||
</TitleBox>
|
</TitleBox>
|
||||||
<Actions>
|
<Actions>
|
||||||
<ActionBox>
|
<ActionBox>
|
||||||
<TitleContainer>
|
{project.onboardingStatus.status ===
|
||||||
<CircleContainer>1</CircleContainer>
|
'first-flag-created' ? (
|
||||||
Create a feature flag
|
<ExistingFlag
|
||||||
</TitleContainer>
|
projectId={projectId}
|
||||||
<Typography>
|
featureId={project.onboardingStatus.feature}
|
||||||
<div>
|
/>
|
||||||
The project currently holds no feature toggles.
|
) : (
|
||||||
</div>
|
<CreateFlag />
|
||||||
<div>Create a feature flag to get started.</div>
|
)}
|
||||||
</Typography>
|
|
||||||
<FlagCreationButton />
|
|
||||||
</ActionBox>
|
</ActionBox>
|
||||||
<ActionBox>
|
<ActionBox>
|
||||||
<TitleContainer>
|
<TitleContainer>
|
||||||
<CircleContainer>2</CircleContainer>
|
<NeutralCircleContainer>2</NeutralCircleContainer>
|
||||||
Connect an SDK
|
Connect an SDK
|
||||||
</TitleContainer>
|
</TitleContainer>
|
||||||
<Typography>
|
<Typography>
|
||||||
@ -92,7 +121,7 @@ export const WelcomeToProject = ({ projectId }: IWelcomeToProjectProps) => {
|
|||||||
maxWidth='200px'
|
maxWidth='200px'
|
||||||
projectId={projectId}
|
projectId={projectId}
|
||||||
Icon={Add}
|
Icon={Add}
|
||||||
disabled={true}
|
disabled={!isFirstFlagCreated}
|
||||||
permission={CREATE_FEATURE}
|
permission={CREATE_FEATURE}
|
||||||
>
|
>
|
||||||
Connect SDK
|
Connect SDK
|
||||||
@ -102,3 +131,55 @@ export const WelcomeToProject = ({ projectId }: IWelcomeToProjectProps) => {
|
|||||||
</Container>
|
</Container>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const CreateFlag = () => {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<TitleContainer>
|
||||||
|
<NeutralCircleContainer>1</NeutralCircleContainer>
|
||||||
|
Create a feature flag
|
||||||
|
</TitleContainer>
|
||||||
|
<Typography>
|
||||||
|
<div>The project currently holds no feature toggles.</div>
|
||||||
|
<div>Create a feature flag to get started.</div>
|
||||||
|
</Typography>
|
||||||
|
<FlagCreationButton />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const ExistingFlag = ({ featureId, projectId }: IExistingFlagsProps) => {
|
||||||
|
const theme = useTheme();
|
||||||
|
const { feature } = useFeature(projectId, featureId);
|
||||||
|
const { featureTypes } = useFeatureTypes();
|
||||||
|
const IconComponent = getFeatureTypeIcons(feature.type);
|
||||||
|
const typeName = featureTypes.find(
|
||||||
|
(featureType) => featureType.id === feature.type,
|
||||||
|
)?.name;
|
||||||
|
const typeTitle = `${typeName || feature.type} flag`;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<TitleContainer>
|
||||||
|
<MainCircleContainer>✓</MainCircleContainer>
|
||||||
|
Create a feature flag
|
||||||
|
</TitleContainer>
|
||||||
|
<TitleContainer>
|
||||||
|
<HtmlTooltip arrow title={typeTitle} describeChild>
|
||||||
|
<TypeCircleContainer>
|
||||||
|
<IconComponent />
|
||||||
|
</TypeCircleContainer>
|
||||||
|
</HtmlTooltip>
|
||||||
|
<StyledLink
|
||||||
|
to={`/projects/${projectId}/features/${feature.name}`}
|
||||||
|
>
|
||||||
|
{feature.name}
|
||||||
|
</StyledLink>
|
||||||
|
</TitleContainer>
|
||||||
|
<Typography>
|
||||||
|
Your project is not yet connected to any SDK. In order to start
|
||||||
|
using your feature flag connect an SDK to the project.
|
||||||
|
</Typography>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
@ -21,6 +21,9 @@ test('Show outdated SDKs and apps using them', async () => {
|
|||||||
count: 57,
|
count: 57,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
onboardingStatus: {
|
||||||
|
status: 'onboarded',
|
||||||
|
},
|
||||||
});
|
});
|
||||||
render(
|
render(
|
||||||
<Routes>
|
<Routes>
|
||||||
|
@ -24,6 +24,9 @@ const fallbackProject: IProjectOverview = {
|
|||||||
projectActivityPastWindow: 0,
|
projectActivityPastWindow: 0,
|
||||||
projectMembersAddedCurrentWindow: 0,
|
projectMembersAddedCurrentWindow: 0,
|
||||||
},
|
},
|
||||||
|
onboardingStatus: {
|
||||||
|
status: 'onboarded',
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const useProjectOverview = (id: string, options: SWRConfiguration = {}) => {
|
const useProjectOverview = (id: string, options: SWRConfiguration = {}) => {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import type { ProjectStatsSchema } from 'openapi';
|
import type { ProjectOverviewSchema, ProjectStatsSchema } from 'openapi';
|
||||||
import type { IFeatureFlagListItem } from './featureToggle';
|
import type { IFeatureFlagListItem } from './featureToggle';
|
||||||
import type { ProjectEnvironmentType } from 'component/project/Project/ProjectFeatureToggles/hooks/useEnvironmentsRef';
|
import type { ProjectEnvironmentType } from 'component/project/Project/ProjectFeatureToggles/hooks/useEnvironmentsRef';
|
||||||
import type { ProjectMode } from 'component/project/Project/hooks/useProjectEnterpriseSettingsForm';
|
import type { ProjectMode } from 'component/project/Project/hooks/useProjectEnterpriseSettingsForm';
|
||||||
@ -47,6 +47,7 @@ export interface IProjectOverview {
|
|||||||
featureLimit?: number;
|
featureLimit?: number;
|
||||||
featureNaming?: FeatureNamingType;
|
featureNaming?: FeatureNamingType;
|
||||||
archivedAt?: Date;
|
archivedAt?: Date;
|
||||||
|
onboardingStatus: ProjectOverviewSchema['onboardingStatus'];
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IProjectHealthReport extends IProject {
|
export interface IProjectHealthReport extends IProject {
|
||||||
|
@ -942,6 +942,11 @@ export * from './projectInsightsSchemaHealth';
|
|||||||
export * from './projectInsightsSchemaMembers';
|
export * from './projectInsightsSchemaMembers';
|
||||||
export * from './projectOverviewSchema';
|
export * from './projectOverviewSchema';
|
||||||
export * from './projectOverviewSchemaMode';
|
export * from './projectOverviewSchemaMode';
|
||||||
|
export * from './projectOverviewSchemaOnboardingStatus';
|
||||||
|
export * from './projectOverviewSchemaOnboardingStatusOneOf';
|
||||||
|
export * from './projectOverviewSchemaOnboardingStatusOneOfStatus';
|
||||||
|
export * from './projectOverviewSchemaOnboardingStatusOneOfThree';
|
||||||
|
export * from './projectOverviewSchemaOnboardingStatusOneOfThreeStatus';
|
||||||
export * from './projectRoleSchema';
|
export * from './projectRoleSchema';
|
||||||
export * from './projectRoleUsageSchema';
|
export * from './projectRoleUsageSchema';
|
||||||
export * from './projectSchema';
|
export * from './projectSchema';
|
||||||
|
@ -7,6 +7,7 @@ import type { ProjectEnvironmentSchema } from './projectEnvironmentSchema';
|
|||||||
import type { CreateFeatureNamingPatternSchema } from './createFeatureNamingPatternSchema';
|
import type { CreateFeatureNamingPatternSchema } from './createFeatureNamingPatternSchema';
|
||||||
import type { FeatureTypeCountSchema } from './featureTypeCountSchema';
|
import type { FeatureTypeCountSchema } from './featureTypeCountSchema';
|
||||||
import type { ProjectOverviewSchemaMode } from './projectOverviewSchemaMode';
|
import type { ProjectOverviewSchemaMode } from './projectOverviewSchemaMode';
|
||||||
|
import type { ProjectOverviewSchemaOnboardingStatus } from './projectOverviewSchemaOnboardingStatus';
|
||||||
import type { ProjectStatsSchema } from './projectStatsSchema';
|
import type { ProjectStatsSchema } from './projectStatsSchema';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -50,6 +51,8 @@ export interface ProjectOverviewSchema {
|
|||||||
mode?: ProjectOverviewSchemaMode;
|
mode?: ProjectOverviewSchemaMode;
|
||||||
/** The name of this project */
|
/** The name of this project */
|
||||||
name: string;
|
name: string;
|
||||||
|
/** The current onboarding status of the project. */
|
||||||
|
onboardingStatus: ProjectOverviewSchemaOnboardingStatus;
|
||||||
/** Project statistics */
|
/** Project statistics */
|
||||||
stats?: ProjectStatsSchema;
|
stats?: ProjectStatsSchema;
|
||||||
/**
|
/**
|
||||||
|
@ -0,0 +1,14 @@
|
|||||||
|
/**
|
||||||
|
* Generated by Orval
|
||||||
|
* Do not edit manually.
|
||||||
|
* See `gen:api` script in package.json
|
||||||
|
*/
|
||||||
|
import type { ProjectOverviewSchemaOnboardingStatusOneOf } from './projectOverviewSchemaOnboardingStatusOneOf';
|
||||||
|
import type { ProjectOverviewSchemaOnboardingStatusOneOfThree } from './projectOverviewSchemaOnboardingStatusOneOfThree';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The current onboarding status of the project.
|
||||||
|
*/
|
||||||
|
export type ProjectOverviewSchemaOnboardingStatus =
|
||||||
|
| ProjectOverviewSchemaOnboardingStatusOneOf
|
||||||
|
| ProjectOverviewSchemaOnboardingStatusOneOfThree;
|
@ -0,0 +1,10 @@
|
|||||||
|
/**
|
||||||
|
* Generated by Orval
|
||||||
|
* Do not edit manually.
|
||||||
|
* See `gen:api` script in package.json
|
||||||
|
*/
|
||||||
|
import type { ProjectOverviewSchemaOnboardingStatusOneOfStatus } from './projectOverviewSchemaOnboardingStatusOneOfStatus';
|
||||||
|
|
||||||
|
export type ProjectOverviewSchemaOnboardingStatusOneOf = {
|
||||||
|
status: ProjectOverviewSchemaOnboardingStatusOneOfStatus;
|
||||||
|
};
|
@ -0,0 +1,14 @@
|
|||||||
|
/**
|
||||||
|
* Generated by Orval
|
||||||
|
* Do not edit manually.
|
||||||
|
* See `gen:api` script in package.json
|
||||||
|
*/
|
||||||
|
|
||||||
|
export type ProjectOverviewSchemaOnboardingStatusOneOfStatus =
|
||||||
|
(typeof ProjectOverviewSchemaOnboardingStatusOneOfStatus)[keyof typeof ProjectOverviewSchemaOnboardingStatusOneOfStatus];
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-redeclare
|
||||||
|
export const ProjectOverviewSchemaOnboardingStatusOneOfStatus = {
|
||||||
|
'onboarding-started': 'onboarding-started',
|
||||||
|
onboarded: 'onboarded',
|
||||||
|
} as const;
|
@ -0,0 +1,12 @@
|
|||||||
|
/**
|
||||||
|
* Generated by Orval
|
||||||
|
* Do not edit manually.
|
||||||
|
* See `gen:api` script in package.json
|
||||||
|
*/
|
||||||
|
import type { ProjectOverviewSchemaOnboardingStatusOneOfThreeStatus } from './projectOverviewSchemaOnboardingStatusOneOfThreeStatus';
|
||||||
|
|
||||||
|
export type ProjectOverviewSchemaOnboardingStatusOneOfThree = {
|
||||||
|
/** The name of the feature flag */
|
||||||
|
feature: string;
|
||||||
|
status: ProjectOverviewSchemaOnboardingStatusOneOfThreeStatus;
|
||||||
|
};
|
@ -0,0 +1,13 @@
|
|||||||
|
/**
|
||||||
|
* Generated by Orval
|
||||||
|
* Do not edit manually.
|
||||||
|
* See `gen:api` script in package.json
|
||||||
|
*/
|
||||||
|
|
||||||
|
export type ProjectOverviewSchemaOnboardingStatusOneOfThreeStatus =
|
||||||
|
(typeof ProjectOverviewSchemaOnboardingStatusOneOfThreeStatus)[keyof typeof ProjectOverviewSchemaOnboardingStatusOneOfThreeStatus];
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-redeclare
|
||||||
|
export const ProjectOverviewSchemaOnboardingStatusOneOfThreeStatus = {
|
||||||
|
'first-flag-created': 'first-flag-created',
|
||||||
|
} as const;
|
Loading…
Reference in New Issue
Block a user