@gooddata/sdk-ui-ext 11.53.0-alpha.1 → 11.53.0-alpha.2
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/esm/insightView/InsightRenderer.d.ts +3 -6
- package/esm/insightView/InsightRenderer.d.ts.map +1 -1
- package/esm/insightView/InsightRenderer.js +193 -143
- package/esm/internal/components/BaseVisualization.d.ts +6 -33
- package/esm/internal/components/BaseVisualization.d.ts.map +1 -1
- package/esm/internal/components/BaseVisualization.js +255 -213
- package/esm/internal/index.d.ts +1 -1
- package/esm/internal/index.d.ts.map +1 -1
- package/esm/internal/index.js +1 -1
- package/package.json +21 -21
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { type WrappedComponentProps } from "react-intl";
|
|
2
1
|
import { type IUserWorkspaceSettings } from "@gooddata/sdk-backend-spi";
|
|
3
2
|
import { type IColorPalette, type IInsightDefinition, type IInsightWidget, type ITheme, type IWorkspacePermissions } from "@gooddata/sdk-model";
|
|
4
3
|
import { type ILocale, type ITranslations, type OnError } from "@gooddata/sdk-ui";
|
|
@@ -21,17 +20,15 @@ export interface IInsightRendererProps extends Omit<IInsightViewProps, "insight"
|
|
|
21
20
|
*/
|
|
22
21
|
widget?: IInsightWidget;
|
|
23
22
|
}
|
|
24
|
-
|
|
23
|
+
type InsightRendererCoreProps = IInsightRendererProps & {
|
|
25
24
|
messages: ITranslations;
|
|
26
|
-
}, "theme" | "themeIsLoading" | "themeStatus">>> & {
|
|
27
|
-
WrappedComponent: import("react").ComponentType<Omit<IInsightRendererProps & WrappedComponentProps & {
|
|
28
|
-
messages: ITranslations;
|
|
29
|
-
}, "theme" | "themeIsLoading" | "themeStatus">>;
|
|
30
25
|
};
|
|
26
|
+
export declare const IntlInsightRenderer: import("react").ComponentType<InsightRendererCoreProps>;
|
|
31
27
|
/**
|
|
32
28
|
* Renders insight passed as a parameter.
|
|
33
29
|
*
|
|
34
30
|
* @internal
|
|
35
31
|
*/
|
|
36
32
|
export declare function InsightRenderer(props: IInsightRendererProps): import("react/jsx-runtime").JSX.Element | null;
|
|
33
|
+
export {};
|
|
37
34
|
//# sourceMappingURL=InsightRenderer.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InsightRenderer.d.ts","sourceRoot":"","sources":["../../src/insightView/InsightRenderer.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"InsightRenderer.d.ts","sourceRoot":"","sources":["../../src/insightView/InsightRenderer.tsx"],"names":[],"mappings":"AAYA,OAAO,EAGH,KAAK,sBAAsB,EAC9B,MAAM,2BAA2B,CAAC;AACnC,OAAO,EACH,KAAK,aAAa,EAClB,KAAK,kBAAkB,EACvB,KAAK,cAAc,EACnB,KAAK,MAAM,EACX,KAAK,qBAAqB,EAM7B,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAKH,KAAK,OAAO,EACZ,KAAK,aAAa,EAGlB,KAAK,OAAO,EAMf,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EAGH,KAAK,iBAAiB,EAKzB,MAAM,sBAAsB,CAAC;AAE9B;;GAEG;AACH,MAAM,WAAW,qBAAsB,SAAQ,IAAI,CAC/C,iBAAiB,EACjB,SAAS,GAAG,gBAAgB,GAAG,iBAAiB,GAAG,WAAW,CACjE;IACG,OAAO,EAAE,kBAAkB,GAAG,SAAS,CAAC;IACxC,MAAM,EAAE,OAAO,CAAC;IAChB,QAAQ,EAAE,sBAAsB,GAAG,SAAS,CAAC;IAC7C,WAAW,CAAC,EAAE,qBAAqB,CAAC;IACpC,YAAY,EAAE,aAAa,GAAG,SAAS,CAAC;IACxC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC;IACzB;;;OAGG;IACH,MAAM,CAAC,EAAE,cAAc,CAAC;CAC3B;AAED,KAAK,wBAAwB,GAAG,qBAAqB,GAAG;IAAE,QAAQ,EAAE,aAAa,CAAA;CAAE,CAAC;AAuXpF,eAAO,MAAM,mBAAmB,yDAAoC,CAAC;AAwBrE;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,qBAAqB,kDAuC3D"}
|
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
// (C) 2020-2026 GoodData Corporation
|
|
3
|
-
import {
|
|
3
|
+
import { memo, useCallback, useEffect, useLayoutEffect, useRef, useState } from "react";
|
|
4
4
|
import { isEqual } from "lodash-es";
|
|
5
5
|
import { createRoot } from "react-dom/client";
|
|
6
|
-
import { injectIntl } from "react-intl";
|
|
7
6
|
import { v4 as uuidv4 } from "uuid";
|
|
8
7
|
import { ExecutionFactoryUpgradingToExecByReference, ExecutionFactoryWithFixedFilters, } from "@gooddata/sdk-backend-base";
|
|
9
8
|
import { insightProperties, insightSetProperties, insightTitle, insightVisualizationType, insightVisualizationUrl, } from "@gooddata/sdk-model";
|
|
10
9
|
import { DefaultLocale, ErrorComponent, IntlWrapper, LoadingComponent, fillMissingFormats, fillMissingTitlesWithMessages, ignoreTitlesForSimpleMeasures, useResolveMessages, withContexts, } from "@gooddata/sdk-ui";
|
|
11
|
-
import {
|
|
10
|
+
import { useTheme } from "@gooddata/sdk-ui-theme-provider";
|
|
12
11
|
import { DEFAULT_MESSAGES, FullVisualizationCatalog, resolveMessages, } from "../internal/index.js";
|
|
13
12
|
const getElementId = () => `gd-vis-${uuidv4()}`;
|
|
14
13
|
const visualizationUriRootStyle = {
|
|
@@ -17,58 +16,102 @@ const visualizationUriRootStyle = {
|
|
|
17
16
|
flex: "1 1 auto",
|
|
18
17
|
flexDirection: "column",
|
|
19
18
|
};
|
|
20
|
-
|
|
19
|
+
const noop = () => { };
|
|
20
|
+
const defaultFilters = [];
|
|
21
|
+
const defaultDrillableItems = [];
|
|
22
|
+
/**
|
|
23
|
+
* Applies the defaults on the props. The values used as defaults are referentially stable so that they do not
|
|
24
|
+
* trigger any unnecessary work down the line.
|
|
25
|
+
*/
|
|
26
|
+
const resolveProps = (props) => ({
|
|
27
|
+
...props,
|
|
28
|
+
ErrorComponent: props.ErrorComponent ?? ErrorComponent,
|
|
29
|
+
filters: props.filters ?? defaultFilters,
|
|
30
|
+
drillableItems: props.drillableItems ?? defaultDrillableItems,
|
|
31
|
+
LoadingComponent: props.LoadingComponent ?? LoadingComponent,
|
|
32
|
+
pushData: props.pushData ?? noop,
|
|
33
|
+
locale: props.locale ?? DefaultLocale,
|
|
34
|
+
afterRender: props.afterRender ?? noop,
|
|
35
|
+
});
|
|
36
|
+
// this needs to be a memoized component as it can happen that this might be rendered multiple times
|
|
21
37
|
// with the same props (referentially) - this might make the rendered visualization behave unpredictably
|
|
22
38
|
// and is bad for performance so we need to make sure the re-renders are performed only if necessary
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
39
|
+
const InsightRendererCore = memo(function InsightRendererCore(props) {
|
|
40
|
+
const theme = useTheme();
|
|
41
|
+
const currentProps = { ...resolveProps(props), theme };
|
|
42
|
+
const [elementId] = useState(getElementId);
|
|
43
|
+
const visualizationRef = useRef(undefined);
|
|
44
|
+
const containerRef = useRef(null);
|
|
27
45
|
/**
|
|
28
46
|
* The component may render both visualization and config panel. In React18 we therefore need two
|
|
29
47
|
* roots with their respective render methods. This Map holds the roots for both and provides
|
|
30
48
|
* render and unmount methods whenever needed.
|
|
31
49
|
*/
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
50
|
+
const reactRootsMapRef = useRef(new Map());
|
|
51
|
+
/**
|
|
52
|
+
* Whether the effects are currently torn down. Used to tell a real unmount apart from a teardown that is
|
|
53
|
+
* immediately followed by a new setup of the same component instance.
|
|
54
|
+
*/
|
|
55
|
+
const isUnmountedRef = useRef(false);
|
|
56
|
+
/**
|
|
57
|
+
* The callbacks and element getters below outlive the render they were created in (the visualization
|
|
58
|
+
* instance only ever gets the ones from the render it was set up in). They therefore read the props from
|
|
59
|
+
* this ref to always see the current values - the very same way `this.props` did before.
|
|
60
|
+
*
|
|
61
|
+
* This effect must stay first so that the ref is up to date before any other effect runs. It is a layout
|
|
62
|
+
* effect so that it keeps the pre-paint semantics the class lifecycle methods had.
|
|
63
|
+
*/
|
|
64
|
+
const propsRef = useRef(currentProps);
|
|
65
|
+
useLayoutEffect(() => {
|
|
66
|
+
propsRef.current = currentProps;
|
|
67
|
+
});
|
|
68
|
+
const unmountVisualization = useCallback(() => {
|
|
69
|
+
if (visualizationRef.current) {
|
|
70
|
+
visualizationRef.current.unmount();
|
|
45
71
|
}
|
|
46
|
-
|
|
47
|
-
};
|
|
48
|
-
|
|
72
|
+
visualizationRef.current = undefined;
|
|
73
|
+
}, []);
|
|
74
|
+
const getExecutionFactory = useCallback(() => {
|
|
75
|
+
const { backend, workspace, executeByReference, filters } = propsRef.current;
|
|
76
|
+
const factory = backend.workspace(workspace).execution();
|
|
77
|
+
if (executeByReference) {
|
|
78
|
+
/*
|
|
79
|
+
* When executing by reference, decorate the original execution factory so that it
|
|
80
|
+
* transparently routes `forInsight` to `forInsightByRef` AND adds the filters
|
|
81
|
+
* from InsightView props.
|
|
82
|
+
*
|
|
83
|
+
* Code will pass this factory over to the pluggable visualizations - they will do execution
|
|
84
|
+
* `forInsight` and under the covers things will be routed and done differently without the
|
|
85
|
+
* plug viz knowing.
|
|
86
|
+
*/
|
|
87
|
+
return new ExecutionFactoryUpgradingToExecByReference(new ExecutionFactoryWithFixedFilters(factory, filters));
|
|
88
|
+
}
|
|
89
|
+
return factory;
|
|
90
|
+
}, []);
|
|
91
|
+
const updateVisualization = useCallback(() => {
|
|
49
92
|
// if the container no longer exists, update was called after unmount -> do nothing
|
|
50
|
-
if (!
|
|
93
|
+
if (!visualizationRef.current || !containerRef.current) {
|
|
51
94
|
return;
|
|
52
95
|
}
|
|
96
|
+
const { insight: insightProp, config = {}, settings, locale, messages, widget, drillableItems, colorPalette, execConfig, theme, } = propsRef.current;
|
|
53
97
|
// if there is no insight, bail early
|
|
54
|
-
if (!
|
|
98
|
+
if (!insightProp) {
|
|
55
99
|
return;
|
|
56
100
|
}
|
|
57
|
-
const {
|
|
58
|
-
const { responsiveUiDateFormat } = this.props.settings ?? {};
|
|
101
|
+
const { responsiveUiDateFormat } = settings ?? {};
|
|
59
102
|
const visProps = {
|
|
60
|
-
locale
|
|
61
|
-
messages
|
|
103
|
+
locale,
|
|
104
|
+
messages,
|
|
62
105
|
dateFormat: responsiveUiDateFormat,
|
|
63
|
-
a11yTitle:
|
|
64
|
-
a11yDescription:
|
|
106
|
+
a11yTitle: widget?.title,
|
|
107
|
+
a11yDescription: widget?.description,
|
|
65
108
|
custom: {
|
|
66
|
-
drillableItems
|
|
67
|
-
lastSavedVisClassUrl: insightVisualizationUrl(
|
|
109
|
+
drillableItems,
|
|
110
|
+
lastSavedVisClassUrl: insightVisualizationUrl(insightProp),
|
|
68
111
|
},
|
|
69
112
|
config: {
|
|
70
113
|
separators: config.separators,
|
|
71
|
-
colorPalette
|
|
114
|
+
colorPalette,
|
|
72
115
|
mapboxToken: config.mapboxToken,
|
|
73
116
|
agGridToken: config.agGridToken,
|
|
74
117
|
forceDisableDrillOnAxes: config.forceDisableDrillOnAxes,
|
|
@@ -76,13 +119,13 @@ class InsightRendererCore extends PureComponent {
|
|
|
76
119
|
isExportMode: config.isExportMode,
|
|
77
120
|
enableExecutionCancelling: config.enableExecutionCancelling,
|
|
78
121
|
},
|
|
79
|
-
executionConfig:
|
|
122
|
+
executionConfig: execConfig,
|
|
80
123
|
customVisualizationConfig: config,
|
|
81
|
-
theme
|
|
124
|
+
theme,
|
|
82
125
|
supportsChartFill: config.supportsChartFill,
|
|
83
126
|
};
|
|
84
|
-
const visClass = insightVisualizationType(
|
|
85
|
-
const filled = fillMissingTitlesWithMessages(
|
|
127
|
+
const visClass = insightVisualizationType(insightProp);
|
|
128
|
+
const filled = fillMissingTitlesWithMessages(insightProp, locale, messages, undefined);
|
|
86
129
|
let insight = fillMissingFormats(filled);
|
|
87
130
|
/**
|
|
88
131
|
* Ignore titles for simple measures in all visualizations except for repeater.
|
|
@@ -95,29 +138,60 @@ class InsightRendererCore extends PureComponent {
|
|
|
95
138
|
if (visClass !== "repeater") {
|
|
96
139
|
insight = ignoreTitlesForSimpleMeasures(insight);
|
|
97
140
|
}
|
|
98
|
-
|
|
99
|
-
};
|
|
100
|
-
|
|
141
|
+
visualizationRef.current?.update(visProps, insight, {}, getExecutionFactory());
|
|
142
|
+
}, [getExecutionFactory]);
|
|
143
|
+
const reactRenderFunction = useCallback((children, element) => {
|
|
144
|
+
if (!element) {
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
const htmlElement = element;
|
|
148
|
+
if (!reactRootsMapRef.current.get(htmlElement)) {
|
|
149
|
+
reactRootsMapRef.current.set(htmlElement, createRoot(htmlElement));
|
|
150
|
+
}
|
|
151
|
+
reactRootsMapRef.current.get(htmlElement).render(children);
|
|
152
|
+
}, []);
|
|
153
|
+
const reactUnmountFunction = useCallback(() => {
|
|
154
|
+
reactRootsMapRef.current.forEach((root) => root.render(null));
|
|
155
|
+
}, []);
|
|
156
|
+
const onExportReadyDecorator = useCallback((exportFunction) => {
|
|
157
|
+
const { onExportReady } = propsRef.current;
|
|
158
|
+
if (!onExportReady) {
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
const decorator = (exportConfig) => {
|
|
162
|
+
const { insight } = propsRef.current;
|
|
163
|
+
if (exportConfig.title || !insight) {
|
|
164
|
+
return exportFunction(exportConfig);
|
|
165
|
+
}
|
|
166
|
+
return exportFunction({
|
|
167
|
+
...exportConfig,
|
|
168
|
+
title: insightTitle(insight),
|
|
169
|
+
});
|
|
170
|
+
};
|
|
171
|
+
onExportReady(decorator);
|
|
172
|
+
}, []);
|
|
173
|
+
const setupVisualization = useCallback(() => {
|
|
174
|
+
const { insight, settings, backend, workspace, permissions, locale, messages, pushData, onDrill, onDataView, onLoadingChanged, afterRender, } = propsRef.current;
|
|
101
175
|
// if there is no insight, bail early
|
|
102
|
-
if (!
|
|
176
|
+
if (!insight) {
|
|
103
177
|
return;
|
|
104
178
|
}
|
|
105
179
|
// the visualization we may have from earlier is no longer valid -> get rid of it
|
|
106
|
-
|
|
107
|
-
const visualizationFactory = FullVisualizationCatalog.forInsight(
|
|
108
|
-
|
|
109
|
-
backend:
|
|
180
|
+
unmountVisualization();
|
|
181
|
+
const visualizationFactory = FullVisualizationCatalog.forInsight(insight, settings?.enableNewPivotTable ?? true, settings?.enableNewGeoPushpin ?? false).getFactory();
|
|
182
|
+
visualizationRef.current = visualizationFactory({
|
|
183
|
+
backend: backend,
|
|
110
184
|
callbacks: {
|
|
111
185
|
onError: (error) => {
|
|
112
|
-
|
|
113
|
-
|
|
186
|
+
propsRef.current.onError?.(error);
|
|
187
|
+
propsRef.current.onLoadingChanged?.({ isLoading: false });
|
|
114
188
|
},
|
|
115
|
-
onLoadingChanged
|
|
116
|
-
pushData
|
|
117
|
-
onDrill
|
|
118
|
-
onDataView
|
|
119
|
-
onExportReady:
|
|
120
|
-
afterRender
|
|
189
|
+
onLoadingChanged,
|
|
190
|
+
pushData,
|
|
191
|
+
onDrill,
|
|
192
|
+
onDataView,
|
|
193
|
+
onExportReady: onExportReadyDecorator,
|
|
194
|
+
afterRender,
|
|
121
195
|
},
|
|
122
196
|
// This renderer has no configuration panel of its own — it renders read-only insights.
|
|
123
197
|
// It used to resolve the panel with a document-wide lookup of the well-known
|
|
@@ -130,107 +204,83 @@ class InsightRendererCore extends PureComponent {
|
|
|
130
204
|
// fix STL-3184
|
|
131
205
|
configPanelElement: () => null,
|
|
132
206
|
element: () => {
|
|
133
|
-
const rootNode =
|
|
134
|
-
return rootNode.querySelector(`#${
|
|
207
|
+
const rootNode = containerRef.current?.getRootNode() ?? document;
|
|
208
|
+
return rootNode.querySelector(`#${elementId}`);
|
|
135
209
|
},
|
|
136
210
|
environment: "dashboards", // TODO get rid of this
|
|
137
|
-
locale
|
|
138
|
-
messages
|
|
139
|
-
projectId:
|
|
140
|
-
visualizationProperties: insightProperties(
|
|
141
|
-
featureFlags:
|
|
142
|
-
permissions
|
|
143
|
-
renderFun:
|
|
144
|
-
unmountFun:
|
|
211
|
+
locale,
|
|
212
|
+
messages,
|
|
213
|
+
projectId: workspace,
|
|
214
|
+
visualizationProperties: insightProperties(insight),
|
|
215
|
+
featureFlags: settings,
|
|
216
|
+
permissions,
|
|
217
|
+
renderFun: reactRenderFunction,
|
|
218
|
+
unmountFun: reactUnmountFunction,
|
|
145
219
|
});
|
|
146
|
-
};
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
};
|
|
158
|
-
};
|
|
159
|
-
getReactUnmountFunction = () => {
|
|
160
|
-
return () => this.reactRootsMap.forEach((root) => root.render(null));
|
|
161
|
-
};
|
|
162
|
-
onExportReadyDecorator = (exportFunction) => {
|
|
163
|
-
if (!this.props.onExportReady) {
|
|
220
|
+
}, [elementId, onExportReadyDecorator, reactRenderFunction, reactUnmountFunction, unmountVisualization]);
|
|
221
|
+
const prevPropsRef = useRef(undefined);
|
|
222
|
+
// componentDidMount & componentDidUpdate: intentionally without dependencies so that it runs after
|
|
223
|
+
// every render of this (memoized) component. A layout effect so that it keeps running before paint,
|
|
224
|
+
// the very same way the class lifecycle methods did.
|
|
225
|
+
useLayoutEffect(() => {
|
|
226
|
+
const prevProps = prevPropsRef.current;
|
|
227
|
+
prevPropsRef.current = currentProps;
|
|
228
|
+
if (!prevProps) {
|
|
229
|
+
setupVisualization();
|
|
230
|
+
updateVisualization();
|
|
164
231
|
return;
|
|
165
232
|
}
|
|
166
|
-
const decorator = (exportConfig) => {
|
|
167
|
-
if (exportConfig.title || !this.props.insight) {
|
|
168
|
-
return exportFunction(exportConfig);
|
|
169
|
-
}
|
|
170
|
-
return exportFunction({
|
|
171
|
-
...exportConfig,
|
|
172
|
-
title: insightTitle(this.props.insight),
|
|
173
|
-
});
|
|
174
|
-
};
|
|
175
|
-
this.props.onExportReady(decorator);
|
|
176
|
-
};
|
|
177
|
-
getExecutionFactory = () => {
|
|
178
|
-
const factory = this.props.backend.workspace(this.props.workspace).execution();
|
|
179
|
-
if (this.props.executeByReference) {
|
|
180
|
-
/*
|
|
181
|
-
* When executing by reference, decorate the original execution factory so that it
|
|
182
|
-
* transparently routes `forInsight` to `forInsightByRef` AND adds the filters
|
|
183
|
-
* from InsightView props.
|
|
184
|
-
*
|
|
185
|
-
* Code will pass this factory over to the pluggable visualizations - they will do execution
|
|
186
|
-
* `forInsight` and under the covers things will be routed and done differently without the
|
|
187
|
-
* plug viz knowing.
|
|
188
|
-
*/
|
|
189
|
-
return new ExecutionFactoryUpgradingToExecByReference(new ExecutionFactoryWithFixedFilters(factory, this.props.filters));
|
|
190
|
-
}
|
|
191
|
-
return factory;
|
|
192
|
-
};
|
|
193
|
-
componentDidMountInner = () => {
|
|
194
|
-
this.setupVisualization();
|
|
195
|
-
return this.updateVisualization();
|
|
196
|
-
};
|
|
197
|
-
componentDidMount() {
|
|
198
|
-
this.componentDidMountInner();
|
|
199
|
-
}
|
|
200
|
-
componentDidUpdateInner = (prevProps) => {
|
|
201
233
|
/**
|
|
202
234
|
* Ignore properties when comparing insights to determine if a new setup is needed: changes to properties
|
|
203
235
|
* only will be handled using the updateVisualization without unnecessary new setup just fine.
|
|
204
236
|
*/
|
|
205
237
|
const prevInsightForCompare = prevProps.insight && insightSetProperties(prevProps.insight, {});
|
|
206
|
-
const newInsightForCompare =
|
|
238
|
+
const newInsightForCompare = currentProps.insight && insightSetProperties(currentProps.insight, {});
|
|
207
239
|
const needsNewSetup = !isEqual(newInsightForCompare, prevInsightForCompare) ||
|
|
208
|
-
!isEqual(
|
|
209
|
-
!isEqual(
|
|
210
|
-
|
|
240
|
+
!isEqual(currentProps.filters, prevProps.filters) ||
|
|
241
|
+
!isEqual(currentProps.settings, prevProps.settings) ||
|
|
242
|
+
currentProps.workspace !== prevProps.workspace;
|
|
211
243
|
if (needsNewSetup) {
|
|
212
|
-
|
|
244
|
+
setupVisualization();
|
|
213
245
|
}
|
|
214
|
-
|
|
215
|
-
};
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
246
|
+
updateVisualization();
|
|
247
|
+
});
|
|
248
|
+
// componentWillUnmount
|
|
249
|
+
useEffect(() => {
|
|
250
|
+
const reactRootsMap = reactRootsMapRef.current;
|
|
251
|
+
isUnmountedRef.current = false;
|
|
252
|
+
return () => {
|
|
253
|
+
unmountVisualization();
|
|
254
|
+
/**
|
|
255
|
+
* Unlike componentWillUnmount, this cleanup also runs when the effects of this very component
|
|
256
|
+
* instance are torn down and set up again (StrictMode double-invoke in development, <Activity>
|
|
257
|
+
* hiding, Fast Refresh). The refs survive that, so the setup state has to be reset here -
|
|
258
|
+
* otherwise the next effect pass would see unchanged props, skip setupVisualization and leave
|
|
259
|
+
* an empty container behind.
|
|
260
|
+
*/
|
|
261
|
+
prevPropsRef.current = undefined;
|
|
262
|
+
isUnmountedRef.current = true;
|
|
263
|
+
// In order to avoid race conditions when mounting and unmounting synchronously,
|
|
264
|
+
// we use timeout for React18.
|
|
265
|
+
// https://github.com/facebook/react/issues/25675
|
|
266
|
+
setTimeout(() => {
|
|
267
|
+
// the component was mounted again in the meantime, the roots are in use - keep them so
|
|
268
|
+
// that the visualization set up by the new effect pass is not torn down underneath it
|
|
269
|
+
if (!isUnmountedRef.current) {
|
|
270
|
+
return;
|
|
271
|
+
}
|
|
272
|
+
reactRootsMap.forEach((root) => root.unmount());
|
|
273
|
+
// the roots above are gone; drop them so that a later remount creates fresh ones
|
|
274
|
+
reactRootsMap.clear();
|
|
275
|
+
}, 0);
|
|
276
|
+
};
|
|
277
|
+
}, [unmountVisualization]);
|
|
278
|
+
return (
|
|
279
|
+
// never ever dynamically change the props of this div, otherwise bad things will happen
|
|
280
|
+
// e.g. visualization being rendered multiple times, etc.
|
|
281
|
+
_jsx("div", { className: "visualization-uri-root", id: elementId, ref: containerRef, style: visualizationUriRootStyle }));
|
|
282
|
+
});
|
|
283
|
+
export const IntlInsightRenderer = withContexts(InsightRendererCore);
|
|
234
284
|
/**
|
|
235
285
|
* Updated callback (callback with a different reference) is not properly propagated to the "visualization" instance
|
|
236
286
|
* (because it only takes the callbacks provided on the first render)
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { PureComponent } from "react";
|
|
2
1
|
import { type IAnalyticalBackend, type IPreparedExecution } from "@gooddata/sdk-backend-spi";
|
|
3
2
|
import { type IExecutionConfig, type IInsight, type IInsightDefinition, type ISettings, type ITheme, type IVisualizationClass, type IWorkspacePermissions } from "@gooddata/sdk-model";
|
|
4
3
|
import { type ExplicitDrill, type ILocale, type OnError, type OnExportReady, type OnLoadingChanged, type VisualizationEnvironment } from "@gooddata/sdk-ui";
|
|
@@ -46,39 +45,13 @@ export interface IBaseVisualizationProps extends IVisCallbacks {
|
|
|
46
45
|
configurationPanelRenderers?: IConfigurationPanelRenderers;
|
|
47
46
|
supportsChartFill?: boolean;
|
|
48
47
|
}
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
private executionFactory;
|
|
54
|
-
private containerRef;
|
|
55
|
-
/**
|
|
56
|
-
* The component may render both visualization and config panel. In React18 we therefore need two
|
|
57
|
-
* roots with their respective render methods. This Map holds the roots for both and provides
|
|
58
|
-
* render and unmount methods whenever needed.
|
|
59
|
-
*/
|
|
60
|
-
private reactRootsMap;
|
|
61
|
-
constructor(props: IBaseVisualizationProps);
|
|
62
|
-
componentWillUnmount(): void;
|
|
63
|
-
UNSAFE_componentWillReceiveProps(nextProps: IBaseVisualizationProps): void;
|
|
64
|
-
componentDidMount(): void;
|
|
65
|
-
componentDidUpdate(): void;
|
|
66
|
-
render(): import("react/jsx-runtime").JSX.Element;
|
|
67
|
-
private getVisElementClassName;
|
|
68
|
-
private getClassName;
|
|
69
|
-
private setupVisualization;
|
|
70
|
-
private getReactRenderFunction;
|
|
71
|
-
private getReactUnmountFunction;
|
|
72
|
-
private updateVisualization;
|
|
73
|
-
private triggerPlaceNewDerivedBucketItems;
|
|
74
|
-
private triggerExtendedReferencePointChanged;
|
|
75
|
-
private triggerPropertiesChanged;
|
|
76
|
-
private static bucketReferencePointHasChanged;
|
|
77
|
-
private static propertiesControlsHasChanged;
|
|
78
|
-
private somePropertiesRelevantForReferencePointChanged;
|
|
79
|
-
private getVisualizationProps;
|
|
80
|
-
getInsightWithDrillDownApplied(sourceVisualization: IInsight, drillDownContext: IDrillDownContext): IInsight;
|
|
48
|
+
/**
|
|
49
|
+
* Imperative API of the {@link BaseVisualization}, available through its ref.
|
|
50
|
+
*/
|
|
51
|
+
export interface IBaseVisualizationApi {
|
|
81
52
|
getExecution(): IPreparedExecution | null;
|
|
82
53
|
getExecutions(): IPreparedExecution[] | undefined;
|
|
54
|
+
getInsightWithDrillDownApplied(sourceVisualization: IInsight, drillDownContext: IDrillDownContext): IInsight;
|
|
83
55
|
}
|
|
56
|
+
export declare const BaseVisualization: import("react").ForwardRefExoticComponent<IBaseVisualizationProps & import("react").RefAttributes<IBaseVisualizationApi>>;
|
|
84
57
|
//# sourceMappingURL=BaseVisualization.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BaseVisualization.d.ts","sourceRoot":"","sources":["../../../src/internal/components/BaseVisualization.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"BaseVisualization.d.ts","sourceRoot":"","sources":["../../../src/internal/components/BaseVisualization.tsx"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
// (C) 2019-2026 GoodData Corporation
|
|
3
|
-
import {
|
|
3
|
+
import { forwardRef, useEffect, useImperativeHandle, useLayoutEffect, useRef, useState } from "react";
|
|
4
4
|
import { isEmpty, isEqual, omit } from "lodash-es";
|
|
5
5
|
import { createRoot } from "react-dom/client";
|
|
6
6
|
import { v4 as uuidv4 } from "uuid";
|
|
@@ -8,268 +8,310 @@ import { insightProperties, isInsight, visClassUrl, } from "@gooddata/sdk-model"
|
|
|
8
8
|
import { ConfigPanelClassName, } from "../interfaces/Visualization.js";
|
|
9
9
|
import { cleanupKeyDriverAnalysisOnMetrics, hideKeyDriverOnMetrics } from "../utils/keyDriverAnalysis.js";
|
|
10
10
|
import { FullVisualizationCatalog } from "./VisualizationCatalog.js";
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
11
|
+
const noop = () => { };
|
|
12
|
+
function getVisualizationId(insight) {
|
|
13
|
+
return isInsight(insight) ? insight.insight.identifier : "__new_visualization__";
|
|
14
|
+
}
|
|
15
|
+
function bucketReferencePointHasChanged(currentReferencePoint, nextReferencePoint) {
|
|
16
|
+
return !isEqual(omit(currentReferencePoint, ["properties", "availableSorts"]), omit(nextReferencePoint, ["properties", "availableSorts"]));
|
|
17
|
+
}
|
|
18
|
+
function propertiesControlsHasChanged(currentReferencePoint, nextReferencePoint) {
|
|
19
|
+
return !isEqual(currentReferencePoint?.properties?.controls, nextReferencePoint?.properties?.controls);
|
|
20
|
+
}
|
|
21
|
+
export const BaseVisualization = forwardRef(function BaseVisualization(props, ref) {
|
|
22
|
+
const { visualizationCatalog = FullVisualizationCatalog, newDerivedBucketItems = [], referencePoint = undefined, onExtendedReferencePointChanged = noop, onNewDerivedBucketItemsPlaced = noop, isMdObjectValid = true, configPanelClassName = ConfigPanelClassName, featureFlags = {}, } = props;
|
|
23
|
+
/**
|
|
24
|
+
* Props with the defaults applied; the lifecycle handling below compares and passes them around
|
|
25
|
+
* the very same way the class component did with props defaulted by React.
|
|
26
|
+
*/
|
|
27
|
+
const currentProps = {
|
|
28
|
+
...props,
|
|
29
|
+
visualizationCatalog,
|
|
30
|
+
newDerivedBucketItems,
|
|
31
|
+
referencePoint,
|
|
32
|
+
onExtendedReferencePointChanged,
|
|
33
|
+
onNewDerivedBucketItemsPlaced,
|
|
34
|
+
isMdObjectValid,
|
|
35
|
+
configPanelClassName,
|
|
36
|
+
featureFlags,
|
|
21
37
|
};
|
|
22
|
-
visElementId;
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
38
|
+
const [visElementId, setVisElementId] = useState(() => uuidv4());
|
|
39
|
+
/**
|
|
40
|
+
* Mirror of the visElementId state. The element lookups handed over to the pluggable visualization
|
|
41
|
+
* are lazy, so they must see the new id as soon as it is generated - that is, before the state
|
|
42
|
+
* update is processed and the container div is remounted under the new key.
|
|
43
|
+
*/
|
|
44
|
+
const visElementIdRef = useRef(visElementId);
|
|
45
|
+
const visualization = useRef(undefined);
|
|
46
|
+
const containerRef = useRef(null);
|
|
26
47
|
/**
|
|
27
48
|
* The component may render both visualization and config panel. In React18 we therefore need two
|
|
28
49
|
* roots with their respective render methods. This Map holds the roots for both and provides
|
|
29
50
|
* render and unmount methods whenever needed.
|
|
30
51
|
*/
|
|
31
|
-
reactRootsMap = new Map();
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
if (isInsight(insight)) {
|
|
37
|
-
visualizationId = insight.insight.identifier;
|
|
38
|
-
}
|
|
39
|
-
else {
|
|
40
|
-
visualizationId = "__new_visualization__";
|
|
41
|
-
}
|
|
42
|
-
this.visElementId = uuidv4();
|
|
43
|
-
this.executionFactory = props.backend
|
|
44
|
-
.withCorrelation({ visualizationId })
|
|
52
|
+
const reactRootsMap = useRef(new Map());
|
|
53
|
+
const executionFactory = useRef(undefined);
|
|
54
|
+
if (!executionFactory.current) {
|
|
55
|
+
executionFactory.current = props.backend
|
|
56
|
+
.withCorrelation({ visualizationId: getVisualizationId(props.insight) })
|
|
45
57
|
.workspace(props.projectId)
|
|
46
58
|
.execution();
|
|
47
|
-
this.containerRef = createRef();
|
|
48
|
-
}
|
|
49
|
-
componentWillUnmount() {
|
|
50
|
-
if (this.visualization) {
|
|
51
|
-
this.visualization.unmount();
|
|
52
|
-
}
|
|
53
|
-
// In order to avoid race conditions when mounting and unmounting synchronously,
|
|
54
|
-
// we use timeout for React18.
|
|
55
|
-
// https://github.com/facebook/react/issues/25675
|
|
56
|
-
this.reactRootsMap.forEach((root) => setTimeout(() => root.unmount(), 0));
|
|
57
|
-
}
|
|
58
|
-
UNSAFE_componentWillReceiveProps(nextProps) {
|
|
59
|
-
const newDerivedBucketItemsChanged = !isEmpty(nextProps.newDerivedBucketItems) &&
|
|
60
|
-
!isEqual(nextProps.newDerivedBucketItems, this.props.newDerivedBucketItems);
|
|
61
|
-
if (newDerivedBucketItemsChanged) {
|
|
62
|
-
this.triggerPlaceNewDerivedBucketItems(nextProps);
|
|
63
|
-
return;
|
|
64
|
-
}
|
|
65
|
-
// buckets changed from within inner visualization logic
|
|
66
|
-
const bucketsToUpdate = this.visualization?.getBucketsToUpdate(this.props.referencePoint, nextProps.referencePoint);
|
|
67
|
-
if (bucketsToUpdate) {
|
|
68
|
-
this.triggerPlaceNewDerivedBucketItems(nextProps, bucketsToUpdate);
|
|
69
|
-
this.triggerExtendedReferencePointChanged(nextProps, this.props);
|
|
70
|
-
return;
|
|
71
|
-
}
|
|
72
|
-
const visualizationClassChanged = !isEqual(nextProps.visualizationClass, this.props.visualizationClass);
|
|
73
|
-
const referencePointChanged = BaseVisualization.bucketReferencePointHasChanged(this.props.referencePoint, nextProps.referencePoint);
|
|
74
|
-
const relevantPropertiesChanged = this.somePropertiesRelevantForReferencePointChanged(this.props.referencePoint, nextProps.referencePoint);
|
|
75
|
-
const labelsChanged = !isEqual(this.props.insight?.insight.attributeFilterConfigs, nextProps.insight?.insight.attributeFilterConfigs);
|
|
76
|
-
const propertiesControlsChanged = BaseVisualization.propertiesControlsHasChanged(this.props.referencePoint, nextProps.referencePoint);
|
|
77
|
-
if (visualizationClassChanged) {
|
|
78
|
-
this.visElementId = uuidv4();
|
|
79
|
-
this.setupVisualization(nextProps);
|
|
80
|
-
}
|
|
81
|
-
if (referencePointChanged ||
|
|
82
|
-
relevantPropertiesChanged ||
|
|
83
|
-
visualizationClassChanged ||
|
|
84
|
-
labelsChanged) {
|
|
85
|
-
this.triggerExtendedReferencePointChanged(nextProps,
|
|
86
|
-
// only pass current props if the visualization class is the same (see getExtendedReferencePoint JSDoc)
|
|
87
|
-
visualizationClassChanged ? undefined : this.props);
|
|
88
|
-
// Some of the properties eg. stacking of measures, dual axes influence sorting
|
|
89
|
-
}
|
|
90
|
-
else if (propertiesControlsChanged) {
|
|
91
|
-
this.triggerPropertiesChanged(nextProps, this.props);
|
|
92
|
-
}
|
|
93
59
|
}
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
return
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
60
|
+
const getVisElementClassName = () => `gd-vis-${visElementIdRef.current}`;
|
|
61
|
+
const getClassName = () => `gd-base-visualization ${getVisElementClassName()}`;
|
|
62
|
+
const getReactRenderFunction = () => {
|
|
63
|
+
return (children, element) => {
|
|
64
|
+
if (!element) {
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
if (!reactRootsMap.current.get(element)) {
|
|
68
|
+
reactRootsMap.current.set(element, createRoot(element));
|
|
69
|
+
}
|
|
70
|
+
reactRootsMap.current.get(element).render(children);
|
|
71
|
+
};
|
|
72
|
+
};
|
|
73
|
+
const getReactUnmountFunction = () => {
|
|
74
|
+
return () => reactRootsMap.current.forEach((root) => root.render(null));
|
|
75
|
+
};
|
|
76
|
+
/**
|
|
77
|
+
* The `hostProps` are the equivalent of `this.props` of the original class component: the class
|
|
78
|
+
* picked the catalog and the messages from the props of the last completed render, which - when
|
|
79
|
+
* setting up on a visualization class change - were still the previous ones. Everything else is
|
|
80
|
+
* taken from the props the visualization is being set up for.
|
|
81
|
+
*/
|
|
82
|
+
const setupVisualization = (setupProps, hostProps = setupProps) => {
|
|
83
|
+
const { insight, visualizationClass, environment, locale, featureFlags: setupFeatureFlags, permissions, projectId, configPanelClassName: setupConfigPanelClassName, renderer, unmount, } = setupProps;
|
|
84
|
+
if (visualization.current) {
|
|
85
|
+
visualization.current.unmount();
|
|
117
86
|
}
|
|
118
87
|
const visUri = visClassUrl(visualizationClass);
|
|
119
88
|
let visFactory;
|
|
120
89
|
try {
|
|
121
|
-
visFactory =
|
|
122
|
-
.visualizationCatalog.forUri(visUri,
|
|
90
|
+
visFactory = hostProps
|
|
91
|
+
.visualizationCatalog.forUri(visUri, setupFeatureFlags?.enableNewPivotTable ?? true, setupFeatureFlags?.enableNewGeoPushpin ?? false)
|
|
123
92
|
.getFactory();
|
|
124
93
|
}
|
|
125
94
|
catch {
|
|
126
95
|
console.error(`Error: unsupported visualization type - ${visUri}`);
|
|
127
96
|
}
|
|
128
|
-
let visualizationId;
|
|
129
|
-
if (isInsight(insight)) {
|
|
130
|
-
visualizationId = insight.insight.identifier;
|
|
131
|
-
}
|
|
132
|
-
else {
|
|
133
|
-
visualizationId = "__new_visualization__";
|
|
134
|
-
}
|
|
135
97
|
if (visFactory) {
|
|
136
98
|
const constructorParams = {
|
|
137
99
|
projectId,
|
|
138
100
|
locale,
|
|
139
|
-
messages:
|
|
101
|
+
messages: hostProps.messages,
|
|
140
102
|
environment,
|
|
141
|
-
backend:
|
|
103
|
+
backend: setupProps.backend.withCorrelation({
|
|
104
|
+
visualizationId: getVisualizationId(insight),
|
|
105
|
+
}),
|
|
142
106
|
element: () => {
|
|
143
|
-
const rootNode =
|
|
144
|
-
return rootNode.querySelector(`.${
|
|
107
|
+
const rootNode = containerRef.current?.getRootNode() ?? document;
|
|
108
|
+
return rootNode.querySelector(`.${getVisElementClassName()}`);
|
|
145
109
|
},
|
|
146
110
|
configPanelElement: () => {
|
|
147
|
-
const rootNode =
|
|
148
|
-
return rootNode.querySelector(`.${
|
|
111
|
+
const rootNode = containerRef.current?.getRootNode() ?? document;
|
|
112
|
+
return rootNode.querySelector(`.${setupConfigPanelClassName}`);
|
|
149
113
|
},
|
|
150
114
|
callbacks: {
|
|
151
|
-
afterRender:
|
|
152
|
-
onLoadingChanged:
|
|
153
|
-
onError:
|
|
154
|
-
onExportReady:
|
|
155
|
-
pushData:
|
|
156
|
-
onDrill:
|
|
157
|
-
onDataView:
|
|
115
|
+
afterRender: setupProps.afterRender,
|
|
116
|
+
onLoadingChanged: setupProps.onLoadingChanged,
|
|
117
|
+
onError: setupProps.onError,
|
|
118
|
+
onExportReady: setupProps.onExportReady,
|
|
119
|
+
pushData: setupProps.pushData,
|
|
120
|
+
onDrill: setupProps.onDrill,
|
|
121
|
+
onDataView: setupProps.onDataView,
|
|
158
122
|
},
|
|
159
|
-
featureFlags,
|
|
123
|
+
featureFlags: setupFeatureFlags,
|
|
160
124
|
permissions,
|
|
161
|
-
visualizationProperties: insightProperties(
|
|
162
|
-
renderFun: (renderer ??
|
|
163
|
-
unmountFun: unmount ??
|
|
125
|
+
visualizationProperties: insightProperties(setupProps.insight),
|
|
126
|
+
renderFun: (renderer ?? getReactRenderFunction()),
|
|
127
|
+
unmountFun: unmount ?? getReactUnmountFunction(),
|
|
164
128
|
};
|
|
165
|
-
|
|
129
|
+
visualization.current = visFactory(constructorParams);
|
|
166
130
|
}
|
|
167
|
-
}
|
|
168
|
-
getReactRenderFunction = () => {
|
|
169
|
-
return (children, element) => {
|
|
170
|
-
if (!element) {
|
|
171
|
-
return;
|
|
172
|
-
}
|
|
173
|
-
if (!this.reactRootsMap.get(element)) {
|
|
174
|
-
this.reactRootsMap.set(element, createRoot(element));
|
|
175
|
-
}
|
|
176
|
-
this.reactRootsMap.get(element).render(children);
|
|
177
|
-
};
|
|
178
131
|
};
|
|
179
|
-
|
|
180
|
-
return
|
|
132
|
+
const getVisualizationProps = () => {
|
|
133
|
+
return {
|
|
134
|
+
locale: props.locale,
|
|
135
|
+
dateFormat: props.dateFormat,
|
|
136
|
+
dimensions: {
|
|
137
|
+
width: props.width,
|
|
138
|
+
height: props.height,
|
|
139
|
+
},
|
|
140
|
+
custom: {
|
|
141
|
+
drillableItems: props.drillableItems,
|
|
142
|
+
totalsEditAllowed: props.totalsEditAllowed,
|
|
143
|
+
lastSavedVisClassUrl: props.lastSavedVisClassUrl,
|
|
144
|
+
sourceInsightId: props.sourceInsightId,
|
|
145
|
+
configurationPanelRenderers: props.configurationPanelRenderers,
|
|
146
|
+
},
|
|
147
|
+
messages: props.messages,
|
|
148
|
+
config: props.config,
|
|
149
|
+
theme: props.theme,
|
|
150
|
+
referenceTheme: props.referenceTheme,
|
|
151
|
+
executionConfig: props.executionConfig,
|
|
152
|
+
supportsChartFill: props.supportsChartFill,
|
|
153
|
+
};
|
|
181
154
|
};
|
|
182
|
-
updateVisualization() {
|
|
183
|
-
if (!
|
|
155
|
+
const updateVisualization = () => {
|
|
156
|
+
if (!visualization.current) {
|
|
184
157
|
return;
|
|
185
158
|
}
|
|
186
|
-
|
|
187
|
-
}
|
|
188
|
-
triggerPlaceNewDerivedBucketItems(
|
|
189
|
-
const { newDerivedBucketItems, referencePoint, onNewDerivedBucketItemsPlaced } =
|
|
190
|
-
const newDerivedBucketItemsToPlace = newBucketItemsFromVisualization ??
|
|
191
|
-
if (
|
|
192
|
-
|
|
159
|
+
visualization.current.update(getVisualizationProps(), props.insight, props.insightPropertiesMeta, executionFactory.current);
|
|
160
|
+
};
|
|
161
|
+
const triggerPlaceNewDerivedBucketItems = (triggerProps, newBucketItemsFromVisualization) => {
|
|
162
|
+
const { newDerivedBucketItems: triggerNewDerivedBucketItems, referencePoint: triggerReferencePoint, onNewDerivedBucketItemsPlaced: triggerOnNewDerivedBucketItemsPlaced, } = triggerProps;
|
|
163
|
+
const newDerivedBucketItemsToPlace = newBucketItemsFromVisualization ?? triggerNewDerivedBucketItems;
|
|
164
|
+
if (visualization.current &&
|
|
165
|
+
triggerReferencePoint &&
|
|
193
166
|
newDerivedBucketItemsToPlace &&
|
|
194
|
-
|
|
195
|
-
void
|
|
196
|
-
.addNewDerivedBucketItems(
|
|
197
|
-
.then(
|
|
167
|
+
triggerOnNewDerivedBucketItemsPlaced) {
|
|
168
|
+
void visualization.current
|
|
169
|
+
.addNewDerivedBucketItems(triggerReferencePoint, newDerivedBucketItemsToPlace)
|
|
170
|
+
.then(triggerOnNewDerivedBucketItemsPlaced);
|
|
198
171
|
}
|
|
199
|
-
}
|
|
200
|
-
triggerExtendedReferencePointChanged(newProps,
|
|
201
|
-
const { referencePoint: newReferencePoint, onExtendedReferencePointChanged } = newProps;
|
|
202
|
-
if (
|
|
203
|
-
void
|
|
204
|
-
.getExtendedReferencePoint(newReferencePoint,
|
|
172
|
+
};
|
|
173
|
+
const triggerExtendedReferencePointChanged = (newProps, previousProps) => {
|
|
174
|
+
const { referencePoint: newReferencePoint, onExtendedReferencePointChanged: newOnExtendedReferencePointChanged, } = newProps;
|
|
175
|
+
if (visualization.current && newReferencePoint && newOnExtendedReferencePointChanged) {
|
|
176
|
+
void visualization.current
|
|
177
|
+
.getExtendedReferencePoint(newReferencePoint, previousProps?.referencePoint)
|
|
205
178
|
.then(async (extendedReferencePoint) => {
|
|
206
|
-
const sortConfig = await
|
|
179
|
+
const sortConfig = await visualization.current.getSortConfig(extendedReferencePoint);
|
|
207
180
|
let updatedExtendedReferencePoint = cleanupKeyDriverAnalysisOnMetrics(extendedReferencePoint);
|
|
208
181
|
updatedExtendedReferencePoint = hideKeyDriverOnMetrics(updatedExtendedReferencePoint);
|
|
209
182
|
// new sort config needs to be sent together with new reference point to avoid double executions with old invalid sort until new one arrives by its own handler
|
|
210
|
-
|
|
183
|
+
newOnExtendedReferencePointChanged(updatedExtendedReferencePoint, sortConfig);
|
|
211
184
|
});
|
|
212
185
|
}
|
|
213
|
-
}
|
|
214
|
-
triggerPropertiesChanged(newProps,
|
|
186
|
+
};
|
|
187
|
+
const triggerPropertiesChanged = (newProps, previousProps) => {
|
|
215
188
|
const { referencePoint: newReferencePoint, onSortingChanged } = newProps;
|
|
216
189
|
// Some of the properties eg. stacking of measures, dual axes influence sorting
|
|
217
|
-
if (
|
|
218
|
-
void
|
|
219
|
-
.getExtendedReferencePoint(newReferencePoint,
|
|
190
|
+
if (visualization.current && newReferencePoint && onSortingChanged) {
|
|
191
|
+
void visualization.current
|
|
192
|
+
.getExtendedReferencePoint(newReferencePoint, previousProps?.referencePoint)
|
|
220
193
|
.then((extendedRefPoint) => {
|
|
221
|
-
void
|
|
194
|
+
void visualization.current.getSortConfig(extendedRefPoint).then(onSortingChanged);
|
|
222
195
|
});
|
|
223
196
|
}
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
static propertiesControlsHasChanged(currentReferencePoint, nextReferencePoint) {
|
|
229
|
-
return !isEqual(currentReferencePoint?.properties?.controls, nextReferencePoint?.properties?.controls);
|
|
230
|
-
}
|
|
231
|
-
somePropertiesRelevantForReferencePointChanged(currentReferencePoint, nextReferencePoint) {
|
|
232
|
-
if (this.visualization) {
|
|
233
|
-
return this.visualization.haveSomePropertiesRelevantForReferencePointChanged(currentReferencePoint, nextReferencePoint);
|
|
197
|
+
};
|
|
198
|
+
const somePropertiesRelevantForReferencePointChanged = (currentReferencePoint, nextReferencePoint) => {
|
|
199
|
+
if (visualization.current) {
|
|
200
|
+
return visualization.current.haveSomePropertiesRelevantForReferencePointChanged(currentReferencePoint, nextReferencePoint);
|
|
234
201
|
}
|
|
235
202
|
return false;
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
return
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
height: this.props.height,
|
|
244
|
-
},
|
|
245
|
-
custom: {
|
|
246
|
-
drillableItems: this.props.drillableItems,
|
|
247
|
-
totalsEditAllowed: this.props.totalsEditAllowed,
|
|
248
|
-
lastSavedVisClassUrl: this.props.lastSavedVisClassUrl,
|
|
249
|
-
sourceInsightId: this.props.sourceInsightId,
|
|
250
|
-
configurationPanelRenderers: this.props.configurationPanelRenderers,
|
|
251
|
-
},
|
|
252
|
-
messages: this.props.messages,
|
|
253
|
-
config: this.props.config,
|
|
254
|
-
theme: this.props.theme,
|
|
255
|
-
referenceTheme: this.props.referenceTheme,
|
|
256
|
-
executionConfig: this.props.executionConfig,
|
|
257
|
-
supportsChartFill: this.props.supportsChartFill,
|
|
258
|
-
};
|
|
259
|
-
}
|
|
260
|
-
getInsightWithDrillDownApplied(sourceVisualization, drillDownContext) {
|
|
261
|
-
return this.visualization.getInsightWithDrillDownApplied(sourceVisualization, drillDownContext, this.props.backend.capabilities.supportsElementUris ?? true);
|
|
262
|
-
}
|
|
263
|
-
getExecution() {
|
|
264
|
-
if (!this.visualization) {
|
|
265
|
-
this.setupVisualization(this.props);
|
|
203
|
+
};
|
|
204
|
+
const getInsightWithDrillDownApplied = (sourceVisualization, drillDownContext) => {
|
|
205
|
+
return visualization.current.getInsightWithDrillDownApplied(sourceVisualization, drillDownContext, props.backend.capabilities.supportsElementUris ?? true);
|
|
206
|
+
};
|
|
207
|
+
const getExecution = () => {
|
|
208
|
+
if (!visualization.current) {
|
|
209
|
+
setupVisualization(currentProps);
|
|
266
210
|
}
|
|
267
|
-
return
|
|
268
|
-
}
|
|
269
|
-
getExecutions() {
|
|
270
|
-
if (!
|
|
271
|
-
|
|
211
|
+
return visualization.current.getExecution(getVisualizationProps(), props.insight, executionFactory.current);
|
|
212
|
+
};
|
|
213
|
+
const getExecutions = () => {
|
|
214
|
+
if (!visualization.current) {
|
|
215
|
+
setupVisualization(currentProps);
|
|
272
216
|
}
|
|
273
|
-
return
|
|
274
|
-
}
|
|
275
|
-
|
|
217
|
+
return visualization.current?.getExecutions?.(getVisualizationProps(), props.insight, executionFactory.current);
|
|
218
|
+
};
|
|
219
|
+
useImperativeHandle(ref, () => ({
|
|
220
|
+
getExecution,
|
|
221
|
+
getExecutions,
|
|
222
|
+
getInsightWithDrillDownApplied,
|
|
223
|
+
}));
|
|
224
|
+
const prevPropsRef = useRef(currentProps);
|
|
225
|
+
const mountedRef = useRef(false);
|
|
226
|
+
/**
|
|
227
|
+
* Replacement of UNSAFE_componentWillReceiveProps. Runs before the mount & update effect below so
|
|
228
|
+
* that the derived bucket items and the reference point are handled before the visualization is
|
|
229
|
+
* updated, the same way the class did it in the pre-render phase.
|
|
230
|
+
*
|
|
231
|
+
* The effect intentionally has no dependency list - it has to see every single commit, exactly like
|
|
232
|
+
* the class lifecycle did; the props diff below decides what actually happens. The visElementId is
|
|
233
|
+
* regenerated only when the visualization class really changes, so there is no update loop.
|
|
234
|
+
*/
|
|
235
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
236
|
+
useLayoutEffect(() => {
|
|
237
|
+
const previousProps = prevPropsRef.current;
|
|
238
|
+
prevPropsRef.current = currentProps;
|
|
239
|
+
if (previousProps === currentProps) {
|
|
240
|
+
// the very first run, there is nothing to diff against yet
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
243
|
+
const newDerivedBucketItemsChanged = !isEmpty(currentProps.newDerivedBucketItems) &&
|
|
244
|
+
!isEqual(currentProps.newDerivedBucketItems, previousProps.newDerivedBucketItems);
|
|
245
|
+
if (newDerivedBucketItemsChanged) {
|
|
246
|
+
triggerPlaceNewDerivedBucketItems(currentProps);
|
|
247
|
+
return;
|
|
248
|
+
}
|
|
249
|
+
// buckets changed from within inner visualization logic
|
|
250
|
+
const bucketsToUpdate = visualization.current?.getBucketsToUpdate(previousProps.referencePoint, currentProps.referencePoint);
|
|
251
|
+
if (bucketsToUpdate) {
|
|
252
|
+
triggerPlaceNewDerivedBucketItems(currentProps, bucketsToUpdate);
|
|
253
|
+
triggerExtendedReferencePointChanged(currentProps, previousProps);
|
|
254
|
+
return;
|
|
255
|
+
}
|
|
256
|
+
const visualizationClassChanged = !isEqual(currentProps.visualizationClass, previousProps.visualizationClass);
|
|
257
|
+
const referencePointChanged = bucketReferencePointHasChanged(previousProps.referencePoint, currentProps.referencePoint);
|
|
258
|
+
const relevantPropertiesChanged = somePropertiesRelevantForReferencePointChanged(previousProps.referencePoint, currentProps.referencePoint);
|
|
259
|
+
const labelsChanged = !isEqual(previousProps.insight?.insight.attributeFilterConfigs, currentProps.insight?.insight.attributeFilterConfigs);
|
|
260
|
+
const propertiesControlsChanged = propertiesControlsHasChanged(previousProps.referencePoint, currentProps.referencePoint);
|
|
261
|
+
if (visualizationClassChanged) {
|
|
262
|
+
const newVisElementId = uuidv4();
|
|
263
|
+
visElementIdRef.current = newVisElementId;
|
|
264
|
+
setVisElementId(newVisElementId);
|
|
265
|
+
setupVisualization(currentProps, previousProps);
|
|
266
|
+
}
|
|
267
|
+
if (referencePointChanged ||
|
|
268
|
+
relevantPropertiesChanged ||
|
|
269
|
+
visualizationClassChanged ||
|
|
270
|
+
labelsChanged) {
|
|
271
|
+
triggerExtendedReferencePointChanged(currentProps,
|
|
272
|
+
// only pass current props if the visualization class is the same (see getExtendedReferencePoint JSDoc)
|
|
273
|
+
visualizationClassChanged ? undefined : previousProps);
|
|
274
|
+
// Some of the properties eg. stacking of measures, dual axes influence sorting
|
|
275
|
+
}
|
|
276
|
+
else if (propertiesControlsChanged) {
|
|
277
|
+
triggerPropertiesChanged(currentProps, previousProps);
|
|
278
|
+
}
|
|
279
|
+
});
|
|
280
|
+
/**
|
|
281
|
+
* Replacement of componentDidMount and componentDidUpdate.
|
|
282
|
+
*/
|
|
283
|
+
useLayoutEffect(() => {
|
|
284
|
+
if (!mountedRef.current) {
|
|
285
|
+
mountedRef.current = true;
|
|
286
|
+
setupVisualization(currentProps);
|
|
287
|
+
updateVisualization();
|
|
288
|
+
triggerExtendedReferencePointChanged(currentProps);
|
|
289
|
+
return;
|
|
290
|
+
}
|
|
291
|
+
if (visElementId !== visElementIdRef.current) {
|
|
292
|
+
// the visualization class has just changed; the container div is about to be remounted
|
|
293
|
+
// under the new key, so postpone the update until it is in the DOM
|
|
294
|
+
return;
|
|
295
|
+
}
|
|
296
|
+
if (isMdObjectValid) {
|
|
297
|
+
updateVisualization();
|
|
298
|
+
}
|
|
299
|
+
});
|
|
300
|
+
/**
|
|
301
|
+
* Replacement of componentWillUnmount.
|
|
302
|
+
*/
|
|
303
|
+
useEffect(() => {
|
|
304
|
+
const reactRoots = reactRootsMap.current;
|
|
305
|
+
return () => {
|
|
306
|
+
// a subsequent mount (React StrictMode remounts the tree in development) has to set the
|
|
307
|
+
// visualization up again, exactly like componentDidMount did
|
|
308
|
+
mountedRef.current = false;
|
|
309
|
+
visualization.current?.unmount();
|
|
310
|
+
// In order to avoid race conditions when mounting and unmounting synchronously,
|
|
311
|
+
// we use timeout for React18.
|
|
312
|
+
// https://github.com/facebook/react/issues/25675
|
|
313
|
+
reactRoots.forEach((root) => setTimeout(() => root.unmount(), 0));
|
|
314
|
+
};
|
|
315
|
+
}, []);
|
|
316
|
+
return (_jsx("div", { "aria-label": "base-visualization", style: { height: "100%" }, className: getClassName(), ref: containerRef }, visElementId));
|
|
317
|
+
});
|
package/esm/internal/index.d.ts
CHANGED
|
@@ -8,7 +8,7 @@ export { ColorDropdown } from "./components/configurationControls/colors/colorDr
|
|
|
8
8
|
export { ColoredItemContent } from "./components/configurationControls/colors/coloredItemsList/ColoredItemContent.js";
|
|
9
9
|
export { LegendSection } from "./components/configurationControls/legend/LegendSection.js";
|
|
10
10
|
export { MinMaxControl } from "./components/configurationControls/MinMaxControl.js";
|
|
11
|
-
export { BaseVisualization, type IBaseVisualizationProps } from "./components/BaseVisualization.js";
|
|
11
|
+
export { BaseVisualization, type IBaseVisualizationApi, type IBaseVisualizationProps, } from "./components/BaseVisualization.js";
|
|
12
12
|
export { DefaultVisualizationCatalog, FullVisualizationCatalog, type IVisualizationCatalog, } from "./components/VisualizationCatalog.js";
|
|
13
13
|
export { resolveMessages, DEFAULT_LANGUAGE, DEFAULT_MESSAGES } from "./utils/translations.js";
|
|
14
14
|
export { createIntlMock } from "./tests/testIntlProvider.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/internal/index.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,IAAI,EAAE,MAAM,qBAAqB,CAAC;AAC3C,OAAO,EAAE,wBAAwB,EAAE,MAAM,gCAAgC,CAAC;AAC1E,OAAO,EAAE,oBAAoB,EAAE,MAAM,iEAAiE,CAAC;AACvG,OAAO,EAAE,eAAe,EAAE,MAAM,4DAA4D,CAAC;AAC7F,OAAO,EAAE,mBAAmB,EAAE,MAAM,gEAAgE,CAAC;AACrG,OAAO,EAAE,cAAc,EAAE,MAAM,2DAA2D,CAAC;AAC3F,OAAO,EAAE,aAAa,EAAE,MAAM,0EAA0E,CAAC;AACzG,OAAO,EAAE,kBAAkB,EAAE,MAAM,kFAAkF,CAAC;AACtH,OAAO,EAAE,aAAa,EAAE,MAAM,4DAA4D,CAAC;AAC3F,OAAO,EAAE,aAAa,EAAE,MAAM,qDAAqD,CAAC;AAEpF,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/internal/index.ts"],"names":[],"mappings":"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"}
|
package/esm/internal/index.js
CHANGED
|
@@ -10,7 +10,7 @@ export { ColorDropdown } from "./components/configurationControls/colors/colorDr
|
|
|
10
10
|
export { ColoredItemContent } from "./components/configurationControls/colors/coloredItemsList/ColoredItemContent.js";
|
|
11
11
|
export { LegendSection } from "./components/configurationControls/legend/LegendSection.js";
|
|
12
12
|
export { MinMaxControl } from "./components/configurationControls/MinMaxControl.js";
|
|
13
|
-
export { BaseVisualization } from "./components/BaseVisualization.js";
|
|
13
|
+
export { BaseVisualization, } from "./components/BaseVisualization.js";
|
|
14
14
|
export { DefaultVisualizationCatalog, FullVisualizationCatalog, } from "./components/VisualizationCatalog.js";
|
|
15
15
|
export { resolveMessages, DEFAULT_LANGUAGE, DEFAULT_MESSAGES } from "./utils/translations.js";
|
|
16
16
|
export { createIntlMock } from "./tests/testIntlProvider.js";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gooddata/sdk-ui-ext",
|
|
3
|
-
"version": "11.53.0-alpha.
|
|
3
|
+
"version": "11.53.0-alpha.2",
|
|
4
4
|
"description": "GoodData.UI SDK - Extensions",
|
|
5
5
|
"license": "LicenseRef-LICENSE",
|
|
6
6
|
"author": "GoodData Corporation",
|
|
@@ -63,20 +63,20 @@
|
|
|
63
63
|
"ts-invariant": "0.10.3",
|
|
64
64
|
"tslib": "2.8.1",
|
|
65
65
|
"uuid": "11.1.1",
|
|
66
|
-
"@gooddata/sdk-backend-base": "11.53.0-alpha.
|
|
67
|
-
"@gooddata/sdk-backend-spi": "11.53.0-alpha.
|
|
68
|
-
"@gooddata/sdk-
|
|
69
|
-
"@gooddata/sdk-
|
|
70
|
-
"@gooddata/sdk-
|
|
71
|
-
"@gooddata/sdk-ui-charts": "11.53.0-alpha.
|
|
72
|
-
"@gooddata/sdk-ui-geo": "11.53.0-alpha.
|
|
73
|
-
"@gooddata/sdk-ui-
|
|
74
|
-
"@gooddata/sdk-ui-
|
|
75
|
-
"@gooddata/sdk-ui-pivot": "11.53.0-alpha.
|
|
76
|
-
"@gooddata/sdk-ui-vis-commons": "11.53.0-alpha.
|
|
77
|
-
"@gooddata/sdk-ui-
|
|
78
|
-
"@gooddata/util": "11.53.0-alpha.
|
|
79
|
-
"@gooddata/sdk-ui-
|
|
66
|
+
"@gooddata/sdk-backend-base": "11.53.0-alpha.2",
|
|
67
|
+
"@gooddata/sdk-backend-spi": "11.53.0-alpha.2",
|
|
68
|
+
"@gooddata/sdk-model": "11.53.0-alpha.2",
|
|
69
|
+
"@gooddata/sdk-ui": "11.53.0-alpha.2",
|
|
70
|
+
"@gooddata/sdk-embedding": "11.53.0-alpha.2",
|
|
71
|
+
"@gooddata/sdk-ui-charts": "11.53.0-alpha.2",
|
|
72
|
+
"@gooddata/sdk-ui-geo": "11.53.0-alpha.2",
|
|
73
|
+
"@gooddata/sdk-ui-filters": "11.53.0-alpha.2",
|
|
74
|
+
"@gooddata/sdk-ui-kit": "11.53.0-alpha.2",
|
|
75
|
+
"@gooddata/sdk-ui-pivot": "11.53.0-alpha.2",
|
|
76
|
+
"@gooddata/sdk-ui-vis-commons": "11.53.0-alpha.2",
|
|
77
|
+
"@gooddata/sdk-ui-semantic-search": "11.53.0-alpha.2",
|
|
78
|
+
"@gooddata/util": "11.53.0-alpha.2",
|
|
79
|
+
"@gooddata/sdk-ui-theme-provider": "11.53.0-alpha.2"
|
|
80
80
|
},
|
|
81
81
|
"devDependencies": {
|
|
82
82
|
"@microsoft/api-documenter": "^7.17.0",
|
|
@@ -124,12 +124,12 @@
|
|
|
124
124
|
"typescript": "5.9.3",
|
|
125
125
|
"vitest": "4.1.8",
|
|
126
126
|
"vitest-dom": "0.1.1",
|
|
127
|
-
"@gooddata/eslint-config": "11.53.0-alpha.
|
|
128
|
-
"@gooddata/
|
|
129
|
-
"@gooddata/
|
|
130
|
-
"@gooddata/
|
|
131
|
-
"@gooddata/
|
|
132
|
-
"@gooddata/
|
|
127
|
+
"@gooddata/eslint-config": "11.53.0-alpha.2",
|
|
128
|
+
"@gooddata/i18n-toolkit": "11.53.0-alpha.2",
|
|
129
|
+
"@gooddata/oxlint-config": "11.53.0-alpha.2",
|
|
130
|
+
"@gooddata/reference-workspace": "11.53.0-alpha.2",
|
|
131
|
+
"@gooddata/sdk-backend-mockingbird": "11.53.0-alpha.2",
|
|
132
|
+
"@gooddata/stylelint-config": "11.53.0-alpha.2"
|
|
133
133
|
},
|
|
134
134
|
"peerDependencies": {
|
|
135
135
|
"react": "^18.0.0 || ^19.0.0",
|