Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor front end code pt 1 #8438

Merged
merged 7 commits into from
Oct 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 23 additions & 10 deletions frontend/src/component/personalDashboard/FlagMetricsChart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -121,10 +121,12 @@ const useFlagMetrics = (
environment: string | null,
hoursBack: number,
) => {
const { featureMetrics: metrics = [], loading } = useFeatureMetricsRaw(
flagName,
hoursBack,
);
const {
featureMetrics: metrics = [],
loading,
error,
} = useFeatureMetricsRaw(flagName, hoursBack);

const sortedMetrics = useMemo(() => {
return [...metrics].sort((metricA, metricB) => {
return metricA.timestamp.localeCompare(metricB.timestamp);
Expand All @@ -151,7 +153,7 @@ const useFlagMetrics = (
return createBarChartOptions(theme, hoursBack, locationSettings);
}, [theme, hoursBack, locationSettings]);

return { data, options, loading };
return { data, options, loading, error };
};

const EnvironmentSelect: FC<{
Expand Down Expand Up @@ -222,11 +224,22 @@ export const FlagMetricsChart: FC<{
const { environment, setEnvironment, activeEnvironments } =
useMetricsEnvironments(flag.project, flag.name);

const { data, options, loading } = useFlagMetrics(
flag.name,
environment,
hoursBack,
);
const {
data,
options,
loading,
error: metricsError,
} = useFlagMetrics(flag.name, environment, hoursBack);

if (metricsError) {
return (
<ChartContainer>
<PlaceholderFlagMetricsChart
label={`Couldn't fetch metrics for the current flag. This may be a transient error, or your flag name ("${flag.name}") may be causing issues.`}
/>
</ChartContainer>
);
}

const noData = data.datasets[0].data.length === 0;

Expand Down
19 changes: 18 additions & 1 deletion frontend/src/component/personalDashboard/Grid.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ export const FlagGrid = styled(ContentGrid)(
);

export const GridItem = styled('div', {
shouldForwardProp: (prop) => !['gridArea', 'sx'].includes(prop.toString()),
shouldForwardProp: (prop) => !['gridArea'].includes(prop.toString()),
})<{ gridArea: string }>(({ theme, gridArea }) => ({
padding: theme.spacing(2, 4),
maxHeight: '100%',
Expand Down Expand Up @@ -113,3 +113,20 @@ export const StyledList = styled(List)(({ theme }) => ({
maxHeight: '100%',
})({ theme }),
}));

export const StyledCardTitle = styled('div')<{ lines?: number }>(
({ theme, lines = 2 }) => ({
fontWeight: theme.typography.fontWeightRegular,
fontSize: theme.typography.body1.fontSize,
lineClamp: `${lines}`,
WebkitLineClamp: lines,
lineHeight: '1.2',
display: '-webkit-box',
boxOrient: 'vertical',
textOverflow: 'ellipsis',
overflow: 'hidden',
alignItems: 'flex-start',
WebkitBoxOrient: 'vertical',
wordBreak: 'break-word',
}),
);
180 changes: 180 additions & 0 deletions frontend/src/component/personalDashboard/MyFlags.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
import { type FC, useEffect, useRef } from 'react';
import {
ContentGridContainer,
FlagGrid,
ListItemBox,
SpacedGridItem,
StyledCardTitle,
StyledList,
listItemStyle,
} from './Grid';
import { usePlausibleTracker } from 'hooks/usePlausibleTracker';
import { getFeatureTypeIcons } from 'utils/getFeatureTypeIcons';
import {
Alert,
IconButton,
Link,
ListItem,
ListItemButton,
Typography,
styled,
} from '@mui/material';
import LinkIcon from '@mui/icons-material/ArrowForward';
import React from 'react';
import type { PersonalDashboardSchemaFlagsItem } from 'openapi';

const NoActiveFlagsInfo = styled('div')(({ theme }) => ({
display: 'flex',
flexFlow: 'column',
gap: theme.spacing(2),
}));

const FlagListItem: FC<{
flag: { name: string; project: string; type: string };
selected: boolean;
onClick: () => void;
}> = ({ flag, selected, onClick }) => {
const activeFlagRef = useRef<HTMLLIElement>(null);
const { trackEvent } = usePlausibleTracker();

useEffect(() => {
if (activeFlagRef.current) {
activeFlagRef.current.scrollIntoView({
block: 'nearest',
inline: 'start',
});
}
}, []);
const IconComponent = getFeatureTypeIcons(flag.type);
const flagLink = `projects/${flag.project}/features/${flag.name}`;
return (
<ListItem
key={flag.name}
disablePadding={true}
sx={{ mb: 1 }}
ref={selected ? activeFlagRef : null}
>
<ListItemButton
sx={listItemStyle}
selected={selected}
onClick={onClick}
>
<ListItemBox>
<IconComponent color='primary' />
<StyledCardTitle>{flag.name}</StyledCardTitle>
<IconButton
component={Link}
href={flagLink}
onClick={() => {
trackEvent('personal-dashboard', {
props: {
eventType: `Go to flag from list`,
},
});
}}
size='small'
sx={{ ml: 'auto' }}
>
<LinkIcon titleAccess={flagLink} />
</IconButton>
</ListItemBox>
</ListItemButton>
</ListItem>
);
};

type FlagData =
| {
state: 'flags';
flags: PersonalDashboardSchemaFlagsItem[];
activeFlag: PersonalDashboardSchemaFlagsItem;
}
| {
state: 'no flags';
};

type Props = {
hasProjects: boolean;
flagData: FlagData;
setActiveFlag: (flag: PersonalDashboardSchemaFlagsItem) => void;
refetchDashboard: () => void;
};

export const MyFlags: FC<Props> = ({
hasProjects,
flagData,
setActiveFlag,
refetchDashboard,
}) => {
return (
<ContentGridContainer>
<FlagGrid>
<SpacedGridItem gridArea='flags'>
{flagData.state === 'flags' ? (
<StyledList
disablePadding={true}
sx={{
height: '100%',
overflow: 'auto',
}}
>
{flagData.flags.map((flag) => (
<FlagListItem
key={flag.name}
flag={flag}
selected={
flag.name === flagData.activeFlag.name
}
onClick={() => setActiveFlag(flag)}
/>
))}
</StyledList>
) : hasProjects ? (
<NoActiveFlagsInfo>
<Typography>
You have not created or favorited any feature
flags. Once you do, they will show up here.
</Typography>
<Typography>
To create a new flag, go to one of your
projects.
</Typography>
</NoActiveFlagsInfo>
) : (
<Alert severity='info'>
You need to create or join a project to be able to
add a flag, or you must be given the rights by your
admin to add feature flags.
</Alert>
)}
</SpacedGridItem>

<SpacedGridItem gridArea='chart'>
{flagData.state === 'flags' ? (
<FlagMetricsChart
flag={flagData.activeFlag}
onArchive={refetchDashboard}
/>
) : (
<PlaceholderFlagMetricsChart
label={
'Metrics for your feature flags will be shown here'
}
/>
)}
</SpacedGridItem>
</FlagGrid>
</ContentGridContainer>
);
};

const FlagMetricsChart = React.lazy(() =>
import('./FlagMetricsChart').then((module) => ({
default: module.FlagMetricsChart,
})),
);
const PlaceholderFlagMetricsChart = React.lazy(() =>
import('./FlagMetricsChart').then((module) => ({
default: module.PlaceholderFlagMetricsChartWithWrapper,
})),
);
2 changes: 1 addition & 1 deletion frontend/src/component/personalDashboard/MyProjects.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import { ConnectSDK, CreateFlag, ExistingFlag } from './ConnectSDK';
import { LatestProjectEvents } from './LatestProjectEvents';
import { RoleAndOwnerInfo } from './RoleAndOwnerInfo';
import { forwardRef, useEffect, useRef, type FC } from 'react';
import { StyledCardTitle } from './PersonalDashboard';
import type {
PersonalDashboardProjectDetailsSchema,
PersonalDashboardSchemaAdminsItem,
Expand All @@ -28,6 +27,7 @@ import {
GridItem,
SpacedGridItem,
StyledList,
StyledCardTitle,
} from './Grid';
import { ContactAdmins, DataError } from './ProjectDetailsError';
import { usePlausibleTracker } from 'hooks/usePlausibleTracker';
Expand Down
Loading
Loading