[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:
parent
dee1272dd6
commit
8be1dd7c54
|
@ -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>
|
||||
|
|
|
@ -6,3 +6,4 @@
|
|||
*/
|
||||
|
||||
export { ResultFieldValue } from './result_field_value';
|
||||
export { Result } from './result';
|
||||
|
|
|
@ -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} />
|
||||
|
|
|
@ -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>
|
||||
);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue