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

Combobox component replacement #2319

Draft
wants to merge 31 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
54443eb
replace combobox instances with new components
manV Sep 23, 2024
271af41
update account name list combobox
manV Sep 24, 2024
e464d53
update cloud account combobox
manV Sep 24, 2024
c8deae4
update vulnerability scan list filter comboboxes
manV Sep 24, 2024
d726c1b
update vulnerability scan results filter comboboxes
manV Sep 24, 2024
96c2fbf
combobox replacement on unique vulnerabilities filters
manV Sep 25, 2024
9b4c5be
combobox replacement rutime BOM table filters
manV Sep 25, 2024
703c504
combobox replacement for most exploitable vulnerabilities filter
manV Sep 25, 2024
7a4b295
combobox replacement for pod table filters
manV Sep 25, 2024
0bac3e2
combobox replacement for kubernetes table filter
manV Sep 25, 2024
e2857d3
combobox replacement for hosts table
manV Sep 25, 2024
f5ccbd1
combobox replacement for container table filters
manV Sep 25, 2024
b8282ff
combobox replacement for cloud resources table
manV Sep 25, 2024
9bb6676
combobox replacement for threatgraph filters
manV Sep 25, 2024
75d0080
combobox replacement for vulnerability feeds filter
manV Sep 25, 2024
5a03ea0
combobox replacement for secret feeds filter
manV Sep 25, 2024
4ab7129
combobox replacement for malware feeds
manV Sep 25, 2024
ee5df68
combobox replacement for unique secrets table filter
manV Sep 25, 2024
404286d
combobox replacement for secret scans table filters
manV Sep 25, 2024
f5c019c
combobox replacement for secret results table filters
manV Sep 25, 2024
4e8b9d1
combobox replacement for most exp secrets table filters
manV Sep 25, 2024
9b86d58
combobox replacement for registry image tags table filter
manV Sep 25, 2024
205a768
combobox replacement for posture scan results table
manV Sep 25, 2024
e245b32
combobox replacement for posture accounts table filters
manV Sep 25, 2024
7342aa7
combobox replacement for cloud posture accounts table filters
manV Sep 25, 2024
9d9bfb7
combobox replacement for unique malware table filters
manV Sep 25, 2024
a3d0dbf
combobox replacement for most exploitable malware table filters
manV Sep 25, 2024
51e035c
combobox replacement for malware scans table filters
manV Sep 25, 2024
dcebbd8
combobox replacement for malware scans table filters
manV Sep 25, 2024
ec73e8f
combobox replacement for reports table filters
manV Sep 25, 2024
718f653
combobox replacement for integration form field selection
manV Sep 25, 2024
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
Original file line number Diff line number Diff line change
@@ -1,15 +1,21 @@
import { useSuspenseInfiniteQuery } from '@suspensive/react-query';
import { debounce } from 'lodash-es';
import { Suspense, useEffect, useMemo, useState } from 'react';
import { CircleSpinner, Combobox, ComboboxOption } from 'ui-components';
import {
CircleSpinner,
ComboboxV2Content,
ComboboxV2Item,
ComboboxV2Provider,
ComboboxV2TriggerButton,
ComboboxV2TriggerInput,
} from 'ui-components';

import { queries } from '@/queries';
import { CloudNodeType } from '@/types/common';
import { useDebouncedValue } from '@/utils/useDebouncedValue';

type SearchableCloudAccountsListProps = {
interface SearchableCloudAccountsListProps {
cloudProvider: CloudNodeType;
onChange?: (value: string[]) => void;
onClearAll?: () => void;
defaultSelectedAccounts?: string[];
valueKey?: 'nodeId' | 'nodeName';
active?: boolean;
Expand All @@ -18,21 +24,21 @@ type SearchableCloudAccountsListProps = {
helperText?: string;
displayValue?: string;
color?: 'error' | 'default';
};
}

const fieldName = 'account_name';
const PAGE_SIZE = 15;
const SearchableCloudAccounts = ({
cloudProvider,
onChange,
onClearAll,
defaultSelectedAccounts,
triggerVariant,
label,
helperText,
color,
}: SearchableCloudAccountsListProps) => {
const [searchText, setSearchText] = useState('');
const debouncedSearchText = useDebouncedValue(searchText, 500);

const [selectedAccounts, setSelectedAccounts] = useState<string[]>(
defaultSelectedAccounts ?? [],
Expand All @@ -52,10 +58,11 @@ const SearchableCloudAccounts = ({
cloudProvider: cloudProvider,
fieldName: fieldName,
size: PAGE_SIZE,
searchText,
searchText: debouncedSearchText,
}),
keepPreviousData: true,
getNextPageParam: (lastPage, allPages) => {
if (lastPage.data.length < PAGE_SIZE) return null;
return allPages.length * PAGE_SIZE;
},
getPreviousPageParam: (firstPage, allPages) => {
Expand All @@ -64,53 +71,61 @@ const SearchableCloudAccounts = ({
},
});

const searchAccount = debounce((query: string) => {
setSearchText(query);
}, 1000);

const onEndReached = () => {
if (hasNextPage) fetchNextPage();
};

return (
<>
<Combobox
label={label}
triggerVariant={triggerVariant}
startIcon={
isFetchingNextPage ? <CircleSpinner size="sm" className="w-3 h-3" /> : undefined
}
<ComboboxV2Provider
loading={isFetchingNextPage}
name={fieldName}
getDisplayValue={() =>
isSelectVariantType && selectedAccounts.length > 0
? `${selectedAccounts.length} selected`
: 'Name'
}
multiple
value={selectedAccounts}
onChange={(values) => {
defaultSelectedValue={defaultSelectedAccounts ?? []}
selectedValue={selectedAccounts}
setSelectedValue={(values) => {
setSelectedAccounts(values);
onChange?.(values);
}}
onQueryChange={searchAccount}
clearAllElement="Clear"
onClearAll={onClearAll}
onEndReached={onEndReached}
helperText={helperText}
color={color}
value={searchText}
setValue={setSearchText}
>
{data?.pages
.flatMap((page) => {
return page.data;
})
.map((item, index) => {
return (
<ComboboxOption key={`${item}-${index}`} value={item}>
{item}
</ComboboxOption>
);
})}
</Combobox>
{triggerVariant === 'select' ? (
<ComboboxV2TriggerInput
label={label}
startIcon={
isFetchingNextPage ? (
<CircleSpinner size="sm" className="w-3 h-3" />
) : undefined
}
getDisplayValue={() =>
selectedAccounts.length > 0 ? `${selectedAccounts.length} selected` : 'Name'
}
placeholder="Name"
helperText={helperText}
color={color}
/>
) : (
<ComboboxV2TriggerButton>Name</ComboboxV2TriggerButton>
)}
<ComboboxV2Content
width={isSelectVariantType ? 'anchor' : 'fixed'}
clearButtonContent="Clear"
onEndReached={onEndReached}
searchPlaceholder="Search"
>
{data?.pages
.flatMap((page) => {
return page.data;
})
.map((item, index) => {
return (
<ComboboxV2Item key={`${item}-${index}`} value={item}>
{item}
</ComboboxV2Item>
);
})}
</ComboboxV2Content>
</ComboboxV2Provider>
</>
);
};
Expand All @@ -121,20 +136,24 @@ export const SearchableCloudAccountName = (props: SearchableCloudAccountsListPro
<Suspense
fallback={
<>
<Combobox
<ComboboxV2Provider
name={fieldName}
value={defaultSelectedAccounts}
label={label}
triggerVariant={triggerVariant}
startIcon={<CircleSpinner size="sm" className="w-3 h-3" />}
getDisplayValue={() => {
return displayValue ? displayValue : `Name`;
}}
multiple
onQueryChange={() => {
// no operation
}}
/>
defaultSelectedValue={defaultSelectedAccounts}
loading
>
{triggerVariant === 'select' ? (
<ComboboxV2TriggerInput
label={label}
startIcon={<CircleSpinner size="sm" className="w-3 h-3" />}
></ComboboxV2TriggerInput>
) : (
<ComboboxV2TriggerButton
startIcon={<CircleSpinner size="sm" className="w-3 h-3" />}
>
{displayValue ? displayValue : 'Name'}
</ComboboxV2TriggerButton>
)}
</ComboboxV2Provider>
</>
}
>
Expand Down
Loading
Loading