kibana/examples/guided_onboarding_example/public/components/main.tsx
Sander Philipse 2ba56a55a4
[9.0] [Search] Remove website search guided onboarding (#224538) (#224665)
# Backport

This will backport the following commits from `main` to `9.0`:
- [[Search] Remove website search guided onboarding
(#224538)](https://github.com/elastic/kibana/pull/224538)

<!--- Backport version: 10.0.1 -->

### Questions ?
Please refer to the [Backport tool
documentation](https://github.com/sorenlouv/backport)

<!--BACKPORT [{"author":{"name":"Sander
Philipse","email":"94373878+sphilipse@users.noreply.github.com"},"sourceCommit":{"committedDate":"2025-06-19T17:34:32Z","message":"[Search]
Remove website search guided onboarding (#224538)\n\n## Summary\n\nThis
removes the deprecated website search guided onboarding from\nKibana.
Deprecated because we no longer offer a managed web
crawler.\n\n---------\n\nCo-authored-by: kibanamachine
<42973632+kibanamachine@users.noreply.github.com>","sha":"9171743e8368a47503cf5892a8b7e47d35b42319","branchLabelMapping":{"^v9.1.0$":"main","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["release_note:skip","Team:Search","backport:prev-minor","v9.1.0","v9.0.1"],"title":"[Search]
Remove website search guided
onboarding","number":224538,"url":"https://github.com/elastic/kibana/pull/224538","mergeCommit":{"message":"[Search]
Remove website search guided onboarding (#224538)\n\n## Summary\n\nThis
removes the deprecated website search guided onboarding from\nKibana.
Deprecated because we no longer offer a managed web
crawler.\n\n---------\n\nCo-authored-by: kibanamachine
<42973632+kibanamachine@users.noreply.github.com>","sha":"9171743e8368a47503cf5892a8b7e47d35b42319"}},"sourceBranch":"main","suggestedTargetBranches":["9.0"],"targetPullRequestStates":[{"branch":"main","label":"v9.1.0","branchLabelMappingKey":"^v9.1.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/224538","number":224538,"mergeCommit":{"message":"[Search]
Remove website search guided onboarding (#224538)\n\n## Summary\n\nThis
removes the deprecated website search guided onboarding from\nKibana.
Deprecated because we no longer offer a managed web
crawler.\n\n---------\n\nCo-authored-by: kibanamachine
<42973632+kibanamachine@users.noreply.github.com>","sha":"9171743e8368a47503cf5892a8b7e47d35b42319"}},{"branch":"9.0","label":"v9.0.1","branchLabelMappingKey":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"}]}]
BACKPORT-->

---------

Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
2025-06-20 08:07:25 -05:00

356 lines
11 KiB
TypeScript

/*
* 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", the "GNU Affero General Public License v3.0 only", 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", the "GNU Affero General Public
* License v3.0 only", or the "Server Side Public License, v 1".
*/
import React, { useEffect, useState } from 'react';
import { useHistory } from 'react-router-dom';
import { FormattedMessage } from '@kbn/i18n-react';
import { i18n } from '@kbn/i18n';
import { CoreStart } from '@kbn/core/public';
import {
EuiButton,
EuiFieldText,
EuiFlexGroup,
EuiFlexItem,
EuiFormRow,
EuiHorizontalRule,
EuiPageSection,
EuiPageHeader,
EuiSelect,
EuiSpacer,
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';
interface MainProps {
guidedOnboarding?: GuidedOnboardingPluginStart;
notifications: CoreStart['notifications'];
}
const exampleGuideIds: GuideId[] = ['databaseSearch', 'siem', 'kubernetes', 'testGuide'];
const selectOptions: EuiSelectOption[] = exampleGuideIds.map((guideId) => ({
value: guideId,
text: guideId,
}));
export const Main = (props: MainProps) => {
const { guidedOnboarding, notifications } = props;
const history = useHistory();
const [guidesState, setGuidesState] = useState<GuideState[] | undefined>(undefined);
const [activeGuide, setActiveGuide] = useState<GuideState | undefined>(undefined);
const [selectedGuide, setSelectedGuide] = useState<GuideId | undefined>('kubernetes');
const [selectedStep, setSelectedStep] = useState<GuideStepIds | undefined>(undefined);
useEffect(() => {
const fetchGuidesState = async () => {
const newGuidesState = await guidedOnboarding?.guidedOnboardingApi?.fetchAllGuidesState();
setGuidesState(newGuidesState ? newGuidesState.state : []);
};
fetchGuidesState();
}, [guidedOnboarding]);
useEffect(() => {
const newActiveGuide = guidesState?.find((guide) => guide.isActive === true);
if (newActiveGuide) {
setActiveGuide(newActiveGuide);
}
}, [guidesState, setActiveGuide]);
const activateGuide = async (guideId: GuideId, guideState?: GuideState) => {
const response = await guidedOnboarding?.guidedOnboardingApi?.activateGuide(
guideId,
guideState
);
if (response) {
notifications.toasts.addSuccess(
i18n.translate('guidedOnboardingExample.startGuide.toastLabel', {
defaultMessage: 'Guide (re-)started',
})
);
}
};
const updateGuideState = async () => {
if (!selectedGuide) {
return;
}
const selectedGuideConfig = await guidedOnboarding?.guidedOnboardingApi?.getGuideConfig(
selectedGuide
);
if (!selectedGuideConfig) {
return;
}
const selectedStepIndex = selectedGuideConfig.steps.findIndex(
(step) => step.id === selectedStep!
);
// Noop if the selected step is invalid
if (selectedStepIndex === -1) {
return;
}
const updatedSteps: GuideStep[] = selectedGuideConfig.steps.map((step, stepIndex) => {
if (selectedStepIndex > stepIndex) {
return {
id: step.id,
status: 'complete',
};
}
if (selectedStepIndex < stepIndex) {
return {
id: step.id,
status: 'inactive',
};
}
return {
id: step.id,
status: 'active',
};
});
const updatedGuideState: GuideState = {
isActive: true,
status: 'in_progress',
steps: updatedSteps,
guideId: selectedGuide!,
};
const response = await guidedOnboarding?.guidedOnboardingApi?.updatePluginState(
{ status: 'in_progress', guide: updatedGuideState },
true
);
if (response) {
notifications.toasts.addSuccess(
i18n.translate('guidedOnboardingExample.updateGuideState.toastLabel', {
defaultMessage: 'Guide state updated',
})
);
}
};
return (
<>
<EuiPageHeader>
<EuiTitle>
<h2>
<FormattedMessage
id="guidedOnboardingExample.main.title"
defaultMessage="Guided setup state"
/>
</h2>
</EuiTitle>
</EuiPageHeader>
<EuiPageSection>
<EuiText>
<h3>
<FormattedMessage
id="guidedOnboardingExample.main.currentStateTitle"
defaultMessage="Current state"
/>
</h3>
<p>
<FormattedMessage
id="guidedOnboardingExample.guidesSelection.state.explanation"
defaultMessage="The guide state on this page is updated automatically via an Observable subscription,
so there is no need to 'load' the state from the server."
/>
</p>
{activeGuide ? (
<dl>
<dt>
<FormattedMessage
id="guidedOnboardingExample.guidesSelection.state.activeGuideLabel"
defaultMessage="Active guide"
/>
</dt>
<dd>{activeGuide.guideId}</dd>
<dt>
<FormattedMessage
id="guidedOnboardingExample.guidesSelection.state.activeStepLabel"
defaultMessage="Steps status"
/>
</dt>
<dd>
{activeGuide.steps.map((step) => {
return (
<>
{`Step "${step.id}": ${step.status}`} <br />
</>
);
})}
</dd>
</dl>
) : (
<p>
<FormattedMessage
id="guidedOnboardingExample.guidesSelection.state.noActiveGuidesMessage"
defaultMessage="There are currently no active guides."
/>
</p>
)}
</EuiText>
<EuiHorizontalRule />
<EuiText>
<h3>
<FormattedMessage
id="guidedOnboardingExample.main.startGuide.title"
defaultMessage="Guides"
/>
</h3>
</EuiText>
<EuiSpacer />
<EuiFlexGrid columns={3}>
{exampleGuideIds.map((guideId) => {
const guideState = guidesState?.find((guide) => guide.guideId === guideId);
return (
<EuiFlexItem>
<EuiButton
onClick={() => activateGuide(guideId, guideState)}
fill
disabled={guideState?.status === 'complete'}
>
{guideState === undefined && (
<FormattedMessage
id="guidedOnboardingExample.guidesSelection.startButtonLabel"
defaultMessage="Start {guideId} guide"
values={{
guideId,
}}
/>
)}
{(guideState?.isActive === true ||
guideState?.status === 'in_progress' ||
guideState?.status === 'ready_to_complete' ||
guideState?.status === 'not_started') && (
<FormattedMessage
id="guidedOnboardingExample.guidesSelection.continueButtonLabel"
defaultMessage="Continue {guideId} guide"
values={{
guideId,
}}
/>
)}
{guideState?.status === 'complete' && (
<FormattedMessage
id="guidedOnboardingExample.guidesSelection.completeButtonLabel"
defaultMessage="Guide {guideId} complete"
values={{
guideId,
}}
/>
)}
</EuiButton>
</EuiFlexItem>
);
})}
</EuiFlexGrid>
<EuiSpacer />
<EuiHorizontalRule />
<EuiText>
<h3>
<FormattedMessage
id="guidedOnboardingExample.main.setGuideState.title"
defaultMessage="Set guide state"
/>
</h3>
</EuiText>
<EuiSpacer />
<EuiFlexGroup>
<EuiFlexItem>
<EuiFormRow label="Guide" helpText="Select a guide">
<EuiSelect
id="guideSelect"
options={selectOptions}
value={selectedGuide}
onChange={(e) => {
const value = e.target.value as GuideId;
const shouldResetState = value.trim().length === 0;
if (shouldResetState) {
setSelectedGuide(undefined);
setSelectedStep(undefined);
} else {
setSelectedGuide(value);
}
}}
/>
</EuiFormRow>
</EuiFlexItem>
<EuiFlexItem>
<EuiFormRow label="Step ID">
<EuiFieldText
value={selectedStep}
onChange={(e) => setSelectedStep(e.target.value as GuideStepIds)}
/>
</EuiFormRow>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiFormRow hasEmptyLabelSpace>
<EuiButton onClick={updateGuideState}>Save</EuiButton>
</EuiFormRow>
</EuiFlexItem>
</EuiFlexGroup>
<EuiSpacer />
<EuiHorizontalRule />
<EuiText>
<h3>
<FormattedMessage
id="guidedOnboardingExample.main.examplePages.title"
defaultMessage="Example pages for test guide"
/>
</h3>
</EuiText>
<EuiSpacer />
<EuiFlexGroup>
<EuiFlexItem grow={false}>
<EuiButton onClick={() => history.push('stepOne')}>
<FormattedMessage
id="guidedOnboardingExample.main.examplePages.stepOne.link"
defaultMessage="Step 1"
/>
</EuiButton>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiButton onClick={() => history.push('stepTwo')}>
<FormattedMessage
id="guidedOnboardingExample.main.examplePages.stepTwo.link"
defaultMessage="Step 2"
/>
</EuiButton>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiButton onClick={() => history.push('stepThree')}>
<FormattedMessage
id="guidedOnboardingExample.main.examplePages.stepThree.link"
defaultMessage="Step 3"
/>
</EuiButton>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiButton onClick={() => history.push('stepFour')}>
<FormattedMessage
id="guidedOnboardingExample.main.examplePages.stepFour.link"
defaultMessage="Step 4"
/>
</EuiButton>
</EuiFlexItem>
</EuiFlexGroup>
</EuiPageSection>
</>
);
};