fix(ws): fixed filter by labels during workspace creation (#524)
Signed-off-by: paulovmr <832830+paulovmr@users.noreply.github.com>
This commit is contained in:
parent
fd2dc790ff
commit
a932c0fc4c
|
@ -22,34 +22,18 @@ type FilterableDataFieldKeys = FilterableDataFieldKey<typeof fields>;
|
|||
|
||||
type WorkspaceFormImageListProps = {
|
||||
images: WorkspacekindsImageConfigValue[];
|
||||
selectedLabels: Map<string, Set<string>>;
|
||||
selectedImage: WorkspacekindsImageConfigValue | undefined;
|
||||
onSelect: (workspaceImage: WorkspacekindsImageConfigValue | undefined) => void;
|
||||
};
|
||||
|
||||
export const WorkspaceFormImageList: React.FunctionComponent<WorkspaceFormImageListProps> = ({
|
||||
images,
|
||||
selectedLabels,
|
||||
selectedImage,
|
||||
onSelect,
|
||||
}) => {
|
||||
const [filters, setFilters] = useState<FilteredColumn[]>([]);
|
||||
const filterRef = useRef<FilterRef>(null);
|
||||
|
||||
const getFilteredWorkspaceImagesByLabels = useCallback(
|
||||
(unfilteredImages: WorkspacekindsImageConfigValue[]) =>
|
||||
unfilteredImages.filter((image) =>
|
||||
image.labels.reduce((accumulator, label) => {
|
||||
if (selectedLabels.has(label.key)) {
|
||||
const labelValues: Set<string> | undefined = selectedLabels.get(label.key);
|
||||
return accumulator && labelValues !== undefined && labelValues.has(label.value);
|
||||
}
|
||||
return accumulator;
|
||||
}, true),
|
||||
),
|
||||
[selectedLabels],
|
||||
);
|
||||
|
||||
const clearAllFilters = useCallback(() => {
|
||||
filterRef.current?.clearAll();
|
||||
}, []);
|
||||
|
@ -67,7 +51,7 @@ export const WorkspaceFormImageList: React.FunctionComponent<WorkspaceFormImageL
|
|||
searchValueInput = new RegExp(filter.value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), 'i');
|
||||
}
|
||||
|
||||
const filterResult = result.filter((image) => {
|
||||
return result.filter((image) => {
|
||||
if (filter.value === '') {
|
||||
return true;
|
||||
}
|
||||
|
@ -82,9 +66,8 @@ export const WorkspaceFormImageList: React.FunctionComponent<WorkspaceFormImageL
|
|||
return true;
|
||||
}
|
||||
});
|
||||
return getFilteredWorkspaceImagesByLabels(filterResult);
|
||||
}, images);
|
||||
}, [filters, getFilteredWorkspaceImagesByLabels, images]);
|
||||
}, [filters, images]);
|
||||
|
||||
const onChange = useCallback(
|
||||
(event: React.FormEvent<HTMLInputElement>) => {
|
||||
|
|
|
@ -16,17 +16,16 @@ const WorkspaceFormImageSelection: React.FunctionComponent<WorkspaceFormImageSel
|
|||
selectedImage,
|
||||
onSelect,
|
||||
}) => {
|
||||
const [selectedLabels, setSelectedLabels] = useState<Map<string, Set<string>>>(new Map());
|
||||
const [filteredImages, setFilteredImages] = useState<WorkspacekindsImageConfigValue[]>(images);
|
||||
|
||||
const imageFilterContent = useMemo(
|
||||
() => (
|
||||
<FilterByLabels
|
||||
labelledObjects={images.flatMap((image) => image.labels)}
|
||||
selectedLabels={selectedLabels}
|
||||
onSelect={setSelectedLabels}
|
||||
labelledObjects={images}
|
||||
setLabelledObjects={(obj) => setFilteredImages(obj as WorkspacekindsImageConfigValue[])}
|
||||
/>
|
||||
),
|
||||
[images, selectedLabels, setSelectedLabels],
|
||||
[images, setFilteredImages],
|
||||
);
|
||||
|
||||
return (
|
||||
|
@ -35,8 +34,7 @@ const WorkspaceFormImageSelection: React.FunctionComponent<WorkspaceFormImageSel
|
|||
<SplitItem style={{ minWidth: '200px' }}>{imageFilterContent}</SplitItem>
|
||||
<SplitItem isFilled>
|
||||
<WorkspaceFormImageList
|
||||
images={images}
|
||||
selectedLabels={selectedLabels}
|
||||
images={filteredImages}
|
||||
selectedImage={selectedImage}
|
||||
onSelect={onSelect}
|
||||
/>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import React, { useCallback, useMemo } from 'react';
|
||||
import React, { useCallback, useMemo, useState } from 'react';
|
||||
import {
|
||||
FilterSidePanel,
|
||||
FilterSidePanelCategory,
|
||||
|
@ -6,27 +6,28 @@ import {
|
|||
} from '@patternfly/react-catalog-view-extension';
|
||||
import '@patternfly/react-catalog-view-extension/dist/css/react-catalog-view-extension.css';
|
||||
import { formatLabelKey } from '~/shared/utilities/WorkspaceUtils';
|
||||
import { WorkspacesOptionLabel } from '~/generated/data-contracts';
|
||||
|
||||
type FilterByLabelsProps = {
|
||||
labelledObjects: WorkspacesOptionLabel[];
|
||||
selectedLabels: Map<string, Set<string>>;
|
||||
onSelect: (labels: Map<string, Set<string>>) => void;
|
||||
labelledObjects: { labels: { key: string; value: string }[] }[];
|
||||
setLabelledObjects: (labelledObjects: { labels: { key: string; value: string }[] }[]) => void;
|
||||
};
|
||||
|
||||
export const FilterByLabels: React.FunctionComponent<FilterByLabelsProps> = ({
|
||||
labelledObjects,
|
||||
selectedLabels,
|
||||
onSelect,
|
||||
setLabelledObjects,
|
||||
}) => {
|
||||
const [selectedLabels, setSelectedLabels] = useState<Map<string, Set<string>>>(new Map());
|
||||
|
||||
const filterMap = useMemo(() => {
|
||||
const labelsMap = new Map<string, Set<string>>();
|
||||
labelledObjects.forEach((labelledObject) => {
|
||||
if (!labelsMap.has(labelledObject.key)) {
|
||||
labelsMap.set(labelledObject.key, new Set<string>());
|
||||
}
|
||||
labelsMap.get(labelledObject.key)?.add(labelledObject.value);
|
||||
});
|
||||
labelledObjects
|
||||
.flatMap((labelledObject) => labelledObject.labels)
|
||||
.forEach((label) => {
|
||||
if (!labelsMap.has(label.key)) {
|
||||
labelsMap.set(label.key, new Set<string>());
|
||||
}
|
||||
labelsMap.get(label.key)?.add(label.value);
|
||||
});
|
||||
return labelsMap;
|
||||
}, [labelledObjects]);
|
||||
|
||||
|
@ -53,9 +54,30 @@ export const FilterByLabels: React.FunctionComponent<FilterByLabelsProps> = ({
|
|||
}
|
||||
}
|
||||
|
||||
onSelect(newSelectedLabels);
|
||||
setLabelledObjects(
|
||||
labelledObjects.filter((labelledObject) =>
|
||||
[...newSelectedLabels.entries()].reduce(
|
||||
(accumulator, [selectedLabelKey, selectedLabelValues]) => {
|
||||
if (selectedLabelValues.size > 0) {
|
||||
return (
|
||||
accumulator &&
|
||||
labelledObject.labels.some(
|
||||
(imageLabel) =>
|
||||
imageLabel.key === selectedLabelKey &&
|
||||
selectedLabelValues.has(imageLabel.value),
|
||||
)
|
||||
);
|
||||
}
|
||||
return accumulator;
|
||||
},
|
||||
true,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
setSelectedLabels(newSelectedLabels);
|
||||
},
|
||||
[selectedLabels, onSelect],
|
||||
[selectedLabels, labelledObjects, setLabelledObjects],
|
||||
);
|
||||
|
||||
return (
|
||||
|
|
|
@ -22,31 +22,16 @@ type FilterableDataFieldKeys = FilterableDataFieldKey<typeof fields>;
|
|||
|
||||
type WorkspaceFormPodConfigListProps = {
|
||||
podConfigs: WorkspacekindsPodConfigValue[];
|
||||
selectedLabels: Map<string, Set<string>>;
|
||||
selectedPodConfig: WorkspacekindsPodConfigValue | undefined;
|
||||
onSelect: (workspacePodConfig: WorkspacekindsPodConfigValue | undefined) => void;
|
||||
};
|
||||
|
||||
export const WorkspaceFormPodConfigList: React.FunctionComponent<
|
||||
WorkspaceFormPodConfigListProps
|
||||
> = ({ podConfigs, selectedLabels, selectedPodConfig, onSelect }) => {
|
||||
> = ({ podConfigs, selectedPodConfig, onSelect }) => {
|
||||
const [filters, setFilters] = useState<FilteredColumn[]>([]);
|
||||
const filterRef = useRef<FilterRef>(null);
|
||||
|
||||
const getFilteredWorkspacePodConfigsByLabels = useCallback(
|
||||
(unfilteredPodConfigs: WorkspacekindsPodConfigValue[]) =>
|
||||
unfilteredPodConfigs.filter((podConfig) =>
|
||||
podConfig.labels.reduce((accumulator, label) => {
|
||||
if (selectedLabels.has(label.key)) {
|
||||
const labelValues: Set<string> | undefined = selectedLabels.get(label.key);
|
||||
return accumulator && labelValues !== undefined && labelValues.has(label.value);
|
||||
}
|
||||
return accumulator;
|
||||
}, true),
|
||||
),
|
||||
[selectedLabels],
|
||||
);
|
||||
|
||||
const clearAllFilters = useCallback(() => {
|
||||
filterRef.current?.clearAll();
|
||||
}, []);
|
||||
|
@ -62,7 +47,7 @@ export const WorkspaceFormPodConfigList: React.FunctionComponent<
|
|||
} catch {
|
||||
searchValueInput = new RegExp(filter.value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), 'i');
|
||||
}
|
||||
const filterResult = result.filter((podConfig) => {
|
||||
return result.filter((podConfig) => {
|
||||
if (filter.value === '') {
|
||||
return true;
|
||||
}
|
||||
|
@ -77,9 +62,8 @@ export const WorkspaceFormPodConfigList: React.FunctionComponent<
|
|||
return true;
|
||||
}
|
||||
});
|
||||
return getFilteredWorkspacePodConfigsByLabels(filterResult);
|
||||
}, podConfigs);
|
||||
}, [filters, getFilteredWorkspacePodConfigsByLabels, podConfigs]);
|
||||
}, [filters, podConfigs]);
|
||||
|
||||
const onChange = useCallback(
|
||||
(event: React.FormEvent<HTMLInputElement>) => {
|
||||
|
|
|
@ -14,17 +14,17 @@ interface WorkspaceFormPodConfigSelectionProps {
|
|||
const WorkspaceFormPodConfigSelection: React.FunctionComponent<
|
||||
WorkspaceFormPodConfigSelectionProps
|
||||
> = ({ podConfigs, selectedPodConfig, onSelect }) => {
|
||||
const [selectedLabels, setSelectedLabels] = useState<Map<string, Set<string>>>(new Map());
|
||||
const [filteredPodConfigs, setFilteredPodConfigs] =
|
||||
useState<WorkspacekindsPodConfigValue[]>(podConfigs);
|
||||
|
||||
const podConfigFilterContent = useMemo(
|
||||
() => (
|
||||
<FilterByLabels
|
||||
labelledObjects={podConfigs.flatMap((podConfig) => podConfig.labels)}
|
||||
selectedLabels={selectedLabels}
|
||||
onSelect={setSelectedLabels}
|
||||
labelledObjects={podConfigs}
|
||||
setLabelledObjects={(obj) => setFilteredPodConfigs(obj as WorkspacekindsPodConfigValue[])}
|
||||
/>
|
||||
),
|
||||
[podConfigs, selectedLabels, setSelectedLabels],
|
||||
[podConfigs, setFilteredPodConfigs],
|
||||
);
|
||||
|
||||
return (
|
||||
|
@ -33,8 +33,7 @@ const WorkspaceFormPodConfigSelection: React.FunctionComponent<
|
|||
<SplitItem style={{ minWidth: '200px' }}>{podConfigFilterContent}</SplitItem>
|
||||
<SplitItem isFilled>
|
||||
<WorkspaceFormPodConfigList
|
||||
podConfigs={podConfigs}
|
||||
selectedLabels={selectedLabels}
|
||||
podConfigs={filteredPodConfigs}
|
||||
selectedPodConfig={selectedPodConfig}
|
||||
onSelect={onSelect}
|
||||
/>
|
||||
|
|
Loading…
Reference in New Issue