diff --git a/frontend/src/component/personalDashboard/Grid.tsx b/frontend/src/component/personalDashboard/Grid.tsx
new file mode 100644
index 000000000000..de1ce152ecc9
--- /dev/null
+++ b/frontend/src/component/personalDashboard/Grid.tsx
@@ -0,0 +1,31 @@
+import { Box, Grid, styled } from '@mui/material';
+import type { Theme } from '@mui/material/styles/createTheme';
+
+export const ContentGrid = styled(Grid)(({ theme }) => ({
+ backgroundColor: theme.palette.background.paper,
+ borderRadius: `${theme.shape.borderRadiusLarge}px`,
+}));
+
+export const SpacedGridItem = styled(Grid)(({ theme }) => ({
+ padding: theme.spacing(4),
+ border: `0.5px solid ${theme.palette.divider}`,
+}));
+
+export const ListItemBox = styled(Box)(({ theme }) => ({
+ display: 'flex',
+ gap: theme.spacing(2),
+ alignItems: 'center',
+ width: '100%',
+}));
+
+export const listItemStyle = (theme: Theme) => ({
+ borderRadius: theme.spacing(0.5),
+ borderLeft: `${theme.spacing(0.5)} solid transparent`,
+ '&.Mui-selected': {
+ borderLeft: `${theme.spacing(0.5)} solid ${theme.palette.primary.main}`,
+ },
+ display: 'flex',
+ flexDirection: 'column',
+ alignItems: 'flex-start',
+ gap: theme.spacing(1),
+});
diff --git a/frontend/src/component/personalDashboard/MyProjects.tsx b/frontend/src/component/personalDashboard/MyProjects.tsx
new file mode 100644
index 000000000000..629ebe4941a7
--- /dev/null
+++ b/frontend/src/component/personalDashboard/MyProjects.tsx
@@ -0,0 +1,175 @@
+import {
+ Box,
+ IconButton,
+ Link,
+ List,
+ ListItem,
+ ListItemButton,
+ Typography,
+} from '@mui/material';
+import { Badge } from '../common/Badge/Badge';
+import { ProjectIcon } from '../common/ProjectIcon/ProjectIcon';
+import LinkIcon from '@mui/icons-material/Link';
+import { ProjectSetupComplete } from './ProjectSetupComplete';
+import { ConnectSDK, CreateFlag, ExistingFlag } from './ConnectSDK';
+import { LatestProjectEvents } from './LatestProjectEvents';
+import { RoleAndOwnerInfo } from './RoleAndOwnerInfo';
+import type { FC } from 'react';
+import { StyledCardTitle } from './PersonalDashboard';
+import type {
+ PersonalDashboardProjectDetailsSchema,
+ PersonalDashboardSchemaProjectsItem,
+} from '../../openapi';
+import {
+ ContentGrid,
+ ListItemBox,
+ listItemStyle,
+ SpacedGridItem,
+} from './Grid';
+
+const ActiveProjectDetails: FC<{
+ project: PersonalDashboardSchemaProjectsItem;
+}> = ({ project }) => {
+ return (
+
+
+
+ {project.featureCount}
+
+
+ flags
+
+
+
+
+ {project.memberCount}
+
+
+ members
+
+
+
+
+ {project.health}%
+
+
+ health
+
+
+
+ );
+};
+
+export const MyProjects: FC<{
+ projects: PersonalDashboardSchemaProjectsItem[];
+ personalDashboardProjectDetails?: PersonalDashboardProjectDetailsSchema;
+ activeProject: string;
+ setActiveProject: (project: string) => void;
+}> = ({
+ projects,
+ personalDashboardProjectDetails,
+ setActiveProject,
+ activeProject,
+}) => {
+ const activeProjectStage =
+ personalDashboardProjectDetails?.onboardingStatus.status ?? 'loading';
+ const setupIncomplete =
+ activeProjectStage === 'onboarding-started' ||
+ activeProjectStage === 'first-flag-created';
+
+ return (
+
+
+ My projects
+
+
+ {setupIncomplete ? (
+ Setup incomplete
+ ) : null}
+
+
+
+ {projects.map((project) => {
+ return (
+
+ setActiveProject(project.id)}
+ >
+
+
+
+ {project.name}
+
+
+
+
+
+ {project.id === activeProject ? (
+
+ ) : null}
+
+
+ );
+ })}
+
+
+
+ {activeProjectStage === 'onboarded' ? (
+
+ ) : null}
+ {activeProjectStage === 'onboarding-started' ||
+ activeProjectStage === 'loading' ? (
+
+ ) : null}
+ {activeProjectStage === 'first-flag-created' ? (
+
+ ) : null}
+
+
+ {activeProjectStage === 'onboarded' &&
+ personalDashboardProjectDetails ? (
+
+ ) : null}
+ {setupIncomplete || activeProjectStage === 'loading' ? (
+
+ ) : null}
+
+
+
+ {activeProject ? (
+
+ ) : null}
+
+
+ );
+};
diff --git a/frontend/src/component/personalDashboard/PersonalDashboard.tsx b/frontend/src/component/personalDashboard/PersonalDashboard.tsx
index 2989672b22a3..f3d8416a52fd 100644
--- a/frontend/src/component/personalDashboard/PersonalDashboard.tsx
+++ b/frontend/src/component/personalDashboard/PersonalDashboard.tsx
@@ -1,7 +1,5 @@
import { useAuthUser } from 'hooks/api/getters/useAuth/useAuthUser';
import {
- Box,
- Grid,
IconButton,
Link,
List,
@@ -10,15 +8,10 @@ import {
styled,
Typography,
} from '@mui/material';
-import type { Theme } from '@mui/material/styles/createTheme';
-import { ProjectIcon } from 'component/common/ProjectIcon/ProjectIcon';
import React, { type FC, useEffect, useState } from 'react';
import LinkIcon from '@mui/icons-material/Link';
-import { Badge } from '../common/Badge/Badge';
-import { ConnectSDK, CreateFlag, ExistingFlag } from './ConnectSDK';
import { WelcomeDialog } from './WelcomeDialog';
import { useLocalStorageState } from 'hooks/useLocalStorageState';
-import { ProjectSetupComplete } from './ProjectSetupComplete';
import { usePersonalDashboard } from 'hooks/api/getters/usePersonalDashboard/usePersonalDashboard';
import { getFeatureTypeIcons } from 'utils/getFeatureTypeIcons';
import type {
@@ -26,12 +19,17 @@ import type {
PersonalDashboardSchemaProjectsItem,
} from '../../openapi';
import { FlagExposure } from 'component/feature/FeatureView/FeatureOverview/FeatureLifecycle/FlagExposure';
-import { RoleAndOwnerInfo } from './RoleAndOwnerInfo';
-import { ContentGridNoProjects } from './ContentGridNoProjects';
-import { LatestProjectEvents } from './LatestProjectEvents';
import { usePersonalDashboardProjectDetails } from 'hooks/api/getters/usePersonalDashboard/usePersonalDashboardProjectDetails';
import HelpOutline from '@mui/icons-material/HelpOutline';
import useLoading from '../../hooks/useLoading';
+import { MyProjects } from './MyProjects';
+import {
+ ContentGrid,
+ ListItemBox,
+ listItemStyle,
+ SpacedGridItem,
+} from './Grid';
+import { ContentGridNoProjects } from './ContentGridNoProjects';
const ScreenExplanation = styled('div')(({ theme }) => ({
marginBottom: theme.spacing(4),
@@ -39,30 +37,6 @@ const ScreenExplanation = styled('div')(({ theme }) => ({
alignItems: 'center',
}));
-const ContentGrid = styled(Grid)(({ theme }) => ({
- backgroundColor: theme.palette.background.paper,
- borderRadius: `${theme.shape.borderRadiusLarge}px`,
-}));
-
-const ProjectBox = styled(Box)(({ theme }) => ({
- display: 'flex',
- gap: theme.spacing(2),
- alignItems: 'center',
- width: '100%',
-}));
-
-const projectStyle = (theme: Theme) => ({
- borderRadius: theme.spacing(0.5),
- borderLeft: `${theme.spacing(0.5)} solid transparent`,
- '&.Mui-selected': {
- borderLeft: `${theme.spacing(0.5)} solid ${theme.palette.primary.main}`,
- },
- display: 'flex',
- flexDirection: 'column',
- alignItems: 'flex-start',
- gap: theme.spacing(1),
-});
-
export const StyledCardTitle = styled('div')<{ lines?: number }>(
({ theme, lines = 2 }) => ({
fontWeight: theme.typography.fontWeightRegular,
@@ -80,56 +54,6 @@ export const StyledCardTitle = styled('div')<{ lines?: number }>(
}),
);
-const ActiveProjectDetails: FC<{
- project: PersonalDashboardSchemaProjectsItem;
-}> = ({ project }) => {
- return (
-
-
-
- {project.featureCount}
-
-
- flags
-
-
-
-
- {project.memberCount}
-
-
- members
-
-
-
-
- {project.health}%
-
-
- health
-
-
-
- );
-};
-
-const SpacedGridItem = styled(Grid)(({ theme }) => ({
- padding: theme.spacing(4),
- border: `0.5px solid ${theme.palette.divider}`,
-}));
-
-const useProjects = (projects: PersonalDashboardSchemaProjectsItem[]) => {
- const [activeProject, setActiveProject] = useState(projects[0]?.id);
-
- useEffect(() => {
- if (!activeProject && projects.length > 0) {
- setActiveProject(projects[0].id);
- }
- }, [JSON.stringify(projects)]);
-
- return { projects, activeProject, setActiveProject };
-};
-
const FlagListItem: FC<{
flag: { name: string; project: string; type: string };
selected: boolean;
@@ -139,11 +63,11 @@ const FlagListItem: FC<{
return (
-
+
{flag.name}
-
+
);
};
+const useActiveProject = (projects: PersonalDashboardSchemaProjectsItem[]) => {
+ const [activeProject, setActiveProject] = useState(projects[0]?.id);
+
+ useEffect(() => {
+ if (!activeProject && projects.length > 0) {
+ setActiveProject(projects[0].id);
+ }
+ }, [JSON.stringify(projects)]);
+
+ return [activeProject, setActiveProject] as const;
+};
+
export const PersonalDashboard = () => {
const { user } = useAuthUser();
@@ -181,32 +117,25 @@ export const PersonalDashboard = () => {
}
}, [JSON.stringify(personalDashboard?.flags)]);
- const { projects, activeProject, setActiveProject } = useProjects(
- personalDashboard?.projects || [],
- );
+ const [welcomeDialog, setWelcomeDialog] = useLocalStorageState<
+ 'open' | 'closed'
+ >('welcome-dialog:v1', 'open');
+
+ const projects = personalDashboard?.projects || [];
+ const [activeProject, setActiveProject] = useActiveProject(projects);
const { personalDashboardProjectDetails, loading: loadingDetails } =
usePersonalDashboardProjectDetails(activeProject);
- const stage =
+ const activeProjectStage =
personalDashboardProjectDetails?.onboardingStatus.status ?? 'loading';
-
- const [welcomeDialog, setWelcomeDialog] = useLocalStorageState<
- 'open' | 'closed'
- >('welcome-dialog:v1', 'open');
+ const setupIncomplete =
+ activeProjectStage === 'onboarding-started' ||
+ activeProjectStage === 'first-flag-created';
const noProjects = projects.length === 0;
- const setupIncomplete =
- personalDashboardProjectDetails?.onboardingStatus.status ===
- 'onboarding-started' ||
- personalDashboardProjectDetails?.onboardingStatus.status ===
- 'first-flag-created';
- const onboarded =
- personalDashboardProjectDetails?.onboardingStatus.status ===
- 'onboarded';
-
- const projectStageRef = useLoading(stage === 'loading');
+ const projectStageRef = useLoading(activeProjectStage === 'loading');
return (
@@ -215,13 +144,13 @@ export const PersonalDashboard = () => {
- {onboarded
+ {activeProjectStage === 'onboarded'
? 'We have gathered projects and flags you have favorited or owned'
: null}
{setupIncomplete
? 'Here are some tasks we think would be useful in order to get the most out of Unleash'
: null}
- {stage === 'loading'
+ {activeProjectStage === 'loading'
? 'We have gathered projects and flags you have favorited or owned'
: null}
@@ -241,104 +170,16 @@ export const PersonalDashboard = () => {
admins={personalDashboard.admins}
/>
) : (
-
-
- My projects
-
-
- {setupIncomplete ? (
- Setup incomplete
- ) : null}
-
-
-
- {projects.map((project) => {
- return (
-
-
- setActiveProject(project.id)
- }
- >
-
-
-
- {project.name}
-
-
-
-
-
- {project.id === activeProject ? (
-
- ) : null}
-
-
- );
- })}
-
-
-
- {stage === 'onboarded' ? (
-
- ) : null}
- {stage === 'onboarding-started' ||
- stage === 'loading' ? (
-
- ) : null}
- {stage === 'first-flag-created' ? (
-
- ) : null}
-
-
- {stage === 'onboarded' &&
- personalDashboardProjectDetails ? (
-
- ) : null}
- {setupIncomplete || stage === 'loading' ? (
-
- ) : null}
-
-
-
- {activeProject ? (
-
- ) : null}
-
-
+
)}
+
My feature flags