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

update table filters into separate chip groups #3202

Merged
merged 2 commits into from
Sep 17, 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
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ describe('Manage runs', () => {
});

it('has param experiment filter by default', () => {
cy.findByTestId('experiment-filter-chip').should('have.text', 'Experiment: Default');
cy.findByTestId('experiment-filter-chip').should('have.text', 'Default');
});

it('has param run IDs checked by default', () => {
Expand Down
4 changes: 4 additions & 0 deletions frontend/src/app/App.scss
Original file line number Diff line number Diff line change
Expand Up @@ -70,3 +70,7 @@ body,
min-height: 0;
}

.pf-v5-c-truncate {
--pf-v5-c-truncate--MinWidth: 0;
--pf-v5-c-truncate__start--MinWidth: 0;
}
79 changes: 35 additions & 44 deletions frontend/src/components/FilterToolbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@
ToolbarFilter,
ToolbarGroup,
ToolbarItem,
ToolbarChip,
Tooltip,
Dropdown,
DropdownItem,
MenuToggle,
Expand All @@ -24,7 +22,6 @@
filterOptionRenders: Record<T, (props: FilterOptionRenders) => React.ReactNode>;
filterData: Record<T, string | { label: string; value: string } | undefined>;
onFilterUpdate: (filterType: T, value?: string | { label: string; value: string }) => void;
onClearFilters: () => void;
testId?: string;
};

Expand All @@ -33,7 +30,6 @@
filterOptionRenders,
filterData,
onFilterUpdate,
onClearFilters,
children,
testId = 'filter-toolbar',
...toolbarGroupProps
Expand All @@ -42,8 +38,6 @@
const keys = Object.keys(filterOptions) as Array<T>;
const [open, setOpen] = React.useState(false);
const [currentFilterType, setCurrentFilterType] = React.useState<T>(keys[0]);
const isToolbarChip = (v: unknown): v is ToolbarChip & { key: T } =>
!!v && Object.keys(v).every((k) => ['key', 'node'].includes(k));
const filterItem = filterData[currentFilterType];

return (
Expand Down Expand Up @@ -85,45 +79,42 @@
</DropdownList>
</Dropdown>
</ToolbarItem>
<ToolbarFilter
categoryName="Filters"
data-testid={`${testId}-text-field`}
variant="search-filter"
chips={keys
.map<ToolbarChip | null>((filterKey) => {
const optionValue = filterOptions[filterKey];
const data = filterData[filterKey];
if (data) {
const dataValue: { label: string; value: string } | undefined =
typeof data === 'string' ? { label: data, value: data } : data;
return {
key: filterKey,
node: (
<span data-testid={`${optionValue?.toLowerCase()}-filter-chip`}>
<b>{optionValue}:</b>{' '}
<Tooltip content={dataValue.value} position="top-start">
<span>{dataValue.label}</span>
</Tooltip>
</span>
),
};
{keys.map((filterKey) => {
const optionValue = filterOptions[filterKey];
const data = filterData[filterKey];
const dataValue: { label: string; value: string } | undefined =
typeof data === 'string' ? { label: data, value: data } : data;
return optionValue ? (
<ToolbarFilter
key={filterKey}
categoryName={optionValue}
data-testid={`${testId}-text-field`}
variant="search-filter"
chips={
data && dataValue
? [
{
key: filterKey,
node: (
<span data-testid={`${filterKey}-filter-chip`}>{dataValue.label}</span>
),
},
]
: []
}
return null;
})
.filter(isToolbarChip)}
deleteChip={(_, chip) => {
if (isToolbarChip(chip)) {
onFilterUpdate(chip.key, '');
}
}}
deleteChipGroup={() => onClearFilters()}
>
{filterOptionRenders[currentFilterType]({
onChange: (value, label) =>
onFilterUpdate(currentFilterType, label && value ? { label, value } : value),
...(typeof filterItem === 'string' ? { value: filterItem } : filterItem),
})}
</ToolbarFilter>
deleteChip={() => {
onFilterUpdate(filterKey, '');

Check warning on line 106 in frontend/src/components/FilterToolbar.tsx

View check run for this annotation

Codecov / codecov/patch

frontend/src/components/FilterToolbar.tsx#L106

Added line #L106 was not covered by tests
}}
showToolbarItem={currentFilterType === filterKey}
>
{filterOptionRenders[filterKey]({
onChange: (value, label) =>
onFilterUpdate(filterKey, label && value ? { label, value } : value),
...(typeof filterItem === 'string' ? { value: filterItem } : filterItem),
})}
</ToolbarFilter>
) : null;

Check warning on line 116 in frontend/src/components/FilterToolbar.tsx

View check run for this annotation

Codecov / codecov/patch

frontend/src/components/FilterToolbar.tsx#L116

Added line #L116 was not covered by tests
})}
</ToolbarGroup>
{children}
</>
Expand Down
5 changes: 4 additions & 1 deletion frontend/src/components/table/TableBase.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ type Props<DataType> = {
enablePagination?: boolean | 'compact';
truncateRenderingAt?: number;
toolbarContent?: React.ReactElement<typeof ToolbarItem | typeof ToolbarGroup>;
onClearFilters?: () => void;
bottomToolbarContent?: React.ReactElement<typeof ToolbarItem | typeof ToolbarGroup>;
emptyTableView?: React.ReactNode;
caption?: string;
Expand Down Expand Up @@ -92,6 +93,7 @@ const TableBase = <T,>({
rowRenderer,
enablePagination,
toolbarContent,
onClearFilters,
bottomToolbarContent,
emptyTableView,
caption,
Expand Down Expand Up @@ -274,7 +276,8 @@ const TableBase = <T,>({
<Toolbar
inset={{ default: 'insetNone' }}
className="pf-v5-u-w-100"
customChipGroupContent={<></>}
customChipGroupContent={onClearFilters ? undefined : <></>}
clearAllFilters={onClearFilters}
>
<ToolbarContent>
{toolbarContent}
Expand Down
32 changes: 19 additions & 13 deletions frontend/src/concepts/connectionTypes/fields/DropdownFormField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,24 @@
const hasValidOption = field.properties.items?.find((f) => f.value || f.label);

const menuToggleText = () => {
let text = field.name ? `Select ${field.name} ` : 'No values defined yet ';
if (!isMulti && isPreview) {
const defaultOption = field.properties.items?.find(
(i) => i.value === field.properties.defaultValue?.[0],
);
if (defaultOption) {
text = defaultOption.label || defaultOption.value;
}
} else if (!isMulti && !isPreview) {
const currentSelection = field.properties.items?.find((i) => value?.includes(i.value));
if (currentSelection) {
text = currentSelection.label || currentSelection.value;
let text = field.properties.items?.some((i) => i.label || i.value)
? field.name
? `Select ${field.name} `
: 'Select'

Check warning on line 25 in frontend/src/concepts/connectionTypes/fields/DropdownFormField.tsx

View check run for this annotation

Codecov / codecov/patch

frontend/src/concepts/connectionTypes/fields/DropdownFormField.tsx#L25

Added line #L25 was not covered by tests
: 'No values defined';
if (!isMulti) {
if (isPreview) {
const defaultOption = field.properties.items?.find(
(i) => i.value === field.properties.defaultValue?.[0],
);
if (defaultOption) {
text = defaultOption.label || defaultOption.value;
}
} else {
const currentSelection = field.properties.items?.find((i) => value?.includes(i.value));
if (currentSelection) {
text = currentSelection.label || currentSelection.value;
}
}
}
return text;
Expand Down Expand Up @@ -74,7 +80,7 @@
<>
{menuToggleText()}
{isMulti && (
<Badge>
<Badge className="pf-v5-u-ml-xs">
{(isPreview ? field.properties.defaultValue?.length : value?.length) ?? 0}{' '}
selected
</Badge>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { useCompareRuns } from '~/concepts/pipelines/content/compareRuns/Compare

export type FilterProps = Pick<
React.ComponentProps<typeof PipelineFilterBar>,
'filterData' | 'onFilterUpdate' | 'onClearFilters'
'filterData' | 'onFilterUpdate'
>;

const CompareRunTableToolbar: React.FC<FilterProps> = ({ ...toolbarProps }) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ const ExperimentTable: React.FC<ExperimentTableProps> = ({
getActionColumnItems,
...tableProps
}) => {
const filterToolbarProps = usePipelineFilter(setFilter);
const { onClearFilters, ...filterToolbarProps } = usePipelineFilter(setFilter);
const {
selections,
tableProps: checkboxTableProps,
Expand All @@ -65,9 +65,8 @@ const ExperimentTable: React.FC<ExperimentTableProps> = ({
data={experiments}
columns={experimentColumns}
enablePagination="compact"
emptyTableView={
<DashboardEmptyTableView onClearFilters={filterToolbarProps.onClearFilters} />
}
emptyTableView={<DashboardEmptyTableView onClearFilters={onClearFilters} />}
onClearFilters={onClearFilters}
toolbarContent={
<ExperimentTableToolbar data-testid="experiment-table-toolbar" {...filterToolbarProps}>
{toolbarContentRenderer(selections)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ const options = {

export type FilterProps = Pick<
React.ComponentProps<typeof PipelineFilterBar>,
'filterData' | 'onFilterUpdate' | 'onClearFilters'
'filterData' | 'onFilterUpdate'
>;

type ExperimentTableToolbarProps = FilterProps & {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ type PipelinesTableProps = {
setSortDirection: (dir: 'asc' | 'desc') => void;
} & Pick<
React.ComponentProps<typeof Table>,
'toolbarContent' | 'emptyTableView' | 'enablePagination' | 'variant'
'toolbarContent' | 'emptyTableView' | 'enablePagination' | 'variant' | 'onClearFilters'
>;

const PipelinesTable: React.FC<PipelinesTableProps> = ({
Expand All @@ -38,6 +38,7 @@ const PipelinesTable: React.FC<PipelinesTableProps> = ({
emptyTableView,
toolbarContent,
variant,
onClearFilters,
...sortProps
}) => {
const { refreshAllAPI } = usePipelinesAPI();
Expand All @@ -56,6 +57,7 @@ const PipelinesTable: React.FC<PipelinesTableProps> = ({
{...checkboxTableProps}
enablePagination={enablePagination}
emptyTableView={emptyTableView}
onClearFilters={onClearFilters}
toolbarContent={toolbarContent}
variant={variant}
loading={loading}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ const PipelineRecurringRunTable: React.FC<PipelineRecurringRunTableProps> = ({
}) => {
const { refreshAllAPI } = usePipelinesAPI();
const { experimentId, pipelineVersionId } = useParams();
const filterToolbarProps = usePipelineFilter(setFilter);
const { onClearFilters, ...filterToolbarProps } = usePipelineFilter(setFilter);
const isExperimentsAvailable = useIsAreaAvailable(SupportedArea.PIPELINE_EXPERIMENTS).status;
const {
selections,
Expand Down Expand Up @@ -88,9 +88,8 @@ const PipelineRecurringRunTable: React.FC<PipelineRecurringRunTableProps> = ({
data={recurringRuns}
columns={getColumns()}
enablePagination="compact"
emptyTableView={
<DashboardEmptyTableView onClearFilters={filterToolbarProps.onClearFilters} />
}
emptyTableView={<DashboardEmptyTableView onClearFilters={onClearFilters} />}
onClearFilters={onClearFilters}
toolbarContent={
<PipelineRecurringRunTableToolbar
{...filterToolbarProps}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { useContextExperimentArchived as useIsExperimentArchived } from '~/pages

export type FilterProps = Pick<
React.ComponentProps<typeof PipelineFilterBar>,
'filterData' | 'onFilterUpdate' | 'onClearFilters'
'filterData' | 'onFilterUpdate'
>;

interface PipelineRecurringRunTableToolbarProps extends FilterProps {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ const PipelineRunTableInternal: React.FC<PipelineRunTableInternalProps> = ({
const navigate = useNavigate();
const { experimentId, pipelineVersionId, pipelineId } = useParams();
const { namespace, refreshAllAPI } = usePipelinesAPI();
const filterToolbarProps = usePipelineFilter(setFilter);
const { onClearFilters, ...filterToolbarProps } = usePipelineFilter(setFilter);
const {
selections: selectedIds,
tableProps: checkboxTableProps,
Expand Down Expand Up @@ -234,9 +234,8 @@ const PipelineRunTableInternal: React.FC<PipelineRunTableInternalProps> = ({
data={runs}
columns={getColumns()}
enablePagination="compact"
emptyTableView={
<DashboardEmptyTableView onClearFilters={filterToolbarProps.onClearFilters} />
}
emptyTableView={<DashboardEmptyTableView onClearFilters={onClearFilters} />}
onClearFilters={onClearFilters}
toolbarContent={
<PipelineRunTableToolbar
data-testid={`${runType}-runs-table-toolbar`}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { SupportedArea, useIsAreaAvailable } from '~/concepts/areas';

export type FilterProps = Pick<
React.ComponentProps<typeof PipelineFilterBar>,
'filterData' | 'onFilterUpdate' | 'onClearFilters'
'filterData' | 'onFilterUpdate'
>;

interface PipelineRunTableToolbarProps extends FilterProps {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ export const getDataValue = (data: string | { value: string } | undefined): stri

export type FilterProps = Pick<
React.ComponentProps<typeof FilterToolbar>,
'filterData' | 'onFilterUpdate' | 'onClearFilters'
>;
'filterData' | 'onFilterUpdate'
> & { onClearFilters: () => void };

const defaultFilterData: FilterProps['filterData'] = {
[FilterOptions.NAME]: '',
Expand Down
17 changes: 5 additions & 12 deletions frontend/src/pages/connectionTypes/ConnectionTypesTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ type Props = {

const ConnectionTypesTable: React.FC<Props> = ({ connectionTypes, onUpdate }) => {
const [filterData, setFilterData] = React.useState<FilterDataType>(initialFilterData);
const onClearFilters = React.useCallback(() => setFilterData(initialFilterData), [setFilterData]);
const onClearFilters = React.useCallback(() => setFilterData(initialFilterData), []);

const [deleteConnectionType, setDeleteConnectionType] = React.useState<
ConnectionTypeConfigMapObj | undefined
Expand All @@ -30,7 +30,7 @@ const ConnectionTypesTable: React.FC<Props> = ({ connectionTypes, onUpdate }) =>
() =>
connectionTypes.filter((connectionType) => {
const keywordFilter = filterData.Keyword?.toLowerCase();
const createFilter = filterData['Created by']?.toLowerCase();
const createFilter = filterData.Creator?.toLowerCase();
const categoryFilter = filterData.Category?.toLowerCase();

if (
Expand Down Expand Up @@ -58,10 +58,6 @@ const ConnectionTypesTable: React.FC<Props> = ({ connectionTypes, onUpdate }) =>
[connectionTypes, filterData],
);

const resetFilters = () => {
setFilterData(initialFilterData);
};

return (
<>
<Table
Expand All @@ -80,15 +76,12 @@ const ConnectionTypesTable: React.FC<Props> = ({ connectionTypes, onUpdate }) =>
handleDelete={(connection) => setDeleteConnectionType(connection)}
/>
)}
onClearFilters={onClearFilters}
toolbarContent={
<ConnectionTypesTableToolbar
filterData={filterData}
setFilterData={setFilterData}
onClearFilters={onClearFilters}
/>
<ConnectionTypesTableToolbar filterData={filterData} setFilterData={setFilterData} />
}
disableItemCount
emptyTableView={<DashboardEmptyTableView onClearFilters={resetFilters} />}
emptyTableView={<DashboardEmptyTableView onClearFilters={onClearFilters} />}
id="connectionTypes-list-table"
/>
{deleteConnectionType ? (
Expand Down
Loading
Loading