Skip to content

Commit

Permalink
fix: sonar duplication
Browse files Browse the repository at this point in the history
sonar duplication
  • Loading branch information
815are committed Oct 24, 2024
1 parent d7f4d03 commit c1483b4
Show file tree
Hide file tree
Showing 5 changed files with 143 additions and 175 deletions.
79 changes: 4 additions & 75 deletions packages/ui-components/src/components/UIComboBox/UIComboBox.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from 'react';
import type { IComboBoxProps, IComboBoxState, IAutofillProps, IButtonProps, ICalloutProps } from '@fluentui/react';
import type { IComboBoxProps, IComboBoxState, IAutofillProps, IButtonProps } from '@fluentui/react';
import {
ComboBox,
IComboBox,
Expand All @@ -18,7 +18,7 @@ import { UiIcons } from '../Icons';
import type { UIMessagesExtendedProps, InputValidationMessageInfo } from '../../helper/ValidationMessage';
import { getMessageInfo, MESSAGE_TYPES_CLASSNAME_MAP } from '../../helper/ValidationMessage';
import { labelGlobalStyle } from '../UILabel';
import { isDropdownEmpty, getCalloutCollisionTransformationProps } from '../UIDropdown';
import { isDropdownEmpty, getCalloutCollisionTransformationPropsForDropdown } from '../UIDropdown';
import { CalloutCollisionTransform } from '../UICallout';
import { isHTMLInputElement } from '../../utilities';

Expand Down Expand Up @@ -116,7 +116,7 @@ export class UIComboBox extends React.Component<UIComboBoxProps, UIComboBoxState
private query = '';
private ignoreOpenKeys: Array<string> = ['Meta', 'Control', 'Shift', 'Tab', 'Alt', 'CapsLock'];
private isListHidden = false;
private calloutCollisionTransform = new CalloutCollisionTransform(this.comboboxDomRef, this.menuDomRef);
public readonly calloutCollisionTransform = new CalloutCollisionTransform(this.comboboxDomRef, this.menuDomRef);

/**
* Initializes component properties.
Expand All @@ -139,9 +139,6 @@ export class UIComboBox extends React.Component<UIComboBoxProps, UIComboBoxState
this.onScrollToItem = this.onScrollToItem.bind(this);
this.setFocus = this.setFocus.bind(this);
this.onRenderIcon = this.onRenderIcon.bind(this);
this.preventDismissOnEvent = this.preventDismissOnEvent.bind(this);
this.onLayerDidMount = this.onLayerDidMount.bind(this);
this.onLayerWillUnmount = this.onLayerWillUnmount.bind(this);

initializeComponentRef(this);

Expand Down Expand Up @@ -710,69 +707,6 @@ export class UIComboBox extends React.Component<UIComboBoxProps, UIComboBoxState
return defaultRender?.(props) ?? null;
}

/**
* Method returns additional callout props for callout collision transformation if feature is enabled.
*
* @returns Callout props to enable callout collision transformation.
*/
private getCalloutCollisionTransformationProps(): ICalloutProps {
return (
getCalloutCollisionTransformationProps(
this.calloutCollisionTransform,
this.props.multiSelect,
this.props.calloutCollisionTransformation
) ?? {}
);
}

/**
* Method prevents callout dismiss/close if focus/click on target elements.
*
* @param event Triggered event to check.
* @returns Returns true if callout should not be closed.
*/
private preventDismissOnEvent(
event: Event | React.FocusEvent<Element> | React.KeyboardEvent<Element> | React.MouseEvent<Element, MouseEvent>
): boolean {
let preventDismiss = false;
if (this.props.calloutProps?.preventDismissOnEvent) {
preventDismiss = this.props.calloutProps.preventDismissOnEvent(event);
}
if (!preventDismiss) {
const { preventDismissOnEvent } = this.getCalloutCollisionTransformationProps();
if (preventDismissOnEvent) {
return preventDismissOnEvent(event);
}
}
return preventDismiss;
}

/**
* Callback for when the callout layer is mounted.
*/
private onLayerDidMount(): void {
const { layerProps } = this.getCalloutCollisionTransformationProps();
if (this.props.calloutProps?.layerProps?.onLayerDidMount) {
this.props.calloutProps?.layerProps?.onLayerDidMount();
}
if (layerProps?.onLayerDidMount) {
layerProps.onLayerDidMount();
}
}

/**
* Callback for when the callout layer is unmounted.
*/
private onLayerWillUnmount(): void {
const { layerProps } = this.getCalloutCollisionTransformationProps();
if (this.props.calloutProps?.layerProps?.onLayerWillUnmount) {
this.props.calloutProps?.layerProps?.onLayerWillUnmount();
}
if (layerProps?.onLayerWillUnmount) {
layerProps.onLayerWillUnmount();
}
}

/**
* @returns {JSX.Element}
*/
Expand Down Expand Up @@ -830,12 +764,7 @@ export class UIComboBox extends React.Component<UIComboBoxProps, UIComboBoxState
},

...this.props.calloutProps,
preventDismissOnEvent: this.preventDismissOnEvent,
layerProps: {
...this.props.calloutProps?.layerProps,
onLayerDidMount: this.onLayerDidMount,
onLayerWillUnmount: this.onLayerWillUnmount
}
...getCalloutCollisionTransformationPropsForDropdown(this)
}}
{...(this.props.highlight && {
onInput: this.onInput,
Expand Down
80 changes: 4 additions & 76 deletions packages/ui-components/src/components/UIDropdown/UIDropdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,15 @@ import type {
IDropdownProps,
IDropdownStyles,
ICalloutContentStyleProps,
ICalloutContentStyles,
ICalloutProps
ICalloutContentStyles
} from '@fluentui/react';
import { Dropdown, DropdownMenuItemType, IDropdownOption, ResponsiveMode } from '@fluentui/react';

import { UIIcon } from '../UIIcon';
import type { UIMessagesExtendedProps, InputValidationMessageInfo } from '../../helper/ValidationMessage';
import { getMessageInfo, MESSAGE_TYPES_CLASSNAME_MAP } from '../../helper/ValidationMessage';
import { labelGlobalStyle } from '../UILabel';
import { isDropdownEmpty, getCalloutCollisionTransformationProps } from './utils';
import { isDropdownEmpty, getCalloutCollisionTransformationPropsForDropdown } from './utils';
import { CalloutCollisionTransform } from '../UICallout';

import './UIDropdown.scss';
Expand Down Expand Up @@ -64,7 +63,7 @@ const ERROR_BORDER_COLOR = 'var(--vscode-inputValidation-errorBorder)';
export class UIDropdown extends React.Component<UIDropdownProps, UIDropdownState> {
private dropdownDomRef = React.createRef<HTMLDivElement>();
private menuDomRef = React.createRef<HTMLDivElement>();
private calloutCollisionTransform = new CalloutCollisionTransform(this.dropdownDomRef, this.menuDomRef);
public readonly calloutCollisionTransform = new CalloutCollisionTransform(this.dropdownDomRef, this.menuDomRef);

/**
* Initializes component properties.
Expand All @@ -78,9 +77,6 @@ export class UIDropdown extends React.Component<UIDropdownProps, UIDropdownState
options: [],
isOpen: false
};
this.preventDismissOnEvent = this.preventDismissOnEvent.bind(this);
this.onLayerDidMount = this.onLayerDidMount.bind(this);
this.onLayerWillUnmount = this.onLayerWillUnmount.bind(this);
}

onRenderCaretDown = (): JSX.Element => {
Expand Down Expand Up @@ -286,69 +282,6 @@ export class UIDropdown extends React.Component<UIDropdownProps, UIDropdownState
return additionalProps;
}

/**
* Method returns additional callout props for callout collision transformation if feature is enabled.
*
* @returns Callout props to enable callout collision transformation.
*/
private getCalloutCollisionTransformationProps(): ICalloutProps {
return (
getCalloutCollisionTransformationProps(
this.calloutCollisionTransform,
this.props.multiSelect,
this.props.calloutCollisionTransformation
) ?? {}
);
}

/**
* Method prevents callout dismiss/close if focus/click on target elements.
*
* @param event Triggered event to check.
* @returns Returns true if callout should not be closed.
*/
private preventDismissOnEvent(
event: Event | React.FocusEvent<Element> | React.KeyboardEvent<Element> | React.MouseEvent<Element, MouseEvent>
): boolean {
let preventDismiss = false;
if (this.props.calloutProps?.preventDismissOnEvent) {
preventDismiss = this.props.calloutProps.preventDismissOnEvent(event);
}
if (!preventDismiss) {
const { preventDismissOnEvent } = this.getCalloutCollisionTransformationProps();
if (preventDismissOnEvent) {
return preventDismissOnEvent(event);
}
}
return preventDismiss;
}

/**
* Callback for when the callout layer is mounted.
*/
private onLayerDidMount(): void {
const { layerProps } = this.getCalloutCollisionTransformationProps();
if (this.props.calloutProps?.layerProps?.onLayerDidMount) {
this.props.calloutProps?.layerProps?.onLayerDidMount();
}
if (layerProps?.onLayerDidMount) {
layerProps.onLayerDidMount();
}
}

/**
* Callback for when the callout layer is unmounted.
*/
private onLayerWillUnmount(): void {
const { layerProps } = this.getCalloutCollisionTransformationProps();
if (this.props.calloutProps?.layerProps?.onLayerWillUnmount) {
this.props.calloutProps?.layerProps?.onLayerWillUnmount();
}
if (layerProps?.onLayerWillUnmount) {
layerProps.onLayerWillUnmount();
}
}

/**
* @returns {JSX.Element}
*/
Expand Down Expand Up @@ -397,12 +330,7 @@ export class UIDropdown extends React.Component<UIDropdownProps, UIDropdownState
ref: this.menuDomRef
},
...this.props.calloutProps,
preventDismissOnEvent: this.preventDismissOnEvent,
layerProps: {
...this.props.calloutProps?.layerProps,
onLayerDidMount: this.onLayerDidMount,
onLayerWillUnmount: this.onLayerWillUnmount
}
...getCalloutCollisionTransformationPropsForDropdown(this)
}}
onRenderOption={this.onRenderOption.bind(this)}
onRenderItem={this.onRenderItem.bind(this)}
Expand Down
102 changes: 102 additions & 0 deletions packages/ui-components/src/components/UIDropdown/utils.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import type { IDropdownProps, IComboBoxProps, ICalloutProps } from '@fluentui/react';
import type { CalloutCollisionTransform } from '../UICallout';
import type { UIDropdown } from './UIDropdown';
import type { UIComboBox } from '../UIComboBox';

/**
* Method checks if drodpown or combobox is empty or any value is selected.
Expand Down Expand Up @@ -44,3 +46,103 @@ export function getCalloutCollisionTransformationProps(
}
return undefined;
}

/**
* Method returns callback function to 'onLayerDidMount' property of dropdown 'callout'.
*
* @param dropdown Instance of dropdown.
* @returns Returns callback function to 'onLayerDidMount' property of dropdown 'callout'.
*/
function getOnLayerDidMount(dropdown: UIDropdown | UIComboBox): () => void {
return () => {
const { layerProps } =
getCalloutCollisionTransformationProps(
dropdown.calloutCollisionTransform,
dropdown.props.multiSelect,
dropdown.props.calloutCollisionTransformation
) ?? {};
if (dropdown.props.calloutProps?.layerProps?.onLayerDidMount) {
dropdown.props.calloutProps?.layerProps?.onLayerDidMount();
}
if (layerProps?.onLayerDidMount) {
layerProps.onLayerDidMount();
}
};
}

/**
* Method returns callback function to 'onLayerWillUnmount' property of dropdown 'callout'.
*
* @param dropdown Instance of dropdown.
* @returns Returns callback function to 'onLayerWillUnmount' property of dropdown 'callout'.
*/
function getOnLayerWillUnmount(dropdown: UIDropdown | UIComboBox): () => void {
return () => {
const { layerProps } =
getCalloutCollisionTransformationProps(
dropdown.calloutCollisionTransform,
dropdown.props.multiSelect,
dropdown.props.calloutCollisionTransformation
) ?? {};
if (dropdown.props.calloutProps?.layerProps?.onLayerWillUnmount) {
dropdown.props.calloutProps?.layerProps?.onLayerWillUnmount();
}
if (layerProps?.onLayerWillUnmount) {
layerProps.onLayerWillUnmount();
}
};
}

/**
* Method returns callback function to 'preventDismissOnEvent' property of dropdown 'callout', which prevents callout dismiss/close if focus/click on target elements.
*
* @param dropdown Instance of dropdown.
* @returns Returns callback function to 'preventDismissOnEvent' property of dropdown 'callout'.
*/
function getPreventDismissOnEvent(
dropdown: UIDropdown | UIComboBox
): (
event: Event | React.FocusEvent<Element> | React.KeyboardEvent<Element> | React.MouseEvent<Element, MouseEvent>
) => boolean {
return (event) => {
let preventDismiss = false;
if (dropdown.props.calloutProps?.preventDismissOnEvent) {
preventDismiss = dropdown.props.calloutProps.preventDismissOnEvent(event);
}
if (!preventDismiss) {
const { preventDismissOnEvent } =
getCalloutCollisionTransformationProps(
dropdown.calloutCollisionTransform,
dropdown.props.multiSelect,
dropdown.props.calloutCollisionTransformation
) ?? {};
if (preventDismissOnEvent) {
return preventDismissOnEvent(event);
}
}
return preventDismiss;
};
}

/**
* Method returns additional callout props for callout collision transformation if feature is enabled.
* Callout collision transformation checks if dropdown menu overlaps with dialog action/submit buttons
* and if overlap happens, then additional offset is applied to make action buttons visible.
*
* @param dropdown Instance of dropdown.
* @returns Callout props to enable callout collision transformation.
*/
export function getCalloutCollisionTransformationPropsForDropdown(
dropdown: UIDropdown | UIComboBox
): ICalloutProps | undefined {
if (dropdown.props.multiSelect && dropdown.props.calloutCollisionTransformation) {
return {
preventDismissOnEvent: getPreventDismissOnEvent(dropdown),
layerProps: {
onLayerDidMount: getOnLayerDidMount(dropdown),
onLayerWillUnmount: getOnLayerWillUnmount(dropdown)
}
};
}
return undefined;
}
30 changes: 16 additions & 14 deletions packages/ui-components/test/unit/components/UICombobox.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -792,16 +792,22 @@ describe('<UIComboBox />', () => {
const dropdown = wrapper.find(ComboBox);
expect(dropdown.length).toEqual(1);
const calloutProps = dropdown.prop('calloutProps');
expect(calloutProps?.preventDismissOnEvent).toBeDefined();
expect(calloutProps?.layerProps?.onLayerDidMount).toBeDefined();
expect(calloutProps?.layerProps?.onLayerWillUnmount).toBeDefined();

calloutProps?.preventDismissOnEvent?.({} as Event);
calloutProps?.layerProps?.onLayerDidMount?.();
calloutProps?.layerProps?.onLayerWillUnmount?.();
expect(CalloutCollisionTransformSpy.preventDismissOnEvent).toBeCalledTimes(expected ? 1 : 0);
expect(CalloutCollisionTransformSpy.applyTransformation).toBeCalledTimes(expected ? 1 : 0);
expect(CalloutCollisionTransformSpy.resetTransformation).toBeCalledTimes(expected ? 1 : 0);
if (expected) {
expect(calloutProps?.preventDismissOnEvent).toBeDefined();
expect(calloutProps?.layerProps?.onLayerDidMount).toBeDefined();
expect(calloutProps?.layerProps?.onLayerWillUnmount).toBeDefined();

calloutProps?.preventDismissOnEvent?.({} as Event);
calloutProps?.layerProps?.onLayerDidMount?.();
calloutProps?.layerProps?.onLayerWillUnmount?.();
expect(CalloutCollisionTransformSpy.preventDismissOnEvent).toBeCalledTimes(expected ? 1 : 0);
expect(CalloutCollisionTransformSpy.applyTransformation).toBeCalledTimes(expected ? 1 : 0);
expect(CalloutCollisionTransformSpy.resetTransformation).toBeCalledTimes(expected ? 1 : 0);
} else {
expect(calloutProps?.preventDismissOnEvent).toBeUndefined();
expect(calloutProps?.layerProps?.onLayerDidMount).toBeUndefined();
expect(calloutProps?.layerProps?.onLayerWillUnmount).toBeUndefined();
}
});
}

Expand All @@ -823,10 +829,6 @@ describe('<UIComboBox />', () => {
const dropdown = wrapper.find(ComboBox);
expect(dropdown.length).toEqual(1);
const calloutProps = dropdown.prop('calloutProps');
// if (expected) {
expect(calloutProps?.preventDismissOnEvent).toBeDefined();
expect(calloutProps?.layerProps?.onLayerDidMount).toBeDefined();
expect(calloutProps?.layerProps?.onLayerWillUnmount).toBeDefined();

calloutProps?.preventDismissOnEvent?.({} as Event);
calloutProps?.layerProps?.onLayerDidMount?.();
Expand Down
Loading

0 comments on commit c1483b4

Please sign in to comment.