Skip to content

Commit

Permalink
feat: add TreeDetailsFilter drawer on TreeDetails page
Browse files Browse the repository at this point in the history
  • Loading branch information
lfjnascimento committed Jul 19, 2024
1 parent dbcd868 commit d69a9e7
Show file tree
Hide file tree
Showing 4 changed files with 174 additions and 16 deletions.
16 changes: 13 additions & 3 deletions dashboard/src/locales/messages/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ export const messages = {
filters: 'Filters',
seconds: 'sec',
successful: 'Successful',
architecture: 'Architecture',
branch: 'Branch',
configs: 'Configs',
status: 'Status',
timing: 'Timing',
},
routes: {
deviceMonitor: 'Devices',
Expand Down Expand Up @@ -45,11 +50,16 @@ export const messages = {
tree: 'Tree',
},
filter: {
min: 'Min',
max: 'Max',
architectureSubtitle: 'Please select one or more Architectures:',
branchSubtitle: 'Please select one or more Branches:',
configsSubtitle: 'Please select one or more configs:',
filtering: 'Filtering',
treeURL: 'Tree URL',
max: 'Max',
min: 'Min',
refresh: 'Refresh',
statusSubtitle: 'Please select one or more Status:',
treeURL: 'Tree URL',
timingSubtitle: 'Please select a range of timing:',
},
},
};
33 changes: 20 additions & 13 deletions dashboard/src/routes/TreeDetails/TreeDetails.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
import { useParams } from 'react-router-dom';

import { useEffect, useState } from 'react';
import { useEffect, useState, useRef } from 'react';

import { FormattedMessage } from 'react-intl';

import { MdExpandMore } from 'react-icons/md';

import TreeDetailsTab from '@/components/Tabs/TreeDetailsTab';
import ButtonWithIcon from '@/components/Button/ButtonWithIcon';
import { useTreeDetails } from '@/api/TreeDetails';

import TreeDetailsTab from '@/components/Tabs/TreeDetailsTab';
import { IListingItem } from '@/components/ListingItem/ListingItem';
import { ISummaryItem } from '@/components/Summary/Summary';
import { Results } from '@/types/tree/TreeDetails';
import { AccordionItemBuildsTrigger } from '@/components/Accordion/Accordion';
import {
Results,
TTreeDetailsFilter,
TreeDetails as TreeDetailsType,
} from '@/types/tree/TreeDetails';

import TreeDetailsFilter from './TreeDetailsFilter';

export interface ITreeDetails {
archs: ISummaryItem[];
Expand All @@ -24,9 +24,16 @@ export interface ITreeDetails {

const TreeDetails = (): JSX.Element => {
const { treeId } = useParams();
const { data } = useTreeDetails(treeId ?? '');
const [filter, setFilter] = useState<
TTreeDetailsFilter | Record<string, never>
>({});
const { data } = useTreeDetails(treeId ?? '', filter);

const [treeDetailsData, setTreeDetailsData] = useState<ITreeDetails>();
const initialDataRef = useRef<TreeDetailsType | undefined>();
if (!initialDataRef.current) {
initialDataRef.current = data;
}

useEffect(() => {
if (data) {
Expand Down Expand Up @@ -75,9 +82,9 @@ const TreeDetails = (): JSX.Element => {
<div className="flex flex-col pt-8">
<div className="flex flex-col pb-2">
<div className="flex justify-end">
<ButtonWithIcon
icon={<MdExpandMore />}
label={<FormattedMessage id="global.filters" />}
<TreeDetailsFilter
data={initialDataRef.current}
onFilter={setFilter}
/>
</div>
<TreeDetailsTab treeDetailsData={treeDetailsData} />
Expand Down
132 changes: 132 additions & 0 deletions dashboard/src/routes/TreeDetails/TreeDetailsFilter.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
import { useCallback, useMemo } from 'react';
import { useIntl } from 'react-intl';

import FilterDrawer from '@/components/Filter/Drawer';
import FilterSummarySection from '@/components/Filter/SummarySection';
import FilterCheckboxSection, {
ICheckboxSection,
} from '@/components/Filter/CheckboxSection';
import {
TreeDetails as TreeDetailsType,
TTreeDetailsFilter,
} from '@/types/tree/TreeDetails';

interface ITreeDetailsFilter {
data?: TreeDetailsType;
onFilter: (filter: TTreeDetailsFilter) => void;
}

type TFilterApplied = { [key: string]: boolean };

const sanitizeData = (
data: TreeDetailsType | undefined,
): [TFilterApplied, TFilterApplied, TFilterApplied, TFilterApplied, string] => {
const status = { TRUE: false, FALSE: false };
const branches: TFilterApplied = {};
const configs: TFilterApplied = {};
const archs: TFilterApplied = {};
let treeUrl = '';

if (data)
data.builds.forEach(b => {
if (b.git_repository_branch) branches[b.git_repository_branch] = false;
if (b.config_name) configs[b.config_name] = false;
if (b.architecture) archs[b.architecture] = false;
if (!treeUrl && b.git_repository_url) treeUrl = b.git_repository_url;
});

return [status, branches, configs, archs, treeUrl];
};

const getFilterListFromObj = (filterObj: TFilterApplied): string[] =>
Object.keys(filterObj).filter(key => filterObj[key]);

const TreeDetailsFilter = ({
data,
onFilter,
}: ITreeDetailsFilter): JSX.Element => {
const intl = useIntl();

const [statusObj, branchObj, configObj, archObj, treeUrl] = useMemo(
() => sanitizeData(data),
[data],
);

const onClickFilterHandle = useCallback(() => {
const filter: TTreeDetailsFilter = {};

filter.config_name = getFilterListFromObj(configObj);
filter.git_repository_branch = getFilterListFromObj(branchObj);
filter.architecture = getFilterListFromObj(archObj);
filter.valid = getFilterListFromObj(statusObj);

onFilter(filter);
}, [onFilter, configObj, branchObj, archObj, statusObj]);

const checkboxSectionsProps: ICheckboxSection[] = useMemo(() => {
return [
{
title: intl.formatMessage({ id: 'global.branch' }),
subtitle: intl.formatMessage({ id: 'filter.branchSubtitle' }),
items: branchObj,
onClickItem: (branch: string, isChecked: boolean) =>
(branchObj[branch] = isChecked),
},
{
title: intl.formatMessage({ id: 'global.status' }),
subtitle: intl.formatMessage({ id: 'filter.statusSubtitle' }),
items: Object.keys(statusObj).reduce((acc, k) => {
const newKey = k == 'TRUE' ? 'valid' : 'invalid';
acc[newKey] = statusObj[k];
return acc;
}, {} as TFilterApplied),
onClickItem: (status: string, isChecked: boolean) =>
(statusObj[status == 'valid' ? 'TRUE' : 'FALSE'] = isChecked),
},
{
title: intl.formatMessage({ id: 'global.configs' }),
subtitle: intl.formatMessage({ id: 'filter.configsSubtitle' }),
items: configObj,
onClickItem: (config: string, isChecked: boolean) =>
(configObj[config] = isChecked),
},
{
title: intl.formatMessage({ id: 'global.architecture' }),
subtitle: intl.formatMessage({ id: 'filter.architectureSubtitle' }),
items: archObj,
onClickItem: (arch: string, isChecked: boolean) =>
(archObj[arch] = isChecked),
},
];
}, [statusObj, branchObj, configObj, archObj, intl]);

const checkboxSectionsComponents = useMemo(
() =>
checkboxSectionsProps.map(props => (
<FilterCheckboxSection key={props.title} {...props} />
)),
[checkboxSectionsProps],
);

return (
<FilterDrawer treeURL={treeUrl} onFilter={onClickFilterHandle}>
<FilterSummarySection {...summarySectionProps} />
{checkboxSectionsComponents}
</FilterDrawer>
);
};

export default TreeDetailsFilter;

const summarySectionProps = {
title: 'Tree',
columns: [
{ title: 'Tree', value: 'stable-rc' },
{ title: 'Matainer', value: '' },
{ title: 'Estimate to complete', value: '' },
{
title: 'Commit/tag',
value: '5.15.150-rc1 - 3ab4d9c9e190217ee7e974c70b96795cd2f74611',
},
],
};
9 changes: 9 additions & 0 deletions dashboard/src/types/tree/TreeDetails.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,12 @@ export type Results = {
invalid: number;
null: number;
};
export interface TTreeDetailsFilter
extends Partial<{
[K in keyof Omit<
TreeDetailsBuild,
'test_status' | 'misc' | 'valid'
>]: TreeDetailsBuild[K][];
}> {
valid?: string[];
}

0 comments on commit d69a9e7

Please sign in to comment.