[Guided onboarding] Register test guide in the example plugin (#147703)

This PR moves the test guide used for testing and dev work to the guided
onboarding package. It is now being registered when the guided
onboarding example plugin is being setup. For that a server side is
added to the example plugin.
Registering the test guide from the example plugin demonstrates how the
"register guide" function can be used for production guides. The test
config needs to be in the `kbn-guided-onboarding` package because
example plugins have some problems importing files from other plugins.
That way the test config is available to the example plugin and to the
guided onboarding plugin for unit and functional tests.

Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
Yulia Čech 2023-01-20 11:29:25 +01:00 committed by GitHub
parent f90a89a839
commit e7746b24d5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
30 changed files with 165 additions and 105 deletions

View file

@ -7,7 +7,7 @@
"githubTeam": "platform-onboarding"
},
"description": "Example plugin to consume guidedOnboarding",
"server": false,
"server": true,
"ui": true,
"requiredPlugins": ["navigation", "guidedOnboarding"],
"optionalPlugins": []

View file

@ -0,0 +1,12 @@
/*
* 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 { PluginInitializerContext } from '@kbn/core/server';
import { GuidedOnboardingExamplePlugin } from './plugin';
export const plugin = (ctx: PluginInitializerContext) => new GuidedOnboardingExamplePlugin(ctx);

View file

@ -0,0 +1,36 @@
/*
* 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 { GuidedOnboardingPluginSetup } from '@kbn/guided-onboarding-plugin/server';
import { PluginInitializerContext, CoreSetup, Plugin, Logger } from '@kbn/core/server';
import { testGuideId, testGuideConfig } from '@kbn/guided-onboarding';
interface PluginsSetup {
guidedOnboarding: GuidedOnboardingPluginSetup;
}
export class GuidedOnboardingExamplePlugin implements Plugin {
private readonly logger: Logger;
constructor(initializerContext: PluginInitializerContext) {
this.logger = initializerContext.logger.get();
}
public setup(coreSetup: CoreSetup, { guidedOnboarding }: PluginsSetup) {
this.logger.debug('guidedOnboardingExample: Setup');
guidedOnboarding.registerGuideConfig(testGuideId, testGuideConfig);
return {};
}
public start() {
this.logger.debug('guidedOnboardingExample: Started');
return {};
}
public stop() {}
}

View file

@ -0,0 +1,13 @@
/*
* 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.
*/
// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface GuidedOnboardingExamplePluginSetup {}
// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface GuidedOnboardingExamplePluginStart {}

View file

@ -13,6 +13,10 @@ export type {
StepStatus,
GuideStep,
GuideStatus,
GuideConfig,
StepConfig,
StepDescriptionWithLink,
} from './src/types';
export { GuideCard, InfrastructureLinkCard } from './src/components/landing_page';
export type { GuideCardUseCase } from './src/components/landing_page';
export { testGuideId, testGuideConfig } from './src/common/test_guide_config';

View file

@ -6,8 +6,7 @@
* Side Public License, v 1.
*/
import type { GuideId } from '@kbn/guided-onboarding';
import type { GuideConfig } from './types';
import type { GuideId, GuideConfig } from '../types';
export const testGuideId: GuideId = 'testGuide';
export const testGuideConfig: GuideConfig = {

View file

@ -45,3 +45,56 @@ export interface GuideStep {
id: GuideStepIds;
status: StepStatus;
}
export interface GuideConfig {
title: string;
description: string;
guideName: string;
telemetryId: string;
docs?: {
text: string;
url: string;
};
completedGuideRedirectLocation?: {
appID: string;
path: string;
};
steps: StepConfig[];
}
/* To append a link to the description, specify its text and url in the properties.
* An example:
* {
* description: 'This is a description with a link'.
* linkText: 'My link',
* linkUrl: 'example.com',
* isLinkExternal: true,
* }
*
*/
export interface StepDescriptionWithLink {
descriptionText: string;
linkText: string;
linkUrl: string;
isLinkExternal?: boolean;
}
export interface StepConfig {
id: GuideStepIds;
title: string;
// description is displayed as a single paragraph, can be combined with description list
description?: string | StepDescriptionWithLink;
// description list is displayed as an unordered list, can be combined with description
descriptionList?: Array<string | StepDescriptionWithLink>;
location?: {
appID: string;
path: string;
};
status?: StepStatus;
integration?: string;
manualCompletion?: {
title: string;
description: string;
readyToCompleteOnNavigation?: boolean;
};
}

View file

@ -7,12 +7,4 @@
*/
export { PLUGIN_ID, PLUGIN_NAME, API_BASE_PATH } from './constants';
export { testGuideConfig, testGuideId } from './test_guide_config';
export type {
PluginStatus,
PluginState,
StepConfig,
GuideConfig,
GuidesConfig,
StepDescriptionWithLink,
} from './types';
export type { PluginStatus, PluginState, GuidesConfig } from './types';

View file

@ -6,7 +6,7 @@
* Side Public License, v 1.
*/
import type { GuideId, GuideState, GuideStepIds, StepStatus } from '@kbn/guided-onboarding';
import type { GuideId, GuideState, GuideConfig } from '@kbn/guided-onboarding';
/**
* Guided onboarding overall status:
@ -32,59 +32,6 @@ export interface PluginState {
activeGuide?: GuideState;
}
/* To append a link to the description, specify its text and url in the properties.
* An example:
* {
* description: 'This is a description with a link'.
* linkText: 'My link',
* linkUrl: 'example.com',
* isLinkExternal: true,
* }
*
*/
export interface StepDescriptionWithLink {
descriptionText: string;
linkText: string;
linkUrl: string;
isLinkExternal?: boolean;
}
export interface StepConfig {
id: GuideStepIds;
title: string;
// description is displayed as a single paragraph, can be combined with description list
description?: string | StepDescriptionWithLink;
// description list is displayed as an unordered list, can be combined with description
descriptionList?: Array<string | StepDescriptionWithLink>;
location?: {
appID: string;
path: string;
};
status?: StepStatus;
integration?: string;
manualCompletion?: {
title: string;
description: string;
readyToCompleteOnNavigation?: boolean;
};
}
export interface GuideConfig {
title: string;
description: string;
guideName: string;
telemetryId: string;
docs?: {
text: string;
url: string;
};
completedGuideRedirectLocation?: {
appID: string;
path: string;
};
steps: StepConfig[];
}
export type GuidesConfig = {
[key in GuideId]: GuideConfig;
};

View file

@ -9,9 +9,9 @@
import React from 'react';
import { EuiButton } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import type { GuideState } from '@kbn/guided-onboarding';
import type { GuideState, GuideConfig } from '@kbn/guided-onboarding';
import type { GuideConfig, PluginState } from '../../common';
import type { PluginState } from '../../common';
import { GuideButtonPopover } from './guide_button_popover';
interface GuideButtonProps {

View file

@ -14,9 +14,10 @@ import { notificationServiceMock } from '@kbn/core-notifications-browser-mocks';
import { httpServiceMock } from '@kbn/core/public/mocks';
import type { HttpSetup } from '@kbn/core/public';
import { registerTestBed, TestBed } from '@kbn/test-jest-helpers';
import { testGuideConfig, testGuideId } from '@kbn/guided-onboarding';
import type { PluginState } from '../../common';
import { API_BASE_PATH, testGuideConfig, testGuideId } from '../../common';
import { API_BASE_PATH } from '../../common';
import { apiService } from '../services/api';
import type { GuidedOnboardingApi } from '../types';
import {

View file

@ -32,10 +32,10 @@ import { i18n } from '@kbn/i18n';
import { ApplicationStart, NotificationsStart } from '@kbn/core/public';
import type { GuideState, GuideStep as GuideStepStatus } from '@kbn/guided-onboarding';
import { GuideId } from '@kbn/guided-onboarding';
import type { GuideId, GuideConfig, StepConfig } from '@kbn/guided-onboarding';
import type { GuidedOnboardingApi } from '../types';
import type { GuideConfig, PluginState, StepConfig } from '../../common';
import type { PluginState } from '../../common';
import { GuideStep } from './guide_panel_step';
import { QuitGuideModal } from './quit_guide_modal';

View file

@ -22,8 +22,7 @@ import {
import { i18n } from '@kbn/i18n';
import type { StepStatus } from '@kbn/guided-onboarding';
import type { StepDescriptionWithLink, StepConfig } from '../../common';
import type { StepStatus, StepConfig, StepDescriptionWithLink } from '@kbn/guided-onboarding';
import { getGuidePanelStepStyles } from './guide_panel_step.styles';
interface GuideStepProps {

View file

@ -9,9 +9,10 @@
import { HttpSetup } from '@kbn/core/public';
import { httpServiceMock } from '@kbn/core/public/mocks';
import type { GuideState } from '@kbn/guided-onboarding';
import { testGuideConfig, testGuideId } from '@kbn/guided-onboarding';
import { firstValueFrom, Subscription } from 'rxjs';
import { API_BASE_PATH, testGuideConfig, testGuideId } from '../../common';
import { API_BASE_PATH } from '../../common';
import { ApiService } from './api';
import {
testGuideFirstStep,

View file

@ -17,10 +17,16 @@ import {
concat,
from,
} from 'rxjs';
import type { GuideState, GuideId, GuideStep, GuideStepIds } from '@kbn/guided-onboarding';
import type {
GuideState,
GuideId,
GuideStep,
GuideStepIds,
GuideConfig,
} from '@kbn/guided-onboarding';
import { API_BASE_PATH } from '../../common';
import type { PluginState, PluginStatus, GuideConfig } from '../../common';
import type { PluginState, PluginStatus } from '../../common';
import { GuidedOnboardingApi } from '../types';
import {
getInProgressStepId,
@ -169,7 +175,7 @@ export class ApiService implements GuidedOnboardingApi {
/**
* Activates a guide by guideId.
* This is useful for the onboarding landing page, when a user selects a guide to start or continue.
* @param {GuideId} guideId the id of the guide (one of search, observability, security)
* @param {GuideId} guideId the id of the guide (one of search, kubernetes, siem)
* @param {GuideState} guide (optional) the selected guide state, if it exists (i.e., if a user is continuing a guide)
* @return {Promise} a promise with the updated plugin state
*/
@ -247,7 +253,7 @@ export class ApiService implements GuidedOnboardingApi {
* Completes a guide.
* Updates the overall guide status to 'complete', and marks it as inactive.
* This is useful for the dropdown panel, when the user clicks the "Continue using Elastic" button after completing all steps.
* @param {GuideId} guideId the id of the guide (one of search, observability, security)
* @param {GuideId} guideId the id of the guide (one of search, kubernetes, siem)
* @return {Promise} a promise with the updated plugin state
*/
public async completeGuide(guideId: GuideId): Promise<{ pluginState: PluginState } | undefined> {
@ -277,7 +283,7 @@ export class ApiService implements GuidedOnboardingApi {
* An observable with the boolean value if the step is in progress (i.e., user clicked "Start" on a step).
* Returns true, if the passed params identify the guide step that is currently in progress.
* Returns false otherwise.
* @param {GuideId} guideId the id of the guide (one of search, observability, security)
* @param {GuideId} guideId the id of the guide (one of search, kubernetes, siem)
* @param {GuideStepIds} stepId the id of the step in the guide
* @return {Observable} an observable with the boolean value
*/
@ -294,7 +300,7 @@ export class ApiService implements GuidedOnboardingApi {
* An observable with the boolean value if the step is ready_to_complete (i.e., user needs to click the "Mark done" button).
* Returns true, if the passed params identify the guide step that is currently ready_to_complete.
* Returns false otherwise.
* @param {GuideId} guideId the id of the guide (one of search, observability, security)
* @param {GuideId} guideId the id of the guide (one of search, kubernetes, siem)
* @param {GuideStepIds} stepId the id of the step in the guide
* @return {Observable} an observable with the boolean value
*/
@ -310,7 +316,7 @@ export class ApiService implements GuidedOnboardingApi {
/**
* Updates the selected step to 'in_progress' state.
* This is useful for the dropdown panel, when the user clicks the "Start" button for the active step.
* @param {GuideId} guideId the id of the guide (one of search, observability, security)
* @param {GuideId} guideId the id of the guide (one of search, kubernetes, siem)
* @param {GuideStepIds} stepId the id of the step
* @return {Promise} a promise with the updated plugin state
*/
@ -352,7 +358,7 @@ export class ApiService implements GuidedOnboardingApi {
/**
* Completes the guide step identified by the passed params.
* A noop if the passed step is not active.
* @param {GuideId} guideId the id of the guide (one of search, observability, security)
* @param {GuideId} guideId the id of the guide (one of search, kubernetes, siem)
* @param {GuideStepIds} stepId the id of the step in the guide
* @return {Promise} a promise with the updated state or undefined if the operation fails
*/

View file

@ -7,8 +7,9 @@
*/
import { HttpSetup } from '@kbn/core-http-browser';
import { testGuideConfig, testGuideId } from '@kbn/guided-onboarding';
import { httpServiceMock } from '@kbn/core-http-browser-mocks';
import { API_BASE_PATH, testGuideConfig, testGuideId } from '../../common';
import { API_BASE_PATH } from '../../common';
import {
testGuideNotActiveState,
testGuideStep1InProgressState,

View file

@ -7,8 +7,8 @@
*/
import { HttpSetup } from '@kbn/core-http-browser';
import { GuideId, GuideState, GuideStatus } from '@kbn/guided-onboarding';
import type { GuideConfig, GuidesConfig } from '../../common';
import { GuideId, GuideState, GuideStatus, GuideConfig } from '@kbn/guided-onboarding';
import type { GuidesConfig } from '../../common';
import { API_BASE_PATH } from '../../common';
import { findGuideConfigByGuideId, getInProgressStepConfig } from './helpers';

View file

@ -6,7 +6,7 @@
* Side Public License, v 1.
*/
import { testGuideConfig, testGuideId } from '../../common';
import { testGuideConfig, testGuideId } from '@kbn/guided-onboarding';
import type { GuidesConfig } from '../../common';
import {
findGuideConfigByGuideId,

View file

@ -12,8 +12,10 @@ import type {
GuideState,
GuideStep,
StepStatus,
GuideConfig,
StepConfig,
} from '@kbn/guided-onboarding';
import type { GuidesConfig, PluginState, GuideConfig, StepConfig } from '../../common';
import type { GuidesConfig, PluginState } from '../../common';
export const findGuideConfigByGuideId = (
guidesConfig?: GuidesConfig,

View file

@ -8,9 +8,9 @@
import { Observable } from 'rxjs';
import { HttpSetup } from '@kbn/core/public';
import type { GuideState, GuideId, GuideStepIds } from '@kbn/guided-onboarding';
import type { GuideState, GuideId, GuideStepIds, GuideConfig } from '@kbn/guided-onboarding';
import type { CloudStart } from '@kbn/cloud-plugin/public';
import type { PluginStatus, PluginState, GuideConfig } from '../common';
import type { PluginStatus, PluginState } from '../common';
// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface GuidedOnboardingPluginSetup {}

View file

@ -14,4 +14,3 @@ export function plugin(initializerContext: PluginInitializerContext) {
}
export type { GuidedOnboardingPluginSetup, GuidedOnboardingPluginStart } from './types';
export { testGuideConfig } from '../common/test_guide_config';

View file

@ -8,24 +8,21 @@
import { PluginInitializerContext, CoreSetup, Plugin, Logger } from '@kbn/core/server';
import type { GuideId } from '@kbn/guided-onboarding';
import type { GuideId, GuideConfig } from '@kbn/guided-onboarding';
import { GuidedOnboardingPluginSetup, GuidedOnboardingPluginStart } from './types';
import { defineRoutes } from './routes';
import { guideStateSavedObjects, pluginStateSavedObjects } from './saved_objects';
import type { GuideConfig, GuidesConfig } from '../common';
import { testGuideConfig, testGuideId } from '../common';
import type { GuidesConfig } from '../common';
export class GuidedOnboardingPlugin
implements Plugin<GuidedOnboardingPluginSetup, GuidedOnboardingPluginStart>
{
private readonly logger: Logger;
private readonly guidesConfig: GuidesConfig;
private readonly isDevMode: boolean;
constructor(initializerContext: PluginInitializerContext) {
this.logger = initializerContext.logger.get();
this.guidesConfig = {} as GuidesConfig;
this.isDevMode = initializerContext.env.mode.dev;
}
public setup(core: CoreSetup) {
@ -39,10 +36,6 @@ export class GuidedOnboardingPlugin
core.savedObjects.registerType(guideStateSavedObjects);
core.savedObjects.registerType(pluginStateSavedObjects);
// add a config for a test guide if running in dev mode
if (this.isDevMode) {
this.guidesConfig[testGuideId] = testGuideConfig;
}
return {
registerGuideConfig: (guideId: GuideId, guideConfig: GuideConfig) => {
if (this.guidesConfig[guideId]) {

View file

@ -6,8 +6,7 @@
* Side Public License, v 1.
*/
import type { GuideId } from '@kbn/guided-onboarding';
import type { GuideConfig } from '../common';
import type { GuideId, GuideConfig } from '@kbn/guided-onboarding';
export interface GuidedOnboardingPluginSetup {
registerGuideConfig: (guideId: GuideId, guideConfig: GuideConfig) => void;

View file

@ -16,7 +16,7 @@ import {
pluginStateSavedObjectsId,
guideStateSavedObjectsType,
} from '@kbn/guided-onboarding-plugin/server/saved_objects/guided_setup';
import { testGuideId } from '@kbn/guided-onboarding-plugin/common';
import { testGuideId } from '@kbn/guided-onboarding';
import type { FtrProviderContext } from '../../ftr_provider_context';
import { createGuides, createPluginState } from './helpers';

View file

@ -5,7 +5,7 @@
* 2.0.
*/
import type { GuideConfig } from '@kbn/guided-onboarding-plugin/common';
import type { GuideConfig } from '@kbn/guided-onboarding';
import { i18n } from '@kbn/i18n';
export const searchGuideId = 'search';

View file

@ -46,5 +46,6 @@
"@kbn/data-views-plugin",
"@kbn/cypress-config",
"@kbn/discover-plugin",
"@kbn/guided-onboarding",
]
}

View file

@ -5,7 +5,7 @@
* 2.0.
*/
import type { GuideConfig } from '@kbn/guided-onboarding-plugin/common';
import type { GuideConfig } from '@kbn/guided-onboarding';
import { i18n } from '@kbn/i18n';
export const kubernetesGuideId = 'kubernetes';

View file

@ -67,6 +67,7 @@
"@kbn/share-plugin",
"@kbn/core-notifications-browser",
"@kbn/slo-schema",
"@kbn/guided-onboarding",
"@kbn/charts-plugin",
],
"exclude": [

View file

@ -5,7 +5,7 @@
* 2.0.
*/
import type { GuideConfig } from '@kbn/guided-onboarding-plugin/common';
import type { GuideConfig } from '@kbn/guided-onboarding';
import { i18n } from '@kbn/i18n';
export const siemGuideId = 'siem';

View file

@ -134,5 +134,6 @@
"@kbn/controls-plugin",
"@kbn/shared-ux-utility",
"@kbn/user-profile-components",
"@kbn/guided-onboarding",
]
}