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:
parent
3bc9c9ae8a
commit
fac7b476cf
@ -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>
|
||||||
|
@ -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>
|
||||||
|
29
frontend/src/component/personalDashboard/RemoteData.ts
Normal file
29
frontend/src/component/personalDashboard/RemoteData.ts
Normal 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>;
|
||||||
|
};
|
Loading…
Reference in New Issue
Block a user