[App Search] Add custom actions prop to Result component (#94378)

* Add custom actions prop to Result component

- will be used by upcoming Curations work to promote and hide documents

* Add Result custom actions to library

+ [misc] export main Result component from index
This commit is contained in:
Constance 2021-03-11 08:40:31 -08:00 committed by GitHub
parent dee1272dd6
commit 8be1dd7c54
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 84 additions and 3 deletions

View file

@ -5,7 +5,7 @@
* 2.0.
*/
import React from 'react';
import React, { useState } from 'react';
import {
EuiSpacer,
@ -18,7 +18,7 @@ import {
import { SetAppSearchChrome as SetPageChrome } from '../../../shared/kibana_chrome';
import { Schema } from '../../../shared/types';
import { Result } from '../result/result';
import { Result } from '../result';
export const Library: React.FC = () => {
const props = {
@ -70,6 +70,16 @@ export const Library: React.FC = () => {
length: 'number',
};
const [isActionButtonFilled, setIsActionButtonFilled] = useState(false);
const actions = [
{
title: 'Fill this action button',
onClick: () => setIsActionButtonFilled(!isActionButtonFilled),
iconType: isActionButtonFilled ? 'starFilled' : 'starEmpty',
iconColor: 'primary',
},
];
return (
<>
<SetPageChrome trail={['Library']} />
@ -202,6 +212,22 @@ export const Library: React.FC = () => {
<Result {...props} shouldLinkToDetailPage />
<EuiSpacer />
<EuiSpacer />
<EuiTitle size="s">
<h3>With custom actions</h3>
</EuiTitle>
<EuiSpacer />
<Result {...props} actions={actions} />
<EuiSpacer />
<EuiSpacer />
<EuiTitle size="s">
<h3>With custom actions and a link</h3>
</EuiTitle>
<EuiSpacer />
<Result {...props} actions={actions} shouldLinkToDetailPage />
<EuiSpacer />
<EuiSpacer />
<EuiTitle size="s">
<h3>With field value type highlights</h3>

View file

@ -6,3 +6,4 @@
*/
export { ResultFieldValue } from './result_field_value';
export { Result } from './result';

View file

@ -96,6 +96,39 @@ describe('Result', () => {
});
});
describe('actions', () => {
const actions = [
{
title: 'Hide',
onClick: jest.fn(),
iconType: 'eyeClosed',
iconColor: 'danger',
},
{
title: 'Bookmark',
onClick: jest.fn(),
iconType: 'starFilled',
iconColor: 'primary',
},
];
it('will render an action button for each action passed', () => {
const wrapper = shallow(<Result {...props} actions={actions} />);
expect(wrapper.find('.appSearchResult__actionButton')).toHaveLength(2);
wrapper.find('.appSearchResult__actionButton').first().simulate('click');
expect(actions[0].onClick).toHaveBeenCalled();
wrapper.find('.appSearchResult__actionButton').last().simulate('click');
expect(actions[1].onClick).toHaveBeenCalled();
});
it('will render custom actions seamlessly next to the document detail link', () => {
const wrapper = shallow(<Result {...props} actions={actions} shouldLinkToDetailPage />);
expect(wrapper.find('.appSearchResult__actionButton')).toHaveLength(3);
});
});
it('will render field details with type highlights if schemaForTypeHighlights has been provided', () => {
const wrapper = shallow(
<Result {...props} shouldLinkToDetailPage schemaForTypeHighlights={schema} />

View file

@ -22,7 +22,7 @@ import { generateEncodedPath } from '../../utils/encode_path_params';
import { ResultField } from './result_field';
import { ResultHeader } from './result_header';
import { FieldValue, Result as ResultType } from './types';
import { FieldValue, Result as ResultType, ResultAction } from './types';
interface Props {
result: ResultType;
@ -30,6 +30,7 @@ interface Props {
showScore?: boolean;
shouldLinkToDetailPage?: boolean;
schemaForTypeHighlights?: Schema;
actions?: ResultAction[];
}
const RESULT_CUTOFF = 5;
@ -40,6 +41,7 @@ export const Result: React.FC<Props> = ({
showScore = false,
shouldLinkToDetailPage = false,
schemaForTypeHighlights,
actions = [],
}) => {
const [isOpen, setIsOpen] = useState(false);
@ -142,6 +144,18 @@ export const Result: React.FC<Props> = ({
</a>
</ReactRouterHelper>
)}
{actions.map(({ onClick, title, iconType, iconColor }) => (
<button
key={title}
aria-label={title}
title={title}
onClick={onClick}
className="appSearchResult__actionButton"
type="button"
>
<EuiIcon type={iconType} color={iconColor} />
</button>
))}
</div>
</EuiPanel>
);

View file

@ -33,3 +33,10 @@ export type Result = {
// You'll need to cast it to FieldValue whenever you use it.
[key: string]: object;
};
export interface ResultAction {
onClick(): void;
title: string;
iconType: string;
iconColor?: string;
}