mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 17:59:23 -04:00
# Backport This will backport the following commits from `main` to `8.11`: - [[Enterprise Search] fix: show/hide ent-search cards based on access (#168890)](https://github.com/elastic/kibana/pull/168890) <!--- Backport version: 8.9.7 --> ### Questions ? Please refer to the [Backport tool documentation](https://github.com/sqren/backport) <!--BACKPORT [{"author":{"name":"Rodney Norris","email":"rodney.norris@elastic.co"},"sourceCommit":{"committedDate":"2023-10-16T13:47:56Z","message":"[Enterprise Search] fix: show/hide ent-search cards based on access (#168890)\n\n## Summary\r\n\r\nWhen refactoring the Enterprise Search overview page we inadvertently\r\nremoved the access and admin checks for app search and workplace search\r\nproduct cards. This fix re-adds those checks.","sha":"f6a18581e8bbd692abe55f3dd24ec34f9bb347eb","branchLabelMapping":{"^v8.12.0$":"main","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["backport","release_note:fix","Team:EnterpriseSearch","v8.12.0","v8.11.1","v8.10.4"],"number":168890,"url":"https://github.com/elastic/kibana/pull/168890","mergeCommit":{"message":"[Enterprise Search] fix: show/hide ent-search cards based on access (#168890)\n\n## Summary\r\n\r\nWhen refactoring the Enterprise Search overview page we inadvertently\r\nremoved the access and admin checks for app search and workplace search\r\nproduct cards. This fix re-adds those checks.","sha":"f6a18581e8bbd692abe55f3dd24ec34f9bb347eb"}},"sourceBranch":"main","suggestedTargetBranches":["8.11","8.10"],"targetPullRequestStates":[{"branch":"main","label":"v8.12.0","labelRegex":"^v8.12.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/168890","number":168890,"mergeCommit":{"message":"[Enterprise Search] fix: show/hide ent-search cards based on access (#168890)\n\n## Summary\r\n\r\nWhen refactoring the Enterprise Search overview page we inadvertently\r\nremoved the access and admin checks for app search and workplace search\r\nproduct cards. This fix re-adds those checks.","sha":"f6a18581e8bbd692abe55f3dd24ec34f9bb347eb"}},{"branch":"8.11","label":"v8.11.1","labelRegex":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"},{"branch":"8.10","label":"v8.10.4","labelRegex":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"}]}] BACKPORT--> Co-authored-by: Rodney Norris <rodney.norris@elastic.co>
This commit is contained in:
parent
c275374166
commit
db0b55331c
7 changed files with 203 additions and 31 deletions
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import { setMockValues } from '../../../__mocks__/kea_logic';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import { mount } from 'enzyme';
|
||||
|
||||
import { AppSearchProductCard } from './app_search_product_card';
|
||||
import { EnterpriseSearchProductCard } from './enterprise_search_product_card';
|
||||
import { WorkplaceSearchProductCard } from './workplace_search_product_card';
|
||||
|
||||
describe('EnterpriseSearchProductCard', () => {
|
||||
beforeEach(() => {
|
||||
setMockValues({ config: { canDeployEntSearch: true, host: 'localhost' } });
|
||||
});
|
||||
|
||||
it('renders both services with access', () => {
|
||||
const wrapper = mount(
|
||||
<EnterpriseSearchProductCard
|
||||
hasAppSearchAccess
|
||||
hasWorkplaceSearchAccess
|
||||
isWorkplaceSearchAdmin
|
||||
/>
|
||||
);
|
||||
|
||||
expect(wrapper.find(AppSearchProductCard)).toHaveLength(1);
|
||||
expect(wrapper.find(WorkplaceSearchProductCard)).toHaveLength(1);
|
||||
});
|
||||
it('can render just app search', () => {
|
||||
const wrapper = mount(
|
||||
<EnterpriseSearchProductCard
|
||||
hasAppSearchAccess
|
||||
hasWorkplaceSearchAccess={false}
|
||||
isWorkplaceSearchAdmin={false}
|
||||
/>
|
||||
);
|
||||
|
||||
expect(wrapper.find(AppSearchProductCard)).toHaveLength(1);
|
||||
expect(wrapper.find(WorkplaceSearchProductCard)).toHaveLength(0);
|
||||
});
|
||||
it('can render just workplace search', () => {
|
||||
const wrapper = mount(
|
||||
<EnterpriseSearchProductCard
|
||||
hasAppSearchAccess={false}
|
||||
hasWorkplaceSearchAccess
|
||||
isWorkplaceSearchAdmin
|
||||
/>
|
||||
);
|
||||
|
||||
expect(wrapper.find(AppSearchProductCard)).toHaveLength(0);
|
||||
expect(wrapper.find(WorkplaceSearchProductCard)).toHaveLength(1);
|
||||
});
|
||||
});
|
|
@ -19,23 +19,45 @@ import { ProductCard } from '../product_card';
|
|||
import { AppSearchProductCard } from './app_search_product_card';
|
||||
import { WorkplaceSearchProductCard } from './workplace_search_product_card';
|
||||
|
||||
export const EnterpriseSearchProductCard = () => (
|
||||
<ProductCard
|
||||
description={i18n.translate('xpack.enterpriseSearch.entSearch.productCardDescription', {
|
||||
defaultMessage:
|
||||
'Standalone applications tailored to simpler, user-friendly and business-focused search experiences.',
|
||||
})}
|
||||
emptyCta
|
||||
cta={i18n.translate('xpack.enterpriseSearch.enterpriseSearchCard.cta', {
|
||||
defaultMessage: 'Learn more',
|
||||
})}
|
||||
url={docLinks.start}
|
||||
icon="logoEnterpriseSearch"
|
||||
name={ENTERPRISE_SEARCH_PRODUCT_NAME}
|
||||
productId={ENTERPRISE_SEARCH_CONTENT_PLUGIN.ID}
|
||||
rightPanelItems={[
|
||||
<AppSearchProductCard hasBorder={false} hasShadow={false} />,
|
||||
<WorkplaceSearchProductCard hasBorder={false} hasShadow={false} />,
|
||||
]}
|
||||
/>
|
||||
);
|
||||
export interface EnterpriseSearchProductCardProps {
|
||||
hasAppSearchAccess: boolean;
|
||||
hasWorkplaceSearchAccess: boolean;
|
||||
isWorkplaceSearchAdmin: boolean;
|
||||
}
|
||||
|
||||
export const EnterpriseSearchProductCard = ({
|
||||
hasAppSearchAccess,
|
||||
hasWorkplaceSearchAccess,
|
||||
isWorkplaceSearchAdmin,
|
||||
}: EnterpriseSearchProductCardProps) => {
|
||||
const rightPanelItems: React.ReactNode[] = [];
|
||||
if (hasAppSearchAccess) {
|
||||
rightPanelItems.push(<AppSearchProductCard hasBorder={false} hasShadow={false} />);
|
||||
}
|
||||
if (hasWorkplaceSearchAccess) {
|
||||
rightPanelItems.push(
|
||||
<WorkplaceSearchProductCard
|
||||
isWorkplaceSearchAdmin={isWorkplaceSearchAdmin}
|
||||
hasBorder={false}
|
||||
hasShadow={false}
|
||||
/>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<ProductCard
|
||||
description={i18n.translate('xpack.enterpriseSearch.entSearch.productCardDescription', {
|
||||
defaultMessage:
|
||||
'Standalone applications tailored to simpler, user-friendly and business-focused search experiences.',
|
||||
})}
|
||||
emptyCta
|
||||
cta={i18n.translate('xpack.enterpriseSearch.enterpriseSearchCard.cta', {
|
||||
defaultMessage: 'Learn more',
|
||||
})}
|
||||
url={docLinks.start}
|
||||
icon="logoEnterpriseSearch"
|
||||
name={ENTERPRISE_SEARCH_PRODUCT_NAME}
|
||||
productId={ENTERPRISE_SEARCH_CONTENT_PLUGIN.ID}
|
||||
rightPanelItems={rightPanelItems}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -21,10 +21,15 @@ import { EnterpriseSearchProductCard } from './enterprise_search_product_card';
|
|||
|
||||
import { ProductSelector } from '.';
|
||||
|
||||
const props = {
|
||||
access: { hasAppSearchAccess: true, hasWorkplaceSearchAccess: true },
|
||||
isWorkplaceSearchAdmin: true,
|
||||
};
|
||||
|
||||
describe('ProductSelector', () => {
|
||||
it('renders the overview page, product cards, & setup guide CTAs with no host set', () => {
|
||||
setMockValues({ config: { canDeployEntSearch: true, host: '' } });
|
||||
const wrapper = shallow(<ProductSelector />);
|
||||
const wrapper = shallow(<ProductSelector {...props} />);
|
||||
|
||||
expect(wrapper.find(ElasticsearchProductCard)).toHaveLength(1);
|
||||
expect(wrapper.find(EnterpriseSearchProductCard)).toHaveLength(1);
|
||||
|
@ -33,14 +38,14 @@ describe('ProductSelector', () => {
|
|||
|
||||
it('renders the trial callout', () => {
|
||||
setMockValues({ config: { canDeployEntSearch: true, host: 'localhost' } });
|
||||
const wrapper = shallow(<ProductSelector />);
|
||||
const wrapper = shallow(<ProductSelector {...props} />);
|
||||
|
||||
expect(wrapper.find(TrialCallout)).toHaveLength(1);
|
||||
});
|
||||
|
||||
it('does not render connection error callout without an error', () => {
|
||||
setMockValues({ config: { canDeployEntSearch: true, host: 'localhost' } });
|
||||
const wrapper = shallow(<ProductSelector />);
|
||||
const wrapper = shallow(<ProductSelector {...props} />);
|
||||
|
||||
expect(wrapper.find(ErrorStateCallout)).toHaveLength(0);
|
||||
});
|
||||
|
@ -50,7 +55,7 @@ describe('ProductSelector', () => {
|
|||
config: { canDeployEntSearch: true, host: 'localhost' },
|
||||
errorConnectingMessage: '502 Bad Gateway',
|
||||
});
|
||||
const wrapper = shallow(<ProductSelector />);
|
||||
const wrapper = shallow(<ProductSelector {...props} />);
|
||||
|
||||
expect(wrapper.find(ErrorStateCallout)).toHaveLength(1);
|
||||
});
|
||||
|
@ -61,11 +66,37 @@ describe('ProductSelector', () => {
|
|||
});
|
||||
|
||||
it('does not render the Setup CTA when there is a host', () => {
|
||||
const wrapper = shallow(<ProductSelector />);
|
||||
const wrapper = shallow(<ProductSelector {...props} />);
|
||||
|
||||
expect(wrapper.find(ElasticsearchProductCard)).toHaveLength(1);
|
||||
expect(wrapper.find(EnterpriseSearchProductCard)).toHaveLength(1);
|
||||
expect(wrapper.find(SetupGuideCta)).toHaveLength(0);
|
||||
});
|
||||
|
||||
it('does not render EnterpriseSearch card without access', () => {
|
||||
const wrapper = shallow(<ProductSelector access={{}} isWorkplaceSearchAdmin={false} />);
|
||||
|
||||
expect(wrapper.find(ElasticsearchProductCard)).toHaveLength(1);
|
||||
expect(wrapper.find(EnterpriseSearchProductCard)).toHaveLength(0);
|
||||
expect(wrapper.find(SetupGuideCta)).toHaveLength(0);
|
||||
});
|
||||
|
||||
it('does render EnterpriseSearch card with access to either service', () => {
|
||||
const appSearchWrapper = shallow(
|
||||
<ProductSelector
|
||||
access={{ hasAppSearchAccess: true, hasWorkplaceSearchAccess: false }}
|
||||
isWorkplaceSearchAdmin={false}
|
||||
/>
|
||||
);
|
||||
const workplaceSearchWrapper = shallow(
|
||||
<ProductSelector
|
||||
access={{ hasAppSearchAccess: false, hasWorkplaceSearchAccess: true }}
|
||||
isWorkplaceSearchAdmin={false}
|
||||
/>
|
||||
);
|
||||
|
||||
expect(appSearchWrapper.find(EnterpriseSearchProductCard)).toHaveLength(1);
|
||||
expect(workplaceSearchWrapper.find(EnterpriseSearchProductCard)).toHaveLength(1);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -40,7 +40,19 @@ import { IngestionSelector } from './ingestion_selector';
|
|||
|
||||
import './product_selector.scss';
|
||||
|
||||
export const ProductSelector: React.FC = () => {
|
||||
interface ProductSelectorProps {
|
||||
access: {
|
||||
hasAppSearchAccess?: boolean;
|
||||
hasWorkplaceSearchAccess?: boolean;
|
||||
};
|
||||
isWorkplaceSearchAdmin: boolean;
|
||||
}
|
||||
|
||||
export const ProductSelector: React.FC<ProductSelectorProps> = ({
|
||||
access,
|
||||
isWorkplaceSearchAdmin,
|
||||
}) => {
|
||||
const { hasAppSearchAccess, hasWorkplaceSearchAccess } = access;
|
||||
const { config } = useValues(KibanaLogic);
|
||||
const { errorConnectingMessage } = useValues(HttpLogic);
|
||||
const { security } = useValues(KibanaLogic);
|
||||
|
@ -138,9 +150,15 @@ export const ProductSelector: React.FC = () => {
|
|||
<EuiFlexItem>
|
||||
<ElasticsearchProductCard />
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EnterpriseSearchProductCard />
|
||||
</EuiFlexItem>
|
||||
{(hasAppSearchAccess || hasWorkplaceSearchAccess) && (
|
||||
<EuiFlexItem>
|
||||
<EnterpriseSearchProductCard
|
||||
hasAppSearchAccess={hasAppSearchAccess ?? false}
|
||||
hasWorkplaceSearchAccess={hasWorkplaceSearchAccess ?? false}
|
||||
isWorkplaceSearchAdmin={isWorkplaceSearchAdmin}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
)}
|
||||
{!config.host && config.canDeployEntSearch && (
|
||||
<EuiFlexItem>
|
||||
<SetupGuideCta />
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import { shallow } from 'enzyme';
|
||||
|
||||
import { WORKPLACE_SEARCH_PLUGIN } from '../../../../../common/constants';
|
||||
import { ProductCard } from '../product_card';
|
||||
|
||||
import { WorkplaceSearchProductCard } from './workplace_search_product_card';
|
||||
|
||||
describe('WorkplaceSearchProductCard', () => {
|
||||
it('renders with url when admin', () => {
|
||||
const wrapper = shallow(
|
||||
<WorkplaceSearchProductCard hasBorder hasShadow isWorkplaceSearchAdmin />
|
||||
);
|
||||
|
||||
expect(wrapper.find(ProductCard)).toHaveLength(1);
|
||||
expect(wrapper.find(ProductCard).prop('url')).toEqual(WORKPLACE_SEARCH_PLUGIN.URL);
|
||||
});
|
||||
it('renders with non-admin url when not admin', () => {
|
||||
const wrapper = shallow(
|
||||
<WorkplaceSearchProductCard hasBorder hasShadow isWorkplaceSearchAdmin={false} />
|
||||
);
|
||||
|
||||
expect(wrapper.find(ProductCard)).toHaveLength(1);
|
||||
expect(wrapper.find(ProductCard).prop('url')).toEqual(WORKPLACE_SEARCH_PLUGIN.NON_ADMIN_URL);
|
||||
});
|
||||
});
|
|
@ -15,11 +15,13 @@ import { ProductCard } from '../product_card';
|
|||
export interface WorkplaceSearchProductCardProps {
|
||||
hasBorder: boolean;
|
||||
hasShadow: boolean;
|
||||
isWorkplaceSearchAdmin: boolean;
|
||||
}
|
||||
|
||||
export const WorkplaceSearchProductCard: React.FC<WorkplaceSearchProductCardProps> = ({
|
||||
hasBorder = true,
|
||||
hasShadow = true,
|
||||
isWorkplaceSearchAdmin,
|
||||
}) => (
|
||||
<ProductCard
|
||||
hasBorder={hasBorder}
|
||||
|
@ -35,6 +37,8 @@ export const WorkplaceSearchProductCard: React.FC<WorkplaceSearchProductCardProp
|
|||
icon="logoWorkplaceSearch"
|
||||
name={WORKPLACE_SEARCH_PLUGIN.NAME}
|
||||
productId={WORKPLACE_SEARCH_PLUGIN.ID}
|
||||
url={WORKPLACE_SEARCH_PLUGIN.URL}
|
||||
url={
|
||||
isWorkplaceSearchAdmin ? WORKPLACE_SEARCH_PLUGIN.URL : WORKPLACE_SEARCH_PLUGIN.NON_ADMIN_URL
|
||||
}
|
||||
/>
|
||||
);
|
||||
|
|
|
@ -21,6 +21,8 @@ import { SetupGuide } from './components/setup_guide';
|
|||
import { ROOT_PATH, SETUP_GUIDE_PATH } from './routes';
|
||||
|
||||
export const EnterpriseSearchOverview: React.FC<InitialAppData> = ({
|
||||
access = {},
|
||||
workplaceSearch,
|
||||
enterpriseSearchVersion,
|
||||
kibanaVersion,
|
||||
}) => {
|
||||
|
@ -29,6 +31,8 @@ export const EnterpriseSearchOverview: React.FC<InitialAppData> = ({
|
|||
const incompatibleVersions = !!(
|
||||
config.host && isVersionMismatch(enterpriseSearchVersion, kibanaVersion)
|
||||
);
|
||||
const isWorkplaceSearchAdmin = !!workplaceSearch?.account?.isAdmin;
|
||||
|
||||
const showView = () => {
|
||||
if (incompatibleVersions) {
|
||||
return (
|
||||
|
@ -39,7 +43,7 @@ export const EnterpriseSearchOverview: React.FC<InitialAppData> = ({
|
|||
);
|
||||
}
|
||||
|
||||
return <ProductSelector />;
|
||||
return <ProductSelector isWorkplaceSearchAdmin={isWorkplaceSearchAdmin} access={access} />;
|
||||
};
|
||||
|
||||
return (
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue