diff --git a/frontend/src/component/personalDashboard/MyProjects.tsx b/frontend/src/component/personalDashboard/MyProjects.tsx index 090b64d5c396..b111244bf4f0 100644 --- a/frontend/src/component/personalDashboard/MyProjects.tsx +++ b/frontend/src/component/personalDashboard/MyProjects.tsx @@ -137,8 +137,12 @@ export const MyProjects: FC<{ - {activeProjectStage === 'onboarded' ? ( - + {activeProjectStage === 'onboarded' && + personalDashboardProjectDetails ? ( + ) : null} {activeProjectStage === 'onboarding-started' || activeProjectStage === 'loading' ? ( diff --git a/frontend/src/component/personalDashboard/ProjectSetupComplete.tsx b/frontend/src/component/personalDashboard/ProjectSetupComplete.tsx index b656bd4da37b..b20fcf413687 100644 --- a/frontend/src/component/personalDashboard/ProjectSetupComplete.tsx +++ b/frontend/src/component/personalDashboard/ProjectSetupComplete.tsx @@ -2,6 +2,7 @@ import { styled, Typography } from '@mui/material'; import type { FC } from 'react'; import { Link } from 'react-router-dom'; import Lightbulb from '@mui/icons-material/LightbulbOutlined'; +import type { PersonalDashboardProjectDetailsSchemaInsights } from '../../openapi'; const TitleContainer = styled('div')(({ theme }) => ({ display: 'flex', @@ -18,18 +19,17 @@ const ActionBox = styled('article')(({ theme }) => ({ flexDirection: 'column', })); -export const ProjectSetupComplete: FC<{ project: string }> = ({ project }) => { +const PercentageScore = styled('span')(({ theme }) => ({ + color: theme.palette.primary.main, +})); + +const ConnectedSdkProject: FC<{ project: string }> = ({ project }) => { return ( - - - -

Project Insight

-
+ <> This project already has connected SDKs and existing feature flags. - Create a new feature flag @@ -40,6 +40,91 @@ export const ProjectSetupComplete: FC<{ project: string }> = ({ project }) => { {' '} to work with existing flags + + ); +}; + +type HeathTrend = 'consistent' | 'improved' | 'declined' | 'unknown'; + +const determineProjectHealthTrend = ( + insights: PersonalDashboardProjectDetailsSchemaInsights, +) => { + let trend: HeathTrend = 'unknown'; + if ( + insights.avgHealthCurrentWindow !== null && + insights.avgHealthPastWindow !== null + ) { + if (insights.avgHealthCurrentWindow > insights.avgHealthPastWindow) { + trend = 'improved'; + } else if ( + insights.avgHealthCurrentWindow < insights.avgHealthPastWindow + ) { + trend = 'declined'; + } else if ( + insights.avgHealthPastWindow === insights.avgHealthCurrentWindow + ) { + trend = 'consistent'; + } + } + return trend; +}; + +export const ProjectSetupComplete: FC<{ + project: string; + insights: PersonalDashboardProjectDetailsSchemaInsights; +}> = ({ project, insights }) => { + const projectHealthTrend = determineProjectHealthTrend(insights); + + return ( + + + +

Project Insight

+
+ + {projectHealthTrend === 'unknown' ? ( + + ) : null} + {projectHealthTrend === 'improved' ? ( + + On average, your project health went up from{' '} + + {insights.avgHealthPastWindow}% + {' '} + to{' '} + + {insights.avgHealthCurrentWindow}% + {' '} + during the last 4 weeks. + + ) : null} + {projectHealthTrend === 'declined' ? ( + + On average, your project health went down from{' '} + + {insights.avgHealthPastWindow}% + {' '} + to{' '} + + {insights.avgHealthCurrentWindow}% + {' '} + during the last 4 weeks. + + ) : null} + {projectHealthTrend === 'consistent' ? ( + + On average, your project health has remained at{' '} + + {insights.avgHealthCurrentWindow}% + {' '} + during the last 4 weeks. + + ) : null} + {projectHealthTrend !== 'unknown' ? ( + + View more insights + + ) : null}
); }; diff --git a/frontend/src/openapi/models/index.ts b/frontend/src/openapi/models/index.ts index dda12b8c3067..997af9ecd04d 100644 --- a/frontend/src/openapi/models/index.ts +++ b/frontend/src/openapi/models/index.ts @@ -904,6 +904,7 @@ export * from './patchesSchema'; export * from './patsSchema'; export * from './permissionSchema'; export * from './personalDashboardProjectDetailsSchema'; +export * from './personalDashboardProjectDetailsSchemaInsights'; export * from './personalDashboardProjectDetailsSchemaLatestEventsItem'; export * from './personalDashboardProjectDetailsSchemaOnboardingStatus'; export * from './personalDashboardProjectDetailsSchemaOnboardingStatusOneOf'; @@ -1144,6 +1145,10 @@ export * from './signalEndpointSignalsSchema'; export * from './signalEndpointTokenSchema'; export * from './signalEndpointTokensSchema'; export * from './signalEndpointsSchema'; +export * from './signalQueryResponseSchema'; +export * from './signalQuerySignalSchema'; +export * from './signalQuerySignalSchemaPayload'; +export * from './signalQuerySignalSchemaSource'; export * from './signalSchema'; export * from './signalSchemaPayload'; export * from './signalSchemaSource'; diff --git a/frontend/src/openapi/models/personalDashboardProjectDetailsSchema.ts b/frontend/src/openapi/models/personalDashboardProjectDetailsSchema.ts index eea01840a2f8..b74e064d4dad 100644 --- a/frontend/src/openapi/models/personalDashboardProjectDetailsSchema.ts +++ b/frontend/src/openapi/models/personalDashboardProjectDetailsSchema.ts @@ -3,6 +3,7 @@ * Do not edit manually. * See `gen:api` script in package.json */ +import type { PersonalDashboardProjectDetailsSchemaInsights } from './personalDashboardProjectDetailsSchemaInsights'; import type { PersonalDashboardProjectDetailsSchemaLatestEventsItem } from './personalDashboardProjectDetailsSchemaLatestEventsItem'; import type { PersonalDashboardProjectDetailsSchemaOnboardingStatus } from './personalDashboardProjectDetailsSchemaOnboardingStatus'; import type { PersonalDashboardProjectDetailsSchemaOwners } from './personalDashboardProjectDetailsSchemaOwners'; @@ -12,6 +13,8 @@ import type { PersonalDashboardProjectDetailsSchemaRolesItem } from './personalD * Project details in personal dashboard */ export interface PersonalDashboardProjectDetailsSchema { + /** Insights for the project */ + insights: PersonalDashboardProjectDetailsSchemaInsights; /** The latest events for the project. */ latestEvents: PersonalDashboardProjectDetailsSchemaLatestEventsItem[]; /** The current onboarding status of the project. */ diff --git a/frontend/src/openapi/models/personalDashboardProjectDetailsSchemaInsights.ts b/frontend/src/openapi/models/personalDashboardProjectDetailsSchemaInsights.ts new file mode 100644 index 000000000000..d081685ecfa5 --- /dev/null +++ b/frontend/src/openapi/models/personalDashboardProjectDetailsSchemaInsights.ts @@ -0,0 +1,21 @@ +/** + * Generated by Orval + * Do not edit manually. + * See `gen:api` script in package.json + */ + +/** + * Insights for the project + */ +export type PersonalDashboardProjectDetailsSchemaInsights = { + /** + * The average health score in the current window of the last 4 weeks + * @nullable + */ + avgHealthCurrentWindow: number | null; + /** + * The average health score in the previous 4 weeks before the current window + * @nullable + */ + avgHealthPastWindow: number | null; +}; diff --git a/frontend/src/openapi/models/personalDashboardSchemaAdminsItem.ts b/frontend/src/openapi/models/personalDashboardSchemaAdminsItem.ts index da0c317e9f27..51abb597209b 100644 --- a/frontend/src/openapi/models/personalDashboardSchemaAdminsItem.ts +++ b/frontend/src/openapi/models/personalDashboardSchemaAdminsItem.ts @@ -5,11 +5,9 @@ */ export type PersonalDashboardSchemaAdminsItem = { - /** @nullable */ email?: string; /** The user ID. */ id: number; - /** @nullable */ imageUrl?: string; /** The user's name. */ name?: string; diff --git a/frontend/src/openapi/models/signalQueryResponseSchema.ts b/frontend/src/openapi/models/signalQueryResponseSchema.ts new file mode 100644 index 000000000000..0d14dd0295a2 --- /dev/null +++ b/frontend/src/openapi/models/signalQueryResponseSchema.ts @@ -0,0 +1,19 @@ +/** + * Generated by Orval + * Do not edit manually. + * See `gen:api` script in package.json + */ +import type { SignalQuerySignalSchema } from './signalQuerySignalSchema'; + +/** + * A list of signals that have been registered by the system + */ +export interface SignalQueryResponseSchema { + /** The list of signals */ + signals: SignalQuerySignalSchema[]; + /** + * The total count of signals + * @minimum 0 + */ + total: number; +} diff --git a/frontend/src/openapi/models/signalQuerySignalSchema.ts b/frontend/src/openapi/models/signalQuerySignalSchema.ts new file mode 100644 index 000000000000..e0bc1c1bcf0f --- /dev/null +++ b/frontend/src/openapi/models/signalQuerySignalSchema.ts @@ -0,0 +1,41 @@ +/** + * Generated by Orval + * Do not edit manually. + * See `gen:api` script in package.json + */ +import type { SignalQuerySignalSchemaPayload } from './signalQuerySignalSchemaPayload'; +import type { SignalQuerySignalSchemaSource } from './signalQuerySignalSchemaSource'; + +/** + * An object describing a signal enriched with source data. + */ +export interface SignalQuerySignalSchema { + /** The date and time of when the signal was created. */ + createdAt: string; + /** + * The signal's ID. Signal IDs are incrementing integers. In other words, a more recently created signal will always have a higher ID than an older one. + * @minimum 1 + */ + id: number; + /** The payload of the signal. */ + payload?: SignalQuerySignalSchemaPayload; + /** The signal source type. Should be used along with `sourceId` to uniquely identify the resource that created this signal. */ + source: SignalQuerySignalSchemaSource; + /** + * A more detailed description of the source that registered this signal. + * @nullable + */ + sourceDescription?: string | null; + /** The ID of the source that created this signal. Should be used along with `source` to uniquely identify the resource that created this signal. */ + sourceId: number; + /** + * The name of the source that registered this signal. + * @nullable + */ + sourceName?: string | null; + /** + * The name of the token used to register this signal. + * @nullable + */ + tokenName?: string | null; +} diff --git a/frontend/src/openapi/models/signalQuerySignalSchemaPayload.ts b/frontend/src/openapi/models/signalQuerySignalSchemaPayload.ts new file mode 100644 index 000000000000..93481236f465 --- /dev/null +++ b/frontend/src/openapi/models/signalQuerySignalSchemaPayload.ts @@ -0,0 +1,10 @@ +/** + * Generated by Orval + * Do not edit manually. + * See `gen:api` script in package.json + */ + +/** + * The payload of the signal. + */ +export type SignalQuerySignalSchemaPayload = { [key: string]: unknown }; diff --git a/frontend/src/openapi/models/signalQuerySignalSchemaSource.ts b/frontend/src/openapi/models/signalQuerySignalSchemaSource.ts new file mode 100644 index 000000000000..ded90885e2f3 --- /dev/null +++ b/frontend/src/openapi/models/signalQuerySignalSchemaSource.ts @@ -0,0 +1,16 @@ +/** + * Generated by Orval + * Do not edit manually. + * See `gen:api` script in package.json + */ + +/** + * The signal source type. Should be used along with `sourceId` to uniquely identify the resource that created this signal. + */ +export type SignalQuerySignalSchemaSource = + (typeof SignalQuerySignalSchemaSource)[keyof typeof SignalQuerySignalSchemaSource]; + +// eslint-disable-next-line @typescript-eslint/no-redeclare +export const SignalQuerySignalSchemaSource = { + 'signal-endpoint': 'signal-endpoint', +} as const;