@equinor/fusion-framework-module-widget 2.0.10 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +82 -70
- package/dist/esm/Widget.js +255 -0
- package/dist/esm/Widget.js.map +1 -0
- package/dist/esm/WidgetModuleConfigurator.js +39 -73
- package/dist/esm/WidgetModuleConfigurator.js.map +1 -1
- package/dist/esm/WidgetModuleProvider.js +85 -17
- package/dist/esm/WidgetModuleProvider.js.map +1 -1
- package/dist/esm/enable-widget-module.js +8 -2
- package/dist/esm/enable-widget-module.js.map +1 -1
- package/dist/esm/errors.js +22 -4
- package/dist/esm/errors.js.map +1 -1
- package/dist/esm/events.js +2 -0
- package/dist/esm/events.js.map +1 -0
- package/dist/esm/index.js +1 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/module.js +5 -2
- package/dist/esm/module.js.map +1 -1
- package/dist/esm/state/actions.js +31 -0
- package/dist/esm/state/actions.js.map +1 -0
- package/dist/esm/state/create-reducer.js +32 -0
- package/dist/esm/state/create-reducer.js.map +1 -0
- package/dist/esm/state/create-state.js +12 -0
- package/dist/esm/state/create-state.js.map +1 -0
- package/dist/esm/state/flows.js +21 -0
- package/dist/esm/state/flows.js.map +1 -0
- package/dist/esm/utils.js +43 -0
- package/dist/esm/utils.js.map +1 -0
- package/dist/esm/version.js +2 -1
- package/dist/esm/version.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types/Widget.d.ts +78 -0
- package/dist/types/WidgetModuleConfigurator.d.ts +27 -27
- package/dist/types/WidgetModuleProvider.d.ts +44 -5
- package/dist/types/enable-widget-module.d.ts +5 -1
- package/dist/types/errors.d.ts +7 -2
- package/dist/types/events.d.ts +54 -0
- package/dist/types/index.d.ts +1 -1
- package/dist/types/module.d.ts +3 -3
- package/dist/types/state/actions.d.ts +92 -0
- package/dist/types/state/create-reducer.d.ts +3 -0
- package/dist/types/state/create-state.d.ts +5 -0
- package/dist/types/state/flows.d.ts +7 -0
- package/dist/types/types.d.ts +81 -5
- package/dist/types/utils.d.ts +5 -0
- package/dist/types/version.d.ts +1 -1
- package/package.json +4 -1
- package/src/Widget.ts +324 -0
- package/src/WidgetModuleConfigurator.ts +48 -118
- package/src/WidgetModuleProvider.ts +110 -22
- package/src/enable-widget-module.ts +2 -2
- package/src/errors.ts +38 -4
- package/src/events.ts +75 -0
- package/src/index.ts +1 -5
- package/src/module.ts +8 -5
- package/src/state/actions.ts +70 -0
- package/src/state/create-reducer.ts +44 -0
- package/src/state/create-state.ts +21 -0
- package/src/state/flows.ts +75 -0
- package/src/types.ts +89 -9
- package/src/utils.ts +51 -0
- package/src/version.ts +1 -1
- package/tsconfig.json +1 -3
- package/dist/esm/WidgetModuleConfigBuilder.js +0 -42
- package/dist/esm/WidgetModuleConfigBuilder.js.map +0 -1
- package/dist/types/WidgetModuleConfigBuilder.d.ts +0 -19
- package/src/WidgetModuleConfigBuilder.ts +0 -70
|
@@ -6,68 +6,156 @@ import { EventModule } from '@equinor/fusion-framework-module-event';
|
|
|
6
6
|
|
|
7
7
|
import { Query } from '@equinor/fusion-query';
|
|
8
8
|
|
|
9
|
-
import type { GetWidgetParameters, WidgetManifest } from './types';
|
|
9
|
+
import type { GetWidgetParameters, WidgetConfig, WidgetManifest } from './types';
|
|
10
10
|
|
|
11
11
|
import { WidgetModuleConfig } from './WidgetModuleConfigurator';
|
|
12
|
-
import {
|
|
12
|
+
import { WidgetManifestLoadError, WidgetConfigLoadError } from './errors';
|
|
13
|
+
import { Widget } from './Widget';
|
|
13
14
|
|
|
14
15
|
export interface IWidgetModuleProvider {
|
|
15
16
|
getWidget(
|
|
16
17
|
widgetKey: GetWidgetParameters['widgetKey'],
|
|
17
|
-
args
|
|
18
|
+
args?: GetWidgetParameters['args'],
|
|
19
|
+
): Widget;
|
|
20
|
+
getWidgetManifest(
|
|
21
|
+
widgetKey: GetWidgetParameters['widgetKey'],
|
|
22
|
+
args?: GetWidgetParameters['args'],
|
|
18
23
|
): Observable<WidgetManifest>;
|
|
24
|
+
getWidgetConfig(
|
|
25
|
+
widgetKey: GetWidgetParameters['widgetKey'],
|
|
26
|
+
args?: GetWidgetParameters['args'],
|
|
27
|
+
): Observable<WidgetConfig>;
|
|
19
28
|
}
|
|
20
29
|
|
|
30
|
+
/**
|
|
31
|
+
* The `WidgetModuleProvider` class implements the `IWidgetModuleProvider` interface and serves as a provider for managing widgets.
|
|
32
|
+
*/
|
|
21
33
|
export class WidgetModuleProvider implements IWidgetModuleProvider {
|
|
22
|
-
|
|
34
|
+
// Private fields
|
|
23
35
|
#subscription = new Subscription();
|
|
36
|
+
#config: WidgetModuleConfig;
|
|
37
|
+
#event?: ModuleType<EventModule>;
|
|
24
38
|
|
|
39
|
+
/**
|
|
40
|
+
* Constructs a new `WidgetModuleProvider` instance.
|
|
41
|
+
* @param args - An object containing configuration and optional event module for the widget provider.
|
|
42
|
+
*/
|
|
25
43
|
constructor(args: { config: WidgetModuleConfig; event?: ModuleType<EventModule> }) {
|
|
26
|
-
const { config } = args;
|
|
27
|
-
|
|
28
|
-
this.#
|
|
44
|
+
const { config, event } = args;
|
|
45
|
+
this.#event = event;
|
|
46
|
+
this.#config = config;
|
|
47
|
+
}
|
|
29
48
|
|
|
30
|
-
|
|
49
|
+
/**
|
|
50
|
+
* Retrieves a widget instance based on the provided name and optional parameters.
|
|
51
|
+
* @param name - The name of the widget.
|
|
52
|
+
* @param widgetParams - Optional parameters for the widget.
|
|
53
|
+
* @returns A new `Widget` instance.
|
|
54
|
+
*/
|
|
55
|
+
public getWidget(name: string, widgetPrams?: GetWidgetParameters['args']): Widget {
|
|
56
|
+
return new Widget(
|
|
57
|
+
{ name },
|
|
58
|
+
{ provider: this, event: this.#event, widgetPrams, config: this.#config },
|
|
59
|
+
);
|
|
31
60
|
}
|
|
32
61
|
|
|
33
|
-
|
|
34
|
-
|
|
62
|
+
/**
|
|
63
|
+
* Retrieves the manifest of a widget as an observable stream.
|
|
64
|
+
* @param name - The name of the widget.
|
|
65
|
+
* @param widgetParams - Optional parameters for the widget.
|
|
66
|
+
* @returns An observable stream of the widget manifest.
|
|
67
|
+
*/
|
|
68
|
+
public getWidgetManifest(
|
|
69
|
+
name: string,
|
|
70
|
+
widgetPrams?: GetWidgetParameters['args'],
|
|
71
|
+
): Observable<WidgetManifest> {
|
|
72
|
+
return this._getWidget(name, widgetPrams);
|
|
35
73
|
}
|
|
36
74
|
|
|
37
|
-
|
|
38
|
-
|
|
75
|
+
/**
|
|
76
|
+
* Retrieves the config of a widget as an observable stream.
|
|
77
|
+
* @param name - The name of the widget.
|
|
78
|
+
* @param widgetParams - Optional parameters for the widget.
|
|
79
|
+
* @returns An observable stream of the widget config.
|
|
80
|
+
*/
|
|
81
|
+
public getWidgetConfig(
|
|
82
|
+
name: string,
|
|
83
|
+
widgetPrams?: GetWidgetParameters['args'],
|
|
84
|
+
): Observable<WidgetConfig> {
|
|
85
|
+
return this._getWidgetConfig(name, widgetPrams);
|
|
39
86
|
}
|
|
40
87
|
|
|
41
|
-
|
|
42
|
-
|
|
88
|
+
protected _getWidgetConfig(
|
|
89
|
+
widgetKey: GetWidgetParameters['widgetKey'],
|
|
90
|
+
args?: GetWidgetParameters['args'],
|
|
91
|
+
): Observable<WidgetConfig> {
|
|
92
|
+
const client = new Query(this.#config.client.getWidgetConfig);
|
|
93
|
+
this.#subscription.add(() => client.complete());
|
|
94
|
+
return Query.extractQueryValue(
|
|
95
|
+
client.query({ widgetKey, args }).pipe(
|
|
96
|
+
catchError((err) => {
|
|
97
|
+
// Extract the cause since the error will be a `QueryError`
|
|
98
|
+
const { cause } = err;
|
|
99
|
+
|
|
100
|
+
// Handle specific errors and throw a `GetWidgetManifestError` if applicable
|
|
101
|
+
if (cause instanceof WidgetManifestLoadError) {
|
|
102
|
+
throw cause;
|
|
103
|
+
}
|
|
104
|
+
if (cause instanceof HttpResponseError) {
|
|
105
|
+
throw WidgetManifestLoadError.fromHttpResponse(cause.response, {
|
|
106
|
+
cause,
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
// Throw a generic `GetWidgetManifestError` for unknown errors
|
|
110
|
+
throw new WidgetManifestLoadError('unknown', 'failed to load config', {
|
|
111
|
+
cause,
|
|
112
|
+
});
|
|
113
|
+
}),
|
|
114
|
+
),
|
|
115
|
+
);
|
|
43
116
|
}
|
|
44
117
|
|
|
45
118
|
/**
|
|
46
|
-
*
|
|
47
|
-
* @param widgetKey -
|
|
48
|
-
* @param
|
|
119
|
+
* Fetches the configuration for a widget using a query.
|
|
120
|
+
* @param widgetKey - The key identifying the widget.
|
|
121
|
+
* @param args - Optional arguments for the widget.
|
|
122
|
+
* @returns An observable stream of the widget manifest.
|
|
123
|
+
* @protected
|
|
49
124
|
*/
|
|
50
125
|
protected _getWidget(
|
|
51
126
|
widgetKey: GetWidgetParameters['widgetKey'],
|
|
52
127
|
args?: GetWidgetParameters['args'],
|
|
53
128
|
): Observable<WidgetManifest> {
|
|
129
|
+
// Create a new query using the configured client
|
|
130
|
+
const client = new Query(this.#config.client.getWidgetManifest);
|
|
131
|
+
this.#subscription.add(() => client.complete());
|
|
132
|
+
|
|
133
|
+
// Execute the query and handle errors
|
|
54
134
|
return Query.extractQueryValue(
|
|
55
|
-
|
|
135
|
+
client.query({ widgetKey, args }).pipe(
|
|
56
136
|
catchError((err) => {
|
|
57
|
-
|
|
137
|
+
// Extract the cause since the error will be a `QueryError`
|
|
58
138
|
const { cause } = err;
|
|
59
|
-
|
|
139
|
+
|
|
140
|
+
// Handle specific errors and throw a `GetWidgetConfigError` if applicable
|
|
141
|
+
if (cause instanceof WidgetConfigLoadError) {
|
|
60
142
|
throw cause;
|
|
61
143
|
}
|
|
62
144
|
if (cause instanceof HttpResponseError) {
|
|
63
|
-
throw
|
|
145
|
+
throw WidgetConfigLoadError.fromHttpResponse(cause.response, { cause });
|
|
64
146
|
}
|
|
65
|
-
|
|
147
|
+
// Throw a generic `GetWidgetManifestError` for unknown errors
|
|
148
|
+
throw new WidgetConfigLoadError('unknown', 'failed to load config', {
|
|
149
|
+
cause,
|
|
150
|
+
});
|
|
66
151
|
}),
|
|
67
152
|
),
|
|
68
153
|
);
|
|
69
154
|
}
|
|
70
155
|
|
|
156
|
+
/**
|
|
157
|
+
* Disposes of the widget provider by unsubscribing from any active subscriptions.
|
|
158
|
+
*/
|
|
71
159
|
public dispose() {
|
|
72
160
|
this.#subscription.unsubscribe();
|
|
73
161
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { IModulesConfigurator } from '@equinor/fusion-framework-module';
|
|
2
|
-
import type { WidgetModuleConfigBuilderCallback } from './WidgetModuleConfigBuilder';
|
|
3
2
|
|
|
4
3
|
import { module } from './module';
|
|
4
|
+
import { WidgetModuleConfigBuilderCallback } from './WidgetModuleConfigurator';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Method for enabling the widget module
|
|
@@ -15,7 +15,7 @@ export const enableWidgetModule = (
|
|
|
15
15
|
configurator.addConfig({
|
|
16
16
|
module,
|
|
17
17
|
configure: (widgetConfigurator) => {
|
|
18
|
-
builder && widgetConfigurator
|
|
18
|
+
builder && builder(widgetConfigurator);
|
|
19
19
|
},
|
|
20
20
|
});
|
|
21
21
|
};
|
package/src/errors.ts
CHANGED
|
@@ -1,18 +1,22 @@
|
|
|
1
1
|
type WidgetErrorType = 'not_found' | 'unauthorized' | 'unknown';
|
|
2
2
|
|
|
3
|
-
export class
|
|
3
|
+
export class WidgetManifestLoadError extends Error {
|
|
4
4
|
static fromHttpResponse(response: Response, options?: ErrorOptions) {
|
|
5
5
|
switch (response.status) {
|
|
6
6
|
case 401:
|
|
7
|
-
return new
|
|
7
|
+
return new WidgetManifestLoadError(
|
|
8
8
|
'unauthorized',
|
|
9
9
|
'failed to load widget manifest, request not authorized',
|
|
10
10
|
options,
|
|
11
11
|
);
|
|
12
12
|
case 404:
|
|
13
|
-
return new
|
|
13
|
+
return new WidgetManifestLoadError(
|
|
14
|
+
'not_found',
|
|
15
|
+
'widget manifest not found',
|
|
16
|
+
options,
|
|
17
|
+
);
|
|
14
18
|
}
|
|
15
|
-
return new
|
|
19
|
+
return new WidgetManifestLoadError(
|
|
16
20
|
'unknown',
|
|
17
21
|
`failed to load widget manifest, status code ${response.status}`,
|
|
18
22
|
options,
|
|
@@ -24,6 +28,35 @@ export class GetWidgetError extends Error {
|
|
|
24
28
|
options?: ErrorOptions,
|
|
25
29
|
) {
|
|
26
30
|
super(message, options);
|
|
31
|
+
this.name = 'GetWidgetLoadManifestErrors';
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export class WidgetConfigLoadError extends Error {
|
|
36
|
+
static fromHttpResponse(response: Response, options?: ErrorOptions) {
|
|
37
|
+
switch (response.status) {
|
|
38
|
+
case 401:
|
|
39
|
+
return new WidgetConfigLoadError(
|
|
40
|
+
'unauthorized',
|
|
41
|
+
'failed to load widget config, request not authorized',
|
|
42
|
+
options,
|
|
43
|
+
);
|
|
44
|
+
case 404:
|
|
45
|
+
return new WidgetConfigLoadError('not_found', 'widget config not found', options);
|
|
46
|
+
}
|
|
47
|
+
return new WidgetConfigLoadError(
|
|
48
|
+
'unknown',
|
|
49
|
+
`failed to load widget config, status code ${response.status}`,
|
|
50
|
+
options,
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
constructor(
|
|
54
|
+
public readonly type: WidgetErrorType,
|
|
55
|
+
message?: string,
|
|
56
|
+
options?: ErrorOptions,
|
|
57
|
+
) {
|
|
58
|
+
super(message, options);
|
|
59
|
+
this.name = 'GetWidgetLoadConfigError';
|
|
27
60
|
}
|
|
28
61
|
}
|
|
29
62
|
|
|
@@ -34,5 +67,6 @@ export class WidgetScriptModuleError extends Error {
|
|
|
34
67
|
options?: ErrorOptions,
|
|
35
68
|
) {
|
|
36
69
|
super(message, options);
|
|
70
|
+
this.name = 'WidgetScriptModuleError';
|
|
37
71
|
}
|
|
38
72
|
}
|
package/src/events.ts
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import type { FrameworkEvent, FrameworkEventInit } from '@equinor/fusion-framework-module-event';
|
|
2
|
+
|
|
3
|
+
import type { Widget } from './Widget';
|
|
4
|
+
|
|
5
|
+
import type {
|
|
6
|
+
WidgetConfig,
|
|
7
|
+
WidgetManifest,
|
|
8
|
+
WidgetModulesInstance,
|
|
9
|
+
WidgetScriptModule,
|
|
10
|
+
} from './types';
|
|
11
|
+
|
|
12
|
+
/** base event type for applications */
|
|
13
|
+
export type WidgetEventInit<TDetail extends Record<string, unknown> | unknown = unknown> =
|
|
14
|
+
FrameworkEventInit<
|
|
15
|
+
/** additional event details and key of target event */
|
|
16
|
+
TDetail & { name: string },
|
|
17
|
+
/** source of the event */
|
|
18
|
+
Widget
|
|
19
|
+
>;
|
|
20
|
+
|
|
21
|
+
export type WidgetEvent<TDetail extends Record<string, unknown> | unknown = unknown> =
|
|
22
|
+
FrameworkEvent<WidgetEventInit<TDetail>>;
|
|
23
|
+
|
|
24
|
+
export type WidgetEventFailure = FrameworkEvent<
|
|
25
|
+
WidgetEventInit<{
|
|
26
|
+
error: WidgetConfig;
|
|
27
|
+
}>
|
|
28
|
+
>;
|
|
29
|
+
|
|
30
|
+
declare module '@equinor/fusion-framework-module-event' {
|
|
31
|
+
interface FrameworkEventMap {
|
|
32
|
+
/** fired when the application has initiated its modules */
|
|
33
|
+
onWidgetModulesLoaded: WidgetEvent<{
|
|
34
|
+
/** initiated modules for application */
|
|
35
|
+
modules: WidgetModulesInstance;
|
|
36
|
+
}>;
|
|
37
|
+
|
|
38
|
+
onWidgetManifestLoad: WidgetEvent;
|
|
39
|
+
/** fired when the application has loaded corresponding manifest */
|
|
40
|
+
onWidgetManifestLoaded: WidgetEvent<{
|
|
41
|
+
manifest: WidgetManifest;
|
|
42
|
+
}>;
|
|
43
|
+
onWidgetManifestFailure: WidgetEventFailure;
|
|
44
|
+
|
|
45
|
+
onWidgetConfigLoad: WidgetEvent;
|
|
46
|
+
/** fired when the application has loaded corresponding config */
|
|
47
|
+
onWidgetConfigLoaded: WidgetEvent<{
|
|
48
|
+
config: WidgetConfig;
|
|
49
|
+
}>;
|
|
50
|
+
onWidgetConfigFailure: WidgetEventFailure;
|
|
51
|
+
|
|
52
|
+
/** fired when the application has loaded corresponding javascript module */
|
|
53
|
+
onAWidgetScriptLoad: WidgetEvent;
|
|
54
|
+
onWidgetScriptLoaded: WidgetEvent<{
|
|
55
|
+
script: WidgetScriptModule;
|
|
56
|
+
}>;
|
|
57
|
+
onWidgetScriptFailure: WidgetEventFailure;
|
|
58
|
+
|
|
59
|
+
/** fired before application loads manifest, config and script */
|
|
60
|
+
onWidgetInitialize: WidgetEvent;
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* fired after application has loaded manifest, config and script
|
|
64
|
+
*
|
|
65
|
+
* __note:__ not fired until all loaders has settled (last emit)
|
|
66
|
+
*/
|
|
67
|
+
onWidgetInitialized: WidgetEvent;
|
|
68
|
+
|
|
69
|
+
/** fired when application fails to load either manifest, config and script */
|
|
70
|
+
onWidgetInitializeFailure: WidgetEventFailure;
|
|
71
|
+
|
|
72
|
+
/** fired when the application is disposed (unmounts) */
|
|
73
|
+
onWidgetDispose: FrameworkEvent<WidgetEventInit>;
|
|
74
|
+
}
|
|
75
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -1,8 +1,4 @@
|
|
|
1
|
-
export {
|
|
2
|
-
WidgetModuleConfigurator,
|
|
3
|
-
IWidgetModuleConfigurator,
|
|
4
|
-
WidgetModuleConfig,
|
|
5
|
-
} from './WidgetModuleConfigurator';
|
|
1
|
+
export { WidgetModuleConfigurator, WidgetModuleConfig } from './WidgetModuleConfigurator';
|
|
6
2
|
|
|
7
3
|
export { WidgetModuleProvider } from './WidgetModuleProvider';
|
|
8
4
|
|
package/src/module.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Module } from '@equinor/fusion-framework-module';
|
|
2
2
|
import { ModuleDeps } from './types';
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import { WidgetModuleConfigurator } from './WidgetModuleConfigurator';
|
|
5
5
|
import { IWidgetModuleProvider, WidgetModuleProvider } from './WidgetModuleProvider';
|
|
6
6
|
|
|
7
7
|
export const moduleKey = 'widget';
|
|
@@ -9,15 +9,18 @@ export const moduleKey = 'widget';
|
|
|
9
9
|
export type WidgetModule = Module<
|
|
10
10
|
typeof moduleKey,
|
|
11
11
|
IWidgetModuleProvider,
|
|
12
|
-
|
|
12
|
+
WidgetModuleConfigurator,
|
|
13
13
|
ModuleDeps
|
|
14
14
|
>;
|
|
15
15
|
|
|
16
16
|
export const module: WidgetModule = {
|
|
17
17
|
name: moduleKey,
|
|
18
|
-
configure
|
|
18
|
+
configure() {
|
|
19
|
+
const config = new WidgetModuleConfigurator();
|
|
20
|
+
return config;
|
|
21
|
+
},
|
|
19
22
|
initialize: async (args) => {
|
|
20
|
-
const config = await
|
|
23
|
+
const config = await args.config.createConfigAsync(args);
|
|
21
24
|
const event = await args.requireInstance('event').catch(() => undefined);
|
|
22
25
|
return new WidgetModuleProvider({ config, event });
|
|
23
26
|
},
|
|
@@ -30,6 +33,6 @@ export default module;
|
|
|
30
33
|
|
|
31
34
|
declare module '@equinor/fusion-framework-module' {
|
|
32
35
|
interface Modules {
|
|
33
|
-
|
|
36
|
+
[moduleKey]: WidgetModule;
|
|
34
37
|
}
|
|
35
38
|
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ActionInstanceMap,
|
|
3
|
+
ActionTypes,
|
|
4
|
+
createAction,
|
|
5
|
+
createAsyncAction,
|
|
6
|
+
} from '@equinor/fusion-observable';
|
|
7
|
+
import {
|
|
8
|
+
GetWidgetParameters,
|
|
9
|
+
WidgetConfig,
|
|
10
|
+
WidgetManifest,
|
|
11
|
+
WidgetModulesInstance,
|
|
12
|
+
WidgetScriptModule,
|
|
13
|
+
} from '../types';
|
|
14
|
+
|
|
15
|
+
const createActions = () => ({
|
|
16
|
+
/** Manifest loading */
|
|
17
|
+
setManifest: createAction('set_manifest', (manifest: WidgetManifest, update?: boolean) => ({
|
|
18
|
+
payload: manifest,
|
|
19
|
+
meta: {
|
|
20
|
+
created: Date.now(),
|
|
21
|
+
update,
|
|
22
|
+
},
|
|
23
|
+
})),
|
|
24
|
+
fetchManifest: createAsyncAction(
|
|
25
|
+
'fetch_manifest',
|
|
26
|
+
(payload: { key: string; args?: GetWidgetParameters['args'] }, update?: boolean) => ({
|
|
27
|
+
payload,
|
|
28
|
+
meta: { update },
|
|
29
|
+
}),
|
|
30
|
+
(manifest: WidgetManifest) => ({ payload: manifest }),
|
|
31
|
+
(error: unknown) => ({ payload: error }),
|
|
32
|
+
),
|
|
33
|
+
/** Config loading */
|
|
34
|
+
setConfig: createAction('set_config', (config: WidgetConfig) => ({ payload: config })),
|
|
35
|
+
fetchConfig: createAsyncAction(
|
|
36
|
+
'fetch_config',
|
|
37
|
+
(payload: { key: string; args?: GetWidgetParameters['args'] }, update?: boolean) => ({
|
|
38
|
+
payload,
|
|
39
|
+
meta: { update },
|
|
40
|
+
}),
|
|
41
|
+
(config: WidgetConfig) => ({ payload: config }),
|
|
42
|
+
(error: unknown) => ({ payload: error }),
|
|
43
|
+
),
|
|
44
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
45
|
+
setModule: createAction('set_module', (module: any) => ({ payload: module })),
|
|
46
|
+
importWidget: createAsyncAction(
|
|
47
|
+
'import_widget',
|
|
48
|
+
(entrypoint: string) => ({ payload: entrypoint }),
|
|
49
|
+
(module: WidgetScriptModule) => ({ payload: module }),
|
|
50
|
+
(error: unknown) => ({ payload: error }),
|
|
51
|
+
),
|
|
52
|
+
// widget Instance
|
|
53
|
+
setInstance: createAction('set_instance', (instance: WidgetModulesInstance) => ({
|
|
54
|
+
payload: instance,
|
|
55
|
+
})),
|
|
56
|
+
initialize: createAsyncAction(
|
|
57
|
+
'initialize_widget',
|
|
58
|
+
() => ({ payload: null }),
|
|
59
|
+
() => ({ payload: null }),
|
|
60
|
+
(error: unknown) => ({ payload: error }),
|
|
61
|
+
),
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
export const actions = createActions();
|
|
65
|
+
|
|
66
|
+
export type ActionBuilder = ReturnType<typeof createActions>;
|
|
67
|
+
|
|
68
|
+
export type ActionMap = ActionInstanceMap<ActionBuilder>;
|
|
69
|
+
|
|
70
|
+
export type Actions = ActionTypes<typeof actions>;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import {
|
|
2
|
+
actionBaseType,
|
|
3
|
+
createReducer as makeReducer,
|
|
4
|
+
isCompleteAction,
|
|
5
|
+
isRequestAction,
|
|
6
|
+
} from '@equinor/fusion-observable';
|
|
7
|
+
|
|
8
|
+
import { enableMapSet } from 'immer';
|
|
9
|
+
|
|
10
|
+
enableMapSet();
|
|
11
|
+
|
|
12
|
+
import { actions } from './actions';
|
|
13
|
+
import { WidgetStateInitial, WidgetState } from '../types';
|
|
14
|
+
|
|
15
|
+
export const createReducer = (value: WidgetStateInitial) =>
|
|
16
|
+
makeReducer({ ...value, status: new Set() } as WidgetState, (builder) =>
|
|
17
|
+
builder
|
|
18
|
+
.addCase(actions.setManifest, (state, action) => {
|
|
19
|
+
if (action.meta.update) {
|
|
20
|
+
state.manifest = { ...state.manifest, ...action.payload };
|
|
21
|
+
} else {
|
|
22
|
+
state.manifest = action.payload;
|
|
23
|
+
}
|
|
24
|
+
})
|
|
25
|
+
.addCase(actions.setConfig, (state, action) => {
|
|
26
|
+
state.config = action.payload;
|
|
27
|
+
})
|
|
28
|
+
.addCase(actions.setModule, (state, action) => {
|
|
29
|
+
state.modules = action.payload;
|
|
30
|
+
})
|
|
31
|
+
.addCase(actions.setInstance, (state, action) => {
|
|
32
|
+
state.instance = action.payload;
|
|
33
|
+
})
|
|
34
|
+
/** mark status as loading {{type}} */
|
|
35
|
+
.addMatcher(isRequestAction, (state, action) => {
|
|
36
|
+
state.status.add(actionBaseType(action));
|
|
37
|
+
})
|
|
38
|
+
/** clear status {{type}} */
|
|
39
|
+
.addMatcher(isCompleteAction, (state, action) => {
|
|
40
|
+
state.status.delete(actionBaseType(action));
|
|
41
|
+
}),
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
export default createReducer;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { FlowSubject } from '@equinor/fusion-observable';
|
|
2
|
+
|
|
3
|
+
import { createReducer } from './create-reducer';
|
|
4
|
+
|
|
5
|
+
import { handleFetchManifest, handleImportWidget, handleFetchConfig } from './flows';
|
|
6
|
+
|
|
7
|
+
import type { Actions } from './actions';
|
|
8
|
+
import { WidgetState, WidgetStateInitial } from '../types';
|
|
9
|
+
import WidgetModuleProvider from '../WidgetModuleProvider';
|
|
10
|
+
|
|
11
|
+
export const createState = (
|
|
12
|
+
value: WidgetStateInitial,
|
|
13
|
+
provider: WidgetModuleProvider,
|
|
14
|
+
): FlowSubject<WidgetState, Actions> => {
|
|
15
|
+
const reducer = createReducer(value);
|
|
16
|
+
const state = new FlowSubject<WidgetState, Actions>(reducer);
|
|
17
|
+
state.addFlow(handleFetchManifest(provider));
|
|
18
|
+
state.addFlow(handleImportWidget());
|
|
19
|
+
state.addFlow(handleFetchConfig(provider));
|
|
20
|
+
return state;
|
|
21
|
+
};
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { from, of, concat } from 'rxjs';
|
|
2
|
+
import { catchError, filter, last, map, share, switchMap } from 'rxjs/operators';
|
|
3
|
+
|
|
4
|
+
import { actions } from './actions';
|
|
5
|
+
|
|
6
|
+
import type { Flow } from '@equinor/fusion-observable';
|
|
7
|
+
|
|
8
|
+
import type { Actions } from './actions';
|
|
9
|
+
import { WidgetState } from '../types';
|
|
10
|
+
import type WidgetModuleProvider from '../WidgetModuleProvider';
|
|
11
|
+
|
|
12
|
+
export const handleFetchManifest =
|
|
13
|
+
(provider: WidgetModuleProvider): Flow<Actions, WidgetState> =>
|
|
14
|
+
(action$) =>
|
|
15
|
+
action$.pipe(
|
|
16
|
+
filter(actions.fetchManifest.match),
|
|
17
|
+
switchMap((action) => {
|
|
18
|
+
const {
|
|
19
|
+
payload: { key, args },
|
|
20
|
+
meta: { update },
|
|
21
|
+
} = action;
|
|
22
|
+
|
|
23
|
+
const subject = from(provider.getWidgetManifest(key, args)).pipe(
|
|
24
|
+
filter((x) => !!x),
|
|
25
|
+
share(),
|
|
26
|
+
);
|
|
27
|
+
return concat(
|
|
28
|
+
subject.pipe(map((manifest) => actions.setManifest(manifest, update))),
|
|
29
|
+
subject.pipe(
|
|
30
|
+
last(),
|
|
31
|
+
map((manifest) => actions.fetchManifest.success(manifest)),
|
|
32
|
+
),
|
|
33
|
+
).pipe(
|
|
34
|
+
catchError((err) => {
|
|
35
|
+
console.log(err, action.payload);
|
|
36
|
+
return of(actions.fetchManifest.failure(err));
|
|
37
|
+
}),
|
|
38
|
+
);
|
|
39
|
+
}),
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
export const handleFetchConfig =
|
|
43
|
+
(provider: WidgetModuleProvider): Flow<Actions, WidgetState> =>
|
|
44
|
+
(action$) =>
|
|
45
|
+
action$.pipe(
|
|
46
|
+
filter(actions.fetchConfig.match),
|
|
47
|
+
switchMap(({ payload: { key, args } }) => {
|
|
48
|
+
const subject = from(provider.getWidgetConfig(key, args)).pipe(
|
|
49
|
+
filter((x) => !!x),
|
|
50
|
+
share(),
|
|
51
|
+
);
|
|
52
|
+
return concat(
|
|
53
|
+
subject.pipe(map((manifest) => actions.setConfig(manifest))),
|
|
54
|
+
subject.pipe(
|
|
55
|
+
last(),
|
|
56
|
+
map((manifest) => actions.fetchConfig.success(manifest)),
|
|
57
|
+
),
|
|
58
|
+
).pipe(
|
|
59
|
+
catchError((err) => {
|
|
60
|
+
return of(actions.fetchConfig.failure(err));
|
|
61
|
+
}),
|
|
62
|
+
);
|
|
63
|
+
}),
|
|
64
|
+
);
|
|
65
|
+
|
|
66
|
+
export const handleImportWidget = (): Flow<Actions, WidgetState> => (action$) =>
|
|
67
|
+
action$.pipe(
|
|
68
|
+
filter(actions.importWidget.match),
|
|
69
|
+
switchMap(({ payload }) => {
|
|
70
|
+
return from(import(/* @vite-ignore */ payload)).pipe(
|
|
71
|
+
map(actions.importWidget.success),
|
|
72
|
+
catchError((err) => of(actions.importWidget.failure(err))),
|
|
73
|
+
);
|
|
74
|
+
}),
|
|
75
|
+
);
|