Skip to content

Commit 645d5a6

Browse files
Merge pull request #15679 from logonoff/CONSOLE-4840-guided-tour
CONSOLE-4840: Migrate GuidedTour to dynamic
2 parents efd72db + 1208430 commit 645d5a6

File tree

19 files changed

+129
-117
lines changed

19 files changed

+129
-117
lines changed

frontend/packages/console-app/console-extensions.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,13 @@
1010
"importRedirectURL": { "$codeRef": "perspective.getImportRedirectURL" }
1111
}
1212
},
13+
{
14+
"type": "INTERNAL_DO_NOT_USE.guided-tour",
15+
"properties": {
16+
"perspective": "admin",
17+
"tour": { "$codeRef": "getGuidedTour" }
18+
}
19+
},
1320
{
1421
"type": "console.flag/model",
1522
"properties": {

frontend/packages/console-app/package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
"@console/webterminal-plugin": "0.0.0-fixed"
2828
},
2929
"consolePlugin": {
30-
"entry": "src/plugin.tsx",
30+
"entry": "src/plugin.ts",
3131
"exposedModules": {
3232
"tourContext": "src/components/tour/tour-context.ts",
3333
"quickStartContext": "src/components/quick-starts/utils/quick-start-context.tsx",
@@ -89,7 +89,8 @@
8989
"volumeSnapshotContentDetails": "src/components/volume-snapshot/volume-snapshot-content-details.tsx",
9090
"ConsoleOperatorConfig": "src/components/console-operator/ConsoleOperatorConfig.tsx",
9191
"UserPreferencePage": "src/components/user-preferences/UserPreferencePage.tsx",
92-
"ConsolePluginManifestPage": "src/components/console-operator/ConsolePluginManifestPage.tsx"
92+
"ConsolePluginManifestPage": "src/components/console-operator/ConsolePluginManifestPage.tsx",
93+
"getGuidedTour": "src/components/guided-tour/index.tsx"
9394
}
9495
}
9596
}

frontend/packages/console-app/src/components/guided-tour/index.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,3 +85,5 @@ export const getGuidedTour = (): TourDataType => ({
8585
modalVariant: ModalVariant.medium,
8686
},
8787
});
88+
89+
export default getGuidedTour();

frontend/packages/console-app/src/components/tour/__tests__/tour-context.spec.ts

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import * as redux from 'react-redux';
2-
import * as useExtensionsModule from '@console/plugin-sdk/src/api/useExtensions';
2+
import * as useResolvedExtensions from '@console/dynamic-plugin-sdk/src/api/useResolvedExtensions';
33
import * as userHooks from '@console/shared/src/hooks/useUserSettingsCompatibility';
44
import { testHook } from '@console/shared/src/test-utils/hooks-utils';
55
import { TourActions } from '../const';
@@ -62,13 +62,15 @@ describe('guided-tour-context', () => {
6262
};
6363

6464
mockTourExtension = [
65-
{
66-
type: 'GuidedTour',
67-
properties: {
68-
perspective: 'dev',
69-
tour: mockTour,
65+
[
66+
{
67+
type: 'INTERNAL_DO_NOT_USE.guided-tour',
68+
properties: {
69+
perspective: 'dev',
70+
tour: mockTour,
71+
},
7072
},
71-
},
73+
],
7274
];
7375
});
7476

@@ -80,7 +82,7 @@ describe('guided-tour-context', () => {
8082
B: false,
8183
},
8284
);
83-
spyOn(useExtensionsModule, 'useExtensions').and.returnValue(mockTourExtension);
85+
spyOn(useResolvedExtensions, 'useResolvedExtensions').and.returnValue(mockTourExtension);
8486
spyOn(TourModule, 'useTourStateForPerspective').and.returnValue([
8587
{ completed: false },
8688
() => null,
@@ -110,7 +112,7 @@ describe('guided-tour-context', () => {
110112
B: false,
111113
},
112114
);
113-
spyOn(useExtensionsModule, 'useExtensions').and.returnValue([]);
115+
spyOn(useResolvedExtensions, 'useResolvedExtensions').and.returnValue([[]]);
114116
spyOn(TourModule, 'useTourStateForPerspective').and.returnValue([
115117
{ completed: false },
116118
() => null,
@@ -133,7 +135,7 @@ describe('guided-tour-context', () => {
133135
B: false,
134136
},
135137
);
136-
spyOn(useExtensionsModule, 'useExtensions').and.returnValue(mockTourExtension);
138+
spyOn(useResolvedExtensions, 'useResolvedExtensions').and.returnValue(mockTourExtension);
137139
spyOn(TourModule, 'useTourStateForPerspective').and.returnValue([
138140
{ completed: false },
139141
() => null,

frontend/packages/console-app/src/components/tour/tour-context.ts

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,14 @@ import { pick, union, isEqual } from 'lodash';
1212
import { useSelector } from 'react-redux';
1313
import { createSelector } from 'reselect';
1414
import { useActivePerspective } from '@console/dynamic-plugin-sdk';
15+
import { useResolvedExtensions } from '@console/dynamic-plugin-sdk/src/api/useResolvedExtensions';
16+
import {
17+
INTERNAL_DO_NOT_USE_isGuidedTour as isGuidedTour,
18+
INTERNAL_DO_NOT_USE_GuidedTour as GuidedTour,
19+
} from '@console/dynamic-plugin-sdk/src/extensions/guided-tour';
1520
import { getFlagsObject } from '@console/internal/reducers/features';
1621
import { RootState } from '@console/internal/redux';
17-
import { useExtensions } from '@console/plugin-sdk/src/api/useExtensions';
18-
import { isGuidedTour, GuidedTour } from '@console/plugin-sdk/src/typings/guided-tour';
22+
import { useTranslatedExtensions } from '@console/plugin-sdk/src/utils/useTranslatedExtensions';
1923
import { useUserSettingsCompatibility } from '@console/shared/src/hooks/useUserSettingsCompatibility';
2024
import { TourActions, TOUR_LOCAL_STORAGE_KEY } from './const';
2125
import { TourDataType, Step } from './type';
@@ -117,13 +121,24 @@ export const useTourStateForPerspective = (
117121
];
118122
};
119123

124+
/**
125+
* Hook to get translated guided tour extensions.
126+
*
127+
* As the translated strings of format `%namespace~string%` are behind a codeRef,
128+
* `useResolvedExtensions` does not translate the extensions.
129+
*
130+
* `useTranslatedExtensions` utility is only called in `useExtensions`. We do not
131+
* have the tour strings at this point as the codeRef is not resolved yet.
132+
*/
133+
const useTranslatedTourExtensions = () => {
134+
const [tourExtensionsRaw] = useResolvedExtensions<GuidedTour>(isGuidedTour);
135+
return useTranslatedExtensions(tourExtensionsRaw);
136+
};
137+
120138
export const useTourValuesForContext = (): TourContextType => {
121-
// declaring a method for the perspective instead of using getActivePerspective
122-
// because importing getActivePerspective in this file throws error
123-
// Uncaught ReferenceError: Cannot access 'allModels' before initialization and this hook is used in plugin extension for ContextProvider
124139
const [activePerspective] = useActivePerspective();
125140
const [perspective, setPerspective] = useState<string>(activePerspective);
126-
const tourExtension = useExtensions<GuidedTour>(isGuidedTour);
141+
const tourExtension = useTranslatedTourExtensions();
127142
const tour = tourExtension.find(({ properties }) => properties.perspective === perspective);
128143
const selectorSteps = tour?.properties?.tour?.steps ?? [];
129144
const flags = useSelector(
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
// See console-extensions.json instead
2+
export default [];

frontend/packages/console-app/src/plugin.tsx

Lines changed: 0 additions & 14 deletions
This file was deleted.
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/* eslint-disable @typescript-eslint/naming-convention */
2+
3+
import type { TourDataType } from '@console/app/src/components/tour';
4+
import type {
5+
Extension,
6+
ExtensionDeclaration,
7+
CodeRef,
8+
} from '@console/dynamic-plugin-sdk/src/types';
9+
10+
// This extension is not part of the console dynamic plugin SDK public API.
11+
// It is intended for internal use only. Please do not use it. Pretty please?
12+
13+
// Reasons:
14+
// 1. The `tour` CodeRef is structured for static plugins. i18n support is not good.
15+
// 2. We are investigating removal of the guided tour entirely.
16+
// 3. We do not guarantee the stability of the extension properties and type.
17+
18+
/** @hidden */
19+
export type INTERNAL_DO_NOT_USE_GuidedTour = ExtensionDeclaration<
20+
'INTERNAL_DO_NOT_USE.guided-tour',
21+
{
22+
perspective: string;
23+
tour: CodeRef<TourDataType>;
24+
}
25+
>;
26+
27+
/** @hidden */
28+
export const INTERNAL_DO_NOT_USE_isGuidedTour = (
29+
e: Extension,
30+
): e is INTERNAL_DO_NOT_USE_GuidedTour => {
31+
return e.type === 'INTERNAL_DO_NOT_USE.guided-tour';
32+
};
Lines changed: 33 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,25 @@
11
# OpenShift Console Static Plugins
22

33
> [!CAUTION]
4-
> The static plugin system is deprecated and is actively being removed. New and existing plugins should
5-
> use the [dynamic plugin system](../console-dynamic-plugin-sdk/README.md) instead.
4+
> New console plugins should use the dynamic plugin system as described in
5+
> the [Console Dynamic Plugins README]. New static plugins will not be accepted.
66
7-
Static plugins become part of the Console application during its webpack build. Their code is maintained
8-
as part of the frontend monorepo, built and released as an integral part of Console.
7+
Static plugins become part of the Console application during its webpack build.
8+
Their code is maintained as part of the frontend monorepo, built and released as
9+
an integral part of Console.
910

10-
The `@console/app` package represents the core application. Static plugins to be automatically included
11-
in the build are declared as `dependencies` of this package. This can be overridden via `CONSOLE_PLUGINS`
12-
env. variable whose value is a comma separated list of plugin package names.
11+
The `@console/app` package represents the core application. Static plugins to be
12+
automatically included in the build are declared as `dependencies` of this package.
13+
This can be overridden via `CONSOLE_PLUGINS` env. variable whose value is a comma
14+
separated list of plugin package names.
1315

1416
For example:
1517

1618
```sh
17-
CONSOLE_PLUGINS=dev-console,operator-lifecycle-manager yarn dev
19+
# start a dev server with only `dev-console` and `topology` plugins enabled
20+
CONSOLE_PLUGINS=dev-console,topology yarn dev
1821
```
1922

20-
starts webpack dev-server with only DevConsole and OLM plugins included in the build.
21-
2223
Example project structure:
2324

2425
```
@@ -32,8 +33,8 @@ packages/foo-plugin/
3233

3334
## `package.json`
3435

35-
`name` must include the `@console` scope. `version` should be `0.0.0-fixed`. Additional plugin metadata
36-
is declared via the `consolePlugin` object.
36+
`name` must include the `@console` scope. `version` should be `0.0.0-fixed`.
37+
Additional plugin metadata is declared via the [`consolePlugin` object].
3738

3839
```jsonc
3940
{
@@ -42,43 +43,31 @@ is declared via the `consolePlugin` object.
4243
"private": true,
4344
// scripts, dependencies, devDependencies, ...
4445
"consolePlugin": {
45-
"entry": "src/plugin.ts",
4646
"exposedModules": {
4747
"barUtils": "src/utils/bar.ts"
4848
}
4949
}
5050
}
5151
```
5252

53-
Static plugins can provide both static and dynamic extensions. All paths in the `consolePlugin` object
54-
are relative to plugin package root directory and expected to reference actual files (including proper
55-
file extension).
56-
57-
## Static extensions
58-
59-
The `consolePlugin.entry` path in `package.json` file points to the plugin entry module which exports
60-
all of the plugin's static extensions.
53+
Static plugins can provide extensions. All paths in the `consolePlugin` object
54+
are relative to plugin package root directory and expected to reference actual
55+
files (including proper file extension). Barrel files (index files which
56+
re-export other modules) are discouraged and not supported.
6157

62-
The standard way to reference additional code in static extensions is via ES6 module `import` function,
63-
which generates a separate [webpack chunk](https://webpack.js.org/guides/code-splitting/) to be loaded
64-
on demand at runtime.
58+
## Extensions
6559

66-
## Dynamic extensions
67-
68-
Plugin's dynamic extensions are declared via `console-extensions.json` file; see the relevant section in
69-
[Console Dynamic Plugins README](/frontend/packages/console-dynamic-plugin-sdk/README.md) for details.
70-
71-
When loading static plugins during Console startup, the overall list of plugin's extensions is computed
72-
as `[...staticExtensions, ...dynamicExtensions]`.
60+
Plugin's extensions are declared via `console-extensions.json` file; see the
61+
relevant section in [Console Dynamic Plugins README] for details.
7362

7463
## `OWNERS`
7564

76-
The main purpose of `OWNERS` file is to list people responsible for reviewing and approving pull requests
77-
related to the given package or project. It also gives us the ability to add labels to pull requests for
78-
easier categorization.
65+
The main purpose of `OWNERS` file is to list people responsible for reviewing
66+
and approving pull requests related to the given package or project. It also
67+
gives us the ability to add labels to pull requests for easier categorization.
7968

80-
Packages maintained by core Console group (`packages/console-xxx`) usually inherit their reviewer/approver
81-
list from root frontend `OWNERS` file. Packages maintained by other groups (`packages/xxx-plugin`) should
69+
Packages maintained by core Console team usually inherit their reviewer/approver
70+
list from root frontend `OWNERS` file. Packages maintained by other teams should
8271
provide their own list.
8372

8473
```yaml
@@ -92,15 +81,15 @@ labels:
9281
- component/sdk
9382
```
9483
95-
To add new component label in [Prow CI/CD system](https://github.com/kubernetes/test-infra), open a pull
96-
request that modifies
97-
[`core-services/prow/02_config/_labels.yaml`](https://github.com/openshift/release/blob/master/core-services/prow/02_config/_labels.yaml)
98-
in `openshift/release` repository.
84+
To add new component label in [Prow CI/CD system], open a pull request that modifies
85+
[`core-services/prow/02_config/_labels.yaml`] in `openshift/release` repository.
9986

10087
## Build time constraints and specifics
10188

10289
- From webpack perspective, the list of plugins to be included in the build is immutable.
103-
- The core application package (`@console/app`) is a static plugin, loaded before any other plugins.
104-
- Plugin entry modules are loaded during Console startup. To avoid breaking the overall Console UX:
105-
- Additional code should be loaded via the `import` function.
106-
- Side effects, such as CSS imports, should be avoided if possible.
90+
- The core application package (`@console/app`) is a static plugin is always loaded first.
91+
92+
[Console Dynamic Plugins README]: /frontend/packages/console-dynamic-plugin-sdk/README.md
93+
[Prow CI/CD system]: https://github.com/kubernetes/test-infra
94+
[`consolePlugin` object]: /frontend/packages/console-dynamic-plugin-sdk/src/build-types.ts
95+
[`core-services/prow/02_config/_labels.yaml`]: https://github.com/openshift/release/blob/master/core-services/prow/02_config/_labels.yaml

frontend/packages/console-plugin-sdk/src/api/useExtensions.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { useRef, useCallback, useEffect } from 'react';
22
import * as _ from 'lodash';
33
import { useForceRender } from '@console/shared/src/hooks/useForceRender';
44
import { Extension, ExtensionTypeGuard, LoadedExtension } from '../typings';
5-
import useTranslatedExtensions from '../utils/useTranslatedExtensions';
5+
import { useTranslatedExtensions } from '../utils/useTranslatedExtensions';
66
import { subscribeToExtensions } from './pluginSubscriptionService';
77

88
/**

0 commit comments

Comments
 (0)