[Guided onboarding] Add guided onboarding to the home page (#143837)

* [Guided onboarding] Add guided onboarding to the home page

* [Guided onboarding] Fix smaller screen layout

* [Guided onboarding] Disable welcome screen on use case click

* Revert "[Guided onboarding] Disable welcome screen on use case click"

This reverts commit abc347e741.

* [Guided onboarding] Update snapshots

* [Guided onboarding] Address CR comments

* [Guided onboarding] Address copy comments
This commit is contained in:
Yulia Čech 2022-10-27 09:47:05 +02:00 committed by GitHub
parent 8eeb9e2fa2
commit d0bea55fdf
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 127 additions and 10 deletions

View file

@ -28,8 +28,10 @@ exports[`home change home route should render a link to change the default route
"integrations": true,
},
},
"navigateToUrl": [MockFunction],
}
}
isCloudEnabled={false}
isDarkMode={false}
/>
<ManageData
@ -41,6 +43,7 @@ exports[`home change home route should render a link to change the default route
"integrations": true,
},
},
"navigateToUrl": [MockFunction],
}
}
features={Array []}
@ -82,8 +85,10 @@ exports[`home directories should not render directory entry when showOnHomePage
"integrations": true,
},
},
"navigateToUrl": [MockFunction],
}
}
isCloudEnabled={false}
isDarkMode={false}
/>
<ManageData
@ -95,6 +100,7 @@ exports[`home directories should not render directory entry when showOnHomePage
"integrations": true,
},
},
"navigateToUrl": [MockFunction],
}
}
features={Array []}
@ -136,8 +142,10 @@ exports[`home directories should render ADMIN directory entry in "Manage your da
"integrations": true,
},
},
"navigateToUrl": [MockFunction],
}
}
isCloudEnabled={false}
isDarkMode={false}
/>
<ManageData
@ -149,6 +157,7 @@ exports[`home directories should render ADMIN directory entry in "Manage your da
"integrations": true,
},
},
"navigateToUrl": [MockFunction],
}
}
features={
@ -237,8 +246,10 @@ exports[`home directories should render solutions in the "solution section" 1`]
"integrations": true,
},
},
"navigateToUrl": [MockFunction],
}
}
isCloudEnabled={false}
isDarkMode={false}
/>
<ManageData
@ -250,6 +261,7 @@ exports[`home directories should render solutions in the "solution section" 1`]
"integrations": true,
},
},
"navigateToUrl": [MockFunction],
}
}
features={Array []}
@ -291,8 +303,22 @@ exports[`home isNewKibanaInstance should safely handle exceptions 1`] = `
"integrations": true,
},
},
"navigateToUrl": [MockFunction] {
"calls": Array [
Array [
"./home#/getting_started",
],
],
"results": Array [
Object {
"type": "return",
"value": undefined,
},
],
},
}
}
isCloudEnabled={false}
isDarkMode={false}
/>
<ManageData
@ -304,6 +330,19 @@ exports[`home isNewKibanaInstance should safely handle exceptions 1`] = `
"integrations": true,
},
},
"navigateToUrl": [MockFunction] {
"calls": Array [
Array [
"./home#/getting_started",
],
],
"results": Array [
Object {
"type": "return",
"value": undefined,
},
],
},
}
}
features={Array []}
@ -345,8 +384,22 @@ exports[`home isNewKibanaInstance should set isNewKibanaInstance to false when t
"integrations": true,
},
},
"navigateToUrl": [MockFunction] {
"calls": Array [
Array [
"./home#/getting_started",
],
],
"results": Array [
Object {
"type": "return",
"value": undefined,
},
],
},
}
}
isCloudEnabled={false}
isDarkMode={false}
/>
<ManageData
@ -358,6 +411,19 @@ exports[`home isNewKibanaInstance should set isNewKibanaInstance to false when t
"integrations": true,
},
},
"navigateToUrl": [MockFunction] {
"calls": Array [
Array [
"./home#/getting_started",
],
],
"results": Array [
Object {
"type": "return",
"value": undefined,
},
],
},
}
}
features={Array []}
@ -406,8 +472,10 @@ exports[`home should render home component 1`] = `
"integrations": true,
},
},
"navigateToUrl": [MockFunction],
}
}
isCloudEnabled={false}
isDarkMode={false}
/>
<ManageData
@ -419,6 +487,7 @@ exports[`home should render home component 1`] = `
"integrations": true,
},
},
"navigateToUrl": [MockFunction],
}
}
features={Array []}

View file

@ -28,7 +28,7 @@ exports[`AddData render 1`] = `
<EuiText>
<p>
<FormattedMessage
defaultMessage="To start working with your data, use one of our many ingest options. Collect data from an app or service, or upload a file. If you're not ready to use your own data, add a sample data set."
defaultMessage="To start working with your data, use one of our many ingest options. Collect data from an app or service, or upload a file. If you're not ready to use your own data, play with a sample data set."
id="home.addData.text"
values={Object {}}
/>
@ -37,8 +37,6 @@ exports[`AddData render 1`] = `
<EuiSpacer />
<EuiFlexGroup
gutterSize="m"
responsive={false}
wrap={true}
>
<EuiFlexItem
grow={false}
@ -57,6 +55,7 @@ exports[`AddData render 1`] = `
<EuiButton
data-test-subj="homeAddData"
fill={true}
fullWidth={true}
href="/app/integrations/browse"
iconType="plusInCircle"
onClick={[Function]}

View file

@ -40,6 +40,7 @@ describe('AddData', () => {
addBasePath={addBasePathMock}
application={applicationStartMock}
isDarkMode={false}
isCloudEnabled={false}
/>
);
expect(component).toMatchSnapshot();

View file

@ -29,9 +29,10 @@ interface Props {
addBasePath: (path: string) => string;
application: ApplicationStart;
isDarkMode: boolean;
isCloudEnabled: boolean;
}
export const AddData: FC<Props> = ({ addBasePath, application, isDarkMode }) => {
export const AddData: FC<Props> = ({ addBasePath, application, isDarkMode, isCloudEnabled }) => {
const { trackUiMetric } = getServices();
const canAccessIntegrations = application.capabilities.navLinks.integrations;
if (canAccessIntegrations) {
@ -59,26 +60,47 @@ export const AddData: FC<Props> = ({ addBasePath, application, isDarkMode }) =>
<p>
<FormattedMessage
id="home.addData.text"
defaultMessage="To start working with your data, use one of our many ingest options. Collect data from an app or service, or upload a file. If you're not ready to use your own data, add a sample data set."
defaultMessage="To start working with your data, use one of our many ingest options. Collect data from an app or service, or upload a file. If you're not ready to use your own data, play with a sample data set."
/>
</p>
</EuiText>
<EuiSpacer />
<EuiFlexGroup gutterSize="m" responsive={false} wrap>
<EuiFlexGroup gutterSize="m">
{isCloudEnabled && (
<EuiFlexItem grow={false}>
{/* eslint-disable-next-line @elastic/eui/href-or-on-click */}
<EuiButton
data-test-subj="guidedOnboardingLink"
fill
href={addBasePath('#/getting_started')}
onClick={(event: MouseEvent) => {
trackUiMetric(METRIC_TYPE.CLICK, 'guided_onboarding_link');
}}
>
<FormattedMessage
id="home.addData.guidedOnboardingLinkLabel"
defaultMessage="Launch setup guide"
/>
</EuiButton>
</EuiFlexItem>
)}
<EuiFlexItem grow={false}>
<RedirectAppLinks application={application}>
{/* eslint-disable-next-line @elastic/eui/href-or-on-click */}
<EuiButton
data-test-subj="homeAddData"
fill
// on self managed this button is primary
// on Cloud this button is secondary, because there is a "guided onboarding" button
fill={!isCloudEnabled}
href={addBasePath('/app/integrations/browse')}
iconType="plusInCircle"
onClick={(event: MouseEvent) => {
trackUiMetric(METRIC_TYPE.CLICK, 'home_tutorial_directory');
createAppNavigationHandler('/app/integrations/browse')(event);
}}
fullWidth
>
<FormattedMessage
id="home.addData.addDataButtonLabel"

View file

@ -14,6 +14,7 @@ import { Home } from './home';
import { Welcome } from './welcome';
let mockHasIntegrationsPermission = true;
const mockNavigateToUrl = jest.fn();
jest.mock('../kibana_services', () => ({
getServices: () => ({
getBasePath: () => 'path',
@ -23,6 +24,7 @@ jest.mock('../kibana_services', () => ({
setBreadcrumbs: () => {},
},
application: {
navigateToUrl: mockNavigateToUrl,
capabilities: {
navLinks: {
integrations: mockHasIntegrationsPermission,
@ -59,6 +61,7 @@ describe('home', () => {
return `base_path/${url}`;
},
hasUserDataView: jest.fn(async () => true),
isCloudEnabled: false,
};
});
@ -230,6 +233,16 @@ describe('home', () => {
expect(component.find(Welcome).exists()).toBe(false);
});
test('should redirect to guided onboarding on Cloud instead of welcome screen', async () => {
const isCloudEnabled = true;
const hasUserDataView = jest.fn(async () => false);
const component = await renderHome({ isCloudEnabled, hasUserDataView });
expect(component.find(Welcome).exists()).toBe(false);
expect(mockNavigateToUrl).toHaveBeenCalledTimes(1);
});
});
describe('isNewKibanaInstance', () => {

View file

@ -33,6 +33,7 @@ export interface HomeProps {
localStorage: Storage;
urlBasePath: string;
hasUserDataView: () => Promise<boolean>;
isCloudEnabled: boolean;
}
interface State {
@ -126,7 +127,7 @@ export class Home extends Component<HomeProps, State> {
}
private renderNormal() {
const { addBasePath, solutions } = this.props;
const { addBasePath, solutions, isCloudEnabled } = this.props;
const { application, trackUiMetric } = getServices();
const isDarkMode = getServices().uiSettings?.get('theme:darkMode') || false;
const devTools = this.findDirectoryById('console');
@ -148,7 +149,12 @@ export class Home extends Component<HomeProps, State> {
>
<SolutionsSection addBasePath={addBasePath} solutions={solutions} />
<AddData addBasePath={addBasePath} application={application} isDarkMode={isDarkMode} />
<AddData
addBasePath={addBasePath}
application={application}
isDarkMode={isDarkMode}
isCloudEnabled={isCloudEnabled}
/>
<ManageData
addBasePath={addBasePath}
@ -182,12 +188,18 @@ export class Home extends Component<HomeProps, State> {
public render() {
const { isLoading, isWelcomeEnabled, isNewKibanaInstance } = this.state;
const { isCloudEnabled } = this.props;
const { application } = getServices();
if (isWelcomeEnabled) {
if (isLoading) {
return this.renderLoading();
}
if (isNewKibanaInstance) {
if (isCloudEnabled) {
application.navigateToUrl('./home#/getting_started');
return;
}
return this.renderWelcome();
}
}

View file

@ -79,6 +79,7 @@ export function HomeApp({ directories, solutions }) {
localStorage={localStorage}
urlBasePath={getBasePath()}
hasUserDataView={() => dataViewsService.hasUserDataView()}
isCloudEnabled={isCloudEnabled}
/>
</Route>
<Redirect to="/" />

View file

@ -45,7 +45,7 @@ export function SampleDataCard({ urlBasePath, onDecline, onConfirm }: Props) {
description={
<FormattedMessage
id="home.letsStartDescription"
defaultMessage="Add data to your cluster from any source, then analyze and visualize it in real time. Use our solutions to add search anywhere, observe your ecosystem, and protect against security threats."
defaultMessage="Add data to your cluster from any source, then analyze and visualize it in real time. Use our solutions to add search anywhere, observe your ecosystem, and defend against security threats."
/>
}
footer={