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 to PF5 - part II - onSelect, onToggle event handlers #1221

Merged
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 @@ -4,6 +4,8 @@ import { useHistory } from 'react-router';
import { ActionService, ActionServiceProvider } from '@openshift-console/dynamic-plugin-sdk';
import { Dropdown, DropdownItem, DropdownToggle, KebabToggle } from '@patternfly/react-core';

import { ToggleEventType } from '../../utils';

export interface ActionServiceDropdownProps<T> {
/** The contextId of the `console.action/provider` extension to use */
contextId: string;
Expand Down Expand Up @@ -67,12 +69,18 @@ const ActionsAsDropdown = ({
const history = useHistory();
const [isActionMenuOpen, setIsActionMenuOpen] = useState(false);
const isPlain = variant === 'kebab';

const onToggle: (isExpanded: boolean, event: ToggleEventType) => void = (isExpanded) => {
setIsActionMenuOpen(isExpanded);
};

const toggle =
variant === 'kebab' ? (
<KebabToggle onToggle={setIsActionMenuOpen} />
<KebabToggle onToggle={onToggle} />
) : (
<DropdownToggle onToggle={setIsActionMenuOpen}>{dropdownToggleText}</DropdownToggle>
<DropdownToggle onToggle={onToggle}>{dropdownToggleText}</DropdownToggle>
);

return (
<Dropdown
position="right"
Expand Down
34 changes: 23 additions & 11 deletions packages/common/src/components/Filter/AutocompleteFilter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import {
ToolbarFilter,
} from '@patternfly/react-core';

import { SelectEventType, SelectValueType, ToggleEventType } from '../../utils';

import { FilterTypeProps } from './types';

/**
Expand Down Expand Up @@ -65,6 +67,25 @@ export const AutocompleteFilter = ({
);
};

const onSelect: (
event: SelectEventType,
value: SelectValueType,
isPlaceholder?: boolean,
) => void = (event, value, isPlaceholder) => {
if (isPlaceholder) {
return;
}
// behave as Console's AutocompleteInput used i.e. to filter pods by label
if (!hasFilter(value)) {
addFilter(value);
}
setExpanded(false);
};

const onToggle: (isExpanded: boolean, event: ToggleEventType) => void = (isExpanded) => {
setExpanded(isExpanded);
};

return (
<ToolbarFilter
key={filterId}
Expand All @@ -77,23 +98,14 @@ export const AutocompleteFilter = ({
<Select
variant={SelectVariant.typeahead}
aria-label={placeholderLabel}
onSelect={(event, option, isPlaceholder) => {
if (isPlaceholder) {
return;
}
// behave as Console's AutocompleteInput used i.e. to filter pods by label
if (!hasFilter(option)) {
addFilter(option);
}
setExpanded(false);
}}
onSelect={onSelect}
// intentionally keep the selections list empty
// the select should pretend to be stateless
// the selection is stored outside in a new chip
selections={[]}
placeholderText={placeholderLabel}
isOpen={isExpanded}
onToggle={setExpanded}
onToggle={onToggle}
onFilter={onFilter}
shouldResetOnSelect={true}
>
Expand Down
26 changes: 18 additions & 8 deletions packages/common/src/components/Filter/EnumFilter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
ToolbarFilter,
} from '@patternfly/react-core';

import { localeCompare } from '../../utils';
import { localeCompare, SelectEventType, SelectValueType, ToggleEventType } from '../../utils';

import { FilterTypeProps } from './types';

Expand Down Expand Up @@ -138,6 +138,21 @@ export const EnumFilter = ({
}
};

const onSelect: (
event: SelectEventType,
value: SelectValueType,
isPlaceholder?: boolean,
) => void = (event, value, isPlaceholder) => {
if (isPlaceholder) {
return;
}
hasFilter(value) ? deleteFilter(value) : addFilter(value);
};

const onToggle: (isExpanded: boolean, event: ToggleEventType) => void = (isExpanded) => {
setExpanded(isExpanded);
};

return (
<ToolbarFilter
key={filterId}
Expand All @@ -150,16 +165,11 @@ export const EnumFilter = ({
<Select
variant={SelectVariant.checkbox}
aria-label={placeholderLabel}
onSelect={(event, option, isPlaceholder) => {
if (isPlaceholder) {
return;
}
hasFilter(option) ? deleteFilter(option) : addFilter(option);
}}
onSelect={onSelect}
selections={selectedUniqueEnumLabels}
placeholderText={placeholderLabel}
isOpen={isExpanded}
onToggle={setExpanded}
onToggle={onToggle}
>
{uniqueEnumLabels.map((label) => (
<SelectOption key={label} value={label} />
Expand Down
28 changes: 19 additions & 9 deletions packages/common/src/components/Filter/GroupedEnumFilter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
ToolbarFilter,
} from '@patternfly/react-core';

import { EnumValue } from '../../utils';
import { EnumValue, SelectEventType, SelectValueType, ToggleEventType } from '../../utils';

import { FilterTypeProps, InlineFilter } from './types';

Expand Down Expand Up @@ -107,6 +107,22 @@ export const GroupedEnumFilter = ({
return filteredGroups;
};

const onSelect: (
event: SelectEventType,
value: SelectValueType,
isPlaceholder?: boolean,
) => void = (event, value, isPlaceholder) => {
if (isPlaceholder) {
return;
}
const id = typeof value === 'string' ? value : (value as EnumValue).id;
hasFilter(id) ? deleteFilter(id) : addFilter(id);
};

const onToggle: (isExpanded: boolean, event: ToggleEventType) => void = (isExpanded) => {
setExpanded(isExpanded);
};

return (
<>
{/**
Expand Down Expand Up @@ -141,19 +157,13 @@ export const GroupedEnumFilter = ({
variant={SelectVariant.checkbox}
isGrouped
aria-label={placeholderLabel}
onSelect={(event, option, isPlaceholder) => {
if (isPlaceholder) {
return;
}
const id = typeof option === 'string' ? option : (option as EnumValue).id;
hasFilter(id) ? deleteFilter(id) : addFilter(id);
}}
onSelect={onSelect}
selections={supportedEnumValues
.filter(({ id }) => selectedEnumIds.includes(id))
.map(toSelectOption)}
placeholderText={placeholderLabel}
isOpen={isExpanded}
onToggle={setExpanded}
onToggle={onToggle}
hasInlineFilter={hasInlineFilter}
onFilter={onFilter}
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import {
ToolbarItem,
} from '@patternfly/react-core';

import { SelectEventType, SelectValueType, ToggleEventType } from '../../utils';

import { FilterFromDef } from './FilterFromDef';
import { MetaFilterProps } from './types';

Expand Down Expand Up @@ -44,19 +46,27 @@ export const AttributeValueFilter = ({
const selectOptionToFilter = (selectedId) =>
fieldFilters.find(({ resourceFieldId }) => resourceFieldId === selectedId) ?? currentFilter;

const onFilterTypeSelect = (event, value, isPlaceholder) => {
const onFilterTypeSelect: (
event: SelectEventType,
value: SelectValueType,
isPlaceholder?: boolean,
) => void = (_event, value: IdOption, isPlaceholder) => {
if (!isPlaceholder) {
setCurrentFilter(selectOptionToFilter(value?.id));
setExpanded(!expanded);
}
};

const onToggle: (isExpanded: boolean, event: ToggleEventType) => void = (isExpanded) => {
setExpanded(isExpanded);
};

return (
<ToolbarGroup variant="filter-group">
<ToolbarItem>
<Select
onSelect={onFilterTypeSelect}
onToggle={setExpanded}
onToggle={onToggle}
isOpen={expanded}
variant={SelectVariant.single}
aria-label={'Select Filter'}
Expand Down
35 changes: 35 additions & 0 deletions packages/common/src/utils/types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import React from 'react';

import { SelectOptionObject } from '@patternfly/react-core';
export interface EnumGroup {
groupId: string;
label: string;
Expand Down Expand Up @@ -53,3 +55,36 @@ export interface GlobalActionToolbarProps<T> {
// data currently visible on the screen (i.e. adjusted by paging and filtering)
dataOnScreen: T[];
}

/**
* @typedef {Object} ToggleEventType
* @description Represents the possible event types that can be used for toggling actions.
*
* @property {Event} Event - A standard DOM event.
* @property {React.KeyboardEvent<Element>} React.KeyboardEvent - A React-specific keyboard event.
* @property {React.MouseEvent<Element, MouseEvent>} React.MouseEvent - A React-specific mouse event.
* @property {React.ChangeEvent<Element>} React.ChangeEvent - A React-specific change event.
*/
export type ToggleEventType =
| Event
| React.KeyboardEvent<Element>
| React.MouseEvent<Element, MouseEvent>
| React.ChangeEvent<Element>;

/**
* @typedef {Object} SelectEventType
* @description Represents the possible event types that can be used for select actions.
*
* @property {React.MouseEvent<Element, MouseEvent>} React.MouseEvent - A React-specific mouse event.
* @property {React.ChangeEvent<Element>} React.ChangeEvent - A React-specific change event.
*/
export type SelectEventType = React.MouseEvent<Element, MouseEvent> | React.ChangeEvent<Element>;

/**
* @typedef {Object} SelectValueType
* @description Represents the possible value types that can be used for select actions.
*
* @property {string} string .
* @property {SelectOptionObject} SelectOptionObject
*/
export type SelectValueType = string | SelectOptionObject;
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React, { useCallback, useMemo } from 'react';
import { useToggle } from 'src/modules/Providers/hooks';

import { SelectEventType, SelectValueType } from '@kubev2v/common';
import { Select, SelectOption, SelectVariant } from '@patternfly/react-core';

/**
Expand Down Expand Up @@ -60,10 +61,14 @@ export const SettingsSelectInput: React.FC<SettingsSelectInputProps> = ({
const valueLabel = keyToName?.[value] || value;

// Callback function to handle selection in the dropdown menu
const onSelect = useCallback(
(event, selection) => {
const onSelect: (
event: SelectEventType,
value: SelectValueType,
isPlaceholder?: boolean,
) => void = useCallback(
(_event, value: string | number) => {
// Use the dictionary to find the key corresponding to the selected name
const key = nameToKey[selection] || selection;
const key = nameToKey[value] || value;
onChange(key);

// Toggle the dropdown menu open state
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React, { useState } from 'react';
import { useForkliftTranslation } from 'src/utils/i18n';

import { SelectEventType, SelectValueType } from '@kubev2v/common';
import { Select, SelectOption, SelectVariant } from '@patternfly/react-core';
import FilterIcon from '@patternfly/react-icons/dist/esm/icons/filter-icon';

Expand Down Expand Up @@ -28,11 +29,15 @@ export const SelectProvider: React.FunctionComponent<SelectProviderProps> = ({

const providerTypesArray = Object.keys(providerTypes);

const onSelect = (_, selection: string) => {
const onSelect: (
event: SelectEventType,
value: SelectValueType,
isPlaceholder?: boolean,
) => void = (_, value: string) => {
const prevTypeFilters = filterState.typeFilters;
const typeFilters = prevTypeFilters.includes(selection)
? prevTypeFilters.filter((item: string) => item !== selection)
: [...prevTypeFilters, selection];
const typeFilters = prevTypeFilters.includes(value)
? prevTypeFilters.filter((item: string) => item !== value)
: [...prevTypeFilters, value];
filterDispatch({ type: 'UPDATE_TYPE_FILTERS', payload: typeFilters });
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React, { FC } from 'react';
import { useToggle } from 'src/modules/Providers/hooks';
import { useForkliftTranslation } from 'src/utils/i18n';

import { SelectEventType, SelectValueType } from '@kubev2v/common';
import {
Button,
DataListAction,
Expand Down Expand Up @@ -54,6 +55,29 @@ export const MappingListItem: FC<MappingListItemProps> = ({
deleteMapping({ source, destination });
};

const onSelectSource: (
event: SelectEventType,
value: SelectValueType,
isPlaceholder?: boolean,
) => void = (event, value: string, isPlaceholder) => {
!isPlaceholder &&
replaceMapping({
current: { source, destination },
next: { source: value, destination },
});
};

const onSelectDestination: (
event: SelectEventType,
value: SelectValueType,
isPlaceholder?: boolean,
) => void = (event, value: string) => {
replaceMapping({
current: { source, destination },
next: { source, destination: value },
});
};

return (
<DataListItem aria-labelledby="">
<DataListItemRow>
Expand All @@ -64,13 +88,7 @@ export const MappingListItem: FC<MappingListItemProps> = ({
variant={SelectVariant.single}
aria-label=""
onToggle={setToggleSrcOpen}
onSelect={(event, value: string, isPlaceholder: boolean) =>
!isPlaceholder &&
replaceMapping({
current: { source, destination },
next: { source: value, destination },
})
}
onSelect={onSelectSource}
selections={source}
isOpen={isSrcOpen}
isDisabled={!isEditable}
Expand All @@ -89,12 +107,7 @@ export const MappingListItem: FC<MappingListItemProps> = ({
variant={SelectVariant.single}
aria-label=""
onToggle={setToggleTrgOpen}
onSelect={(event, value: string) =>
replaceMapping({
current: { source, destination },
next: { source, destination: value },
})
}
onSelect={onSelectDestination}
selections={destination}
isOpen={isTrgOpen}
isDisabled={!isEditable}
Expand Down
Loading