@gooddata/sdk-ui-dashboard 11.58.0-alpha.4 → 11.58.0-alpha.6
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/__version.d.ts +1 -1
- package/esm/__version.js +1 -1
- package/esm/_staging/insight/insightWidgetDescription.d.ts +9 -0
- package/esm/_staging/insight/insightWidgetDescription.d.ts.map +1 -0
- package/esm/_staging/insight/insightWidgetDescription.js +12 -0
- package/esm/_staging/sharedHooks/useRichTextFilters.d.ts +4 -22
- package/esm/_staging/sharedHooks/useRichTextFilters.d.ts.map +1 -1
- package/esm/_staging/sharedHooks/useRichTextFilters.js +11 -15
- package/esm/_staging/sharedHooks/useRichTextInputs.d.ts +35 -0
- package/esm/_staging/sharedHooks/useRichTextInputs.d.ts.map +1 -0
- package/esm/_staging/sharedHooks/useRichTextInputs.js +37 -0
- package/esm/index.d.ts +2 -2
- package/esm/index.d.ts.map +1 -1
- package/esm/index.js +1 -1
- package/esm/model/DashboardTester.d.ts.map +1 -1
- package/esm/model/DashboardTester.js +2 -4
- package/esm/model/commandHandlers/dashboard/initializeDashboardHandler/index.d.ts.map +1 -1
- package/esm/model/commandHandlers/dashboard/initializeDashboardHandler/index.js +21 -13
- package/esm/model/commandHandlers/parameters/dashboardParameterRoots.d.ts +20 -0
- package/esm/model/commandHandlers/parameters/dashboardParameterRoots.d.ts.map +1 -0
- package/esm/model/commandHandlers/parameters/dashboardParameterRoots.js +61 -0
- package/esm/model/commandHandlers/parameters/loadParameterDependencies.d.ts +27 -0
- package/esm/model/commandHandlers/parameters/loadParameterDependencies.d.ts.map +1 -0
- package/esm/model/commandHandlers/parameters/loadParameterDependencies.js +114 -0
- package/esm/model/commandHandlers/parameters/parameterDependenciesWorker.d.ts +6 -0
- package/esm/model/commandHandlers/parameters/parameterDependenciesWorker.d.ts.map +1 -0
- package/esm/model/commandHandlers/parameters/parameterDependenciesWorker.js +107 -0
- package/esm/model/react/useInitializeDashboardStore.d.ts.map +1 -1
- package/esm/model/react/useInitializeDashboardStore.js +2 -4
- package/esm/model/react/useTextParameters.d.ts +34 -0
- package/esm/model/react/useTextParameters.d.ts.map +1 -0
- package/esm/model/react/useTextParameters.js +68 -0
- package/esm/model/react/useWidgetExecConfig.d.ts.map +1 -1
- package/esm/model/react/useWidgetExecConfig.js +3 -2
- package/esm/model/store/catalog/catalogReducers.d.ts +8 -8
- package/esm/model/store/catalog/catalogReducers.d.ts.map +1 -1
- package/esm/model/store/catalog/catalogReducers.js +25 -12
- package/esm/model/store/catalog/catalogSelectors.d.ts +8 -16
- package/esm/model/store/catalog/catalogSelectors.d.ts.map +1 -1
- package/esm/model/store/catalog/catalogSelectors.js +7 -15
- package/esm/model/store/catalog/catalogState.d.ts +15 -30
- package/esm/model/store/catalog/catalogState.d.ts.map +1 -1
- package/esm/model/store/catalog/catalogState.js +1 -2
- package/esm/model/store/catalog/index.d.ts +4 -4
- package/esm/model/store/tabs/parameters/parametersHelpers.d.ts +25 -9
- package/esm/model/store/tabs/parameters/parametersHelpers.d.ts.map +1 -1
- package/esm/model/store/tabs/parameters/parametersHelpers.js +46 -13
- package/esm/model/store/tabs/parameters/parametersSelectors.d.ts +9 -9
- package/esm/model/store/tabs/parameters/parametersSelectors.d.ts.map +1 -1
- package/esm/model/store/tabs/parameters/parametersSelectors.js +26 -22
- package/esm/presentation/dashboard/DashboardSidebar/SidebarResizeContext.d.ts.map +1 -1
- package/esm/presentation/dashboard/DashboardSidebar/SidebarResizeContext.js +7 -1
- package/esm/presentation/flexibleLayout/DefaultDashboardLayoutRenderer/DashboardLayoutSectionHeaderDescription.d.ts.map +1 -1
- package/esm/presentation/flexibleLayout/DefaultDashboardLayoutRenderer/DashboardLayoutSectionHeaderDescription.js +3 -10
- package/esm/presentation/flexibleLayout/DefaultDashboardLayoutRenderer/EditableHeader/SectionHeaderEditable.d.ts.map +1 -1
- package/esm/presentation/flexibleLayout/DefaultDashboardLayoutRenderer/EditableHeader/SectionHeaderEditable.js +5 -10
- package/esm/presentation/localization/bundles/de-DE.localization-bundle.d.ts +6 -1
- package/esm/presentation/localization/bundles/de-DE.localization-bundle.d.ts.map +1 -1
- package/esm/presentation/localization/bundles/de-DE.localization-bundle.js +8 -3
- package/esm/presentation/localization/bundles/en-AU.localization-bundle.d.ts +6 -1
- package/esm/presentation/localization/bundles/en-AU.localization-bundle.d.ts.map +1 -1
- package/esm/presentation/localization/bundles/en-AU.localization-bundle.js +8 -3
- package/esm/presentation/localization/bundles/en-GB.localization-bundle.d.ts +6 -1
- package/esm/presentation/localization/bundles/en-GB.localization-bundle.d.ts.map +1 -1
- package/esm/presentation/localization/bundles/en-GB.localization-bundle.js +8 -3
- package/esm/presentation/localization/bundles/es-419.localization-bundle.d.ts +6 -1
- package/esm/presentation/localization/bundles/es-419.localization-bundle.d.ts.map +1 -1
- package/esm/presentation/localization/bundles/es-419.localization-bundle.js +13 -8
- package/esm/presentation/localization/bundles/es-ES.localization-bundle.d.ts +6 -1
- package/esm/presentation/localization/bundles/es-ES.localization-bundle.d.ts.map +1 -1
- package/esm/presentation/localization/bundles/es-ES.localization-bundle.js +8 -3
- package/esm/presentation/localization/bundles/fi-FI.localization-bundle.d.ts +6 -1
- package/esm/presentation/localization/bundles/fi-FI.localization-bundle.d.ts.map +1 -1
- package/esm/presentation/localization/bundles/fi-FI.localization-bundle.js +8 -3
- package/esm/presentation/localization/bundles/fr-CA.localization-bundle.d.ts +6 -1
- package/esm/presentation/localization/bundles/fr-CA.localization-bundle.d.ts.map +1 -1
- package/esm/presentation/localization/bundles/fr-CA.localization-bundle.js +8 -3
- package/esm/presentation/localization/bundles/fr-FR.localization-bundle.d.ts +6 -1
- package/esm/presentation/localization/bundles/fr-FR.localization-bundle.d.ts.map +1 -1
- package/esm/presentation/localization/bundles/fr-FR.localization-bundle.js +8 -3
- package/esm/presentation/localization/bundles/id-ID.localization-bundle.d.ts +6 -1
- package/esm/presentation/localization/bundles/id-ID.localization-bundle.d.ts.map +1 -1
- package/esm/presentation/localization/bundles/id-ID.localization-bundle.js +8 -3
- package/esm/presentation/localization/bundles/it-IT.localization-bundle.d.ts +6 -1
- package/esm/presentation/localization/bundles/it-IT.localization-bundle.d.ts.map +1 -1
- package/esm/presentation/localization/bundles/it-IT.localization-bundle.js +10 -5
- package/esm/presentation/localization/bundles/ja-JP.localization-bundle.d.ts +6 -1
- package/esm/presentation/localization/bundles/ja-JP.localization-bundle.d.ts.map +1 -1
- package/esm/presentation/localization/bundles/ja-JP.localization-bundle.js +8 -3
- package/esm/presentation/localization/bundles/ko-KR.localization-bundle.d.ts +6 -1
- package/esm/presentation/localization/bundles/ko-KR.localization-bundle.d.ts.map +1 -1
- package/esm/presentation/localization/bundles/ko-KR.localization-bundle.js +9 -4
- package/esm/presentation/localization/bundles/nl-NL.localization-bundle.d.ts +6 -1
- package/esm/presentation/localization/bundles/nl-NL.localization-bundle.d.ts.map +1 -1
- package/esm/presentation/localization/bundles/nl-NL.localization-bundle.js +8 -3
- package/esm/presentation/localization/bundles/pl-PL.localization-bundle.d.ts +6 -1
- package/esm/presentation/localization/bundles/pl-PL.localization-bundle.d.ts.map +1 -1
- package/esm/presentation/localization/bundles/pl-PL.localization-bundle.js +8 -3
- package/esm/presentation/localization/bundles/pt-BR.localization-bundle.d.ts +6 -1
- package/esm/presentation/localization/bundles/pt-BR.localization-bundle.d.ts.map +1 -1
- package/esm/presentation/localization/bundles/pt-BR.localization-bundle.js +8 -3
- package/esm/presentation/localization/bundles/pt-PT.localization-bundle.d.ts +6 -1
- package/esm/presentation/localization/bundles/pt-PT.localization-bundle.d.ts.map +1 -1
- package/esm/presentation/localization/bundles/pt-PT.localization-bundle.js +8 -3
- package/esm/presentation/localization/bundles/ru-RU.localization-bundle.d.ts +6 -1
- package/esm/presentation/localization/bundles/ru-RU.localization-bundle.d.ts.map +1 -1
- package/esm/presentation/localization/bundles/ru-RU.localization-bundle.js +8 -3
- package/esm/presentation/localization/bundles/sl-SI.localization-bundle.d.ts +6 -1
- package/esm/presentation/localization/bundles/sl-SI.localization-bundle.d.ts.map +1 -1
- package/esm/presentation/localization/bundles/sl-SI.localization-bundle.js +9 -4
- package/esm/presentation/localization/bundles/th-TH.localization-bundle.d.ts +6 -1
- package/esm/presentation/localization/bundles/th-TH.localization-bundle.d.ts.map +1 -1
- package/esm/presentation/localization/bundles/th-TH.localization-bundle.js +9 -4
- package/esm/presentation/localization/bundles/tr-TR.localization-bundle.d.ts +6 -1
- package/esm/presentation/localization/bundles/tr-TR.localization-bundle.d.ts.map +1 -1
- package/esm/presentation/localization/bundles/tr-TR.localization-bundle.js +9 -4
- package/esm/presentation/localization/bundles/uk-UA.localization-bundle.d.ts +6 -1
- package/esm/presentation/localization/bundles/uk-UA.localization-bundle.d.ts.map +1 -1
- package/esm/presentation/localization/bundles/uk-UA.localization-bundle.js +18 -13
- package/esm/presentation/localization/bundles/vi-VN.localization-bundle.d.ts +6 -1
- package/esm/presentation/localization/bundles/vi-VN.localization-bundle.d.ts.map +1 -1
- package/esm/presentation/localization/bundles/vi-VN.localization-bundle.js +9 -4
- package/esm/presentation/localization/bundles/zh-HK.localization-bundle.d.ts +6 -1
- package/esm/presentation/localization/bundles/zh-HK.localization-bundle.d.ts.map +1 -1
- package/esm/presentation/localization/bundles/zh-HK.localization-bundle.js +10 -5
- package/esm/presentation/localization/bundles/zh-Hans.localization-bundle.d.ts +6 -1
- package/esm/presentation/localization/bundles/zh-Hans.localization-bundle.d.ts.map +1 -1
- package/esm/presentation/localization/bundles/zh-Hans.localization-bundle.js +9 -4
- package/esm/presentation/localization/bundles/zh-Hant.localization-bundle.d.ts +6 -1
- package/esm/presentation/localization/bundles/zh-Hant.localization-bundle.d.ts.map +1 -1
- package/esm/presentation/localization/bundles/zh-Hant.localization-bundle.js +12 -7
- package/esm/presentation/topBar/buttonBar/button/saveButton/DefaultSaveButton.d.ts.map +1 -1
- package/esm/presentation/topBar/buttonBar/button/saveButton/DefaultSaveButton.js +3 -2
- package/esm/presentation/widget/description/ExportModeInsightWidgetDescription.d.ts.map +1 -1
- package/esm/presentation/widget/description/ExportModeInsightWidgetDescription.js +4 -11
- package/esm/presentation/widget/description/InsightWidgetDescriptionTrigger.d.ts.map +1 -1
- package/esm/presentation/widget/description/InsightWidgetDescriptionTrigger.js +4 -9
- package/esm/presentation/widget/description/types.d.ts +3 -5
- package/esm/presentation/widget/description/types.d.ts.map +1 -1
- package/esm/presentation/widget/description/useInsightWidgetDescription.d.ts.map +1 -1
- package/esm/presentation/widget/description/useInsightWidgetDescription.js +2 -5
- package/esm/presentation/widget/insight/ViewModeDashboardInsight/InsightDrillDialog/InsightDrillDialog.d.ts.map +1 -1
- package/esm/presentation/widget/insight/ViewModeDashboardInsight/InsightDrillDialog/InsightDrillDialog.js +5 -10
- package/esm/presentation/widget/insight/configuration/InsightDescriptionConfig/InsightDescription.d.ts +4 -3
- package/esm/presentation/widget/insight/configuration/InsightDescriptionConfig/InsightDescription.d.ts.map +1 -1
- package/esm/presentation/widget/insight/configuration/InsightDescriptionConfig/InsightDescription.js +5 -7
- package/esm/presentation/widget/insight/configuration/InsightDescriptionConfig/InsightDescriptionConfig.d.ts.map +1 -1
- package/esm/presentation/widget/insight/configuration/InsightDescriptionConfig/InsightDescriptionConfig.js +1 -3
- package/esm/presentation/widget/richText/EditModeDashboardRichText.d.ts.map +1 -1
- package/esm/presentation/widget/richText/EditModeDashboardRichText.js +5 -9
- package/esm/presentation/widget/richText/ViewModeDashboardRichText.d.ts.map +1 -1
- package/esm/presentation/widget/richText/ViewModeDashboardRichText.js +4 -10
- package/esm/sdk-ui-dashboard.d.ts +34 -60
- package/package.json +21 -21
- package/esm/model/commandHandlers/parameters/filterParameterDependenciesWorker.d.ts +0 -45
- package/esm/model/commandHandlers/parameters/filterParameterDependenciesWorker.d.ts.map +0 -1
- package/esm/model/commandHandlers/parameters/filterParameterDependenciesWorker.js +0 -99
- package/esm/model/commandHandlers/parameters/insightParameterDependenciesWorker.d.ts +0 -11
- package/esm/model/commandHandlers/parameters/insightParameterDependenciesWorker.d.ts.map +0 -1
- package/esm/model/commandHandlers/parameters/insightParameterDependenciesWorker.js +0 -71
- package/esm/model/commandHandlers/parameters/loadFilterParameterDependencies.d.ts +0 -22
- package/esm/model/commandHandlers/parameters/loadFilterParameterDependencies.d.ts.map +0 -1
- package/esm/model/commandHandlers/parameters/loadFilterParameterDependencies.js +0 -39
- package/esm/model/commandHandlers/parameters/loadInsightParameterDependencies.d.ts +0 -21
- package/esm/model/commandHandlers/parameters/loadInsightParameterDependencies.d.ts.map +0 -1
- package/esm/model/commandHandlers/parameters/loadInsightParameterDependencies.js +0 -86
|
@@ -30,8 +30,8 @@ import { uiActions } from "../../../store/ui/index.js";
|
|
|
30
30
|
import { unavailableObjectsActions } from "../../../store/unavailableObjects/index.js";
|
|
31
31
|
import { selectUnavailableObjects } from "../../../store/unavailableObjects/unavailableObjectsSelectors.js";
|
|
32
32
|
import { userActions } from "../../../store/user/index.js";
|
|
33
|
-
import {
|
|
34
|
-
import {
|
|
33
|
+
import { collectDashboardParameterRoots } from "../../parameters/dashboardParameterRoots.js";
|
|
34
|
+
import { loadParameterDependencies } from "../../parameters/loadParameterDependencies.js";
|
|
35
35
|
import { changeDashboardTimezoneOverrideHandler } from "../../timezone/changeDashboardTimezoneOverrideHandler.js";
|
|
36
36
|
import { applyDefaultFilterView } from "../common/filterViews.js";
|
|
37
37
|
import { actionsToInitializeExistingDashboard, actionsToInitializeNewDashboard, } from "../common/stateInitializers.js";
|
|
@@ -195,11 +195,11 @@ function* loadExistingDashboard(ctx, cmd, dashboardRef) {
|
|
|
195
195
|
// Note: activeTabLocalIdentifier is app state only, NOT persisted to/read from dashboard MD
|
|
196
196
|
const resolvedActiveTabId = resolveActiveTabId(dashboardWithFilterView.tabs, cmd.payload.initialTabId, undefined);
|
|
197
197
|
const dashboard = dashboardWithFilterView;
|
|
198
|
-
const
|
|
198
|
+
const enableParameters = config.settings?.enableParameters ?? false;
|
|
199
|
+
const [{ tabsAttributeFilterConfigs, tabsDateFilterConfig, tabsDateFilterConfigSource }, workspaceParameters, parameterDependencies,] = yield all([
|
|
199
200
|
call(getTabsFilterConfigs, dashboard, config, ctx, cmd),
|
|
200
201
|
call(loadWorkspaceParametersWithStatus, ctx, config.settings),
|
|
201
|
-
call(
|
|
202
|
-
call(loadFilterParameterDependencies, ctx, collectDashboardFilterContextItems(dashboard), config.settings?.enableParameters ?? false),
|
|
202
|
+
call(loadParameterDependencies, ctx, enableParameters ? collectDashboardParameterRoots(dashboard, insights) : []),
|
|
203
203
|
]);
|
|
204
204
|
const workspaceParametersList = Array.isArray(workspaceParameters) ? workspaceParameters : [];
|
|
205
205
|
const initActions = yield call(actionsToInitializeExistingDashboard, ctx, dashboard, insights, config.settings, config.settings.enableImmediateAttributeFilterDisplayAsLabelMigration ?? false, undefined, undefined, tabsAttributeFilterConfigs, tabsDateFilterConfig, tabsDateFilterConfigSource, createDisplayFormMap([], []), cmd.payload.persistedDashboard, resolvedActiveTabId, workspaceParametersList);
|
|
@@ -214,8 +214,13 @@ function* loadExistingDashboard(ctx, cmd, dashboardRef) {
|
|
|
214
214
|
permissionsActions.setPermissions(permissions),
|
|
215
215
|
catalogActions.setCatalogItems(catalogPayload),
|
|
216
216
|
catalogActions.setCatalogParameters(makeCatalogParametersPayload(workspaceParameters)),
|
|
217
|
-
catalogActions.
|
|
218
|
-
|
|
217
|
+
catalogActions.setCatalogParameterDependencies({
|
|
218
|
+
status: enableParameters ? "loaded" : "uninitialized",
|
|
219
|
+
byRoot: {},
|
|
220
|
+
requestedRoots: {},
|
|
221
|
+
}),
|
|
222
|
+
catalogActions.mergeCatalogParameterDependencies(parameterDependencies.byRoot),
|
|
223
|
+
catalogActions.markParameterDependenciesFailed(parameterDependencies.failedRoots),
|
|
219
224
|
...initActions,
|
|
220
225
|
// NOTE: Tab configs (dateFilterConfig, dateFilterConfigs, attributeFilterConfigs, filterContext)
|
|
221
226
|
// are now initialized as part of the tabs state in initActions via setTabs action
|
|
@@ -259,10 +264,8 @@ function* initializeNewDashboard(ctx, cmd) {
|
|
|
259
264
|
const { initActions, dashboard, insights } = yield call(actionsToInitializeNewDashboard, ctx, config.settings, dateFilterConfig, loadedCatalog
|
|
260
265
|
? createDisplayFormMapFromCatalog(loadedCatalog.catalog, loadedCatalog.computedAttributes)
|
|
261
266
|
: createDisplayFormMap([], []), cmd.payload.initialTabId, workspaceParametersList);
|
|
262
|
-
const
|
|
263
|
-
|
|
264
|
-
// resolve yet; this only records the status so the widgets do not wait for a load that never comes
|
|
265
|
-
const filterParameterDependencies = yield call(loadFilterParameterDependencies, ctx, [], config.settings?.enableParameters ?? false);
|
|
267
|
+
const enableParameters = config.settings?.enableParameters ?? false;
|
|
268
|
+
const parameterDependencies = yield call(loadParameterDependencies, ctx, enableParameters ? collectDashboardParameterRoots(dashboard, insights) : []);
|
|
266
269
|
const batch = batchActions([
|
|
267
270
|
backendCapabilitiesActions.setBackendCapabilities(backend.capabilities),
|
|
268
271
|
configActions.setConfig(config),
|
|
@@ -279,8 +282,13 @@ function* initializeNewDashboard(ctx, cmd) {
|
|
|
279
282
|
dateHierarchyTemplates: dateHierarchyTemplates,
|
|
280
283
|
}),
|
|
281
284
|
catalogActions.setCatalogParameters(makeCatalogParametersPayload(workspaceParameters)),
|
|
282
|
-
catalogActions.
|
|
283
|
-
|
|
285
|
+
catalogActions.setCatalogParameterDependencies({
|
|
286
|
+
status: enableParameters ? "loaded" : "uninitialized",
|
|
287
|
+
byRoot: {},
|
|
288
|
+
requestedRoots: {},
|
|
289
|
+
}),
|
|
290
|
+
catalogActions.mergeCatalogParameterDependencies(parameterDependencies.byRoot),
|
|
291
|
+
catalogActions.markParameterDependenciesFailed(parameterDependencies.failedRoots),
|
|
284
292
|
listedDashboardsActions.setListedDashboards(listedDashboards),
|
|
285
293
|
accessibleDashboardsActions.setAccessibleDashboards(listedDashboards),
|
|
286
294
|
executionResultsActions.clearAllExecutionResults(),
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { type IDashboard, type IInsight, type IdentifierRef } from "@gooddata/sdk-model";
|
|
2
|
+
/**
|
|
3
|
+
* Every dependency root the dashboard needs parameters for: its insights, text references, and
|
|
4
|
+
* dashboard filters across all tabs. Collected at initialization so one references call covers the
|
|
5
|
+
* whole dashboard.
|
|
6
|
+
*
|
|
7
|
+
* A widget whose insight did not load keeps its own description, which is what it renders.
|
|
8
|
+
*
|
|
9
|
+
* @internal
|
|
10
|
+
*/
|
|
11
|
+
export declare function collectDashboardParameterRoots(dashboard: IDashboard | undefined, insights: IInsight[]): IdentifierRef[];
|
|
12
|
+
/**
|
|
13
|
+
* The dependency roots of a text: the metrics and computed attributes it references, which the
|
|
14
|
+
* text executes and whose parameters therefore apply to it. Labels resolve through their own
|
|
15
|
+
* display form and parameters are never executed, so neither is a root.
|
|
16
|
+
*
|
|
17
|
+
* @internal
|
|
18
|
+
*/
|
|
19
|
+
export declare function collectTextReferenceRoots(content: string): IdentifierRef[];
|
|
20
|
+
//# sourceMappingURL=dashboardParameterRoots.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dashboardParameterRoots.d.ts","sourceRoot":"","sources":["../../../../src/model/commandHandlers/parameters/dashboardParameterRoots.ts"],"names":[],"mappings":"AAKA,OAAO,EACH,KAAK,UAAU,EAEf,KAAK,QAAQ,EACb,KAAK,aAAa,EAKrB,MAAM,qBAAqB,CAAC;AAS7B;;;;;;;;GAQG;AACH,wBAAgB,8BAA8B,CAC1C,SAAS,EAAE,UAAU,GAAG,SAAS,EACjC,QAAQ,EAAE,QAAQ,EAAE,GACrB,aAAa,EAAE,CA+BjB;AAED;;;;;;GAMG;AACH,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,MAAM,GAAG,aAAa,EAAE,CAM1E"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
// (C) 2026 GoodData Corporation
|
|
2
|
+
import { uniqBy } from "lodash-es";
|
|
3
|
+
import { walkLayout } from "@gooddata/sdk-backend-spi";
|
|
4
|
+
import { isIdentifierRef, isInsightWidget, isRichTextWidget, serializeObjRef, } from "@gooddata/sdk-model";
|
|
5
|
+
import { collectReferences } from "@gooddata/sdk-ui-kit";
|
|
6
|
+
import { insightWidgetDescription } from "../../../_staging/insight/insightWidgetDescription.js";
|
|
7
|
+
import { newInsightMap } from "../../../_staging/metadata/objRefMap.js";
|
|
8
|
+
import { collectFilterParameterRoots } from "../../store/tabs/parameters/parametersHelpers.js";
|
|
9
|
+
import { insightRoots } from "./loadParameterDependencies.js";
|
|
10
|
+
/**
|
|
11
|
+
* Every dependency root the dashboard needs parameters for: its insights, text references, and
|
|
12
|
+
* dashboard filters across all tabs. Collected at initialization so one references call covers the
|
|
13
|
+
* whole dashboard.
|
|
14
|
+
*
|
|
15
|
+
* A widget whose insight did not load keeps its own description, which is what it renders.
|
|
16
|
+
*
|
|
17
|
+
* @internal
|
|
18
|
+
*/
|
|
19
|
+
export function collectDashboardParameterRoots(dashboard, insights) {
|
|
20
|
+
const insightMap = newInsightMap(insights);
|
|
21
|
+
const roots = insightRoots(insights);
|
|
22
|
+
function textRoots(content) {
|
|
23
|
+
return content ? collectTextReferenceRoots(content) : [];
|
|
24
|
+
}
|
|
25
|
+
function widgetText(widget) {
|
|
26
|
+
if (isRichTextWidget(widget)) {
|
|
27
|
+
return widget.content;
|
|
28
|
+
}
|
|
29
|
+
return isInsightWidget(widget)
|
|
30
|
+
? insightWidgetDescription(widget, insightMap.get(widget.insight))
|
|
31
|
+
: undefined;
|
|
32
|
+
}
|
|
33
|
+
for (const layout of [dashboard?.layout, ...(dashboard?.tabs ?? []).map((tab) => tab.layout)]) {
|
|
34
|
+
if (layout) {
|
|
35
|
+
walkLayout(layout, {
|
|
36
|
+
sectionCallback: (section) => roots.push(...textRoots(section.header?.description)),
|
|
37
|
+
widgetCallback: (widget) => roots.push(...textRoots(widgetText(widget))),
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
const filters = [
|
|
42
|
+
...(dashboard?.tabs ?? []).flatMap((tab) => tab.filterContext?.filters ?? []),
|
|
43
|
+
...(dashboard?.filterContext?.filters ?? []),
|
|
44
|
+
];
|
|
45
|
+
roots.push(...collectFilterParameterRoots(filters));
|
|
46
|
+
return uniqBy(roots, serializeObjRef);
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* The dependency roots of a text: the metrics and computed attributes it references, which the
|
|
50
|
+
* text executes and whose parameters therefore apply to it. Labels resolve through their own
|
|
51
|
+
* display form and parameters are never executed, so neither is a root.
|
|
52
|
+
*
|
|
53
|
+
* @internal
|
|
54
|
+
*/
|
|
55
|
+
export function collectTextReferenceRoots(content) {
|
|
56
|
+
const roots = Object.values(collectReferences(content))
|
|
57
|
+
.filter(({ type }) => type === "measure" || type === "computedAttribute")
|
|
58
|
+
.map(({ ref }) => ref)
|
|
59
|
+
.filter(isIdentifierRef);
|
|
60
|
+
return uniqBy(roots, serializeObjRef);
|
|
61
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { type IInsight, type IdentifierRef } from "@gooddata/sdk-model";
|
|
2
|
+
import { type DashboardContext } from "../../types/commonTypes.js";
|
|
3
|
+
interface IParameterDependenciesLoadResult {
|
|
4
|
+
byRoot: Record<string, IdentifierRef[]>;
|
|
5
|
+
failedRoots: IdentifierRef[];
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Loads the root -> parameter dependencies of `roots` from the workspace references service.
|
|
9
|
+
*
|
|
10
|
+
* @remarks
|
|
11
|
+
* Walks the dependency graph in `direction: "down"` from each root, then collects the parameter
|
|
12
|
+
* nodes reachable from it through metrics and computed attributes. Each root is keyed by
|
|
13
|
+
* `serializeObjRef` of the ref exactly as it was supplied, so a caller looks its own refs up again.
|
|
14
|
+
* A batch the backend rejects for one unknown root is retried root by root, so the remaining roots
|
|
15
|
+
* stay available and only the rejected ones fail. Any other failure is endpoint-wide and fails every
|
|
16
|
+
* root at once.
|
|
17
|
+
*/
|
|
18
|
+
export declare function loadParameterDependencies(ctx: DashboardContext, roots: IdentifierRef[]): Promise<IParameterDependenciesLoadResult>;
|
|
19
|
+
/**
|
|
20
|
+
* The dependency roots of insights: their own refs, less the ones spelled by uri - the graph is
|
|
21
|
+
* walked by identifier.
|
|
22
|
+
*
|
|
23
|
+
* @internal
|
|
24
|
+
*/
|
|
25
|
+
export declare function insightRoots(insights: IInsight[]): IdentifierRef[];
|
|
26
|
+
export {};
|
|
27
|
+
//# sourceMappingURL=loadParameterDependencies.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loadParameterDependencies.d.ts","sourceRoot":"","sources":["../../../../src/model/commandHandlers/parameters/loadParameterDependencies.ts"],"names":[],"mappings":"AAGA,OAAO,EACH,KAAK,QAAQ,EACb,KAAK,aAAa,EAIrB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAE,KAAK,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAEnE,UAAU,gCAAgC;IACtC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,EAAE,CAAC,CAAC;IACxC,WAAW,EAAE,aAAa,EAAE,CAAC;CAChC;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,yBAAyB,CAC3C,GAAG,EAAE,gBAAgB,EACrB,KAAK,EAAE,aAAa,EAAE,GACvB,OAAO,CAAC,gCAAgC,CAAC,CAwB3C;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,QAAQ,EAAE,GAAG,aAAa,EAAE,CAElE"}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
// (C) 2026 GoodData Corporation
|
|
2
|
+
import { isUnexpectedResponseError } from "@gooddata/sdk-backend-spi";
|
|
3
|
+
import { insightRef, isIdentifierRef, serializeObjRef, } from "@gooddata/sdk-model";
|
|
4
|
+
/**
|
|
5
|
+
* Loads the root -> parameter dependencies of `roots` from the workspace references service.
|
|
6
|
+
*
|
|
7
|
+
* @remarks
|
|
8
|
+
* Walks the dependency graph in `direction: "down"` from each root, then collects the parameter
|
|
9
|
+
* nodes reachable from it through metrics and computed attributes. Each root is keyed by
|
|
10
|
+
* `serializeObjRef` of the ref exactly as it was supplied, so a caller looks its own refs up again.
|
|
11
|
+
* A batch the backend rejects for one unknown root is retried root by root, so the remaining roots
|
|
12
|
+
* stay available and only the rejected ones fail. Any other failure is endpoint-wide and fails every
|
|
13
|
+
* root at once.
|
|
14
|
+
*/
|
|
15
|
+
export async function loadParameterDependencies(ctx, roots) {
|
|
16
|
+
if (roots.length === 0) {
|
|
17
|
+
return { byRoot: {}, failedRoots: [] };
|
|
18
|
+
}
|
|
19
|
+
try {
|
|
20
|
+
return { byRoot: await loadReachableParameterMap(ctx, roots), failedRoots: [] };
|
|
21
|
+
}
|
|
22
|
+
catch (error) {
|
|
23
|
+
if (roots.length === 1 || !rejectsWholeBatch(error)) {
|
|
24
|
+
return { byRoot: {}, failedRoots: roots };
|
|
25
|
+
}
|
|
26
|
+
const results = await Promise.allSettled(roots.map((root) => loadReachableParameterMap(ctx, [root])));
|
|
27
|
+
const byRoot = {};
|
|
28
|
+
const failedRoots = [];
|
|
29
|
+
for (let i = 0; i < roots.length; i++) {
|
|
30
|
+
const result = results[i];
|
|
31
|
+
if (result.status === "fulfilled") {
|
|
32
|
+
Object.assign(byRoot, result.value);
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
failedRoots.push(roots[i]);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return { byRoot, failedRoots };
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* The dependency roots of insights: their own refs, less the ones spelled by uri - the graph is
|
|
43
|
+
* walked by identifier.
|
|
44
|
+
*
|
|
45
|
+
* @internal
|
|
46
|
+
*/
|
|
47
|
+
export function insightRoots(insights) {
|
|
48
|
+
return insights.map(insightRef).filter(isIdentifierRef);
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* The graph endpoint answers a batch holding one root it does not know with `400`, so the other
|
|
52
|
+
* roots are lost with it and only a per-root retry tells them apart. Every other failure - the
|
|
53
|
+
* endpoint down, the session gone - fails a retry the same way, for every root.
|
|
54
|
+
*/
|
|
55
|
+
function rejectsWholeBatch(error) {
|
|
56
|
+
return isUnexpectedResponseError(error) && error.httpStatus === 400;
|
|
57
|
+
}
|
|
58
|
+
async function loadReachableParameterMap(ctx, roots) {
|
|
59
|
+
const result = await ctx.backend
|
|
60
|
+
.workspace(ctx.workspace)
|
|
61
|
+
.references()
|
|
62
|
+
.getReferences(roots, { direction: "down" });
|
|
63
|
+
return buildReachableParameterMap(roots, result.edges);
|
|
64
|
+
}
|
|
65
|
+
function buildReachableParameterMap(roots, edges) {
|
|
66
|
+
const adjacency = buildAdjacency(edges);
|
|
67
|
+
const result = {};
|
|
68
|
+
for (const root of roots) {
|
|
69
|
+
result[serializeObjRef(root)] = reachableParameterRefs(graphInsightRef(root), adjacency);
|
|
70
|
+
}
|
|
71
|
+
return result;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Only insight roots arrive untyped, and the graph needs the type to start the walk. The map key
|
|
75
|
+
* keeps the ref as it was supplied, so the coercion never reaches it.
|
|
76
|
+
*/
|
|
77
|
+
function graphInsightRef(root) {
|
|
78
|
+
return root.type ? root : { ...root, type: "insight" };
|
|
79
|
+
}
|
|
80
|
+
function buildAdjacency(edges) {
|
|
81
|
+
const adjacency = new Map();
|
|
82
|
+
for (const edge of edges) {
|
|
83
|
+
const fromKey = serializeObjRef(edge.from);
|
|
84
|
+
const neighbors = adjacency.get(fromKey);
|
|
85
|
+
if (neighbors) {
|
|
86
|
+
neighbors.push(edge.to);
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
adjacency.set(fromKey, [edge.to]);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
return adjacency;
|
|
93
|
+
}
|
|
94
|
+
function reachableParameterRefs(start, adjacency) {
|
|
95
|
+
const parameters = [];
|
|
96
|
+
const visited = new Set([serializeObjRef(start)]);
|
|
97
|
+
const queue = [start];
|
|
98
|
+
for (let i = 0; i < queue.length; i++) {
|
|
99
|
+
for (const neighbor of adjacency.get(serializeObjRef(queue[i])) ?? []) {
|
|
100
|
+
const key = serializeObjRef(neighbor);
|
|
101
|
+
if (visited.has(key)) {
|
|
102
|
+
continue;
|
|
103
|
+
}
|
|
104
|
+
visited.add(key);
|
|
105
|
+
if (neighbor.type === "parameter") {
|
|
106
|
+
parameters.push(neighbor);
|
|
107
|
+
}
|
|
108
|
+
else {
|
|
109
|
+
queue.push(neighbor);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
return parameters;
|
|
114
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { type SagaIterator } from "redux-saga";
|
|
2
|
+
import { type IdentifierRef } from "@gooddata/sdk-model";
|
|
3
|
+
import { type DashboardContext } from "../../types/commonTypes.js";
|
|
4
|
+
export declare const requestParameterDependencies: import("@reduxjs/toolkit").ActionCreatorWithPayload<IdentifierRef[], string>;
|
|
5
|
+
export declare function newParameterDependenciesWorker(): (ctx: DashboardContext) => SagaIterator<void>;
|
|
6
|
+
//# sourceMappingURL=parameterDependenciesWorker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parameterDependenciesWorker.d.ts","sourceRoot":"","sources":["../../../../src/model/commandHandlers/parameters/parameterDependenciesWorker.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,YAAY,CAAC;AAG/C,OAAO,EAAiB,KAAK,aAAa,EAAmB,MAAM,qBAAqB,CAAC;AAYzF,OAAO,EAAE,KAAK,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAOnE,eAAO,MAAM,4BAA4B,8EAAiE,CAAC;AAM3G,wBAAgB,8BAA8B,UACQ,gBAAgB,KAAG,YAAY,CAAC,IAAI,CAAC,CAM1F"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
// (C) 2026 GoodData Corporation
|
|
2
|
+
import { createAction } from "@reduxjs/toolkit";
|
|
3
|
+
import { uniqBy } from "lodash-es";
|
|
4
|
+
import { batchActions } from "redux-batched-actions";
|
|
5
|
+
import { call, put, select, takeEvery } from "redux-saga/effects";
|
|
6
|
+
import { serializeObjRef } from "@gooddata/sdk-model";
|
|
7
|
+
import { selectCatalogParameterDependencies, selectCatalogParameterDependenciesStatus, selectCatalogRequestedParameterRoots, } from "../../store/catalog/catalogSelectors.js";
|
|
8
|
+
import { catalogActions } from "../../store/catalog/index.js";
|
|
9
|
+
import { insightsActions } from "../../store/insights/index.js";
|
|
10
|
+
import { selectFiltersByTab } from "../../store/tabs/filterContext/filterContextSelectors.js";
|
|
11
|
+
import { tabsActions } from "../../store/tabs/index.js";
|
|
12
|
+
import { collectFilterParameterRoots } from "../../store/tabs/parameters/parametersHelpers.js";
|
|
13
|
+
import { insightRoots, loadParameterDependencies } from "./loadParameterDependencies.js";
|
|
14
|
+
const TABS_ACTION_PREFIX = `${tabsActions.setTabs.type.split("/")[0]}/`;
|
|
15
|
+
export const requestParameterDependencies = createAction("parameterDependencies/request");
|
|
16
|
+
export function newParameterDependenciesWorker() {
|
|
17
|
+
return function* parameterDependenciesWorker(ctx) {
|
|
18
|
+
const generation = { current: 0 };
|
|
19
|
+
yield takeEvery(writesParameterDependencyInputs, function* onInputsWritten(action) {
|
|
20
|
+
yield call(updateParameterDependencies, ctx, generation, action);
|
|
21
|
+
});
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
function* updateParameterDependencies(ctx, generation, action) {
|
|
25
|
+
const actions = unbatched(action);
|
|
26
|
+
if (actions.some(catalogActions.setCatalogParameterDependencies.match)) {
|
|
27
|
+
generation.current += 1;
|
|
28
|
+
}
|
|
29
|
+
const explicitlyRequestedRoots = actions.flatMap(requestedRootsOf);
|
|
30
|
+
const status = yield select(selectCatalogParameterDependenciesStatus);
|
|
31
|
+
if (status !== "loaded") {
|
|
32
|
+
if (explicitlyRequestedRoots.length > 0) {
|
|
33
|
+
yield put(catalogActions.markParameterDependenciesFailed(explicitlyRequestedRoots));
|
|
34
|
+
}
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
const known = yield select(selectCatalogParameterDependencies);
|
|
38
|
+
const requested = yield select(selectCatalogRequestedParameterRoots);
|
|
39
|
+
const refreshRoots = insightRoots(actions.flatMap(writtenInsightsOf));
|
|
40
|
+
const requestedRoots = [
|
|
41
|
+
...insightRoots(actions.flatMap(replacedInsightsOf)),
|
|
42
|
+
...explicitlyRequestedRoots,
|
|
43
|
+
];
|
|
44
|
+
if (actions.some(writesTabs)) {
|
|
45
|
+
const filtersByTab = yield select(selectFiltersByTab);
|
|
46
|
+
requestedRoots.push(...collectFilterParameterRoots(Object.values(filtersByTab).flat()));
|
|
47
|
+
}
|
|
48
|
+
const unknownRoots = requestedRoots.filter((root) => {
|
|
49
|
+
const key = serializeObjRef(root);
|
|
50
|
+
return !(key in known) && !(key in requested);
|
|
51
|
+
});
|
|
52
|
+
const roots = uniqBy([...refreshRoots, ...unknownRoots], serializeObjRef);
|
|
53
|
+
yield call(loadAndMergeParameterDependencies, ctx, generation, roots);
|
|
54
|
+
}
|
|
55
|
+
function* loadAndMergeParameterDependencies(ctx, generation, roots) {
|
|
56
|
+
if (roots.length === 0) {
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
const requestGeneration = generation.current;
|
|
60
|
+
yield put(catalogActions.markParameterDependenciesPending(roots));
|
|
61
|
+
const loaded = yield call(loadParameterDependencies, ctx, roots);
|
|
62
|
+
if (generation.current !== requestGeneration) {
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
yield put(batchActions([
|
|
66
|
+
catalogActions.mergeCatalogParameterDependencies(loaded.byRoot),
|
|
67
|
+
catalogActions.markParameterDependenciesFailed(loaded.failedRoots),
|
|
68
|
+
]));
|
|
69
|
+
}
|
|
70
|
+
function writesParameterDependencyInputs(action) {
|
|
71
|
+
return unbatched(action).some((item) => catalogActions.setCatalogParameterDependencies.match(item) ||
|
|
72
|
+
requestParameterDependencies.match(item) ||
|
|
73
|
+
writtenInsightsOf(item).length > 0 ||
|
|
74
|
+
replacedInsightsOf(item).length > 0 ||
|
|
75
|
+
writesTabs(item));
|
|
76
|
+
}
|
|
77
|
+
function requestedRootsOf(action) {
|
|
78
|
+
return requestParameterDependencies.match(action) ? action.payload : [];
|
|
79
|
+
}
|
|
80
|
+
function writtenInsightsOf(action) {
|
|
81
|
+
if (insightsActions.addInsights.match(action)) {
|
|
82
|
+
return entityPayloadInsights(action.payload);
|
|
83
|
+
}
|
|
84
|
+
if (insightsActions.upsertInsight.match(action)) {
|
|
85
|
+
return [action.payload];
|
|
86
|
+
}
|
|
87
|
+
return [];
|
|
88
|
+
}
|
|
89
|
+
function replacedInsightsOf(action) {
|
|
90
|
+
return insightsActions.setInsights.match(action) ? entityPayloadInsights(action.payload) : [];
|
|
91
|
+
}
|
|
92
|
+
function entityPayloadInsights(payload) {
|
|
93
|
+
return Array.isArray(payload) ? [...payload] : Object.values(payload);
|
|
94
|
+
}
|
|
95
|
+
function writesTabs(action) {
|
|
96
|
+
return action.type.startsWith(TABS_ACTION_PREFIX);
|
|
97
|
+
}
|
|
98
|
+
function unbatched(action) {
|
|
99
|
+
return isBatchAction(action) ? action.payload.flatMap(unbatched) : [action];
|
|
100
|
+
}
|
|
101
|
+
function isBatchAction(action) {
|
|
102
|
+
return ("meta" in action &&
|
|
103
|
+
typeof action.meta === "object" &&
|
|
104
|
+
action.meta !== null &&
|
|
105
|
+
"batch" in action.meta &&
|
|
106
|
+
action.meta.batch === true);
|
|
107
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useInitializeDashboardStore.d.ts","sourceRoot":"","sources":["../../../src/model/react/useInitializeDashboardStore.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"useInitializeDashboardStore.d.ts","sourceRoot":"","sources":["../../../src/model/react/useInitializeDashboardStore.ts"],"names":[],"mappings":"AAuBA,OAAO,EAAE,KAAK,sBAAsB,EAAwB,MAAM,4BAA4B,CAAC;AAI/F,OAAO,EAAE,KAAK,4BAA4B,EAAE,MAAM,YAAY,CAAC;AA6D/D;;;;;;GAMG;AACH,eAAO,MAAM,2BAA2B,UAC7B,4BAA4B,KACpC,sBAAsB,GAAG,IA2G3B,CAAC"}
|
|
@@ -6,8 +6,7 @@ import { enrichMapboxToken, useMapboxToken } from "@gooddata/sdk-ui-geo";
|
|
|
6
6
|
import { enrichAgGridToken, useAgGridToken } from "@gooddata/sdk-ui-pivot/next";
|
|
7
7
|
import { shallowEqualObjects } from "@gooddata/util";
|
|
8
8
|
import { newDashboardSummaryWorkflowWorker } from "../commandHandlers/dashboard/dashboardSummaryWorkflowWorker.js";
|
|
9
|
-
import {
|
|
10
|
-
import { newInsightParameterDependenciesWorker } from "../commandHandlers/parameters/insightParameterDependenciesWorker.js";
|
|
9
|
+
import { newParameterDependenciesWorker } from "../commandHandlers/parameters/parameterDependenciesWorker.js";
|
|
11
10
|
import { newRenderingWorker } from "../commandHandlers/render/renderingWorker.js";
|
|
12
11
|
import { InitialLoadCorrelationId, initializeDashboardWithPersistedDashboard, } from "../commands/dashboard.js";
|
|
13
12
|
import { dashboardDeinitialized } from "../events/dashboard.js";
|
|
@@ -113,8 +112,7 @@ export const useInitializeDashboardStore = (props) => {
|
|
|
113
112
|
isExport: config?.isExport,
|
|
114
113
|
}),
|
|
115
114
|
newDashboardSummaryWorkflowWorker(),
|
|
116
|
-
|
|
117
|
-
newFilterParameterDependenciesWorker(),
|
|
115
|
+
newParameterDependenciesWorker(),
|
|
118
116
|
];
|
|
119
117
|
// Create new store and fire load dashboard command.
|
|
120
118
|
const newDashboardStore = createDashboardStore({
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { type IExecutionConfig, type IInsight, type ObjRef } from "@gooddata/sdk-model";
|
|
2
|
+
/**
|
|
3
|
+
* @internal
|
|
4
|
+
*/
|
|
5
|
+
export interface ITextParameters {
|
|
6
|
+
execConfig: IExecutionConfig;
|
|
7
|
+
parameterDisplayValues: ReadonlyMap<string, string> | undefined;
|
|
8
|
+
loading: boolean;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* What a text needs from the parameters of the dashboard.
|
|
12
|
+
*
|
|
13
|
+
* `execConfig` is the execution config for the references the text resolves: the dashboard-level
|
|
14
|
+
* settings plus the parameters the referenced metrics and computed attributes depend on, so a number
|
|
15
|
+
* in a text reads the same as the chart beside it.
|
|
16
|
+
*
|
|
17
|
+
* `parameterDisplayValues` is the text every parameter shows in a `{parameter/<id>}` reference, by
|
|
18
|
+
* parameter identifier. It is `undefined` where the dashboard resolves no parameters at all, or where
|
|
19
|
+
* the workspace parameters did not load, so the host passes nothing on and the token stays as it was
|
|
20
|
+
* typed. A failed load must not show every parameter as unknown.
|
|
21
|
+
*
|
|
22
|
+
* `loading` is true while a root the text references, or a root of a dashboard filter that applies to
|
|
23
|
+
* the text, is neither in the map nor marked failed. The host defers the execution until then, so a
|
|
24
|
+
* reference is never executed without the parameters it depends on and then executed again with them.
|
|
25
|
+
*
|
|
26
|
+
* @param content - the text whose references are executed
|
|
27
|
+
* @param ref - the widget hosting the text; `undefined` for a host outside any widget, which takes
|
|
28
|
+
* the active tab
|
|
29
|
+
* @param insight - the insight the host shows, whose authored values take part in the resolution and
|
|
30
|
+
* whose own filters the text executes under, so its dependencies apply too
|
|
31
|
+
* @internal
|
|
32
|
+
*/
|
|
33
|
+
export declare function useTextParameters(content: string, ref?: ObjRef, insight?: IInsight): ITextParameters;
|
|
34
|
+
//# sourceMappingURL=useTextParameters.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useTextParameters.d.ts","sourceRoot":"","sources":["../../../src/model/react/useTextParameters.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,gBAAgB,EAAE,KAAK,QAAQ,EAAE,KAAK,MAAM,EAAmB,MAAM,qBAAqB,CAAC;AAkBzG;;GAEG;AACH,MAAM,WAAW,eAAe;IAC5B,UAAU,EAAE,gBAAgB,CAAC;IAC7B,sBAAsB,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,CAAC;IAChE,OAAO,EAAE,OAAO,CAAC;CACpB;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,QAAQ,GAAG,eAAe,CA6DpG"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
// (C) 2026 GoodData Corporation
|
|
2
|
+
import { useEffect, useMemo } from "react";
|
|
3
|
+
import { serializeObjRef } from "@gooddata/sdk-model";
|
|
4
|
+
import { collectTextReferenceRoots } from "../commandHandlers/parameters/dashboardParameterRoots.js";
|
|
5
|
+
import { insightRoots } from "../commandHandlers/parameters/loadParameterDependencies.js";
|
|
6
|
+
import { requestParameterDependencies } from "../commandHandlers/parameters/parameterDependenciesWorker.js";
|
|
7
|
+
import { selectCatalogParametersIsLoaded, selectCatalogRequestedParameterRoots, } from "../store/catalog/catalogSelectors.js";
|
|
8
|
+
import { resolveEffectiveParameterValuesForRoots, resolveParameterDisplayValues, } from "../store/tabs/parameters/parametersHelpers.js";
|
|
9
|
+
import { selectWidgetParameterContext } from "../store/tabs/parameters/parametersSelectors.js";
|
|
10
|
+
import { useDashboardDispatch, useDashboardSelector } from "./DashboardStoreProvider.js";
|
|
11
|
+
import { useDashboardExecConfig } from "./useWidgetExecConfig.js";
|
|
12
|
+
/**
|
|
13
|
+
* What a text needs from the parameters of the dashboard.
|
|
14
|
+
*
|
|
15
|
+
* `execConfig` is the execution config for the references the text resolves: the dashboard-level
|
|
16
|
+
* settings plus the parameters the referenced metrics and computed attributes depend on, so a number
|
|
17
|
+
* in a text reads the same as the chart beside it.
|
|
18
|
+
*
|
|
19
|
+
* `parameterDisplayValues` is the text every parameter shows in a `{parameter/<id>}` reference, by
|
|
20
|
+
* parameter identifier. It is `undefined` where the dashboard resolves no parameters at all, or where
|
|
21
|
+
* the workspace parameters did not load, so the host passes nothing on and the token stays as it was
|
|
22
|
+
* typed. A failed load must not show every parameter as unknown.
|
|
23
|
+
*
|
|
24
|
+
* `loading` is true while a root the text references, or a root of a dashboard filter that applies to
|
|
25
|
+
* the text, is neither in the map nor marked failed. The host defers the execution until then, so a
|
|
26
|
+
* reference is never executed without the parameters it depends on and then executed again with them.
|
|
27
|
+
*
|
|
28
|
+
* @param content - the text whose references are executed
|
|
29
|
+
* @param ref - the widget hosting the text; `undefined` for a host outside any widget, which takes
|
|
30
|
+
* the active tab
|
|
31
|
+
* @param insight - the insight the host shows, whose authored values take part in the resolution and
|
|
32
|
+
* whose own filters the text executes under, so its dependencies apply too
|
|
33
|
+
* @internal
|
|
34
|
+
*/
|
|
35
|
+
export function useTextParameters(content, ref, insight) {
|
|
36
|
+
const dashboardExecConfig = useDashboardExecConfig();
|
|
37
|
+
const parameterContext = useDashboardSelector(selectWidgetParameterContext(ref));
|
|
38
|
+
const requestedRoots = useDashboardSelector(selectCatalogRequestedParameterRoots);
|
|
39
|
+
const isCatalogLoaded = useDashboardSelector(selectCatalogParametersIsLoaded);
|
|
40
|
+
const dispatch = useDashboardDispatch();
|
|
41
|
+
// the host executes the text under the insight's own filters, so the text depends on whatever
|
|
42
|
+
// the insight depends on, the same root the chart resolves
|
|
43
|
+
const roots = useMemo(() => insight
|
|
44
|
+
? [...collectTextReferenceRoots(content), ...insightRoots([insight])]
|
|
45
|
+
: collectTextReferenceRoots(content), [content, insight]);
|
|
46
|
+
const missingRoots = useMemo(() => parameterContext
|
|
47
|
+
? [...roots, ...parameterContext.filterRoots].filter((root) => !(serializeObjRef(root) in parameterContext.dependenciesByRoot))
|
|
48
|
+
: [], [roots, parameterContext]);
|
|
49
|
+
// a text edited here, shown for an insight the dashboard did not load with, or under a filter
|
|
50
|
+
// added later has roots the initial references call never saw; the worker loads them
|
|
51
|
+
useEffect(() => {
|
|
52
|
+
const rootsToRequest = missingRoots.filter((root) => !(serializeObjRef(root) in requestedRoots));
|
|
53
|
+
if (rootsToRequest.length > 0) {
|
|
54
|
+
dispatch(requestParameterDependencies(rootsToRequest));
|
|
55
|
+
}
|
|
56
|
+
}, [missingRoots, requestedRoots, dispatch]);
|
|
57
|
+
const parameterValues = useMemo(() => resolveEffectiveParameterValuesForRoots(parameterContext, roots, insight), [parameterContext, roots, insight]);
|
|
58
|
+
const execConfig = useMemo(() => ({
|
|
59
|
+
...dashboardExecConfig,
|
|
60
|
+
// omit when empty so it does not bust the execution's defFingerprint
|
|
61
|
+
...(parameterValues.length > 0 ? { parameterValues } : {}),
|
|
62
|
+
}), [dashboardExecConfig, parameterValues]);
|
|
63
|
+
const parameterDisplayValues = useMemo(() => parameterContext && isCatalogLoaded
|
|
64
|
+
? resolveParameterDisplayValues(parameterContext, insight)
|
|
65
|
+
: undefined, [parameterContext, isCatalogLoaded, insight]);
|
|
66
|
+
const loading = useMemo(() => missingRoots.some((root) => requestedRoots[serializeObjRef(root)] !== "failed"), [missingRoots, requestedRoots]);
|
|
67
|
+
return useMemo(() => ({ execConfig, parameterDisplayValues, loading }), [execConfig, parameterDisplayValues, loading]);
|
|
68
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useWidgetExecConfig.d.ts","sourceRoot":"","sources":["../../../src/model/react/useWidgetExecConfig.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,gBAAgB,EAAE,KAAK,QAAQ,EAAE,KAAK,MAAM,
|
|
1
|
+
{"version":3,"file":"useWidgetExecConfig.d.ts","sourceRoot":"","sources":["../../../src/model/react/useWidgetExecConfig.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,gBAAgB,EAAE,KAAK,QAAQ,EAAE,KAAK,MAAM,EAAc,MAAM,qBAAqB,CAAC;AASpG;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,IAAI,gBAAgB,CAWzD;AAED;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,GAAG,gBAAgB,CAepF"}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
// (C) 2026 GoodData Corporation
|
|
2
2
|
import { useMemo } from "react";
|
|
3
|
+
import { insightRef } from "@gooddata/sdk-model";
|
|
3
4
|
import { selectEffectiveDashboardTimezone } from "../store/meta/metaSelectors.js";
|
|
4
|
-
import {
|
|
5
|
+
import { resolveEffectiveParameterValuesForRoots } from "../store/tabs/parameters/parametersHelpers.js";
|
|
5
6
|
import { selectWidgetParameterContext } from "../store/tabs/parameters/parametersSelectors.js";
|
|
6
7
|
import { selectExecutionTimestamp } from "../store/ui/uiSelectors.js";
|
|
7
8
|
import { useDashboardSelector } from "./DashboardStoreProvider.js";
|
|
@@ -34,7 +35,7 @@ export function useDashboardExecConfig() {
|
|
|
34
35
|
export function useWidgetExecConfig(ref, insight) {
|
|
35
36
|
const dashboardExecConfig = useDashboardExecConfig();
|
|
36
37
|
const parameterContext = useDashboardSelector(selectWidgetParameterContext(ref));
|
|
37
|
-
const parameterValues = useMemo(() =>
|
|
38
|
+
const parameterValues = useMemo(() => resolveEffectiveParameterValuesForRoots(parameterContext, [insightRef(insight)], insight), [parameterContext, insight]);
|
|
38
39
|
return useMemo(() => ({
|
|
39
40
|
...dashboardExecConfig,
|
|
40
41
|
// omit when empty so it does not bust the execution's defFingerprint
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type Action, type CaseReducer } from "@reduxjs/toolkit";
|
|
2
2
|
import { type ICatalogAttribute, type ICatalogAttributeHierarchy, type ICatalogComputedAttribute, type ICatalogDateDataset, type ICatalogFact, type ICatalogMeasure, type IDateHierarchyTemplate, type IdentifierRef } from "@gooddata/sdk-model";
|
|
3
|
-
import { type CatalogState, type
|
|
3
|
+
import { type CatalogState, type ICatalogParameterDependenciesState, type ICatalogParametersState } from "./catalogState.js";
|
|
4
4
|
type CatalogReducer<A extends Action> = CaseReducer<CatalogState, A>;
|
|
5
5
|
/**
|
|
6
6
|
* @public
|
|
@@ -46,20 +46,20 @@ export declare const catalogReducers: {
|
|
|
46
46
|
payload: ICatalogParametersState;
|
|
47
47
|
type: string;
|
|
48
48
|
}>;
|
|
49
|
-
|
|
50
|
-
payload:
|
|
49
|
+
setCatalogParameterDependencies: CatalogReducer<{
|
|
50
|
+
payload: ICatalogParameterDependenciesState;
|
|
51
51
|
type: string;
|
|
52
52
|
}>;
|
|
53
|
-
|
|
53
|
+
mergeCatalogParameterDependencies: CatalogReducer<{
|
|
54
54
|
payload: Record<string, IdentifierRef[]>;
|
|
55
55
|
type: string;
|
|
56
56
|
}>;
|
|
57
|
-
|
|
58
|
-
payload:
|
|
57
|
+
markParameterDependenciesPending: CatalogReducer<{
|
|
58
|
+
payload: IdentifierRef[];
|
|
59
59
|
type: string;
|
|
60
60
|
}>;
|
|
61
|
-
|
|
62
|
-
payload:
|
|
61
|
+
markParameterDependenciesFailed: CatalogReducer<{
|
|
62
|
+
payload: IdentifierRef[];
|
|
63
63
|
type: string;
|
|
64
64
|
}>;
|
|
65
65
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"catalogReducers.d.ts","sourceRoot":"","sources":["../../../../src/model/store/catalog/catalogReducers.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,MAAM,EAAE,KAAK,WAAW,EAAsB,MAAM,kBAAkB,CAAC;AAErF,OAAO,EACH,KAAK,iBAAiB,EACtB,KAAK,0BAA0B,EAC/B,KAAK,yBAAyB,EAC9B,KAAK,mBAAmB,EACxB,KAAK,YAAY,EACjB,KAAK,eAAe,EACpB,KAAK,sBAAsB,EAC3B,KAAK,aAAa,
|
|
1
|
+
{"version":3,"file":"catalogReducers.d.ts","sourceRoot":"","sources":["../../../../src/model/store/catalog/catalogReducers.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,MAAM,EAAE,KAAK,WAAW,EAAsB,MAAM,kBAAkB,CAAC;AAErF,OAAO,EACH,KAAK,iBAAiB,EACtB,KAAK,0BAA0B,EAC/B,KAAK,yBAAyB,EAC9B,KAAK,mBAAmB,EACxB,KAAK,YAAY,EACjB,KAAK,eAAe,EACpB,KAAK,sBAAsB,EAC3B,KAAK,aAAa,EAErB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACH,KAAK,YAAY,EACjB,KAAK,kCAAkC,EACvC,KAAK,uBAAuB,EAC/B,MAAM,mBAAmB,CAAC;AAE3B,KAAK,cAAc,CAAC,CAAC,SAAS,MAAM,IAAI,WAAW,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC;AAErE;;GAEG;AACH,MAAM,MAAM,sBAAsB,GAAG;IACjC,UAAU,CAAC,EAAE,iBAAiB,EAAE,CAAC;IACjC,QAAQ,CAAC,EAAE,eAAe,EAAE,CAAC;IAC7B,KAAK,CAAC,EAAE,YAAY,EAAE,CAAC;IACvB,YAAY,CAAC,EAAE,mBAAmB,EAAE,CAAC;IACrC,oBAAoB,CAAC,EAAE,0BAA0B,EAAE,CAAC;IACpD,kBAAkB,CAAC,EAAE,yBAAyB,EAAE,CAAC;IACjD,sBAAsB,CAAC,EAAE,sBAAsB,EAAE,CAAC;CACrD,CAAC;AAsBF;;GAEG;AACH,MAAM,MAAM,iCAAiC,GAAG;IAC5C,QAAQ,EAAE,eAAe,EAAE,CAAC;IAC5B,KAAK,EAAE,YAAY,EAAE,CAAC;CACzB,CAAC;AAiFF,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAW3B,CAAC"}
|