mirror of
https://github.com/Unleash/unleash.git
synced 2025-01-06 00:07:44 +01:00
256 lines
8.8 KiB
TypeScript
256 lines
8.8 KiB
TypeScript
import { useAuthUser } from 'hooks/api/getters/useAuth/useAuthUser';
|
|
import {
|
|
Accordion,
|
|
AccordionDetails,
|
|
AccordionSummary,
|
|
Button,
|
|
styled,
|
|
Typography,
|
|
} from '@mui/material';
|
|
import { WelcomeDialog } from './WelcomeDialog';
|
|
import { useLocalStorageState } from 'hooks/useLocalStorageState';
|
|
import { usePersonalDashboard } from 'hooks/api/getters/usePersonalDashboard/usePersonalDashboard';
|
|
import { usePersonalDashboardProjectDetails } from 'hooks/api/getters/usePersonalDashboard/usePersonalDashboardProjectDetails';
|
|
import { MyProjects } from './MyProjects';
|
|
import ExpandMore from '@mui/icons-material/ExpandMore';
|
|
import { usePlausibleTracker } from 'hooks/usePlausibleTracker';
|
|
import useSplashApi from 'hooks/api/actions/useSplashApi/useSplashApi';
|
|
import { useAuthSplash } from 'hooks/api/getters/useAuth/useAuthSplash';
|
|
import { useDashboardState } from './useDashboardState';
|
|
import { MyFlags } from './MyFlags';
|
|
import { usePageTitle } from 'hooks/usePageTitle';
|
|
import { fromPersonalDashboardProjectDetailsOutput } from './RemoteData';
|
|
import { useEffect } from 'react';
|
|
|
|
const WelcomeSection = styled('div')(({ theme }) => ({
|
|
display: 'flex',
|
|
justifyContent: 'space-between',
|
|
gap: theme.spacing(1),
|
|
flexFlow: 'row wrap',
|
|
alignItems: 'baseline',
|
|
}));
|
|
|
|
const ViewKeyConceptsButton = styled(Button)({
|
|
fontWeight: 'normal',
|
|
padding: 0,
|
|
margin: 0,
|
|
});
|
|
|
|
const SectionAccordion = styled(Accordion)(({ theme }) => ({
|
|
border: `1px solid ${theme.palette.divider}`,
|
|
borderRadius: theme.shape.borderRadiusMedium,
|
|
backgroundColor: theme.palette.background.paper,
|
|
boxShadow: 'none',
|
|
'& .expanded': {
|
|
'&:before': {
|
|
opacity: '0 !important',
|
|
},
|
|
},
|
|
|
|
// add a top border to the region when the accordion is collapsed.
|
|
// This retains the border between the summary and the region
|
|
// during the collapsing animation
|
|
"[aria-expanded='false']+.MuiCollapse-root .MuiAccordion-region": {
|
|
borderTop: `1px solid ${theme.palette.divider}`,
|
|
},
|
|
|
|
overflow: 'hidden',
|
|
}));
|
|
|
|
const StyledAccordionSummary = styled(AccordionSummary)(({ theme }) => ({
|
|
border: 'none',
|
|
padding: theme.spacing(2, 4),
|
|
margin: 0,
|
|
// increase specificity to override the default margin
|
|
'&>.MuiAccordionSummary-content.MuiAccordionSummary-content': {
|
|
margin: '0',
|
|
},
|
|
"&[aria-expanded='true']": {
|
|
// only add the border when it's open
|
|
borderBottom: `1px solid ${theme.palette.divider}`,
|
|
},
|
|
}));
|
|
|
|
const StyledAccordionDetails = styled(AccordionDetails)({
|
|
padding: 0,
|
|
});
|
|
|
|
const MainContent = styled('div')(({ theme }) => ({
|
|
display: 'flex',
|
|
flexDirection: 'column',
|
|
gap: theme.spacing(2),
|
|
}));
|
|
|
|
const AccordionSummaryText = styled('div')(({ theme }) => ({
|
|
display: 'flex',
|
|
flexDirection: 'column',
|
|
gap: theme.spacing(0.5),
|
|
}));
|
|
|
|
const AccordionSummaryHeader = styled('h3')(({ theme }) => ({
|
|
color: theme.palette.text.primary,
|
|
fontSize: theme.typography.body1.fontSize,
|
|
fontWeight: theme.typography.body2.fontWeight,
|
|
margin: 0,
|
|
}));
|
|
|
|
const AccordionSummarySubtitle = styled(Typography)(({ theme }) => ({
|
|
color: theme.palette.text.secondary,
|
|
fontSize: theme.typography.body2.fontSize,
|
|
fontWeight: theme.typography.body2.fontWeight,
|
|
}));
|
|
|
|
export const PersonalDashboard = () => {
|
|
const { user } = useAuthUser();
|
|
const { trackEvent } = usePlausibleTracker();
|
|
const { setSplashSeen } = useSplashApi();
|
|
const { splash } = useAuthSplash();
|
|
const name = user?.name || '';
|
|
|
|
usePageTitle(name ? `Dashboard: ${name}` : 'Dashboard');
|
|
|
|
const { personalDashboard, refetch: refetchDashboard } =
|
|
usePersonalDashboard();
|
|
|
|
const projects = personalDashboard?.projects || [];
|
|
|
|
const {
|
|
activeProject,
|
|
setActiveProject,
|
|
activeFlag,
|
|
setActiveFlag,
|
|
toggleSectionState,
|
|
expandFlags,
|
|
expandProjects,
|
|
} = useDashboardState(projects, personalDashboard?.flags ?? []);
|
|
|
|
const [welcomeDialog, setWelcomeDialog] = useLocalStorageState<
|
|
'open' | 'closed'
|
|
>(
|
|
'welcome-dialog:v1',
|
|
splash?.personalDashboardKeyConcepts ? 'closed' : 'open',
|
|
);
|
|
|
|
const personalDashboardProjectDetails =
|
|
fromPersonalDashboardProjectDetailsOutput(
|
|
usePersonalDashboardProjectDetails(activeProject),
|
|
);
|
|
|
|
useEffect(() => {
|
|
trackEvent('personal-dashboard', {
|
|
props: {
|
|
eventType: 'seen',
|
|
},
|
|
});
|
|
}, []);
|
|
|
|
return (
|
|
<MainContent>
|
|
<WelcomeSection>
|
|
<Typography component='h2' variant='h2'>
|
|
Welcome {name}
|
|
</Typography>
|
|
|
|
<ViewKeyConceptsButton
|
|
sx={{
|
|
fontWeight: 'normal',
|
|
}}
|
|
size={'small'}
|
|
variant='text'
|
|
onClick={() => {
|
|
trackEvent('personal-dashboard', {
|
|
props: {
|
|
eventType: 'open key concepts',
|
|
},
|
|
});
|
|
setWelcomeDialog('open');
|
|
}}
|
|
>
|
|
View key concepts
|
|
</ViewKeyConceptsButton>
|
|
</WelcomeSection>
|
|
|
|
<SectionAccordion
|
|
disableGutters
|
|
expanded={expandProjects ?? true}
|
|
onChange={() => toggleSectionState('projects')}
|
|
>
|
|
<StyledAccordionSummary
|
|
expandIcon={
|
|
<ExpandMore titleAccess='Toggle projects section' />
|
|
}
|
|
id='projects-panel-header'
|
|
aria-controls='projects-panel-content'
|
|
>
|
|
<AccordionSummaryText>
|
|
<AccordionSummaryHeader>
|
|
My projects
|
|
</AccordionSummaryHeader>
|
|
<AccordionSummarySubtitle>
|
|
Favorite projects, projects you own, and projects
|
|
you are a member of
|
|
</AccordionSummarySubtitle>
|
|
</AccordionSummaryText>
|
|
</StyledAccordionSummary>
|
|
<StyledAccordionDetails>
|
|
<MyProjects
|
|
owners={personalDashboard?.projectOwners ?? []}
|
|
admins={personalDashboard?.admins ?? []}
|
|
projects={projects}
|
|
activeProject={activeProject || ''}
|
|
setActiveProject={setActiveProject}
|
|
personalDashboardProjectDetails={
|
|
personalDashboardProjectDetails
|
|
}
|
|
/>
|
|
</StyledAccordionDetails>
|
|
</SectionAccordion>
|
|
|
|
<SectionAccordion
|
|
expanded={expandFlags ?? true}
|
|
onChange={() => toggleSectionState('flags')}
|
|
>
|
|
<StyledAccordionSummary
|
|
expandIcon={
|
|
<ExpandMore titleAccess='Toggle flags section' />
|
|
}
|
|
id='flags-panel-header'
|
|
aria-controls='flags-panel-content'
|
|
>
|
|
<AccordionSummaryText>
|
|
<AccordionSummaryHeader>
|
|
My feature flags
|
|
</AccordionSummaryHeader>
|
|
<AccordionSummarySubtitle>
|
|
Feature flags you have created or favorited
|
|
</AccordionSummarySubtitle>
|
|
</AccordionSummaryText>
|
|
</StyledAccordionSummary>
|
|
<StyledAccordionDetails>
|
|
<MyFlags
|
|
hasProjects={projects?.length > 0}
|
|
flagData={
|
|
personalDashboard?.flags.length
|
|
? {
|
|
state: 'flags' as const,
|
|
activeFlag,
|
|
flags: personalDashboard.flags,
|
|
}
|
|
: { state: 'no flags' as const }
|
|
}
|
|
setActiveFlag={setActiveFlag}
|
|
refetchDashboard={refetchDashboard}
|
|
/>
|
|
</StyledAccordionDetails>
|
|
</SectionAccordion>
|
|
<WelcomeDialog
|
|
open={welcomeDialog === 'open'}
|
|
onClose={() => {
|
|
setSplashSeen('personalDashboardKeyConcepts');
|
|
setWelcomeDialog('closed');
|
|
}}
|
|
/>
|
|
</MainContent>
|
|
);
|
|
};
|