1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-09-15 17:50:48 +02:00

fix: switch to remotedata

This commit is contained in:
Thomas Heartman 2024-10-21 13:50:35 +02:00
parent 3bc9c9ae8a
commit fac7b476cf
No known key found for this signature in database
GPG Key ID: BD1F880DAED1EE78
3 changed files with 134 additions and 141 deletions

View File

@ -1,9 +1,11 @@
import type { RemoteData } from './RemoteData';
import { import {
Box, Box,
IconButton, IconButton,
ListItem, ListItem,
ListItemButton, ListItemButton,
Typography, Typography,
styled,
} from '@mui/material'; } from '@mui/material';
import { ProjectIcon } from '../common/ProjectIcon/ProjectIcon'; import { ProjectIcon } from '../common/ProjectIcon/ProjectIcon';
import LinkIcon from '@mui/icons-material/ArrowForward'; import LinkIcon from '@mui/icons-material/ArrowForward';
@ -33,8 +35,7 @@ import { ContactAdmins, DataError } from './ProjectDetailsError';
import { usePlausibleTracker } from 'hooks/usePlausibleTracker'; import { usePlausibleTracker } from 'hooks/usePlausibleTracker';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import { ActionBox } from './ActionBox'; import { ActionBox } from './ActionBox';
import { NoProjectsContactAdmin } from './NoProjectsContactAdmin'; import useLoading from 'hooks/useLoading';
import { AskOwnerToAddYouToTheirProject } from './AskOwnerToAddYouToTheirProject';
const ActiveProjectDetails: FC<{ const ActiveProjectDetails: FC<{
project: PersonalDashboardSchemaProjectsItem; project: PersonalDashboardSchemaProjectsItem;
@ -69,6 +70,10 @@ const ActiveProjectDetails: FC<{
); );
}; };
const SkeletonDiv = styled('div')({
height: '80%',
});
const ProjectListItem: FC<{ const ProjectListItem: FC<{
project: PersonalDashboardSchemaProjectsItem; project: PersonalDashboardSchemaProjectsItem;
selected: boolean; selected: boolean;
@ -122,16 +127,11 @@ const ProjectListItem: FC<{
); );
}; };
type MyProjectsState =
| 'no projects'
| 'projects'
| 'projects with error or loading';
export const MyProjects = forwardRef< export const MyProjects = forwardRef<
HTMLDivElement, HTMLDivElement,
{ {
projects: PersonalDashboardSchemaProjectsItem[]; projects: PersonalDashboardSchemaProjectsItem[];
personalDashboardProjectDetails?: PersonalDashboardProjectDetailsSchema; personalDashboardProjectDetails: RemoteData<PersonalDashboardProjectDetailsSchema>;
activeProject: string; activeProject: string;
setActiveProject: (project: string) => void; setActiveProject: (project: string) => void;
admins: PersonalDashboardSchemaAdminsItem[]; admins: PersonalDashboardSchemaAdminsItem[];
@ -147,149 +147,103 @@ export const MyProjects = forwardRef<
admins, admins,
owners, owners,
}, },
ref, // ref,
) => { ) => {
const state: MyProjectsState = projects.length const ref = useLoading(
? personalDashboardProjectDetails personalDashboardProjectDetails.state === 'loading',
? 'projects' );
: 'projects with error or loading'
: 'no projects';
const activeProjectStage = // const state: MyProjectsState = projects.length
personalDashboardProjectDetails?.onboardingStatus.status ?? // ? personalDashboardProjectDetails
'loading'; // ? 'projects'
const setupIncomplete = // : 'projects with error or loading'
activeProjectStage === 'onboarding-started' || // : 'no projects';
activeProjectStage === 'first-flag-created';
const getGridContents = (): { const getGridContents = (): {
list: ReactNode; list: ReactNode;
box1: ReactNode; box1: ReactNode;
box2: ReactNode; box2: ReactNode;
} => { } => {
switch (state) { const list = projects.length ? (
case 'no projects': <StyledList>
return { {projects.map((project) => (
list: ( <ProjectListItem
<ActionBox> key={project.id}
<Typography> project={project}
You don't currently have access to any selected={project.id === activeProject}
projects in the system. onClick={() => setActiveProject(project.id)}
</Typography> />
<Typography> ))}
To get started, you can{' '} </StyledList>
<Link to='/projects?create=true'> ) : (
create your own project <ActionBox>
</Link> <Typography>
. Alternatively, you can review the You don't currently have access to any projects in the
available projects in the system and ask the system.
owner for access. </Typography>
</Typography> <Typography>
</ActionBox> To get started, you can{' '}
), <Link to='/projects?create=true'>
box1: <NoProjectsContactAdmin admins={admins} />, create your own project
box2: ( </Link>
<AskOwnerToAddYouToTheirProject owners={owners} /> . Alternatively, you can review the available projects
), in the system and ask the owner for access.
}; </Typography>
</ActionBox>
);
case 'projects with error or loading': const [box1, box2] = (() => {
return { switch (personalDashboardProjectDetails.state) {
list: ( case 'success': {
<StyledList> const activeProjectStage =
{projects.map((project) => ( personalDashboardProjectDetails.data
<ProjectListItem .onboardingStatus.status ?? 'loading';
key={project.id} const setupIncomplete =
project={project} activeProjectStage === 'onboarding-started' ||
selected={project.id === activeProject} activeProjectStage === 'first-flag-created';
onClick={() =>
setActiveProject(project.id)
}
/>
))}
</StyledList>
),
box1: (
<div data-loading>
<DataError
data-loading
project={activeProject}
/>
</div>
),
box2: (
<div data-loading>
<ContactAdmins admins={admins} />
</div>
),
};
case 'projects': { if (activeProjectStage === 'onboarded') {
const box1 = (() => { return [
if (
activeProjectStage === 'onboarded' &&
personalDashboardProjectDetails
) {
return (
<ProjectSetupComplete <ProjectSetupComplete
project={activeProject} project={activeProject}
insights={ insights={
personalDashboardProjectDetails.insights personalDashboardProjectDetails.data
.insights
} }
/> />,
);
} else if (
activeProjectStage === 'onboarding-started' ||
activeProjectStage === 'loading'
) {
return <CreateFlag project={activeProject} />;
} else if (
activeProjectStage === 'first-flag-created'
) {
return <ExistingFlag project={activeProject} />;
}
})();
const box2 = (() => {
if (
activeProjectStage === 'onboarded' &&
personalDashboardProjectDetails
) {
return (
<LatestProjectEvents <LatestProjectEvents
latestEvents={ latestEvents={
personalDashboardProjectDetails.latestEvents personalDashboardProjectDetails.data
.latestEvents
} }
/> />,
); ];
} else if ( } else if (setupIncomplete) {
setupIncomplete || return [
activeProjectStage === 'loading' <CreateFlag project={activeProject} />,
) { <ConnectSDK project={activeProject} />,
return <ConnectSDK project={activeProject} />; ];
} else {
return [
<ExistingFlag project={activeProject} />,
<ConnectSDK project={activeProject} />,
];
} }
})(); }
case 'error':
return { return [
list: ( <DataError project={activeProject} />,
<StyledList> <ContactAdmins admins={admins} />,
{projects.map((project) => ( ];
<ProjectListItem default: // loading
key={project.id} return [
project={project} <SkeletonDiv data-loading />,
selected={project.id === activeProject} <SkeletonDiv data-loading />,
onClick={() => ];
setActiveProject(project.id)
}
/>
))}
</StyledList>
),
box1,
box2,
};
} }
} })();
return { list, box1, box2 };
}; };
const { list, box1, box2 } = getGridContents(); const { list, box1, box2 } = getGridContents();
@ -303,14 +257,19 @@ export const MyProjects = forwardRef<
<GridItem gridArea='owners'> <GridItem gridArea='owners'>
<RoleAndOwnerInfo <RoleAndOwnerInfo
roles={ roles={
personalDashboardProjectDetails?.roles.map( personalDashboardProjectDetails.state ===
(role) => role.name, 'success'
) ?? [] ? personalDashboardProjectDetails.data.roles.map(
(role) => role.name,
)
: []
} }
owners={ owners={
personalDashboardProjectDetails?.owners ?? [ personalDashboardProjectDetails.state ===
{ ownerType: 'user', name: '?' }, 'success'
] ? personalDashboardProjectDetails.data
.owners
: [{ ownerType: 'user', name: '?' }]
} }
/> />
</GridItem> </GridItem>

View File

@ -20,6 +20,7 @@ import { useAuthSplash } from 'hooks/api/getters/useAuth/useAuthSplash';
import { useDashboardState } from './useDashboardState'; import { useDashboardState } from './useDashboardState';
import { MyFlags } from './MyFlags'; import { MyFlags } from './MyFlags';
import { usePageTitle } from 'hooks/usePageTitle'; import { usePageTitle } from 'hooks/usePageTitle';
import { fromPersonalDashboardProjectDetailsOutput } from './RemoteData';
const WelcomeSection = styled('div')(({ theme }) => ({ const WelcomeSection = styled('div')(({ theme }) => ({
display: 'flex', display: 'flex',
@ -130,10 +131,14 @@ export const PersonalDashboard = () => {
splash?.personalDashboardKeyConcepts ? 'closed' : 'open', splash?.personalDashboardKeyConcepts ? 'closed' : 'open',
); );
const { personalDashboardProjectDetails, loading: detailsLoading } = const personalDashboardProjectDetails =
usePersonalDashboardProjectDetails(activeProject); fromPersonalDashboardProjectDetailsOutput(
usePersonalDashboardProjectDetails(activeProject),
);
const loadingProjectDetailsRef = useLoading(detailsLoading); const loadingProjectDetailsRef = useLoading(
personalDashboardProjectDetails.state === 'loading',
);
return ( return (
<MainContent> <MainContent>

View File

@ -0,0 +1,29 @@
import type { IPersonalDashboardProjectDetailsOutput } from 'hooks/api/getters/usePersonalDashboard/usePersonalDashboardProjectDetails';
import type { PersonalDashboardProjectDetailsSchema } from 'openapi';
type RemoteData<T> = { refetch: () => void } & (
| { state: 'error'; error: Error }
| { state: 'loading' }
| { state: 'success'; data: T }
);
export const fromPersonalDashboardProjectDetailsOutput = ({
personalDashboardProjectDetails,
error,
}: IPersonalDashboardProjectDetailsOutput): RemoteData<PersonalDashboardProjectDetailsSchema> => {
const converted = error
? {
state: 'error',
error,
}
: personalDashboardProjectDetails
? {
state: 'success',
data: personalDashboardProjectDetails,
}
: {
state: 'loading' as const,
};
return converted as RemoteData<PersonalDashboardProjectDetailsSchema>;
};