mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
[Guided onboarding] Registers 3 separate guide IDs for search (#149968)
## Summary Fixes https://github.com/elastic/kibana/issues/149691 Follow up to https://github.com/elastic/kibana/pull/149528 This PR adds 3 separate guide ID values `appSearch`, `websiteSearch` and `databaseSearch` instead of previously used `search`. With that change, each card for Search on the landing page has its own independent guide that can be completed. Example plugin for guided onboarding is also updated so that all 3 search guides can be managed there. Otherwise there should not be any UI/UX changes. Currently, all 3 ids are registered with the same config and that can be easily updated by the team in the future. #### Screenshot <img width="485" alt="Screenshot 2023-01-31 at 18 24 12" src="https://user-images.githubusercontent.com/6585477/215840343-f9a65be3-0568-40ca-b458-5de92bfe8aaf.png"> ### Checklist - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
af3ae7b555
commit
8705a6a77b
11 changed files with 76 additions and 26 deletions
|
@ -25,6 +25,7 @@ import {
|
|||
EuiText,
|
||||
EuiTitle,
|
||||
EuiSelectOption,
|
||||
EuiFlexGrid,
|
||||
} from '@elastic/eui';
|
||||
import type { GuideState, GuideStepIds, GuideId, GuideStep } from '@kbn/guided-onboarding';
|
||||
import type { GuidedOnboardingPluginStart } from '@kbn/guided-onboarding-plugin/public';
|
||||
|
@ -34,7 +35,14 @@ interface MainProps {
|
|||
notifications: CoreStart['notifications'];
|
||||
}
|
||||
|
||||
const exampleGuideIds: GuideId[] = ['search', 'siem', 'kubernetes', 'testGuide'];
|
||||
const exampleGuideIds: GuideId[] = [
|
||||
'appSearch',
|
||||
'websiteSearch',
|
||||
'databaseSearch',
|
||||
'siem',
|
||||
'kubernetes',
|
||||
'testGuide',
|
||||
];
|
||||
const selectOptions: EuiSelectOption[] = exampleGuideIds.map((guideId) => ({
|
||||
value: guideId,
|
||||
text: guideId,
|
||||
|
@ -211,7 +219,7 @@ export const Main = (props: MainProps) => {
|
|||
</h3>
|
||||
</EuiText>
|
||||
<EuiSpacer />
|
||||
<EuiFlexGroup>
|
||||
<EuiFlexGrid columns={3}>
|
||||
{exampleGuideIds.map((guideId) => {
|
||||
const guideState = guidesState?.find((guide) => guide.guideId === guideId);
|
||||
return (
|
||||
|
@ -255,7 +263,7 @@ export const Main = (props: MainProps) => {
|
|||
</EuiFlexItem>
|
||||
);
|
||||
})}
|
||||
</EuiFlexGroup>
|
||||
</EuiFlexGrid>
|
||||
<EuiSpacer />
|
||||
<EuiHorizontalRule />
|
||||
<EuiText>
|
||||
|
|
|
@ -15,7 +15,7 @@ exports[`guide cards snapshots should render all cards 1`] = `
|
|||
activeFilter="all"
|
||||
card={
|
||||
Object {
|
||||
"guideId": "search",
|
||||
"guideId": "appSearch",
|
||||
"order": 1,
|
||||
"solution": "search",
|
||||
"telemetryId": "onboarding--search--application",
|
||||
|
@ -87,7 +87,7 @@ exports[`guide cards snapshots should render all cards 1`] = `
|
|||
activeFilter="all"
|
||||
card={
|
||||
Object {
|
||||
"guideId": "search",
|
||||
"guideId": "websiteSearch",
|
||||
"order": 4,
|
||||
"solution": "search",
|
||||
"telemetryId": "onboarding--search--website",
|
||||
|
@ -162,7 +162,7 @@ exports[`guide cards snapshots should render all cards 1`] = `
|
|||
activeFilter="all"
|
||||
card={
|
||||
Object {
|
||||
"guideId": "search",
|
||||
"guideId": "databaseSearch",
|
||||
"order": 7,
|
||||
"solution": "search",
|
||||
"telemetryId": "onboarding--search--database",
|
||||
|
|
|
@ -33,7 +33,7 @@ export const guideCards: GuideCardConstants[] = [
|
|||
title: i18n.translate('guidedOnboardingPackage.gettingStarted.cards.appSearch.title', {
|
||||
defaultMessage: 'Build an application on top of Elasticsearch',
|
||||
}),
|
||||
guideId: 'search',
|
||||
guideId: 'appSearch',
|
||||
telemetryId: 'onboarding--search--application',
|
||||
order: 1,
|
||||
},
|
||||
|
@ -42,7 +42,7 @@ export const guideCards: GuideCardConstants[] = [
|
|||
title: i18n.translate('guidedOnboardingPackage.gettingStarted.cards.websiteSearch.title', {
|
||||
defaultMessage: 'Add search to my website',
|
||||
}),
|
||||
guideId: 'search',
|
||||
guideId: 'websiteSearch',
|
||||
telemetryId: 'onboarding--search--website',
|
||||
order: 4,
|
||||
},
|
||||
|
@ -51,7 +51,7 @@ export const guideCards: GuideCardConstants[] = [
|
|||
title: i18n.translate('guidedOnboardingPackage.gettingStarted.cards.databaseSearch.title', {
|
||||
defaultMessage: 'Search across databases and business systems',
|
||||
}),
|
||||
guideId: 'search',
|
||||
guideId: 'databaseSearch',
|
||||
telemetryId: 'onboarding--search--database',
|
||||
order: 7,
|
||||
},
|
||||
|
|
|
@ -6,7 +6,13 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
export type GuideId = 'kubernetes' | 'siem' | 'search' | 'testGuide';
|
||||
export type GuideId =
|
||||
| 'kubernetes'
|
||||
| 'siem'
|
||||
| 'appSearch'
|
||||
| 'websiteSearch'
|
||||
| 'databaseSearch'
|
||||
| 'testGuide';
|
||||
|
||||
type KubernetesStepIds = 'add_data' | 'view_dashboard' | 'tour_observability';
|
||||
type SiemStepIds = 'add_data' | 'rules' | 'alertsCases';
|
||||
|
|
|
@ -15,7 +15,7 @@ export default function testGetGuideConfig({ getService }: FtrProviderContext) {
|
|||
|
||||
describe('GET /api/guided_onboarding/configs', () => {
|
||||
// check that production guides are present
|
||||
['siem', 'search', 'kubernetes'].map((guideId) => {
|
||||
['siem', 'appSearch', 'websiteSearch', 'databaseSearch', 'kubernetes'].map((guideId) => {
|
||||
it(`returns config for ${guideId}`, async () => {
|
||||
const response = await supertest.get(`${getConfigsPath}/${guideId}`).expect(200);
|
||||
expect(response.body).not.to.be.empty();
|
||||
|
|
|
@ -12,6 +12,7 @@ import {
|
|||
guideStateSavedObjectsType,
|
||||
pluginStateSavedObjectsType,
|
||||
} from '@kbn/guided-onboarding-plugin/server/saved_objects/guided_setup';
|
||||
import { appSearchGuideId } from '@kbn/enterprise-search-plugin/common/guided_onboarding/search_guide_config';
|
||||
import type { FtrProviderContext } from '../../ftr_provider_context';
|
||||
import { createGuides } from './helpers';
|
||||
|
||||
|
@ -37,13 +38,13 @@ export default function testGetGuidesState({ getService }: FtrProviderContext) {
|
|||
it('returns all created guides (active and inactive)', async () => {
|
||||
await createGuides(kibanaServer, [
|
||||
testGuideStep1ActiveState,
|
||||
{ ...testGuideStep1ActiveState, guideId: 'search' },
|
||||
{ ...testGuideStep1ActiveState, guideId: appSearchGuideId },
|
||||
]);
|
||||
const response = await supertest.get(getGuidesPath).expect(200);
|
||||
expect(response.body).not.to.be.empty();
|
||||
expect(response.body.state).to.eql([
|
||||
testGuideStep1ActiveState,
|
||||
{ ...testGuideStep1ActiveState, guideId: 'search' },
|
||||
{ ...testGuideStep1ActiveState, guideId: appSearchGuideId },
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -17,6 +17,7 @@ import {
|
|||
guideStateSavedObjectsType,
|
||||
} from '@kbn/guided-onboarding-plugin/server/saved_objects/guided_setup';
|
||||
import { testGuideId } from '@kbn/guided-onboarding';
|
||||
import { appSearchGuideId } from '@kbn/enterprise-search-plugin/common/guided_onboarding/search_guide_config';
|
||||
import type { FtrProviderContext } from '../../ftr_provider_context';
|
||||
import { createGuides, createPluginState } from './helpers';
|
||||
|
||||
|
@ -126,7 +127,7 @@ export default function testPutState({ getService }: FtrProviderContext) {
|
|||
// create an active guide and an inactive guide
|
||||
await createGuides(kibanaServer, [
|
||||
testGuideStep1ActiveState,
|
||||
{ ...testGuideNotActiveState, guideId: 'search' },
|
||||
{ ...testGuideNotActiveState, guideId: appSearchGuideId },
|
||||
]);
|
||||
|
||||
// Create a new guide with isActive: true
|
||||
|
@ -150,7 +151,7 @@ export default function testPutState({ getService }: FtrProviderContext) {
|
|||
|
||||
const searchGuideSO = await kibanaServer.savedObjects.get({
|
||||
type: guideStateSavedObjectsType,
|
||||
id: 'search',
|
||||
id: appSearchGuideId,
|
||||
});
|
||||
expect(searchGuideSO.attributes.isActive).to.eql(false);
|
||||
|
||||
|
|
|
@ -67,5 +67,6 @@
|
|||
"@kbn/safer-lodash-set",
|
||||
"@kbn/utility-types",
|
||||
"@kbn/dev-proc-runner",
|
||||
"@kbn/enterprise-search-plugin",
|
||||
]
|
||||
}
|
||||
|
|
|
@ -8,8 +8,10 @@
|
|||
import type { GuideConfig } from '@kbn/guided-onboarding';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
|
||||
export const searchGuideId = 'search';
|
||||
export const searchGuideConfig: GuideConfig = {
|
||||
export const appSearchGuideId = 'appSearch';
|
||||
export const websiteSearchGuideId = 'websiteSearch';
|
||||
export const databaseSearchGuideId = 'databaseSearch';
|
||||
const guideConfig: Omit<GuideConfig, 'telemetryId'> = {
|
||||
title: i18n.translate('xpack.enterpriseSearch.guideConfig.title', {
|
||||
defaultMessage: 'Search my data',
|
||||
}),
|
||||
|
@ -18,7 +20,6 @@ export const searchGuideConfig: GuideConfig = {
|
|||
'Build custom search experiences with your data using Elastic’s out-of-the-box web crawler, connectors, and robust APIs. Gain deep insights from the built-in search analytics to curate results and optimize relevance.',
|
||||
}),
|
||||
guideName: 'Enterprise Search',
|
||||
telemetryId: 'search',
|
||||
steps: [
|
||||
{
|
||||
id: 'add_data',
|
||||
|
@ -90,3 +91,15 @@ export const searchGuideConfig: GuideConfig = {
|
|||
},
|
||||
],
|
||||
};
|
||||
export const appSearchGuideConfig: GuideConfig = {
|
||||
...guideConfig,
|
||||
telemetryId: 'appSearch',
|
||||
};
|
||||
export const websiteSearchGuideConfig: GuideConfig = {
|
||||
...guideConfig,
|
||||
telemetryId: 'websiteSearch',
|
||||
};
|
||||
export const databaseSearchGuideConfig: GuideConfig = {
|
||||
...guideConfig,
|
||||
telemetryId: 'databaseSearch',
|
||||
};
|
||||
|
|
|
@ -68,18 +68,29 @@ export const SearchIndex: React.FC = () => {
|
|||
const { indexName } = useValues(IndexNameLogic);
|
||||
|
||||
/**
|
||||
* Guided Onboarding needs us to mark the add data step as complete as soon as the user has data in an index
|
||||
* Guided Onboarding needs us to mark the add data step as complete as soon as the user has data in an index.
|
||||
* This needs to be checked for any of the 3 registered search guideIds
|
||||
* Putting it here guarantees that if a user is viewing an index with data, it'll be marked as complete
|
||||
*/
|
||||
const { guidedOnboarding } = useValues(KibanaLogic);
|
||||
const isDataStepActive = useObservable(
|
||||
guidedOnboarding.guidedOnboardingApi!.isGuideStepActive$('search', 'add_data')
|
||||
const isAppGuideActive = useObservable(
|
||||
guidedOnboarding.guidedOnboardingApi!.isGuideStepActive$('appSearch', 'add_data')
|
||||
);
|
||||
const isWebsiteGuideActive = useObservable(
|
||||
guidedOnboarding.guidedOnboardingApi!.isGuideStepActive$('websiteSearch', 'add_data')
|
||||
);
|
||||
const isDatabaseGuideActive = useObservable(
|
||||
guidedOnboarding.guidedOnboardingApi!.isGuideStepActive$('databaseSearch', 'add_data')
|
||||
);
|
||||
useEffect(() => {
|
||||
if (isDataStepActive && index?.count) {
|
||||
guidedOnboarding.guidedOnboardingApi?.completeGuideStep('search', 'add_data');
|
||||
if (isAppGuideActive && index?.count) {
|
||||
guidedOnboarding.guidedOnboardingApi?.completeGuideStep('appSearch', 'add_data');
|
||||
} else if (isWebsiteGuideActive && index?.count) {
|
||||
guidedOnboarding.guidedOnboardingApi?.completeGuideStep('websiteSearch', 'add_data');
|
||||
} else if (isDatabaseGuideActive && index?.count) {
|
||||
guidedOnboarding.guidedOnboardingApi?.completeGuideStep('databaseSearch', 'add_data');
|
||||
}
|
||||
}, [isDataStepActive, index?.count]);
|
||||
}, [isAppGuideActive, isWebsiteGuideActive, isDatabaseGuideActive, index?.count]);
|
||||
|
||||
useEffect(() => {
|
||||
if (
|
||||
|
|
|
@ -38,7 +38,14 @@ import {
|
|||
ENTERPRISE_SEARCH_ANALYTICS_LOGS_SOURCE_ID,
|
||||
} from '../common/constants';
|
||||
|
||||
import { searchGuideId, searchGuideConfig } from '../common/guided_onboarding/search_guide_config';
|
||||
import {
|
||||
appSearchGuideId,
|
||||
websiteSearchGuideId,
|
||||
databaseSearchGuideId,
|
||||
appSearchGuideConfig,
|
||||
websiteSearchGuideConfig,
|
||||
databaseSearchGuideConfig,
|
||||
} from '../common/guided_onboarding/search_guide_config';
|
||||
|
||||
import { registerTelemetryUsageCollector as registerASTelemetryUsageCollector } from './collectors/app_search/telemetry';
|
||||
import { registerTelemetryUsageCollector as registerESTelemetryUsageCollector } from './collectors/enterprise_search/telemetry';
|
||||
|
@ -264,7 +271,9 @@ export class EnterpriseSearchPlugin implements Plugin {
|
|||
/**
|
||||
* Register a config for the search guide
|
||||
*/
|
||||
guidedOnboarding.registerGuideConfig(searchGuideId, searchGuideConfig);
|
||||
guidedOnboarding.registerGuideConfig(appSearchGuideId, appSearchGuideConfig);
|
||||
guidedOnboarding.registerGuideConfig(websiteSearchGuideId, websiteSearchGuideConfig);
|
||||
guidedOnboarding.registerGuideConfig(databaseSearchGuideId, databaseSearchGuideConfig);
|
||||
}
|
||||
|
||||
public start() {}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue