Skip to content

Commit

Permalink
fix: Project select bug with duplicate values (#6405)
Browse files Browse the repository at this point in the history
Project select fix for Executive Dashboard and Playground

Extract the select to it's own component and move to `common`
Re-use for both Dashboard and Playground
Adds the id in parenthesis when there are duplicate names

<img width="1406" alt="Screenshot 2024-03-01 at 12 04 22"
src="https://github.com/Unleash/unleash/assets/104830839/379ea11f-d627-493e-8088-a739d58fba61">
<img width="1434" alt="Screenshot 2024-03-01 at 12 36 46"
src="https://github.com/Unleash/unleash/assets/104830839/9c5cf863-002c-4630-ac3a-4a869303a308">

---------

Signed-off-by: andreas-unleash <[email protected]>
  • Loading branch information
andreas-unleash authored Mar 1, 2024
1 parent a4a604a commit 7b67f21
Show file tree
Hide file tree
Showing 5 changed files with 198 additions and 214 deletions.
112 changes: 112 additions & 0 deletions frontend/src/component/common/ProjectSelect/ProjectSelect.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
import { ComponentProps, Dispatch, SetStateAction, VFC } from 'react';
import { Autocomplete, SxProps, TextField } from '@mui/material';
import { renderOption } from 'component/playground/Playground/PlaygroundForm/renderOption';
import useProjects from 'hooks/api/getters/useProjects/useProjects';

interface IOption {
label: string;
id: string;
}

export const allOption = { label: 'ALL', id: '*' };

interface IProjectSelectProps {
selectedProjects: string[];
onChange: Dispatch<SetStateAction<string[]>>;
dataTestId?: string;
sx?: SxProps;
disabled?: boolean;
}

function findAllIndexes(arr: string[], name: string): number[] {
const indexes: number[] = [];
arr.forEach((currentValue, index) => {
if (currentValue === name) {
indexes.push(index);
}
});
return indexes;
}

export const ProjectSelect: VFC<IProjectSelectProps> = ({
selectedProjects,
onChange,
dataTestId,
sx,
disabled,
}) => {
const { projects: availableProjects } = useProjects();

const projectNames = availableProjects.map(({ name }) => name);

const projectsOptions = [
allOption,
...availableProjects.map(({ name, id }) => {
const indexes = findAllIndexes(projectNames, name);
const isDuplicate = indexes.length > 1;

return {
label: isDuplicate ? `${name} - (${id})` : name,
id,
};
}),
];

const isAllProjects =
selectedProjects &&
(selectedProjects.length === 0 ||
(selectedProjects.length === 1 && selectedProjects[0] === '*'));

const onProjectsChange: ComponentProps<typeof Autocomplete>['onChange'] = (
event,
value,
reason,
) => {
const newProjects = value as IOption | IOption[];
if (reason === 'clear' || newProjects === null) {
return onChange([allOption.id]);
}
if (Array.isArray(newProjects)) {
if (newProjects.length === 0) {
return onChange([allOption.id]);
}
if (
newProjects.find(({ id }) => id === allOption.id) !== undefined
) {
return onChange([allOption.id]);
}
return onChange(newProjects.map(({ id }) => id));
}
if (newProjects.id === allOption.id) {
return onChange([allOption.id]);
}

return onChange([newProjects.id]);
};

return (
<Autocomplete
disablePortal
id='projects'
limitTags={3}
multiple={!isAllProjects}
options={projectsOptions}
sx={sx}
renderInput={(params) => <TextField {...params} label='Projects' />}
renderOption={renderOption}
getOptionLabel={({ label }) => label}
disableCloseOnSelect
size='small'
disabled={disabled}
value={
isAllProjects
? allOption
: projectsOptions.filter(({ id }) =>
selectedProjects.includes(id),
)
}
onChange={onProjectsChange}
data-testid={dataTestId ? dataTestId : 'PROJECT_SELECT'}
/>
);
};
37 changes: 34 additions & 3 deletions frontend/src/component/executiveDashboard/ExecutiveDashboard.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
import { useMemo, useState, VFC } from 'react';
import { Box, styled, useMediaQuery, useTheme } from '@mui/material';
import {
Box,
styled,
Typography,
useMediaQuery,
useTheme,
} from '@mui/material';
import { UsersChart } from './UsersChart/UsersChart';
import { FlagsChart } from './FlagsChart/FlagsChart';
import { useExecutiveDashboard } from 'hooks/api/getters/useExecutiveSummary/useExecutiveSummary';
Expand All @@ -10,7 +16,10 @@ import { FlagsProjectChart } from './FlagsProjectChart/FlagsProjectChart';
import { ProjectHealthChart } from './ProjectHealthChart/ProjectHealthChart';
import { TimeToProductionChart } from './TimeToProductionChart/TimeToProductionChart';
import { TimeToProduction } from './TimeToProduction/TimeToProduction';
import { ProjectSelect, allOption } from './ProjectSelect/ProjectSelect';
import {
ProjectSelect,
allOption,
} from '../common/ProjectSelect/ProjectSelect';
import { MetricsSummaryChart } from './MetricsSummaryChart/MetricsSummaryChart';
import {
ExecutiveSummarySchemaMetricsSummaryTrendsItem,
Expand All @@ -26,6 +35,18 @@ const StyledGrid = styled(Box)(({ theme }) => ({
gap: theme.spacing(2),
}));

const StyledBox = styled(Box)(({ theme }) => ({
marginBottom: theme.spacing(4),
marginTop: theme.spacing(4),
[theme.breakpoints.down('lg')]: {
width: '100%',
marginLeft: 0,
},
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
}));

const useDashboardGrid = () => {
const theme = useTheme();
const isMediumScreen = useMediaQuery(theme.breakpoints.down('lg'));
Expand Down Expand Up @@ -153,7 +174,17 @@ export const ExecutiveDashboard: VFC = () => {
/>
</Widget>
</StyledGrid>
<ProjectSelect selectedProjects={projects} onChange={setProjects} />
<StyledBox>
<Typography variant='h2' component='span'>
Insights per project
</Typography>
<ProjectSelect
selectedProjects={projects}
onChange={setProjects}
dataTestId={'DASHBOARD_PROJECT_SELECT'}
sx={{ flex: 1, maxWidth: '360px' }}
/>
</StyledBox>
<StyledGrid>
<Widget
title='Number of flags per project'
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useMemo } from 'react';
import { allOption } from '../ProjectSelect/ProjectSelect';
import { allOption } from 'component/common/ProjectSelect/ProjectSelect';

export const useFilteredTrends = <
T extends {
Expand Down
Loading

0 comments on commit 7b67f21

Please sign in to comment.