diff --git a/dashboard/src/components/Filter/CheckboxSection.tsx b/dashboard/src/components/Filter/CheckboxSection.tsx
index ef81dfc..a7aadb6 100644
--- a/dashboard/src/components/Filter/CheckboxSection.tsx
+++ b/dashboard/src/components/Filter/CheckboxSection.tsx
@@ -4,27 +4,29 @@ import { useCallback, useMemo } from 'react';
import Checkbox from '../Checkbox/Checkbox';
-type TOnClickItem = (itemIdx: number, isChecked: boolean) => void;
+type TOnClickItem = (value: string, isChecked: boolean) => void;
+
+type TItems = { [key: string]: boolean };
interface ICheckboxSectionItem {
- text: string;
+ value: string;
onClickItem: TOnClickItem;
- idx: number;
+ isSelected: boolean;
}
interface ICheckboxList {
- items: string[];
+ items: TItems;
onClickItem: TOnClickItem;
}
interface ICheckboxSubsection {
- items: string[];
+ items: TItems;
title: string;
onClickItem: TOnClickItem;
}
export interface ICheckboxSection {
- items?: string[];
+ items?: TItems;
title: string;
subtitle?: string;
subsections?: ICheckboxSubsection[];
@@ -33,26 +35,32 @@ export interface ICheckboxSection {
}
const CheckboxSectionItem = ({
- text,
+ value,
onClickItem,
- idx,
+ isSelected,
}: ICheckboxSectionItem): JSX.Element => {
const handleOnToggle = useCallback(
- (isChecked: boolean) => onClickItem(idx, isChecked),
- [idx, onClickItem],
+ (isChecked: boolean) => onClickItem(value, isChecked),
+ [value, onClickItem],
+ );
+ return (
+
);
- return ;
};
const CheckboxList = ({ items, onClickItem }: ICheckboxList): JSX.Element => {
const itemComponents = useMemo(
() =>
- items.map((text, idx) => (
+ Object.keys(items).map(key => (
)),
[items, onClickItem],
diff --git a/dashboard/src/components/Filter/stories/CheckboxSection.stories.tsx b/dashboard/src/components/Filter/stories/CheckboxSection.stories.tsx
deleted file mode 100644
index a0d6e22..0000000
--- a/dashboard/src/components/Filter/stories/CheckboxSection.stories.tsx
+++ /dev/null
@@ -1,49 +0,0 @@
-import type { Meta, StoryObj } from '@storybook/react';
-import { fn } from '@storybook/test';
-
-import CheckboxSection from '../CheckboxSection';
-
-const ActionsData = {
- onClickItem: fn(),
-};
-
-const meta: Meta = {
- title: 'Filter CheckboxSection',
- component: CheckboxSection,
- parameters: {
- layout: 'centered',
- },
- tags: ['autodocs'],
- args: {
- ...ActionsData,
- },
-};
-
-export default meta;
-type Story = StoryObj;
-
-export const Default: Story = {
- args: {
- items: ['linux-5.15.y', 'Status:failed', 'Status: Warnings'],
- title: 'Branch',
- subtitle: 'Please select one or more Branches',
- },
-};
-
-export const WithSubSections: Story = {
- args: {
- title: 'Error Summary',
- subsections: [
- {
- title: 'Errors',
- items: ['linux-5.15.y', 'Status:failed', 'Status: Warnings'],
- onClickItem: ActionsData.onClickItem,
- },
- {
- title: 'Warnings',
- items: ['linux-5.15.y', 'Status:failed', 'Status: Warnings'],
- onClickItem: ActionsData.onClickItem,
- },
- ],
- },
-};
diff --git a/dashboard/src/components/Filter/stories/FilterDrawer.stories.tsx b/dashboard/src/components/Filter/stories/FilterDrawer.stories.tsx
deleted file mode 100644
index eafbaf7..0000000
--- a/dashboard/src/components/Filter/stories/FilterDrawer.stories.tsx
+++ /dev/null
@@ -1,85 +0,0 @@
-import type { Meta, StoryObj } from '@storybook/react';
-import { fn } from '@storybook/test';
-
-import { IntlProvider } from 'react-intl';
-import { flatten } from 'flat';
-
-import { LOCALES } from '../../../locales/constants';
-
-import { messages } from '../../../locales/messages';
-
-import FilterDrawer from '../Drawer';
-
-import CheckboxSection from '../CheckboxSection';
-import TimeRangeSection from '../TimeRangeSection';
-import SummarySection from '../SummarySection';
-
-const ActionsData = {
- onRefresh: fn(),
- onCancel: fn(),
- onFilter: fn(),
-};
-
-const meta: Meta = {
- title: 'FilterDrawer',
- component: FilterDrawer,
- parameters: {
- layout: 'centered',
- },
- tags: ['autodocs'],
-};
-
-export default meta;
-type Story = StoryObj;
-
-export const Default: Story = {
- decorators: [
- (): JSX.Element => (
-
-
-
-
-
-
-
-
- ),
- ],
-};
-
-const summarySectionProps = {
- title: 'Tree',
- columns: [
- { title: 'Tree', value: 'stable-rc' },
- { title: 'Matainer', value: 'Shannon Nelson' },
- {
- title: 'Commit/tag',
- value: '5.15.150-rc1 - 3ab4d9c9e190217ee7e974c70b96795cd2f74611',
- },
- ],
-};
-
-const checkboxSectionProps = {
- items: ['linux-5.15.y', 'Status:failed', 'Status: Warnings'],
- title: 'Branch',
- subtitle: 'Please select one or more Branches',
- onClickItem: (idx: number, isChecked: boolean): void =>
- console.log(idx, isChecked),
-};
-
-const onChangeM = (e: React.FormEvent): void =>
- console.log(e.target);
-const timeRangeSectionProps = {
- title: 'Timing',
- subtitle: 'Please select a range of timing:',
- min: 0,
- max: 100,
- onMinChange: onChangeM,
- onMaxChange: onChangeM,
-};
diff --git a/dashboard/src/components/Filter/stories/TimeRangeSection.stories.tsx b/dashboard/src/components/Filter/stories/TimeRangeSection.stories.tsx
deleted file mode 100644
index ba7d99c..0000000
--- a/dashboard/src/components/Filter/stories/TimeRangeSection.stories.tsx
+++ /dev/null
@@ -1,50 +0,0 @@
-import type { Meta, StoryObj } from '@storybook/react';
-import { IntlProvider } from 'react-intl';
-import { flatten } from 'flat';
-
-import { fn } from '@storybook/test';
-
-import { LOCALES } from '../../../locales/constants';
-
-import { messages } from '../../../locales/messages';
-
-import TimeRangeSection from '../TimeRangeSection';
-
-const ActionsData = {
- onMinChange: fn(),
- onMaxChange: fn(),
-};
-
-const meta: Meta = {
- title: 'Filter TimeRangeSection',
- component: TimeRangeSection,
- parameters: {
- layout: 'centered',
- },
- tags: ['autodocs'],
- args: {
- ...ActionsData,
- },
-};
-
-export default meta;
-type Story = StoryObj;
-
-export const Default: Story = {
- args: {
- title: 'Timing',
- subtitle: 'Please select a range of timing:',
- min: 0,
- max: 10,
- },
- decorators: [
- (story): JSX.Element => (
-
- {story()}
-
- ),
- ],
-};
diff --git a/dashboard/src/routes/TreeDetails/TreeDetailsFilter.tsx b/dashboard/src/routes/TreeDetails/TreeDetailsFilter.tsx
index 206766f..94d3866 100644
--- a/dashboard/src/routes/TreeDetails/TreeDetailsFilter.tsx
+++ b/dashboard/src/routes/TreeDetails/TreeDetailsFilter.tsx
@@ -1,4 +1,4 @@
-import { useCallback, useMemo, useState } from 'react';
+import { useCallback, useMemo } from 'react';
import { useIntl } from 'react-intl';
import FilterDrawer from '@/components/Filter/Drawer';
@@ -16,107 +16,92 @@ interface ITreeDetailsFilter {
onFilter: (filter: TTreeDetailsFilter) => void;
}
+type TFilterApplied = { [key: string]: boolean };
+
const sanitizeData = (
data: TreeDetailsType | undefined,
-): [string[], string[], string[], string[], string] => {
- const validList = ['TRUE', 'FALSE'];
- const branchSet = new Set();
- const configSet = new Set();
- const archSet = new Set();
+): [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) branchSet.add(b.git_repository_branch);
- if (b.config_name) configSet.add(b.config_name);
- if (b.architecture) archSet.add(b.architecture);
+ 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;
});
- //TODO: try to avoid this set < > array thing
- return [
- validList,
- Array.from(branchSet),
- Array.from(configSet),
- Array.from(archSet),
- treeUrl,
- ];
+ return [status, branches, configs, archs, treeUrl];
};
-const getNewFilter = (
- value: T,
- isChecked: boolean,
- currentFilter: T[],
-): T[] => {
- if (isChecked) return [...currentFilter, value];
- return currentFilter.filter(item => item != value);
-};
+const getFilterListFromObj = (filterObj: TFilterApplied): string[] =>
+ Object.keys(filterObj).filter(key => filterObj[key]);
const TreeDetailsFilter = ({
data,
onFilter,
}: ITreeDetailsFilter): JSX.Element => {
const intl = useIntl();
- const [branchFilter, setBranchFilter] = useState([]);
- const [configFilter, setConfigFilter] = useState([]);
- const [archFilter, setArchFilter] = useState([]);
- const [statusFilter, setStatusFilter] = useState([]);
- const [statusList, branchList, configList, archList, treeUrl] = useMemo(
+ const [statusObj, branchObj, configObj, archObj, treeUrl] = useMemo(
() => sanitizeData(data),
[data],
);
const onClickFilterHandle = useCallback(() => {
const filter: TTreeDetailsFilter = {};
- if (statusFilter.length) filter.valid = statusFilter;
- if (branchFilter.length) filter.git_repository_branch = branchFilter;
- if (configFilter.length) filter.config_name = configFilter;
- if (archFilter.length) filter.architecture = archFilter;
+
+ filter.config_name = getFilterListFromObj(configObj);
+ filter.git_repository_branch = getFilterListFromObj(branchObj);
+ filter.architecture = getFilterListFromObj(archObj);
+ filter.valid = getFilterListFromObj(statusObj);
onFilter(filter);
- }, [statusFilter, branchFilter, configFilter, archFilter, onFilter]);
+ }, [onFilter, configObj, branchObj, archObj, statusObj]);
+
+ console.log('validObj:', statusObj);
const checkboxSectionsProps: ICheckboxSection[] = useMemo(() => {
return [
{
title: intl.formatMessage({ id: 'global.branch' }),
subtitle: intl.formatMessage({ id: 'filter.branchSubtitle' }),
- items: branchList,
- onClickItem: (idx: number, isChecked: boolean) =>
- setBranchFilter(current =>
- getNewFilter(branchList[idx], isChecked, current),
- ),
+ items: branchObj,
+ onClickItem: (branch: string, isChecked: boolean) =>
+ (branchObj[branch] = isChecked),
},
{
title: intl.formatMessage({ id: 'global.status' }),
subtitle: intl.formatMessage({ id: 'filter.statusSubtitle' }),
- items: statusList.map(v => (v === 'TRUE' ? 'valid' : 'invalid')),
- onClickItem: (idx: number, isChecked: boolean) =>
- setStatusFilter(current =>
- getNewFilter(statusList[idx], isChecked, current),
- ),
+ items: Object.keys(statusObj).reduce((acc, k) => {
+ const newKey = k == 'TRUE' ? 'valid' : 'invalid';
+ acc[newKey] = statusObj[k];
+ console.log('acc:', acc);
+ 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: configList,
- onClickItem: (idx: number, isChecked: boolean) =>
- setConfigFilter(current =>
- getNewFilter(configList[idx], isChecked, current),
- ),
+ items: configObj,
+ onClickItem: (config: string, isChecked: boolean) =>
+ (configObj[config] = isChecked),
},
{
title: intl.formatMessage({ id: 'global.architecture' }),
subtitle: intl.formatMessage({ id: 'filter.architectureSubtitle' }),
- items: archList,
- onClickItem: (idx: number, isChecked: boolean) =>
- setArchFilter(current =>
- getNewFilter(archList[idx], isChecked, current),
- ),
+ items: archObj,
+ onClickItem: (arch: string, isChecked: boolean) =>
+ (archObj[arch] = isChecked),
},
];
- }, [statusList, branchList, configList, archList, intl]);
+ }, [statusObj, branchObj, configObj, archObj, intl]);
const checkboxSectionsComponents = useMemo(
() =>