[Guided onboarding] Search guide copy (#144234)

* [Guided onboarding] Update the search guide config to use the correct copy

* [Guided onboarding] Remove the docs link, not needed in 8.6

* [Guided onboarding] Delete the step id type for the removed search step

* Update src/plugins/guided_onboarding/public/constants/guides_config/search.ts

Co-authored-by: Kelly Murphy <kelly.murphy@elastic.co>

* Update src/plugins/guided_onboarding/public/constants/guides_config/search.ts

Co-authored-by: Kelly Murphy <kelly.murphy@elastic.co>

* Update src/plugins/guided_onboarding/public/constants/guides_config/search.ts

Co-authored-by: Kelly Murphy <kelly.murphy@elastic.co>

* Update src/plugins/guided_onboarding/public/constants/guides_config/search.ts

Co-authored-by: Kelly Murphy <kelly.murphy@elastic.co>

* Update src/plugins/guided_onboarding/public/constants/guides_config/search.ts

Co-authored-by: Kelly Murphy <kelly.murphy@elastic.co>

* Update src/plugins/guided_onboarding/public/constants/guides_config/search.ts

Co-authored-by: Kelly Murphy <kelly.murphy@elastic.co>

* [Guided onboarding] Update step description and description list

* Update src/plugins/guided_onboarding/public/constants/guides_config/search.ts

Co-authored-by: Casey Zumwalt <casey@zumwa.lt>

* Update src/plugins/guided_onboarding/public/constants/guides_config/search.ts

Co-authored-by: Casey Zumwalt <casey@zumwa.lt>

* Update src/plugins/guided_onboarding/public/constants/guides_config/search.ts

Co-authored-by: Casey Zumwalt <casey@zumwa.lt>

* [Guided onboarding] Update the copy

Co-authored-by: Kelly Murphy <kelly.murphy@elastic.co>
Co-authored-by: Casey Zumwalt <casey@zumwa.lt>
This commit is contained in:
Yulia Čech 2022-11-02 15:46:31 +01:00 committed by GitHub
parent 2c909c18cd
commit 92db69cce5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 113 additions and 111 deletions

View file

@ -216,7 +216,8 @@ export const Main = (props: MainProps) => {
)}
{(guideState?.isActive === true ||
guideState?.status === 'in_progress' ||
guideState?.status === 'ready_to_complete') && (
guideState?.status === 'ready_to_complete' ||
guideState?.status === 'not_started') && (
<FormattedMessage
id="guidedOnboardingExample.guidesSelection.continueButtonLabel"
defaultMessage="Continue {guideId} guide"

View file

@ -10,7 +10,7 @@ export type GuideId = 'observability' | 'security' | 'search' | 'testGuide';
type ObservabilityStepIds = 'add_data' | 'view_dashboard' | 'tour_observability';
type SecurityStepIds = 'add_data' | 'rules' | 'alertsCases';
type SearchStepIds = 'add_data' | 'browse_docs' | 'search_experience';
type SearchStepIds = 'add_data' | 'search_experience';
type TestGuideIds = 'step1' | 'step2' | 'step3';
export type GuideStepIds = ObservabilityStepIds | SecurityStepIds | SearchStepIds | TestGuideIds;

View file

@ -21,50 +21,50 @@ import { registerTestBed, TestBed } from '@kbn/test-jest-helpers';
const applicationMock = applicationServiceMock.createStartContract();
const mockActiveSearchGuideState: GuideState = {
guideId: 'search',
const mockActiveTestGuideState: GuideState = {
guideId: 'testGuide',
isActive: true,
status: 'in_progress',
steps: [
{
id: 'add_data',
id: 'step1',
status: 'active',
},
{
id: 'browse_docs',
id: 'step2',
status: 'inactive',
},
{
id: 'search_experience',
id: 'step3',
status: 'inactive',
},
],
};
const mockInProgressSearchGuideState: GuideState = {
...mockActiveSearchGuideState,
const mockInProgressTestGuideState: GuideState = {
...mockActiveTestGuideState,
steps: [
{
id: mockActiveSearchGuideState.steps[0].id,
...mockActiveTestGuideState.steps[0],
status: 'in_progress',
},
mockActiveSearchGuideState.steps[1],
mockActiveSearchGuideState.steps[2],
mockActiveTestGuideState.steps[1],
mockActiveTestGuideState.steps[2],
],
};
const mockReadyToCompleteSearchGuideState: GuideState = {
...mockActiveSearchGuideState,
const mockReadyToCompleteTestGuideState: GuideState = {
...mockActiveTestGuideState,
steps: [
{
id: mockActiveSearchGuideState.steps[0].id,
...mockActiveTestGuideState.steps[0],
status: 'complete',
},
{
id: mockActiveSearchGuideState.steps[1].id,
...mockActiveTestGuideState.steps[1],
status: 'ready_to_complete',
},
mockActiveSearchGuideState.steps[2],
mockActiveTestGuideState.steps[2],
],
};
@ -120,8 +120,8 @@ describe('Guided setup', () => {
test('should be enabled if there is an active guide', async () => {
const { exists, component, find } = testBed;
// Enable the "search" guide
await updateComponentWithState(component, mockActiveSearchGuideState, true);
// Enable the "test" guide
await updateComponentWithState(component, mockActiveTestGuideState, true);
expect(exists('disabledGuideButton')).toBe(false);
expect(exists('guideButton')).toBe(true);
@ -131,7 +131,7 @@ describe('Guided setup', () => {
test('should show the step number in the button label if a step is active', async () => {
const { component, find } = testBed;
await updateComponentWithState(component, mockInProgressSearchGuideState, true);
await updateComponentWithState(component, mockInProgressTestGuideState, true);
expect(find('guideButton').text()).toEqual('Setup guide: step 1');
});
@ -139,7 +139,7 @@ describe('Guided setup', () => {
test('shows the step number in the button label if a step is ready to complete', async () => {
const { component, find } = testBed;
await updateComponentWithState(component, mockReadyToCompleteSearchGuideState, true);
await updateComponentWithState(component, mockReadyToCompleteTestGuideState, true);
expect(find('guideButton').text()).toEqual('Setup guide: step 2');
});
@ -147,7 +147,7 @@ describe('Guided setup', () => {
test('shows the manual completion popover if a step is ready to complete', async () => {
const { component, exists } = testBed;
await updateComponentWithState(component, mockReadyToCompleteSearchGuideState, false);
await updateComponentWithState(component, mockReadyToCompleteTestGuideState, false);
expect(exists('manualCompletionPopover')).toBe(true);
});
@ -155,7 +155,7 @@ describe('Guided setup', () => {
test('shows no manual completion popover if a step is in progress', async () => {
const { component, exists } = testBed;
await updateComponentWithState(component, mockInProgressSearchGuideState, false);
await updateComponentWithState(component, mockInProgressTestGuideState, false);
expect(exists('manualCompletionPopoverPanel')).toBe(false);
});
@ -165,29 +165,29 @@ describe('Guided setup', () => {
test('should be enabled if a guide is activated', async () => {
const { exists, component, find } = testBed;
await updateComponentWithState(component, mockActiveSearchGuideState, true);
await updateComponentWithState(component, mockActiveTestGuideState, true);
expect(exists('guidePanel')).toBe(true);
expect(exists('guideProgress')).toBe(false);
expect(find('guidePanelStep').length).toEqual(guidesConfig.search.steps.length);
expect(find('guidePanelStep').length).toEqual(guidesConfig.testGuide.steps.length);
});
test('should show the progress bar if the first step has been completed', async () => {
const { component, exists } = testBed;
const mockCompleteSearchGuideState: GuideState = {
...mockActiveSearchGuideState,
const mockCompleteTestGuideState: GuideState = {
...mockActiveTestGuideState,
steps: [
{
id: mockActiveSearchGuideState.steps[0].id,
...mockActiveTestGuideState.steps[0],
status: 'complete',
},
mockActiveSearchGuideState.steps[1],
mockActiveSearchGuideState.steps[2],
mockActiveTestGuideState.steps[1],
mockActiveTestGuideState.steps[2],
],
};
await updateComponentWithState(component, mockCompleteSearchGuideState, true);
await updateComponentWithState(component, mockCompleteTestGuideState, true);
expect(exists('guidePanel')).toBe(true);
expect(exists('guideProgress')).toBe(true);
@ -197,20 +197,20 @@ describe('Guided setup', () => {
const { component, exists, find } = testBed;
const readyToCompleteGuideState: GuideState = {
guideId: 'search',
guideId: 'testGuide',
status: 'ready_to_complete',
isActive: true,
steps: [
{
id: 'add_data',
id: 'step1',
status: 'complete',
},
{
id: 'browse_docs',
id: 'step2',
status: 'complete',
},
{
id: 'search_experience',
id: 'step3',
status: 'complete',
},
],
@ -220,7 +220,7 @@ describe('Guided setup', () => {
expect(find('guideTitle').text()).toContain('Well done');
expect(find('guideDescription').text()).toContain(
`You've completed the Elastic Enterprise Search guide`
`You've completed the Elastic Testing example guide`
);
expect(exists('useElasticButton')).toBe(true);
});
@ -239,7 +239,7 @@ describe('Guided setup', () => {
test('can start a step if step has not been started', async () => {
const { component, find, exists } = testBed;
await updateComponentWithState(component, mockActiveSearchGuideState, true);
await updateComponentWithState(component, mockActiveTestGuideState, true);
expect(find('activeStepButton').text()).toEqual('Start');
@ -251,7 +251,7 @@ describe('Guided setup', () => {
test('can continue a step if step is in progress', async () => {
const { component, find, exists } = testBed;
await updateComponentWithState(component, mockInProgressSearchGuideState, true);
await updateComponentWithState(component, mockInProgressTestGuideState, true);
expect(find('activeStepButton').text()).toEqual('Continue');
@ -263,7 +263,7 @@ describe('Guided setup', () => {
test('can mark a step "done" if step is ready to complete', async () => {
const { component, find, exists } = testBed;
await updateComponentWithState(component, mockReadyToCompleteSearchGuideState, true);
await updateComponentWithState(component, mockReadyToCompleteTestGuideState, true);
expect(find('activeStepButton').text()).toEqual('Mark done');
@ -279,20 +279,20 @@ describe('Guided setup', () => {
const { component, find } = testBed;
const mockSingleSentenceStepDescriptionGuideState: GuideState = {
guideId: 'observability',
guideId: 'testGuide',
isActive: true,
status: 'in_progress',
steps: [
{
id: 'add_data',
id: 'step1',
status: 'complete',
},
{
id: 'view_dashboard',
id: 'step2',
status: 'complete',
},
{
id: 'tour_observability',
id: 'step3',
status: 'in_progress',
},
],
@ -307,23 +307,21 @@ describe('Guided setup', () => {
expect(
find('guidePanelStepDescription')
.last()
.containsMatchingElement(
<p>{guidesConfig.observability.steps[2].descriptionList[0]}</p>
)
.containsMatchingElement(<p>{guidesConfig.testGuide.steps[2].description}</p>)
).toBe(true);
});
test('should render the step description as an unordered list if it is more than one sentence', async () => {
const { component, find } = testBed;
await updateComponentWithState(component, mockActiveSearchGuideState, true);
await updateComponentWithState(component, mockActiveTestGuideState, true);
expect(
find('guidePanelStepDescription')
.first()
.containsMatchingElement(
<ul>
{guidesConfig.search.steps[0].descriptionList.map((description, i) => (
{guidesConfig.testGuide.steps[0].descriptionList?.map((description, i) => (
<li key={i}>{description}</li>
))}
</ul>
@ -337,8 +335,8 @@ describe('Guided setup', () => {
const { component, find, exists } = testBed;
await act(async () => {
// Enable the "search" guide
await apiService.updateGuideState(mockActiveSearchGuideState, true);
// Enable the "test" guide
await apiService.updateGuideState(mockActiveTestGuideState, true);
});
component.update();

View file

@ -29,10 +29,13 @@ export const getGuidePanelStepStyles = (euiTheme: EuiThemeComputed, stepStatus:
color: ${euiTheme.colors.title};
}
`,
stepDescription: css`
margin-left: 32px;
`,
stepListItems: css`
padding-left: 28px;
description: css`
p {
margin-left: 32px;
margin-block-end: 0;
}
ul {
padding-left: 28px;
}
`,
});

View file

@ -93,11 +93,10 @@ export const GuideStep = ({
>
<>
<EuiSpacer size="s" />
<EuiText size="s" data-test-subj="guidePanelStepDescription">
{stepConfig.descriptionList.length === 1 ? (
<p css={styles.stepDescription}>{stepConfig.descriptionList[0]}</p> // If there is only one description, render it as a paragraph
) : (
<ul css={styles.stepListItems}>
<EuiText size="s" data-test-subj="guidePanelStepDescription" css={styles.description}>
{stepConfig.description && <p>{stepConfig.description}</p>}
{stepConfig.descriptionList && (
<ul>
{stepConfig.descriptionList.map((description, index) => {
return <li key={`description-${index}`}>{description}</li>;
})}

View file

@ -31,11 +31,9 @@ export const observabilityConfig: GuideConfig = {
defaultMessage: 'Add and verify your data',
}),
integration: 'kubernetes',
descriptionList: [
i18n.translate('guidedOnboarding.observabilityGuide.addDataStep.description', {
defaultMessage: 'Start by adding your data by setting up the Kubernetes integration.',
}),
],
description: i18n.translate('guidedOnboarding.observabilityGuide.addDataStep.description', {
defaultMessage: 'Start by adding your data by setting up the Kubernetes integration.',
}),
location: {
appID: 'integrations',
path: '/detail/kubernetes/overview',
@ -46,11 +44,12 @@ export const observabilityConfig: GuideConfig = {
title: i18n.translate('guidedOnboarding.observabilityGuide.viewDashboardStep.title', {
defaultMessage: 'Explore Kubernetes metrics',
}),
descriptionList: [
i18n.translate('guidedOnboarding.observabilityGuide.viewDashboardStep.description', {
description: i18n.translate(
'guidedOnboarding.observabilityGuide.viewDashboardStep.description',
{
defaultMessage: 'Stream, visualize, and analyze your Kubernetes infrastructure metrics.',
}),
],
}
),
location: {
appID: 'dashboards',
path: '#/view/kubernetes-e0195ce0-bcaf-11ec-b64f-7dd6e8e82013',
@ -76,12 +75,13 @@ export const observabilityConfig: GuideConfig = {
title: i18n.translate('guidedOnboarding.observabilityGuide.tourObservabilityStep.title', {
defaultMessage: 'Tour Elastic Observability',
}),
descriptionList: [
i18n.translate('guidedOnboarding.observabilityGuide.tourObservabilityStep.description', {
description: i18n.translate(
'guidedOnboarding.observabilityGuide.tourObservabilityStep.description',
{
defaultMessage:
'Get familiar with the rest of Elastic Observability and explore even more integrations.',
}),
],
}
),
location: {
appID: 'observability',
path: '/overview',

View file

@ -6,60 +6,59 @@
* Side Public License, v 1.
*/
import { i18n } from '@kbn/i18n';
import type { GuideConfig } from '../../types';
export const searchConfig: GuideConfig = {
title: 'Search my data',
description: `We'll help you build world-class search experiences with your data, using Elastic's out-of-the-box web crawler, connectors, and our robust APIs. Gain deep insights from the built-in search analytics and use that data to inform changes to relevance.`,
title: i18n.translate('guidedOnboarding.searchGuide.title', {
defaultMessage: 'Search my data',
}),
description: i18n.translate('guidedOnboarding.searchGuide.description', {
defaultMessage: `Build custom search experiences with your data using Elastics 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',
docs: {
text: 'Enterprise Search 101 Documentation',
url: 'example.com',
},
steps: [
{
id: 'add_data',
title: 'Add data',
title: i18n.translate('guidedOnboarding.searchGuide.addDataStep.title', {
defaultMessage: 'Add data',
}),
descriptionList: [
'Lorem ipsum dolor sit amet, consectetur adipiscing elit.',
'Nullam ligula enim, malesuada a finibus vel, cursus sed risus.',
'Vivamus pretium, elit dictum lacinia aliquet, libero nibh dictum enim, a rhoncus leo magna in sapien.',
i18n.translate('guidedOnboarding.searchGuide.addDataStep.description1', {
defaultMessage: 'Select an ingestion method.',
}),
i18n.translate('guidedOnboarding.searchGuide.addDataStep.description2', {
defaultMessage: 'Create a new Elasticsearch index.',
}),
i18n.translate('guidedOnboarding.searchGuide.addDataStep.description3', {
defaultMessage: 'Configure your ingestion settings.',
}),
],
location: {
appID: 'enterpriseSearch',
path: '',
},
},
{
id: 'browse_docs',
title: 'Browse your documents',
descriptionList: [
'Lorem ipsum dolor sit amet, consectetur adipiscing elit.',
'Nullam ligula enim, malesuada a finibus vel, cursus sed risus.',
'Vivamus pretium, elit dictum lacinia aliquet, libero nibh dictum enim, a rhoncus leo magna in sapien.',
],
location: {
appID: 'guidedOnboardingExample',
path: 'stepTwo',
},
manualCompletion: {
title: 'Manual completion step title',
description:
'Mark the step complete by opening the panel and clicking the button "Mark done"',
readyToCompleteOnNavigation: true,
},
},
{
id: 'search_experience',
title: 'Build a search experience',
title: i18n.translate('guidedOnboarding.searchGuide.searchExperienceStep.title', {
defaultMessage: 'Build a search experience',
}),
descriptionList: [
'Lorem ipsum dolor sit amet, consectetur adipiscing elit.',
'Nullam ligula enim, malesuada a finibus vel, cursus sed risus.',
'Vivamus pretium, elit dictum lacinia aliquet, libero nibh dictum enim, a rhoncus leo magna in sapien.',
i18n.translate('guidedOnboarding.searchGuide.searchExperienceStep.descriptionList.item1', {
defaultMessage: 'Learn more about Elastics Search UI framework.',
}),
i18n.translate('guidedOnboarding.searchGuide.searchExperienceStep.descriptionList.item2', {
defaultMessage: 'Try the Search UI tutorial for Elasticsearch.',
}),
i18n.translate('guidedOnboarding.searchGuide.searchExperienceStep.descriptionList.item3', {
defaultMessage:
'Build a world-class search experience for your customers, employees, or users.',
}),
],
location: {
appID: 'guidedOnboardingExample',
path: 'stepThree',
appID: 'enterpriseSearch',
path: '/search_experiences',
},
},
],

View file

@ -51,9 +51,8 @@ export const testGuideConfig: GuideConfig = {
{
id: 'step3',
title: 'Step 3 (manual completion after click)',
descriptionList: [
description:
'This step is completed by clicking a button on the page and then clicking the popover on the guide button in the header and marking the step done',
],
manualCompletion: {
title: 'Manual completion step title',
description:

View file

@ -54,7 +54,10 @@ export interface GuidedOnboardingApi {
export interface StepConfig {
id: GuideStepIds;
title: string;
descriptionList: string[];
// description is displayed as a single paragraph, can be combined with description list
description?: string;
// description list is displayed as an unordered list, can be combined with description
descriptionList?: string[];
location?: {
appID: string;
path: string;