Fix search date suggestion crash (#26476)
* Fix search date suggestion crash * Fix tests * Improve snapshots * Fix snapshot
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
1383d51436
Коммит
8e43d45b3f
@@ -24,4 +24,4 @@ function mapStateToProps(state: GlobalState) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export default connect(mapStateToProps)(SearchDateSuggestion);
|
export default connect(mapStateToProps, null, null, {forwardRef: true})(SearchDateSuggestion);
|
||||||
|
|||||||
@@ -15,9 +15,9 @@ import 'react-day-picker/dist/style.css';
|
|||||||
|
|
||||||
type Props = SuggestionProps<never> & {
|
type Props = SuggestionProps<never> & {
|
||||||
currentDate?: Date;
|
currentDate?: Date;
|
||||||
handleEscape: () => void;
|
handleEscape?: () => void;
|
||||||
locale: string;
|
locale: string;
|
||||||
preventClose: () => void;
|
preventClose?: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default class SearchDateSuggestion extends React.PureComponent<Props> {
|
export default class SearchDateSuggestion extends React.PureComponent<Props> {
|
||||||
@@ -36,7 +36,7 @@ export default class SearchDateSuggestion extends React.PureComponent<Props> {
|
|||||||
if (Keyboard.isKeyPressed(e, Constants.KeyCodes.DOWN) && document.activeElement?.id === 'searchBox') {
|
if (Keyboard.isKeyPressed(e, Constants.KeyCodes.DOWN) && document.activeElement?.id === 'searchBox') {
|
||||||
this.setState({datePickerFocused: true});
|
this.setState({datePickerFocused: true});
|
||||||
} else if (Keyboard.isKeyPressed(e, Constants.KeyCodes.ESCAPE)) {
|
} else if (Keyboard.isKeyPressed(e, Constants.KeyCodes.ESCAPE)) {
|
||||||
this.props.handleEscape();
|
this.props.handleEscape?.();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import Popover from 'components/widgets/popover';
|
|||||||
import Constants from 'utils/constants';
|
import Constants from 'utils/constants';
|
||||||
|
|
||||||
import type {UserProfile} from './command_provider/app_command_parser/app_command_parser_dependencies';
|
import type {UserProfile} from './command_provider/app_command_parser/app_command_parser_dependencies';
|
||||||
|
import type {Props} from './suggestion_list';
|
||||||
import SuggestionList from './suggestion_list';
|
import SuggestionList from './suggestion_list';
|
||||||
|
|
||||||
interface Item extends UserProfile {
|
interface Item extends UserProfile {
|
||||||
@@ -18,34 +19,6 @@ interface Item extends UserProfile {
|
|||||||
name: string;
|
name: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Props {
|
|
||||||
ariaLiveRef?: React.RefObject<HTMLDivElement>;
|
|
||||||
inputRef?: React.RefObject<HTMLInputElement>;
|
|
||||||
open: boolean;
|
|
||||||
position?: 'top' | 'bottom';
|
|
||||||
renderDividers?: string[];
|
|
||||||
renderNoResults?: boolean;
|
|
||||||
onCompleteWord: (term: string, matchedPretext: string, e?: React.KeyboardEventHandler<HTMLDivElement>) => boolean;
|
|
||||||
preventClose?: () => void;
|
|
||||||
onItemHover: (term: string) => void;
|
|
||||||
pretext: string;
|
|
||||||
cleared: boolean;
|
|
||||||
matchedPretext: string[];
|
|
||||||
items: any[];
|
|
||||||
terms: string[];
|
|
||||||
selection: string;
|
|
||||||
components: Array<React.FunctionComponent<any>>;
|
|
||||||
wrapperHeight?: number;
|
|
||||||
|
|
||||||
// suggestionBoxAlgn is an optional object that can be passed to align the SuggestionList with the keyboard caret
|
|
||||||
// as the user is typing.
|
|
||||||
suggestionBoxAlgn?: {
|
|
||||||
lineHeight: number;
|
|
||||||
pixelsToMoveX: number;
|
|
||||||
pixelsToMoveY: number;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export default class SearchSuggestionList extends SuggestionList {
|
export default class SearchSuggestionList extends SuggestionList {
|
||||||
popoverRef: React.RefObject<BSPopover>;
|
popoverRef: React.RefObject<BSPopover>;
|
||||||
itemsContainerRef: React.RefObject<HTMLDivElement>;
|
itemsContainerRef: React.RefObject<HTMLDivElement>;
|
||||||
|
|||||||
@@ -6,8 +6,12 @@ import React, {memo} from 'react';
|
|||||||
import Popover from 'components/widgets/popover';
|
import Popover from 'components/widgets/popover';
|
||||||
|
|
||||||
type SuggestionItem = {
|
type SuggestionItem = {
|
||||||
|
date: string;
|
||||||
|
label: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
type SuggestionItemProps = {
|
||||||
key: string;
|
key: string;
|
||||||
ref: string;
|
|
||||||
item: SuggestionItem;
|
item: SuggestionItem;
|
||||||
term: string;
|
term: string;
|
||||||
matchedPretext: string;
|
matchedPretext: string;
|
||||||
@@ -24,7 +28,7 @@ type Props = {
|
|||||||
terms: string[];
|
terms: string[];
|
||||||
preventClose: () => void;
|
preventClose: () => void;
|
||||||
handleEscape: () => void;
|
handleEscape: () => void;
|
||||||
components: Array<React.ComponentType<SuggestionItem>>;
|
components: Array<React.ComponentType<SuggestionItemProps>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
const SuggestionDate = ({
|
const SuggestionDate = ({
|
||||||
@@ -54,7 +58,6 @@ const SuggestionDate = ({
|
|||||||
>
|
>
|
||||||
<Component
|
<Component
|
||||||
key={term}
|
key={term}
|
||||||
ref={term}
|
|
||||||
item={item}
|
item={item}
|
||||||
term={term}
|
term={term}
|
||||||
matchedPretext={matchedPretext[0]}
|
matchedPretext={matchedPretext[0]}
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import LoadingSpinner from 'components/widgets/loading/loading_spinner';
|
|||||||
import {Constants} from 'utils/constants';
|
import {Constants} from 'utils/constants';
|
||||||
import {isEmptyObject} from 'utils/utils';
|
import {isEmptyObject} from 'utils/utils';
|
||||||
|
|
||||||
interface Props {
|
export interface Props {
|
||||||
ariaLiveRef?: React.RefObject<HTMLDivElement>;
|
ariaLiveRef?: React.RefObject<HTMLDivElement>;
|
||||||
inputRef?: React.RefObject<HTMLDivElement>;
|
inputRef?: React.RefObject<HTMLDivElement>;
|
||||||
open: boolean;
|
open: boolean;
|
||||||
@@ -28,7 +28,7 @@ interface Props {
|
|||||||
items: any[];
|
items: any[];
|
||||||
terms: string[];
|
terms: string[];
|
||||||
selection: string;
|
selection: string;
|
||||||
components: Array<React.FunctionComponent<any>>;
|
components: Array<React.ComponentType<any>>;
|
||||||
wrapperHeight?: number;
|
wrapperHeight?: number;
|
||||||
|
|
||||||
// suggestionBoxAlgn is an optional object that can be passed to align the SuggestionList with the keyboard caret
|
// suggestionBoxAlgn is an optional object that can be passed to align the SuggestionList with the keyboard caret
|
||||||
|
|||||||
@@ -56,7 +56,6 @@ exports[`component/user_group_popover should match snapshot 1`] = `
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
canManageGroup={true}
|
|
||||||
group={
|
group={
|
||||||
Object {
|
Object {
|
||||||
"allow_reference": true,
|
"allow_reference": true,
|
||||||
@@ -79,49 +78,8 @@ exports[`component/user_group_popover should match snapshot 1`] = `
|
|||||||
searchTerm=""
|
searchTerm=""
|
||||||
showUserOverlay={[MockFunction]}
|
showUserOverlay={[MockFunction]}
|
||||||
>
|
>
|
||||||
<Memo(Popover)
|
<Popover
|
||||||
actions={
|
|
||||||
Object {
|
|
||||||
"openModal": [MockFunction],
|
|
||||||
"searchProfiles": [MockFunction],
|
|
||||||
"setPopoverSearchTerm": [MockFunction] {
|
|
||||||
"calls": Array [
|
|
||||||
Array [
|
|
||||||
"",
|
|
||||||
],
|
|
||||||
],
|
|
||||||
"results": Array [
|
|
||||||
Object {
|
|
||||||
"type": "return",
|
|
||||||
"value": undefined,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
canManageGroup={true}
|
|
||||||
group={
|
|
||||||
Object {
|
|
||||||
"allow_reference": true,
|
|
||||||
"create_at": 1,
|
|
||||||
"delete_at": 0,
|
|
||||||
"description": "",
|
|
||||||
"display_name": "group_display_name",
|
|
||||||
"has_syncables": false,
|
|
||||||
"id": "group1",
|
|
||||||
"member_count": 15,
|
|
||||||
"name": "group_name",
|
|
||||||
"remote_id": "",
|
|
||||||
"scheme_admin": false,
|
|
||||||
"source": "",
|
|
||||||
"update_at": 1,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
hide={[MockFunction]}
|
|
||||||
id="user-group-popover"
|
id="user-group-popover"
|
||||||
returnFocus={[MockFunction]}
|
|
||||||
searchTerm=""
|
|
||||||
showUserOverlay={[MockFunction]}
|
|
||||||
>
|
>
|
||||||
<Popover
|
<Popover
|
||||||
bsClass="popover"
|
bsClass="popover"
|
||||||
@@ -2126,7 +2084,7 @@ exports[`component/user_group_popover should match snapshot 1`] = `
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Popover>
|
</Popover>
|
||||||
</Memo(Popover)>
|
</Popover>
|
||||||
</Memo(UserGroupPopover)>
|
</Memo(UserGroupPopover)>
|
||||||
</Router>
|
</Router>
|
||||||
</BrowserRouter>
|
</BrowserRouter>
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
// See LICENSE.txt for license information.
|
// See LICENSE.txt for license information.
|
||||||
|
|
||||||
import type {ReactWrapper} from 'enzyme';
|
import type {ReactWrapper} from 'enzyme';
|
||||||
|
import type {ComponentProps} from 'react';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import {Provider} from 'react-redux';
|
import {Provider} from 'react-redux';
|
||||||
import {BrowserRouter} from 'react-router-dom';
|
import {BrowserRouter} from 'react-router-dom';
|
||||||
@@ -100,10 +101,9 @@ describe('component/user_group_popover', () => {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const baseProps = {
|
const baseProps: ComponentProps<typeof UserGroupPopover> = {
|
||||||
searchTerm: '',
|
searchTerm: '',
|
||||||
group: group1,
|
group: group1,
|
||||||
canManageGroup: true,
|
|
||||||
showUserOverlay: jest.fn(),
|
showUserOverlay: jest.fn(),
|
||||||
hide: jest.fn(),
|
hide: jest.fn(),
|
||||||
returnFocus: jest.fn(),
|
returnFocus: jest.fn(),
|
||||||
|
|||||||
@@ -64,16 +64,14 @@ export type Props = {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const UserGroupPopover = (props: Props) => {
|
const UserGroupPopover = ({
|
||||||
const {
|
actions,
|
||||||
group,
|
group,
|
||||||
actions,
|
hide,
|
||||||
hide,
|
returnFocus,
|
||||||
returnFocus,
|
searchTerm,
|
||||||
searchTerm,
|
showUserOverlay,
|
||||||
showUserOverlay,
|
}: Props) => {
|
||||||
} = props;
|
|
||||||
|
|
||||||
const {formatMessage} = useIntl();
|
const {formatMessage} = useIntl();
|
||||||
|
|
||||||
const closeRef = useRef<HTMLButtonElement>(null);
|
const closeRef = useRef<HTMLButtonElement>(null);
|
||||||
@@ -183,7 +181,6 @@ const UserGroupPopover = (props: Props) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Popover
|
<Popover
|
||||||
{...props}
|
|
||||||
id='user-group-popover'
|
id='user-group-popover'
|
||||||
>
|
>
|
||||||
{tabCatcher}
|
{tabCatcher}
|
||||||
|
|||||||
@@ -19,10 +19,9 @@ interface Props {
|
|||||||
style?: React.CSSProperties;
|
style?: React.CSSProperties;
|
||||||
onMouseOut?: React.MouseEventHandler<BSPopover>; // didn't find a better way to satisfy typing, so for now we have a slight 'bootstrap leakage'
|
onMouseOut?: React.MouseEventHandler<BSPopover>; // didn't find a better way to satisfy typing, so for now we have a slight 'bootstrap leakage'
|
||||||
onMouseOver?: React.MouseEventHandler<BSPopover>;
|
onMouseOver?: React.MouseEventHandler<BSPopover>;
|
||||||
ref?: React.Ref<BSPopover>;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const Popover = ({
|
const Popover = React.forwardRef<BSPopover, Props>(({
|
||||||
placement = 'right',
|
placement = 'right',
|
||||||
popoverSize = 'sm',
|
popoverSize = 'sm',
|
||||||
children,
|
children,
|
||||||
@@ -33,8 +32,7 @@ const Popover = ({
|
|||||||
onMouseOver,
|
onMouseOver,
|
||||||
className,
|
className,
|
||||||
style,
|
style,
|
||||||
ref,
|
}, ref?) => {
|
||||||
}: Props) => {
|
|
||||||
return (
|
return (
|
||||||
<BSPopover
|
<BSPopover
|
||||||
id={id}
|
id={id}
|
||||||
@@ -45,13 +43,15 @@ const Popover = ({
|
|||||||
bsClass='popover'
|
bsClass='popover'
|
||||||
title={title}
|
title={title}
|
||||||
bsSize={popoverSize && SizeMap[popoverSize] as BSSizes} // map our sizes to bootstrap
|
bsSize={popoverSize && SizeMap[popoverSize] as BSSizes} // map our sizes to bootstrap
|
||||||
onMouseOut={onMouseOut!}
|
onMouseOut={onMouseOut}
|
||||||
onMouseOver={onMouseOver}
|
onMouseOver={onMouseOver}
|
||||||
ref={ref}
|
ref={ref}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
</BSPopover>
|
</BSPopover>
|
||||||
);
|
);
|
||||||
};
|
});
|
||||||
|
|
||||||
|
Popover.displayName = 'Popover';
|
||||||
|
|
||||||
export default React.memo(Popover);
|
export default React.memo(Popover);
|
||||||
|
|||||||
Ссылка в новой задаче
Block a user