Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ export const GuidedOnboardingExampleApp = (props: GuidedOnboardingExampleAppDeps
<StepOne guidedOnboarding={guidedOnboarding} />
</Route>
<Route exact path="/stepTwo">
<StepTwo guidedOnboarding={guidedOnboarding} />
<StepTwo />
</Route>
<Route exact path="/stepThree">
<StepThree guidedOnboarding={guidedOnboarding} />
Expand Down
11 changes: 10 additions & 1 deletion examples/guided_onboarding_example/public/components/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,7 @@ export const Main = (props: MainProps) => {
{ value: 'observability', text: 'observability' },
{ value: 'security', text: 'security' },
{ value: 'search', text: 'search' },
{ value: 'testGuide', text: 'test guide' },
]}
value={selectedGuide}
onChange={(e) => {
Expand Down Expand Up @@ -294,7 +295,7 @@ export const Main = (props: MainProps) => {
<h3>
<FormattedMessage
id="guidedOnboardingExample.main.examplePages.title"
defaultMessage="Example pages"
defaultMessage="Example pages for test guide"
/>
</h3>
</EuiText>
Expand All @@ -316,6 +317,14 @@ export const Main = (props: MainProps) => {
/>
</EuiButton>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiButton onClick={() => history.push('stepThree')}>
<FormattedMessage
id="guidedOnboardingExample.main.examplePages.stepThree.link"
defaultMessage="Step 3"
/>
</EuiButton>
</EuiFlexItem>
</EuiFlexGroup>
</EuiPageContentBody>
</>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export const StepOne = ({ guidedOnboarding }: GuidedOnboardingExampleAppDeps) =>
const [isTourStepOpen, setIsTourStepOpen] = useState<boolean>(false);

const isTourActive = useObservable(
guidedOnboardingApi!.isGuideStepActive$('search', 'add_data'),
guidedOnboardingApi!.isGuideStepActive$('testGuide', 'step1'),
false
);
useEffect(() => {
Expand All @@ -45,7 +45,7 @@ export const StepOne = ({ guidedOnboarding }: GuidedOnboardingExampleAppDeps) =>
<h2>
<FormattedMessage
id="guidedOnboardingExample.stepOne.title"
defaultMessage="Example step Add data"
defaultMessage="Example step 1"
/>
</h2>
</EuiTitle>
Expand All @@ -56,7 +56,7 @@ export const StepOne = ({ guidedOnboarding }: GuidedOnboardingExampleAppDeps) =>
<FormattedMessage
id="guidedOnboardingExample.guidesSelection.stepOne.explanation"
defaultMessage="The code on this page is listening to the guided setup state with a useObservable hook. If the state is set to
Search guide, step Add data, a EUI tour will be displayed, pointing to the button below."
Test guide, step 1, a EUI tour will be displayed, pointing to the button below."
/>
</p>
</EuiText>
Expand All @@ -72,12 +72,12 @@ export const StepOne = ({ guidedOnboarding }: GuidedOnboardingExampleAppDeps) =>
onFinish={() => setIsTourStepOpen(false)}
step={1}
stepsTotal={1}
title="Step Add data"
title="Step 1"
anchorPosition="rightUp"
>
<EuiButton
onClick={async () => {
await guidedOnboardingApi?.completeGuideStep('search', 'add_data');
await guidedOnboardingApi?.completeGuideStep('testGuide', 'step1');
}}
>
Complete step 1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export const StepThree = (props: StepThreeProps) => {

useEffect(() => {
const subscription = guidedOnboardingApi
?.isGuideStepActive$('search', 'search_experience')
?.isGuideStepActive$('testGuide', 'step3')
.subscribe((isStepActive) => {
setIsTourStepOpen(isStepActive);
});
Expand All @@ -53,9 +53,17 @@ export const StepThree = (props: StepThreeProps) => {
<EuiText>
<p>
<FormattedMessage
id="guidedOnboardingExample.guidesSelection.stepThree.explanation"
defaultMessage="The code on this page is listening to the guided setup state using an Observable subscription. If the state is set to
Search guide, step Search experience, a EUI tour will be displayed, pointing to the button below."
id="guidedOnboardingExample.guidesSelection.stepThree.explanation1"
defaultMessage="The code on this page is listening to the guided setup state using an Observable subscription.
If the state is set to Test, step 3, a EUI tour will be displayed, pointing to the button below."
/>
</p>
<p>
<FormattedMessage
id="guidedOnboardingExample.guidesSelection.stepTwo.explanation2"
defaultMessage="This page is used for the manual completion of Test guide, step 3. After clicking the page,
the manual completion popover
should appear on the header button 'Setup guide' to open the panel and mark the step done."
/>
</p>
</EuiText>
Expand All @@ -73,12 +81,12 @@ export const StepThree = (props: StepThreeProps) => {
}}
step={1}
stepsTotal={1}
title="Step Build search experience"
title="Step 3"
anchorPosition="rightUp"
>
<EuiButton
onClick={async () => {
await guidedOnboardingApi?.completeGuideStep('search', 'search_experience');
await guidedOnboardingApi?.completeGuideStep('testGuide', 'step3');
}}
>
Complete step 3
Expand Down
55 changes: 5 additions & 50 deletions examples/guided_onboarding_example/public/components/step_two.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,37 +6,17 @@
* Side Public License, v 1.
*/

import React, { useEffect, useState } from 'react';
import React from 'react';

import { EuiButton, EuiSpacer, EuiText, EuiTitle, EuiTourStep } from '@elastic/eui';
import { EuiText, EuiTitle } from '@elastic/eui';

import { GuidedOnboardingPluginStart } from '@kbn/guided-onboarding-plugin/public/types';
import { FormattedMessage } from '@kbn/i18n-react';
import {
EuiPageContentHeader_Deprecated as EuiPageContentHeader,
EuiPageContentBody_Deprecated as EuiPageContentBody,
} from '@elastic/eui';

interface StepTwoProps {
guidedOnboarding: GuidedOnboardingPluginStart;
}

export const StepTwo = (props: StepTwoProps) => {
const {
guidedOnboarding: { guidedOnboardingApi },
} = props;

const [isTourStepOpen, setIsTourStepOpen] = useState<boolean>(false);

useEffect(() => {
const subscription = guidedOnboardingApi
?.isGuideStepActive$('search', 'browse_docs')
.subscribe((isStepActive) => {
setIsTourStepOpen(isStepActive);
});
return () => subscription?.unsubscribe();
}, [guidedOnboardingApi]);

export const StepTwo = () => {
return (
<>
<EuiPageContentHeader>
Expand All @@ -54,36 +34,11 @@ export const StepTwo = (props: StepTwoProps) => {
<p>
<FormattedMessage
id="guidedOnboardingExample.guidesSelection.stepTwo.explanation"
defaultMessage="The code on this page is listening to the guided setup state using an Observable subscription. If the state is set to
Search guide, step Browse documents, a EUI tour will be displayed, pointing to the button below."
defaultMessage="This page is used for the manual completion of Test guide, step 2. The manual completion popover
should appear on the header button 'Setup guide' to open the panel and mark the step done."
/>
</p>
</EuiText>
<EuiSpacer />
<EuiTourStep
content={
<EuiText>
<p>Click this button to complete step 2.</p>
</EuiText>
}
isStepOpen={isTourStepOpen}
minWidth={300}
onFinish={() => {
setIsTourStepOpen(false);
}}
step={1}
stepsTotal={1}
title="Step Browse documents"
anchorPosition="rightUp"
>
<EuiButton
onClick={async () => {
await guidedOnboardingApi?.completeGuideStep('search', 'browse_docs');
}}
>
Complete step 2
</EuiButton>
</EuiTourStep>
</EuiPageContentBody>
</>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
import React, { ReactNode } from 'react';
import { EuiCard, EuiText, EuiImage } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { GuideId } from '../../types';

type UseCaseConstants = {
[key in UseCase]: {
Expand Down Expand Up @@ -53,7 +52,7 @@ const constants: UseCaseConstants = {
export type UseCase = 'search' | 'observability' | 'security';

export interface UseCaseCardProps {
useCase: GuideId;
useCase: UseCase;
title: string;
description: string;
footer: ReactNode;
Expand Down
11 changes: 6 additions & 5 deletions packages/kbn-guided-onboarding/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,14 @@
* Side Public License, v 1.
*/

export type GuideId = 'observability' | 'security' | 'search';
export type GuideId = 'observability' | 'security' | 'search' | 'testGuide';

export type ObservabilityStepIds = 'add_data' | 'view_dashboard' | 'tour_observability';
export type SecurityStepIds = 'add_data' | 'rules' | 'alertsCases';
export type SearchStepIds = 'add_data' | 'browse_docs' | 'search_experience';
type ObservabilityStepIds = 'add_data' | 'view_dashboard' | 'tour_observability';
type SecurityStepIds = 'add_data' | 'rules' | 'alertsCases';
type SearchStepIds = 'add_data' | 'browse_docs' | 'search_experience';
type TestGuideIds = 'step1' | 'step2' | 'step3';

export type GuideStepIds = ObservabilityStepIds | SecurityStepIds | SearchStepIds;
export type GuideStepIds = ObservabilityStepIds | SecurityStepIds | SearchStepIds | TestGuideIds;

export interface GuideState {
guideId: GuideId;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@ import type { GuidesConfig } from '../../types';
import { securityConfig } from './security';
import { observabilityConfig } from './observability';
import { searchConfig } from './search';
import { testGuideConfig } from './test_guide';

export const guidesConfig: GuidesConfig = {
security: securityConfig,
observability: observabilityConfig,
search: searchConfig,
testGuide: testGuideConfig,
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/*
* 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 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/

import type { GuideConfig } from '../../types';

export const testGuideConfig: GuideConfig = {
title: 'Test guide for development',
description: `This guide is used to test the guided onboarding UI while in development and to run automated tests for the API and UI components.`,
guideName: 'Testing example',
docs: {
text: 'Testing example docs',
url: 'example.com',
},
steps: [
{
id: 'step1',
title: 'Step 1 (completed via an API request)',
descriptionList: [
`This step is directly completed by clicking the button that uses the API function 'completeGuideStep`,
'Navigate to /guidedOnboardingExample/stepOne to complete the step.',
],
location: {
appID: 'guidedOnboardingExample',
path: 'stepOne',
},
integration: 'testIntegration',
},
{
id: 'step2',
title: 'Step 2 (manual completion after navigation)',
descriptionList: [
'This step is set to ready_to_complete on page navigation.',
'After that click the popover on the guide button in the header and mark the step done',
],
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: 'step3',
title: 'Step 3 (manual completion after click)',
descriptionList: [
'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:
'Mark the step complete by opening the panel and clicking the button "Mark done"',
},
location: {
appID: 'guidedOnboardingExample',
path: 'stepThree',
},
},
],
};
Loading