mirror of
https://github.com/elastic/kibana.git
synced 2025-06-28 11:05:39 -04:00
# 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>
356 lines
11 KiB
TypeScript
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>
|
|
</>
|
|
);
|
|
};
|