@grafana/plugin-ui 0.14.1-dsconfig.0d5c985 → 0.14.1-dsconfig.9143abf

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 (222) hide show
  1. package/dist/cjs/index.cjs +1165 -317
  2. package/dist/cjs/index.cjs.map +1 -1
  3. package/dist/cjs/index.d.cts +129 -5
  4. package/dist/cjs/schemas.cjs +14853 -0
  5. package/dist/cjs/schemas.cjs.map +1 -0
  6. package/dist/cjs/schemas.d.cts +373 -0
  7. package/dist/cjs/test-utils.d.cts +23 -23
  8. package/dist/esm/components/ConfigEditor/ConfigSection/ConfigDescriptionLink.js +2 -2
  9. package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/DatasourceConfigWizard.js +14 -9
  10. package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/DatasourceConfigWizard.js.map +1 -1
  11. package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/DatasourceErrorBoundary.js +27 -0
  12. package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/DatasourceErrorBoundary.js.map +1 -0
  13. package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/SchemaField.js +16 -5
  14. package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/SchemaField.js.map +1 -1
  15. package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/SidebarNav.js.map +1 -1
  16. package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/TabLayout.js +9 -4
  17. package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/TabLayout.js.map +1 -1
  18. package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/fieldUtils.js +61 -11
  19. package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/fieldUtils.js.map +1 -1
  20. package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/{useDatasourceConfigForm.js → hooks/useDatasourceConfigForm.js} +71 -29
  21. package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/hooks/useDatasourceConfigForm.js.map +1 -0
  22. package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/hooks/useHealthChecks.js +106 -0
  23. package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/hooks/useHealthChecks.js.map +1 -0
  24. package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/{AuthorizationHeaderField.js → inputs/AuthorizationHeaderField.js} +6 -8
  25. package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/inputs/AuthorizationHeaderField.js.map +1 -0
  26. package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/{ComplexFieldNote.js → inputs/ComplexFieldNote.js} +6 -4
  27. package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/inputs/ComplexFieldNote.js.map +1 -0
  28. package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/inputs/FileUploadField.js +106 -0
  29. package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/inputs/FileUploadField.js.map +1 -0
  30. package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/{IndexedPairEditor.js → inputs/IndexedPairEditor.js} +52 -52
  31. package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/inputs/IndexedPairEditor.js.map +1 -0
  32. package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/inputs/ObjectArrayEditor.js +190 -0
  33. package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/inputs/ObjectArrayEditor.js.map +1 -0
  34. package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/{PdcFieldNote.js → inputs/PdcFieldNote.js} +5 -8
  35. package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/inputs/PdcFieldNote.js.map +1 -0
  36. package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/{SecureFieldInput.js → inputs/SecureFieldInput.js} +8 -10
  37. package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/inputs/SecureFieldInput.js.map +1 -0
  38. package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/inputs/StringArrayInput.js +80 -0
  39. package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/inputs/StringArrayInput.js.map +1 -0
  40. package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/renderFieldInput.js +76 -41
  41. package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/renderFieldInput.js.map +1 -1
  42. package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/resolvePluginName.js +30 -0
  43. package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/resolvePluginName.js.map +1 -0
  44. package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/tabStyles.js +4 -4
  45. package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/tabStyles.js.map +1 -1
  46. package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/wizardStyles.js +3 -3
  47. package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/wizardStyles.js.map +1 -1
  48. package/dist/esm/components/DataLinks/DataLink.js +2 -2
  49. package/dist/esm/components/DataLinks/DataLinks.js +2 -2
  50. package/dist/esm/components/DataSourcePicker/DataSourcePicker.js +7 -7
  51. package/dist/esm/components/DatePicker/styles.js +2 -2
  52. package/dist/esm/components/DatePickerWithInput/styles.js +2 -2
  53. package/dist/esm/components/QueryEditor/EditorField.js +2 -2
  54. package/dist/esm/components/QueryEditor/EditorHeader.js +2 -2
  55. package/dist/esm/components/QueryEditor/EditorRow.js +2 -2
  56. package/dist/esm/components/QueryEditor/EditorSwitch.js +2 -2
  57. package/dist/esm/components/QueryEditor/InputGroup.js +2 -2
  58. package/dist/esm/components/QueryEditor/Space.js +2 -2
  59. package/dist/esm/components/QueryEditor/query-editor-raw/RawEditor.js +2 -2
  60. package/dist/esm/components/QueryEditor/visual-query-builder/EditorField.js +2 -2
  61. package/dist/esm/components/QueryEditor/visual-query-builder/EditorRow.js +2 -2
  62. package/dist/esm/components/QueryEditor/visual-query-builder/Preview.js +2 -2
  63. package/dist/esm/components/QueryEditor/visual-query-builder/SelectRow.js +2 -2
  64. package/dist/esm/datasource/SqlDatasource.js +10 -10
  65. package/dist/esm/datasource/schema/cel.js +42 -0
  66. package/dist/esm/datasource/schema/cel.js.map +1 -0
  67. package/dist/esm/datasource/schema/config.js +37 -14
  68. package/dist/esm/datasource/schema/config.js.map +1 -1
  69. package/dist/esm/datasource/schema/datasource.js +129 -3
  70. package/dist/esm/datasource/schema/datasource.js.map +1 -1
  71. package/dist/esm/datasource/schema/datasources/alertmanager.schema.json.js +77 -0
  72. package/dist/esm/datasource/schema/datasources/alertmanager.schema.json.js.map +1 -0
  73. package/dist/esm/datasource/schema/datasources/cloudwatch.schema.json.js +384 -0
  74. package/dist/esm/datasource/schema/datasources/cloudwatch.schema.json.js.map +1 -0
  75. package/dist/esm/datasource/schema/datasources/elasticsearch.schema.json.js +287 -0
  76. package/dist/esm/datasource/schema/datasources/elasticsearch.schema.json.js.map +1 -0
  77. package/dist/esm/datasource/schema/datasources/grafana-amazonprometheus-datasource.schema.json.js +166 -0
  78. package/dist/esm/datasource/schema/datasources/grafana-amazonprometheus-datasource.schema.json.js.map +1 -0
  79. package/dist/esm/datasource/schema/datasources/grafana-appdynamics-datasource.schema.json.js +145 -0
  80. package/dist/esm/datasource/schema/datasources/grafana-appdynamics-datasource.schema.json.js.map +1 -0
  81. package/dist/esm/datasource/schema/datasources/grafana-astradb-datasource.schema.json.js +123 -0
  82. package/dist/esm/datasource/schema/datasources/grafana-astradb-datasource.schema.json.js.map +1 -0
  83. package/dist/esm/datasource/schema/datasources/grafana-athena-datasource.schema.json.js +158 -0
  84. package/dist/esm/datasource/schema/datasources/grafana-athena-datasource.schema.json.js.map +1 -0
  85. package/dist/esm/datasource/schema/datasources/grafana-azure-data-explorer-datasource.schema.json.js +204 -0
  86. package/dist/esm/datasource/schema/datasources/grafana-azure-data-explorer-datasource.schema.json.js.map +1 -0
  87. package/dist/esm/datasource/schema/datasources/grafana-azure-monitor-datasource.schema.json.js +294 -0
  88. package/dist/esm/datasource/schema/datasources/grafana-azure-monitor-datasource.schema.json.js.map +1 -0
  89. package/dist/esm/datasource/schema/datasources/grafana-azuredevops-datasource.schema.json.js +101 -0
  90. package/dist/esm/datasource/schema/datasources/grafana-azuredevops-datasource.schema.json.js.map +1 -0
  91. package/dist/esm/datasource/schema/datasources/grafana-azureprometheus-datasource.schema.json.js +125 -0
  92. package/dist/esm/datasource/schema/datasources/grafana-azureprometheus-datasource.schema.json.js.map +1 -0
  93. package/dist/esm/datasource/schema/datasources/grafana-bigquery-datasource.schema.json.js +508 -0
  94. package/dist/esm/datasource/schema/datasources/grafana-bigquery-datasource.schema.json.js.map +1 -0
  95. package/dist/esm/datasource/schema/datasources/grafana-clickhouse-datasource.schema.json.js +1400 -0
  96. package/dist/esm/datasource/schema/datasources/grafana-clickhouse-datasource.schema.json.js.map +1 -0
  97. package/dist/esm/datasource/schema/datasources/grafana-cockroachdb-datasource.schema.json.js +302 -0
  98. package/dist/esm/datasource/schema/datasources/grafana-cockroachdb-datasource.schema.json.js.map +1 -0
  99. package/dist/esm/datasource/schema/datasources/grafana-databricks-datasource.schema.json.js +291 -0
  100. package/dist/esm/datasource/schema/datasources/grafana-databricks-datasource.schema.json.js.map +1 -0
  101. package/dist/esm/datasource/schema/datasources/grafana-datadog-datasource.schema.json.js +155 -0
  102. package/dist/esm/datasource/schema/datasources/grafana-datadog-datasource.schema.json.js.map +1 -0
  103. package/dist/esm/datasource/schema/datasources/grafana-dynatrace-datasource.schema.json.js +179 -0
  104. package/dist/esm/datasource/schema/datasources/grafana-dynatrace-datasource.schema.json.js.map +1 -0
  105. package/dist/esm/datasource/schema/datasources/grafana-falconlogscale-datasource.schema.json.js +134 -0
  106. package/dist/esm/datasource/schema/datasources/grafana-falconlogscale-datasource.schema.json.js.map +1 -0
  107. package/dist/esm/datasource/schema/datasources/grafana-github-datasource.schema.json.js +156 -0
  108. package/dist/esm/datasource/schema/datasources/grafana-github-datasource.schema.json.js.map +1 -0
  109. package/dist/esm/datasource/schema/datasources/grafana-gitlab-datasource.schema.json.js +84 -0
  110. package/dist/esm/datasource/schema/datasources/grafana-gitlab-datasource.schema.json.js.map +1 -0
  111. package/dist/esm/datasource/schema/datasources/grafana-googlesheets-datasource.schema.json.js +231 -0
  112. package/dist/esm/datasource/schema/datasources/grafana-googlesheets-datasource.schema.json.js.map +1 -0
  113. package/dist/esm/datasource/schema/datasources/grafana-honeycomb-datasource.schema.json.js +87 -0
  114. package/dist/esm/datasource/schema/datasources/grafana-honeycomb-datasource.schema.json.js.map +1 -0
  115. package/dist/esm/datasource/schema/datasources/grafana-iot-sitewise-datasource.schema.json.js +159 -0
  116. package/dist/esm/datasource/schema/datasources/grafana-iot-sitewise-datasource.schema.json.js.map +1 -0
  117. package/dist/esm/datasource/schema/datasources/grafana-jira-datasource.schema.json.js +188 -0
  118. package/dist/esm/datasource/schema/datasources/grafana-jira-datasource.schema.json.js.map +1 -0
  119. package/dist/esm/datasource/schema/datasources/grafana-looker-datasource.schema.json.js +82 -0
  120. package/dist/esm/datasource/schema/datasources/grafana-looker-datasource.schema.json.js.map +1 -0
  121. package/dist/esm/datasource/schema/datasources/grafana-mongodb-datasource.schema.json.js +278 -0
  122. package/dist/esm/datasource/schema/datasources/grafana-mongodb-datasource.schema.json.js.map +1 -0
  123. package/dist/esm/datasource/schema/datasources/grafana-mqtt-datasource.schema.json.js +168 -0
  124. package/dist/esm/datasource/schema/datasources/grafana-mqtt-datasource.schema.json.js.map +1 -0
  125. package/dist/esm/datasource/schema/datasources/grafana-newrelic-datasource.schema.json.js +129 -0
  126. package/dist/esm/datasource/schema/datasources/grafana-newrelic-datasource.schema.json.js.map +1 -0
  127. package/dist/esm/datasource/schema/datasources/grafana-odbc-datasource.schema.json.js +56 -0
  128. package/dist/esm/datasource/schema/datasources/grafana-odbc-datasource.schema.json.js.map +1 -0
  129. package/dist/esm/datasource/schema/datasources/grafana-opensearch-datasource.schema.json.js +212 -0
  130. package/dist/esm/datasource/schema/datasources/grafana-opensearch-datasource.schema.json.js.map +1 -0
  131. package/dist/esm/datasource/schema/datasources/grafana-oracle-datasource.schema.json.js +186 -0
  132. package/dist/esm/datasource/schema/datasources/grafana-oracle-datasource.schema.json.js.map +1 -0
  133. package/dist/esm/datasource/schema/datasources/grafana-pagerduty-datasource.schema.json.js +85 -0
  134. package/dist/esm/datasource/schema/datasources/grafana-pagerduty-datasource.schema.json.js.map +1 -0
  135. package/dist/esm/datasource/schema/datasources/grafana-postgresql-datasource.schema.json.js +411 -0
  136. package/dist/esm/datasource/schema/datasources/grafana-postgresql-datasource.schema.json.js.map +1 -0
  137. package/dist/esm/datasource/schema/datasources/grafana-pyroscope-datasource.schema.json.js +41 -0
  138. package/dist/esm/datasource/schema/datasources/grafana-pyroscope-datasource.schema.json.js.map +1 -0
  139. package/dist/esm/datasource/schema/datasources/grafana-redshift-datasource.schema.json.js +201 -0
  140. package/dist/esm/datasource/schema/datasources/grafana-redshift-datasource.schema.json.js.map +1 -0
  141. package/dist/esm/datasource/schema/datasources/grafana-salesforce-datasource.schema.json.js +201 -0
  142. package/dist/esm/datasource/schema/datasources/grafana-salesforce-datasource.schema.json.js.map +1 -0
  143. package/dist/esm/datasource/schema/datasources/grafana-saphana-datasource.schema.json.js +208 -0
  144. package/dist/esm/datasource/schema/datasources/grafana-saphana-datasource.schema.json.js.map +1 -0
  145. package/dist/esm/datasource/schema/datasources/grafana-sentry-datasource.schema.json.js +94 -0
  146. package/dist/esm/datasource/schema/datasources/grafana-sentry-datasource.schema.json.js.map +1 -0
  147. package/dist/esm/datasource/schema/datasources/grafana-servicenow-datasource.schema.json.js +179 -0
  148. package/dist/esm/datasource/schema/datasources/grafana-servicenow-datasource.schema.json.js.map +1 -0
  149. package/dist/esm/datasource/schema/datasources/grafana-snowflake-datasource.schema.json.js +304 -0
  150. package/dist/esm/datasource/schema/datasources/grafana-snowflake-datasource.schema.json.js.map +1 -0
  151. package/dist/esm/datasource/schema/datasources/grafana-splunk-datasource.schema.json.js +319 -0
  152. package/dist/esm/datasource/schema/datasources/grafana-splunk-datasource.schema.json.js.map +1 -0
  153. package/dist/esm/datasource/schema/datasources/grafana-splunkobservability-datasource.schema.json.js +90 -0
  154. package/dist/esm/datasource/schema/datasources/grafana-splunkobservability-datasource.schema.json.js.map +1 -0
  155. package/dist/esm/datasource/schema/datasources/grafana-strava-datasource.schema.json.js +74 -0
  156. package/dist/esm/datasource/schema/datasources/grafana-strava-datasource.schema.json.js.map +1 -0
  157. package/dist/esm/datasource/schema/datasources/grafana-sumologic-datasource.schema.json.js +102 -0
  158. package/dist/esm/datasource/schema/datasources/grafana-sumologic-datasource.schema.json.js.map +1 -0
  159. package/dist/esm/datasource/schema/datasources/grafana-surrealdb-datasource.schema.json.js +92 -0
  160. package/dist/esm/datasource/schema/datasources/grafana-surrealdb-datasource.schema.json.js.map +1 -0
  161. package/dist/esm/datasource/schema/datasources/grafana-timestream-datasource.schema.json.js +145 -0
  162. package/dist/esm/datasource/schema/datasources/grafana-timestream-datasource.schema.json.js.map +1 -0
  163. package/dist/esm/datasource/schema/datasources/grafana-wavefront-datasource.schema.json.js +80 -0
  164. package/dist/esm/datasource/schema/datasources/grafana-wavefront-datasource.schema.json.js.map +1 -0
  165. package/dist/esm/datasource/schema/datasources/grafana-x-ray-datasource.schema.json.js +112 -0
  166. package/dist/esm/datasource/schema/datasources/grafana-x-ray-datasource.schema.json.js.map +1 -0
  167. package/dist/esm/datasource/schema/datasources/grafana-yugabyte-datasource.schema.json.js +114 -0
  168. package/dist/esm/datasource/schema/datasources/grafana-yugabyte-datasource.schema.json.js.map +1 -0
  169. package/dist/esm/datasource/schema/datasources/graphite.schema.json.js +104 -0
  170. package/dist/esm/datasource/schema/datasources/graphite.schema.json.js.map +1 -0
  171. package/dist/esm/datasource/schema/datasources/influxdb.schema.json.js +717 -0
  172. package/dist/esm/datasource/schema/datasources/influxdb.schema.json.js.map +1 -0
  173. package/dist/esm/datasource/schema/datasources/jaeger.schema.json.js +59 -0
  174. package/dist/esm/datasource/schema/datasources/jaeger.schema.json.js.map +1 -0
  175. package/dist/esm/datasource/schema/datasources/loki.schema.json.js +545 -0
  176. package/dist/esm/datasource/schema/datasources/loki.schema.json.js.map +1 -0
  177. package/dist/esm/datasource/schema/datasources/marcusolsson-csv-datasource.schema.json.js +45 -0
  178. package/dist/esm/datasource/schema/datasources/marcusolsson-csv-datasource.schema.json.js.map +1 -0
  179. package/dist/esm/datasource/schema/datasources/marcusolsson-json-datasource.schema.json.js +36 -0
  180. package/dist/esm/datasource/schema/datasources/marcusolsson-json-datasource.schema.json.js.map +1 -0
  181. package/dist/esm/datasource/schema/datasources/mssql.schema.json.js +292 -0
  182. package/dist/esm/datasource/schema/datasources/mssql.schema.json.js.map +1 -0
  183. package/dist/esm/datasource/schema/datasources/mysql.schema.json.js +304 -0
  184. package/dist/esm/datasource/schema/datasources/mysql.schema.json.js.map +1 -0
  185. package/dist/esm/datasource/schema/datasources/opentsdb.schema.json.js +113 -0
  186. package/dist/esm/datasource/schema/datasources/opentsdb.schema.json.js.map +1 -0
  187. package/dist/esm/datasource/schema/datasources/prometheus.schema.json.js +783 -0
  188. package/dist/esm/datasource/schema/datasources/prometheus.schema.json.js.map +1 -0
  189. package/dist/esm/datasource/schema/datasources/stackdriver.schema.json.js +224 -0
  190. package/dist/esm/datasource/schema/datasources/stackdriver.schema.json.js.map +1 -0
  191. package/dist/esm/datasource/schema/datasources/tempo.schema.json.js +664 -0
  192. package/dist/esm/datasource/schema/datasources/tempo.schema.json.js.map +1 -0
  193. package/dist/esm/datasource/schema/datasources/yesoreyeram-infinity-datasource.schema.json.js +1073 -0
  194. package/dist/esm/datasource/schema/datasources/yesoreyeram-infinity-datasource.schema.json.js.map +1 -0
  195. package/dist/esm/datasource/schema/datasources/zipkin.schema.json.js +40 -0
  196. package/dist/esm/datasource/schema/datasources/zipkin.schema.json.js.map +1 -0
  197. package/dist/esm/datasource/schema/dsconfig.js +17 -0
  198. package/dist/esm/datasource/schema/dsconfig.js.map +1 -0
  199. package/dist/esm/datasource/schema/{llmHints.js → llm.js} +1 -1
  200. package/dist/esm/datasource/schema/llm.js.map +1 -0
  201. package/dist/esm/datasource/schema/{provisioningYaml.js → provisioning.js} +78 -2
  202. package/dist/esm/datasource/schema/provisioning.js.map +1 -0
  203. package/dist/esm/datasource/schema/schemaRegistry.js +139 -0
  204. package/dist/esm/datasource/schema/schemaRegistry.js.map +1 -0
  205. package/dist/esm/index.d.ts +129 -5
  206. package/dist/esm/index.js +8 -4
  207. package/dist/esm/index.js.map +1 -1
  208. package/dist/esm/schemas.d.ts +373 -0
  209. package/dist/esm/schemas.js +2 -0
  210. package/dist/esm/schemas.js.map +1 -0
  211. package/dist/esm/test-utils.d.ts +23 -23
  212. package/package.json +23 -6
  213. package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/AuthorizationHeaderField.js.map +0 -1
  214. package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/ComplexFieldNote.js.map +0 -1
  215. package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/IndexedPairEditor.js.map +0 -1
  216. package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/PdcFieldNote.js.map +0 -1
  217. package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/SecureFieldInput.js.map +0 -1
  218. package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/StringArrayInput.js +0 -84
  219. package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/StringArrayInput.js.map +0 -1
  220. package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/useDatasourceConfigForm.js.map +0 -1
  221. package/dist/esm/datasource/schema/llmHints.js.map +0 -1
  222. package/dist/esm/datasource/schema/provisioningYaml.js.map +0 -1
@@ -17,10 +17,12 @@ var AutoSizer = require('react-virtualized-auto-sizer');
17
17
  var sqlFormatter = require('sql-formatter');
18
18
  var rxjs = require('rxjs');
19
19
  var operators$1 = require('rxjs/operators');
20
+ var celJs = require('@marcbachmann/cel-js');
20
21
  var reactHookForm = require('react-hook-form');
21
22
  var dnd = require('@hello-pangea/dnd');
22
23
  var reactPopperTooltip = require('react-popper-tooltip');
23
24
  var Prism = require('prismjs');
25
+ var schemas = require('./schemas.cjs');
24
26
  var yaml = require('js-yaml');
25
27
 
26
28
  function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; }
@@ -78,7 +80,7 @@ function Segment(props) {
78
80
  );
79
81
  }
80
82
 
81
- const getStyles$v = (theme) => {
83
+ const getStyles$x = (theme) => {
82
84
  const containerBorder = theme.isDark ? theme.v1.palette.dark9 : theme.v1.palette.gray5;
83
85
  return {
84
86
  container: css.css`
@@ -228,7 +230,7 @@ const getBodyStyles = (theme) => {
228
230
 
229
231
  const DatePicker = React.memo((props) => {
230
232
  const theme = ui.useTheme2();
231
- const styles = getStyles$v(theme);
233
+ const styles = getStyles$x(theme);
232
234
  const { isOpen, onClose } = props;
233
235
  if (!isOpen) {
234
236
  return null;
@@ -258,7 +260,7 @@ const Body = React.memo(({ value, onChange }) => {
258
260
  });
259
261
  Body.displayName = "Body";
260
262
 
261
- function getStyles$u() {
263
+ function getStyles$w() {
262
264
  return {
263
265
  input: css.css({
264
266
  /* hides the native Calendar picker icon given when using type=date */
@@ -274,7 +276,7 @@ const formatDate = (date) => date.toISOString().split("T")[0];
274
276
  const DatePickerWithInput = (props) => {
275
277
  const { value, onChange, className, ...rest } = props;
276
278
  const [open, setOpen] = React.useState(false);
277
- const styles = getStyles$u();
279
+ const styles = getStyles$w();
278
280
  return /* @__PURE__ */ React__default.default.createElement(React__default.default.Fragment, null, /* @__PURE__ */ React__default.default.createElement(
279
281
  ui.Input,
280
282
  {
@@ -341,15 +343,15 @@ function getSignatureDisplayModel(signature) {
341
343
  }
342
344
  PluginSignatureBadge.displayName = "PluginSignatureBadge";
343
345
 
344
- var __defProp$3 = Object.defineProperty;
345
- var __defNormalProp$3 = (obj, key, value) => key in obj ? __defProp$3(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
346
- var __publicField$3 = (obj, key, value) => __defNormalProp$3(obj, typeof key !== "symbol" ? key + "" : key, value);
346
+ var __defProp$4 = Object.defineProperty;
347
+ var __defNormalProp$4 = (obj, key, value) => key in obj ? __defProp$4(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
348
+ var __publicField$4 = (obj, key, value) => __defNormalProp$4(obj, typeof key !== "symbol" ? key + "" : key, value);
347
349
  class DataSourcePicker extends React.PureComponent {
348
350
  constructor(props) {
349
351
  super(props);
350
- __publicField$3(this, "dataSourceSrv", runtime.getDataSourceSrv());
351
- __publicField$3(this, "state", {});
352
- __publicField$3(this, "onChange", (item) => {
352
+ __publicField$4(this, "dataSourceSrv", runtime.getDataSourceSrv());
353
+ __publicField$4(this, "state", {});
354
+ __publicField$4(this, "onChange", (item) => {
353
355
  const dsSettings = this.dataSourceSrv.getInstanceSettings(item.value);
354
356
  if (dsSettings) {
355
357
  this.props.onChange(dsSettings);
@@ -429,14 +431,14 @@ class DataSourcePicker extends React.PureComponent {
429
431
  ));
430
432
  }
431
433
  }
432
- __publicField$3(DataSourcePicker, "defaultProps", {
434
+ __publicField$4(DataSourcePicker, "defaultProps", {
433
435
  autoFocus: false,
434
436
  openMenuOnFocus: false,
435
437
  placeholder: "Select datasource"
436
438
  });
437
439
 
438
440
  const { FormField, Switch } = ui.LegacyForms;
439
- const getStyles$t = ui.stylesFactory(() => ({
441
+ const getStyles$v = ui.stylesFactory(() => ({
440
442
  firstRow: css.css`
441
443
  display: flex;
442
444
  `,
@@ -453,7 +455,7 @@ const getStyles$t = ui.stylesFactory(() => ({
453
455
  }));
454
456
  const DataLink = (props) => {
455
457
  const { value, onChange, onDelete, suggestions, className } = props;
456
- const styles = getStyles$t();
458
+ const styles = getStyles$v();
457
459
  const [showInternalLink, setShowInternalLink] = useInternalLink(value.datasourceUid);
458
460
  const handleChange = (field) => (event) => {
459
461
  onChange({
@@ -570,7 +572,7 @@ function useInternalLink(datasourceUid) {
570
572
  return [showInternalLink, setShowInternalLink];
571
573
  }
572
574
 
573
- const getStyles$s = (theme) => ({
575
+ const getStyles$u = (theme) => ({
574
576
  infoText: css.css`
575
577
  padding-bottom: ${theme.v1.spacing.md};
576
578
  color: ${theme.v1.colors.textWeak};
@@ -582,7 +584,7 @@ const getStyles$s = (theme) => ({
582
584
  const DataLinks = (props) => {
583
585
  const { value, onChange } = props;
584
586
  const theme = ui.useTheme2();
585
- const styles = getStyles$s(theme);
587
+ const styles = getStyles$u(theme);
586
588
  return /* @__PURE__ */ React__default.default.createElement(React__default.default.Fragment, null, /* @__PURE__ */ React__default.default.createElement("h3", { className: "page-heading" }, "Data links"), /* @__PURE__ */ React__default.default.createElement("div", { className: styles.infoText }, "Add links to existing fields. Links will be shown in log row details next to the field value."), /* @__PURE__ */ React__default.default.createElement("div", { className: "gf-form-group" }, value && value.map((field, index) => {
587
589
  return /* @__PURE__ */ React__default.default.createElement(
588
590
  DataLink,
@@ -5478,7 +5480,7 @@ const getButtonStyles = (theme) => ({
5478
5480
  });
5479
5481
 
5480
5482
  const InputGroup = ({ children }) => {
5481
- const styles = ui.useStyles2(getStyles$r);
5483
+ const styles = ui.useStyles2(getStyles$t);
5482
5484
  const modifiedChildren = React.Children.map(children, (child) => {
5483
5485
  if (React.isValidElement(child) && child.props.invalid) {
5484
5486
  return React.cloneElement(child, { className: css.cx(child.props.className, styles.invalidChild) });
@@ -5496,7 +5498,7 @@ const borderPriority = [
5496
5498
  "focused"
5497
5499
  // highest priority
5498
5500
  ];
5499
- const getStyles$r = () => ({
5501
+ const getStyles$t = () => ({
5500
5502
  root: css.css({
5501
5503
  display: "flex",
5502
5504
  // Style the direct children of the component
@@ -5579,10 +5581,10 @@ const EditorFieldGroup = ({ children }) => {
5579
5581
  };
5580
5582
 
5581
5583
  const EditorHeader = ({ children }) => {
5582
- const styles = ui.useStyles2(getStyles$q);
5584
+ const styles = ui.useStyles2(getStyles$s);
5583
5585
  return /* @__PURE__ */ React__default.default.createElement("div", { className: styles.root }, children);
5584
5586
  };
5585
- const getStyles$q = (theme) => ({
5587
+ const getStyles$s = (theme) => ({
5586
5588
  root: css.css({
5587
5589
  display: "flex",
5588
5590
  flexWrap: "wrap",
@@ -5595,12 +5597,12 @@ const getStyles$q = (theme) => ({
5595
5597
  const EditorField$1 = (props) => {
5596
5598
  var _a;
5597
5599
  const { label, optional, tooltip, tooltipInteractive, children, width, ...fieldProps } = props;
5598
- const styles = ui.useStyles2(getStyles$p, width);
5600
+ const styles = ui.useStyles2(getStyles$r, width);
5599
5601
  const childInputId = (fieldProps == null ? void 0 : fieldProps.htmlFor) || ((_a = ui.ReactUtils) == null ? void 0 : _a.getChildId(children));
5600
5602
  const labelEl = /* @__PURE__ */ React__default.default.createElement(React__default.default.Fragment, null, /* @__PURE__ */ React__default.default.createElement("label", { className: styles.label, htmlFor: childInputId }, label, optional && /* @__PURE__ */ React__default.default.createElement("span", { className: styles.optional }, " - optional"), tooltip && /* @__PURE__ */ React__default.default.createElement(ui.Tooltip, { placement: "top", content: tooltip, theme: "info", interactive: tooltipInteractive }, /* @__PURE__ */ React__default.default.createElement(ui.Icon, { tabIndex: 0, name: "info-circle", size: "sm", className: styles.icon }))), /* @__PURE__ */ React__default.default.createElement(ui.Space, { v: 0.5 }));
5601
5603
  return /* @__PURE__ */ React__default.default.createElement("div", { className: styles.root }, /* @__PURE__ */ React__default.default.createElement(ui.Field, { className: styles.field, label: labelEl, ...fieldProps }, children));
5602
5604
  };
5603
- const getStyles$p = (theme, width) => {
5605
+ const getStyles$r = (theme, width) => {
5604
5606
  return {
5605
5607
  root: css.css({
5606
5608
  minWidth: theme.spacing(width != null ? width : 0)
@@ -5628,10 +5630,10 @@ const getStyles$p = (theme, width) => {
5628
5630
  };
5629
5631
 
5630
5632
  const EditorRow$1 = ({ children }) => {
5631
- const styles = ui.useStyles2(getStyles$o);
5633
+ const styles = ui.useStyles2(getStyles$q);
5632
5634
  return /* @__PURE__ */ React__default.default.createElement("div", { className: styles.root }, /* @__PURE__ */ React__default.default.createElement(EditorStack, { gap: 2 }, children));
5633
5635
  };
5634
- const getStyles$o = (theme) => {
5636
+ const getStyles$q = (theme) => {
5635
5637
  return {
5636
5638
  root: css.css({
5637
5639
  padding: theme.spacing(1),
@@ -5646,10 +5648,10 @@ const EditorRows$1 = ({ children }) => {
5646
5648
  };
5647
5649
 
5648
5650
  const EditorSwitch = (props) => {
5649
- const styles = getStyles$n();
5651
+ const styles = getStyles$p();
5650
5652
  return /* @__PURE__ */ React__default.default.createElement("div", { className: styles.switch }, /* @__PURE__ */ React__default.default.createElement(ui.Switch, { ...props }));
5651
5653
  };
5652
- const getStyles$n = () => {
5654
+ const getStyles$p = () => {
5653
5655
  return {
5654
5656
  switch: css.css({
5655
5657
  display: "flex",
@@ -5707,10 +5709,10 @@ const getSelectStyles = (theme) => ({
5707
5709
  });
5708
5710
 
5709
5711
  const Space = ({ v = 0, h = 0, layout = "block" }) => {
5710
- const styles = ui.useStyles2(getStyles$m, v, h, layout);
5712
+ const styles = ui.useStyles2(getStyles$o, v, h, layout);
5711
5713
  return /* @__PURE__ */ React__default.default.createElement("span", { className: css.cx(styles.wrapper) });
5712
5714
  };
5713
- const getStyles$m = (theme, v, h, layout) => ({
5715
+ const getStyles$o = (theme, v, h, layout) => ({
5714
5716
  wrapper: css.css([
5715
5717
  {
5716
5718
  paddingRight: theme.spacing(h != null ? h : 0),
@@ -6322,7 +6324,7 @@ function RawEditor({
6322
6324
  language = "sql"
6323
6325
  }) {
6324
6326
  const theme = ui.useTheme2();
6325
- const styles = ui.useStyles2(getStyles$l);
6327
+ const styles = ui.useStyles2(getStyles$n);
6326
6328
  const [isExpanded, setIsExpanded] = React.useState(false);
6327
6329
  const [toolboxRef, toolboxMeasure] = reactUse.useMeasure();
6328
6330
  const [editorRef, editorMeasure] = reactUse.useMeasure();
@@ -6392,7 +6394,7 @@ function RawEditor({
6392
6394
  renderEditor(true)
6393
6395
  ));
6394
6396
  }
6395
- function getStyles$l(theme) {
6397
+ function getStyles$n(theme) {
6396
6398
  return {
6397
6399
  modal: css.css`
6398
6400
  width: 95vw;
@@ -6407,7 +6409,7 @@ function getStyles$l(theme) {
6407
6409
 
6408
6410
  function Preview({ rawSql, language = "sql" }) {
6409
6411
  const [_, copyToClipboard] = reactUse.useCopyToClipboard();
6410
- const styles = ui.useStyles2(getStyles$k);
6412
+ const styles = ui.useStyles2(getStyles$m);
6411
6413
  const labelElement = /* @__PURE__ */ React__default.default.createElement("div", { className: styles.labelWrapper }, /* @__PURE__ */ React__default.default.createElement("label", { className: styles.label }, "Preview"), /* @__PURE__ */ React__default.default.createElement(ui.IconButton, { tooltip: "Copy to clipboard", onClick: () => copyToClipboard(rawSql), name: "copy" }));
6412
6414
  return /* @__PURE__ */ React__default.default.createElement(ui.Field, { label: labelElement, className: styles.grow }, /* @__PURE__ */ React__default.default.createElement(
6413
6415
  ui.CodeEditor,
@@ -6421,7 +6423,7 @@ function Preview({ rawSql, language = "sql" }) {
6421
6423
  }
6422
6424
  ));
6423
6425
  }
6424
- function getStyles$k(theme) {
6426
+ function getStyles$m(theme) {
6425
6427
  return {
6426
6428
  grow: css.css({ flexGrow: 1 }),
6427
6429
  label: css.css({ fontSize: 12, fontWeight: theme.typography.fontWeightMedium }),
@@ -6540,7 +6542,7 @@ function SQLOrderByRow({ fields, query, onQueryChange, db }) {
6540
6542
  const asteriskValue = { label: "*", value: "*" };
6541
6543
  function SelectRow({ sql, columns, onSqlChange, functions }) {
6542
6544
  var _a;
6543
- const styles = ui.useStyles2(getStyles$j);
6545
+ const styles = ui.useStyles2(getStyles$l);
6544
6546
  const columnsWithAsterisk = [asteriskValue, ...columns || []];
6545
6547
  const onColumnChange = React.useCallback(
6546
6548
  (item, index) => (column) => {
@@ -6636,7 +6638,7 @@ function SelectRow({ sql, columns, onSqlChange, functions }) {
6636
6638
  }
6637
6639
  ));
6638
6640
  }
6639
- const getStyles$j = () => {
6641
+ const getStyles$l = () => {
6640
6642
  return { addButton: css.css({ alignSelf: "flex-start" }) };
6641
6643
  };
6642
6644
  function getColumnValue({ parameters }) {
@@ -6982,10 +6984,10 @@ function mapFieldsToTypes(columns) {
6982
6984
  }
6983
6985
 
6984
6986
  const EditorRow = ({ children }) => {
6985
- const styles = ui.useStyles2(getStyles$i);
6987
+ const styles = ui.useStyles2(getStyles$k);
6986
6988
  return /* @__PURE__ */ React__default.default.createElement("div", { className: styles.root }, /* @__PURE__ */ React__default.default.createElement(EditorStack, { gap: 2 }, children));
6987
6989
  };
6988
- const getStyles$i = (theme) => {
6990
+ const getStyles$k = (theme) => {
6989
6991
  return {
6990
6992
  root: css.css({
6991
6993
  padding: theme.spacing(1),
@@ -6999,12 +7001,12 @@ const EditorField = (props) => {
6999
7001
  var _a;
7000
7002
  const { label, optional, tooltip, children, width, ...fieldProps } = props;
7001
7003
  const theme = ui.useTheme2();
7002
- const styles = getStyles$h(theme, width);
7004
+ const styles = getStyles$j(theme, width);
7003
7005
  const childInputId = (fieldProps == null ? void 0 : fieldProps.htmlFor) || ((_a = ui.ReactUtils) == null ? void 0 : _a.getChildId(children));
7004
7006
  const labelEl = /* @__PURE__ */ React__default.default.createElement(React__default.default.Fragment, null, /* @__PURE__ */ React__default.default.createElement("label", { className: styles.label, htmlFor: childInputId }, label, optional && /* @__PURE__ */ React__default.default.createElement("span", { className: styles.optional }, " - optional"), tooltip && /* @__PURE__ */ React__default.default.createElement(ui.Tooltip, { placement: "top", content: tooltip, theme: "info" }, /* @__PURE__ */ React__default.default.createElement(ui.Icon, { name: "info-circle", size: "sm", className: styles.icon }))), /* @__PURE__ */ React__default.default.createElement(Space, { v: 0.5 }));
7005
7007
  return /* @__PURE__ */ React__default.default.createElement("div", { className: styles.root }, /* @__PURE__ */ React__default.default.createElement(ui.Field, { className: styles.field, label: labelEl, ...fieldProps }, children));
7006
7008
  };
7007
- const getStyles$h = ui.stylesFactory((theme, width) => {
7009
+ const getStyles$j = ui.stylesFactory((theme, width) => {
7008
7010
  return {
7009
7011
  root: css.css({
7010
7012
  minWidth: theme.spacing(width != null ? width : 0)
@@ -7067,20 +7069,20 @@ const MACRO_NAMES = [
7067
7069
  "$__unixEpochGroupAlias"
7068
7070
  ];
7069
7071
 
7070
- var __defProp$2 = Object.defineProperty;
7071
- var __defNormalProp$2 = (obj, key, value) => key in obj ? __defProp$2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
7072
- var __publicField$2 = (obj, key, value) => __defNormalProp$2(obj, typeof key !== "symbol" ? key + "" : key, value);
7072
+ var __defProp$3 = Object.defineProperty;
7073
+ var __defNormalProp$3 = (obj, key, value) => key in obj ? __defProp$3(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
7074
+ var __publicField$3 = (obj, key, value) => __defNormalProp$3(obj, typeof key !== "symbol" ? key + "" : key, value);
7073
7075
  class SqlDatasource extends runtime.DataSourceWithBackend {
7074
7076
  constructor(instanceSettings, templateSrv = runtime.getTemplateSrv()) {
7075
7077
  super(instanceSettings);
7076
7078
  this.templateSrv = templateSrv;
7077
- __publicField$2(this, "id");
7078
- __publicField$2(this, "name");
7079
- __publicField$2(this, "interval");
7080
- __publicField$2(this, "db");
7081
- __publicField$2(this, "dataset");
7082
- __publicField$2(this, "annotations", {});
7083
- __publicField$2(this, "interpolateVariable", (value, variable) => {
7079
+ __publicField$3(this, "id");
7080
+ __publicField$3(this, "name");
7081
+ __publicField$3(this, "interval");
7082
+ __publicField$3(this, "db");
7083
+ __publicField$3(this, "dataset");
7084
+ __publicField$3(this, "annotations", {});
7085
+ __publicField$3(this, "interpolateVariable", (value, variable) => {
7084
7086
  if (typeof value === "string") {
7085
7087
  if (variable.multi || variable.includeAll) {
7086
7088
  const result = this.getQueryModel().quoteLiteral(value);
@@ -7454,7 +7456,7 @@ const ConfigSubSection = ({ children, ...props }) => {
7454
7456
  function ConfigDescriptionLink(props) {
7455
7457
  const { description, suffix, feature } = props;
7456
7458
  const text = `Learn more about ${feature}`;
7457
- const styles = ui.useStyles2(getStyles$g);
7459
+ const styles = ui.useStyles2(getStyles$i);
7458
7460
  return /* @__PURE__ */ React__default.default.createElement("span", { className: styles.container }, description, /* @__PURE__ */ React__default.default.createElement(
7459
7461
  "a",
7460
7462
  {
@@ -7466,7 +7468,7 @@ function ConfigDescriptionLink(props) {
7466
7468
  text
7467
7469
  ));
7468
7470
  }
7469
- const getStyles$g = (theme) => {
7471
+ const getStyles$i = (theme) => {
7470
7472
  return {
7471
7473
  container: css.css({
7472
7474
  color: theme.colors.text.secondary,
@@ -8435,6 +8437,44 @@ const AdvancedHttpSettings = ({
8435
8437
  ));
8436
8438
  };
8437
8439
 
8440
+ const exprCache = /* @__PURE__ */ new Map();
8441
+ function getCompiled(expr) {
8442
+ if (exprCache.has(expr)) {
8443
+ return exprCache.get(expr);
8444
+ }
8445
+ try {
8446
+ const compiled = celJs.parse(expr);
8447
+ exprCache.set(expr, compiled);
8448
+ return compiled;
8449
+ } catch (e) {
8450
+ exprCache.set(expr, null);
8451
+ return null;
8452
+ }
8453
+ }
8454
+ function evaluateCelExpression(expr, context, defaultValue = false) {
8455
+ if (!expr || !expr.trim()) {
8456
+ return defaultValue;
8457
+ }
8458
+ const compiled = getCompiled(expr);
8459
+ if (!compiled) {
8460
+ return defaultValue;
8461
+ }
8462
+ try {
8463
+ const result = compiled(context);
8464
+ return !!result;
8465
+ } catch (e) {
8466
+ return defaultValue;
8467
+ }
8468
+ }
8469
+ function extractFieldRefs(expr) {
8470
+ const matches = expr.matchAll(/([\w.]+)\s*(?:==|!=)/g);
8471
+ const refs = /* @__PURE__ */ new Set();
8472
+ for (const m of matches) {
8473
+ refs.add(m[1]);
8474
+ }
8475
+ return [...refs];
8476
+ }
8477
+
8438
8478
  function resolveGroups(schema) {
8439
8479
  const fieldMap = /* @__PURE__ */ new Map();
8440
8480
  for (const f of schema.fields) {
@@ -8458,18 +8498,18 @@ function resolveGroups(schema) {
8458
8498
  ];
8459
8499
  }
8460
8500
  function resolveRequiredFieldsGroup(schema) {
8461
- var _a;
8501
+ var _a, _b;
8462
8502
  const fieldMap = /* @__PURE__ */ new Map();
8463
8503
  for (const f of schema.fields) {
8464
8504
  fieldMap.set(f.id, f);
8465
8505
  }
8466
8506
  const requiredIds = /* @__PURE__ */ new Set();
8467
8507
  for (const f of schema.fields) {
8468
- if (f.required) {
8508
+ if (f.required || ((_a = f.tags) == null ? void 0 : _a.includes("pinned"))) {
8469
8509
  requiredIds.add(f.id);
8470
8510
  }
8471
8511
  }
8472
- const authGroup = (_a = schema.groups) == null ? void 0 : _a.find((g) => g.id === "auth");
8512
+ const authGroup = (_b = schema.groups) == null ? void 0 : _b.find((g) => g.id === "auth");
8473
8513
  if (authGroup) {
8474
8514
  for (const ref of authGroup.fieldRefs) {
8475
8515
  if (fieldMap.has(ref)) {
@@ -8485,16 +8525,17 @@ function resolveRequiredFieldsGroup(schema) {
8485
8525
  includeIds.add(id);
8486
8526
  const f = fieldMap.get(id);
8487
8527
  if (f == null ? void 0 : f.dependsOn) {
8488
- const parsed = parseDependsOn(f.dependsOn);
8489
- if (parsed && fieldMap.has(parsed.field)) {
8490
- includeIds.add(parsed.field);
8528
+ for (const ref of extractFieldRefs(f.dependsOn)) {
8529
+ if (fieldMap.has(ref)) {
8530
+ includeIds.add(ref);
8531
+ }
8491
8532
  }
8492
8533
  }
8493
8534
  }
8494
8535
  for (const f of schema.fields) {
8495
8536
  if (f.dependsOn && !includeIds.has(f.id)) {
8496
- const parsed = parseDependsOn(f.dependsOn);
8497
- if (parsed && requiredIds.has(parsed.field)) {
8537
+ const refs = extractFieldRefs(f.dependsOn);
8538
+ if (refs.some((ref) => requiredIds.has(ref))) {
8498
8539
  includeIds.add(f.id);
8499
8540
  }
8500
8541
  }
@@ -8506,7 +8547,7 @@ function resolveRequiredFieldsGroup(schema) {
8506
8547
  return {
8507
8548
  group: {
8508
8549
  id: "_required",
8509
- title: "Required",
8550
+ title: "General",
8510
8551
  fieldRefs: virtualFields.map((f) => f.id)
8511
8552
  },
8512
8553
  fields: virtualFields
@@ -8515,16 +8556,36 @@ function resolveRequiredFieldsGroup(schema) {
8515
8556
  function formKey(field) {
8516
8557
  return field.section ? `${field.section}.${field.key}` : field.key;
8517
8558
  }
8559
+ function getWatchedValue(watchedValues, key) {
8560
+ if (key.includes(".")) {
8561
+ const parts = key.split(".");
8562
+ let current = watchedValues;
8563
+ for (const part of parts) {
8564
+ if (current == null || typeof current !== "object") {
8565
+ return watchedValues[key];
8566
+ }
8567
+ current = current[part];
8568
+ }
8569
+ if (current !== void 0) {
8570
+ return current;
8571
+ }
8572
+ return watchedValues[key];
8573
+ }
8574
+ return watchedValues[key];
8575
+ }
8518
8576
  function parseDependsOn(expr) {
8519
8577
  var _a, _b;
8520
- const m = expr.match(/^(.+?)\s*==\s*(?:'([^']*)'|"([^"]*)"|(.+))$/);
8578
+ const m = expr.match(/^([\w.]+)\s*(==|!=)\s*(?:'([^']*)'|"([^"]*)"|(\S+))$/);
8521
8579
  if (!m) {
8522
8580
  return null;
8523
8581
  }
8524
- return { field: m[1].trim(), value: ((_b = (_a = m[2]) != null ? _a : m[3]) != null ? _b : m[4]).trim() };
8582
+ return { field: m[1], value: ((_b = (_a = m[3]) != null ? _a : m[4]) != null ? _b : m[5]).trim(), negate: m[2] === "!=" };
8583
+ }
8584
+ function evaluateDependsOn(parsed, currentValue) {
8585
+ const matches = String(currentValue != null ? currentValue : "") === parsed.value;
8586
+ return parsed.negate ? !matches : matches;
8525
8587
  }
8526
8588
  function resolveActiveOverride(field, watchedValues, fieldById) {
8527
- var _a;
8528
8589
  if (!field.overrides || field.overrides.length === 0) {
8529
8590
  return void 0;
8530
8591
  }
@@ -8535,7 +8596,7 @@ function resolveActiveOverride(field, watchedValues, fieldById) {
8535
8596
  }
8536
8597
  const depField = fieldById.get(parsed.field);
8537
8598
  const depKey = depField ? formKey(depField) : parsed.field;
8538
- if (String((_a = watchedValues[depKey]) != null ? _a : "") === parsed.value) {
8599
+ if (evaluateDependsOn(parsed, getWatchedValue(watchedValues, depKey))) {
8539
8600
  return ov;
8540
8601
  }
8541
8602
  }
@@ -8669,6 +8730,52 @@ function computeVirtualFieldValues(schema, existingValues) {
8669
8730
  }
8670
8731
 
8671
8732
  const SECURE_FIELD_CONFIGURED = "__CONFIGURED__";
8733
+ function resolveSecureKeyTemplate(template, item, index) {
8734
+ return template.replace(/\{index1\}/g, String(index + 1)).replace(/\{index\}/g, String(index)).replace(/\{item\.(\w+)\}/g, (_, key) => {
8735
+ var _a;
8736
+ return String((_a = item[key]) != null ? _a : "");
8737
+ });
8738
+ }
8739
+ function evaluateItemCondition(condition, item) {
8740
+ const trimmed = condition.trim();
8741
+ if (trimmed === "true") {
8742
+ return true;
8743
+ }
8744
+ const match = trimmed.match(/^item\.(\w+)\s*==\s*(.+)$/);
8745
+ if (!match) {
8746
+ return false;
8747
+ }
8748
+ const [, key, rawValue] = match;
8749
+ const actualValue = item[key];
8750
+ const expected = rawValue.trim();
8751
+ if (expected === "true") {
8752
+ return actualValue === true;
8753
+ }
8754
+ if (expected === "false") {
8755
+ return actualValue === false;
8756
+ }
8757
+ const unquoted = expected.replace(/^['"]|['"]$/g, "");
8758
+ return String(actualValue) === unquoted;
8759
+ }
8760
+ function findActiveSecureOverride(itemFields, item, index) {
8761
+ for (const field of itemFields) {
8762
+ if (!field.overrides) {
8763
+ continue;
8764
+ }
8765
+ for (const override of field.overrides) {
8766
+ if (!override.secureKey) {
8767
+ continue;
8768
+ }
8769
+ if (evaluateItemCondition(override.when, item)) {
8770
+ return {
8771
+ fieldKey: field.key,
8772
+ resolvedKey: resolveSecureKeyTemplate(override.secureKey, item, index)
8773
+ };
8774
+ }
8775
+ }
8776
+ }
8777
+ return null;
8778
+ }
8672
8779
  function patternToRegex(pattern) {
8673
8780
  const escaped = pattern.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
8674
8781
  return new RegExp("^" + escaped.replace("\\{index\\}", "(\\d+)") + "$");
@@ -8775,7 +8882,7 @@ function resolveRawPath(ref, ds) {
8775
8882
  return void 0;
8776
8883
  }
8777
8884
  async function fetchExistingValues(dsUid, fields) {
8778
- var _a, _b, _c, _d, _e;
8885
+ var _a, _b, _c, _d, _e, _f;
8779
8886
  try {
8780
8887
  const ds = await runtime.getBackendSrv().get(`/api/datasources/uid/${dsUid}`, void 0, void 0, {
8781
8888
  showErrorAlert: false
@@ -8816,6 +8923,32 @@ async function fetchExistingValues(dsUid, fields) {
8816
8923
  }
8817
8924
  }
8818
8925
  }
8926
+ for (const field of fields) {
8927
+ if (field.valueType !== "array" || !((_f = field.item) == null ? void 0 : _f.fields)) {
8928
+ continue;
8929
+ }
8930
+ const itemFields = field.item.fields;
8931
+ const hasSecureOverride = itemFields.some((f) => {
8932
+ var _a2;
8933
+ return (_a2 = f.overrides) == null ? void 0 : _a2.some((o) => o.secureKey);
8934
+ });
8935
+ if (!hasSecureOverride) {
8936
+ continue;
8937
+ }
8938
+ const fk = formKey(field);
8939
+ const arr = values[fk];
8940
+ if (!Array.isArray(arr)) {
8941
+ continue;
8942
+ }
8943
+ values[fk] = arr.map((item, idx) => {
8944
+ var _a2;
8945
+ const match = findActiveSecureOverride(itemFields, item, idx);
8946
+ if (match && ((_a2 = ds.secureJsonFields) == null ? void 0 : _a2[match.resolvedKey])) {
8947
+ return { ...item, [match.fieldKey]: SECURE_FIELD_CONFIGURED };
8948
+ }
8949
+ return item;
8950
+ });
8951
+ }
8819
8952
  return { values, readOnly: !!ds.readOnly };
8820
8953
  } catch (err) {
8821
8954
  const message = err instanceof Error ? err.message : "Failed to load datasource configuration";
@@ -8823,7 +8956,7 @@ async function fetchExistingValues(dsUid, fields) {
8823
8956
  }
8824
8957
  }
8825
8958
  function buildDatasourceConfigPayload(data, fields, existing, isFieldVisible) {
8826
- var _a, _b, _c, _d;
8959
+ var _a, _b, _c, _d, _e, _f, _g, _h;
8827
8960
  const rootFields = {};
8828
8961
  const jsonData = { ...(_a = existing.jsonData) != null ? _a : {} };
8829
8962
  const secureJsonData = {};
@@ -8872,6 +9005,60 @@ function buildDatasourceConfigPayload(data, fields, existing, isFieldVisible) {
8872
9005
  break;
8873
9006
  }
8874
9007
  }
9008
+ for (const field of fields) {
9009
+ if (field.valueType !== "array" || !((_e = field.item) == null ? void 0 : _e.fields) || field.target !== "jsonData") {
9010
+ continue;
9011
+ }
9012
+ const itemFields = field.item.fields;
9013
+ const hasSecureOverride = itemFields.some((f) => {
9014
+ var _a2;
9015
+ return (_a2 = f.overrides) == null ? void 0 : _a2.some((o) => o.secureKey);
9016
+ });
9017
+ if (!hasSecureOverride) {
9018
+ continue;
9019
+ }
9020
+ const arr = field.section ? (_f = jsonData[field.section]) == null ? void 0 : _f[field.key] : jsonData[field.key];
9021
+ if (!Array.isArray(arr)) {
9022
+ continue;
9023
+ }
9024
+ const secureKeyOverrides = [];
9025
+ for (const f of itemFields) {
9026
+ for (const o of (_g = f.overrides) != null ? _g : []) {
9027
+ if (o.secureKey) {
9028
+ secureKeyOverrides.push({ fieldKey: f.key, override: o });
9029
+ }
9030
+ }
9031
+ }
9032
+ const activeSecureKeys = /* @__PURE__ */ new Set();
9033
+ for (let i = 0; i < arr.length; i++) {
9034
+ const item = arr[i];
9035
+ const match = findActiveSecureOverride(itemFields, item, i);
9036
+ if (!match) {
9037
+ continue;
9038
+ }
9039
+ const resolvedKey = match.resolvedKey;
9040
+ activeSecureKeys.add(resolvedKey);
9041
+ const itemValue = item[match.fieldKey];
9042
+ if (itemValue === SECURE_FIELD_CONFIGURED) {
9043
+ secureJsonFields[resolvedKey] = true;
9044
+ } else if (itemValue && itemValue !== "") {
9045
+ secureJsonData[resolvedKey] = String(itemValue);
9046
+ secureJsonFields[resolvedKey] = false;
9047
+ item[match.fieldKey] = "";
9048
+ }
9049
+ }
9050
+ const existingSecureFields = (_h = existing.secureJsonFields) != null ? _h : {};
9051
+ for (const existingKey of Object.keys(existingSecureFields)) {
9052
+ const couldBeFromThisField = secureKeyOverrides.some((sko) => {
9053
+ const staticPrefix = sko.override.secureKey.split("{")[0];
9054
+ return staticPrefix && existingKey.startsWith(staticPrefix);
9055
+ });
9056
+ if (couldBeFromThisField && !activeSecureKeys.has(existingKey)) {
9057
+ secureJsonFields[existingKey] = false;
9058
+ secureJsonData[existingKey] = "";
9059
+ }
9060
+ }
9061
+ }
8875
9062
  return { rootFields, jsonData, secureJsonData, secureJsonFields };
8876
9063
  }
8877
9064
  async function submitDatasourceConfig(dsUid, data, fields, isFieldVisible) {
@@ -8909,23 +9096,25 @@ function evaluateEffectCondition(when, fieldValue) {
8909
9096
  const eq = String(fieldValue) === String(target);
8910
9097
  return op === "==" ? eq : !eq;
8911
9098
  }
8912
- function isFieldRequired(field, watchedValues, fieldById) {
8913
- var _a;
9099
+ function isFieldRequired(field, watchedValues, fieldById, celContext) {
8914
9100
  if (field.required) {
8915
9101
  return true;
8916
9102
  }
8917
9103
  if (field.requiredWhen) {
9104
+ if (celContext) {
9105
+ return evaluateCelExpression(field.requiredWhen, celContext);
9106
+ }
8918
9107
  const parsed = parseDependsOn(field.requiredWhen);
8919
9108
  if (parsed) {
8920
9109
  const depField = fieldById.get(parsed.field);
8921
9110
  const depKey = depField ? formKey(depField) : parsed.field;
8922
- return String((_a = watchedValues[depKey]) != null ? _a : "") === parsed.value;
9111
+ return evaluateDependsOn(parsed, getWatchedValue(watchedValues, depKey));
8923
9112
  }
8924
9113
  }
8925
9114
  return false;
8926
9115
  }
8927
9116
  function buildValidationRules(field, required) {
8928
- var _a, _b, _c, _d, _e, _f;
9117
+ var _a, _b, _c, _d, _e, _f, _g, _h;
8929
9118
  const rules = {};
8930
9119
  const label = (_a = field.label) != null ? _a : field.key;
8931
9120
  if (required) {
@@ -8943,29 +9132,65 @@ function buildValidationRules(field, required) {
8943
9132
  rules.required = `${label} is required`;
8944
9133
  }
8945
9134
  }
9135
+ if (field.valueType === "array" && ((_b = field.item) == null ? void 0 : _b.valueType) === "object" && ((_c = field.item.fields) == null ? void 0 : _c.length)) {
9136
+ const requiredItemFields = field.item.fields.filter((f) => f.required);
9137
+ if (requiredItemFields.length > 0) {
9138
+ const existingValidate = rules.validate;
9139
+ rules.validate = (value) => {
9140
+ var _a2;
9141
+ if (existingValidate) {
9142
+ const r = existingValidate(value);
9143
+ if (r !== true) {
9144
+ return r;
9145
+ }
9146
+ }
9147
+ if (!Array.isArray(value)) {
9148
+ return true;
9149
+ }
9150
+ const itemErrors = {};
9151
+ for (let i = 0; i < value.length; i++) {
9152
+ const item = value[i];
9153
+ const missing = [];
9154
+ for (const rf of requiredItemFields) {
9155
+ const v = item[rf.key];
9156
+ if (v === void 0 || v === null || v === "") {
9157
+ missing.push((_a2 = rf.label) != null ? _a2 : rf.key);
9158
+ }
9159
+ }
9160
+ if (missing.length > 0) {
9161
+ itemErrors[i] = `${missing.join(", ")} required`;
9162
+ }
9163
+ }
9164
+ if (Object.keys(itemErrors).length === 0) {
9165
+ return true;
9166
+ }
9167
+ return `__ITEM_ERRORS__${JSON.stringify(itemErrors)}`;
9168
+ };
9169
+ }
9170
+ }
8946
9171
  if (field.validations) {
8947
9172
  for (const v of field.validations) {
8948
9173
  switch (v.type) {
8949
9174
  case "pattern":
8950
9175
  rules.pattern = {
8951
9176
  value: new RegExp(v.pattern),
8952
- message: (_b = v.message) != null ? _b : `Invalid ${label}`
9177
+ message: (_d = v.message) != null ? _d : `Invalid ${label}`
8953
9178
  };
8954
9179
  break;
8955
9180
  case "range":
8956
9181
  if (v.min !== void 0) {
8957
- rules.min = { value: v.min, message: (_c = v.message) != null ? _c : `Minimum value is ${v.min}` };
9182
+ rules.min = { value: v.min, message: (_e = v.message) != null ? _e : `Minimum value is ${v.min}` };
8958
9183
  }
8959
9184
  if (v.max !== void 0) {
8960
- rules.max = { value: v.max, message: (_d = v.message) != null ? _d : `Maximum value is ${v.max}` };
9185
+ rules.max = { value: v.max, message: (_f = v.message) != null ? _f : `Maximum value is ${v.max}` };
8961
9186
  }
8962
9187
  break;
8963
9188
  case "length":
8964
9189
  if (v.min !== void 0) {
8965
- rules.minLength = { value: v.min, message: (_e = v.message) != null ? _e : `Minimum length is ${v.min}` };
9190
+ rules.minLength = { value: v.min, message: (_g = v.message) != null ? _g : `Minimum length is ${v.min}` };
8966
9191
  }
8967
9192
  if (v.max !== void 0) {
8968
- rules.maxLength = { value: v.max, message: (_f = v.message) != null ? _f : `Maximum length is ${v.max}` };
9193
+ rules.maxLength = { value: v.max, message: (_h = v.message) != null ? _h : `Maximum length is ${v.max}` };
8969
9194
  }
8970
9195
  break;
8971
9196
  }
@@ -8973,16 +9198,24 @@ function buildValidationRules(field, required) {
8973
9198
  }
8974
9199
  return rules;
8975
9200
  }
9201
+ const ITEM_ERRORS_PREFIX = "__ITEM_ERRORS__";
9202
+ function parseItemErrors(errorMessage) {
9203
+ if (!errorMessage || !errorMessage.startsWith(ITEM_ERRORS_PREFIX)) {
9204
+ return null;
9205
+ }
9206
+ try {
9207
+ return JSON.parse(errorMessage.slice(ITEM_ERRORS_PREFIX.length));
9208
+ } catch (e) {
9209
+ return null;
9210
+ }
9211
+ }
8976
9212
 
8977
- function PdcFieldNote({
8978
- enabled,
8979
- description,
8980
- configUrl
8981
- }) {
8982
- const styles = ui.useStyles2(getStyles$f);
9213
+ const PdcFieldNote = (props) => {
9214
+ const { enabled, description, configUrl } = props;
9215
+ const styles = ui.useStyles2(getStyles$h);
8983
9216
  return /* @__PURE__ */ React__default.default.createElement("div", { className: styles.wrapper }, /* @__PURE__ */ React__default.default.createElement("div", { className: styles.note }, /* @__PURE__ */ React__default.default.createElement(ui.Icon, { name: "shield", size: "xs" }), /* @__PURE__ */ React__default.default.createElement("span", null, "Private data source connect: ", /* @__PURE__ */ React__default.default.createElement("strong", null, enabled ? "Enabled" : "Disabled")), description && /* @__PURE__ */ React__default.default.createElement(ui.Tooltip, { content: description }, /* @__PURE__ */ React__default.default.createElement(ui.Icon, { name: "info-circle", size: "xs" }))), /* @__PURE__ */ React__default.default.createElement(ui.LinkButton, { variant: "secondary", size: "sm", icon: "external-link-alt", href: configUrl }, "Configure in settings"));
8984
- }
8985
- const getStyles$f = (theme) => ({
9217
+ };
9218
+ const getStyles$h = (theme) => ({
8986
9219
  wrapper: css.css({
8987
9220
  display: "flex",
8988
9221
  alignItems: "center",
@@ -9002,18 +9235,14 @@ const getStyles$f = (theme) => ({
9002
9235
  })
9003
9236
  });
9004
9237
 
9005
- function SecureFieldInput({
9006
- formField,
9007
- placeholder,
9008
- disabled,
9009
- label
9010
- }) {
9238
+ function SecureFieldInput(props) {
9011
9239
  var _a;
9240
+ const { formField, placeholder, disabled } = props;
9012
9241
  const isConfigured = formField.value === SECURE_FIELD_CONFIGURED;
9013
9242
  const [revealed, setRevealed] = React.useState(false);
9014
9243
  const styles = ui.useStyles2(getSecureFieldStyles);
9015
9244
  if (isConfigured) {
9016
- return /* @__PURE__ */ React__default.default.createElement("div", { className: styles.configuredRow }, /* @__PURE__ */ React__default.default.createElement("span", { className: styles.configuredBadge }, /* @__PURE__ */ React__default.default.createElement(ui.Icon, { name: "lock", size: "xs" }), label, " configured"), !disabled && /* @__PURE__ */ React__default.default.createElement(ui.Button, { variant: "secondary", fill: "text", size: "sm", onClick: () => formField.onChange(""), type: "button" }, "Reset"));
9245
+ return /* @__PURE__ */ React__default.default.createElement("div", { className: styles.configuredRow }, /* @__PURE__ */ React__default.default.createElement("span", { className: styles.configuredBadge }, /* @__PURE__ */ React__default.default.createElement(ui.Icon, { name: "lock", size: "xs" }), "Configured"), !disabled && /* @__PURE__ */ React__default.default.createElement(ui.Button, { variant: "secondary", fill: "text", size: "sm", onClick: () => formField.onChange(""), type: "button" }, "Reset"));
9017
9246
  }
9018
9247
  return /* @__PURE__ */ React__default.default.createElement(
9019
9248
  ui.Input,
@@ -9042,7 +9271,8 @@ const getSecureFieldStyles = (theme) => ({
9042
9271
  configuredRow: css.css({
9043
9272
  display: "flex",
9044
9273
  alignItems: "center",
9045
- gap: theme.spacing(1)
9274
+ gap: theme.spacing(1),
9275
+ whiteSpace: "nowrap"
9046
9276
  }),
9047
9277
  configuredBadge: css.css({
9048
9278
  display: "inline-flex",
@@ -9052,130 +9282,207 @@ const getSecureFieldStyles = (theme) => ({
9052
9282
  borderRadius: theme.shape.radius.pill,
9053
9283
  backgroundColor: theme.colors.success.transparent,
9054
9284
  color: theme.colors.success.text,
9055
- fontSize: theme.typography.bodySmall.fontSize
9285
+ fontSize: theme.typography.bodySmall.fontSize,
9286
+ whiteSpace: "nowrap"
9056
9287
  })
9057
9288
  });
9058
9289
 
9059
- function StringArrayInput({
9060
- value,
9061
- onChange,
9062
- placeholder,
9063
- disabled
9064
- }) {
9065
- const [draft, setDraft] = React.useState("");
9290
+ const ComplexFieldNote = (props) => {
9291
+ const { count, label } = props;
9292
+ const styles = ui.useStyles2(getStyles$g);
9293
+ return /* @__PURE__ */ React__default.default.createElement("div", { className: styles.note }, /* @__PURE__ */ React__default.default.createElement(ui.Icon, { name: "info-circle", size: "xs" }), /* @__PURE__ */ React__default.default.createElement("span", null, count > 0 ? `${count} ${label.toLowerCase()} configured.` : `No ${label.toLowerCase()} configured.`, " Configure in Grafana UI."));
9294
+ };
9295
+ const getStyles$g = (theme) => ({
9296
+ note: css.css({
9297
+ display: "inline-flex",
9298
+ alignItems: "center",
9299
+ gap: theme.spacing(0.5),
9300
+ padding: `${theme.spacing(0.5)} ${theme.spacing(0.75)}`,
9301
+ fontSize: theme.typography.bodySmall.fontSize,
9302
+ color: theme.colors.text.secondary,
9303
+ backgroundColor: theme.colors.background.secondary,
9304
+ borderRadius: theme.shape.radius.default,
9305
+ border: `1px solid ${theme.colors.border.weak}`
9306
+ })
9307
+ });
9308
+
9309
+ function FileUploadField(props) {
9310
+ var _a, _b, _c, _d, _e, _f, _g;
9311
+ const { field, formField, disabled, setValue } = props;
9312
+ const [mode, setModeLocal] = React.useState("upload");
9313
+ const [error, setError] = React.useState(null);
9314
+ const theme = ui.useTheme2();
9315
+ const mapping = (_a = field.ui) == null ? void 0 : _a.fileMapping;
9316
+ const accept = (_c = (_b = field.ui) == null ? void 0 : _b.accept) != null ? _c : [".json"];
9317
+ const setMode = React.useCallback(
9318
+ (next) => {
9319
+ setModeLocal(next);
9320
+ formField.onChange(next);
9321
+ },
9322
+ [formField]
9323
+ );
9324
+ const processJson = React.useCallback(
9325
+ (text) => {
9326
+ const fileMapping = mapping != null ? mapping : {};
9327
+ try {
9328
+ const parsed = JSON.parse(text);
9329
+ if (typeof parsed !== "object" || parsed === null) {
9330
+ setError("Invalid JSON object");
9331
+ return;
9332
+ }
9333
+ const requiredKeys = Object.keys(fileMapping);
9334
+ const missingKeys = requiredKeys.filter((k) => parsed[k] === void 0);
9335
+ if (missingKeys.length > 0) {
9336
+ setError(`Missing keys: ${missingKeys.join(", ")}`);
9337
+ return;
9338
+ }
9339
+ for (const [jsonKey, targetFieldId] of Object.entries(fileMapping)) {
9340
+ if (parsed[jsonKey] !== void 0) {
9341
+ const parts = targetFieldId.split(".");
9342
+ const fk = parts.length === 2 ? parts[1] : targetFieldId;
9343
+ setValue(fk, parsed[jsonKey]);
9344
+ }
9345
+ }
9346
+ setError(null);
9347
+ setModeLocal("manual");
9348
+ formField.onChange("manual");
9349
+ } catch (e) {
9350
+ setError("Invalid JSON");
9351
+ }
9352
+ },
9353
+ [mapping, setValue, formField]
9354
+ );
9355
+ const styles = getStyles$f(theme);
9356
+ if (mode === "manual") {
9357
+ return /* @__PURE__ */ React__default.default.createElement("div", { className: styles.buttonRow }, /* @__PURE__ */ React__default.default.createElement(ui.Button, { type: "button", fill: "outline", size: "sm", onClick: () => setMode("paste"), disabled }, "Paste JWT Token"), /* @__PURE__ */ React__default.default.createElement("span", { className: styles.separator }, "or"), /* @__PURE__ */ React__default.default.createElement(ui.Button, { type: "button", fill: "outline", size: "sm", onClick: () => setMode("upload"), disabled }, "Upload JWT Token"));
9358
+ }
9359
+ if (mode === "paste") {
9360
+ return /* @__PURE__ */ React__default.default.createElement("div", null, /* @__PURE__ */ React__default.default.createElement(
9361
+ ui.TextArea,
9362
+ {
9363
+ placeholder: (_e = (_d = field.ui) == null ? void 0 : _d.placeholder) != null ? _e : "Paste Google JWT token here",
9364
+ rows: (_g = (_f = field.ui) == null ? void 0 : _f.rows) != null ? _g : 10,
9365
+ onBlur: (e) => {
9366
+ const val = e.currentTarget.value;
9367
+ if (val.trim()) {
9368
+ processJson(val);
9369
+ }
9370
+ },
9371
+ disabled
9372
+ }
9373
+ ), /* @__PURE__ */ React__default.default.createElement("div", { className: styles.buttonRow }, /* @__PURE__ */ React__default.default.createElement(ui.Button, { type: "button", fill: "outline", size: "sm", onClick: () => setMode("upload"), disabled }, "Upload JWT Token"), /* @__PURE__ */ React__default.default.createElement("span", { className: styles.separator }, "or"), /* @__PURE__ */ React__default.default.createElement(ui.Button, { type: "button", fill: "outline", size: "sm", onClick: () => setMode("manual"), disabled }, "Fill In JWT Token manually")), error && /* @__PURE__ */ React__default.default.createElement("span", { className: styles.error }, error));
9374
+ }
9375
+ return /* @__PURE__ */ React__default.default.createElement("div", null, /* @__PURE__ */ React__default.default.createElement(
9376
+ ui.FileDropzone,
9377
+ {
9378
+ options: { multiple: false, accept: accept.join(",") },
9379
+ readAs: "readAsText",
9380
+ onLoad: (result) => {
9381
+ if (typeof result === "string") {
9382
+ processJson(result);
9383
+ }
9384
+ }
9385
+ }
9386
+ ), /* @__PURE__ */ React__default.default.createElement("div", { className: styles.buttonRow }, /* @__PURE__ */ React__default.default.createElement(ui.Button, { type: "button", fill: "outline", size: "sm", onClick: () => setMode("paste"), disabled }, "Paste JWT Token"), /* @__PURE__ */ React__default.default.createElement("span", { className: styles.separator }, "or"), /* @__PURE__ */ React__default.default.createElement(ui.Button, { type: "button", fill: "outline", size: "sm", onClick: () => setMode("manual"), disabled }, "Fill In JWT Token manually")), error && /* @__PURE__ */ React__default.default.createElement("span", { className: styles.error }, error));
9387
+ }
9388
+ function getStyles$f(theme) {
9389
+ return {
9390
+ buttonRow: css.css({
9391
+ marginTop: theme.spacing(1),
9392
+ display: "flex",
9393
+ alignItems: "center",
9394
+ gap: theme.spacing(0.5)
9395
+ }),
9396
+ separator: css.css({
9397
+ padding: `0 ${theme.spacing(0.5)}`,
9398
+ color: theme.colors.text.secondary
9399
+ }),
9400
+ error: css.css({
9401
+ color: theme.colors.error.text,
9402
+ fontSize: theme.typography.bodySmall.fontSize,
9403
+ marginTop: theme.spacing(0.5),
9404
+ display: "block"
9405
+ })
9406
+ };
9407
+ }
9408
+
9409
+ const IndexedPairEditor = (props) => {
9410
+ const { value, onChange, maxItems = 10, disabled, hideControls, itemLabel = "header" } = props;
9066
9411
  const styles = ui.useStyles2(getStyles$e);
9067
- const addTag = () => {
9068
- const trimmed = draft.trim();
9069
- if (trimmed && !value.includes(trimmed)) {
9070
- onChange([...value, trimmed]);
9412
+ const items = Array.isArray(value) ? value : [];
9413
+ const addItem = () => {
9414
+ if (items.length >= maxItems) {
9415
+ return;
9071
9416
  }
9072
- setDraft("");
9417
+ onChange([...items, { index: 0, name: "", value: "" }]);
9418
+ };
9419
+ const removeItem = (index) => {
9420
+ onChange(items.filter((_, i) => i !== index));
9073
9421
  };
9074
- const removeTag = (tag) => {
9075
- onChange(value.filter((v) => v !== tag));
9422
+ const updateItem = (index, key, val) => {
9423
+ const updated = items.map((item, i) => i === index ? { ...item, [key]: val } : item);
9424
+ onChange(updated);
9076
9425
  };
9077
- return /* @__PURE__ */ React__default.default.createElement("div", { className: styles.container }, value.length > 0 && /* @__PURE__ */ React__default.default.createElement("div", { className: styles.tags }, value.map((tag) => /* @__PURE__ */ React__default.default.createElement("span", { key: tag, className: styles.tag }, tag, !disabled && /* @__PURE__ */ React__default.default.createElement(
9078
- "button",
9426
+ return /* @__PURE__ */ React__default.default.createElement(ui.Stack, { direction: "column", gap: 0.5 }, items.map((item, i) => /* @__PURE__ */ React__default.default.createElement(
9427
+ IndexedPairRow,
9079
9428
  {
9080
- type: "button",
9081
- className: styles.tagRemove,
9082
- onClick: () => removeTag(tag),
9083
- "aria-label": `Remove ${tag}`
9429
+ key: item.index || `new-${i}`,
9430
+ item,
9431
+ index: i,
9432
+ disabled,
9433
+ onUpdate: updateItem,
9434
+ onRemove: removeItem,
9435
+ hideControls,
9436
+ itemLabel
9437
+ }
9438
+ )), !hideControls && items.length < maxItems && /* @__PURE__ */ React__default.default.createElement("div", null, /* @__PURE__ */ React__default.default.createElement(ui.Button, { variant: "secondary", size: "sm", icon: "plus", disabled, onClick: addItem, type: "button" }, "Add ", itemLabel)), !hideControls && items.length >= maxItems && /* @__PURE__ */ React__default.default.createElement("span", { className: styles.limitNote }, "Maximum ", maxItems, " ", itemLabel, "s reached"));
9439
+ };
9440
+ const IndexedPairRow = (props) => {
9441
+ const { item, index, disabled, onUpdate, onRemove, hideControls, itemLabel = "header" } = props;
9442
+ const styles = ui.useStyles2(getStyles$e);
9443
+ const secureStyles = ui.useStyles2(getSecureFieldStyles);
9444
+ const isConfigured = item.value === SECURE_FIELD_CONFIGURED;
9445
+ const [editing, setEditing] = React.useState(false);
9446
+ const [revealed, setRevealed] = React.useState(false);
9447
+ return /* @__PURE__ */ React__default.default.createElement(ui.Stack, { direction: "row", gap: 1 }, /* @__PURE__ */ React__default.default.createElement("div", { className: styles.inputCell }, /* @__PURE__ */ React__default.default.createElement(
9448
+ ui.Input,
9449
+ {
9450
+ value: item.name,
9451
+ placeholder: "key",
9452
+ disabled: disabled || hideControls,
9453
+ onChange: (e) => onUpdate(index, "name", e.currentTarget.value),
9454
+ onKeyDown: (e) => {
9455
+ if (e.key === "Enter") {
9456
+ e.preventDefault();
9457
+ }
9458
+ }
9459
+ }
9460
+ )), /* @__PURE__ */ React__default.default.createElement("div", { className: styles.inputCell }, isConfigured && !editing ? /* @__PURE__ */ React__default.default.createElement(ui.Stack, { direction: "row", gap: 1, alignItems: "center" }, /* @__PURE__ */ React__default.default.createElement("span", { className: secureStyles.configuredBadge }, /* @__PURE__ */ React__default.default.createElement(ui.Icon, { name: "lock", size: "xs" }), "Configured"), !disabled && /* @__PURE__ */ React__default.default.createElement(
9461
+ ui.Button,
9462
+ {
9463
+ variant: "secondary",
9464
+ fill: "text",
9465
+ size: "sm",
9466
+ onClick: () => {
9467
+ setEditing(true);
9468
+ onUpdate(index, "value", "");
9469
+ },
9470
+ type: "button"
9084
9471
  },
9085
- /* @__PURE__ */ React__default.default.createElement(ui.Icon, { name: "times", size: "xs" })
9086
- )))), /* @__PURE__ */ React__default.default.createElement(
9472
+ "Reset"
9473
+ )) : /* @__PURE__ */ React__default.default.createElement(
9087
9474
  ui.Input,
9088
9475
  {
9089
- value: draft,
9090
- onChange: (e) => setDraft(e.currentTarget.value),
9476
+ value: item.value === SECURE_FIELD_CONFIGURED ? "" : item.value,
9477
+ placeholder: `${itemLabel} value`,
9478
+ disabled,
9479
+ type: revealed ? "text" : "password",
9480
+ onChange: (e) => onUpdate(index, "value", e.currentTarget.value),
9091
9481
  onKeyDown: (e) => {
9092
9482
  if (e.key === "Enter") {
9093
9483
  e.preventDefault();
9094
- addTag();
9095
9484
  }
9096
9485
  },
9097
- onBlur: addTag,
9098
- placeholder,
9099
- disabled
9100
- }
9101
- ));
9102
- }
9103
- const getStyles$e = (theme) => ({
9104
- container: css.css({
9105
- display: "flex",
9106
- flexDirection: "column",
9107
- gap: theme.spacing(0.5)
9108
- }),
9109
- tags: css.css({
9110
- display: "flex",
9111
- flexWrap: "wrap",
9112
- gap: theme.spacing(0.5)
9113
- }),
9114
- tag: css.css({
9115
- display: "inline-flex",
9116
- alignItems: "center",
9117
- gap: theme.spacing(0.25),
9118
- padding: `${theme.spacing(0.25)} ${theme.spacing(0.75)}`,
9119
- borderRadius: theme.shape.radius.pill,
9120
- backgroundColor: theme.colors.background.secondary,
9121
- border: `1px solid ${theme.colors.border.weak}`,
9122
- fontSize: theme.typography.bodySmall.fontSize,
9123
- color: theme.colors.text.primary
9124
- }),
9125
- tagRemove: css.css({
9126
- display: "inline-flex",
9127
- alignItems: "center",
9128
- padding: 0,
9129
- border: "none",
9130
- backgroundColor: "transparent",
9131
- cursor: "pointer",
9132
- color: theme.colors.text.secondary,
9133
- "&:hover": { color: theme.colors.text.primary }
9134
- })
9135
- });
9136
-
9137
- function IndexedPairRow({
9138
- item,
9139
- index,
9140
- disabled,
9141
- onUpdate,
9142
- onRemove,
9143
- hideControls
9144
- }) {
9145
- const styles = ui.useStyles2(getStyles$d);
9146
- const secureStyles = ui.useStyles2(getSecureFieldStyles);
9147
- const isConfigured = item.value === SECURE_FIELD_CONFIGURED;
9148
- const [editing, setEditing] = React.useState(false);
9149
- const [revealed, setRevealed] = React.useState(false);
9150
- return /* @__PURE__ */ React__default.default.createElement(ui.Stack, { direction: "row", gap: 1 }, /* @__PURE__ */ React__default.default.createElement("div", { className: styles.inputCell }, /* @__PURE__ */ React__default.default.createElement(
9151
- ui.Input,
9152
- {
9153
- value: item.name,
9154
- placeholder: "Header name",
9155
- disabled: disabled || hideControls,
9156
- onChange: (e) => onUpdate(index, "name", e.currentTarget.value)
9157
- }
9158
- )), /* @__PURE__ */ React__default.default.createElement("div", { className: styles.inputCell }, isConfigured && !editing ? /* @__PURE__ */ React__default.default.createElement(ui.Stack, { direction: "row", gap: 1, alignItems: "center" }, /* @__PURE__ */ React__default.default.createElement("span", { className: secureStyles.configuredBadge }, /* @__PURE__ */ React__default.default.createElement(ui.Icon, { name: "lock", size: "xs" }), "Configured"), !disabled && /* @__PURE__ */ React__default.default.createElement(
9159
- ui.Button,
9160
- {
9161
- variant: "secondary",
9162
- fill: "text",
9163
- size: "sm",
9164
- onClick: () => {
9165
- setEditing(true);
9166
- onUpdate(index, "value", "");
9167
- },
9168
- type: "button"
9169
- },
9170
- "Reset"
9171
- )) : /* @__PURE__ */ React__default.default.createElement(
9172
- ui.Input,
9173
- {
9174
- value: item.value === SECURE_FIELD_CONFIGURED ? "" : item.value,
9175
- placeholder: "Header value",
9176
- disabled,
9177
- type: revealed ? "text" : "password",
9178
- onChange: (e) => onUpdate(index, "value", e.currentTarget.value),
9179
9486
  suffix: /* @__PURE__ */ React__default.default.createElement(
9180
9487
  ui.Button,
9181
9488
  {
@@ -9189,34 +9496,56 @@ function IndexedPairRow({
9189
9496
  }
9190
9497
  )
9191
9498
  }
9192
- )), !hideControls && /* @__PURE__ */ React__default.default.createElement(ui.Tooltip, { content: "Remove header" }, /* @__PURE__ */ React__default.default.createElement(
9499
+ )), !hideControls && /* @__PURE__ */ React__default.default.createElement(ui.Tooltip, { content: `Remove ${itemLabel}` }, /* @__PURE__ */ React__default.default.createElement(
9193
9500
  ui.Button,
9194
9501
  {
9195
9502
  variant: "secondary",
9196
9503
  fill: "text",
9197
9504
  size: "sm",
9198
9505
  icon: "trash-alt",
9199
- "aria-label": "Remove header",
9506
+ "aria-label": `Remove ${itemLabel}`,
9200
9507
  disabled,
9201
9508
  onClick: () => onRemove(index),
9202
9509
  type: "button"
9203
9510
  }
9204
9511
  )));
9205
- }
9206
- function IndexedPairEditor({
9207
- value,
9208
- onChange,
9209
- maxItems = 10,
9210
- disabled,
9211
- hideControls
9212
- }) {
9512
+ };
9513
+ const getStyles$e = (theme) => ({
9514
+ inputCell: css.css({
9515
+ flex: "1 1 0",
9516
+ minWidth: 0,
9517
+ overflow: "hidden"
9518
+ }),
9519
+ limitNote: css.css({
9520
+ fontSize: theme.typography.bodySmall.fontSize,
9521
+ color: theme.colors.text.secondary
9522
+ })
9523
+ });
9524
+
9525
+ function ObjectArrayEditor(props) {
9526
+ var _a, _b, _c, _d, _e, _f;
9527
+ const { field, value, onChange, disabled, errorMessage } = props;
9213
9528
  const styles = ui.useStyles2(getStyles$d);
9529
+ const itemFields = (_b = (_a = field.item) == null ? void 0 : _a.fields) != null ? _b : [];
9530
+ const layoutRows = computeLayoutRows(itemFields);
9214
9531
  const items = Array.isArray(value) ? value : [];
9532
+ const maxItems = (_e = (_d = (_c = field.validations) == null ? void 0 : _c.find((v) => v.type === "itemCount")) == null ? void 0 : _d.max) != null ? _e : 20;
9533
+ const label = (_f = field.label) != null ? _f : field.key;
9534
+ const itemErrors = parseItemErrors(errorMessage);
9215
9535
  const addItem = () => {
9536
+ var _a2, _b2;
9216
9537
  if (items.length >= maxItems) {
9217
9538
  return;
9218
9539
  }
9219
- onChange([...items, { index: 0, name: "", value: "" }]);
9540
+ const empty = {};
9541
+ for (const f of itemFields) {
9542
+ if (f.valueType === "boolean") {
9543
+ empty[f.key] = (_a2 = f.defaultValue) != null ? _a2 : false;
9544
+ } else {
9545
+ empty[f.key] = (_b2 = f.defaultValue) != null ? _b2 : "";
9546
+ }
9547
+ }
9548
+ onChange([...items, empty]);
9220
9549
  };
9221
9550
  const removeItem = (index) => {
9222
9551
  onChange(items.filter((_, i) => i !== index));
@@ -9225,78 +9554,241 @@ function IndexedPairEditor({
9225
9554
  const updated = items.map((item, i) => i === index ? { ...item, [key]: val } : item);
9226
9555
  onChange(updated);
9227
9556
  };
9228
- return /* @__PURE__ */ React__default.default.createElement(ui.Stack, { direction: "column", gap: 0.5 }, items.map((item, i) => /* @__PURE__ */ React__default.default.createElement(
9229
- IndexedPairRow,
9557
+ return /* @__PURE__ */ React__default.default.createElement(ui.Stack, { direction: "column", gap: 1 }, items.map((item, i) => /* @__PURE__ */ React__default.default.createElement(
9558
+ ObjectArrayItemRow,
9230
9559
  {
9231
- key: item.index || `new-${i}`,
9560
+ key: i,
9232
9561
  item,
9233
9562
  index: i,
9234
- disabled,
9563
+ itemFields,
9564
+ layoutRows,
9565
+ disabled: !!disabled,
9235
9566
  onUpdate: updateItem,
9236
9567
  onRemove: removeItem,
9237
- hideControls
9568
+ showLabels: true,
9569
+ error: itemErrors == null ? void 0 : itemErrors[i]
9570
+ }
9571
+ )), items.length < maxItems && /* @__PURE__ */ React__default.default.createElement("div", null, /* @__PURE__ */ React__default.default.createElement(ui.Button, { variant: "secondary", size: "sm", icon: "plus", disabled, onClick: addItem, type: "button" }, "Add ", label.toLowerCase())), items.length >= maxItems && /* @__PURE__ */ React__default.default.createElement("span", { className: styles.limitNote }, "Maximum ", maxItems, " items reached"));
9572
+ }
9573
+ function computeLayoutRows(fields) {
9574
+ var _a;
9575
+ const hasExplicitRow = fields.some((f) => {
9576
+ var _a2;
9577
+ return ((_a2 = f.ui) == null ? void 0 : _a2.row) !== void 0;
9578
+ });
9579
+ if (!hasExplicitRow) {
9580
+ if (fields.length <= 3) {
9581
+ return [fields];
9582
+ }
9583
+ return fields.map((f) => [f]);
9584
+ }
9585
+ const rowMap = /* @__PURE__ */ new Map();
9586
+ const noRow = [];
9587
+ for (const f of fields) {
9588
+ if (((_a = f.ui) == null ? void 0 : _a.row) !== void 0) {
9589
+ const existing = rowMap.get(f.ui.row);
9590
+ if (existing) {
9591
+ existing.push(f);
9592
+ } else {
9593
+ rowMap.set(f.ui.row, [f]);
9594
+ }
9595
+ } else {
9596
+ noRow.push(f);
9238
9597
  }
9239
- )), !hideControls && items.length < maxItems && /* @__PURE__ */ React__default.default.createElement("div", null, /* @__PURE__ */ React__default.default.createElement(ui.Button, { variant: "secondary", size: "sm", icon: "plus", disabled, onClick: addItem, type: "button" }, "Add header")), !hideControls && items.length >= maxItems && /* @__PURE__ */ React__default.default.createElement("span", { className: styles.limitNote }, "Maximum ", maxItems, " headers reached"));
9598
+ }
9599
+ const sortedKeys = [...rowMap.keys()].sort((a, b) => a - b);
9600
+ const rows = sortedKeys.map((k) => rowMap.get(k));
9601
+ for (const f of noRow) {
9602
+ rows.push([f]);
9603
+ }
9604
+ return rows;
9605
+ }
9606
+ function makeItemFormField(item, index, fieldKey, onUpdate) {
9607
+ return {
9608
+ name: `item-${index}-${fieldKey}`,
9609
+ value: item[fieldKey],
9610
+ onChange: (eventOrValue) => {
9611
+ if (eventOrValue != null && typeof eventOrValue === "object" && "target" in eventOrValue) {
9612
+ onUpdate(index, fieldKey, eventOrValue.target.value);
9613
+ } else {
9614
+ onUpdate(index, fieldKey, eventOrValue);
9615
+ }
9616
+ },
9617
+ onBlur: () => {
9618
+ }
9619
+ };
9620
+ }
9621
+ function effectiveItemField(field, isSecure) {
9622
+ if (!isSecure) {
9623
+ return field;
9624
+ }
9625
+ return { ...field, semanticType: "password" };
9626
+ }
9627
+ function ObjectArrayItemRow({
9628
+ item,
9629
+ index,
9630
+ itemFields,
9631
+ layoutRows,
9632
+ disabled,
9633
+ onUpdate,
9634
+ onRemove,
9635
+ showLabels,
9636
+ error
9637
+ }) {
9638
+ const styles = ui.useStyles2(getStyles$d);
9639
+ const secureOverride = findActiveSecureOverride(itemFields, item, index);
9640
+ return /* @__PURE__ */ React__default.default.createElement("div", { className: styles.itemRow }, layoutRows.map((row, rowIdx) => /* @__PURE__ */ React__default.default.createElement(ui.Stack, { key: rowIdx, direction: "row", gap: 1, alignItems: "flex-end", wrap: "wrap" }, row.map((field) => {
9641
+ var _a;
9642
+ const isSecureTarget = (secureOverride == null ? void 0 : secureOverride.fieldKey) === field.key;
9643
+ const eff = effectiveItemField(field, !!isSecureTarget);
9644
+ const formField = makeItemFormField(item, index, field.key, onUpdate);
9645
+ if (isSecureTarget && item[field.key] === SECURE_FIELD_CONFIGURED) {
9646
+ formField.value = SECURE_FIELD_CONFIGURED;
9647
+ }
9648
+ return /* @__PURE__ */ React__default.default.createElement("div", { key: field.key, className: field.valueType === "boolean" ? styles.boolCell : styles.inputCell }, /* @__PURE__ */ React__default.default.createElement("span", { className: styles.cellLabel }, (_a = field.label) != null ? _a : field.key, field.required && /* @__PURE__ */ React__default.default.createElement("span", { className: styles.required }, " *")), renderFieldInput(eff, formField, disabled));
9649
+ }), rowIdx === 0 && /* @__PURE__ */ React__default.default.createElement("div", { className: styles.removeCellWithLabel }, /* @__PURE__ */ React__default.default.createElement(ui.Tooltip, { content: "Remove" }, /* @__PURE__ */ React__default.default.createElement(
9650
+ ui.Button,
9651
+ {
9652
+ variant: "secondary",
9653
+ fill: "text",
9654
+ size: "sm",
9655
+ icon: "trash-alt",
9656
+ "aria-label": "Remove item",
9657
+ disabled,
9658
+ onClick: () => onRemove(index),
9659
+ type: "button"
9660
+ }
9661
+ ))))), error && /* @__PURE__ */ React__default.default.createElement("span", { className: styles.itemError }, error));
9240
9662
  }
9241
9663
  const getStyles$d = (theme) => ({
9664
+ itemRow: css.css({
9665
+ display: "flex",
9666
+ flexDirection: "column",
9667
+ gap: theme.spacing(0.5),
9668
+ padding: theme.spacing(1),
9669
+ borderRadius: theme.shape.radius.default,
9670
+ border: `1px solid ${theme.colors.border.weak}`
9671
+ }),
9242
9672
  inputCell: css.css({
9243
- flex: "1 1 0",
9244
- minWidth: 0,
9673
+ flex: "1 1 120px",
9674
+ minWidth: 120,
9245
9675
  overflow: "hidden"
9246
9676
  }),
9677
+ boolCell: css.css({
9678
+ flex: "0 0 auto",
9679
+ minWidth: 0
9680
+ }),
9681
+ cellLabel: css.css({
9682
+ fontSize: theme.typography.bodySmall.fontSize,
9683
+ color: theme.colors.text.secondary,
9684
+ marginBottom: theme.spacing(0.25)
9685
+ }),
9686
+ required: css.css({
9687
+ color: theme.colors.error.text
9688
+ }),
9689
+ removeCellWithLabel: css.css({
9690
+ flex: "0 0 auto",
9691
+ display: "flex",
9692
+ alignItems: "flex-end",
9693
+ paddingBottom: theme.spacing(0.25)
9694
+ }),
9695
+ itemError: css.css({
9696
+ fontSize: theme.typography.bodySmall.fontSize,
9697
+ color: theme.colors.error.text
9698
+ }),
9247
9699
  limitNote: css.css({
9248
9700
  fontSize: theme.typography.bodySmall.fontSize,
9249
9701
  color: theme.colors.text.secondary
9250
9702
  })
9251
9703
  });
9252
9704
 
9253
- function ComplexFieldNote({ count, label }) {
9705
+ const StringArrayInput = (props) => {
9706
+ const { value, onChange, placeholder, disabled, itemLabel = "item" } = props;
9254
9707
  const styles = ui.useStyles2(getStyles$c);
9255
- return /* @__PURE__ */ React__default.default.createElement("div", { className: styles.note }, /* @__PURE__ */ React__default.default.createElement(ui.Icon, { name: "info-circle", size: "xs" }), /* @__PURE__ */ React__default.default.createElement("span", null, count > 0 ? `${count} ${label.toLowerCase()} configured.` : `No ${label.toLowerCase()} configured.`, " Configure in Grafana UI."));
9256
- }
9708
+ const items = Array.isArray(value) ? value : [];
9709
+ const lastInputRef = React.useRef(null);
9710
+ const shouldFocusLastRef = React.useRef(false);
9711
+ React.useEffect(() => {
9712
+ if (shouldFocusLastRef.current && lastInputRef.current) {
9713
+ lastInputRef.current.focus();
9714
+ shouldFocusLastRef.current = false;
9715
+ }
9716
+ }, [items.length]);
9717
+ const addItem = () => {
9718
+ shouldFocusLastRef.current = true;
9719
+ onChange([...items, ""]);
9720
+ };
9721
+ const removeItem = (index) => {
9722
+ onChange(items.filter((_, i) => i !== index));
9723
+ };
9724
+ const updateItem = (index, val) => {
9725
+ onChange(items.map((item, i) => i === index ? val : item));
9726
+ };
9727
+ const isItemValid = (index, val) => {
9728
+ const trimmed = val.trim();
9729
+ if (trimmed === "") {
9730
+ return false;
9731
+ }
9732
+ return !items.some((item, i) => i !== index && item.trim() === trimmed);
9733
+ };
9734
+ const handleEnter = (index, currentValue) => {
9735
+ if (!isItemValid(index, currentValue)) {
9736
+ return;
9737
+ }
9738
+ if (index === items.length - 1) {
9739
+ shouldFocusLastRef.current = true;
9740
+ onChange([...items, ""]);
9741
+ }
9742
+ };
9743
+ return /* @__PURE__ */ React__default.default.createElement(ui.Stack, { direction: "column", gap: 0.5 }, items.map((item, i) => /* @__PURE__ */ React__default.default.createElement(ui.Stack, { direction: "row", gap: 1, key: i }, /* @__PURE__ */ React__default.default.createElement("div", { className: styles.inputCell }, /* @__PURE__ */ React__default.default.createElement(
9744
+ ui.Input,
9745
+ {
9746
+ ref: i === items.length - 1 ? lastInputRef : void 0,
9747
+ value: item,
9748
+ placeholder: placeholder != null ? placeholder : itemLabel,
9749
+ disabled,
9750
+ onChange: (e) => updateItem(i, e.currentTarget.value),
9751
+ onKeyDown: (e) => {
9752
+ if (e.key === "Enter") {
9753
+ e.preventDefault();
9754
+ handleEnter(i, e.currentTarget.value);
9755
+ }
9756
+ }
9757
+ }
9758
+ )), !disabled && /* @__PURE__ */ React__default.default.createElement(ui.Tooltip, { content: `Remove ${itemLabel}` }, /* @__PURE__ */ React__default.default.createElement(
9759
+ ui.Button,
9760
+ {
9761
+ variant: "secondary",
9762
+ fill: "text",
9763
+ size: "sm",
9764
+ icon: "trash-alt",
9765
+ "aria-label": `Remove ${itemLabel}`,
9766
+ onClick: () => removeItem(i),
9767
+ type: "button"
9768
+ }
9769
+ )))), !disabled && /* @__PURE__ */ React__default.default.createElement("div", null, /* @__PURE__ */ React__default.default.createElement(ui.Button, { variant: "secondary", size: "sm", icon: "plus", onClick: addItem, type: "button" }, "Add")));
9770
+ };
9257
9771
  const getStyles$c = (theme) => ({
9258
- note: css.css({
9259
- display: "inline-flex",
9260
- alignItems: "center",
9261
- gap: theme.spacing(0.5),
9262
- padding: `${theme.spacing(0.5)} ${theme.spacing(0.75)}`,
9263
- fontSize: theme.typography.bodySmall.fontSize,
9264
- color: theme.colors.text.secondary,
9265
- backgroundColor: theme.colors.background.secondary,
9266
- borderRadius: theme.shape.radius.default,
9267
- border: `1px solid ${theme.colors.border.weak}`
9772
+ inputCell: css.css({
9773
+ flex: "1 1 0",
9774
+ minWidth: 0,
9775
+ overflow: "hidden"
9268
9776
  })
9269
9777
  });
9270
9778
 
9271
- function renderFieldInput(field, formField, disabled) {
9272
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r;
9779
+ function renderFieldInput(field, formField, disabled, errorMessage, setValue) {
9780
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w;
9273
9781
  const value = formField.value;
9274
9782
  const placeholder = (_a = field.ui) == null ? void 0 : _a.placeholder;
9275
9783
  const label = (_b = field.label) != null ? _b : field.key;
9784
+ if (((_c = field.ui) == null ? void 0 : _c.component) === "fileUpload" && field.ui.fileMapping && setValue) {
9785
+ return /* @__PURE__ */ React__default.default.createElement(FileUploadField, { field, formField, disabled, setValue });
9786
+ }
9276
9787
  if (field.target === "secureJsonData" || field.semanticType === "password" || field.semanticType === "token") {
9277
9788
  return /* @__PURE__ */ React__default.default.createElement(SecureFieldInput, { formField, placeholder: placeholder != null ? placeholder : label, disabled, label });
9278
9789
  }
9279
- if (field.valueType === "boolean") {
9280
- return /* @__PURE__ */ React__default.default.createElement(ui.Switch, { value: !!value, onChange: (e) => formField.onChange(e.currentTarget.checked), disabled });
9281
- }
9282
- if (field.valueType === "number") {
9283
- return /* @__PURE__ */ React__default.default.createElement(
9284
- ui.Input,
9285
- {
9286
- ...formField,
9287
- value: value !== void 0 && value !== null ? Number(value) : "",
9288
- type: "number",
9289
- placeholder,
9290
- disabled,
9291
- onChange: (e) => {
9292
- const n = e.currentTarget.valueAsNumber;
9293
- formField.onChange(Number.isNaN(n) ? void 0 : n);
9294
- }
9295
- }
9296
- );
9297
- }
9298
- if (((_c = field.ui) == null ? void 0 : _c.component) === "radio") {
9299
- const options = ((_e = (_d = field.ui) == null ? void 0 : _d.options) != null ? _e : []).map((opt) => ({
9790
+ if (((_d = field.ui) == null ? void 0 : _d.component) === "radio") {
9791
+ const options = ((_f = (_e = field.ui) == null ? void 0 : _e.options) != null ? _f : []).map((opt) => ({
9300
9792
  label: opt.label,
9301
9793
  value: String(opt.value),
9302
9794
  description: opt.description
@@ -9306,13 +9798,20 @@ function renderFieldInput(field, formField, disabled) {
9306
9798
  {
9307
9799
  options,
9308
9800
  value: String(value != null ? value : ""),
9309
- onChange: (v) => formField.onChange(v),
9801
+ onChange: (v) => {
9802
+ if (field.valueType === "number") {
9803
+ const n = Number(v);
9804
+ formField.onChange(Number.isNaN(n) ? v : n);
9805
+ } else {
9806
+ formField.onChange(v);
9807
+ }
9808
+ },
9310
9809
  disabled
9311
9810
  }
9312
9811
  ));
9313
9812
  }
9314
- if (((_f = field.ui) == null ? void 0 : _f.component) === "select") {
9315
- const options = ((_h = (_g = field.ui) == null ? void 0 : _g.options) != null ? _h : []).map((opt) => ({
9813
+ if (((_g = field.ui) == null ? void 0 : _g.component) === "select") {
9814
+ const options = ((_i = (_h = field.ui) == null ? void 0 : _h.options) != null ? _i : []).map((opt) => ({
9316
9815
  label: opt.label,
9317
9816
  value: String(opt.value),
9318
9817
  description: opt.description
@@ -9327,10 +9826,29 @@ function renderFieldInput(field, formField, disabled) {
9327
9826
  }
9328
9827
  );
9329
9828
  }
9829
+ if (field.valueType === "boolean") {
9830
+ return /* @__PURE__ */ React__default.default.createElement(ui.Switch, { value: !!value, onChange: (e) => formField.onChange(e.currentTarget.checked), disabled });
9831
+ }
9832
+ if (field.valueType === "number") {
9833
+ return /* @__PURE__ */ React__default.default.createElement(
9834
+ ui.Input,
9835
+ {
9836
+ ...formField,
9837
+ value: value !== void 0 && value !== null ? Number(value) : "",
9838
+ type: "number",
9839
+ placeholder,
9840
+ disabled,
9841
+ onChange: (e) => {
9842
+ const n = e.currentTarget.valueAsNumber;
9843
+ formField.onChange(Number.isNaN(n) ? void 0 : n);
9844
+ }
9845
+ }
9846
+ );
9847
+ }
9330
9848
  if (field.semanticType === "url") {
9331
9849
  return /* @__PURE__ */ React__default.default.createElement(ui.Input, { ...formField, value: String(value != null ? value : ""), type: "url", placeholder, disabled });
9332
9850
  }
9333
- if (((_i = field.ui) == null ? void 0 : _i.component) === "textarea") {
9851
+ if (((_j = field.ui) == null ? void 0 : _j.component) === "textarea") {
9334
9852
  return /* @__PURE__ */ React__default.default.createElement(
9335
9853
  ui.TextArea,
9336
9854
  {
@@ -9338,27 +9856,50 @@ function renderFieldInput(field, formField, disabled) {
9338
9856
  value: String(value != null ? value : ""),
9339
9857
  placeholder,
9340
9858
  disabled,
9341
- rows: (_k = (_j = field.ui) == null ? void 0 : _j.rows) != null ? _k : 3
9859
+ rows: (_l = (_k = field.ui) == null ? void 0 : _k.rows) != null ? _l : 3
9342
9860
  }
9343
9861
  );
9344
9862
  }
9345
- if (field.valueType === "array" && ((_l = field.item) == null ? void 0 : _l.valueType) === "string") {
9863
+ if (((_m = field.storage) == null ? void 0 : _m.type) === "indexedPair") {
9864
+ const items = Array.isArray(value) ? value : [];
9865
+ const maxItems = (_p = (_o = (_n = field.validations) == null ? void 0 : _n.find((v) => v.type === "itemCount")) == null ? void 0 : _o.max) != null ? _p : 10;
9866
+ const itemLabel = (_r = (_q = field.label) == null ? void 0 : _q.toLowerCase().replace(/s$/, "")) != null ? _r : "header";
9867
+ return /* @__PURE__ */ React__default.default.createElement(
9868
+ IndexedPairEditor,
9869
+ {
9870
+ value: items,
9871
+ onChange: formField.onChange,
9872
+ maxItems,
9873
+ disabled,
9874
+ itemLabel
9875
+ }
9876
+ );
9877
+ }
9878
+ if (field.valueType === "array" && ((_s = field.item) == null ? void 0 : _s.valueType) === "string") {
9346
9879
  return /* @__PURE__ */ React__default.default.createElement(
9347
9880
  StringArrayInput,
9348
9881
  {
9349
9882
  value: Array.isArray(value) ? value : [],
9350
9883
  onChange: formField.onChange,
9351
- placeholder: placeholder != null ? placeholder : `Add ${label.toLowerCase()}\u2026`,
9352
- disabled
9884
+ placeholder,
9885
+ disabled,
9886
+ itemLabel: label.toLowerCase().replace(/s$/, "")
9353
9887
  }
9354
9888
  );
9355
9889
  }
9356
- if (((_m = field.storage) == null ? void 0 : _m.type) === "indexedPair") {
9357
- const items = Array.isArray(value) ? value : [];
9358
- const maxItems = (_p = (_o = (_n = field.validations) == null ? void 0 : _n.find((v) => v.type === "itemCount")) == null ? void 0 : _o.max) != null ? _p : 10;
9359
- return /* @__PURE__ */ React__default.default.createElement(IndexedPairEditor, { value: items, onChange: formField.onChange, maxItems, disabled });
9890
+ if (field.valueType === "array" && ((_t = field.item) == null ? void 0 : _t.valueType) === "object" && ((_u = field.item.fields) == null ? void 0 : _u.length)) {
9891
+ return /* @__PURE__ */ React__default.default.createElement(
9892
+ ObjectArrayEditor,
9893
+ {
9894
+ field,
9895
+ value,
9896
+ onChange: formField.onChange,
9897
+ disabled,
9898
+ errorMessage
9899
+ }
9900
+ );
9360
9901
  }
9361
- if (field.valueType === "object" || field.valueType === "map" || field.valueType === "array" && (((_q = field.item) == null ? void 0 : _q.valueType) === "object" || ((_r = field.item) == null ? void 0 : _r.valueType) === "map")) {
9902
+ if (field.valueType === "object" || field.valueType === "map" || field.valueType === "array" && (((_v = field.item) == null ? void 0 : _v.valueType) === "object" || ((_w = field.item) == null ? void 0 : _w.valueType) === "map")) {
9362
9903
  const count = Array.isArray(value) ? value.length : 0;
9363
9904
  return /* @__PURE__ */ React__default.default.createElement(ComplexFieldNote, { count, label });
9364
9905
  }
@@ -9416,8 +9957,8 @@ const getWizardStyles = (theme) => ({
9416
9957
  color: theme.colors.text.primary
9417
9958
  }),
9418
9959
  stepCount: css.css({
9419
- fontSize: "11px",
9420
- fontWeight: "normal",
9960
+ fontSize: theme.typography.bodySmall.fontSize,
9961
+ fontWeight: theme.typography.fontWeightRegular,
9421
9962
  color: theme.colors.text.secondary
9422
9963
  }),
9423
9964
  navActions: css.css({
@@ -9480,12 +10021,22 @@ const getWizardStyles = (theme) => ({
9480
10021
  minWidth: 0
9481
10022
  }),
9482
10023
  fieldError: css.css({
9483
- fontSize: "11px",
10024
+ fontSize: theme.typography.bodySmall.fontSize,
9484
10025
  color: theme.colors.error.text
9485
10026
  })
9486
10027
  });
9487
10028
 
9488
- function SchemaField({ field, control, errors, disabled, dsUid, watchedValues, fieldById }) {
10029
+ function SchemaField({
10030
+ field,
10031
+ control,
10032
+ errors,
10033
+ disabled,
10034
+ dsUid,
10035
+ watchedValues,
10036
+ fieldById,
10037
+ celContext,
10038
+ setValue
10039
+ }) {
9489
10040
  const styles = ui.useStyles2(getWizardStyles);
9490
10041
  const activeOverride = resolveActiveOverride(field, watchedValues, fieldById);
9491
10042
  const fk = formKey(field);
@@ -9506,7 +10057,7 @@ function SchemaField({ field, control, errors, disabled, dsUid, watchedValues, f
9506
10057
  }
9507
10058
  );
9508
10059
  }
9509
- const required = isFieldRequired(field, watchedValues, fieldById);
10060
+ const required = isFieldRequired(field, watchedValues, fieldById, celContext);
9510
10061
  const validationRules = buildValidationRules(field, required);
9511
10062
  return /* @__PURE__ */ React__default.default.createElement(
9512
10063
  reactHookForm.Controller,
@@ -9521,6 +10072,7 @@ function SchemaField({ field, control, errors, disabled, dsUid, watchedValues, f
9521
10072
  const description = (_c = activeOverride == null ? void 0 : activeOverride.description) != null ? _c : field.description;
9522
10073
  const effectiveField = activeOverride ? {
9523
10074
  ...field,
10075
+ description,
9524
10076
  ui: {
9525
10077
  ...field.ui,
9526
10078
  placeholder: (_e = activeOverride.placeholder) != null ? _e : (_d = field.ui) == null ? void 0 : _d.placeholder
@@ -9528,18 +10080,14 @@ function SchemaField({ field, control, errors, disabled, dsUid, watchedValues, f
9528
10080
  } : field;
9529
10081
  const isReadOnly = !!(activeOverride == null ? void 0 : activeOverride.readOnly);
9530
10082
  const isBool = field.valueType === "boolean";
9531
- return /* @__PURE__ */ React__default.default.createElement("div", { className: isBool ? styles.fieldRowCenter : styles.fieldRow }, /* @__PURE__ */ React__default.default.createElement("div", { className: isBool ? styles.fieldLabelRowCompact : styles.fieldLabelRow }, /* @__PURE__ */ React__default.default.createElement("span", { className: styles.fieldLabel }, label, required && /* @__PURE__ */ React__default.default.createElement("span", { className: styles.fieldRequired }, "*")), description && /* @__PURE__ */ React__default.default.createElement(ui.Tooltip, { content: description }, /* @__PURE__ */ React__default.default.createElement(ui.Icon, { name: "info-circle", size: "xs", className: styles.fieldInfoIcon }))), /* @__PURE__ */ React__default.default.createElement("div", { className: styles.fieldInputCol }, renderFieldInput(effectiveField, formField, disabled || isReadOnly), errorMessage && /* @__PURE__ */ React__default.default.createElement("span", { className: styles.fieldError }, errorMessage)));
10083
+ return /* @__PURE__ */ React__default.default.createElement("div", { className: isBool ? styles.fieldRowCenter : styles.fieldRow }, /* @__PURE__ */ React__default.default.createElement("div", { className: isBool ? styles.fieldLabelRowCompact : styles.fieldLabelRow }, /* @__PURE__ */ React__default.default.createElement("span", { className: styles.fieldLabel }, label, required && /* @__PURE__ */ React__default.default.createElement("span", { className: styles.fieldRequired }, "*")), description && /* @__PURE__ */ React__default.default.createElement(ui.Tooltip, { content: description }, /* @__PURE__ */ React__default.default.createElement(ui.Icon, { name: "info-circle", size: "xs", className: styles.fieldInfoIcon }))), /* @__PURE__ */ React__default.default.createElement("div", { className: styles.fieldInputCol }, renderFieldInput(effectiveField, formField, disabled || isReadOnly, errorMessage, setValue), errorMessage && !parseItemErrors(errorMessage) && /* @__PURE__ */ React__default.default.createElement("span", { className: styles.fieldError }, errorMessage)));
9532
10084
  }
9533
10085
  }
9534
10086
  );
9535
10087
  }
9536
10088
 
9537
- function AuthorizationHeaderField({
9538
- headersFieldKey,
9539
- control,
9540
- disabled,
9541
- watchedValues
9542
- }) {
10089
+ const AuthorizationHeaderField = (props) => {
10090
+ const { headersFieldKey, control, disabled, watchedValues } = props;
9543
10091
  const styles = ui.useStyles2(getWizardStyles);
9544
10092
  const items = React.useMemo(
9545
10093
  () => Array.isArray(watchedValues[headersFieldKey]) ? watchedValues[headersFieldKey] : [],
@@ -9577,7 +10125,7 @@ function AuthorizationHeaderField({
9577
10125
  }
9578
10126
  }
9579
10127
  );
9580
- }
10128
+ };
9581
10129
 
9582
10130
  const getTabStyles = (theme) => ({
9583
10131
  root: css.css({
@@ -9627,7 +10175,7 @@ const getTabStyles = (theme) => ({
9627
10175
  width: 12,
9628
10176
  flexShrink: 0,
9629
10177
  alignSelf: "flex-start",
9630
- paddingTop: 4
10178
+ paddingTop: theme.spacing(0.5)
9631
10179
  }),
9632
10180
  navDot: css.css({
9633
10181
  width: 10,
@@ -9673,7 +10221,7 @@ const getTabStyles = (theme) => ({
9673
10221
  }),
9674
10222
  navLabel: css.css({
9675
10223
  fontSize: theme.typography.body.fontSize,
9676
- color: "rgba(204, 204, 220, 0.65)",
10224
+ color: theme.colors.text.secondary,
9677
10225
  lineHeight: 1.4
9678
10226
  }),
9679
10227
  navLabelActive: css.css({
@@ -9755,8 +10303,8 @@ const getTabStyles = (theme) => ({
9755
10303
  textAlign: "left"
9756
10304
  }),
9757
10305
  sectionBadge: css.css({
9758
- fontSize: "11px",
9759
- fontWeight: "normal",
10306
+ fontSize: theme.typography.bodySmall.fontSize,
10307
+ fontWeight: theme.typography.fontWeightRegular,
9760
10308
  color: theme.colors.text.disabled,
9761
10309
  border: `1px solid ${theme.colors.border.weak}`,
9762
10310
  borderRadius: theme.shape.radius.pill,
@@ -9874,15 +10422,18 @@ function TabLayout({ form, schema, dsUid, dsName, onRetest, healthError, renderA
9874
10422
  handleSubmit,
9875
10423
  errors,
9876
10424
  watchedValues,
10425
+ celContext,
9877
10426
  initializing,
9878
10427
  fetchError,
9879
10428
  submitting,
9880
10429
  submitError,
9881
10430
  readOnly,
9882
10431
  isFieldVisible,
10432
+ isFieldDisabled,
9883
10433
  isGroupValid,
9884
10434
  groupHasData,
9885
- onSubmit
10435
+ onSubmit,
10436
+ setValue
9886
10437
  } = form;
9887
10438
  const displayGroups = React.useMemo(() => resolvedGroups.filter((g) => g.group.id !== "_required"), [resolvedGroups]);
9888
10439
  const [expandedSections, setExpandedSections] = React.useState(() => {
@@ -10010,10 +10561,12 @@ function TabLayout({ form, schema, dsUid, dsName, onRetest, healthError, renderA
10010
10561
  field,
10011
10562
  control,
10012
10563
  errors,
10013
- disabled: allDisabled,
10564
+ disabled: allDisabled || isFieldDisabled(field),
10014
10565
  dsUid,
10015
10566
  watchedValues,
10016
- fieldById
10567
+ fieldById,
10568
+ celContext,
10569
+ setValue
10017
10570
  }
10018
10571
  )), showHeaders && /* @__PURE__ */ React__default.default.createElement(
10019
10572
  AuthorizationHeaderField,
@@ -10127,7 +10680,7 @@ function useDatasourceConfigForm({ schema, dsUid, onSuccess, onSaving }) {
10127
10680
  return;
10128
10681
  }
10129
10682
  for (const { sourceKey, effects } of fieldsWithEffects) {
10130
- const currentVal = watchedValues[sourceKey];
10683
+ const currentVal = getWatchedValue(watchedValues, sourceKey);
10131
10684
  const prevVal = prevEffectValuesRef.current[sourceKey];
10132
10685
  if (currentVal === prevVal) {
10133
10686
  continue;
@@ -10158,6 +10711,7 @@ function useDatasourceConfigForm({ schema, dsUid, onSuccess, onSaving }) {
10158
10711
  return {
10159
10712
  depKey: depField ? formKey(depField) : parsed.field,
10160
10713
  depValue: parsed.value,
10714
+ negate: parsed.negate,
10161
10715
  defaultValue: ov.defaultValue
10162
10716
  };
10163
10717
  }).filter(Boolean);
@@ -10175,42 +10729,70 @@ function useDatasourceConfigForm({ schema, dsUid, onSuccess, onSaving }) {
10175
10729
  }
10176
10730
  for (const { targetKey, fieldDefault, overrides } of fieldsWithOverrideDefaults) {
10177
10731
  for (const ov of overrides) {
10178
- const currentDepVal = String((_a = watchedValues[ov.depKey]) != null ? _a : "");
10732
+ const currentDepVal = String((_a = getWatchedValue(watchedValues, ov.depKey)) != null ? _a : "");
10179
10733
  const trackKey = `${targetKey}::${ov.depKey}`;
10180
10734
  const prevDepVal = prevOverrideDepRef.current[trackKey];
10181
10735
  if (currentDepVal === prevDepVal) {
10182
10736
  continue;
10183
10737
  }
10184
10738
  prevOverrideDepRef.current[trackKey] = currentDepVal;
10185
- if (currentDepVal === ov.depValue) {
10739
+ const active = evaluateDependsOn({ value: ov.depValue, negate: ov.negate }, currentDepVal);
10740
+ const wasActive = prevDepVal !== void 0 && evaluateDependsOn({ value: ov.depValue, negate: ov.negate }, prevDepVal);
10741
+ if (active) {
10186
10742
  setValue(targetKey, ov.defaultValue);
10187
- } else if (prevDepVal === ov.depValue && fieldDefault !== void 0) {
10743
+ } else if (wasActive && fieldDefault !== void 0) {
10188
10744
  setValue(targetKey, fieldDefault);
10189
10745
  }
10190
10746
  }
10191
10747
  }
10192
10748
  }, [watchedValues, fieldsWithOverrideDefaults, initializing, setValue]);
10749
+ const celContext = React.useMemo(() => {
10750
+ const ctx = {};
10751
+ for (const f of fieldById.values()) {
10752
+ const fk = formKey(f);
10753
+ const val = getWatchedValue(watchedValues, fk);
10754
+ if (val !== void 0) {
10755
+ const parts = f.id.split(".");
10756
+ let current = ctx;
10757
+ for (let i = 0; i < parts.length - 1; i++) {
10758
+ if (!(parts[i] in current) || typeof current[parts[i]] !== "object" || current[parts[i]] === null) {
10759
+ current[parts[i]] = {};
10760
+ }
10761
+ current = current[parts[i]];
10762
+ }
10763
+ current[parts[parts.length - 1]] = val;
10764
+ }
10765
+ }
10766
+ return ctx;
10767
+ }, [watchedValues, fieldById]);
10193
10768
  const isFieldVisible = React.useCallback(
10194
10769
  (field) => {
10195
- var _a, _b;
10196
- if (field.kind === "virtual" && !field.ui) {
10197
- return false;
10198
- }
10199
- if ((_a = field.tags) == null ? void 0 : _a.some((t) => t.startsWith("managed-by:"))) {
10200
- return false;
10201
- }
10202
- if (!field.dependsOn) {
10203
- return true;
10204
- }
10205
- const parsed = parseDependsOn(field.dependsOn);
10206
- if (!parsed) {
10207
- return true;
10770
+ function check(f, visited) {
10771
+ var _a;
10772
+ if (f.kind === "virtual" && !f.ui) {
10773
+ return false;
10774
+ }
10775
+ if ((_a = f.tags) == null ? void 0 : _a.some((t) => t.startsWith("managed-by:"))) {
10776
+ return false;
10777
+ }
10778
+ if (!f.dependsOn) {
10779
+ return true;
10780
+ }
10781
+ const refs = extractFieldRefs(f.dependsOn);
10782
+ for (const ref of refs) {
10783
+ const depField = fieldById.get(ref);
10784
+ if (depField && !visited.has(depField.id)) {
10785
+ visited.add(f.id);
10786
+ if (!check(depField, visited)) {
10787
+ return false;
10788
+ }
10789
+ }
10790
+ }
10791
+ return evaluateCelExpression(f.dependsOn, celContext);
10208
10792
  }
10209
- const depField = fieldById.get(parsed.field);
10210
- const depKey = depField ? formKey(depField) : parsed.field;
10211
- return String((_b = watchedValues[depKey]) != null ? _b : "") === parsed.value;
10793
+ return check(field, /* @__PURE__ */ new Set());
10212
10794
  },
10213
- [watchedValues, fieldById]
10795
+ [celContext, fieldById]
10214
10796
  );
10215
10797
  const onSubmit = React.useCallback(
10216
10798
  async (data) => {
@@ -10250,8 +10832,8 @@ function useDatasourceConfigForm({ schema, dsUid, onSuccess, onSaving }) {
10250
10832
  if (errors[formKey(field)]) {
10251
10833
  return false;
10252
10834
  }
10253
- if (isFieldRequired(field, watchedValues, fieldById)) {
10254
- const val = watchedValues[formKey(field)];
10835
+ if (isFieldRequired(field, watchedValues, fieldById, celContext)) {
10836
+ const val = getWatchedValue(watchedValues, formKey(field));
10255
10837
  if (val === SECURE_FIELD_CONFIGURED) {
10256
10838
  continue;
10257
10839
  }
@@ -10262,12 +10844,21 @@ function useDatasourceConfigForm({ schema, dsUid, onSuccess, onSaving }) {
10262
10844
  }
10263
10845
  return true;
10264
10846
  },
10265
- [errors, watchedValues, fieldById, isFieldVisible]
10847
+ [errors, watchedValues, fieldById, celContext, isFieldVisible]
10848
+ );
10849
+ const isFieldDisabled = React.useCallback(
10850
+ (field) => {
10851
+ if (!field.disabledWhen) {
10852
+ return false;
10853
+ }
10854
+ return evaluateCelExpression(field.disabledWhen, celContext);
10855
+ },
10856
+ [celContext]
10266
10857
  );
10267
10858
  const groupHasData = React.useCallback(
10268
10859
  (group) => {
10269
10860
  for (const field of group.fields) {
10270
- const val = watchedValues[formKey(field)];
10861
+ const val = getWatchedValue(watchedValues, formKey(field));
10271
10862
  if (val === void 0 || val === null || val === "" || val === false) {
10272
10863
  continue;
10273
10864
  }
@@ -10291,6 +10882,7 @@ function useDatasourceConfigForm({ schema, dsUid, onSuccess, onSaving }) {
10291
10882
  trigger,
10292
10883
  errors,
10293
10884
  watchedValues,
10885
+ celContext,
10294
10886
  // State
10295
10887
  initializing,
10296
10888
  fetchError,
@@ -10299,9 +10891,11 @@ function useDatasourceConfigForm({ schema, dsUid, onSuccess, onSaving }) {
10299
10891
  readOnly,
10300
10892
  // Callbacks
10301
10893
  isFieldVisible,
10894
+ isFieldDisabled,
10302
10895
  isGroupValid,
10303
10896
  groupHasData,
10304
- onSubmit
10897
+ onSubmit,
10898
+ setValue
10305
10899
  };
10306
10900
  }
10307
10901
 
@@ -10348,13 +10942,16 @@ function WizardLayout({ form, schema, dsUid, dsName, onRetest, healthError, rend
10348
10942
  trigger,
10349
10943
  errors,
10350
10944
  watchedValues,
10945
+ celContext,
10351
10946
  initializing,
10352
10947
  fetchError,
10353
10948
  submitting,
10354
10949
  submitError,
10355
10950
  readOnly,
10356
10951
  isFieldVisible,
10357
- onSubmit
10952
+ isFieldDisabled,
10953
+ onSubmit,
10954
+ setValue
10358
10955
  } = form;
10359
10956
  const arrowSteps = React.useMemo(() => {
10360
10957
  const requiredGroup = resolvedGroups.find((g) => g.group.id === "_required");
@@ -10400,8 +10997,8 @@ function WizardLayout({ form, schema, dsUid, dsName, onRetest, healthError, rend
10400
10997
  if (errors[formKey(field)]) {
10401
10998
  return false;
10402
10999
  }
10403
- if (isFieldRequired(field, watchedValues, fieldById)) {
10404
- const val = watchedValues[formKey(field)];
11000
+ if (isFieldRequired(field, watchedValues, fieldById, celContext)) {
11001
+ const val = getWatchedValue(watchedValues, formKey(field));
10405
11002
  if (val === SECURE_FIELD_CONFIGURED) {
10406
11003
  continue;
10407
11004
  }
@@ -10411,7 +11008,7 @@ function WizardLayout({ form, schema, dsUid, dsName, onRetest, healthError, rend
10411
11008
  }
10412
11009
  }
10413
11010
  return true;
10414
- }, [currentResolved, errors, visibleFieldsForStep, watchedValues, fieldById]);
11011
+ }, [currentResolved, errors, visibleFieldsForStep, watchedValues, fieldById, celContext]);
10415
11012
  const goNext = React.useCallback(async () => {
10416
11013
  if (!currentResolved) {
10417
11014
  return;
@@ -10505,10 +11102,12 @@ function WizardLayout({ form, schema, dsUid, dsName, onRetest, healthError, rend
10505
11102
  field,
10506
11103
  control,
10507
11104
  errors,
10508
- disabled: allDisabled,
11105
+ disabled: allDisabled || isFieldDisabled(field),
10509
11106
  dsUid,
10510
11107
  watchedValues,
10511
- fieldById
11108
+ fieldById,
11109
+ celContext,
11110
+ setValue
10512
11111
  }
10513
11112
  )), (currentResolved.group.id === "_required" || currentResolved.group.id === "auth") && httpHeadersField && /* @__PURE__ */ React__default.default.createElement(
10514
11113
  AuthorizationHeaderField,
@@ -10521,6 +11120,155 @@ function WizardLayout({ form, schema, dsUid, dsName, onRetest, healthError, rend
10521
11120
  ), submitError && /* @__PURE__ */ React__default.default.createElement(ui.Alert, { severity: "error", title: "Error" }, submitError), /* @__PURE__ */ React__default.default.createElement("div", { className: styles.buttons }, readOnly ? /* @__PURE__ */ React__default.default.createElement(ui.Button, { variant: "primary", size: "sm", icon: "sync", onClick: onRetest, type: "button" }, "Test") : /* @__PURE__ */ React__default.default.createElement(ui.Button, { variant: "primary", size: "sm", disabled: submitting || !currentGroupValid, type: "submit" }, submitting ? "Saving..." : "Save & Test"), healthError && (renderActions == null ? void 0 : renderActions({ dsUid, dsName, dsType: schema.pluginType, healthError })))));
10522
11121
  }
10523
11122
 
11123
+ var __defProp$2 = Object.defineProperty;
11124
+ var __defNormalProp$2 = (obj, key, value) => key in obj ? __defProp$2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
11125
+ var __publicField$2 = (obj, key, value) => __defNormalProp$2(obj, key + "" , value);
11126
+ class DatasourceErrorBoundary extends React.Component {
11127
+ constructor() {
11128
+ super(...arguments);
11129
+ __publicField$2(this, "state", { error: null });
11130
+ }
11131
+ static getDerivedStateFromError(error) {
11132
+ return { error };
11133
+ }
11134
+ componentDidCatch(error, info) {
11135
+ console.error("[DatasourceConfigWizard] Caught error:", error, info.componentStack);
11136
+ }
11137
+ render() {
11138
+ if (this.state.error) {
11139
+ return /* @__PURE__ */ React__default.default.createElement(ui.Alert, { severity: "warning", title: "Configuration wizard unavailable" }, "Could not load the configuration wizard", this.props.dsName ? ` for ${this.props.dsName}` : "", ". Use the Settings link to configure this datasource manually.");
11140
+ }
11141
+ return this.props.children;
11142
+ }
11143
+ }
11144
+
11145
+ const MAX_CONCURRENCY = 5;
11146
+ function useHealthChecks() {
11147
+ const [healthMap, setHealthMap] = React.useState({});
11148
+ const queueRef = React.useRef([]);
11149
+ const activeRef = React.useRef(0);
11150
+ const mountedRef = React.useRef(true);
11151
+ const everQueuedRef = React.useRef(/* @__PURE__ */ new Set());
11152
+ const checkOne = React.useCallback(async (uid) => {
11153
+ if (!mountedRef.current) {
11154
+ return;
11155
+ }
11156
+ setHealthMap((prev) => ({ ...prev, [uid]: { state: "checking" } }));
11157
+ try {
11158
+ const result = await runtime.getBackendSrv().get(
11159
+ `/api/datasources/uid/${uid}/health`,
11160
+ void 0,
11161
+ void 0,
11162
+ { showErrorAlert: false }
11163
+ );
11164
+ if (!mountedRef.current) {
11165
+ return;
11166
+ }
11167
+ setHealthMap((prev) => {
11168
+ var _a;
11169
+ return {
11170
+ ...prev,
11171
+ [uid]: { state: "done", status: (_a = result.status) != null ? _a : "OK", message: result.message }
11172
+ };
11173
+ });
11174
+ } catch (error) {
11175
+ if (!mountedRef.current) {
11176
+ return;
11177
+ }
11178
+ let status = "ERROR";
11179
+ let message = "";
11180
+ if (error && typeof error === "object" && "data" in error) {
11181
+ const data = error.data;
11182
+ if (data == null ? void 0 : data.status) {
11183
+ status = data.status;
11184
+ }
11185
+ if (data == null ? void 0 : data.message) {
11186
+ message = data.message;
11187
+ }
11188
+ }
11189
+ if (!message) {
11190
+ message = error instanceof Error ? error.message : String(error);
11191
+ }
11192
+ setHealthMap((prev) => ({
11193
+ ...prev,
11194
+ [uid]: { state: "done", status, message }
11195
+ }));
11196
+ }
11197
+ }, []);
11198
+ const processQueue = React.useCallback(() => {
11199
+ while (activeRef.current < MAX_CONCURRENCY && queueRef.current.length > 0) {
11200
+ const uid = queueRef.current.shift();
11201
+ activeRef.current++;
11202
+ checkOne(uid).finally(() => {
11203
+ activeRef.current--;
11204
+ processQueue();
11205
+ });
11206
+ }
11207
+ }, [checkOne]);
11208
+ const checkUids = React.useCallback(
11209
+ (uids) => {
11210
+ const toCheck = [];
11211
+ for (const uid of uids) {
11212
+ if (everQueuedRef.current.has(uid)) {
11213
+ continue;
11214
+ }
11215
+ everQueuedRef.current.add(uid);
11216
+ toCheck.push(uid);
11217
+ }
11218
+ if (toCheck.length === 0) {
11219
+ return;
11220
+ }
11221
+ setHealthMap((prev) => {
11222
+ const next = { ...prev };
11223
+ for (const uid of toCheck) {
11224
+ next[uid] = { state: "pending" };
11225
+ }
11226
+ return next;
11227
+ });
11228
+ queueRef.current.push(...toCheck);
11229
+ processQueue();
11230
+ },
11231
+ [processQueue]
11232
+ );
11233
+ const retry = React.useCallback(
11234
+ (uid) => {
11235
+ everQueuedRef.current.delete(uid);
11236
+ everQueuedRef.current.add(uid);
11237
+ setHealthMap((prev) => ({ ...prev, [uid]: { state: "pending" } }));
11238
+ queueRef.current.push(uid);
11239
+ processQueue();
11240
+ },
11241
+ [processQueue]
11242
+ );
11243
+ return { healthMap, checkUids, retry };
11244
+ }
11245
+
11246
+ let pluginNameCache = null;
11247
+ function buildPluginNameCache() {
11248
+ var _a;
11249
+ if (pluginNameCache) {
11250
+ return pluginNameCache;
11251
+ }
11252
+ const map = /* @__PURE__ */ new Map();
11253
+ try {
11254
+ const list = runtime.getDataSourceSrv().getList();
11255
+ for (const ds of list) {
11256
+ if (((_a = ds.meta) == null ? void 0 : _a.name) && ds.type && !map.has(ds.type)) {
11257
+ map.set(ds.type, ds.meta.name);
11258
+ }
11259
+ }
11260
+ } catch (ex) {
11261
+ console.error(ex);
11262
+ }
11263
+ pluginNameCache = map;
11264
+ return map;
11265
+ }
11266
+ function resolvePluginName(pluginType) {
11267
+ var _a;
11268
+ const cache = buildPluginNameCache();
11269
+ return (_a = cache.get(pluginType)) != null ? _a : pluginType;
11270
+ }
11271
+
10524
11272
  var __defProp$1 = Object.defineProperty;
10525
11273
  var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
10526
11274
  var __publicField$1 = (obj, key, value) => __defNormalProp$1(obj, typeof key !== "symbol" ? key + "" : key, value);
@@ -12026,6 +12774,21 @@ function generateTroubleshootingFields(schema) {
12026
12774
  return result;
12027
12775
  }
12028
12776
 
12777
+ const ROOT_CONFIG_FIELDS = [
12778
+ "name",
12779
+ "type",
12780
+ "id",
12781
+ "uid",
12782
+ "access",
12783
+ "url",
12784
+ "basicAuth",
12785
+ "basicAuthUser",
12786
+ "user",
12787
+ "isDefault",
12788
+ "database",
12789
+ "withCredentials"
12790
+ ];
12791
+
12029
12792
  function yamlIndent(depth) {
12030
12793
  return " ".repeat(depth);
12031
12794
  }
@@ -12378,7 +13141,83 @@ function datasourceToProvisioningYaml(ds, schema) {
12378
13141
  lines.push(" # mySecret: xxxxxx");
12379
13142
  return lines.join("\n");
12380
13143
  }
13144
+ function getYamlRenderOptions(ds) {
13145
+ var _a, _b, _c;
13146
+ return {
13147
+ jsonDataKeys: Object.keys((_a = ds.jsonData) != null ? _a : {}).sort(),
13148
+ secureKeys: [
13149
+ .../* @__PURE__ */ new Set([
13150
+ ...Object.keys((_b = ds.secureJsonData) != null ? _b : {}),
13151
+ ...Object.keys((_c = ds.secureJsonFields) != null ? _c : {})
13152
+ ])
13153
+ ].sort()
13154
+ };
13155
+ }
13156
+ const configToYaml = (ds, options = {}) => {
13157
+ var _a, _b, _c;
13158
+ const { jsonDataKeys, secureKeys } = {
13159
+ ...getYamlRenderOptions(ds),
13160
+ ...options
13161
+ };
13162
+ const root = {};
13163
+ for (const key of ROOT_CONFIG_FIELDS) {
13164
+ root[key] = (_a = ds[key]) != null ? _a : "";
13165
+ }
13166
+ const jsonData = (_b = ds.jsonData) != null ? _b : {};
13167
+ if (jsonDataKeys.length > 0) {
13168
+ const jsonDataYaml = {};
13169
+ for (const key of jsonDataKeys) {
13170
+ jsonDataYaml[key] = (_c = jsonData[key]) != null ? _c : "";
13171
+ }
13172
+ root.jsonData = jsonDataYaml;
13173
+ }
13174
+ if (secureKeys.length > 0) {
13175
+ const secureJsonData = {};
13176
+ for (const key of secureKeys) {
13177
+ secureJsonData[key] = "********";
13178
+ }
13179
+ root.secureJsonData = secureJsonData;
13180
+ }
13181
+ return yaml__default.default.dump(root, { lineWidth: -1, sortKeys: false, noRefs: true }).trimEnd();
13182
+ };
13183
+ const formatYamlDiff = (existing, body) => {
13184
+ var _a, _b, _c, _d, _e, _f;
13185
+ const updated = { ...existing, ...body };
13186
+ const existingJD = (_a = existing.jsonData) != null ? _a : {};
13187
+ const updatedJD = (_b = updated.jsonData) != null ? _b : {};
13188
+ const jsonDataKeys = [.../* @__PURE__ */ new Set([...Object.keys(existingJD), ...Object.keys(updatedJD)])].sort();
13189
+ const secureKeys = [
13190
+ .../* @__PURE__ */ new Set([
13191
+ ...Object.keys((_c = existing.secureJsonData) != null ? _c : {}),
13192
+ ...Object.keys((_d = existing.secureJsonFields) != null ? _d : {}),
13193
+ ...Object.keys((_e = updated.secureJsonData) != null ? _e : {}),
13194
+ ...Object.keys((_f = updated.secureJsonFields) != null ? _f : {})
13195
+ ])
13196
+ ].sort();
13197
+ const currentYaml = configToYaml(existing, { jsonDataKeys, secureKeys });
13198
+ const updatedYaml = configToYaml(updated, { jsonDataKeys, secureKeys });
13199
+ const oldLines = currentYaml.split("\n");
13200
+ const newLines = updatedYaml.split("\n");
13201
+ const maxLen = Math.max(oldLines.length, newLines.length);
13202
+ const diffLines = [];
13203
+ for (let i = 0; i < maxLen; i++) {
13204
+ const oldLine = oldLines[i];
13205
+ const newLine = newLines[i];
13206
+ if (oldLine === newLine) {
13207
+ diffLines.push(` ${oldLine}`);
13208
+ continue;
13209
+ }
13210
+ if (oldLine !== void 0) {
13211
+ diffLines.push(`-${oldLine}`);
13212
+ }
13213
+ if (newLine !== void 0) {
13214
+ diffLines.push(`+${newLine}`);
13215
+ }
13216
+ }
13217
+ return "```diff\n" + diffLines.join("\n") + "\n```";
13218
+ };
12381
13219
 
13220
+ exports.getConfigSchema = schemas.getConfigSchema;
12382
13221
  exports.AccessoryButton = AccessoryButton;
12383
13222
  exports.AdvancedHttpSettings = AdvancedHttpSettings;
12384
13223
  exports.Auth = Auth;
@@ -12399,6 +13238,7 @@ exports.DataSourceDescription = DataSourceDescription;
12399
13238
  exports.DataSourcePicker = DataSourcePicker;
12400
13239
  exports.DatasetSelector = DatasetSelector;
12401
13240
  exports.DatasourceConfigWizard = DatasourceConfigWizard;
13241
+ exports.DatasourceErrorBoundary = DatasourceErrorBoundary;
12402
13242
  exports.DatePicker = DatePicker;
12403
13243
  exports.DatePickerWithInput = DatePickerWithInput;
12404
13244
  exports.DebounceInput = DebounceInput;
@@ -12450,24 +13290,32 @@ exports.TableSelector = TableSelector;
12450
13290
  exports.TokenType = TokenType;
12451
13291
  exports.buildDatasourceConfigPayload = buildDatasourceConfigPayload;
12452
13292
  exports.computeVirtualFieldValues = computeVirtualFieldValues;
13293
+ exports.configToYaml = configToYaml;
12453
13294
  exports.convertLegacyAuthProps = convertLegacyAuthProps;
12454
13295
  exports.datasourceToProvisioningYaml = datasourceToProvisioningYaml;
12455
13296
  exports.evaluateComputedRead = evaluateComputedRead;
13297
+ exports.evaluateDependsOn = evaluateDependsOn;
12456
13298
  exports.expandIndexedPair = expandIndexedPair;
12457
13299
  exports.fetchExistingValues = fetchExistingValues;
13300
+ exports.findActiveSecureOverride = findActiveSecureOverride;
12458
13301
  exports.flattenIndexedPair = flattenIndexedPair;
12459
13302
  exports.formKey = formKey;
12460
13303
  exports.formatDate = formatDate;
13304
+ exports.formatYamlDiff = formatYamlDiff;
12461
13305
  exports.generateLLMHint = generateLLMHint;
12462
13306
  exports.generateTroubleshootingFields = generateTroubleshootingFields;
12463
13307
  exports.getStandardSQLCompletionProvider = getStandardSQLCompletionProvider;
13308
+ exports.getWatchedValue = getWatchedValue;
12464
13309
  exports.grafanaStandardSQLLanguage = language;
12465
13310
  exports.grafanaStandardSQLLanguageConf = conf;
12466
13311
  exports.parseDependsOn = parseDependsOn;
12467
13312
  exports.resolveActiveOverride = resolveActiveOverride;
12468
13313
  exports.resolveGroups = resolveGroups;
13314
+ exports.resolvePluginName = resolvePluginName;
12469
13315
  exports.resolveRequiredFieldsGroup = resolveRequiredFieldsGroup;
13316
+ exports.resolveSecureKeyTemplate = resolveSecureKeyTemplate;
12470
13317
  exports.submitDatasourceConfig = submitDatasourceConfig;
12471
13318
  exports.toOption = toOption;
12472
13319
  exports.toProvisioningYaml = toProvisioningYaml;
13320
+ exports.useHealthChecks = useHealthChecks;
12473
13321
  //# sourceMappingURL=index.cjs.map