@grafana/plugin-ui 0.14.1-dsconfig.b962e11 → 0.14.1-dsconfig.ced809d

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 (214) hide show
  1. package/dist/cjs/index.cjs +1073 -317
  2. package/dist/cjs/index.cjs.map +1 -1
  3. package/dist/cjs/index.d.cts +135 -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/schemaRegistry.js +139 -0
  198. package/dist/esm/datasource/schema/schemaRegistry.js.map +1 -0
  199. package/dist/esm/index.d.ts +135 -5
  200. package/dist/esm/index.js +6 -2
  201. package/dist/esm/index.js.map +1 -1
  202. package/dist/esm/schemas.d.ts +373 -0
  203. package/dist/esm/schemas.js +2 -0
  204. package/dist/esm/schemas.js.map +1 -0
  205. package/dist/esm/test-utils.d.ts +23 -23
  206. package/package.json +23 -6
  207. package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/AuthorizationHeaderField.js.map +0 -1
  208. package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/ComplexFieldNote.js.map +0 -1
  209. package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/IndexedPairEditor.js.map +0 -1
  210. package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/PdcFieldNote.js.map +0 -1
  211. package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/SecureFieldInput.js.map +0 -1
  212. package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/StringArrayInput.js +0 -84
  213. package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/StringArrayInput.js.map +0 -1
  214. package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/useDatasourceConfigForm.js.map +0 -1
@@ -1,8 +1,9 @@
1
1
  import { useState, useMemo, useEffect, useRef, useCallback } from 'react';
2
2
  import { useForm } from 'react-hook-form';
3
- import { resolveGroups, resolveRequiredFieldsGroup, formKey, computeVirtualFieldValues, parseDependsOn } from '../../../datasource/schema/config.js';
4
- import { fetchExistingValues, submitDatasourceConfig, SECURE_FIELD_CONFIGURED } from '../../../datasource/schema/datasource.js';
5
- import { evaluateEffectCondition, isFieldRequired } from './fieldUtils.js';
3
+ import { resolveGroups, resolveRequiredFieldsGroup, formKey, computeVirtualFieldValues, getWatchedValue, parseDependsOn, evaluateDependsOn } from '../../../../datasource/schema/config.js';
4
+ import { evaluateCelExpression, extractFieldRefs } from '../../../../datasource/schema/cel.js';
5
+ import { fetchExistingValues, submitDatasourceConfig, SECURE_FIELD_CONFIGURED } from '../../../../datasource/schema/datasource.js';
6
+ import { evaluateEffectCondition, isFieldRequired } from '../fieldUtils.js';
6
7
 
7
8
  function useDatasourceConfigForm({ schema, dsUid, onSuccess, onSaving }) {
8
9
  const [submitting, setSubmitting] = useState(false);
@@ -102,7 +103,7 @@ function useDatasourceConfigForm({ schema, dsUid, onSuccess, onSaving }) {
102
103
  return;
103
104
  }
104
105
  for (const { sourceKey, effects } of fieldsWithEffects) {
105
- const currentVal = watchedValues[sourceKey];
106
+ const currentVal = getWatchedValue(watchedValues, sourceKey);
106
107
  const prevVal = prevEffectValuesRef.current[sourceKey];
107
108
  if (currentVal === prevVal) {
108
109
  continue;
@@ -133,6 +134,7 @@ function useDatasourceConfigForm({ schema, dsUid, onSuccess, onSaving }) {
133
134
  return {
134
135
  depKey: depField ? formKey(depField) : parsed.field,
135
136
  depValue: parsed.value,
137
+ negate: parsed.negate,
136
138
  defaultValue: ov.defaultValue
137
139
  };
138
140
  }).filter(Boolean);
@@ -150,42 +152,70 @@ function useDatasourceConfigForm({ schema, dsUid, onSuccess, onSaving }) {
150
152
  }
151
153
  for (const { targetKey, fieldDefault, overrides } of fieldsWithOverrideDefaults) {
152
154
  for (const ov of overrides) {
153
- const currentDepVal = String((_a = watchedValues[ov.depKey]) != null ? _a : "");
155
+ const currentDepVal = String((_a = getWatchedValue(watchedValues, ov.depKey)) != null ? _a : "");
154
156
  const trackKey = `${targetKey}::${ov.depKey}`;
155
157
  const prevDepVal = prevOverrideDepRef.current[trackKey];
156
158
  if (currentDepVal === prevDepVal) {
157
159
  continue;
158
160
  }
159
161
  prevOverrideDepRef.current[trackKey] = currentDepVal;
160
- if (currentDepVal === ov.depValue) {
162
+ const active = evaluateDependsOn({ value: ov.depValue, negate: ov.negate }, currentDepVal);
163
+ const wasActive = prevDepVal !== void 0 && evaluateDependsOn({ value: ov.depValue, negate: ov.negate }, prevDepVal);
164
+ if (active) {
161
165
  setValue(targetKey, ov.defaultValue);
162
- } else if (prevDepVal === ov.depValue && fieldDefault !== void 0) {
166
+ } else if (wasActive && fieldDefault !== void 0) {
163
167
  setValue(targetKey, fieldDefault);
164
168
  }
165
169
  }
166
170
  }
167
171
  }, [watchedValues, fieldsWithOverrideDefaults, initializing, setValue]);
172
+ const celContext = useMemo(() => {
173
+ const ctx = {};
174
+ for (const f of fieldById.values()) {
175
+ const fk = formKey(f);
176
+ const val = getWatchedValue(watchedValues, fk);
177
+ if (val !== void 0) {
178
+ const parts = f.id.split(".");
179
+ let current = ctx;
180
+ for (let i = 0; i < parts.length - 1; i++) {
181
+ if (!(parts[i] in current) || typeof current[parts[i]] !== "object" || current[parts[i]] === null) {
182
+ current[parts[i]] = {};
183
+ }
184
+ current = current[parts[i]];
185
+ }
186
+ current[parts[parts.length - 1]] = val;
187
+ }
188
+ }
189
+ return ctx;
190
+ }, [watchedValues, fieldById]);
168
191
  const isFieldVisible = useCallback(
169
192
  (field) => {
170
- var _a, _b;
171
- if (field.kind === "virtual" && !field.ui) {
172
- return false;
173
- }
174
- if ((_a = field.tags) == null ? void 0 : _a.some((t) => t.startsWith("managed-by:"))) {
175
- return false;
176
- }
177
- if (!field.dependsOn) {
178
- return true;
179
- }
180
- const parsed = parseDependsOn(field.dependsOn);
181
- if (!parsed) {
182
- return true;
193
+ function check(f, visited) {
194
+ var _a;
195
+ if (f.kind === "virtual" && !f.ui) {
196
+ return false;
197
+ }
198
+ if ((_a = f.tags) == null ? void 0 : _a.some((t) => t.startsWith("managed-by:"))) {
199
+ return false;
200
+ }
201
+ if (!f.dependsOn) {
202
+ return true;
203
+ }
204
+ const refs = extractFieldRefs(f.dependsOn);
205
+ for (const ref of refs) {
206
+ const depField = fieldById.get(ref);
207
+ if (depField && !visited.has(depField.id)) {
208
+ visited.add(f.id);
209
+ if (!check(depField, visited)) {
210
+ return false;
211
+ }
212
+ }
213
+ }
214
+ return evaluateCelExpression(f.dependsOn, celContext);
183
215
  }
184
- const depField = fieldById.get(parsed.field);
185
- const depKey = depField ? formKey(depField) : parsed.field;
186
- return String((_b = watchedValues[depKey]) != null ? _b : "") === parsed.value;
216
+ return check(field, /* @__PURE__ */ new Set());
187
217
  },
188
- [watchedValues, fieldById]
218
+ [celContext, fieldById]
189
219
  );
190
220
  const onSubmit = useCallback(
191
221
  async (data) => {
@@ -225,8 +255,8 @@ function useDatasourceConfigForm({ schema, dsUid, onSuccess, onSaving }) {
225
255
  if (errors[formKey(field)]) {
226
256
  return false;
227
257
  }
228
- if (isFieldRequired(field, watchedValues, fieldById)) {
229
- const val = watchedValues[formKey(field)];
258
+ if (isFieldRequired(field, watchedValues, fieldById, celContext)) {
259
+ const val = getWatchedValue(watchedValues, formKey(field));
230
260
  if (val === SECURE_FIELD_CONFIGURED) {
231
261
  continue;
232
262
  }
@@ -237,12 +267,21 @@ function useDatasourceConfigForm({ schema, dsUid, onSuccess, onSaving }) {
237
267
  }
238
268
  return true;
239
269
  },
240
- [errors, watchedValues, fieldById, isFieldVisible]
270
+ [errors, watchedValues, fieldById, celContext, isFieldVisible]
271
+ );
272
+ const isFieldDisabled = useCallback(
273
+ (field) => {
274
+ if (!field.disabledWhen) {
275
+ return false;
276
+ }
277
+ return evaluateCelExpression(field.disabledWhen, celContext);
278
+ },
279
+ [celContext]
241
280
  );
242
281
  const groupHasData = useCallback(
243
282
  (group) => {
244
283
  for (const field of group.fields) {
245
- const val = watchedValues[formKey(field)];
284
+ const val = getWatchedValue(watchedValues, formKey(field));
246
285
  if (val === void 0 || val === null || val === "" || val === false) {
247
286
  continue;
248
287
  }
@@ -266,6 +305,7 @@ function useDatasourceConfigForm({ schema, dsUid, onSuccess, onSaving }) {
266
305
  trigger,
267
306
  errors,
268
307
  watchedValues,
308
+ celContext,
269
309
  // State
270
310
  initializing,
271
311
  fetchError,
@@ -274,9 +314,11 @@ function useDatasourceConfigForm({ schema, dsUid, onSuccess, onSaving }) {
274
314
  readOnly,
275
315
  // Callbacks
276
316
  isFieldVisible,
317
+ isFieldDisabled,
277
318
  isGroupValid,
278
319
  groupHasData,
279
- onSubmit
320
+ onSubmit,
321
+ setValue
280
322
  };
281
323
  }
282
324
 
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useDatasourceConfigForm.js","sources":["../../../../../../src/components/ConfigEditor/DatasourceConfigWizard/hooks/useDatasourceConfigForm.ts"],"sourcesContent":["import { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport { useForm } from 'react-hook-form';\nimport type { ConfigField, ConfigGroup, DatasourceConfigSchema } from '../../../../datasource/schema/schema';\nimport {\n resolveGroups,\n resolveRequiredFieldsGroup,\n parseDependsOn,\n evaluateDependsOn,\n computeVirtualFieldValues,\n formKey,\n getWatchedValue,\n} from '../../../../datasource/schema/config';\nimport { extractFieldRefs, evaluateCelExpression } from '../../../../datasource/schema/cel';\nimport {\n SECURE_FIELD_CONFIGURED,\n fetchExistingValues,\n submitDatasourceConfig,\n} from '../../../../datasource/schema/datasource';\nimport type { FormValues } from '../../../../datasource/schema/types';\nimport { evaluateEffectCondition, isFieldRequired } from '../fieldUtils';\n\nexport type DatasourceConfigFormOptions = {\n schema: DatasourceConfigSchema;\n dsUid: string;\n onSuccess: (status: string, message?: string) => void;\n onSaving?: (saving: boolean) => void;\n};\n\nexport type ResolvedGroup = { group: ConfigGroup; fields: ConfigField[] };\n\nexport function useDatasourceConfigForm({ schema, dsUid, onSuccess, onSaving }: DatasourceConfigFormOptions) {\n const [submitting, setSubmitting] = useState(false);\n const [submitError, setSubmitError] = useState<string | null>(null);\n const [initializing, setInitializing] = useState(true);\n const [fetchError, setFetchError] = useState<string | null>(null);\n const [detectedReadOnly, setDetectedReadOnly] = useState(false);\n const readOnly = detectedReadOnly;\n\n const resolvedGroups: ResolvedGroup[] = useMemo(() => {\n const groups = resolveGroups(schema);\n const requiredGroup = resolveRequiredFieldsGroup(schema);\n if (!requiredGroup) {\n return groups;\n }\n return [requiredGroup, ...groups];\n }, [schema]);\n\n const fieldById = useMemo(() => {\n const m = new Map<string, ConfigField>();\n for (const f of schema.fields) {\n m.set(f.id, f);\n }\n return m;\n }, [schema.fields]);\n\n const httpHeadersField = useMemo(\n () => schema.fields.find((f) => f.key === 'httpHeaders' && f.storage?.type === 'indexedPair') ?? null,\n [schema.fields]\n );\n\n const allStorageFields = useMemo(\n () => schema.fields.filter((f) => f.kind !== 'virtual' && !f.isItemField && f.target),\n [schema.fields]\n );\n\n const {\n control,\n handleSubmit,\n watch,\n reset,\n trigger,\n setValue,\n formState: { errors },\n } = useForm<FormValues>({ mode: 'onChange' });\n\n const fieldsWithEffects = useMemo(() => {\n const result: Array<{\n sourceKey: string;\n effects: Array<{ when: string; targets: Array<{ key: string; value: unknown }> }>;\n }> = [];\n for (const field of schema.fields) {\n if (!field.effects || field.effects.length === 0) {\n continue;\n }\n const mapped = field.effects.map((eff) => ({\n when: eff.when,\n targets: Object.entries(eff.set).map(([targetId, val]) => {\n const targetField = fieldById.get(targetId);\n return { key: targetField ? formKey(targetField) : targetId, value: val };\n }),\n }));\n result.push({ sourceKey: formKey(field), effects: mapped });\n }\n return result;\n }, [schema.fields, fieldById]);\n\n // Load existing values on mount\n useEffect(() => {\n let cancelled = false;\n fetchExistingValues(dsUid, allStorageFields).then((result) => {\n if (cancelled) {\n return;\n }\n if (result.error) {\n setFetchError(result.error);\n setInitializing(false);\n return;\n }\n if (result.readOnly) {\n setDetectedReadOnly(true);\n }\n const defaults: FormValues = {};\n for (const field of allStorageFields) {\n if (field.defaultValue !== undefined) {\n defaults[formKey(field)] = field.defaultValue;\n }\n }\n const merged = { ...defaults, ...result.values };\n const virtualValues = computeVirtualFieldValues(schema, merged);\n reset({ ...merged, ...virtualValues });\n setInitializing(false);\n });\n return () => {\n cancelled = true;\n };\n }, [dsUid, allStorageFields, schema, reset]);\n\n const watchedValues = watch();\n\n // Apply field effects\n const prevEffectValuesRef = useRef<Record<string, unknown>>({});\n useEffect(() => {\n if (initializing) {\n return;\n }\n for (const { sourceKey, effects } of fieldsWithEffects) {\n const currentVal = getWatchedValue(watchedValues, sourceKey);\n const prevVal = prevEffectValuesRef.current[sourceKey];\n if (currentVal === prevVal) {\n continue;\n }\n prevEffectValuesRef.current[sourceKey] = currentVal;\n for (const eff of effects) {\n if (evaluateEffectCondition(eff.when, currentVal)) {\n for (const { key, value } of eff.targets) {\n setValue(key, value);\n }\n break;\n }\n }\n }\n }, [watchedValues, fieldsWithEffects, initializing, setValue]);\n\n // Override defaults\n const fieldsWithOverrideDefaults = useMemo(() => {\n const result: Array<{\n targetKey: string;\n fieldDefault: unknown;\n overrides: Array<{ depKey: string; depValue: string; negate: boolean; defaultValue: unknown }>;\n }> = [];\n for (const field of schema.fields) {\n if (!field.overrides || field.overrides.length === 0) {\n continue;\n }\n const ovs = field.overrides\n .filter((ov) => ov.defaultValue !== undefined)\n .map((ov) => {\n const parsed = parseDependsOn(ov.when);\n if (!parsed) {\n return null;\n }\n const depField = fieldById.get(parsed.field);\n return {\n depKey: depField ? formKey(depField) : parsed.field,\n depValue: parsed.value,\n negate: parsed.negate,\n defaultValue: ov.defaultValue,\n };\n })\n .filter(Boolean) as Array<{ depKey: string; depValue: string; negate: boolean; defaultValue: unknown }>;\n if (ovs.length > 0) {\n result.push({ targetKey: formKey(field), fieldDefault: field.defaultValue, overrides: ovs });\n }\n }\n return result;\n }, [schema.fields, fieldById]);\n\n const prevOverrideDepRef = useRef<Record<string, string>>({});\n useEffect(() => {\n if (initializing) {\n return;\n }\n for (const { targetKey, fieldDefault, overrides } of fieldsWithOverrideDefaults) {\n for (const ov of overrides) {\n const currentDepVal = String(getWatchedValue(watchedValues, ov.depKey) ?? '');\n const trackKey = `${targetKey}::${ov.depKey}`;\n const prevDepVal = prevOverrideDepRef.current[trackKey];\n if (currentDepVal === prevDepVal) {\n continue;\n }\n prevOverrideDepRef.current[trackKey] = currentDepVal;\n const active = evaluateDependsOn({ value: ov.depValue, negate: ov.negate }, currentDepVal);\n const wasActive =\n prevDepVal !== undefined && evaluateDependsOn({ value: ov.depValue, negate: ov.negate }, prevDepVal);\n if (active) {\n setValue(targetKey, ov.defaultValue);\n } else if (wasActive && fieldDefault !== undefined) {\n setValue(targetKey, fieldDefault);\n }\n }\n }\n }, [watchedValues, fieldsWithOverrideDefaults, initializing, setValue]);\n\n // Build a CEL-compatible nested context from flat watched values + field ID mappings.\n // Field IDs like \"jsonData.auth_method\" become { jsonData: { auth_method: value } }.\n const celContext = useMemo(() => {\n const ctx: Record<string, unknown> = {};\n for (const f of fieldById.values()) {\n const fk = formKey(f);\n const val = getWatchedValue(watchedValues, fk);\n if (val !== undefined) {\n // Set by field ID path (e.g. \"jsonData.oauth2.oauth2_type\")\n const parts = f.id.split('.');\n let current = ctx as Record<string, unknown>;\n for (let i = 0; i < parts.length - 1; i++) {\n if (!(parts[i] in current) || typeof current[parts[i]] !== 'object' || current[parts[i]] === null) {\n current[parts[i]] = {};\n }\n current = current[parts[i]] as Record<string, unknown>;\n }\n current[parts[parts.length - 1]] = val;\n }\n }\n return ctx;\n }, [watchedValues, fieldById]);\n\n const isFieldVisible = useCallback(\n (field: ConfigField): boolean => {\n // Inner recursive helper with a visited set to guard against circular deps.\n function check(f: ConfigField, visited: Set<string>): boolean {\n if (f.kind === 'virtual' && !f.ui) {\n return false;\n }\n if (f.tags?.some((t) => t.startsWith('managed-by:'))) {\n return false;\n }\n if (!f.dependsOn) {\n return true;\n }\n\n // Transitive visibility: all referenced dependency fields must themselves be visible.\n const refs = extractFieldRefs(f.dependsOn);\n for (const ref of refs) {\n const depField = fieldById.get(ref);\n if (depField && !visited.has(depField.id)) {\n visited.add(f.id);\n if (!check(depField, visited)) {\n return false;\n }\n }\n }\n\n // Evaluate the full CEL expression\n return evaluateCelExpression(f.dependsOn, celContext);\n }\n return check(field, new Set<string>());\n },\n [celContext, fieldById]\n );\n\n const onSubmit = useCallback(\n async (data: FormValues) => {\n setSubmitting(true);\n setSubmitError(null);\n onSaving?.(true);\n const minDelay = new Promise((r) => setTimeout(r, 2000));\n\n try {\n await submitDatasourceConfig(dsUid, data, allStorageFields, isFieldVisible);\n const [refreshed] = await Promise.all([fetchExistingValues(dsUid, allStorageFields), minDelay]);\n const defaults: FormValues = {};\n for (const field of allStorageFields) {\n if (field.defaultValue !== undefined) {\n defaults[formKey(field)] = field.defaultValue;\n }\n }\n const merged = { ...defaults, ...refreshed.values };\n const virtualValues = computeVirtualFieldValues(schema, merged);\n reset({ ...merged, ...virtualValues });\n onSuccess('UPDATED', 'Configuration saved.');\n } catch (err: unknown) {\n await minDelay;\n setSubmitError(err instanceof Error ? err.message : 'Failed to update datasource');\n } finally {\n setSubmitting(false);\n onSaving?.(false);\n }\n },\n [dsUid, allStorageFields, isFieldVisible, schema, reset, onSuccess, onSaving]\n );\n\n /** Check if a group has any visible required fields that are empty. */\n const isGroupValid = useCallback(\n (group: ResolvedGroup): boolean => {\n for (const field of group.fields) {\n if (!isFieldVisible(field)) {\n continue;\n }\n if (errors[formKey(field)]) {\n return false;\n }\n if (isFieldRequired(field, watchedValues, fieldById, celContext)) {\n const val = getWatchedValue(watchedValues, formKey(field));\n if (val === SECURE_FIELD_CONFIGURED) {\n continue;\n }\n if (val === undefined || val === null || val === '') {\n return false;\n }\n }\n }\n return true;\n },\n [errors, watchedValues, fieldById, celContext, isFieldVisible]\n );\n\n const isFieldDisabled = useCallback(\n (field: ConfigField): boolean => {\n if (!field.disabledWhen) {\n return false;\n }\n return evaluateCelExpression(field.disabledWhen, celContext);\n },\n [celContext]\n );\n\n /** Check if a group has any fields with non-default/non-empty values. */\n const groupHasData = useCallback(\n (group: ResolvedGroup): boolean => {\n for (const field of group.fields) {\n const val = getWatchedValue(watchedValues, formKey(field));\n if (val === undefined || val === null || val === '' || val === false) {\n continue;\n }\n if (val === field.defaultValue) {\n continue;\n }\n return true;\n }\n return false;\n },\n [watchedValues]\n );\n\n return {\n // Schema\n resolvedGroups,\n fieldById,\n httpHeadersField,\n // Form\n control,\n handleSubmit,\n trigger,\n errors,\n watchedValues,\n celContext,\n // State\n initializing,\n fetchError,\n submitting,\n submitError,\n readOnly,\n // Callbacks\n isFieldVisible,\n isFieldDisabled,\n isGroupValid,\n groupHasData,\n onSubmit,\n setValue,\n };\n}\n"],"names":["_a"],"mappings":"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"}
@@ -0,0 +1,106 @@
1
+ import { useState, useRef, useCallback } from 'react';
2
+ import { getBackendSrv } from '@grafana/runtime';
3
+
4
+ const MAX_CONCURRENCY = 5;
5
+ function useHealthChecks() {
6
+ const [healthMap, setHealthMap] = useState({});
7
+ const queueRef = useRef([]);
8
+ const activeRef = useRef(0);
9
+ const mountedRef = useRef(true);
10
+ const everQueuedRef = useRef(/* @__PURE__ */ new Set());
11
+ const checkOne = useCallback(async (uid) => {
12
+ if (!mountedRef.current) {
13
+ return;
14
+ }
15
+ setHealthMap((prev) => ({ ...prev, [uid]: { state: "checking" } }));
16
+ try {
17
+ const result = await getBackendSrv().get(
18
+ `/api/datasources/uid/${uid}/health`,
19
+ void 0,
20
+ void 0,
21
+ { showErrorAlert: false }
22
+ );
23
+ if (!mountedRef.current) {
24
+ return;
25
+ }
26
+ setHealthMap((prev) => {
27
+ var _a;
28
+ return {
29
+ ...prev,
30
+ [uid]: { state: "done", status: (_a = result.status) != null ? _a : "OK", message: result.message }
31
+ };
32
+ });
33
+ } catch (error) {
34
+ if (!mountedRef.current) {
35
+ return;
36
+ }
37
+ let status = "ERROR";
38
+ let message = "";
39
+ if (error && typeof error === "object" && "data" in error) {
40
+ const data = error.data;
41
+ if (data == null ? void 0 : data.status) {
42
+ status = data.status;
43
+ }
44
+ if (data == null ? void 0 : data.message) {
45
+ message = data.message;
46
+ }
47
+ }
48
+ if (!message) {
49
+ message = error instanceof Error ? error.message : String(error);
50
+ }
51
+ setHealthMap((prev) => ({
52
+ ...prev,
53
+ [uid]: { state: "done", status, message }
54
+ }));
55
+ }
56
+ }, []);
57
+ const processQueue = useCallback(() => {
58
+ while (activeRef.current < MAX_CONCURRENCY && queueRef.current.length > 0) {
59
+ const uid = queueRef.current.shift();
60
+ activeRef.current++;
61
+ checkOne(uid).finally(() => {
62
+ activeRef.current--;
63
+ processQueue();
64
+ });
65
+ }
66
+ }, [checkOne]);
67
+ const checkUids = useCallback(
68
+ (uids) => {
69
+ const toCheck = [];
70
+ for (const uid of uids) {
71
+ if (everQueuedRef.current.has(uid)) {
72
+ continue;
73
+ }
74
+ everQueuedRef.current.add(uid);
75
+ toCheck.push(uid);
76
+ }
77
+ if (toCheck.length === 0) {
78
+ return;
79
+ }
80
+ setHealthMap((prev) => {
81
+ const next = { ...prev };
82
+ for (const uid of toCheck) {
83
+ next[uid] = { state: "pending" };
84
+ }
85
+ return next;
86
+ });
87
+ queueRef.current.push(...toCheck);
88
+ processQueue();
89
+ },
90
+ [processQueue]
91
+ );
92
+ const retry = useCallback(
93
+ (uid) => {
94
+ everQueuedRef.current.delete(uid);
95
+ everQueuedRef.current.add(uid);
96
+ setHealthMap((prev) => ({ ...prev, [uid]: { state: "pending" } }));
97
+ queueRef.current.push(uid);
98
+ processQueue();
99
+ },
100
+ [processQueue]
101
+ );
102
+ return { healthMap, checkUids, retry };
103
+ }
104
+
105
+ export { useHealthChecks };
106
+ //# sourceMappingURL=useHealthChecks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useHealthChecks.js","sources":["../../../../../../src/components/ConfigEditor/DatasourceConfigWizard/hooks/useHealthChecks.ts"],"sourcesContent":["import { useCallback, useRef, useState } from 'react';\nimport { getBackendSrv } from '@grafana/runtime';\nimport type { TestDataSourceResponse } from '@grafana/data';\n\nconst MAX_CONCURRENCY = 5;\n\nexport type HealthState = 'pending' | 'checking' | 'done';\n\nexport interface DatasourceHealth {\n state: HealthState;\n status?: string;\n message?: string;\n}\n\n/**\n * Health check hook — on-demand only.\n * Call `checkUids(uids)` to trigger checks for specific UIDs.\n * Call `retry(uid)` to force re-check a single UID.\n * UIDs that have already been checked (or are in-flight) are automatically skipped.\n */\nexport function useHealthChecks() {\n const [healthMap, setHealthMap] = useState<Record<string, DatasourceHealth>>({});\n const queueRef = useRef<string[]>([]);\n const activeRef = useRef(0);\n const mountedRef = useRef(true);\n // Permanent set of UIDs that have ever been queued — prevents re-checking on re-render.\n // Only `retry()` removes from this set to allow explicit re-check.\n const everQueuedRef = useRef(new Set<string>());\n\n const checkOne = useCallback(async (uid: string) => {\n if (!mountedRef.current) {\n return;\n }\n setHealthMap((prev) => ({ ...prev, [uid]: { state: 'checking' } }));\n\n try {\n const result: TestDataSourceResponse = await getBackendSrv().get(\n `/api/datasources/uid/${uid}/health`,\n undefined,\n undefined,\n { showErrorAlert: false }\n );\n if (!mountedRef.current) {\n return;\n }\n setHealthMap((prev) => ({\n ...prev,\n [uid]: { state: 'done', status: result.status ?? 'OK', message: result.message },\n }));\n } catch (error: unknown) {\n if (!mountedRef.current) {\n return;\n }\n let status = 'ERROR';\n let message = '';\n if (error && typeof error === 'object' && 'data' in error) {\n const data = (error as { data?: { status?: string; message?: string } }).data;\n if (data?.status) {\n status = data.status;\n }\n if (data?.message) {\n message = data.message;\n }\n }\n if (!message) {\n message = error instanceof Error ? error.message : String(error);\n }\n setHealthMap((prev) => ({\n ...prev,\n [uid]: { state: 'done', status, message },\n }));\n }\n }, []);\n\n const processQueue = useCallback(() => {\n while (activeRef.current < MAX_CONCURRENCY && queueRef.current.length > 0) {\n const uid = queueRef.current.shift()!;\n activeRef.current++;\n checkOne(uid).finally(() => {\n activeRef.current--;\n processQueue();\n });\n }\n }, [checkOne]);\n\n /**\n * Queue health checks for a batch of UIDs.\n * Skips UIDs that have ever been queued before (idempotent — safe to call repeatedly).\n */\n const checkUids = useCallback(\n (uids: string[]) => {\n const toCheck: string[] = [];\n for (const uid of uids) {\n if (everQueuedRef.current.has(uid)) {\n continue;\n }\n everQueuedRef.current.add(uid);\n toCheck.push(uid);\n }\n if (toCheck.length === 0) {\n return;\n }\n setHealthMap((prev) => {\n const next = { ...prev };\n for (const uid of toCheck) {\n next[uid] = { state: 'pending' };\n }\n return next;\n });\n queueRef.current.push(...toCheck);\n processQueue();\n },\n [processQueue]\n );\n\n /**\n * Force re-check a single UID (e.g. after wizard save).\n * Clears the \"ever queued\" flag so checkUids won't block it.\n */\n const retry = useCallback(\n (uid: string) => {\n // Remove from everQueued so it can be re-queued\n everQueuedRef.current.delete(uid);\n // Re-add immediately\n everQueuedRef.current.add(uid);\n setHealthMap((prev) => ({ ...prev, [uid]: { state: 'pending' } }));\n queueRef.current.push(uid);\n processQueue();\n },\n [processQueue]\n );\n\n return { healthMap, checkUids, retry };\n}\n"],"names":[],"mappings":"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"}
@@ -2,14 +2,12 @@ import React, { useMemo } from 'react';
2
2
  import { Controller } from 'react-hook-form';
3
3
  import { useStyles2, Tooltip, Icon } from '@grafana/ui';
4
4
  import { IndexedPairEditor } from './IndexedPairEditor.js';
5
- import { getWizardStyles } from './wizardStyles.js';
5
+ import { getWizardStyles } from '../wizardStyles.js';
6
+ import '@grafana/runtime';
7
+ import '@marcbachmann/cel-js';
6
8
 
7
- function AuthorizationHeaderField({
8
- headersFieldKey,
9
- control,
10
- disabled,
11
- watchedValues
12
- }) {
9
+ const AuthorizationHeaderField = (props) => {
10
+ const { headersFieldKey, control, disabled, watchedValues } = props;
13
11
  const styles = useStyles2(getWizardStyles);
14
12
  const items = useMemo(
15
13
  () => Array.isArray(watchedValues[headersFieldKey]) ? watchedValues[headersFieldKey] : [],
@@ -47,7 +45,7 @@ function AuthorizationHeaderField({
47
45
  }
48
46
  }
49
47
  );
50
- }
48
+ };
51
49
 
52
50
  export { AuthorizationHeaderField };
53
51
  //# sourceMappingURL=AuthorizationHeaderField.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AuthorizationHeaderField.js","sources":["../../../../../../src/components/ConfigEditor/DatasourceConfigWizard/inputs/AuthorizationHeaderField.tsx"],"sourcesContent":["import React, { useMemo } from 'react';\nimport { type useForm, Controller } from 'react-hook-form';\nimport { useStyles2, Icon, Tooltip } from '@grafana/ui';\nimport { IndexedPairEditor } from './IndexedPairEditor';\nimport { getWizardStyles } from '../wizardStyles';\nimport { type IndexedPairItem } from '../../../../datasource/schema/datasource';\nimport { type FormValues } from '../../../../datasource/schema/types';\n\ntype Props = {\n headersFieldKey: string;\n control: ReturnType<typeof useForm<FormValues>>['control'];\n disabled?: boolean;\n watchedValues: Record<string, unknown>;\n};\n\nexport const AuthorizationHeaderField = (props: Props) => {\n const { headersFieldKey, control, disabled, watchedValues } = props;\n const styles = useStyles2(getWizardStyles);\n const items = useMemo(\n () => (Array.isArray(watchedValues[headersFieldKey]) ? watchedValues[headersFieldKey] : []) as IndexedPairItem[],\n [watchedValues, headersFieldKey]\n );\n\n const authEntries = useMemo(() => {\n const entries: Array<{ item: IndexedPairItem; originalIdx: number }> = [];\n for (let i = 0; i < items.length; i++) {\n if (items[i].name.toLowerCase() === 'authorization') {\n entries.push({ item: items[i], originalIdx: i });\n }\n }\n return entries;\n }, [items]);\n\n if (authEntries.length === 0) {\n return null;\n }\n\n const authItems = authEntries.map((e) => e.item);\n\n return (\n <Controller\n name={headersFieldKey}\n control={control}\n render={({ field: formField }) => {\n const handleChange = (updatedAuthItems: IndexedPairItem[]) => {\n const updated = [...items];\n for (let i = 0; i < authEntries.length; i++) {\n if (i < updatedAuthItems.length) {\n updated[authEntries[i].originalIdx] = updatedAuthItems[i];\n }\n }\n formField.onChange(updated);\n };\n\n return (\n <div className={styles.fieldRow}>\n <div className={styles.fieldLabelRow}>\n <span className={styles.fieldLabel}>Custom HTTP Headers</span>\n <Tooltip content=\"Authorization HTTP header(s) sent with every request.\">\n <Icon name=\"info-circle\" size=\"xs\" className={styles.fieldInfoIcon} />\n </Tooltip>\n </div>\n <div className={styles.fieldInputCol}>\n <IndexedPairEditor value={authItems} onChange={handleChange} disabled={disabled} hideControls />\n </div>\n </div>\n );\n }}\n />\n );\n};\n"],"names":[],"mappings":";;;;;;;;AAeO,MAAM,wBAAA,GAA2B,CAAC,KAAA,KAAiB;AACxD,EAAA,MAAM,EAAE,eAAA,EAAiB,OAAA,EAAS,QAAA,EAAU,eAAc,GAAI,KAAA;AAC9D,EAAA,MAAM,MAAA,GAAS,WAAW,eAAe,CAAA;AACzC,EAAA,MAAM,KAAA,GAAQ,OAAA;AAAA,IACZ,MAAO,KAAA,CAAM,OAAA,CAAQ,aAAA,CAAc,eAAe,CAAC,CAAA,GAAI,aAAA,CAAc,eAAe,CAAA,GAAI,EAAC;AAAA,IACzF,CAAC,eAAe,eAAe;AAAA,GACjC;AAEA,EAAA,MAAM,WAAA,GAAc,QAAQ,MAAM;AAChC,IAAA,MAAM,UAAiE,EAAC;AACxE,IAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,KAAA,CAAM,QAAQ,CAAA,EAAA,EAAK;AACrC,MAAA,IAAI,MAAM,CAAC,CAAA,CAAE,IAAA,CAAK,WAAA,OAAkB,eAAA,EAAiB;AACnD,QAAA,OAAA,CAAQ,IAAA,CAAK,EAAE,IAAA,EAAM,KAAA,CAAM,CAAC,CAAA,EAAG,WAAA,EAAa,GAAG,CAAA;AAAA,MACjD;AAAA,IACF;AACA,IAAA,OAAO,OAAA;AAAA,EACT,CAAA,EAAG,CAAC,KAAK,CAAC,CAAA;AAEV,EAAA,IAAI,WAAA,CAAY,WAAW,CAAA,EAAG;AAC5B,IAAA,OAAO,IAAA;AAAA,EACT;AAEA,EAAA,MAAM,YAAY,WAAA,CAAY,GAAA,CAAI,CAAC,CAAA,KAAM,EAAE,IAAI,CAAA;AAE/C,EAAA,uBACE,KAAA,CAAA,aAAA;AAAA,IAAC,UAAA;AAAA,IAAA;AAAA,MACC,IAAA,EAAM,eAAA;AAAA,MACN,OAAA;AAAA,MACA,MAAA,EAAQ,CAAC,EAAE,KAAA,EAAO,WAAU,KAAM;AAChC,QAAA,MAAM,YAAA,GAAe,CAAC,gBAAA,KAAwC;AAC5D,UAAA,MAAM,OAAA,GAAU,CAAC,GAAG,KAAK,CAAA;AACzB,UAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,WAAA,CAAY,QAAQ,CAAA,EAAA,EAAK;AAC3C,YAAA,IAAI,CAAA,GAAI,iBAAiB,MAAA,EAAQ;AAC/B,cAAA,OAAA,CAAQ,YAAY,CAAC,CAAA,CAAE,WAAW,CAAA,GAAI,iBAAiB,CAAC,CAAA;AAAA,YAC1D;AAAA,UACF;AACA,UAAA,SAAA,CAAU,SAAS,OAAO,CAAA;AAAA,QAC5B,CAAA;AAEA,QAAA,uBACE,KAAA,CAAA,aAAA,CAAC,SAAI,SAAA,EAAW,MAAA,CAAO,4BACrB,KAAA,CAAA,aAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAW,MAAA,CAAO,aAAA,EAAA,kBACrB,KAAA,CAAA,aAAA,CAAC,UAAK,SAAA,EAAW,MAAA,CAAO,cAAY,qBAAmB,CAAA,sCACtD,OAAA,EAAA,EAAQ,OAAA,EAAQ,uDAAA,EAAA,kBACf,KAAA,CAAA,aAAA,CAAC,IAAA,EAAA,EAAK,IAAA,EAAK,eAAc,IAAA,EAAK,IAAA,EAAK,WAAW,MAAA,CAAO,aAAA,EAAe,CACtE,CACF,CAAA,kBACA,KAAA,CAAA,aAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAW,MAAA,CAAO,iCACrB,KAAA,CAAA,aAAA,CAAC,iBAAA,EAAA,EAAkB,OAAO,SAAA,EAAW,QAAA,EAAU,cAAc,QAAA,EAAoB,YAAA,EAAY,IAAA,EAAC,CAChG,CACF,CAAA;AAAA,MAEJ;AAAA;AAAA,GACF;AAEJ;;;;"}
@@ -1,12 +1,14 @@
1
1
  import React from 'react';
2
2
  import { css } from '@emotion/css';
3
+ import '@grafana/data';
3
4
  import { useStyles2, Icon } from '@grafana/ui';
4
5
 
5
- function ComplexFieldNote({ count, label }) {
6
- const styles = useStyles2(getStyles$c);
6
+ const ComplexFieldNote = (props) => {
7
+ const { count, label } = props;
8
+ const styles = useStyles2(getStyles$g);
7
9
  return /* @__PURE__ */ React.createElement("div", { className: styles.note }, /* @__PURE__ */ React.createElement(Icon, { name: "info-circle", size: "xs" }), /* @__PURE__ */ React.createElement("span", null, count > 0 ? `${count} ${label.toLowerCase()} configured.` : `No ${label.toLowerCase()} configured.`, " Configure in Grafana UI."));
8
- }
9
- const getStyles$c = (theme) => ({
10
+ };
11
+ const getStyles$g = (theme) => ({
10
12
  note: css({
11
13
  display: "inline-flex",
12
14
  alignItems: "center",
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ComplexFieldNote.js","sources":["../../../../../../src/components/ConfigEditor/DatasourceConfigWizard/inputs/ComplexFieldNote.tsx"],"sourcesContent":["import React from 'react';\nimport { css } from '@emotion/css';\nimport { type GrafanaTheme2 } from '@grafana/data';\nimport { useStyles2, Icon } from '@grafana/ui';\n\ntype Props = { count: number; label: string };\n\nexport const ComplexFieldNote = (props: Props) => {\n const { count, label } = props;\n const styles = useStyles2(getStyles);\n return (\n <div className={styles.note}>\n <Icon name=\"info-circle\" size=\"xs\" />\n <span>\n {count > 0 ? `${count} ${label.toLowerCase()} configured.` : `No ${label.toLowerCase()} configured.`} Configure\n in Grafana UI.\n </span>\n </div>\n );\n};\n\nconst getStyles = (theme: GrafanaTheme2) => ({\n note: css({\n display: 'inline-flex',\n alignItems: 'center',\n gap: theme.spacing(0.5),\n padding: `${theme.spacing(0.5)} ${theme.spacing(0.75)}`,\n fontSize: theme.typography.bodySmall.fontSize,\n color: theme.colors.text.secondary,\n backgroundColor: theme.colors.background.secondary,\n borderRadius: theme.shape.radius.default,\n border: `1px solid ${theme.colors.border.weak}`,\n }),\n});\n"],"names":["getStyles"],"mappings":";;;;;AAOO,MAAM,gBAAA,GAAmB,CAAC,KAAA,KAAiB;AAChD,EAAA,MAAM,EAAE,KAAA,EAAO,KAAA,EAAM,GAAI,KAAA;AACzB,EAAA,MAAM,MAAA,GAAS,WAAWA,WAAS,CAAA;AACnC,EAAA,uBACE,KAAA,CAAA,aAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAW,MAAA,CAAO,IAAA,EAAA,kBACrB,KAAA,CAAA,aAAA,CAAC,IAAA,EAAA,EAAK,IAAA,EAAK,aAAA,EAAc,IAAA,EAAK,IAAA,EAAK,CAAA,kBACnC,KAAA,CAAA,aAAA,CAAC,MAAA,EAAA,IAAA,EACE,KAAA,GAAQ,CAAA,GAAI,CAAA,EAAG,KAAK,CAAA,CAAA,EAAI,KAAA,CAAM,WAAA,EAAa,CAAA,YAAA,CAAA,GAAiB,CAAA,GAAA,EAAM,KAAA,CAAM,WAAA,EAAa,CAAA,YAAA,CAAA,EAAe,2BAEvG,CACF,CAAA;AAEJ;AAEA,MAAMA,WAAA,GAAY,CAAC,KAAA,MAA0B;AAAA,EAC3C,MAAM,GAAA,CAAI;AAAA,IACR,OAAA,EAAS,aAAA;AAAA,IACT,UAAA,EAAY,QAAA;AAAA,IACZ,GAAA,EAAK,KAAA,CAAM,OAAA,CAAQ,GAAG,CAAA;AAAA,IACtB,OAAA,EAAS,CAAA,EAAG,KAAA,CAAM,OAAA,CAAQ,GAAG,CAAC,CAAA,CAAA,EAAI,KAAA,CAAM,OAAA,CAAQ,IAAI,CAAC,CAAA,CAAA;AAAA,IACrD,QAAA,EAAU,KAAA,CAAM,UAAA,CAAW,SAAA,CAAU,QAAA;AAAA,IACrC,KAAA,EAAO,KAAA,CAAM,MAAA,CAAO,IAAA,CAAK,SAAA;AAAA,IACzB,eAAA,EAAiB,KAAA,CAAM,MAAA,CAAO,UAAA,CAAW,SAAA;AAAA,IACzC,YAAA,EAAc,KAAA,CAAM,KAAA,CAAM,MAAA,CAAO,OAAA;AAAA,IACjC,MAAA,EAAQ,CAAA,UAAA,EAAa,KAAA,CAAM,MAAA,CAAO,OAAO,IAAI,CAAA;AAAA,GAC9C;AACH,CAAA,CAAA;;;;"}
@@ -0,0 +1,106 @@
1
+ import React, { useState, useCallback } from 'react';
2
+ import { useTheme2, Button, TextArea, FileDropzone } from '@grafana/ui';
3
+ import { css } from '@emotion/css';
4
+
5
+ function FileUploadField(props) {
6
+ var _a, _b, _c, _d, _e, _f, _g;
7
+ const { field, formField, disabled, setValue } = props;
8
+ const [mode, setModeLocal] = useState("upload");
9
+ const [error, setError] = useState(null);
10
+ const theme = useTheme2();
11
+ const mapping = (_a = field.ui) == null ? void 0 : _a.fileMapping;
12
+ const accept = (_c = (_b = field.ui) == null ? void 0 : _b.accept) != null ? _c : [".json"];
13
+ const setMode = useCallback(
14
+ (next) => {
15
+ setModeLocal(next);
16
+ formField.onChange(next);
17
+ },
18
+ [formField]
19
+ );
20
+ const processJson = useCallback(
21
+ (text) => {
22
+ const fileMapping = mapping != null ? mapping : {};
23
+ try {
24
+ const parsed = JSON.parse(text);
25
+ if (typeof parsed !== "object" || parsed === null) {
26
+ setError("Invalid JSON object");
27
+ return;
28
+ }
29
+ const requiredKeys = Object.keys(fileMapping);
30
+ const missingKeys = requiredKeys.filter((k) => parsed[k] === void 0);
31
+ if (missingKeys.length > 0) {
32
+ setError(`Missing keys: ${missingKeys.join(", ")}`);
33
+ return;
34
+ }
35
+ for (const [jsonKey, targetFieldId] of Object.entries(fileMapping)) {
36
+ if (parsed[jsonKey] !== void 0) {
37
+ const parts = targetFieldId.split(".");
38
+ const fk = parts.length === 2 ? parts[1] : targetFieldId;
39
+ setValue(fk, parsed[jsonKey]);
40
+ }
41
+ }
42
+ setError(null);
43
+ setModeLocal("manual");
44
+ formField.onChange("manual");
45
+ } catch (e) {
46
+ setError("Invalid JSON");
47
+ }
48
+ },
49
+ [mapping, setValue, formField]
50
+ );
51
+ const styles = getStyles$f(theme);
52
+ if (mode === "manual") {
53
+ return /* @__PURE__ */ React.createElement("div", { className: styles.buttonRow }, /* @__PURE__ */ React.createElement(Button, { type: "button", fill: "outline", size: "sm", onClick: () => setMode("paste"), disabled }, "Paste JWT Token"), /* @__PURE__ */ React.createElement("span", { className: styles.separator }, "or"), /* @__PURE__ */ React.createElement(Button, { type: "button", fill: "outline", size: "sm", onClick: () => setMode("upload"), disabled }, "Upload JWT Token"));
54
+ }
55
+ if (mode === "paste") {
56
+ return /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement(
57
+ TextArea,
58
+ {
59
+ placeholder: (_e = (_d = field.ui) == null ? void 0 : _d.placeholder) != null ? _e : "Paste Google JWT token here",
60
+ rows: (_g = (_f = field.ui) == null ? void 0 : _f.rows) != null ? _g : 10,
61
+ onBlur: (e) => {
62
+ const val = e.currentTarget.value;
63
+ if (val.trim()) {
64
+ processJson(val);
65
+ }
66
+ },
67
+ disabled
68
+ }
69
+ ), /* @__PURE__ */ React.createElement("div", { className: styles.buttonRow }, /* @__PURE__ */ React.createElement(Button, { type: "button", fill: "outline", size: "sm", onClick: () => setMode("upload"), disabled }, "Upload JWT Token"), /* @__PURE__ */ React.createElement("span", { className: styles.separator }, "or"), /* @__PURE__ */ React.createElement(Button, { type: "button", fill: "outline", size: "sm", onClick: () => setMode("manual"), disabled }, "Fill In JWT Token manually")), error && /* @__PURE__ */ React.createElement("span", { className: styles.error }, error));
70
+ }
71
+ return /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement(
72
+ FileDropzone,
73
+ {
74
+ options: { multiple: false, accept: accept.join(",") },
75
+ readAs: "readAsText",
76
+ onLoad: (result) => {
77
+ if (typeof result === "string") {
78
+ processJson(result);
79
+ }
80
+ }
81
+ }
82
+ ), /* @__PURE__ */ React.createElement("div", { className: styles.buttonRow }, /* @__PURE__ */ React.createElement(Button, { type: "button", fill: "outline", size: "sm", onClick: () => setMode("paste"), disabled }, "Paste JWT Token"), /* @__PURE__ */ React.createElement("span", { className: styles.separator }, "or"), /* @__PURE__ */ React.createElement(Button, { type: "button", fill: "outline", size: "sm", onClick: () => setMode("manual"), disabled }, "Fill In JWT Token manually")), error && /* @__PURE__ */ React.createElement("span", { className: styles.error }, error));
83
+ }
84
+ function getStyles$f(theme) {
85
+ return {
86
+ buttonRow: css({
87
+ marginTop: theme.spacing(1),
88
+ display: "flex",
89
+ alignItems: "center",
90
+ gap: theme.spacing(0.5)
91
+ }),
92
+ separator: css({
93
+ padding: `0 ${theme.spacing(0.5)}`,
94
+ color: theme.colors.text.secondary
95
+ }),
96
+ error: css({
97
+ color: theme.colors.error.text,
98
+ fontSize: theme.typography.bodySmall.fontSize,
99
+ marginTop: theme.spacing(0.5),
100
+ display: "block"
101
+ })
102
+ };
103
+ }
104
+
105
+ export { FileUploadField };
106
+ //# sourceMappingURL=FileUploadField.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FileUploadField.js","sources":["../../../../../../src/components/ConfigEditor/DatasourceConfigWizard/inputs/FileUploadField.tsx"],"sourcesContent":["import React, { useState, useCallback } from 'react';\nimport { FileDropzone, TextArea, Button, useTheme2 } from '@grafana/ui';\nimport { css } from '@emotion/css';\nimport type { ConfigField } from '../../../../datasource/schema/schema';\nimport type { FormFieldRef } from './SecureFieldInput';\n\ntype EntryMode = 'upload' | 'paste' | 'manual';\n\ntype Props = {\n field: ConfigField;\n formField: FormFieldRef;\n disabled?: boolean;\n setValue: (name: string, value: unknown) => void;\n};\n\nexport function FileUploadField(props: Props) {\n const { field, formField, disabled, setValue } = props;\n const [mode, setModeLocal] = useState<EntryMode>('upload');\n const [error, setError] = useState<string | null>(null);\n const theme = useTheme2();\n const mapping = field.ui?.fileMapping;\n const accept = field.ui?.accept ?? ['.json'];\n\n // Write mode into this field's own Controller value so dependsOn can observe it.\n // e.g. other fields use dependsOn: \"virtual.jwtUpload == 'manual'\" to show/hide.\n const setMode = useCallback(\n (next: EntryMode) => {\n setModeLocal(next);\n formField.onChange(next);\n },\n [formField]\n );\n\n const processJson = useCallback(\n (text: string) => {\n const fileMapping = mapping ?? {};\n try {\n const parsed = JSON.parse(text);\n if (typeof parsed !== 'object' || parsed === null) {\n setError('Invalid JSON object');\n return;\n }\n const requiredKeys = Object.keys(fileMapping);\n const missingKeys = requiredKeys.filter((k) => parsed[k] === undefined);\n if (missingKeys.length > 0) {\n setError(`Missing keys: ${missingKeys.join(', ')}`);\n return;\n }\n for (const [jsonKey, targetFieldId] of Object.entries(fileMapping)) {\n if (parsed[jsonKey] !== undefined) {\n const parts = targetFieldId.split('.');\n const fk = parts.length === 2 ? parts[1] : targetFieldId;\n setValue(fk, parsed[jsonKey]);\n }\n }\n setError(null);\n setModeLocal('manual');\n formField.onChange('manual');\n } catch {\n setError('Invalid JSON');\n }\n },\n [mapping, setValue, formField]\n );\n\n const styles = getStyles(theme);\n\n // Manual mode: just show toggle buttons, fields below are rendered by schema\n if (mode === 'manual') {\n return (\n <div className={styles.buttonRow}>\n <Button type=\"button\" fill=\"outline\" size=\"sm\" onClick={() => setMode('paste')} disabled={disabled}>\n Paste JWT Token\n </Button>\n <span className={styles.separator}>or</span>\n <Button type=\"button\" fill=\"outline\" size=\"sm\" onClick={() => setMode('upload')} disabled={disabled}>\n Upload JWT Token\n </Button>\n </div>\n );\n }\n\n // Paste mode: textarea + toggle buttons\n if (mode === 'paste') {\n return (\n <div>\n <TextArea\n placeholder={field.ui?.placeholder ?? 'Paste Google JWT token here'}\n rows={field.ui?.rows ?? 10}\n onBlur={(e) => {\n const val = e.currentTarget.value;\n if (val.trim()) {\n processJson(val);\n }\n }}\n disabled={disabled}\n />\n <div className={styles.buttonRow}>\n <Button type=\"button\" fill=\"outline\" size=\"sm\" onClick={() => setMode('upload')} disabled={disabled}>\n Upload JWT Token\n </Button>\n <span className={styles.separator}>or</span>\n <Button type=\"button\" fill=\"outline\" size=\"sm\" onClick={() => setMode('manual')} disabled={disabled}>\n Fill In JWT Token manually\n </Button>\n </div>\n {error && <span className={styles.error}>{error}</span>}\n </div>\n );\n }\n\n // Upload mode (default): FileDropzone + toggle buttons\n return (\n <div>\n <FileDropzone\n options={{ multiple: false, accept: accept.join(',') }}\n readAs=\"readAsText\"\n onLoad={(result) => {\n if (typeof result === 'string') {\n processJson(result);\n }\n }}\n />\n <div className={styles.buttonRow}>\n <Button type=\"button\" fill=\"outline\" size=\"sm\" onClick={() => setMode('paste')} disabled={disabled}>\n Paste JWT Token\n </Button>\n <span className={styles.separator}>or</span>\n <Button type=\"button\" fill=\"outline\" size=\"sm\" onClick={() => setMode('manual')} disabled={disabled}>\n Fill In JWT Token manually\n </Button>\n </div>\n {error && <span className={styles.error}>{error}</span>}\n </div>\n );\n}\n\nfunction getStyles(theme: ReturnType<typeof useTheme2>) {\n return {\n buttonRow: css({\n marginTop: theme.spacing(1),\n display: 'flex',\n alignItems: 'center',\n gap: theme.spacing(0.5),\n }),\n separator: css({\n padding: `0 ${theme.spacing(0.5)}`,\n color: theme.colors.text.secondary,\n }),\n error: css({\n color: theme.colors.error.text,\n fontSize: theme.typography.bodySmall.fontSize,\n marginTop: theme.spacing(0.5),\n display: 'block',\n }),\n };\n}\n"],"names":["getStyles"],"mappings":"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"}