Skip to content

Commit

Permalink
Merge pull request #2340 from avivtur/folder-create-fix
Browse files Browse the repository at this point in the history
CNV-54179: Improve folder select
  • Loading branch information
openshift-merge-bot[bot] authored Jan 13, 2025
2 parents c383214 + 18fb54b commit b6a1884
Show file tree
Hide file tree
Showing 5 changed files with 24 additions and 25 deletions.
2 changes: 1 addition & 1 deletion locales/en/plugin__kubevirt-plugin.json
Original file line number Diff line number Diff line change
Expand Up @@ -326,8 +326,8 @@
"Create a Windows boot source": "Create a Windows boot source",
"Create activation key": "Create activation key",
"Create DataSource": "Create DataSource",
"Create folder \"{{filterValue}}\"": "Create folder \"{{filterValue}}\"",
"Create MigrationPolicy": "Create MigrationPolicy",
"Create new option \"{{filterValue}}\"": "Create new option \"{{filterValue}}\"",
"Create new sysprep": "Create new sysprep",
"Create new VirtualMachine": "Create new VirtualMachine",
"Create project": "Create project",
Expand Down
2 changes: 1 addition & 1 deletion src/utils/components/FolderSelect/FolderSelect.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ const FolderSelect: FC<FoldersSelectProps> = ({
<SelectTypeahead
canCreate
dataTestId="vm-folder-select"
getCreateOption={(inputValue, canCreate) => getCreateNewFolderOption(inputValue, canCreate)}
getCreateOption={getCreateNewFolderOption}
initialOptions={folderOptions}
isFullWidth={isFullWidth}
placeholder={t('Search folder')}
Expand Down
35 changes: 18 additions & 17 deletions src/utils/components/SelectTypeahead/SelectTypeahead.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React, { Dispatch, FC, SetStateAction, useEffect, useRef, useState } from 'react';

import { useKubevirtTranslation } from '@kubevirt-utils/hooks/useKubevirtTranslation';
import { isEmpty } from '@kubevirt-utils/utils/utils';
import {
Button,
Expand All @@ -17,7 +18,7 @@ import {
import { FolderIcon, SearchIcon } from '@patternfly/react-icons';
import TimesIcon from '@patternfly/react-icons/dist/esm/icons/times-icon';

import { CREATE_NEW } from './utils/constants';
import { CREATE_NEW, NOT_FOUND } from './utils/constants';
import { createItemId } from './utils/utils';

type SelectTypeaheadProps = {
Expand All @@ -43,35 +44,35 @@ const SelectTypeahead: FC<SelectTypeaheadProps> = ({
setInitialOptions,
setSelected,
}) => {
const { t } = useKubevirtTranslation();
const [isOpen, setIsOpen] = useState(false);
const [inputValue, setInputValue] = useState<string>(selected);
const [filterValue, setFilterValue] = useState<string>('');
const [selectOptions, setSelectOptions] = useState<SelectOptionProps[]>(initialOptions);
const [selectOptions, setSelectOptions] = useState<SelectOptionProps[]>();
const [focusedItemIndex, setFocusedItemIndex] = useState<null | number>(null);
const [activeItemId, setActiveItemId] = useState<null | string>(null);
const textInputRef = useRef<HTMLInputElement>();

useEffect(() => {
if (isEmpty(initialOptions)) {
setSelectOptions([getCreateOption(filterValue, canCreate)]);
return;
const newSelectOptions: SelectOptionProps[] = filterValue
? (initialOptions || [])?.filter((menuItem) =>
String(menuItem.children).toLowerCase().includes(filterValue.toLowerCase()),
)
: initialOptions || [];

if (canCreate) {
const createOption = getCreateOption?.(filterValue, canCreate);
if (createOption && !newSelectOptions.some((option) => option.value === CREATE_NEW)) {
newSelectOptions.push(createOption);
}
}
let newSelectOptions: SelectOptionProps[] = initialOptions || [];

// Filter menu items based on the text input value when one exists
if (filterValue) {
newSelectOptions = initialOptions?.filter((menuItem) =>
String(menuItem.children).toLowerCase().includes(filterValue.toLowerCase()),
);

// If no option matches the filter exactly, display creation option
if (!initialOptions?.some((option) => option.value === filterValue) && canCreate) {
newSelectOptions = [...newSelectOptions, getCreateOption(filterValue, canCreate)];
}
if (!canCreate && newSelectOptions.length === 0 && filterValue) {
newSelectOptions.push({ children: t('Not found'), isDisabled: true, value: NOT_FOUND });
}

setSelectOptions(newSelectOptions);
}, [canCreate, filterValue, getCreateOption, initialOptions]);
}, [canCreate, filterValue, getCreateOption, initialOptions, t]);

const setActiveAndFocusedItem = (itemIndex: number) => {
setFocusedItemIndex(itemIndex);
Expand Down
1 change: 1 addition & 0 deletions src/utils/components/SelectTypeahead/utils/constants.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export const CREATE_NEW = 'create';
export const NOT_FOUND = 'notFound';
9 changes: 3 additions & 6 deletions src/utils/components/SelectTypeahead/utils/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,8 @@ import { SelectOptionProps } from '@patternfly/react-core';
import { CREATE_NEW } from './constants';
export const createItemId = (value: any) => `select-typeahead-${value?.replace(' ', '-')}`;

export const getCreateNewFolderOption = (
filterValue: string,
canCreate = false,
): SelectOptionProps => ({
children: canCreate ? t(`Create new option "{{filterValue}}"`, { filterValue }) : t('Not found'),
isDisabled: !canCreate || isEmpty(filterValue),
export const getCreateNewFolderOption = (filterValue: string): SelectOptionProps => ({
children: t(`Create folder "{{filterValue}}"`, { filterValue }),
isDisabled: isEmpty(filterValue),
value: CREATE_NEW,
});

0 comments on commit b6a1884

Please sign in to comment.