@gooddata/sdk-ui-dashboard 11.42.0-alpha.2 → 11.42.0-alpha.4

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.
Files changed (135) hide show
  1. package/NOTICE +6 -6
  2. package/esm/__version.d.ts +1 -1
  3. package/esm/__version.js +1 -1
  4. package/esm/_staging/automation/index.d.ts +19 -1
  5. package/esm/_staging/automation/index.d.ts.map +1 -1
  6. package/esm/_staging/automation/index.js +64 -1
  7. package/esm/model/commandHandlers/parameters/changeParameterValuesHandler.d.ts.map +1 -1
  8. package/esm/model/commandHandlers/parameters/changeParameterValuesHandler.js +4 -1
  9. package/esm/model/commandHandlers/scheduledEmail/automationParametersRestore.d.ts +12 -0
  10. package/esm/model/commandHandlers/scheduledEmail/automationParametersRestore.d.ts.map +1 -0
  11. package/esm/model/commandHandlers/scheduledEmail/automationParametersRestore.js +26 -0
  12. package/esm/model/commandHandlers/scheduledEmail/initializeAutomationsHandler.d.ts.map +1 -1
  13. package/esm/model/commandHandlers/scheduledEmail/initializeAutomationsHandler.js +12 -1
  14. package/esm/model/commands/parameters.d.ts +6 -1
  15. package/esm/model/commands/parameters.d.ts.map +1 -1
  16. package/esm/model/commands/parameters.js +2 -1
  17. package/esm/model/store/tabs/parameters/parametersReducers.d.ts +4 -0
  18. package/esm/model/store/tabs/parameters/parametersReducers.d.ts.map +1 -1
  19. package/esm/model/store/tabs/parameters/parametersReducers.js +6 -6
  20. package/esm/presentation/automations/scheduledEmail/DefaultScheduledEmailDialog/DefaultScheduledEmailDialog.d.ts.map +1 -1
  21. package/esm/presentation/automations/scheduledEmail/DefaultScheduledEmailDialog/DefaultScheduledEmailDialog.js +16 -2
  22. package/esm/presentation/automations/scheduledEmail/DefaultScheduledEmailDialog/hooks/useEditScheduledEmail.d.ts +2 -1
  23. package/esm/presentation/automations/scheduledEmail/DefaultScheduledEmailDialog/hooks/useEditScheduledEmail.d.ts.map +1 -1
  24. package/esm/presentation/automations/scheduledEmail/DefaultScheduledEmailDialog/hooks/useEditScheduledEmail.js +32 -12
  25. package/esm/presentation/automations/shared/automationFilters/automationParameters.d.ts +33 -1
  26. package/esm/presentation/automations/shared/automationFilters/automationParameters.d.ts.map +1 -1
  27. package/esm/presentation/automations/shared/automationFilters/automationParameters.js +52 -0
  28. package/esm/presentation/automations/shared/automationFilters/components/AutomationFiltersSelect.d.ts +27 -3
  29. package/esm/presentation/automations/shared/automationFilters/components/AutomationFiltersSelect.d.ts.map +1 -1
  30. package/esm/presentation/automations/shared/automationFilters/components/AutomationFiltersSelect.js +44 -12
  31. package/esm/presentation/automations/shared/automationFilters/components/AutomationParameter.d.ts +2 -1
  32. package/esm/presentation/automations/shared/automationFilters/components/AutomationParameter.d.ts.map +1 -1
  33. package/esm/presentation/automations/shared/automationFilters/components/AutomationParameter.js +7 -1
  34. package/esm/presentation/automations/shared/automationFilters/hooks/useValidateExistingAutomationFilters.d.ts +23 -1
  35. package/esm/presentation/automations/shared/automationFilters/hooks/useValidateExistingAutomationFilters.d.ts.map +1 -1
  36. package/esm/presentation/automations/shared/automationFilters/hooks/useValidateExistingAutomationFilters.js +93 -2
  37. package/esm/presentation/automations/shared/automationFilters/useAutomationExportParameters.d.ts +75 -0
  38. package/esm/presentation/automations/shared/automationFilters/useAutomationExportParameters.d.ts.map +1 -0
  39. package/esm/presentation/automations/shared/automationFilters/useAutomationExportParameters.js +143 -0
  40. package/esm/presentation/automations/shared/automationFilters/useAutomationFilters.d.ts +1 -0
  41. package/esm/presentation/automations/shared/automationFilters/useAutomationFilters.d.ts.map +1 -1
  42. package/esm/presentation/automations/shared/automationFilters/useAutomationFilters.js +1 -0
  43. package/esm/presentation/automations/shared/automationFilters/useAutomationFiltersSelect.d.ts.map +1 -1
  44. package/esm/presentation/automations/shared/automationFilters/useAutomationFiltersSelect.js +15 -2
  45. package/esm/presentation/automations/shared/automationFilters/useParameterAnnouncements.d.ts +15 -0
  46. package/esm/presentation/automations/shared/automationFilters/useParameterAnnouncements.d.ts.map +1 -0
  47. package/esm/presentation/automations/shared/automationFilters/useParameterAnnouncements.js +28 -0
  48. package/esm/presentation/localization/bundles/de-DE.localization-bundle.d.ts +4 -0
  49. package/esm/presentation/localization/bundles/de-DE.localization-bundle.d.ts.map +1 -1
  50. package/esm/presentation/localization/bundles/de-DE.localization-bundle.js +4 -0
  51. package/esm/presentation/localization/bundles/en-AU.localization-bundle.d.ts +4 -0
  52. package/esm/presentation/localization/bundles/en-AU.localization-bundle.d.ts.map +1 -1
  53. package/esm/presentation/localization/bundles/en-AU.localization-bundle.js +4 -0
  54. package/esm/presentation/localization/bundles/en-GB.localization-bundle.d.ts +4 -0
  55. package/esm/presentation/localization/bundles/en-GB.localization-bundle.d.ts.map +1 -1
  56. package/esm/presentation/localization/bundles/en-GB.localization-bundle.js +4 -0
  57. package/esm/presentation/localization/bundles/en-US.localization-bundle.d.ts +16 -0
  58. package/esm/presentation/localization/bundles/en-US.localization-bundle.d.ts.map +1 -1
  59. package/esm/presentation/localization/bundles/en-US.localization-bundle.js +16 -0
  60. package/esm/presentation/localization/bundles/es-419.localization-bundle.d.ts +4 -0
  61. package/esm/presentation/localization/bundles/es-419.localization-bundle.d.ts.map +1 -1
  62. package/esm/presentation/localization/bundles/es-419.localization-bundle.js +4 -0
  63. package/esm/presentation/localization/bundles/es-ES.localization-bundle.d.ts +4 -0
  64. package/esm/presentation/localization/bundles/es-ES.localization-bundle.d.ts.map +1 -1
  65. package/esm/presentation/localization/bundles/es-ES.localization-bundle.js +4 -0
  66. package/esm/presentation/localization/bundles/fi-FI.localization-bundle.d.ts +4 -0
  67. package/esm/presentation/localization/bundles/fi-FI.localization-bundle.d.ts.map +1 -1
  68. package/esm/presentation/localization/bundles/fi-FI.localization-bundle.js +4 -0
  69. package/esm/presentation/localization/bundles/fr-CA.localization-bundle.d.ts +4 -0
  70. package/esm/presentation/localization/bundles/fr-CA.localization-bundle.d.ts.map +1 -1
  71. package/esm/presentation/localization/bundles/fr-CA.localization-bundle.js +4 -0
  72. package/esm/presentation/localization/bundles/fr-FR.localization-bundle.d.ts +4 -0
  73. package/esm/presentation/localization/bundles/fr-FR.localization-bundle.d.ts.map +1 -1
  74. package/esm/presentation/localization/bundles/fr-FR.localization-bundle.js +4 -0
  75. package/esm/presentation/localization/bundles/id-ID.localization-bundle.d.ts +4 -0
  76. package/esm/presentation/localization/bundles/id-ID.localization-bundle.d.ts.map +1 -1
  77. package/esm/presentation/localization/bundles/id-ID.localization-bundle.js +4 -0
  78. package/esm/presentation/localization/bundles/it-IT.localization-bundle.d.ts +4 -0
  79. package/esm/presentation/localization/bundles/it-IT.localization-bundle.d.ts.map +1 -1
  80. package/esm/presentation/localization/bundles/it-IT.localization-bundle.js +4 -0
  81. package/esm/presentation/localization/bundles/ja-JP.localization-bundle.d.ts +4 -0
  82. package/esm/presentation/localization/bundles/ja-JP.localization-bundle.d.ts.map +1 -1
  83. package/esm/presentation/localization/bundles/ja-JP.localization-bundle.js +4 -0
  84. package/esm/presentation/localization/bundles/ko-KR.localization-bundle.d.ts +4 -0
  85. package/esm/presentation/localization/bundles/ko-KR.localization-bundle.d.ts.map +1 -1
  86. package/esm/presentation/localization/bundles/ko-KR.localization-bundle.js +4 -0
  87. package/esm/presentation/localization/bundles/nl-NL.localization-bundle.d.ts +4 -0
  88. package/esm/presentation/localization/bundles/nl-NL.localization-bundle.d.ts.map +1 -1
  89. package/esm/presentation/localization/bundles/nl-NL.localization-bundle.js +4 -0
  90. package/esm/presentation/localization/bundles/pl-PL.localization-bundle.d.ts +4 -0
  91. package/esm/presentation/localization/bundles/pl-PL.localization-bundle.d.ts.map +1 -1
  92. package/esm/presentation/localization/bundles/pl-PL.localization-bundle.js +4 -0
  93. package/esm/presentation/localization/bundles/pt-BR.localization-bundle.d.ts +4 -0
  94. package/esm/presentation/localization/bundles/pt-BR.localization-bundle.d.ts.map +1 -1
  95. package/esm/presentation/localization/bundles/pt-BR.localization-bundle.js +4 -0
  96. package/esm/presentation/localization/bundles/pt-PT.localization-bundle.d.ts +4 -0
  97. package/esm/presentation/localization/bundles/pt-PT.localization-bundle.d.ts.map +1 -1
  98. package/esm/presentation/localization/bundles/pt-PT.localization-bundle.js +4 -0
  99. package/esm/presentation/localization/bundles/ru-RU.localization-bundle.d.ts +4 -0
  100. package/esm/presentation/localization/bundles/ru-RU.localization-bundle.d.ts.map +1 -1
  101. package/esm/presentation/localization/bundles/ru-RU.localization-bundle.js +4 -0
  102. package/esm/presentation/localization/bundles/sl-SI.localization-bundle.d.ts +4 -0
  103. package/esm/presentation/localization/bundles/sl-SI.localization-bundle.d.ts.map +1 -1
  104. package/esm/presentation/localization/bundles/sl-SI.localization-bundle.js +4 -0
  105. package/esm/presentation/localization/bundles/th-TH.localization-bundle.d.ts +4 -0
  106. package/esm/presentation/localization/bundles/th-TH.localization-bundle.d.ts.map +1 -1
  107. package/esm/presentation/localization/bundles/th-TH.localization-bundle.js +4 -0
  108. package/esm/presentation/localization/bundles/tr-TR.localization-bundle.d.ts +4 -0
  109. package/esm/presentation/localization/bundles/tr-TR.localization-bundle.d.ts.map +1 -1
  110. package/esm/presentation/localization/bundles/tr-TR.localization-bundle.js +4 -0
  111. package/esm/presentation/localization/bundles/uk-UA.localization-bundle.d.ts +4 -0
  112. package/esm/presentation/localization/bundles/uk-UA.localization-bundle.d.ts.map +1 -1
  113. package/esm/presentation/localization/bundles/uk-UA.localization-bundle.js +4 -0
  114. package/esm/presentation/localization/bundles/vi-VN.localization-bundle.d.ts +4 -0
  115. package/esm/presentation/localization/bundles/vi-VN.localization-bundle.d.ts.map +1 -1
  116. package/esm/presentation/localization/bundles/vi-VN.localization-bundle.js +4 -0
  117. package/esm/presentation/localization/bundles/zh-HK.localization-bundle.d.ts +4 -0
  118. package/esm/presentation/localization/bundles/zh-HK.localization-bundle.d.ts.map +1 -1
  119. package/esm/presentation/localization/bundles/zh-HK.localization-bundle.js +4 -0
  120. package/esm/presentation/localization/bundles/zh-Hans.localization-bundle.d.ts +4 -0
  121. package/esm/presentation/localization/bundles/zh-Hans.localization-bundle.d.ts.map +1 -1
  122. package/esm/presentation/localization/bundles/zh-Hans.localization-bundle.js +4 -0
  123. package/esm/presentation/localization/bundles/zh-Hant.localization-bundle.d.ts +4 -0
  124. package/esm/presentation/localization/bundles/zh-Hant.localization-bundle.d.ts.map +1 -1
  125. package/esm/presentation/localization/bundles/zh-Hant.localization-bundle.js +4 -0
  126. package/esm/presentation/widget/widget/InsightWidget/EditableDashboardInsightWidget.d.ts.map +1 -1
  127. package/esm/presentation/widget/widget/InsightWidget/EditableDashboardInsightWidget.js +10 -1
  128. package/esm/presentation/widget/widget/warningPartialResult/InsightWidgetWarningPartialResult.d.ts +5 -4
  129. package/esm/presentation/widget/widget/warningPartialResult/InsightWidgetWarningPartialResult.d.ts.map +1 -1
  130. package/esm/presentation/widget/widget/warningPartialResult/InsightWidgetWarningPartialResult.js +3 -3
  131. package/esm/sdk-ui-dashboard.d.ts +10 -1
  132. package/package.json +20 -20
  133. package/styles/css/main.css +1 -1
  134. package/styles/css/warningPartialResult.css +1 -1
  135. package/styles/scss/warningPartialResult.scss +1 -1
@@ -1,4 +1,4 @@
1
- import { type DashboardParameterMode, type IAutomationMetadataObjectDefinition, type IDashboardParameter, type IInsightParameterValue, type INumberParameterConstraints, type IParameterMetadataObject, type IdentifierRef } from "@gooddata/sdk-model";
1
+ import { type DashboardParameterMode, type IAutomationMetadataObjectDefinition, type IDashboardExportParameter, type IDashboardParameter, type IInsightParameterValue, type INumberParameterConstraints, type IParameterMetadataObject, type IdentifierRef } from "@gooddata/sdk-model";
2
2
  /**
3
3
  * A workspace parameter resolved for display and editing inside an automation (alert/schedule)
4
4
  * dialog. The `value` is the current effective value the headless run will capture.
@@ -19,6 +19,15 @@ export interface IAutomationParameter {
19
19
  * @internal
20
20
  */
21
21
  export declare function reconstructAutomationParametersFromValues(stored: IInsightParameterValue[], dashboardParameters: IDashboardParameter[], catalog: IParameterMetadataObject[]): IAutomationParameter[];
22
+ /**
23
+ * Stored export overrides ({@link IDashboardExportParameter}) carry the value as a string; it is
24
+ * parsed back to a number and non-finite values are dropped. Title, mode and constraints are
25
+ * re-derived from the current dashboard and workspace catalog, mirroring
26
+ * {@link reconstructAutomationParametersFromValues}.
27
+ *
28
+ * @internal
29
+ */
30
+ export declare function reconstructAutomationParametersFromExportParameters(stored: IDashboardExportParameter[], dashboardParameters: IDashboardParameter[], catalog: IParameterMetadataObject[]): IAutomationParameter[];
22
31
  /**
23
32
  * Parameters of unsupported types are dropped (cannot be rendered/clamped). Dashboard-`hidden`
24
33
  * and `readonly` ones are dropped too — once added they would derive back to an invisible or
@@ -34,4 +43,27 @@ export declare function availableAutomationParameters(catalog: IParameterMetadat
34
43
  * @internal
35
44
  */
36
45
  export declare function setAlertExecutionParameters(automation: IAutomationMetadataObjectDefinition, parameters: IInsightParameterValue[]): IAutomationMetadataObjectDefinition;
46
+ /**
47
+ * Encodes the display-ready chip set back to the neutral export wire shape ({id, value:string,
48
+ * title}). The full per-tab execution set (including `hidden` entries) is converted, not just the
49
+ * visible chips, so the server resolver does not drop omitted parameters to the workspace default.
50
+ *
51
+ * @internal
52
+ */
53
+ export declare function automationParametersToExportParameters(parameters: IAutomationParameter[]): IDashboardExportParameter[];
54
+ /**
55
+ * Encodes the per-tab execution sets to the neutral export wire shape, or `undefined` when
56
+ * `shouldStore` is false (feature off / store-filters unchecked — signals "omit the field; use
57
+ * latest defaults"). Inverse of {@link reconstructAutomationParametersFromExportParameters}.
58
+ *
59
+ * @internal
60
+ */
61
+ export declare function toEffectiveParametersByTab(parametersByTab: Record<string, IAutomationParameter[]>, shouldStore: boolean): Record<string, IDashboardExportParameter[]> | undefined;
62
+ /**
63
+ * The single home for "does this export persist its parameters": widget schedules always do (they
64
+ * have no store-filters checkbox), dashboard schedules follow the store-filters checkbox.
65
+ *
66
+ * @internal
67
+ */
68
+ export declare function shouldStoreExportParameters(isWidgetSchedule: boolean, storeFilters?: boolean): boolean;
37
69
  //# sourceMappingURL=automationParameters.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"automationParameters.d.ts","sourceRoot":"","sources":["../../../../../src/presentation/automations/shared/automationFilters/automationParameters.ts"],"names":[],"mappings":"AAEA,OAAO,EACH,KAAK,sBAAsB,EAE3B,KAAK,mCAAmC,EACxC,KAAK,mBAAmB,EACxB,KAAK,sBAAsB,EAC3B,KAAK,2BAA2B,EAChC,KAAK,wBAAwB,EAC7B,KAAK,aAAa,EAIrB,MAAM,qBAAqB,CAAC;AAE7B;;;;;GAKG;AACH,MAAM,WAAW,oBAAoB;IACjC,GAAG,EAAE,aAAa,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,sBAAsB,CAAC;IAC7B,WAAW,CAAC,EAAE,2BAA2B,CAAC;CAC7C;AAED;;;;;GAKG;AACH,wBAAgB,yCAAyC,CACrD,MAAM,EAAE,sBAAsB,EAAE,EAChC,mBAAmB,EAAE,mBAAmB,EAAE,EAC1C,OAAO,EAAE,wBAAwB,EAAE,GACpC,oBAAoB,EAAE,CAkBxB;AAED;;;;;;GAMG;AACH,wBAAgB,6BAA6B,CACzC,OAAO,EAAE,wBAAwB,EAAE,EACnC,QAAQ,EAAE,oBAAoB,EAAE,EAChC,mBAAmB,GAAE,mBAAmB,EAAO,EAC/C,qBAAqB,GAAE,sBAAsB,EAAO,GACrD,oBAAoB,EAAE,CAqCxB;AAED;;;;;GAKG;AACH,wBAAgB,2BAA2B,CACvC,UAAU,EAAE,mCAAmC,EAC/C,UAAU,EAAE,sBAAsB,EAAE,GACrC,mCAAmC,CAcrC"}
1
+ {"version":3,"file":"automationParameters.d.ts","sourceRoot":"","sources":["../../../../../src/presentation/automations/shared/automationFilters/automationParameters.ts"],"names":[],"mappings":"AAEA,OAAO,EACH,KAAK,sBAAsB,EAE3B,KAAK,mCAAmC,EACxC,KAAK,yBAAyB,EAC9B,KAAK,mBAAmB,EACxB,KAAK,sBAAsB,EAC3B,KAAK,2BAA2B,EAChC,KAAK,wBAAwB,EAC7B,KAAK,aAAa,EAIrB,MAAM,qBAAqB,CAAC;AAI7B;;;;;GAKG;AACH,MAAM,WAAW,oBAAoB;IACjC,GAAG,EAAE,aAAa,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,sBAAsB,CAAC;IAC7B,WAAW,CAAC,EAAE,2BAA2B,CAAC;CAC7C;AAED;;;;;GAKG;AACH,wBAAgB,yCAAyC,CACrD,MAAM,EAAE,sBAAsB,EAAE,EAChC,mBAAmB,EAAE,mBAAmB,EAAE,EAC1C,OAAO,EAAE,wBAAwB,EAAE,GACpC,oBAAoB,EAAE,CAkBxB;AAED;;;;;;;GAOG;AACH,wBAAgB,mDAAmD,CAC/D,MAAM,EAAE,yBAAyB,EAAE,EACnC,mBAAmB,EAAE,mBAAmB,EAAE,EAC1C,OAAO,EAAE,wBAAwB,EAAE,GACpC,oBAAoB,EAAE,CAMxB;AAED;;;;;;GAMG;AACH,wBAAgB,6BAA6B,CACzC,OAAO,EAAE,wBAAwB,EAAE,EACnC,QAAQ,EAAE,oBAAoB,EAAE,EAChC,mBAAmB,GAAE,mBAAmB,EAAO,EAC/C,qBAAqB,GAAE,sBAAsB,EAAO,GACrD,oBAAoB,EAAE,CAqCxB;AAED;;;;;GAKG;AACH,wBAAgB,2BAA2B,CACvC,UAAU,EAAE,mCAAmC,EAC/C,UAAU,EAAE,sBAAsB,EAAE,GACrC,mCAAmC,CAcrC;AAED;;;;;;GAMG;AACH,wBAAgB,sCAAsC,CAClD,UAAU,EAAE,oBAAoB,EAAE,GACnC,yBAAyB,EAAE,CAM7B;AAED;;;;;;GAMG;AACH,wBAAgB,0BAA0B,CACtC,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,oBAAoB,EAAE,CAAC,EACvD,WAAW,EAAE,OAAO,GACrB,MAAM,CAAC,MAAM,EAAE,yBAAyB,EAAE,CAAC,GAAG,SAAS,CASzD;AAED;;;;;GAKG;AACH,wBAAgB,2BAA2B,CAAC,gBAAgB,EAAE,OAAO,EAAE,YAAY,UAAQ,GAAG,OAAO,CAEpG"}
@@ -1,5 +1,6 @@
1
1
  // (C) 2026 GoodData Corporation
2
2
  import { DashboardParameterModeValues, isIdentifierRef, isNumberParameterDefinition, objRefToString, } from "@gooddata/sdk-model";
3
+ import { exportParametersToValues } from "../../../../_staging/automation/index.js";
3
4
  /**
4
5
  * Stored {@link IInsightParameterValue} overrides carry only {ref, value}; title, mode and
5
6
  * constraints are re-derived from the current dashboard and workspace catalog.
@@ -23,6 +24,17 @@ export function reconstructAutomationParametersFromValues(stored, dashboardParam
23
24
  };
24
25
  });
25
26
  }
27
+ /**
28
+ * Stored export overrides ({@link IDashboardExportParameter}) carry the value as a string; it is
29
+ * parsed back to a number and non-finite values are dropped. Title, mode and constraints are
30
+ * re-derived from the current dashboard and workspace catalog, mirroring
31
+ * {@link reconstructAutomationParametersFromValues}.
32
+ *
33
+ * @internal
34
+ */
35
+ export function reconstructAutomationParametersFromExportParameters(stored, dashboardParameters, catalog) {
36
+ return reconstructAutomationParametersFromValues(exportParametersToValues(stored), dashboardParameters, catalog);
37
+ }
26
38
  /**
27
39
  * Parameters of unsupported types are dropped (cannot be rendered/clamped). Dashboard-`hidden`
28
40
  * and `readonly` ones are dropped too — once added they would derive back to an invisible or
@@ -83,6 +95,46 @@ export function setAlertExecutionParameters(automation, parameters) {
83
95
  },
84
96
  };
85
97
  }
98
+ /**
99
+ * Encodes the display-ready chip set back to the neutral export wire shape ({id, value:string,
100
+ * title}). The full per-tab execution set (including `hidden` entries) is converted, not just the
101
+ * visible chips, so the server resolver does not drop omitted parameters to the workspace default.
102
+ *
103
+ * @internal
104
+ */
105
+ export function automationParametersToExportParameters(parameters) {
106
+ return parameters.map((parameter) => ({
107
+ id: parameter.ref.identifier,
108
+ value: String(parameter.value),
109
+ title: parameter.title,
110
+ }));
111
+ }
112
+ /**
113
+ * Encodes the per-tab execution sets to the neutral export wire shape, or `undefined` when
114
+ * `shouldStore` is false (feature off / store-filters unchecked — signals "omit the field; use
115
+ * latest defaults"). Inverse of {@link reconstructAutomationParametersFromExportParameters}.
116
+ *
117
+ * @internal
118
+ */
119
+ export function toEffectiveParametersByTab(parametersByTab, shouldStore) {
120
+ if (!shouldStore) {
121
+ return undefined;
122
+ }
123
+ const result = {};
124
+ for (const [tabId, parameters] of Object.entries(parametersByTab)) {
125
+ result[tabId] = automationParametersToExportParameters(parameters);
126
+ }
127
+ return Object.keys(result).length > 0 ? result : undefined;
128
+ }
129
+ /**
130
+ * The single home for "does this export persist its parameters": widget schedules always do (they
131
+ * have no store-filters checkbox), dashboard schedules follow the store-filters checkbox.
132
+ *
133
+ * @internal
134
+ */
135
+ export function shouldStoreExportParameters(isWidgetSchedule, storeFilters = false) {
136
+ return isWidgetSchedule || storeFilters;
137
+ }
86
138
  function numberConstraints(workspaceParameter) {
87
139
  return workspaceParameter && isNumberParameterDefinition(workspaceParameter.definition)
88
140
  ? workspaceParameter.definition.constraints
@@ -53,6 +53,10 @@ export interface IAutomationFiltersSelectProps {
53
53
  * Workspace parameters addable via the "+" menu (catalog minus the selected set).
54
54
  */
55
55
  availableParameters?: IAutomationParameter[];
56
+ /**
57
+ * Called when a parameter is added from the "+" menu.
58
+ */
59
+ onParameterAdd?: (ref: IdentifierRef) => void;
56
60
  /**
57
61
  * Called when an `active` parameter chip's value is edited.
58
62
  */
@@ -62,9 +66,29 @@ export interface IAutomationFiltersSelectProps {
62
66
  */
63
67
  onParameterDelete?: (ref: IdentifierRef) => void;
64
68
  /**
65
- * Called when a parameter is added from the "+" menu.
69
+ * Parameter chips per tab. Used in tab-rendering mode (multi-tab dashboard schedules).
66
70
  */
67
- onParameterAdd?: (ref: IdentifierRef) => void;
71
+ parametersByTab?: Record<string, IAutomationParameter[]>;
72
+ /**
73
+ * Addable workspace parameters per tab. Used in tab-rendering mode.
74
+ */
75
+ availableParametersByTab?: Record<string, IAutomationParameter[]>;
76
+ /**
77
+ * Called when a parameter is added from a tab section's "+" menu.
78
+ */
79
+ onParameterAddByTab?: (tabId: string, ref: IdentifierRef) => void;
80
+ /**
81
+ * Called when an `active` parameter chip's value is edited in a tab section.
82
+ */
83
+ onParameterChangeByTab?: (tabId: string, ref: IdentifierRef, value: number) => void;
84
+ /**
85
+ * Called when an `active` parameter chip is removed in a tab section.
86
+ */
87
+ onParameterDeleteByTab?: (tabId: string, ref: IdentifierRef) => void;
88
+ /**
89
+ * When the `enableParameters` feature is on, the store-filters tooltip mentions parameter values too.
90
+ */
91
+ parametersEnabled?: boolean;
68
92
  }
69
- export declare function AutomationFiltersSelect({ availableFilters, selectedFilters, onFiltersChange, isDashboardAutomation, storeFilters, onStoreFiltersChange, areFiltersMissing, overlayPositionType, hideTitle, showAllFilters, disableDateFilters, filtersByTab, editedFiltersByTab, onFiltersByTabChange, parameters, onParameterChange, onParameterDelete, availableParameters, onParameterAdd }: IAutomationFiltersSelectProps): import("react/jsx-runtime").JSX.Element;
93
+ export declare function AutomationFiltersSelect({ availableFilters, selectedFilters, onFiltersChange, isDashboardAutomation, storeFilters, onStoreFiltersChange, areFiltersMissing, overlayPositionType, hideTitle, showAllFilters, disableDateFilters, filtersByTab, editedFiltersByTab, onFiltersByTabChange, parameters, availableParameters, onParameterAdd, onParameterChange, onParameterDelete, parametersByTab, availableParametersByTab, onParameterAddByTab, onParameterChangeByTab, onParameterDeleteByTab, parametersEnabled }: IAutomationFiltersSelectProps): import("react/jsx-runtime").JSX.Element;
70
94
  //# sourceMappingURL=AutomationFiltersSelect.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"AutomationFiltersSelect.d.ts","sourceRoot":"","sources":["../../../../../../src/presentation/automations/shared/automationFilters/components/AutomationFiltersSelect.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"AutomationFiltersSelect.d.ts","sourceRoot":"","sources":["../../../../../../src/presentation/automations/shared/automationFilters/components/AutomationFiltersSelect.tsx"],"names":[],"mappings":"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"}
@@ -7,18 +7,21 @@ import { Bubble, BubbleHoverTrigger, Typography, UiButton, UiIconButton, UiToolt
7
7
  import { AUTOMATION_FILTERS_DIALOG_ID, AUTOMATION_FILTERS_DIALOG_TITLE_ID, AUTOMATION_FILTERS_GROUP_LABEL_ID, } from "../../../../constants/automations.js";
8
8
  import { AttributesDropdown, } from "../../../../filterBar/attributeFilter/addAttributeFilter/AttributesDropdown.js";
9
9
  import { useAutomationFilters, useAutomationFiltersByTab } from "../useAutomationFilters.js";
10
+ import { useParameterAnnouncements } from "../useParameterAnnouncements.js";
10
11
  import { AutomationAttributeFilter } from "./AutomationAttributeFilter.js";
11
12
  import { AutomationDateFilter } from "./AutomationDateFilter.js";
12
13
  import { AutomationMeasureValueFilter } from "./AutomationMeasureValueFilter.js";
13
14
  import { AutomationParameter } from "./AutomationParameter.js";
14
15
  const COLLAPSED_FILTERS_COUNT = 2;
15
- function AutomationCheckboxOrNote({ isDashboardAutomation, storeFilters, handleStoreFiltersChange, handleKeyDown, automationFilterSelectTooltipId, }) {
16
+ function AutomationCheckboxOrNote({ isDashboardAutomation, storeFilters, handleStoreFiltersChange, handleKeyDown, automationFilterSelectTooltipId, parametersEnabled, }) {
16
17
  const intl = useIntl();
18
+ // Keep both message ids as static literals so the i18n extractor sees them.
19
+ const useFiltersTooltip = parametersEnabled ? (_jsx(FormattedMessage, { id: "dialogs.automation.filters.useFiltersMessage.parameters.tooltip" })) : (_jsx(FormattedMessage, { id: "dialogs.automation.filters.useFiltersMessage.tooltip" }));
17
20
  return isDashboardAutomation ? (_jsxs("label", { className: "input-checkbox-label gd-automation-filters__use-filters-checkbox s-automation-filters-use-filters-checkbox", children: [
18
21
  _jsx("input", { type: "checkbox", className: "input-checkbox s-checkbox", checked: storeFilters, onChange: (e) => handleStoreFiltersChange(e.target.checked), onKeyDown: handleKeyDown, "aria-label": intl.formatMessage({
19
22
  id: "dialogs.automation.filters.useFiltersMessage",
20
23
  }) }), _jsxs("span", { className: "input-label-text gd-automation-filters__use-filters-message", children: [
21
- _jsx("div", { id: automationFilterSelectTooltipId, className: "sr-only", children: _jsx(FormattedMessage, { id: "dialogs.automation.filters.useFiltersMessage.tooltip" }) }), _jsx(FormattedMessage, { id: "dialogs.automation.filters.useFiltersMessage" }), _jsx(UiTooltip, { arrowPlacement: "left", triggerBy: ["hover", "focus"], optimalPlacement: true, width: 300, content: _jsx(FormattedMessage, { id: "dialogs.automation.filters.useFiltersMessage.tooltip" }), anchor: _jsx(UiIconButton, { icon: "question", variant: "tertiary", size: "xsmall", accessibilityConfig: {
24
+ _jsx("div", { id: automationFilterSelectTooltipId, className: "sr-only", children: useFiltersTooltip }), _jsx(FormattedMessage, { id: "dialogs.automation.filters.useFiltersMessage" }), _jsx(UiTooltip, { arrowPlacement: "left", triggerBy: ["hover", "focus"], optimalPlacement: true, width: 300, content: useFiltersTooltip, anchor: _jsx(UiIconButton, { icon: "question", variant: "tertiary", size: "xsmall", accessibilityConfig: {
22
25
  ariaLabel: intl.formatMessage({
23
26
  id: "dialogs.automation.filters.schedule.ariaLabel",
24
27
  }),
@@ -30,7 +33,7 @@ function AutomationCheckboxOrNote({ isDashboardAutomation, storeFilters, handleS
30
33
  function Divider() {
31
34
  return _jsx("div", { className: "gd-automation-filters__divider", style: { height: "20px" } });
32
35
  }
33
- export function AutomationFiltersSelect({ availableFilters = [], selectedFilters = [], onFiltersChange, isDashboardAutomation, storeFilters, onStoreFiltersChange, areFiltersMissing, overlayPositionType, hideTitle = false, showAllFilters = false, disableDateFilters = false, filtersByTab, editedFiltersByTab, onFiltersByTabChange, parameters = [], onParameterChange, onParameterDelete, availableParameters = [], onParameterAdd, }) {
36
+ export function AutomationFiltersSelect({ availableFilters = [], selectedFilters = [], onFiltersChange, isDashboardAutomation, storeFilters, onStoreFiltersChange, areFiltersMissing, overlayPositionType, hideTitle = false, showAllFilters = false, disableDateFilters = false, filtersByTab, editedFiltersByTab, onFiltersByTabChange, parameters = [], availableParameters = [], onParameterAdd, onParameterChange, onParameterDelete, parametersByTab, availableParametersByTab, onParameterAddByTab, onParameterChangeByTab, onParameterDeleteByTab, parametersEnabled, }) {
34
37
  // Determine rendering mode first
35
38
  const shouldRenderByTab = !!filtersByTab && filtersByTab.length > 1;
36
39
  // Use appropriate hook based on rendering mode
@@ -50,6 +53,7 @@ export function AutomationFiltersSelect({ availableFilters = [], selectedFilters
50
53
  });
51
54
  // Use data from the appropriate hook based on rendering mode
52
55
  const { commonDateFilterId, lockedFilters, attributeConfigs, dateConfigs, filterAnnouncement, filterGroupRef, makeFilterGroupUnfocusable, setAddFilterButtonRefs, } = shouldRenderByTab && tabFiltersData.processedFiltersByTab ? tabFiltersData : flatFiltersData;
56
+ const { focusAddFilterButton } = flatFiltersData;
53
57
  const filters = shouldRenderByTab ? [] : flatFiltersData.visibleFilters;
54
58
  const visibleParameters = shouldRenderByTab ? [] : parameters;
55
59
  const attributes = shouldRenderByTab ? [] : flatFiltersData.attributes;
@@ -90,6 +94,8 @@ export function AutomationFiltersSelect({ availableFilters = [], selectedFilters
90
94
  };
91
95
  const tooltipText = isAddButtonDisabled ? tooltipTextValues.addDisabled : tooltipTextValues.add;
92
96
  const searchAriaLabel = intl.formatMessage({ id: "dialogs.automation.filters.searchAriaLabel" });
97
+ // Screen-reader announcements for parameter chip add/remove/change
98
+ const { parameterAnnouncement, announceParameterAdded, announceParameterChanged, announceParameterRemoved, } = useParameterAnnouncements();
93
99
  const disableFilters = !storeFilters && !!isDashboardAutomation;
94
100
  return (_jsxs("div", { className: "gd-input-component gd-notification-channels-automation-filters s-gd-notifications-channels-dialog-automation-filters", children: [hideTitle ? (_jsx("div", { className: "sr-only", id: AUTOMATION_FILTERS_GROUP_LABEL_ID, children: _jsx(FormattedMessage, { id: "dialogs.schedule.email.filters", values: { count: chipCount } }) })) : (_jsx("div", { className: "gd-label", id: AUTOMATION_FILTERS_GROUP_LABEL_ID, children: isExpandable && !shouldRenderByTab ? (_jsxs(BubbleHoverTrigger, { showDelay: 500, hideDelay: 0, children: [
95
101
  _jsx(UiButton, { label: intl.formatMessage({ id: "dialogs.schedule.email.filters" }, { count: chipCount }), variant: "tertiary", onClick: () => setIsExpanded(!isExpanded), iconAfter: isExpanded ? "navigateUp" : "navigateDown", accessibilityConfig: {
@@ -104,21 +110,38 @@ export function AutomationFiltersSelect({ availableFilters = [], selectedFilters
104
110
  iconAriaHidden: true,
105
111
  } }), _jsx(Bubble, { className: "bubble-primary", alignPoints: [{ align: "bc tc" }], children: isExpanded ? (_jsx(FormattedMessage, { id: "dialogs.automation.filters.showLess" })) : (_jsx(FormattedMessage, { id: "dialogs.automation.filters.showAll" })) })
106
112
  ] })) : (_jsx(FormattedMessage, { id: "dialogs.schedule.email.filters", values: { count: chipCount } })) })), _jsxs("div", { className: "gd-automation-filters", children: [showAllFilters ? (_jsxs(_Fragment, { children: [
107
- _jsx(AutomationCheckboxOrNote, { isDashboardAutomation: isDashboardAutomation, storeFilters: storeFilters, handleStoreFiltersChange: handleStoreFiltersChange, handleKeyDown: handleKeyDown, automationFilterSelectTooltipId: automationFilterSelectTooltipId }), _jsx(Divider, {})
113
+ _jsx(AutomationCheckboxOrNote, { isDashboardAutomation: isDashboardAutomation, storeFilters: storeFilters, handleStoreFiltersChange: handleStoreFiltersChange, handleKeyDown: handleKeyDown, automationFilterSelectTooltipId: automationFilterSelectTooltipId, parametersEnabled: parametersEnabled }), _jsx(Divider, {})
108
114
  ] })) : null, _jsxs("div", { className: `gd-automation-filters__wrapper${storeFilters || !isDashboardAutomation ? "" : " gd-automation-filters__wrapper--disabled"}`, children: [disableFilters ? _jsx("div", { className: "gd-automation-filters__overlay" }) : null, shouldRenderByTab && tabFiltersData.processedFiltersByTab ? (
109
115
  // Render filters grouped by tab with dividers between sections
110
116
  _jsx("div", { className: "gd-automation-filters__list gd-automation-filters__list--tabbed", role: "group", "aria-labelledby": AUTOMATION_FILTERS_GROUP_LABEL_ID, ref: filterGroupRef, onBlur: makeFilterGroupUnfocusable, children: tabFiltersData.processedFiltersByTab.map((tab, index) => {
111
117
  // Check if all filters for this tab are already selected
112
118
  const tabEditedFilters = editedFiltersByTab?.[tab.tabId] ?? [];
113
119
  const tabAvailableFilters = filtersByTab?.find((t) => t.tabId === tab.tabId)?.availableFilters ?? [];
114
- const isTabAddButtonDisabled = tabEditedFilters.length >= tabAvailableFilters.length;
120
+ const tabParameters = parametersByTab?.[tab.tabId] ?? [];
121
+ const tabAvailableParameters = availableParametersByTab?.[tab.tabId] ?? [];
122
+ const tabParameterDropdownItems = tabAvailableParameters.map((parameter) => ({
123
+ type: "parameter",
124
+ ref: parameter.ref,
125
+ title: parameter.title,
126
+ }));
127
+ const isTabAddButtonDisabled = tabEditedFilters.length >= tabAvailableFilters.length &&
128
+ tabAvailableParameters.length === 0;
115
129
  const tabTooltipText = isTabAddButtonDisabled
116
130
  ? tooltipTextValues.addDisabled
117
131
  : tooltipTextValues.add;
118
- return (_jsx(AutomationFiltersTabSection, { tabTitle: tab.tabTitle, tabId: tab.tabId, filters: tab.visibleFilters, attributeConfigs: tab.attributeConfigs, commonDateFilterId: commonDateFilterId, lockedFilters: tab.lockedFilters, onChange: (filter) => tabFiltersData.handleTabFilterChange(tab.tabId, filter), onDelete: (filter) => tabFiltersData.handleTabFilterDelete(tab.tabId, filter), overlayPositionType: overlayPositionType, showDivider: index < tabFiltersData.processedFiltersByTab.length - 1, readonlyFilters: disableFilters,
132
+ return (_jsx(AutomationFiltersTabSection, { tabTitle: tab.tabTitle, tabId: tab.tabId, canAddItems: !isTabAddButtonDisabled, filters: tab.visibleFilters, attributeConfigs: tab.attributeConfigs, commonDateFilterId: commonDateFilterId, lockedFilters: tab.lockedFilters, onChange: (filter) => tabFiltersData.handleTabFilterChange(tab.tabId, filter), onDelete: (filter) => tabFiltersData.handleTabFilterDelete(tab.tabId, filter), parameters: tabParameters, onParameterChange: (ref, value) => {
133
+ announceParameterChanged(tabParameters, ref, value);
134
+ onParameterChangeByTab?.(tab.tabId, ref, value);
135
+ }, onParameterDelete: (ref) => {
136
+ announceParameterRemoved(tabParameters, ref);
137
+ onParameterDeleteByTab?.(tab.tabId, ref);
138
+ }, overlayPositionType: overlayPositionType, showDivider: index < tabFiltersData.processedFiltersByTab.length - 1, readonlyFilters: disableFilters,
119
139
  // Add button for each tab section
120
140
  addFilterButton: _jsx(AttributesDropdown, { id: `${AUTOMATION_FILTERS_DIALOG_ID}-${tab.tabId}`, onClose: () => { }, onSelect: (value) => {
121
141
  tabFiltersData.handleTabFilterAdd(tab.tabId, value, tab.attributes, tab.dateDatasets);
142
+ }, parameters: tabParameterDropdownItems, onParameterSelect: (ref) => {
143
+ announceParameterAdded(tabAvailableParameters, ref);
144
+ onParameterAddByTab?.(tab.tabId, ref);
122
145
  }, attributes: tab.attributes, dateDatasets: tab.dateDatasets, measures: tab.measures, openOnInit: false, overlayPositionType: overlayPositionType, className: "gd-automation-filters__dropdown s-automation-filters-add-filter-dropdown", getCustomItemTitle: (item) => getCatalogItemCustomTitle(item, availableFilters, tab.dateConfigs), accessibilityConfig: {
123
146
  ariaLabelledBy: AUTOMATION_FILTERS_DIALOG_TITLE_ID,
124
147
  searchAriaLabel: searchAriaLabel,
@@ -143,13 +166,22 @@ export function AutomationFiltersSelect({ availableFilters = [], selectedFilters
143
166
  commonDateFilterId === filter.dateFilter.localIdentifier);
144
167
  return (_jsx(AutomationFilter, { filter: filter, attributeConfigs: attributeConfigs, onChange: handleChangeFilter, onDelete: handleDeleteFilter, isCommonDateFilter: isCommonDateFilter, overlayPositionType: overlayPositionType, lockedFilters: lockedFilters, isReadOnly: disableFilters }, dashboardFilterLocalIdentifier(filter)));
145
168
  }),
146
- ...visibleParameters.map((parameter) => (_jsx(AutomationParameter, { parameter: parameter, onChange: onParameterChange, onDelete: onParameterDelete, overlayPositionType: overlayPositionType }, `parameter-${parameter.ref.identifier}`))),
169
+ ...visibleParameters.map((parameter) => (_jsx(AutomationParameter, { parameter: parameter, onChange: (ref, value) => {
170
+ announceParameterChanged(visibleParameters, ref, value);
171
+ onParameterChange?.(ref, value);
172
+ }, onDelete: (ref) => {
173
+ announceParameterRemoved(visibleParameters, ref);
174
+ onParameterDelete?.(ref);
175
+ }, overlayPositionType: overlayPositionType, isReadOnly: disableFilters }, `parameter-${parameter.ref.identifier}`))),
147
176
  ].slice(0, showAllFilters || isExpanded ? undefined : COLLAPSED_FILTERS_COUNT), isExpanded || !isExpandable ? (_jsx(AttributesDropdown, { id: AUTOMATION_FILTERS_DIALOG_ID, onClose: () => { }, onSelect: (value) => {
148
177
  handleAddFilter(value, attributes, dateDatasets);
149
178
  setIsExpanded(true);
150
179
  }, parameters: parameterDropdownItems, onParameterSelect: (ref) => {
180
+ announceParameterAdded(availableParameters, ref);
151
181
  onParameterAdd?.(ref);
152
182
  setIsExpanded(true);
183
+ // Restore "+" focus, else it falls to <body> when the chip's list node unmounts.
184
+ setTimeout(focusAddFilterButton);
153
185
  }, attributes: attributes, dateDatasets: dateDatasets, measures: measures, openOnInit: false, overlayPositionType: overlayPositionType, className: "gd-automation-filters__dropdown s-automation-filters-add-filter-dropdown", getCustomItemTitle: (item) => getCatalogItemCustomTitle(item, availableFilters, dateConfigs), accessibilityConfig: {
154
186
  ariaLabelledBy: AUTOMATION_FILTERS_DIALOG_TITLE_ID,
155
187
  searchAriaLabel: searchAriaLabel,
@@ -165,10 +197,10 @@ export function AutomationFiltersSelect({ availableFilters = [], selectedFilters
165
197
  ariaExpanded: isOpen,
166
198
  ariaHaspopup: "dialog",
167
199
  } }) }) })), DropdownTitleComponent: () => (_jsx("div", { className: "gd-automation-filters__dropdown-header", children: _jsx(Typography, { tagName: "h3", id: AUTOMATION_FILTERS_DIALOG_TITLE_ID, children: _jsx(FormattedMessage, { id: "dialogs.automation.filters.title" }) }) })), renderNoData: () => (_jsx("div", { className: "gd-automation-filters__dropdown-no-filters", children: _jsx(FormattedMessage, { id: "dialogs.automation.filters.noFilters" }) })) })) : null] }))] }), showAllFilters ? null : (_jsxs(_Fragment, { children: [
168
- _jsx(Divider, {}), _jsx(AutomationCheckboxOrNote, { isDashboardAutomation: isDashboardAutomation, storeFilters: storeFilters, handleStoreFiltersChange: handleStoreFiltersChange, handleKeyDown: handleKeyDown, automationFilterSelectTooltipId: automationFilterSelectTooltipId })
200
+ _jsx(Divider, {}), _jsx(AutomationCheckboxOrNote, { isDashboardAutomation: isDashboardAutomation, storeFilters: storeFilters, handleStoreFiltersChange: handleStoreFiltersChange, handleKeyDown: handleKeyDown, automationFilterSelectTooltipId: automationFilterSelectTooltipId, parametersEnabled: parametersEnabled })
169
201
  ] })), areFiltersMissing ? (_jsx("div", { className: "gd-automation-filters__warning-message", children: _jsx(FormattedMessage, { id: "dialogs.automation.filters.missing", values: {
170
202
  b: (chunk) => _jsx("strong", { children: chunk }),
171
- } }) })) : null] }), _jsx("div", { className: "sr-only", "aria-live": "polite", "aria-atomic": "true", role: "status", children: filterAnnouncement })
203
+ } }) })) : null] }), _jsx("div", { className: "sr-only", "aria-live": "polite", "aria-atomic": "true", role: "status", children: filterAnnouncement }), _jsx("div", { className: "sr-only", "aria-live": "polite", "aria-atomic": "true", role: "status", children: parameterAnnouncement })
172
204
  ] }));
173
205
  }
174
206
  function AutomationFilter({ filter, attributeConfigs, onChange, onDelete, isCommonDateFilter, overlayPositionType, lockedFilters, isReadOnly, tabId, }) {
@@ -194,13 +226,13 @@ function AutomationFilter({ filter, attributeConfigs, onChange, onDelete, isComm
194
226
  * Renders filters for a single tab with a tab title header.
195
227
  * Used when displaying filters grouped by tab for whole dashboard automations.
196
228
  */
197
- function AutomationFiltersTabSection({ tabId, tabTitle, filters, attributeConfigs, commonDateFilterId, lockedFilters, onChange, onDelete, overlayPositionType, showDivider = false, addFilterButton, readonlyFilters, }) {
229
+ function AutomationFiltersTabSection({ tabId, tabTitle, filters, attributeConfigs, commonDateFilterId, lockedFilters, onChange, onDelete, parameters, onParameterChange, onParameterDelete, overlayPositionType, showDivider = false, addFilterButton, canAddItems, readonlyFilters, }) {
198
230
  const intl = useIntl();
199
231
  const tabSectionLabelId = useIdPrefixed(`automation-filters-tab-${tabId}`);
200
232
  // Display tab title or fallback to generic "Tab" label
201
233
  const displayTitle = tabTitle || intl.formatMessage({ id: "dialogs.automation.filters.tab.untitled" });
202
234
  const tabLabel = intl.formatMessage({ id: "dialogs.automation.filters.tab.label" });
203
- if (filters.length === 0) {
235
+ if (filters.length === 0 && parameters.length === 0 && !canAddItems) {
204
236
  return null;
205
237
  }
206
238
  const content = (_jsx("span", { className: "gd-automation-filters__tab-title s-automation-filters-tab-title", children: displayTitle }));
@@ -213,7 +245,7 @@ function AutomationFiltersTabSection({ tabId, tabTitle, filters, attributeConfig
213
245
  (isDashboardDateFilter(filter) &&
214
246
  commonDateFilterId === filter.dateFilter.localIdentifier);
215
247
  return (_jsx(AutomationFilter, { filter: filter, attributeConfigs: attributeConfigs, onChange: onChange, onDelete: onDelete, isCommonDateFilter: isCommonDateFilter, overlayPositionType: overlayPositionType, lockedFilters: lockedFilters, isReadOnly: readonlyFilters, tabId: tabId }, dashboardFilterLocalIdentifier(filter)));
216
- }), addFilterButton] })
248
+ }), parameters.map((parameter) => (_jsx(AutomationParameter, { parameter: parameter, onChange: onParameterChange, onDelete: onParameterDelete, overlayPositionType: overlayPositionType, isReadOnly: readonlyFilters }, `parameter-${parameter.ref.identifier}`))), addFilterButton] })
217
249
  ] }), showDivider ? _jsx("div", { className: "gd-automation-filters__tab-divider" }) : null] }));
218
250
  }
219
251
  /**
@@ -10,11 +10,12 @@ export interface IAutomationParameterProps {
10
10
  onChange?: (ref: IdentifierRef, value: number) => void;
11
11
  onDelete?: (ref: IdentifierRef) => void;
12
12
  overlayPositionType?: OverlayPositionType;
13
+ isReadOnly?: boolean;
13
14
  }
14
15
  /**
15
16
  * Workspace parameter as an editable chip in automation dialogs.
16
17
  *
17
18
  * @internal
18
19
  */
19
- export declare function AutomationParameter({ parameter, onChange, onDelete, overlayPositionType }: IAutomationParameterProps): ReactNode;
20
+ export declare function AutomationParameter({ parameter, onChange, onDelete, overlayPositionType, isReadOnly }: IAutomationParameterProps): ReactNode;
20
21
  //# sourceMappingURL=AutomationParameter.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"AutomationParameter.d.ts","sourceRoot":"","sources":["../../../../../../src/presentation/automations/shared/automationFilters/components/AutomationParameter.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAsB,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAI3D,OAAO,EAAgC,KAAK,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACvF,OAAO,EAEH,KAAK,mBAAmB,EAM3B,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EAAE,KAAK,oBAAoB,EAAE,MAAM,4BAA4B,CAAC;AAEvE;;GAEG;AACH,MAAM,WAAW,yBAAyB;IACtC,SAAS,EAAE,oBAAoB,CAAC;IAChC,QAAQ,CAAC,EAAE,CAAC,GAAG,EAAE,aAAa,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACvD,QAAQ,CAAC,EAAE,CAAC,GAAG,EAAE,aAAa,KAAK,IAAI,CAAC;IACxC,mBAAmB,CAAC,EAAE,mBAAmB,CAAC;CAC7C;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,EAChC,SAAS,EACT,QAAQ,EACR,QAAQ,EACR,mBAAmB,EACtB,EAAE,yBAAyB,GAAG,SAAS,CAoEvC"}
1
+ {"version":3,"file":"AutomationParameter.d.ts","sourceRoot":"","sources":["../../../../../../src/presentation/automations/shared/automationFilters/components/AutomationParameter.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAsB,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAI3D,OAAO,EAAgC,KAAK,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACvF,OAAO,EAEH,KAAK,mBAAmB,EAM3B,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EAAE,KAAK,oBAAoB,EAAE,MAAM,4BAA4B,CAAC;AAEvE;;GAEG;AACH,MAAM,WAAW,yBAAyB;IACtC,SAAS,EAAE,oBAAoB,CAAC;IAChC,QAAQ,CAAC,EAAE,CAAC,GAAG,EAAE,aAAa,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACvD,QAAQ,CAAC,EAAE,CAAC,GAAG,EAAE,aAAa,KAAK,IAAI,CAAC;IACxC,mBAAmB,CAAC,EAAE,mBAAmB,CAAC;IAC1C,UAAU,CAAC,EAAE,OAAO,CAAC;CACxB;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,EAChC,SAAS,EACT,QAAQ,EACR,QAAQ,EACR,mBAAmB,EACnB,UAAU,EACb,EAAE,yBAAyB,GAAG,SAAS,CAmFvC"}
@@ -7,7 +7,7 @@ import { Dropdown, ParameterControlDropdown, UiChip, UiTooltip, isActionKey, use
7
7
  *
8
8
  * @internal
9
9
  */
10
- export function AutomationParameter({ parameter, onChange, onDelete, overlayPositionType, }) {
10
+ export function AutomationParameter({ parameter, onChange, onDelete, overlayPositionType, isReadOnly, }) {
11
11
  const intl = useIntl();
12
12
  const { ref, title, value, mode, constraints } = parameter;
13
13
  const testId = `automation-parameter-${ref.identifier}`;
@@ -15,6 +15,12 @@ export function AutomationParameter({ parameter, onChange, onDelete, overlayPosi
15
15
  const lockedTooltip = intl.formatMessage({ id: "dialogs.automation.filters.lockedTooltip" });
16
16
  const deleteAriaLabel = intl.formatMessage({ id: "dialogs.automation.filters.deleteAriaLabel" });
17
17
  const tooltipId = useIdPrefixed("automation-parameter-tooltip");
18
+ if (isReadOnly) {
19
+ // `isDisabled` renders a real disabled button — unfocusable, so keyboard users can't edit or
20
+ // delete. No lock icon/tooltip: unlike author-`READONLY` this chip is only frozen because
21
+ // persistence is off, so it must not read as author-locked.
22
+ return (_jsx(UiChip, { label: label, iconBefore: "parameter", isDisabled: true, isExpandable: false, dataTestId: testId }));
23
+ }
18
24
  if (mode === DashboardParameterModeValues.READONLY) {
19
25
  return (_jsx(UiChip, { label: label, iconBefore: "parameter", isLocked: true, isExpandable: false, dataTestId: testId, renderChipContent: (content) => (_jsx(UiTooltip, { id: tooltipId, arrowPlacement: "top-start", content: lockedTooltip, triggerBy: ["hover", "focus"], anchor: content, anchorWrapperStyles: { display: "flex", width: "100%", height: "100%", minWidth: 0 } })) }));
20
26
  }
@@ -1,4 +1,4 @@
1
- import { type DashboardAttributeFilterSelectionType, type FilterContextItem, type IAutomationMetadataObject, type IAutomationVisibleFilter, type IFilter, type IInsight } from "@gooddata/sdk-model";
1
+ import { type DashboardAttributeFilterSelectionType, type FilterContextItem, type IAutomationMetadataObject, type IAutomationVisibleFilter, type IDashboardExportParameter, type IDashboardParameter, type IFilter, type IInsight, type IParameterMetadataObject } from "@gooddata/sdk-model";
2
2
  import type { ExtendedDashboardWidget } from "../../../../../model/types/layoutTypes.js";
3
3
  export interface IAutomationValidationResult {
4
4
  isValid: boolean;
@@ -12,12 +12,34 @@ export interface IAutomationValidationResult {
12
12
  visibleFilterIsMissingInSavedFilters: boolean;
13
13
  visibleFiltersAreMissing: boolean;
14
14
  incompatibleSelectionTypeIsAppliedInSavedFilters: boolean;
15
+ /**
16
+ * A stored parameter override is stale: its ref left the catalog, its tab is gone, or a
17
+ * `readonly`/`hidden` parameter's pinned value drifted from the current dashboard.
18
+ */
19
+ parametersAreStale?: boolean;
15
20
  }
16
21
  export declare function useValidateExistingAutomationFilters({ automationToEdit, widget, insight }: {
17
22
  automationToEdit?: IAutomationMetadataObject;
18
23
  widget?: ExtendedDashboardWidget;
19
24
  insight?: IInsight;
20
25
  }): IAutomationValidationResult;
26
+ /**
27
+ * Flags stale stored parameter overrides for an existing automation: a ref that left the workspace
28
+ * catalog, a tab that no longer exists, or a `readonly`/`hidden` parameter whose pinned value
29
+ * drifted from the current dashboard. `active` parameters are user-owned, so their drift is allowed.
30
+ */
31
+ export declare function validateExistingAutomationParameters({ storedParametersByTab, catalog, dashboardParametersByTab, existingTabIds, widgetTabId }: {
32
+ storedParametersByTab: Record<string, IDashboardExportParameter[]> | undefined;
33
+ catalog: IParameterMetadataObject[];
34
+ dashboardParametersByTab: Record<string, IDashboardParameter[]>;
35
+ existingTabIds: Set<string>;
36
+ /**
37
+ * For widget schedules, the widget's current tab. A stored override under any other tab is
38
+ * orphaned (the widget was moved) and flagged stale. Undefined for dashboard schedules and when
39
+ * the tab can't be resolved, where every existing tab is accepted.
40
+ */
41
+ widgetTabId?: string;
42
+ }): boolean;
21
43
  /**
22
44
  * Validate existing automation filters against current dashboard filter context and optionally saved widget / insight.
23
45
  * Check for inconsistencies, that could lead to unwanted results when editing existing automation.
@@ -1 +1 @@
1
- {"version":3,"file":"useValidateExistingAutomationFilters.d.ts","sourceRoot":"","sources":["../../../../../../src/presentation/automations/shared/automationFilters/hooks/useValidateExistingAutomationFilters.ts"],"names":[],"mappings":"AAIA,OAAO,EACH,KAAK,qCAAqC,EAC1C,KAAK,iBAAiB,EAEtB,KAAK,yBAAyB,EAC9B,KAAK,wBAAwB,EAC7B,KAAK,OAAO,EAEZ,KAAK,QAAQ,EAkBhB,MAAM,qBAAqB,CAAC;AAsB7B,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,2CAA2C,CAAC;AA+DzF,MAAM,WAAW,2BAA2B;IACxC,OAAO,EAAE,OAAO,CAAC;IACjB,mCAAmC,EAAE,OAAO,CAAC;IAC7C,0CAA0C,EAAE,OAAO,CAAC;IACpD,mCAAmC,EAAE,OAAO,CAAC;IAC7C,0CAA0C,EAAE,OAAO,CAAC;IACpD,oCAAoC,EAAE,OAAO,CAAC;IAC9C,oCAAoC,EAAE,OAAO,CAAC;IAC9C,8CAA8C,EAAE,OAAO,CAAC;IACxD,oCAAoC,EAAE,OAAO,CAAC;IAC9C,wBAAwB,EAAE,OAAO,CAAC;IAClC,gDAAgD,EAAE,OAAO,CAAC;CAC7D;AAgBD,wBAAgB,oCAAoC,CAAC,EACjD,gBAAgB,EAChB,MAAM,EACN,OAAO,EACV,EAAE;IACC,gBAAgB,CAAC,EAAE,yBAAyB,CAAC;IAC7C,MAAM,CAAC,EAAE,uBAAuB,CAAC;IACjC,OAAO,CAAC,EAAE,QAAQ,CAAC;CACtB,GAAG,2BAA2B,CAyF9B;AAMD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,iCAAiC,CAAC,EAC9C,sBAAsB,EACtB,6BAA6B,EAC7B,aAAa,EACb,aAAa,EACb,cAAc,EACd,gBAAgB,EAChB,MAAM,EACN,OAAO,EACP,gBAAgB,EACnB,EAAE;IACC,sBAAsB,EAAE,OAAO,EAAE,CAAC;IAClC,6BAA6B,EAAE,SAAS,GAAG,wBAAwB,EAAE,CAAC;IACtE,aAAa,EAAE,iBAAiB,EAAE,CAAC;IACnC,aAAa,EAAE,iBAAiB,EAAE,CAAC;IACnC,cAAc,EAAE,iBAAiB,EAAE,CAAC;IACpC,gBAAgB,EAAE,iBAAiB,EAAE,CAAC;IACtC,MAAM,CAAC,EAAE,uBAAuB,CAAC;IACjC,OAAO,CAAC,EAAE,QAAQ,CAAC;IACnB,gBAAgB,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,qCAAqC,GAAG,SAAS,CAAC,CAAC;CACrF,GAAG,2BAA2B,CAgE9B;AAED,MAAM,WAAW,4BAA4B;IACzC,KAAK,EAAE,MAAM,CAAC;IACd,gBAAgB,EAAE,iBAAiB,EAAE,CAAC;IACtC,aAAa,EAAE,iBAAiB,EAAE,CAAC;IACnC,aAAa,EAAE,iBAAiB,EAAE,CAAC;CACtC;AAED;;;GAGG;AACH,wBAAgB,uCAAuC,CAAC,EACpD,0BAA0B,EAC1B,kCAAkC,EAClC,sBAAsB,EACtB,kBAAkB,EAClB,qBAAqB,EACxB,EAAE;IACC,0BAA0B,EAAE,MAAM,CAAC,MAAM,EAAE,iBAAiB,EAAE,CAAC,CAAC;IAChE,kCAAkC,EAAE,MAAM,CAAC,MAAM,EAAE,wBAAwB,EAAE,CAAC,CAAC;IAC/E,sBAAsB,EAAE,4BAA4B,EAAE,CAAC;IACvD,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,qBAAqB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,qCAAqC,GAAG,SAAS,CAAC,CAAC,CAAC;CAC1G,GAAG,2BAA2B,CAoE9B"}
1
+ {"version":3,"file":"useValidateExistingAutomationFilters.d.ts","sourceRoot":"","sources":["../../../../../../src/presentation/automations/shared/automationFilters/hooks/useValidateExistingAutomationFilters.ts"],"names":[],"mappings":"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"}
@@ -1,12 +1,17 @@
1
1
  // (C) 2025-2026 GoodData Corporation
2
2
  import { differenceBy, omit } from "lodash-es";
3
- import { dashboardFilterLocalIdentifier, filterLocalIdentifier, isAllDashboardMeasureValueFilter, isAllValuesAttributeFilter, isAllValuesDashboardAttributeFilter, isAttributeFilter, isAttributeFilterWithSelection, isDashboardAttributeFilter, isDashboardCommonDateFilter, isDateFilter, isInsightWidget, isLocalIdRef, isNegativeAttributeFilter, isPositiveAttributeFilter, isRelativeDateFilter, isSingleSelectionFilter, } from "@gooddata/sdk-model";
4
- import { getAutomationAlertFilters, getAutomationDashboardFilters, getAutomationDashboardFiltersByTab, getAutomationVisualizationFilters, } from "../../../../../_staging/automation/index.js";
3
+ import { DashboardParameterModeValues, dashboardFilterLocalIdentifier, filterLocalIdentifier, isAllDashboardMeasureValueFilter, isAllValuesAttributeFilter, isAllValuesDashboardAttributeFilter, isAttributeFilter, isAttributeFilterWithSelection, isDashboardAttributeFilter, isDashboardCommonDateFilter, isDateFilter, isInsightWidget, isLocalIdRef, isNegativeAttributeFilter, isNumberParameterDefinition, isPositiveAttributeFilter, isRelativeDateFilter, isSingleSelectionFilter, } from "@gooddata/sdk-model";
4
+ import { getAutomationAlertFilters, getAutomationDashboardFilters, getAutomationDashboardFiltersByTab, getAutomationExportParametersByTab, getAutomationVisualizationFilters, } from "../../../../../_staging/automation/index.js";
5
5
  import { filterContextItemsToDashboardFiltersByWidget } from "../../../../../converters/filterConverters.js";
6
6
  import { isFilterTypeCompatibleWithSelectionType } from "../../../../../model/commandHandlers/dashboard/common/attributeFilterSelectionTypeCompatibility.js";
7
7
  import { useDashboardSelector } from "../../../../../model/react/DashboardStoreProvider.js";
8
+ import { selectCatalogParameters, selectCatalogParametersIsLoaded, } from "../../../../../model/store/catalog/catalogSelectors.js";
9
+ import { selectEnableParameters } from "../../../../../model/store/config/configSelectors.js";
8
10
  import { selectAutomationCommonDateFilterId, selectAutomationFiltersByTab, selectDashboardFiltersWithoutCrossFiltering, selectDashboardHiddenFilters, selectDashboardLockedFilters, } from "../../../../../model/store/filtering/dashboardFilterSelectors.js";
9
11
  import { selectAttributeFilterConfigsSelectionTypeMap, selectAttributeFilterConfigsSelectionTypeMapByTab, } from "../../../../../model/store/tabs/attributeFilterConfigs/attributeFilterConfigsSelectors.js";
12
+ import { selectWidgetLocalIdToTabIdMap } from "../../../../../model/store/tabs/layout/layoutSelectors.js";
13
+ import { selectSmartPersistedTabsParameters } from "../../../../../model/store/tabs/parameters/parametersSelectors.js";
14
+ import { selectTabs } from "../../../../../model/store/tabs/tabsSelectors.js";
10
15
  import { areFiltersEqual, isFilterIgnoredByWidget, isFilterMatch, isNoopAllTimeDateFilterFixed, } from "../utils.js";
11
16
  function sanitizeCommonDateFilter(filter, commonDateFilterId) {
12
17
  // Sanitize common date filters by removing date dataSet
@@ -51,6 +56,7 @@ const defaultValidState = {
51
56
  visibleFilterIsMissingInSavedFilters: false,
52
57
  visibleFiltersAreMissing: false,
53
58
  incompatibleSelectionTypeIsAppliedInSavedFilters: false,
59
+ parametersAreStale: false,
54
60
  };
55
61
  export function useValidateExistingAutomationFilters({ automationToEdit, widget, insight, }) {
56
62
  const lockedFilters = useDashboardSelector(selectDashboardLockedFilters);
@@ -60,6 +66,52 @@ export function useValidateExistingAutomationFilters({ automationToEdit, widget,
60
66
  const dashboardFiltersByTab = useDashboardSelector(selectAutomationFiltersByTab);
61
67
  const selectionTypeMap = useDashboardSelector(selectAttributeFilterConfigsSelectionTypeMap);
62
68
  const selectionTypeMapByTab = useDashboardSelector(selectAttributeFilterConfigsSelectionTypeMapByTab);
69
+ const parametersEnabled = useDashboardSelector(selectEnableParameters);
70
+ const catalogParameters = useDashboardSelector(selectCatalogParameters);
71
+ const catalogParametersIsLoaded = useDashboardSelector(selectCatalogParametersIsLoaded);
72
+ const dashboardParametersByTab = useDashboardSelector(selectSmartPersistedTabsParameters);
73
+ const tabs = useDashboardSelector(selectTabs);
74
+ const widgetTabMap = useDashboardSelector(selectWidgetLocalIdToTabIdMap);
75
+ // A widget export covers exactly the widget's current tab, so its stored overrides must live under
76
+ // that tab; a dashboard export covers every tab. Resolved here so the validator can flag a widget
77
+ // whose stored override was orphaned under its previous tab after a move.
78
+ const widgetTabId = widget?.localIdentifier ? widgetTabMap[widget.localIdentifier] : undefined;
79
+ // Before the catalog loads, every stored ref looks removed — treat loading as not-stale.
80
+ const parametersAreStale = parametersEnabled && catalogParametersIsLoaded
81
+ ? validateExistingAutomationParameters({
82
+ storedParametersByTab: getAutomationExportParametersByTab(automationToEdit),
83
+ catalog: catalogParameters,
84
+ dashboardParametersByTab,
85
+ existingTabIds: new Set((tabs ?? []).map((tab) => tab.localIdentifier)),
86
+ widgetTabId,
87
+ })
88
+ : false;
89
+ const filterValidation = resolveFilterValidation({
90
+ automationToEdit,
91
+ widget,
92
+ insight,
93
+ lockedFilters,
94
+ hiddenFilters,
95
+ dashboardFilters,
96
+ commonDateFilterId,
97
+ dashboardFiltersByTab,
98
+ selectionTypeMap,
99
+ selectionTypeMapByTab,
100
+ });
101
+ // Parameter staleness is resolved at this single hook boundary and folded into the filter result
102
+ // exactly once; the pure filter validators below never deal with the parameter concept.
103
+ return {
104
+ ...filterValidation,
105
+ isValid: filterValidation.isValid && !parametersAreStale,
106
+ parametersAreStale,
107
+ };
108
+ }
109
+ /**
110
+ * Resolves the filter-only validation result (no parameter staleness) for an existing automation.
111
+ * Pure: it takes everything the hook already read from the store, so the early-return branching stays
112
+ * testable and free of React hooks.
113
+ */
114
+ function resolveFilterValidation({ automationToEdit, widget, insight, lockedFilters, hiddenFilters, dashboardFilters, commonDateFilterId, dashboardFiltersByTab, selectionTypeMap, selectionTypeMapByTab, }) {
63
115
  const savedAutomationVisibleFilters = automationToEdit?.metadata?.visibleFilters;
64
116
  const savedAutomationVisibleFiltersByTab = automationToEdit?.metadata?.visibleFiltersByTab;
65
117
  const ignoredFilters = widget ? dashboardFilters.filter((f) => isFilterIgnoredByWidget(f, widget)) : [];
@@ -114,6 +166,45 @@ export function useValidateExistingAutomationFilters({ automationToEdit, widget,
114
166
  //
115
167
  // Validations
116
168
  //
169
+ /**
170
+ * Flags stale stored parameter overrides for an existing automation: a ref that left the workspace
171
+ * catalog, a tab that no longer exists, or a `readonly`/`hidden` parameter whose pinned value
172
+ * drifted from the current dashboard. `active` parameters are user-owned, so their drift is allowed.
173
+ */
174
+ export function validateExistingAutomationParameters({ storedParametersByTab, catalog, dashboardParametersByTab, existingTabIds, widgetTabId, }) {
175
+ if (!storedParametersByTab) {
176
+ return false;
177
+ }
178
+ const workspaceById = new Map(catalog.map((parameter) => [parameter.id, parameter]));
179
+ for (const [tabId, storedParameters] of Object.entries(storedParametersByTab)) {
180
+ const tabIsValid = widgetTabId === undefined ? existingTabIds.has(tabId) : tabId === widgetTabId;
181
+ if (!tabIsValid) {
182
+ return true;
183
+ }
184
+ const dashboardById = new Map((dashboardParametersByTab[tabId] ?? []).map((parameter) => [parameter.ref.identifier, parameter]));
185
+ for (const stored of storedParameters) {
186
+ const workspaceParameter = workspaceById.get(stored.id);
187
+ if (!workspaceParameter) {
188
+ return true;
189
+ }
190
+ const dashboardParameter = dashboardById.get(stored.id);
191
+ const mode = dashboardParameter?.mode ?? DashboardParameterModeValues.ACTIVE;
192
+ const isPinnedByAuthor = mode === DashboardParameterModeValues.READONLY ||
193
+ mode === DashboardParameterModeValues.HIDDEN;
194
+ if (!isPinnedByAuthor) {
195
+ continue;
196
+ }
197
+ const workspaceDefault = isNumberParameterDefinition(workspaceParameter.definition)
198
+ ? workspaceParameter.definition.defaultValue
199
+ : undefined;
200
+ const currentValue = dashboardParameter?.value ?? workspaceDefault;
201
+ if (typeof currentValue === "number" && Number(stored.value) !== currentValue) {
202
+ return true;
203
+ }
204
+ }
205
+ }
206
+ return false;
207
+ }
117
208
  /**
118
209
  * Validate existing automation filters against current dashboard filter context and optionally saved widget / insight.
119
210
  * Check for inconsistencies, that could lead to unwanted results when editing existing automation.