@gooddata/sdk-code-convertors 11.28.0-alpha.1

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 (237) hide show
  1. package/LICENSE +7 -0
  2. package/README.md +42 -0
  3. package/esm/configs/areaChart.d.ts +113 -0
  4. package/esm/configs/areaChart.d.ts.map +1 -0
  5. package/esm/configs/areaChart.js +232 -0
  6. package/esm/configs/areaChart.js.map +1 -0
  7. package/esm/configs/barChart.d.ts +101 -0
  8. package/esm/configs/barChart.d.ts.map +1 -0
  9. package/esm/configs/barChart.js +210 -0
  10. package/esm/configs/barChart.js.map +1 -0
  11. package/esm/configs/bubbleChart.d.ts +93 -0
  12. package/esm/configs/bubbleChart.d.ts.map +1 -0
  13. package/esm/configs/bubbleChart.js +186 -0
  14. package/esm/configs/bubbleChart.js.map +1 -0
  15. package/esm/configs/bulletChart.d.ts +87 -0
  16. package/esm/configs/bulletChart.d.ts.map +1 -0
  17. package/esm/configs/bulletChart.js +174 -0
  18. package/esm/configs/bulletChart.js.map +1 -0
  19. package/esm/configs/columnChart.d.ts +101 -0
  20. package/esm/configs/columnChart.d.ts.map +1 -0
  21. package/esm/configs/columnChart.js +210 -0
  22. package/esm/configs/columnChart.js.map +1 -0
  23. package/esm/configs/comboChart.d.ts +155 -0
  24. package/esm/configs/comboChart.d.ts.map +1 -0
  25. package/esm/configs/comboChart.js +355 -0
  26. package/esm/configs/comboChart.js.map +1 -0
  27. package/esm/configs/dependencyWheelChart.d.ts +37 -0
  28. package/esm/configs/dependencyWheelChart.d.ts.map +1 -0
  29. package/esm/configs/dependencyWheelChart.js +81 -0
  30. package/esm/configs/dependencyWheelChart.js.map +1 -0
  31. package/esm/configs/donutChart.d.ts +47 -0
  32. package/esm/configs/donutChart.d.ts.map +1 -0
  33. package/esm/configs/donutChart.js +96 -0
  34. package/esm/configs/donutChart.js.map +1 -0
  35. package/esm/configs/funnelChart.d.ts +47 -0
  36. package/esm/configs/funnelChart.d.ts.map +1 -0
  37. package/esm/configs/funnelChart.js +96 -0
  38. package/esm/configs/funnelChart.js.map +1 -0
  39. package/esm/configs/geoAreaChart.d.ts +62 -0
  40. package/esm/configs/geoAreaChart.d.ts.map +1 -0
  41. package/esm/configs/geoAreaChart.js +123 -0
  42. package/esm/configs/geoAreaChart.js.map +1 -0
  43. package/esm/configs/geoChart.d.ts +49 -0
  44. package/esm/configs/geoChart.d.ts.map +1 -0
  45. package/esm/configs/geoChart.js +157 -0
  46. package/esm/configs/geoChart.js.map +1 -0
  47. package/esm/configs/headlineChart.d.ts +89 -0
  48. package/esm/configs/headlineChart.d.ts.map +1 -0
  49. package/esm/configs/headlineChart.js +124 -0
  50. package/esm/configs/headlineChart.js.map +1 -0
  51. package/esm/configs/heatmapChart.d.ts +75 -0
  52. package/esm/configs/heatmapChart.d.ts.map +1 -0
  53. package/esm/configs/heatmapChart.js +158 -0
  54. package/esm/configs/heatmapChart.js.map +1 -0
  55. package/esm/configs/lineChart.d.ts +135 -0
  56. package/esm/configs/lineChart.d.ts.map +1 -0
  57. package/esm/configs/lineChart.js +294 -0
  58. package/esm/configs/lineChart.js.map +1 -0
  59. package/esm/configs/pieChart.d.ts +47 -0
  60. package/esm/configs/pieChart.d.ts.map +1 -0
  61. package/esm/configs/pieChart.js +96 -0
  62. package/esm/configs/pieChart.js.map +1 -0
  63. package/esm/configs/pyramidChart.d.ts +47 -0
  64. package/esm/configs/pyramidChart.d.ts.map +1 -0
  65. package/esm/configs/pyramidChart.js +96 -0
  66. package/esm/configs/pyramidChart.js.map +1 -0
  67. package/esm/configs/repeaterChart.d.ts +36 -0
  68. package/esm/configs/repeaterChart.d.ts.map +1 -0
  69. package/esm/configs/repeaterChart.js +104 -0
  70. package/esm/configs/repeaterChart.js.map +1 -0
  71. package/esm/configs/sankeyChart.d.ts +39 -0
  72. package/esm/configs/sankeyChart.d.ts.map +1 -0
  73. package/esm/configs/sankeyChart.js +84 -0
  74. package/esm/configs/sankeyChart.js.map +1 -0
  75. package/esm/configs/scatterChart.d.ts +95 -0
  76. package/esm/configs/scatterChart.d.ts.map +1 -0
  77. package/esm/configs/scatterChart.js +198 -0
  78. package/esm/configs/scatterChart.js.map +1 -0
  79. package/esm/configs/table.d.ts +61 -0
  80. package/esm/configs/table.d.ts.map +1 -0
  81. package/esm/configs/table.js +169 -0
  82. package/esm/configs/table.js.map +1 -0
  83. package/esm/configs/treemapChart.d.ts +47 -0
  84. package/esm/configs/treemapChart.d.ts.map +1 -0
  85. package/esm/configs/treemapChart.js +96 -0
  86. package/esm/configs/treemapChart.js.map +1 -0
  87. package/esm/configs/types.d.ts +93 -0
  88. package/esm/configs/types.d.ts.map +1 -0
  89. package/esm/configs/types.js +3 -0
  90. package/esm/configs/types.js.map +1 -0
  91. package/esm/configs/utils.d.ts +12 -0
  92. package/esm/configs/utils.d.ts.map +1 -0
  93. package/esm/configs/utils.js +76 -0
  94. package/esm/configs/utils.js.map +1 -0
  95. package/esm/configs/waterfallChart.d.ts +109 -0
  96. package/esm/configs/waterfallChart.d.ts.map +1 -0
  97. package/esm/configs/waterfallChart.js +214 -0
  98. package/esm/configs/waterfallChart.js.map +1 -0
  99. package/esm/conts.d.ts +9 -0
  100. package/esm/conts.d.ts.map +1 -0
  101. package/esm/conts.js +41 -0
  102. package/esm/conts.js.map +1 -0
  103. package/esm/execution/buildAfmExecution.d.ts +5 -0
  104. package/esm/execution/buildAfmExecution.d.ts.map +1 -0
  105. package/esm/execution/buildAfmExecution.js +374 -0
  106. package/esm/execution/buildAfmExecution.js.map +1 -0
  107. package/esm/from/declarativeAttributeHierarchyToYaml.d.ts +12 -0
  108. package/esm/from/declarativeAttributeHierarchyToYaml.d.ts.map +1 -0
  109. package/esm/from/declarativeAttributeHierarchyToYaml.js +26 -0
  110. package/esm/from/declarativeAttributeHierarchyToYaml.js.map +1 -0
  111. package/esm/from/declarativeDashboardToYaml.d.ts +59 -0
  112. package/esm/from/declarativeDashboardToYaml.d.ts.map +1 -0
  113. package/esm/from/declarativeDashboardToYaml.js +771 -0
  114. package/esm/from/declarativeDashboardToYaml.js.map +1 -0
  115. package/esm/from/declarativeDatasetToYaml.d.ts +9 -0
  116. package/esm/from/declarativeDatasetToYaml.d.ts.map +1 -0
  117. package/esm/from/declarativeDatasetToYaml.js +239 -0
  118. package/esm/from/declarativeDatasetToYaml.js.map +1 -0
  119. package/esm/from/declarativeDateInstanceToYaml.d.ts +8 -0
  120. package/esm/from/declarativeDateInstanceToYaml.d.ts.map +1 -0
  121. package/esm/from/declarativeDateInstanceToYaml.js +30 -0
  122. package/esm/from/declarativeDateInstanceToYaml.js.map +1 -0
  123. package/esm/from/declarativeMetricToYaml.d.ts +8 -0
  124. package/esm/from/declarativeMetricToYaml.d.ts.map +1 -0
  125. package/esm/from/declarativeMetricToYaml.js +34 -0
  126. package/esm/from/declarativeMetricToYaml.js.map +1 -0
  127. package/esm/from/declarativePluginToYaml.d.ts +10 -0
  128. package/esm/from/declarativePluginToYaml.d.ts.map +1 -0
  129. package/esm/from/declarativePluginToYaml.js +26 -0
  130. package/esm/from/declarativePluginToYaml.js.map +1 -0
  131. package/esm/from/declarativeVisualisationToYaml.d.ts +64 -0
  132. package/esm/from/declarativeVisualisationToYaml.d.ts.map +1 -0
  133. package/esm/from/declarativeVisualisationToYaml.js +1513 -0
  134. package/esm/from/declarativeVisualisationToYaml.js.map +1 -0
  135. package/esm/index.d.ts +18 -0
  136. package/esm/index.d.ts.map +1 -0
  137. package/esm/index.js +22 -0
  138. package/esm/index.js.map +1 -0
  139. package/esm/schemas/types.d.ts +32 -0
  140. package/esm/schemas/types.d.ts.map +1 -0
  141. package/esm/schemas/types.js +3 -0
  142. package/esm/schemas/types.js.map +1 -0
  143. package/esm/schemas/v1/metadata.d.ts +7277 -0
  144. package/esm/schemas/v1/metadata.d.ts.map +1 -0
  145. package/esm/schemas/v1/metadata.js +3 -0
  146. package/esm/schemas/v1/metadata.js.map +1 -0
  147. package/esm/sdk-code-convertors.d.ts +7861 -0
  148. package/esm/to/yamlAttributeHierarchyToDeclarative.d.ts +5 -0
  149. package/esm/to/yamlAttributeHierarchyToDeclarative.d.ts.map +1 -0
  150. package/esm/to/yamlAttributeHierarchyToDeclarative.js +16 -0
  151. package/esm/to/yamlAttributeHierarchyToDeclarative.js.map +1 -0
  152. package/esm/to/yamlDashboardToDeclarative.d.ts +29 -0
  153. package/esm/to/yamlDashboardToDeclarative.d.ts.map +1 -0
  154. package/esm/to/yamlDashboardToDeclarative.js +732 -0
  155. package/esm/to/yamlDashboardToDeclarative.js.map +1 -0
  156. package/esm/to/yamlDatasetToDeclarative.d.ts +41 -0
  157. package/esm/to/yamlDatasetToDeclarative.d.ts.map +1 -0
  158. package/esm/to/yamlDatasetToDeclarative.js +346 -0
  159. package/esm/to/yamlDatasetToDeclarative.js.map +1 -0
  160. package/esm/to/yamlDateDatasetToDeclarative.d.ts +5 -0
  161. package/esm/to/yamlDateDatasetToDeclarative.d.ts.map +1 -0
  162. package/esm/to/yamlDateDatasetToDeclarative.js +21 -0
  163. package/esm/to/yamlDateDatasetToDeclarative.js.map +1 -0
  164. package/esm/to/yamlMetricToDeclarative.d.ts +5 -0
  165. package/esm/to/yamlMetricToDeclarative.d.ts.map +1 -0
  166. package/esm/to/yamlMetricToDeclarative.js +24 -0
  167. package/esm/to/yamlMetricToDeclarative.js.map +1 -0
  168. package/esm/to/yamlPluginToDeclarative.d.ts +5 -0
  169. package/esm/to/yamlPluginToDeclarative.d.ts.map +1 -0
  170. package/esm/to/yamlPluginToDeclarative.js +17 -0
  171. package/esm/to/yamlPluginToDeclarative.js.map +1 -0
  172. package/esm/to/yamlVisualisationToDeclarative.d.ts +31 -0
  173. package/esm/to/yamlVisualisationToDeclarative.d.ts.map +1 -0
  174. package/esm/to/yamlVisualisationToDeclarative.js +1048 -0
  175. package/esm/to/yamlVisualisationToDeclarative.js.map +1 -0
  176. package/esm/tsdoc-metadata.json +11 -0
  177. package/esm/types.d.ts +66 -0
  178. package/esm/types.d.ts.map +1 -0
  179. package/esm/types.js +22 -0
  180. package/esm/types.js.map +1 -0
  181. package/esm/utils/configUtils.d.ts +20 -0
  182. package/esm/utils/configUtils.d.ts.map +1 -0
  183. package/esm/utils/configUtils.js +312 -0
  184. package/esm/utils/configUtils.js.map +1 -0
  185. package/esm/utils/convertBucketToTitle.d.ts +116 -0
  186. package/esm/utils/convertBucketToTitle.d.ts.map +1 -0
  187. package/esm/utils/convertBucketToTitle.js +370 -0
  188. package/esm/utils/convertBucketToTitle.js.map +1 -0
  189. package/esm/utils/customUrl.d.ts +4 -0
  190. package/esm/utils/customUrl.d.ts.map +1 -0
  191. package/esm/utils/customUrl.js +31 -0
  192. package/esm/utils/customUrl.js.map +1 -0
  193. package/esm/utils/dateUtils.d.ts +5 -0
  194. package/esm/utils/dateUtils.d.ts.map +1 -0
  195. package/esm/utils/dateUtils.js +43 -0
  196. package/esm/utils/dateUtils.js.map +1 -0
  197. package/esm/utils/errors.d.ts +35 -0
  198. package/esm/utils/errors.d.ts.map +1 -0
  199. package/esm/utils/errors.js +65 -0
  200. package/esm/utils/errors.js.map +1 -0
  201. package/esm/utils/filterUtils.d.ts +3 -0
  202. package/esm/utils/filterUtils.d.ts.map +1 -0
  203. package/esm/utils/filterUtils.js +26 -0
  204. package/esm/utils/filterUtils.js.map +1 -0
  205. package/esm/utils/granularityUtils.d.ts +17 -0
  206. package/esm/utils/granularityUtils.d.ts.map +1 -0
  207. package/esm/utils/granularityUtils.js +1434 -0
  208. package/esm/utils/granularityUtils.js.map +1 -0
  209. package/esm/utils/locationUtils.d.ts +11 -0
  210. package/esm/utils/locationUtils.d.ts.map +1 -0
  211. package/esm/utils/locationUtils.js +75 -0
  212. package/esm/utils/locationUtils.js.map +1 -0
  213. package/esm/utils/nameUtils.d.ts +7 -0
  214. package/esm/utils/nameUtils.d.ts.map +1 -0
  215. package/esm/utils/nameUtils.js +37 -0
  216. package/esm/utils/nameUtils.js.map +1 -0
  217. package/esm/utils/permissionUtils.d.ts +29 -0
  218. package/esm/utils/permissionUtils.d.ts.map +1 -0
  219. package/esm/utils/permissionUtils.js +82 -0
  220. package/esm/utils/permissionUtils.js.map +1 -0
  221. package/esm/utils/sharedUtils.d.ts +21 -0
  222. package/esm/utils/sharedUtils.d.ts.map +1 -0
  223. package/esm/utils/sharedUtils.js +63 -0
  224. package/esm/utils/sharedUtils.js.map +1 -0
  225. package/esm/utils/texts.d.ts +8 -0
  226. package/esm/utils/texts.d.ts.map +1 -0
  227. package/esm/utils/texts.js +47 -0
  228. package/esm/utils/texts.js.map +1 -0
  229. package/esm/utils/typeGuards.d.ts +51 -0
  230. package/esm/utils/typeGuards.d.ts.map +1 -0
  231. package/esm/utils/typeGuards.js +286 -0
  232. package/esm/utils/typeGuards.js.map +1 -0
  233. package/esm/utils/yamlUtils.d.ts +28 -0
  234. package/esm/utils/yamlUtils.d.ts.map +1 -0
  235. package/esm/utils/yamlUtils.js +163 -0
  236. package/esm/utils/yamlUtils.js.map +1 -0
  237. package/package.json +74 -0
@@ -0,0 +1,771 @@
1
+ // (C) 2023-2026 GoodData Corporation
2
+ import { Document, Pair, YAMLMap, YAMLSeq } from "yaml";
3
+ import { dashboardFilterReferenceObjRef, isAttributeElementsByRef, isAttributeElementsByValue, isAttributeHierarchyReference, isDashboardAttributeFilter, isDashboardDateFilter, isDrillToAttributeUrl, isDrillToCustomUrl, isDrillToDashboard, isDrillToInsight, isNoopAllTimeDashboardDateFilter, isRelativeDashboardDateFilter, } from "@gooddata/sdk-model";
4
+ import { VisualisationsTypes } from "../conts.js";
5
+ import { serializeUrlTarget } from "../utils/customUrl.js";
6
+ import { CoreErrorCode, newError } from "../utils/errors.js";
7
+ import { parseGranularity } from "../utils/granularityUtils.js";
8
+ import { fromDeclarativePermissions } from "../utils/permissionUtils.js";
9
+ import { DASHBOARD_COMMENT } from "../utils/texts.js";
10
+ import { createFilterContextItemKeyName, entryWithSpace, fillOptionalMetaFields, getIdentifier, } from "../utils/yamlUtils.js";
11
+ /** @public */
12
+ export function declarativeDashboardToYaml(entities, dashboard, filterContexts) {
13
+ const content = dashboard.content;
14
+ // Create new doc and add mandatory fields right away
15
+ const doc = new Document({
16
+ type: "dashboard",
17
+ id: dashboard.id,
18
+ });
19
+ // Add intro comment to the document
20
+ doc.commentBefore = DASHBOARD_COMMENT;
21
+ // Add optional meta fields
22
+ fillOptionalMetaFields(doc, dashboard);
23
+ //settings
24
+ if (content.disableCrossFiltering) {
25
+ doc.add(entryWithSpace("cross_filtering", false));
26
+ }
27
+ if (content.disableUserFilterReset) {
28
+ doc.add(entryWithSpace("user_filters_reset", false));
29
+ }
30
+ if (content.disableUserFilterSave) {
31
+ doc.add(entryWithSpace("user_filters_save", false));
32
+ }
33
+ if (content.disableFilterViews) {
34
+ doc.add(entryWithSpace("filter_views", false));
35
+ }
36
+ // Add enable_section_headers
37
+ if (content.layout?.configuration?.sections?.enableHeader) {
38
+ doc.add(entryWithSpace("enable_section_headers", content.layout?.configuration?.sections?.enableHeader));
39
+ }
40
+ // Add dashboard tabs
41
+ // Note: If there's only 1 tab without a title (implicit first tab visible in edit mode),
42
+ // treat as "no tabs" and use sections format to preserve previous YAML structure
43
+ const hasMultipleTabs = content.tabs && content.tabs.length > 1;
44
+ const hasSingleTabWithTitle = content.tabs && content.tabs.length === 1 && content.tabs[0].title;
45
+ const shouldUseTabs = hasMultipleTabs || hasSingleTabWithTitle;
46
+ if (content.tabs && shouldUseTabs) {
47
+ const tabs = declarativeTabsToYaml(content.tabs, filterContexts, entities);
48
+ if (tabs) {
49
+ doc.add(entryWithSpace("tabs", tabs));
50
+ }
51
+ }
52
+ else if (content.tabs && content.tabs.length === 1) {
53
+ // Dashboard with implicit single tab - create root yaml structure like without tabs
54
+ // but read all metadata from a single tab
55
+ const tab = content.tabs[0];
56
+ const section = declarativeSectionsToYaml(tab.layout, entities);
57
+ if (section) {
58
+ doc.add(entryWithSpace("sections", section));
59
+ }
60
+ const filterContextId = tab.filterContextRef ? getIdentifier(tab.filterContextRef, true) : undefined;
61
+ const { filters, filtersMap } = declarativeFilterContextToYaml(tab.dateFilterConfig, filterContexts?.find((fc) => fc.id === filterContextId));
62
+ declarativeFiltersConfigToYaml(filtersMap, tab.dateFilterConfig, tab.dateFilterConfigs, tab.attributeFilterConfigs);
63
+ const groupedFilters = declarativeFilterGroupsToYaml(filters, tab.filterGroupsConfig);
64
+ if (groupedFilters.items.length > 0) {
65
+ doc.add(entryWithSpace("filters", groupedFilters));
66
+ }
67
+ }
68
+ else {
69
+ // Dashboard without tabs - add sections and filters
70
+ const section = declarativeSectionsToYaml(content.layout, entities);
71
+ if (section) {
72
+ doc.add(entryWithSpace("sections", section));
73
+ }
74
+ const filterContextId = content.filterContextRef
75
+ ? getIdentifier(content.filterContextRef, true)
76
+ : undefined;
77
+ const { filters, filtersMap } = declarativeFilterContextToYaml(content.dateFilterConfig, filterContexts?.find((fc) => fc.id === filterContextId));
78
+ declarativeFiltersConfigToYaml(filtersMap, content.dateFilterConfig, content.dateFilterConfigs, content.attributeFilterConfigs);
79
+ if (filters.items.length > 0) {
80
+ doc.add(entryWithSpace("filters", filters));
81
+ }
82
+ }
83
+ // Add KD plugins definitions
84
+ const plugins = declarativePluginsToYaml(content);
85
+ if (plugins) {
86
+ doc.add(entryWithSpace("plugins", plugins));
87
+ }
88
+ // Add dashboard permissions
89
+ const permissions = declarativePermissionsToYaml(doc, dashboard);
90
+ if (permissions) {
91
+ doc.add(entryWithSpace("permissions", permissions));
92
+ }
93
+ return {
94
+ content: doc.toString({
95
+ lineWidth: 0,
96
+ }),
97
+ json: doc.toJSON(),
98
+ };
99
+ }
100
+ export function declarativeTabsToYaml(tabs, filterContexts, entities) {
101
+ // no tabs
102
+ if (!tabs || tabs.length === 0) {
103
+ return;
104
+ }
105
+ const yamlTabs = new YAMLSeq();
106
+ tabs.forEach((tab) => {
107
+ const yamlTab = new YAMLMap();
108
+ // Add tab id and name
109
+ yamlTab.add(new Pair("id", tab.localIdentifier));
110
+ yamlTab.add(new Pair("title", tab.title));
111
+ // Add tab filters
112
+ let filterContext;
113
+ if (tab.filterContextRef && filterContexts?.length) {
114
+ const filterContextId = getIdentifier(tab.filterContextRef, true);
115
+ filterContext = filterContexts.find((fc) => fc.id === filterContextId);
116
+ }
117
+ if (filterContext) {
118
+ const { filters, filtersMap } = declarativeFilterContextToYaml(tab.dateFilterConfig, filterContext);
119
+ declarativeFiltersConfigToYaml(filtersMap, tab.dateFilterConfig, tab.dateFilterConfigs, tab.attributeFilterConfigs);
120
+ const groupedFilters = declarativeFilterGroupsToYaml(filters, tab.filterGroupsConfig);
121
+ if (groupedFilters.items.length > 0) {
122
+ yamlTab.add(new Pair("filters", groupedFilters));
123
+ }
124
+ }
125
+ // Add tab sections
126
+ if (tab.layout) {
127
+ const tempDashboard = {
128
+ layout: tab.layout,
129
+ };
130
+ const sections = declarativeSectionsToYaml(tempDashboard.layout, entities);
131
+ if (sections) {
132
+ yamlTab.add(new Pair("sections", sections));
133
+ }
134
+ }
135
+ yamlTabs.add(yamlTab);
136
+ });
137
+ return yamlTabs;
138
+ }
139
+ export function declarativeSectionsToYaml(layout, entities) {
140
+ //no sections at all
141
+ if (!layout?.sections?.length) {
142
+ return;
143
+ }
144
+ const sections = new YAMLSeq();
145
+ layout.sections.forEach((section) => {
146
+ const yamlSection = new YAMLMap();
147
+ if (section.header?.title) {
148
+ yamlSection.add(new Pair("title", section.header.title));
149
+ }
150
+ if (section.header?.description) {
151
+ yamlSection.add(new Pair("description", section.header.description));
152
+ }
153
+ if (section.items?.length) {
154
+ const items = new YAMLSeq();
155
+ section.items.forEach((item) => {
156
+ const widget = declarativeWidgetToYaml(item.widget, item.size, entities);
157
+ if (widget) {
158
+ items.add(widget);
159
+ }
160
+ });
161
+ yamlSection.add(new Pair("widgets", items));
162
+ }
163
+ sections.add(yamlSection);
164
+ });
165
+ return sections;
166
+ }
167
+ export function declarativeWidgetToYaml(widget, size, entities) {
168
+ if (!widget) {
169
+ return;
170
+ }
171
+ switch (widget?.type) {
172
+ case "insight":
173
+ return declarativeInsightWidgetToYaml(widget, size, entities);
174
+ case "richText":
175
+ return declarativeRichTextWidgetToYaml(widget, size);
176
+ case "visualizationSwitcher":
177
+ return declarativeVisualizationSwitcherWidgetToYaml(widget, size, entities);
178
+ case "IDashboardLayout":
179
+ return declarativeContainerWidgetToYaml(widget, size, entities);
180
+ default:
181
+ throw newError(CoreErrorCode.ReferenceTypeNotSupported, [String(widget?.type)]);
182
+ }
183
+ }
184
+ export function declarativeInsightWidgetToYaml(widget, size, entities) {
185
+ const yamlWidget = new YAMLMap();
186
+ // Local id of widget
187
+ if (widget.localIdentifier) {
188
+ yamlWidget.add(new Pair("id", widget.localIdentifier));
189
+ }
190
+ // The visualization
191
+ yamlWidget.add(new Pair("visualization", getIdentifier(widget.insight, true)));
192
+ // Title
193
+ if (widget.configuration?.hideTitle) {
194
+ yamlWidget.add(new Pair("title", false));
195
+ }
196
+ else if (widget.title) {
197
+ yamlWidget.add(new Pair("title", widget.title));
198
+ }
199
+ // Description
200
+ if (widget.configuration?.description?.visible === false) {
201
+ yamlWidget.add(new Pair("description", false));
202
+ }
203
+ else if (widget.configuration?.description?.source === "insight") {
204
+ //NOTE: Inherit description is default, so do not add it into yaml
205
+ }
206
+ else if (widget.description) {
207
+ yamlWidget.add(new Pair("description", widget.description));
208
+ }
209
+ // Size
210
+ if (size?.xl?.gridWidth) {
211
+ yamlWidget.add(new Pair("columns", size.xl.gridWidth));
212
+ }
213
+ if (size?.xl?.gridHeight) {
214
+ yamlWidget.add(new Pair("rows", size.xl.gridHeight));
215
+ }
216
+ // Filtering
217
+ if (widget.dateDataSet) {
218
+ yamlWidget.add(new Pair("date", getIdentifier(widget.dateDataSet, true)));
219
+ }
220
+ if (widget.ignoreDashboardFilters?.length) {
221
+ yamlWidget.add(new Pair("ignored_filters", widget.ignoreDashboardFilters.map((df) => {
222
+ return getIdentifier(dashboardFilterReferenceObjRef(df));
223
+ })));
224
+ }
225
+ // Interactions
226
+ if (widget.properties?.["controls"]?.zoomInsight) {
227
+ yamlWidget.add(new Pair("zoom_data", true));
228
+ }
229
+ if (widget.drills?.length) {
230
+ const drills = new YAMLSeq();
231
+ const sourceVisualizationId = getIdentifier(widget.insight, true);
232
+ widget.drills.forEach((drill) => {
233
+ drills.add(declarativeDrillToYaml(drill, entities, sourceVisualizationId));
234
+ });
235
+ yamlWidget.add(new Pair("interactions", drills));
236
+ }
237
+ if (widget.ignoredDrillDownHierarchies?.length) {
238
+ const ignores = widget.ignoredDrillDownHierarchies.map((hierarchy) => declarativeIgnoreDrillDownHierarchyToYaml(hierarchy));
239
+ yamlWidget.add(new Pair("ignored_drill_downs", ignores));
240
+ }
241
+ if (widget.drillDownIntersectionIgnoredAttributes?.length) {
242
+ const ignores = widget.drillDownIntersectionIgnoredAttributes
243
+ .map((hierarchy) => declarativeDrillDownIntersectionIgnoredAttributesToYaml(hierarchy))
244
+ .filter(Boolean);
245
+ yamlWidget.add(new Pair("ignored_drill_downs_intersections", ignores));
246
+ }
247
+ // Cross filtering
248
+ if (widget.ignoreCrossFiltering) {
249
+ yamlWidget.add(new Pair("ignored_cross_filtering", true));
250
+ }
251
+ return yamlWidget;
252
+ }
253
+ export function declarativeIgnoreDrillDownHierarchyToYaml(hierarchy) {
254
+ if (isAttributeHierarchyReference(hierarchy)) {
255
+ return {
256
+ hierarchy: hierarchy.attributeHierarchy,
257
+ on: getIdentifier(hierarchy.attribute),
258
+ };
259
+ }
260
+ return {
261
+ template: hierarchy.dateHierarchyTemplate,
262
+ on: getIdentifier(hierarchy.dateDatasetAttribute),
263
+ };
264
+ }
265
+ export function declarativeDrillDownIntersectionIgnoredAttributesToYaml(hierarchy) {
266
+ if (hierarchy.ignoredAttributes.length === 0) {
267
+ return null;
268
+ }
269
+ return {
270
+ attributes: hierarchy.ignoredAttributes,
271
+ hierarchy: declarativeIgnoreDrillDownHierarchyToYaml(hierarchy.drillDownReference),
272
+ };
273
+ }
274
+ export function declarativeRichTextWidgetToYaml(widget, size) {
275
+ const yamlWidget = new YAMLMap();
276
+ // Local id of widget
277
+ if (widget.localIdentifier) {
278
+ yamlWidget.add(new Pair("id", widget.localIdentifier));
279
+ }
280
+ // The visualization
281
+ yamlWidget.add(new Pair("content", widget.content));
282
+ // Size
283
+ if (size?.xl?.gridWidth) {
284
+ yamlWidget.add(new Pair("columns", size.xl.gridWidth));
285
+ }
286
+ if (size?.xl?.gridHeight) {
287
+ yamlWidget.add(new Pair("rows", size.xl.gridHeight));
288
+ }
289
+ return yamlWidget;
290
+ }
291
+ export function declarativeVisualizationSwitcherWidgetToYaml(widget, size, entities) {
292
+ const yamlWidget = new YAMLMap();
293
+ // Local id of widget
294
+ if (widget.localIdentifier) {
295
+ yamlWidget.add(new Pair("id", widget.localIdentifier));
296
+ }
297
+ // The visualizations
298
+ yamlWidget.add(new Pair("visualizations", widget.visualizations.map((vis) => declarativeInsightWidgetToYaml(vis, undefined, entities))));
299
+ // Size
300
+ if (size?.xl?.gridWidth) {
301
+ yamlWidget.add(new Pair("columns", size.xl.gridWidth));
302
+ }
303
+ if (size?.xl?.gridHeight) {
304
+ yamlWidget.add(new Pair("rows", size.xl.gridHeight));
305
+ }
306
+ return yamlWidget;
307
+ }
308
+ export function declarativeContainerWidgetToYaml(widget, size, entities) {
309
+ const yamlWidget = new YAMLMap();
310
+ // Local id of widget
311
+ if (widget.localIdentifier) {
312
+ yamlWidget.add(new Pair("container", widget.localIdentifier));
313
+ }
314
+ // Size
315
+ if (size?.xl?.gridWidth) {
316
+ yamlWidget.add(new Pair("columns", size.xl.gridWidth));
317
+ }
318
+ if (size?.xl?.gridHeight) {
319
+ yamlWidget.add(new Pair("rows", size.xl.gridHeight));
320
+ }
321
+ // Layout direction
322
+ if (widget.configuration?.direction) {
323
+ yamlWidget.add(new Pair("layout_direction", widget.configuration?.direction));
324
+ }
325
+ // Enable header configuration
326
+ if (widget.configuration?.sections) {
327
+ yamlWidget.add(new Pair("enable_section_headers", widget.configuration.sections.enableHeader));
328
+ }
329
+ // Nested sections
330
+ if (widget.sections?.length) {
331
+ const nestedSections = new YAMLSeq();
332
+ widget.sections.forEach((section) => {
333
+ const yamlSection = new YAMLMap();
334
+ if (section.header?.title) {
335
+ yamlSection.add(new Pair("title", section.header.title));
336
+ }
337
+ if (section.header?.description) {
338
+ yamlSection.add(new Pair("description", section.header.description));
339
+ }
340
+ if (section.items?.length) {
341
+ const widgets = new YAMLSeq();
342
+ section.items.forEach((item) => {
343
+ const yamlNestedWidget = declarativeWidgetToYaml(item.widget, item.size, entities);
344
+ if (yamlNestedWidget) {
345
+ widgets.add(yamlNestedWidget);
346
+ }
347
+ });
348
+ yamlSection.add(new Pair("widgets", widgets));
349
+ }
350
+ nestedSections.add(yamlSection);
351
+ });
352
+ yamlWidget.add(new Pair("sections", nestedSections));
353
+ }
354
+ return yamlWidget;
355
+ }
356
+ export function declarativeDrillToYaml(drill, entities, sourceVisualizationId) {
357
+ const drillYaml = new YAMLMap();
358
+ const originIdentifier = drill.origin.type === "drillFromMeasure" ? drill.origin.measure : drill.origin.attribute;
359
+ drillYaml.add(new Pair("click_on", getIdentifier(originIdentifier)));
360
+ if (isDrillToInsight(drill)) {
361
+ drillYaml.add(new Pair("open_visualization", getIdentifier(drill.target, true)));
362
+ const filters = drillFiltersToYaml(drill, entities, sourceVisualizationId);
363
+ if (filters) {
364
+ drillYaml.add(new Pair("filters", filters));
365
+ }
366
+ return drillYaml;
367
+ }
368
+ if (isDrillToDashboard(drill) && drill.target) {
369
+ const dashboardDrill = drill;
370
+ drillYaml.add(new Pair("open_dashboard", getIdentifier(drill.target, true)));
371
+ if (drill.targetTabLocalIdentifier) {
372
+ drillYaml.add(new Pair("open_dashboard_tab", drill.targetTabLocalIdentifier));
373
+ }
374
+ const filters = drillFiltersToYaml(dashboardDrill, entities, sourceVisualizationId);
375
+ if (filters) {
376
+ drillYaml.add(new Pair("filters", filters));
377
+ }
378
+ return drillYaml;
379
+ }
380
+ if (isDrillToCustomUrl(drill)) {
381
+ if (drill.drillIntersectionIgnoredAttributes?.length) {
382
+ const attrs = new YAMLSeq();
383
+ drill.drillIntersectionIgnoredAttributes.forEach((attr) => attrs.add(attr));
384
+ drillYaml.add(new Pair("ignored_intersection_attributes", attrs));
385
+ }
386
+ drillYaml.add(new Pair("open_url", serializeUrlTarget(drill.target.url)));
387
+ return drillYaml;
388
+ }
389
+ if (isDrillToAttributeUrl(drill)) {
390
+ if (drill.drillIntersectionIgnoredAttributes?.length) {
391
+ const attrs = new YAMLSeq();
392
+ drill.drillIntersectionIgnoredAttributes.forEach((attr) => attrs.add(attr));
393
+ drillYaml.add(new Pair("ignored_intersection_attributes", attrs));
394
+ }
395
+ drillYaml.add(new Pair("open_url", {
396
+ label: getIdentifier(drill.target.displayForm),
397
+ href: getIdentifier(drill.target.hyperlinkDisplayForm),
398
+ }));
399
+ return drillYaml;
400
+ }
401
+ return drillYaml;
402
+ }
403
+ function drillFiltersToYaml(drill, entities, sourceVisualizationId) {
404
+ const filtersYaml = new YAMLMap();
405
+ const excludeYaml = new YAMLMap();
406
+ const includeYaml = new YAMLMap();
407
+ if (drill.drillIntersectionIgnoredAttributes?.length) {
408
+ const attrs = new YAMLSeq();
409
+ drill.drillIntersectionIgnoredAttributes.forEach((attr) => attrs.add(attr));
410
+ excludeYaml.add(new Pair("drilled_datapoint", attrs));
411
+ }
412
+ if (drill.ignoredDashboardFilters?.length) {
413
+ const filters = new YAMLSeq();
414
+ drill.ignoredDashboardFilters.forEach((filter) => filters.add(filter));
415
+ excludeYaml.add(new Pair("dashboard_filters", filters));
416
+ }
417
+ if (drill.includedSourceInsightFiltersObjRefs?.length) {
418
+ includeYaml.add(new Pair("visualization_filters", filterRefsToYaml(drill.includedSourceInsightFiltersObjRefs, entities, sourceVisualizationId)));
419
+ }
420
+ if (drill.includedSourceMeasureFiltersObjRefs?.length) {
421
+ includeYaml.add(new Pair("metric_filters", filterRefsToYaml(drill.includedSourceMeasureFiltersObjRefs, entities, sourceVisualizationId)));
422
+ }
423
+ if (excludeYaml.items.length) {
424
+ filtersYaml.add(new Pair("exclude", excludeYaml));
425
+ }
426
+ if (includeYaml.items.length) {
427
+ filtersYaml.add(new Pair("include", includeYaml));
428
+ }
429
+ return filtersYaml.items.length ? filtersYaml : null;
430
+ }
431
+ function filterRefsToYaml(refs, entities, sourceVisualizationId) {
432
+ const visualisation = entities?.find((entity) => VisualisationsTypes.includes(entity.type) && entity.id === sourceVisualizationId)?.data;
433
+ const filters = visualisation?.query?.filter_by;
434
+ return refs
435
+ .map((ref) => findSourceInsightFilterId(filters, ref) ?? sourceInsightFilterRefFallbackId(ref))
436
+ .filter(Boolean);
437
+ }
438
+ function findSourceInsightFilterId(filters, ref) {
439
+ if (!filters) {
440
+ return undefined;
441
+ }
442
+ return Object.entries(filters).find(([_, filter]) => matchesSourceInsightFilterRef(filter, ref))?.[0];
443
+ }
444
+ function matchesSourceInsightFilterRef(filter, ref) {
445
+ switch (ref.type) {
446
+ case "attributeFilter":
447
+ return filter.type === "attribute_filter" && filter.using === getIdentifier(ref["label"]);
448
+ case "dateFilter":
449
+ return filter.type === "date_filter" && filter.using === getIdentifier(ref["dataSet"], true);
450
+ case "measureValueFilter":
451
+ return filter.type === "metric_value_filter" && filter.using === getIdentifier(ref["measure"]);
452
+ case "rankingFilter":
453
+ return filter.type === "ranking_filter" && filter.using === getIdentifier(ref["measure"]);
454
+ default:
455
+ return false;
456
+ }
457
+ }
458
+ function sourceInsightFilterRefFallbackId(ref) {
459
+ switch (ref.type) {
460
+ case "attributeFilter":
461
+ return getIdentifier(ref["label"]);
462
+ case "dateFilter":
463
+ return getIdentifier(ref["dataSet"], true);
464
+ case "measureValueFilter":
465
+ case "rankingFilter":
466
+ return getIdentifier(ref["measure"]);
467
+ default:
468
+ return null;
469
+ }
470
+ }
471
+ function getDateFilterEmptyValueHandling(filter) {
472
+ const value = filter.dateFilter.emptyValueHandling;
473
+ if (value === "include" || value === "exclude" || value === "only") {
474
+ return value;
475
+ }
476
+ return undefined;
477
+ }
478
+ export function declarativeFilterContextToYaml(dateFilterConfig, filterContext) {
479
+ const filters = [];
480
+ const filtersMap = {};
481
+ const content = filterContext ? filterContext.content : undefined;
482
+ const declarativeFilters = content?.filters ?? [];
483
+ declarativeFilters.forEach((filter) => {
484
+ if (isDashboardDateFilter(filter) && isNoopAllTimeDashboardDateFilter(filter)) {
485
+ return;
486
+ }
487
+ const key = createFilterContextItemKeyName(filter);
488
+ if (isDashboardDateFilter(filter)) {
489
+ const def = declarativeDateFilterToYaml(filter);
490
+ filters.push(new Pair(key, def));
491
+ filtersMap[key] = {
492
+ yaml: def,
493
+ filter: filter,
494
+ };
495
+ }
496
+ if (isDashboardAttributeFilter(filter)) {
497
+ const def = declarativeAttributeFilterToYaml(filter);
498
+ filters.push(new Pair(key, def));
499
+ filtersMap[key] = {
500
+ yaml: def,
501
+ filter: filter,
502
+ };
503
+ }
504
+ });
505
+ // create default date if config is specified but no common date
506
+ const commonFilter = declarativeFilters.find((filter) => {
507
+ if (isDashboardDateFilter(filter)) {
508
+ return !filter.dateFilter.dataSet;
509
+ }
510
+ return false;
511
+ });
512
+ if (!commonFilter && dateFilterConfig) {
513
+ const filter = {
514
+ dateFilter: {
515
+ granularity: "GDC.time.date",
516
+ type: "absolute",
517
+ },
518
+ };
519
+ const key = createFilterContextItemKeyName(filter, "common");
520
+ const def = declarativeDateFilterToYaml(filter);
521
+ filters.unshift(new Pair(key, def));
522
+ filtersMap[key] = {
523
+ yaml: def,
524
+ filter: filter,
525
+ };
526
+ }
527
+ Object.values(filtersMap).forEach(({ filter, yaml }) => {
528
+ if (isDashboardAttributeFilter(filter)) {
529
+ //parents attribute filters
530
+ const attrsIds = filter.attributeFilter.filterElementsBy
531
+ ?.map((element) => {
532
+ return element.filterLocalIdentifier ?? null;
533
+ })
534
+ .filter(Boolean);
535
+ //parents date filters
536
+ const datesIds = filter.attributeFilter.filterElementsByDate
537
+ ?.map((element) => {
538
+ if (!element.isCommonDate && element.filterLocalIdentifier) {
539
+ return {
540
+ using: element.filterLocalIdentifier,
541
+ common: element.isCommonDate,
542
+ };
543
+ }
544
+ return element.filterLocalIdentifier ?? null;
545
+ })
546
+ .filter(Boolean);
547
+ const ids = [...(attrsIds ?? []), ...(datesIds ?? [])];
548
+ if (ids?.length) {
549
+ yaml.add(new Pair("parents", ids));
550
+ }
551
+ //metric filters
552
+ const metricsIds = filter.attributeFilter.validateElementsBy
553
+ ?.map((element) => getIdentifier(element))
554
+ .filter(Boolean);
555
+ if (metricsIds?.length) {
556
+ yaml.add(new Pair("metric_filters", metricsIds));
557
+ }
558
+ }
559
+ });
560
+ return {
561
+ filters: filters.reduce((map, filter) => {
562
+ map.add(filter);
563
+ return map;
564
+ }, new YAMLMap()),
565
+ filtersMap,
566
+ };
567
+ }
568
+ function declarativeDateFilterToYaml(filter) {
569
+ const dateFilter = new YAMLMap();
570
+ dateFilter.add(new Pair("type", "date_filter"));
571
+ const gran = parseGranularity(filter.dateFilter.granularity);
572
+ if (gran !== "DAY") {
573
+ dateFilter.add(new Pair("granularity", gran));
574
+ }
575
+ if (filter.dateFilter.dataSet) {
576
+ dateFilter.add(new Pair("date", getIdentifier(filter.dateFilter.dataSet, true)));
577
+ }
578
+ if (isRelativeDashboardDateFilter(filter)) {
579
+ // Relative filter
580
+ // Casting and parsing cause server may return string sometimes, invalid typing...
581
+ if (typeof filter.dateFilter.from === "number" && typeof filter.dateFilter.to === "number") {
582
+ dateFilter.add(new Pair("from", parseInt(String(filter.dateFilter.from), 10)));
583
+ dateFilter.add(new Pair("to", parseInt(String(filter.dateFilter.to), 10)));
584
+ }
585
+ }
586
+ else {
587
+ // Absolute filter
588
+ if (filter.dateFilter.from) {
589
+ dateFilter.add(new Pair("from", filter.dateFilter.from));
590
+ }
591
+ if (filter.dateFilter.to) {
592
+ dateFilter.add(new Pair("to", filter.dateFilter.to));
593
+ }
594
+ }
595
+ const emptyValueHandling = getDateFilterEmptyValueHandling(filter);
596
+ if (emptyValueHandling) {
597
+ dateFilter.add(new Pair("empty_values", emptyValueHandling));
598
+ }
599
+ return dateFilter;
600
+ }
601
+ function declarativeAttributeFilterToYaml(filter) {
602
+ const attributeFilter = new YAMLMap();
603
+ attributeFilter.add(new Pair("type", "attribute_filter"));
604
+ if (filter.attributeFilter.title) {
605
+ attributeFilter.add(new Pair("title", filter.attributeFilter.title));
606
+ }
607
+ const attributeId = getIdentifier(filter.attributeFilter.displayForm);
608
+ attributeFilter.add(new Pair("using", attributeId));
609
+ if (filter.attributeFilter.selectionMode === "single") {
610
+ attributeFilter.add(new Pair("multiselect", false));
611
+ }
612
+ let values = [];
613
+ if (isAttributeElementsByValue(filter.attributeFilter.attributeElements)) {
614
+ values = filter.attributeFilter.attributeElements.values;
615
+ }
616
+ if (isAttributeElementsByRef(filter.attributeFilter.attributeElements)) {
617
+ values = filter.attributeFilter.attributeElements.uris;
618
+ }
619
+ if (!filter.attributeFilter.negativeSelection) {
620
+ const state = new YAMLMap();
621
+ state.add(new Pair("include", values));
622
+ attributeFilter.add(new Pair("state", state));
623
+ }
624
+ if (filter.attributeFilter.negativeSelection && values.length) {
625
+ const state = new YAMLMap();
626
+ state.add(new Pair("exclude", values));
627
+ attributeFilter.add(new Pair("state", state));
628
+ }
629
+ return attributeFilter;
630
+ }
631
+ export function declarativeFiltersConfigToYaml(filtersMap, dateFilterConfig, dateFilterConfigs, attributeFilterConfigs) {
632
+ attributeFilterConfigs?.forEach((filterSettings) => {
633
+ const filter = filtersMap[filterSettings.localIdentifier];
634
+ if (filter) {
635
+ if (filterSettings.mode && filterSettings.mode !== "active") {
636
+ filter.yaml.add(new Pair("mode", filterSettings.mode));
637
+ }
638
+ if (filterSettings.displayAsLabel) {
639
+ filter.yaml.add(new Pair("display_as", getIdentifier(filterSettings.displayAsLabel)));
640
+ }
641
+ }
642
+ });
643
+ dateFilterConfigs?.forEach((filterSettings) => {
644
+ const filter = Object.values(filtersMap).find((filter) => filter.yaml.get("date") === getIdentifier(filterSettings.dateDataSet, true));
645
+ fillDateFilterConfig(filterSettings.config, filter);
646
+ });
647
+ if (dateFilterConfig) {
648
+ const filter = Object.values(filtersMap).find((filter) => filter.yaml.get("type") === "date_filter" && !filter.yaml.get("date"));
649
+ fillDateFilterConfig(dateFilterConfig, filter);
650
+ }
651
+ }
652
+ function fillDateFilterConfig(config, filter) {
653
+ if (!filter || !config) {
654
+ return;
655
+ }
656
+ if (config.mode !== "active") {
657
+ filter.yaml.add(new Pair("mode", config.mode));
658
+ }
659
+ if (config.filterName) {
660
+ filter.yaml.add(new Pair("title", config.filterName));
661
+ }
662
+ //NOTE: What is it and where?, Not supported now
663
+ //filterSettings.config.addPresets
664
+ //filterSettings.config.hideOptions
665
+ //filterSettings.config.hideGranularities
666
+ }
667
+ export function declarativeFilterGroupsToYaml(filters, filterGroupsConfig) {
668
+ if (!filterGroupsConfig) {
669
+ return filters;
670
+ }
671
+ const sanitizedGroupIds = sanitizeGroupIds(filterGroupsConfig.groups.map((group) => [group, getFilterGroupIdBase(group)]));
672
+ const groupedFilters = new YAMLMap();
673
+ filters.items.forEach((filter) => {
674
+ const groupConfig = filterGroupsConfig.groups.find((group) => group.filters.some(({ filterLocalIdentifier }) => filterLocalIdentifier === filter.key));
675
+ if (!groupConfig) {
676
+ groupedFilters.add(filter);
677
+ return;
678
+ }
679
+ const groupWithId = sanitizedGroupIds.find(([group]) => group === groupConfig);
680
+ if (!groupWithId) {
681
+ throw new Error(`Failed to generate id for filter group ${groupConfig.title}`);
682
+ }
683
+ const [_, groupId] = groupWithId;
684
+ const existingGroup = groupedFilters.get(groupId);
685
+ if (existingGroup) {
686
+ const filtersInGroup = existingGroup.get("filters");
687
+ filtersInGroup.add(filter);
688
+ }
689
+ else {
690
+ const newGroup = new YAMLMap();
691
+ newGroup.add(new Pair("type", "filter_group"));
692
+ newGroup.add(new Pair("title", groupConfig.title));
693
+ const filtersInGroup = new YAMLMap();
694
+ filtersInGroup.add(filter);
695
+ newGroup.add(new Pair("filters", filtersInGroup));
696
+ groupedFilters.add(new Pair(groupId, newGroup));
697
+ }
698
+ });
699
+ return groupedFilters;
700
+ }
701
+ function sanitizeGroupIds(filterGroupIds) {
702
+ const equalClusters = {};
703
+ filterGroupIds.forEach(([_, thisId]) => {
704
+ const cluster = filterGroupIds.filter(([_, id]) => thisId === id).map(([filterGroup]) => filterGroup);
705
+ if (cluster.length > 1) {
706
+ equalClusters[thisId] = cluster;
707
+ }
708
+ });
709
+ if (Object.keys(equalClusters).length === 0) {
710
+ return filterGroupIds;
711
+ }
712
+ const newFilterGroupIds = filterGroupIds.map(([filterGroup, oldId]) => {
713
+ if (filterGroup.localIdentifier) {
714
+ return [filterGroup, filterGroup.localIdentifier];
715
+ }
716
+ const cluster = equalClusters[oldId];
717
+ if (!cluster?.length) {
718
+ return [filterGroup, oldId];
719
+ }
720
+ const groupIndex = cluster
721
+ .filter((group) => !group.localIdentifier)
722
+ .findIndex((group) => group === filterGroup);
723
+ const newId = `${oldId}_${groupIndex + 1}`;
724
+ return [filterGroup, newId];
725
+ });
726
+ return sanitizeGroupIds(newFilterGroupIds);
727
+ }
728
+ function getFilterGroupIdBase({ title, localIdentifier }) {
729
+ if (localIdentifier) {
730
+ return localIdentifier;
731
+ }
732
+ return title
733
+ .normalize()
734
+ .replace(/[^a-zA-Z0-9]/g, "_")
735
+ .toLowerCase();
736
+ }
737
+ export function declarativePluginsToYaml(dashboard) {
738
+ if (!dashboard.plugins?.length) {
739
+ return;
740
+ }
741
+ const plugins = new YAMLSeq();
742
+ dashboard.plugins.forEach((plugin) => {
743
+ const pluginId = getIdentifier(plugin.plugin, true);
744
+ if (plugin.parameters?.length) {
745
+ plugins.add({
746
+ id: pluginId,
747
+ parameters: parseParameters(plugin.parameters),
748
+ });
749
+ }
750
+ else {
751
+ plugins.add(pluginId);
752
+ }
753
+ });
754
+ return plugins;
755
+ }
756
+ export function declarativePermissionsToYaml(doc, dashboard) {
757
+ const permissions = fromDeclarativePermissions(dashboard.permissions);
758
+ if (!permissions) {
759
+ return;
760
+ }
761
+ return doc.createNode(permissions);
762
+ }
763
+ function parseParameters(params) {
764
+ try {
765
+ return JSON.parse(params);
766
+ }
767
+ catch {
768
+ return params;
769
+ }
770
+ }
771
+ //# sourceMappingURL=declarativeDashboardToYaml.js.map