[Enterprise Search] Search Apps. - add popover to disabled button (#154769)

## Summary



https://user-images.githubusercontent.com/1699281/231268612-a94fbd46-19bd-407d-a75c-576313843792.mov


### Checklist

Delete any items that are not applicable to this PR.

- [x] Any text added follows [EUI's writing
guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses
sentence case text and includes [i18n
support](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md)
- [x] Any UI touched in this PR is usable by keyboard only (learn more
about [keyboard accessibility](https://webaim.org/techniques/keyboard/))
- [x] This renders correctly on smaller devices using a responsive
layout. (You can test this [in your
browser](https://www.browserstack.com/guide/responsive-testing-on-local-server))
- [x] This was checked for [cross-browser
compatibility](https://www.elastic.co/support/matrix#matrix_browsers)
This commit is contained in:
Sloane Perrault 2023-04-12 09:18:02 -04:00 committed by GitHub
parent aefc949911
commit 54f8ca1a33
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 173 additions and 14 deletions

View file

@ -9,7 +9,7 @@ import { setMockActions, setMockValues } from '../../../__mocks__/kea_logic';
import React from 'react';
import { shallow } from 'enzyme';
import { mount, shallow } from 'enzyme';
import { Status } from '../../../../../common/types/api';
@ -117,3 +117,117 @@ describe('EnginesList', () => {
expect(wrapper.find(LicensingCallout)).toHaveLength(0);
});
});
describe('CreateEngineButton', () => {
describe('disabled={true}', () => {
it('renders a disabled button that shows a popover when focused', () => {
const wrapper = mount(<CreateEngineButton disabled />);
const button = wrapper.find(
'button[data-test-subj="enterprise-search-content-engines-creation-button"]'
);
expect(button).toHaveLength(1);
expect(button.prop('disabled')).toBeTruthy();
let popover = wrapper.find('div[data-test-subj="create-engine-button-popover-content"]');
expect(popover).toHaveLength(0);
const hoverTarget = wrapper.find('div[data-test-subj="create-engine-button-hover-target"]');
expect(hoverTarget).toHaveLength(1);
hoverTarget.simulate('focus');
wrapper.update();
popover = wrapper.find('div[data-test-subj="create-engine-button-popover-content"]');
expect(popover).toHaveLength(1);
expect(popover.text()).toMatch('Search Applications require a Platinum license');
});
it('renders a disabled button that shows a popover when hovered', () => {
const wrapper = mount(<CreateEngineButton disabled />);
const button = wrapper.find(
'button[data-test-subj="enterprise-search-content-engines-creation-button"]'
);
expect(button).toHaveLength(1);
expect(button.prop('disabled')).toBeTruthy();
let popover = wrapper.find('div[data-test-subj="create-engine-button-popover-content"]');
expect(popover).toHaveLength(0);
const hoverTarget = wrapper.find('div[data-test-subj="create-engine-button-hover-target"]');
expect(hoverTarget).toHaveLength(1);
hoverTarget.simulate('mouseEnter');
wrapper.update();
popover = wrapper.find('div[data-test-subj="create-engine-button-popover-content"]');
expect(popover).toHaveLength(1);
expect(popover.text()).toMatch('Search Applications require a Platinum license');
});
});
describe('disabled={false}', () => {
it('renders a button and does not show a popover when focused', () => {
const wrapper = mount(<CreateEngineButton disabled={false} />);
const button = wrapper.find(
'button[data-test-subj="enterprise-search-content-engines-creation-button"]'
);
expect(button).toHaveLength(1);
expect(button.prop('disabled')).toBeFalsy();
let popover = wrapper.find('div[data-test-subj="create-engine-button-popover-content"]');
expect(popover).toHaveLength(0);
const hoverTarget = wrapper.find('div[data-test-subj="create-engine-button-hover-target"]');
expect(hoverTarget).toHaveLength(1);
hoverTarget.simulate('focus');
wrapper.update();
popover = wrapper.find('div[data-test-subj="create-engine-button-popover-content"]');
expect(popover).toHaveLength(0);
});
it('renders a button and does not show a popover when hovered', () => {
const wrapper = mount(<CreateEngineButton disabled={false} />);
const button = wrapper.find(
'button[data-test-subj="enterprise-search-content-engines-creation-button"]'
);
expect(button).toHaveLength(1);
expect(button.prop('disabled')).toBeFalsy();
let popover = wrapper.find('div[data-test-subj="create-engine-button-popover-content"]');
expect(popover).toHaveLength(0);
const hoverTarget = wrapper.find('div[data-test-subj="create-engine-button-hover-target"]');
expect(hoverTarget).toHaveLength(1);
hoverTarget.simulate('mouseEnter');
wrapper.update();
popover = wrapper.find('div[data-test-subj="create-engine-button-popover-content"]');
expect(popover).toHaveLength(0);
});
});
});

View file

@ -5,12 +5,22 @@
* 2.0.
*/
import React, { useEffect } from 'react';
import React, { useEffect, useState } from 'react';
import { useActions, useValues } from 'kea';
import useThrottle from 'react-use/lib/useThrottle';
import { EuiButton, EuiFlexItem, EuiFieldSearch, EuiLink, EuiSpacer, EuiText } from '@elastic/eui';
import {
EuiButton,
EuiFieldSearch,
EuiFlexGroup,
EuiFlexItem,
EuiLink,
EuiPopover,
EuiPopoverTitle,
EuiSpacer,
EuiText,
} from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { FormattedMessage, FormattedNumber } from '@kbn/i18n-react';
@ -20,6 +30,7 @@ import { docLinks } from '../../../shared/doc_links';
import { KibanaLogic } from '../../../shared/kibana';
import { LicensingLogic } from '../../../shared/licensing';
import { EXPLORE_PLATINUM_FEATURES_LINK } from '../../../workplace_search/constants';
import { EnterpriseSearchEnginesPageTemplate } from '../layout/engines_page_template';
import { LicensingCallout, LICENSING_FEATURE } from '../shared/licensing_callout/licensing_callout';
@ -33,20 +44,54 @@ import { EnginesListFlyoutLogic } from './engines_list_flyout_logic';
import { EnginesListLogic } from './engines_list_logic';
export const CreateEngineButton: React.FC<{ disabled: boolean }> = ({ disabled }) => {
const [showPopover, setShowPopover] = useState<boolean>(false);
const { openEngineCreate } = useActions(EnginesListLogic);
return (
<EuiButton
fill
iconType="plusInCircle"
data-test-subj="enterprise-search-content-engines-creation-button"
data-telemetry-id="entSearchContent-engines-list-createEngine"
disabled={disabled}
onClick={openEngineCreate}
<EuiPopover
isOpen={disabled && showPopover}
closePopover={() => setShowPopover(false)}
button={
<div
data-test-subj="create-engine-button-hover-target"
onMouseEnter={() => setShowPopover(true)}
onFocus={() => setShowPopover(true)}
tabIndex={0}
>
<EuiButton
fill
iconType="plusInCircle"
data-test-subj="enterprise-search-content-engines-creation-button"
data-telemetry-id="entSearchContent-engines-list-createEngine"
disabled={disabled}
onClick={openEngineCreate}
>
{i18n.translate('xpack.enterpriseSearch.content.engines.createEngineButtonLabel', {
defaultMessage: 'Create Search Application',
})}
</EuiButton>
</div>
}
>
{i18n.translate('xpack.enterpriseSearch.content.engines.createEngineButtonLabel', {
defaultMessage: 'Create Search Application',
})}
</EuiButton>
<EuiPopoverTitle>
<FormattedMessage
id="xpack.enterpriseSearch.content.engines.createEngineDisabledPopover.title"
defaultMessage="Platinum only feature"
/>
</EuiPopoverTitle>
<div style={{ width: '300px' }} data-test-subj="create-engine-button-popover-content">
<EuiFlexGroup direction="column" gutterSize="m">
<EuiText size="s">
<FormattedMessage
id="xpack.enterpriseSearch.content.engines.createEngineDisabledPopover.body"
defaultMessage="Search Applications require a Platinum license or higher and are not available to Standard license self-managed deployments."
/>
</EuiText>
<EuiLink target="_blank" href={docLinks.licenseManagement}>
{EXPLORE_PLATINUM_FEATURES_LINK}
</EuiLink>
</EuiFlexGroup>
</div>
</EuiPopover>
);
};