Skip to content

Commit

Permalink
fix: handle project fetching error (#8375)
Browse files Browse the repository at this point in the history
Work in progress
  • Loading branch information
thomasheartman authored Oct 8, 2024
1 parent 21573d3 commit 8a7bf86
Show file tree
Hide file tree
Showing 4 changed files with 235 additions and 126 deletions.
73 changes: 39 additions & 34 deletions frontend/src/component/personalDashboard/ContentGridNoProjects.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,44 @@ type Props = {
admins: PersonalDashboardSchemaAdminsItem[];
};

export const AdminListRendered: React.FC<Pick<Props, 'admins'>> = ({
admins,
}) => {
return (
<BoxMainContent>
{admins.length ? (
<>
<p>
Your Unleash administrator
{admins.length > 1 ? 's are' : ' is'}:
</p>
<AdminList>
{admins.map((admin) => {
return (
<AdminListItem key={admin.id}>
<UserAvatar
sx={{
margin: 0,
}}
user={admin}
/>
<Typography>
{admin.name ||
admin.username ||
admin.email}
</Typography>
</AdminListItem>
);
})}
</AdminList>
</>
) : (
<p>You have no Unleash administrators to contact.</p>
)}
</BoxMainContent>
);
};

export const ContentGridNoProjects: React.FC<Props> = ({ owners, admins }) => {
return (
<ContentGridContainer>
Expand Down Expand Up @@ -98,40 +136,7 @@ export const ContentGridNoProjects: React.FC<Props> = ({ owners, admins }) => {
<NeutralCircleContainer>1</NeutralCircleContainer>
Contact Unleash admin
</TitleContainer>
<BoxMainContent>
{admins.length ? (
<>
<p>
Your Unleash administrator
{admins.length > 1 ? 's are' : ' is'}:
</p>
<AdminList>
{admins.map((admin) => {
return (
<AdminListItem key={admin.id}>
<UserAvatar
sx={{
margin: 0,
}}
user={admin}
/>
<Typography>
{admin.name ||
admin.username ||
admin.email}
</Typography>
</AdminListItem>
);
})}
</AdminList>
</>
) : (
<p>
You have no Unleash administrators to
contact.
</p>
)}
</BoxMainContent>
<AdminListRendered admins={admins} />
</GridContent>
</GridItem>
<GridItem gridArea='box2'>
Expand Down
217 changes: 131 additions & 86 deletions frontend/src/component/personalDashboard/MyProjects.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,11 @@ import { ProjectSetupComplete } from './ProjectSetupComplete';
import { ConnectSDK, CreateFlag, ExistingFlag } from './ConnectSDK';
import { LatestProjectEvents } from './LatestProjectEvents';
import { RoleAndOwnerInfo } from './RoleAndOwnerInfo';
import { useEffect, useRef, type FC } from 'react';
import { forwardRef, useEffect, useRef, type FC } from 'react';
import { StyledCardTitle } from './PersonalDashboard';
import type {
PersonalDashboardProjectDetailsSchema,
PersonalDashboardSchemaAdminsItem,
PersonalDashboardSchemaProjectsItem,
} from '../../openapi';
import {
Expand All @@ -29,6 +30,7 @@ import {
GridItem,
SpacedGridItem,
} from './Grid';
import { ContactAdmins, DataError } from './ProjectDetailsError';

const ActiveProjectDetails: FC<{
project: PersonalDashboardSchemaProjectsItem;
Expand Down Expand Up @@ -108,98 +110,141 @@ const ProjectListItem: FC<{
);
};

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';
export const MyProjects = forwardRef<
HTMLDivElement,
{
projects: PersonalDashboardSchemaProjectsItem[];
personalDashboardProjectDetails?: PersonalDashboardProjectDetailsSchema;
activeProject: string;
setActiveProject: (project: string) => void;
admins: PersonalDashboardSchemaAdminsItem[];
}
>(
(
{
projects,
personalDashboardProjectDetails,
setActiveProject,
activeProject,
admins,
},
ref,
) => {
const activeProjectStage =
personalDashboardProjectDetails?.onboardingStatus.status ??
'loading';
const setupIncomplete =
activeProjectStage === 'onboarding-started' ||
activeProjectStage === 'first-flag-created';

return (
<ContentGridContainer>
<ProjectGrid>
<GridItem gridArea='title'>
<Typography variant='h3'>My projects</Typography>
</GridItem>
<GridItem
gridArea='onboarding'
sx={{
display: 'flex',
justifyContent: 'flex-end',
}}
>
{setupIncomplete ? (
<Badge color='warning'>Setup incomplete</Badge>
) : null}
</GridItem>
<SpacedGridItem gridArea='projects'>
<List
disablePadding={true}
sx={{ maxHeight: '400px', overflow: 'auto' }}
const error = personalDashboardProjectDetails === undefined;

const box1Content = () => {
if (error) {
return <DataError project={activeProject} />;
}

if (
activeProjectStage === 'onboarded' &&
personalDashboardProjectDetails
) {
return (
<ProjectSetupComplete
project={activeProject}
insights={personalDashboardProjectDetails.insights}
/>
);
} else if (
activeProjectStage === 'onboarding-started' ||
activeProjectStage === 'loading'
) {
return <CreateFlag project={activeProject} />;
} else if (activeProjectStage === 'first-flag-created') {
return <ExistingFlag project={activeProject} />;
}
};

const box2Content = () => {
if (error) {
return <ContactAdmins admins={admins} />;
}

if (
activeProjectStage === 'onboarded' &&
personalDashboardProjectDetails
) {
return (
<LatestProjectEvents
latestEvents={
personalDashboardProjectDetails.latestEvents
}
/>
);
}

if (setupIncomplete || activeProjectStage === 'loading') {
return <ConnectSDK project={activeProject} />;
}
};

return (
<ContentGridContainer ref={ref}>
<ProjectGrid>
<GridItem gridArea='title'>
<Typography variant='h3'>My projects</Typography>
</GridItem>
<GridItem
gridArea='onboarding'
sx={{
display: 'flex',
justifyContent: 'flex-end',
}}
>
{projects.map((project) => {
return (
{setupIncomplete ? (
<Badge color='warning'>Setup incomplete</Badge>
) : null}
{error ? (
<Badge color='error'>Setup state unknown</Badge>
) : null}
</GridItem>
<SpacedGridItem gridArea='projects'>
<List
disablePadding={true}
sx={{ maxHeight: '400px', overflow: 'auto' }}
>
{projects.map((project) => (
<ProjectListItem
key={project.id}
project={project}
selected={project.id === activeProject}
onClick={() => setActiveProject(project.id)}
/>
);
})}
</List>
</SpacedGridItem>
<SpacedGridItem gridArea='box1'>
{activeProjectStage === 'onboarded' &&
personalDashboardProjectDetails ? (
<ProjectSetupComplete
project={activeProject}
insights={personalDashboardProjectDetails.insights}
/>
) : null}
{activeProjectStage === 'onboarding-started' ||
activeProjectStage === 'loading' ? (
<CreateFlag project={activeProject} />
) : null}
{activeProjectStage === 'first-flag-created' ? (
<ExistingFlag project={activeProject} />
) : null}
</SpacedGridItem>
<SpacedGridItem gridArea='box2'>
{activeProjectStage === 'onboarded' &&
personalDashboardProjectDetails ? (
<LatestProjectEvents
latestEvents={
personalDashboardProjectDetails.latestEvents
}
/>
) : null}
{setupIncomplete || activeProjectStage === 'loading' ? (
<ConnectSDK project={activeProject} />
) : null}
</SpacedGridItem>
<EmptyGridItem />
<GridItem gridArea='owners'>
{personalDashboardProjectDetails ? (
))}
</List>
</SpacedGridItem>
<SpacedGridItem gridArea='box1'>
{box1Content()}
</SpacedGridItem>
<SpacedGridItem gridArea='box2'>
{box2Content()}
</SpacedGridItem>
<EmptyGridItem />
<GridItem gridArea='owners'>
<RoleAndOwnerInfo
roles={personalDashboardProjectDetails.roles.map(
(role) => role.name,
)}
owners={personalDashboardProjectDetails.owners}
roles={
personalDashboardProjectDetails?.roles.map(
(role) => role.name,
) ?? []
}
owners={
personalDashboardProjectDetails?.owners ?? [
{ ownerType: 'user', name: '?' },
]
}
/>
) : null}
</GridItem>
</ProjectGrid>
</ContentGridContainer>
);
};
</GridItem>
</ProjectGrid>
</ContentGridContainer>
);
},
);
17 changes: 11 additions & 6 deletions frontend/src/component/personalDashboard/PersonalDashboard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ export const StyledCardTitle = styled('div')<{ lines?: number }>(
wordBreak: 'break-word',
}),
);

const FlagListItem: FC<{
flag: { name: string; project: string; type: string };
selected: boolean;
Expand Down Expand Up @@ -167,7 +166,6 @@ const useDashboardState = (
setActiveProject,
};
};

export const PersonalDashboard = () => {
const { user } = useAuthUser();

Expand All @@ -188,8 +186,11 @@ export const PersonalDashboard = () => {
'open' | 'closed'
>('welcome-dialog:v1', 'open');

const { personalDashboardProjectDetails, loading: loadingDetails } =
usePersonalDashboardProjectDetails(activeProject);
const {
personalDashboardProjectDetails,
loading: loadingDetails,
error: detailsError,
} = usePersonalDashboardProjectDetails(activeProject);

const activeProjectStage =
personalDashboardProjectDetails?.onboardingStatus.status ?? 'loading';
Expand All @@ -199,10 +200,12 @@ export const PersonalDashboard = () => {

const noProjects = projects.length === 0;

const projectStageRef = useLoading(activeProjectStage === 'loading');
const projectStageRef = useLoading(
!detailsError && activeProjectStage === 'loading',
);

return (
<div ref={projectStageRef}>
<div>
<Typography component='h2' variant='h2'>
Welcome {name}
</Typography>
Expand Down Expand Up @@ -235,6 +238,8 @@ export const PersonalDashboard = () => {
/>
) : (
<MyProjects
admins={personalDashboard?.admins ?? []}
ref={projectStageRef}
projects={projects}
activeProject={activeProject || ''}
setActiveProject={setActiveProject}
Expand Down
Loading

0 comments on commit 8a7bf86

Please sign in to comment.