@grafana/plugin-ui 0.14.0-dev.1 → 0.14.1-dsconfig.032cfc4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/index.cjs +2803 -185
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/index.d.cts +694 -39
- package/dist/cjs/schemas.cjs +25 -0
- package/dist/cjs/schemas.cjs.map +1 -0
- package/dist/cjs/schemas.d.cts +448 -0
- package/dist/cjs/test-utils.d.cts +23 -23
- package/dist/cjs/useDatasourceSchema-CxPGD2-b.js +17125 -0
- package/dist/cjs/useDatasourceSchema-CxPGD2-b.js.map +1 -0
- package/dist/esm/components/ConfigEditor/ConfigSection/ConfigDescriptionLink.js +2 -2
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/DatasourceConfigWizard.js +234 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/DatasourceConfigWizard.js.map +1 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/DatasourceErrorBoundary.js +27 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/DatasourceErrorBoundary.js.map +1 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/SchemaField.js +71 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/SchemaField.js.map +1 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/SidebarNav.js +54 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/SidebarNav.js.map +1 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/TabLayout.js +181 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/TabLayout.js.map +1 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/cel.js +75 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/cel.js.map +1 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/config.js +258 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/config.js.map +1 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/datasource.js +354 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/datasource.js.map +1 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/fieldUtils.js +138 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/fieldUtils.js.map +1 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/hooks/useDatasourceConfigForm.js +326 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/hooks/useDatasourceConfigForm.js.map +1 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/hooks/useHealthChecks.js +106 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/hooks/useHealthChecks.js.map +1 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/inputs/AuthorizationHeaderField.js +51 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/inputs/AuthorizationHeaderField.js.map +1 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/inputs/ComplexFieldNote.js +26 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/inputs/ComplexFieldNote.js.map +1 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/inputs/FileUploadField.js +106 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/inputs/FileUploadField.js.map +1 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/inputs/IndexedPairEditor.js +124 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/inputs/IndexedPairEditor.js.map +1 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/inputs/ObjectArrayEditor.js +190 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/inputs/ObjectArrayEditor.js.map +1 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/inputs/PdcFieldNote.js +31 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/inputs/PdcFieldNote.js.map +1 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/inputs/SecureFieldInput.js +59 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/inputs/SecureFieldInput.js.map +1 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/inputs/StringArrayInput.js +80 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/inputs/StringArrayInput.js.map +1 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/renderFieldInput.js +141 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/renderFieldInput.js.map +1 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/resolvePluginName.js +30 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/resolvePluginName.js.map +1 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/styles.js +360 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/styles.js.map +1 -0
- package/dist/esm/components/DataLinks/DataLink.js +2 -2
- package/dist/esm/components/DataLinks/DataLinks.js +2 -2
- package/dist/esm/components/DataSourcePicker/DataSourcePicker.js +7 -7
- package/dist/esm/components/DatePicker/styles.js +2 -2
- package/dist/esm/components/DatePickerWithInput/styles.js +2 -2
- package/dist/esm/components/QueryEditor/EditorField.js +2 -2
- package/dist/esm/components/QueryEditor/EditorHeader.js +2 -2
- package/dist/esm/components/QueryEditor/EditorRow.js +2 -2
- package/dist/esm/components/QueryEditor/EditorSwitch.js +2 -2
- package/dist/esm/components/QueryEditor/InlineSelect.js +1 -1
- package/dist/esm/components/QueryEditor/InlineSelect.js.map +1 -1
- package/dist/esm/components/QueryEditor/InputGroup.js +2 -2
- package/dist/esm/components/QueryEditor/QueryEditor.js +3 -1
- package/dist/esm/components/QueryEditor/QueryEditor.js.map +1 -1
- package/dist/esm/components/QueryEditor/QueryHeader.js +2 -2
- package/dist/esm/components/QueryEditor/QueryHeader.js.map +1 -1
- package/dist/esm/components/QueryEditor/Space.js +2 -2
- package/dist/esm/components/QueryEditor/TableSelector.js +0 -1
- package/dist/esm/components/QueryEditor/TableSelector.js.map +1 -1
- package/dist/esm/components/QueryEditor/defaults.js.map +1 -1
- package/dist/esm/components/QueryEditor/query-editor-raw/QueryEditorRaw.js +10 -2
- package/dist/esm/components/QueryEditor/query-editor-raw/QueryEditorRaw.js.map +1 -1
- package/dist/esm/components/QueryEditor/query-editor-raw/QueryToolbox.js +6 -1
- package/dist/esm/components/QueryEditor/query-editor-raw/QueryToolbox.js.map +1 -1
- package/dist/esm/components/QueryEditor/query-editor-raw/RawEditor.js +13 -3
- package/dist/esm/components/QueryEditor/query-editor-raw/RawEditor.js.map +1 -1
- package/dist/esm/components/QueryEditor/types.js +0 -1
- package/dist/esm/components/QueryEditor/types.js.map +1 -1
- package/dist/esm/components/QueryEditor/utils/formatSQL.js +15 -4
- package/dist/esm/components/QueryEditor/utils/formatSQL.js.map +1 -1
- package/dist/esm/components/QueryEditor/visual-query-builder/EditorField.js +2 -2
- package/dist/esm/components/QueryEditor/visual-query-builder/EditorRow.js +2 -2
- package/dist/esm/components/QueryEditor/visual-query-builder/Preview.js +4 -4
- package/dist/esm/components/QueryEditor/visual-query-builder/Preview.js.map +1 -1
- package/dist/esm/components/QueryEditor/visual-query-builder/SQLGroupByRow.js +0 -1
- package/dist/esm/components/QueryEditor/visual-query-builder/SQLGroupByRow.js.map +1 -1
- package/dist/esm/components/QueryEditor/visual-query-builder/SQLOrderByRow.js +0 -1
- package/dist/esm/components/QueryEditor/visual-query-builder/SQLOrderByRow.js.map +1 -1
- package/dist/esm/components/QueryEditor/visual-query-builder/SQLSelectRow.js +0 -1
- package/dist/esm/components/QueryEditor/visual-query-builder/SQLSelectRow.js.map +1 -1
- package/dist/esm/components/QueryEditor/visual-query-builder/SQLWhereRow.js +0 -1
- package/dist/esm/components/QueryEditor/visual-query-builder/SQLWhereRow.js.map +1 -1
- package/dist/esm/components/QueryEditor/visual-query-builder/SelectRow.js +2 -2
- package/dist/esm/components/QueryEditor/visual-query-builder/VisualEditor.js +10 -2
- package/dist/esm/components/QueryEditor/visual-query-builder/VisualEditor.js.map +1 -1
- package/dist/esm/components/SQLEditor/components/SQLEditor.js.map +1 -1
- package/dist/esm/components/SQLEditor/standardSql/definition.js +0 -6
- package/dist/esm/components/SQLEditor/standardSql/definition.js.map +1 -1
- package/dist/esm/components/SQLEditor/standardSql/getStatementPosition.js +2 -1
- package/dist/esm/components/SQLEditor/standardSql/getStatementPosition.js.map +1 -1
- package/dist/esm/components/SQLEditor/standardSql/statementPositionResolversRegistry.js +2 -1
- package/dist/esm/components/SQLEditor/standardSql/statementPositionResolversRegistry.js.map +1 -1
- package/dist/esm/components/SQLEditor/types.js +1 -17
- package/dist/esm/components/SQLEditor/types.js.map +1 -1
- package/dist/esm/components/SQLEditor/utils/LinkedToken.js +1 -1
- package/dist/esm/components/SQLEditor/utils/LinkedToken.js.map +1 -1
- package/dist/esm/components/SQLEditor/utils/linkedTokenBuilder.js +2 -2
- package/dist/esm/components/SQLEditor/utils/tokenType.js +18 -0
- package/dist/esm/components/SQLEditor/utils/tokenType.js.map +1 -0
- package/dist/esm/components/SQLEditor/utils/tokenUtils.js +1 -1
- package/dist/esm/components/VisualQueryBuilder/components/OperationEditorBody.js +1 -1
- package/dist/esm/components/VisualQueryBuilder/components/OperationList.js +1 -1
- package/dist/esm/components/VisualQueryBuilder/components/OperationParamEditor.js +1 -1
- package/dist/esm/components/VisualQueryBuilder/components/OperationsEditorRow.js +1 -1
- package/dist/esm/components/VisualQueryBuilder/components/QueryHeaderSwitch.js +1 -1
- package/dist/esm/components/VisualQueryBuilder/components/QueryOptionGroup.js +1 -1
- package/dist/esm/datasource/SqlDatasource.js +10 -10
- package/dist/esm/index.d.ts +694 -39
- package/dist/esm/index.js +13 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/schema/registry/alertmanager.schema.json.js +77 -0
- package/dist/esm/schema/registry/alertmanager.schema.json.js.map +1 -0
- package/dist/esm/schema/registry/cloudwatch.schema.json.js +384 -0
- package/dist/esm/schema/registry/cloudwatch.schema.json.js.map +1 -0
- package/dist/esm/schema/registry/elasticsearch.schema.json.js +597 -0
- package/dist/esm/schema/registry/elasticsearch.schema.json.js.map +1 -0
- package/dist/esm/schema/registry/grafana-adobeanalytics-datasource.schema.json.js +95 -0
- package/dist/esm/schema/registry/grafana-adobeanalytics-datasource.schema.json.js.map +1 -0
- package/dist/esm/schema/registry/grafana-amazonprometheus-datasource.schema.json.js +166 -0
- package/dist/esm/schema/registry/grafana-amazonprometheus-datasource.schema.json.js.map +1 -0
- package/dist/esm/schema/registry/grafana-appdynamics-datasource.schema.json.js +145 -0
- package/dist/esm/schema/registry/grafana-appdynamics-datasource.schema.json.js.map +1 -0
- package/dist/esm/schema/registry/grafana-astradb-datasource.schema.json.js +123 -0
- package/dist/esm/schema/registry/grafana-astradb-datasource.schema.json.js.map +1 -0
- package/dist/esm/schema/registry/grafana-athena-datasource.schema.json.js +158 -0
- package/dist/esm/schema/registry/grafana-athena-datasource.schema.json.js.map +1 -0
- package/dist/esm/schema/registry/grafana-atlassianstatuspage-datasource.schema.json.js +43 -0
- package/dist/esm/schema/registry/grafana-atlassianstatuspage-datasource.schema.json.js.map +1 -0
- package/dist/esm/schema/registry/grafana-azure-data-explorer-datasource.schema.json.js +204 -0
- package/dist/esm/schema/registry/grafana-azure-data-explorer-datasource.schema.json.js.map +1 -0
- package/dist/esm/schema/registry/grafana-azure-monitor-datasource.schema.json.js +300 -0
- package/dist/esm/schema/registry/grafana-azure-monitor-datasource.schema.json.js.map +1 -0
- package/dist/esm/schema/registry/grafana-azuredevops-datasource.schema.json.js +101 -0
- package/dist/esm/schema/registry/grafana-azuredevops-datasource.schema.json.js.map +1 -0
- package/dist/esm/schema/registry/grafana-azureprometheus-datasource.schema.json.js +125 -0
- package/dist/esm/schema/registry/grafana-azureprometheus-datasource.schema.json.js.map +1 -0
- package/dist/esm/schema/registry/grafana-bigquery-datasource.schema.json.js +508 -0
- package/dist/esm/schema/registry/grafana-bigquery-datasource.schema.json.js.map +1 -0
- package/dist/esm/schema/registry/grafana-catchpoint-datasource.schema.json.js +42 -0
- package/dist/esm/schema/registry/grafana-catchpoint-datasource.schema.json.js.map +1 -0
- package/dist/esm/schema/registry/grafana-clickhouse-datasource.schema.json.js +1400 -0
- package/dist/esm/schema/registry/grafana-clickhouse-datasource.schema.json.js.map +1 -0
- package/dist/esm/schema/registry/grafana-cloudflare-datasource.schema.json.js +42 -0
- package/dist/esm/schema/registry/grafana-cloudflare-datasource.schema.json.js.map +1 -0
- package/dist/esm/schema/registry/grafana-cockroachdb-datasource.schema.json.js +302 -0
- package/dist/esm/schema/registry/grafana-cockroachdb-datasource.schema.json.js.map +1 -0
- package/dist/esm/schema/registry/grafana-databricks-datasource.schema.json.js +291 -0
- package/dist/esm/schema/registry/grafana-databricks-datasource.schema.json.js.map +1 -0
- package/dist/esm/schema/registry/grafana-datadog-datasource.schema.json.js +155 -0
- package/dist/esm/schema/registry/grafana-datadog-datasource.schema.json.js.map +1 -0
- package/dist/esm/schema/registry/grafana-drone-datasource.schema.json.js +64 -0
- package/dist/esm/schema/registry/grafana-drone-datasource.schema.json.js.map +1 -0
- package/dist/esm/schema/registry/grafana-dynatrace-datasource.schema.json.js +179 -0
- package/dist/esm/schema/registry/grafana-dynatrace-datasource.schema.json.js.map +1 -0
- package/dist/esm/schema/registry/grafana-falconlogscale-datasource.schema.json.js +134 -0
- package/dist/esm/schema/registry/grafana-falconlogscale-datasource.schema.json.js.map +1 -0
- package/dist/esm/schema/registry/grafana-github-datasource.schema.json.js +156 -0
- package/dist/esm/schema/registry/grafana-github-datasource.schema.json.js.map +1 -0
- package/dist/esm/schema/registry/grafana-gitlab-datasource.schema.json.js +84 -0
- package/dist/esm/schema/registry/grafana-gitlab-datasource.schema.json.js.map +1 -0
- package/dist/esm/schema/registry/grafana-googlesheets-datasource.schema.json.js +231 -0
- package/dist/esm/schema/registry/grafana-googlesheets-datasource.schema.json.js.map +1 -0
- package/dist/esm/schema/registry/grafana-honeycomb-datasource.schema.json.js +87 -0
- package/dist/esm/schema/registry/grafana-honeycomb-datasource.schema.json.js.map +1 -0
- package/dist/esm/schema/registry/grafana-iot-sitewise-datasource.schema.json.js +159 -0
- package/dist/esm/schema/registry/grafana-iot-sitewise-datasource.schema.json.js.map +1 -0
- package/dist/esm/schema/registry/grafana-jira-datasource.schema.json.js +188 -0
- package/dist/esm/schema/registry/grafana-jira-datasource.schema.json.js.map +1 -0
- package/dist/esm/schema/registry/grafana-logicmonitor-datasource.schema.json.js +63 -0
- package/dist/esm/schema/registry/grafana-logicmonitor-datasource.schema.json.js.map +1 -0
- package/dist/esm/schema/registry/grafana-looker-datasource.schema.json.js +82 -0
- package/dist/esm/schema/registry/grafana-looker-datasource.schema.json.js.map +1 -0
- package/dist/esm/schema/registry/grafana-mongodb-datasource.schema.json.js +278 -0
- package/dist/esm/schema/registry/grafana-mongodb-datasource.schema.json.js.map +1 -0
- package/dist/esm/schema/registry/grafana-mqtt-datasource.schema.json.js +168 -0
- package/dist/esm/schema/registry/grafana-mqtt-datasource.schema.json.js.map +1 -0
- package/dist/esm/schema/registry/grafana-netlify-datasource.schema.json.js +42 -0
- package/dist/esm/schema/registry/grafana-netlify-datasource.schema.json.js.map +1 -0
- package/dist/esm/schema/registry/grafana-newrelic-datasource.schema.json.js +129 -0
- package/dist/esm/schema/registry/grafana-newrelic-datasource.schema.json.js.map +1 -0
- package/dist/esm/schema/registry/grafana-odbc-datasource.schema.json.js +56 -0
- package/dist/esm/schema/registry/grafana-odbc-datasource.schema.json.js.map +1 -0
- package/dist/esm/schema/registry/grafana-opensearch-datasource.schema.json.js +212 -0
- package/dist/esm/schema/registry/grafana-opensearch-datasource.schema.json.js.map +1 -0
- package/dist/esm/schema/registry/grafana-oracle-datasource.schema.json.js +186 -0
- package/dist/esm/schema/registry/grafana-oracle-datasource.schema.json.js.map +1 -0
- package/dist/esm/schema/registry/grafana-pagerduty-datasource.schema.json.js +85 -0
- package/dist/esm/schema/registry/grafana-pagerduty-datasource.schema.json.js.map +1 -0
- package/dist/esm/schema/registry/grafana-postgresql-datasource.schema.json.js +411 -0
- package/dist/esm/schema/registry/grafana-postgresql-datasource.schema.json.js.map +1 -0
- package/dist/esm/schema/registry/grafana-pyroscope-datasource.schema.json.js +41 -0
- package/dist/esm/schema/registry/grafana-pyroscope-datasource.schema.json.js.map +1 -0
- package/dist/esm/schema/registry/grafana-redshift-datasource.schema.json.js +201 -0
- package/dist/esm/schema/registry/grafana-redshift-datasource.schema.json.js.map +1 -0
- package/dist/esm/schema/registry/grafana-salesforce-datasource.schema.json.js +248 -0
- package/dist/esm/schema/registry/grafana-salesforce-datasource.schema.json.js.map +1 -0
- package/dist/esm/schema/registry/grafana-saphana-datasource.schema.json.js +208 -0
- package/dist/esm/schema/registry/grafana-saphana-datasource.schema.json.js.map +1 -0
- package/dist/esm/schema/registry/grafana-sentry-datasource.schema.json.js +94 -0
- package/dist/esm/schema/registry/grafana-sentry-datasource.schema.json.js.map +1 -0
- package/dist/esm/schema/registry/grafana-servicenow-datasource.schema.json.js +179 -0
- package/dist/esm/schema/registry/grafana-servicenow-datasource.schema.json.js.map +1 -0
- package/dist/esm/schema/registry/grafana-snowflake-datasource.schema.json.js +304 -0
- package/dist/esm/schema/registry/grafana-snowflake-datasource.schema.json.js.map +1 -0
- package/dist/esm/schema/registry/grafana-solarwinds-datasource.schema.json.js +77 -0
- package/dist/esm/schema/registry/grafana-solarwinds-datasource.schema.json.js.map +1 -0
- package/dist/esm/schema/registry/grafana-splunk-datasource.schema.json.js +690 -0
- package/dist/esm/schema/registry/grafana-splunk-datasource.schema.json.js.map +1 -0
- package/dist/esm/schema/registry/grafana-splunkobservability-datasource.schema.json.js +90 -0
- package/dist/esm/schema/registry/grafana-splunkobservability-datasource.schema.json.js.map +1 -0
- package/dist/esm/schema/registry/grafana-strava-datasource.schema.json.js +74 -0
- package/dist/esm/schema/registry/grafana-strava-datasource.schema.json.js.map +1 -0
- package/dist/esm/schema/registry/grafana-sumologic-datasource.schema.json.js +102 -0
- package/dist/esm/schema/registry/grafana-sumologic-datasource.schema.json.js.map +1 -0
- package/dist/esm/schema/registry/grafana-surrealdb-datasource.schema.json.js +92 -0
- package/dist/esm/schema/registry/grafana-surrealdb-datasource.schema.json.js.map +1 -0
- package/dist/esm/schema/registry/grafana-timestream-datasource.schema.json.js +145 -0
- package/dist/esm/schema/registry/grafana-timestream-datasource.schema.json.js.map +1 -0
- package/dist/esm/schema/registry/grafana-vercel-datasource.schema.json.js +62 -0
- package/dist/esm/schema/registry/grafana-vercel-datasource.schema.json.js.map +1 -0
- package/dist/esm/schema/registry/grafana-wavefront-datasource.schema.json.js +80 -0
- package/dist/esm/schema/registry/grafana-wavefront-datasource.schema.json.js.map +1 -0
- package/dist/esm/schema/registry/grafana-x-ray-datasource.schema.json.js +112 -0
- package/dist/esm/schema/registry/grafana-x-ray-datasource.schema.json.js.map +1 -0
- package/dist/esm/schema/registry/grafana-yugabyte-datasource.schema.json.js +114 -0
- package/dist/esm/schema/registry/grafana-yugabyte-datasource.schema.json.js.map +1 -0
- package/dist/esm/schema/registry/grafana-zendesk-datasource.schema.json.js +76 -0
- package/dist/esm/schema/registry/grafana-zendesk-datasource.schema.json.js.map +1 -0
- package/dist/esm/schema/registry/graphite.schema.json.js +104 -0
- package/dist/esm/schema/registry/graphite.schema.json.js.map +1 -0
- package/dist/esm/schema/registry/index.js +157 -0
- package/dist/esm/schema/registry/index.js.map +1 -0
- package/dist/esm/schema/registry/influxdb.schema.json.js +717 -0
- package/dist/esm/schema/registry/influxdb.schema.json.js.map +1 -0
- package/dist/esm/schema/registry/jaeger.schema.json.js +59 -0
- package/dist/esm/schema/registry/jaeger.schema.json.js.map +1 -0
- package/dist/esm/schema/registry/loki.schema.json.js +545 -0
- package/dist/esm/schema/registry/loki.schema.json.js.map +1 -0
- package/dist/esm/schema/registry/marcusolsson-csv-datasource.schema.json.js +45 -0
- package/dist/esm/schema/registry/marcusolsson-csv-datasource.schema.json.js.map +1 -0
- package/dist/esm/schema/registry/marcusolsson-json-datasource.schema.json.js +36 -0
- package/dist/esm/schema/registry/marcusolsson-json-datasource.schema.json.js.map +1 -0
- package/dist/esm/schema/registry/mssql.schema.json.js +292 -0
- package/dist/esm/schema/registry/mssql.schema.json.js.map +1 -0
- package/dist/esm/schema/registry/mysql.schema.json.js +304 -0
- package/dist/esm/schema/registry/mysql.schema.json.js.map +1 -0
- package/dist/esm/schema/registry/opentsdb.schema.json.js +113 -0
- package/dist/esm/schema/registry/opentsdb.schema.json.js.map +1 -0
- package/dist/esm/schema/registry/prometheus.schema.json.js +783 -0
- package/dist/esm/schema/registry/prometheus.schema.json.js.map +1 -0
- package/dist/esm/schema/registry/stackdriver.schema.json.js +224 -0
- package/dist/esm/schema/registry/stackdriver.schema.json.js.map +1 -0
- package/dist/esm/schema/registry/tempo.schema.json.js +664 -0
- package/dist/esm/schema/registry/tempo.schema.json.js.map +1 -0
- package/dist/esm/schema/registry/yesoreyeram-infinity-datasource.schema.json.js +1073 -0
- package/dist/esm/schema/registry/yesoreyeram-infinity-datasource.schema.json.js.map +1 -0
- package/dist/esm/schema/registry/zipkin.schema.json.js +40 -0
- package/dist/esm/schema/registry/zipkin.schema.json.js.map +1 -0
- package/dist/esm/schema/utils/dsconfig.js +97 -0
- package/dist/esm/schema/utils/dsconfig.js.map +1 -0
- package/dist/esm/schema/utils/llm.js +54 -0
- package/dist/esm/schema/utils/llm.js.map +1 -0
- package/dist/esm/schema/utils/provisioning.js +434 -0
- package/dist/esm/schema/utils/provisioning.js.map +1 -0
- package/dist/esm/schema/utils/useDatasourceSchema.js +16 -0
- package/dist/esm/schema/utils/useDatasourceSchema.js.map +1 -0
- package/dist/esm/schemas.d.ts +448 -0
- package/dist/esm/schemas.js +6 -0
- package/dist/esm/schemas.js.map +1 -0
- package/dist/esm/test-utils.d.ts +23 -23
- package/package.json +52 -16
package/dist/cjs/index.cjs
CHANGED
|
@@ -11,22 +11,25 @@ var e2eSelectors = require('@grafana/e2e-selectors');
|
|
|
11
11
|
var runtime = require('@grafana/runtime');
|
|
12
12
|
var reactUse = require('react-use');
|
|
13
13
|
var ui$1 = require('@react-awesome-query-builder/ui');
|
|
14
|
-
var lodash = require('lodash');
|
|
15
14
|
var uuid = require('uuid');
|
|
15
|
+
var lodash = require('lodash');
|
|
16
16
|
var AutoSizer = require('react-virtualized-auto-sizer');
|
|
17
|
-
var sqlFormatter = require('sql-formatter
|
|
17
|
+
var sqlFormatter = require('sql-formatter');
|
|
18
18
|
var rxjs = require('rxjs');
|
|
19
19
|
var operators$1 = require('rxjs/operators');
|
|
20
|
+
var useDatasourceSchema = require('./useDatasourceSchema-CxPGD2-b.js');
|
|
21
|
+
var reactHookForm = require('react-hook-form');
|
|
22
|
+
require('@marcbachmann/cel-js');
|
|
20
23
|
var dnd = require('@hello-pangea/dnd');
|
|
21
24
|
var reactPopperTooltip = require('react-popper-tooltip');
|
|
22
25
|
var Prism = require('prismjs');
|
|
26
|
+
require('js-yaml');
|
|
23
27
|
|
|
24
28
|
function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; }
|
|
25
29
|
|
|
26
30
|
var React__default = /*#__PURE__*/_interopDefaultCompat(React);
|
|
27
31
|
var Calendar__default = /*#__PURE__*/_interopDefaultCompat(Calendar);
|
|
28
32
|
var AutoSizer__default = /*#__PURE__*/_interopDefaultCompat(AutoSizer);
|
|
29
|
-
var sqlFormatter__default = /*#__PURE__*/_interopDefaultCompat(sqlFormatter);
|
|
30
33
|
var Prism__default = /*#__PURE__*/_interopDefaultCompat(Prism);
|
|
31
34
|
|
|
32
35
|
const QueryEditorRow = (props) => {
|
|
@@ -76,7 +79,7 @@ function Segment(props) {
|
|
|
76
79
|
);
|
|
77
80
|
}
|
|
78
81
|
|
|
79
|
-
const getStyles$
|
|
82
|
+
const getStyles$x = (theme) => {
|
|
80
83
|
const containerBorder = theme.isDark ? theme.v1.palette.dark9 : theme.v1.palette.gray5;
|
|
81
84
|
return {
|
|
82
85
|
container: css.css`
|
|
@@ -226,7 +229,7 @@ const getBodyStyles = (theme) => {
|
|
|
226
229
|
|
|
227
230
|
const DatePicker = React.memo((props) => {
|
|
228
231
|
const theme = ui.useTheme2();
|
|
229
|
-
const styles = getStyles$
|
|
232
|
+
const styles = getStyles$x(theme);
|
|
230
233
|
const { isOpen, onClose } = props;
|
|
231
234
|
if (!isOpen) {
|
|
232
235
|
return null;
|
|
@@ -256,7 +259,7 @@ const Body = React.memo(({ value, onChange }) => {
|
|
|
256
259
|
});
|
|
257
260
|
Body.displayName = "Body";
|
|
258
261
|
|
|
259
|
-
function getStyles$
|
|
262
|
+
function getStyles$w() {
|
|
260
263
|
return {
|
|
261
264
|
input: css.css({
|
|
262
265
|
/* hides the native Calendar picker icon given when using type=date */
|
|
@@ -272,7 +275,7 @@ const formatDate = (date) => date.toISOString().split("T")[0];
|
|
|
272
275
|
const DatePickerWithInput = (props) => {
|
|
273
276
|
const { value, onChange, className, ...rest } = props;
|
|
274
277
|
const [open, setOpen] = React.useState(false);
|
|
275
|
-
const styles = getStyles$
|
|
278
|
+
const styles = getStyles$w();
|
|
276
279
|
return /* @__PURE__ */ React__default.default.createElement(React__default.default.Fragment, null, /* @__PURE__ */ React__default.default.createElement(
|
|
277
280
|
ui.Input,
|
|
278
281
|
{
|
|
@@ -339,15 +342,15 @@ function getSignatureDisplayModel(signature) {
|
|
|
339
342
|
}
|
|
340
343
|
PluginSignatureBadge.displayName = "PluginSignatureBadge";
|
|
341
344
|
|
|
342
|
-
var __defProp$
|
|
343
|
-
var __defNormalProp$
|
|
344
|
-
var __publicField$
|
|
345
|
+
var __defProp$4 = Object.defineProperty;
|
|
346
|
+
var __defNormalProp$4 = (obj, key, value) => key in obj ? __defProp$4(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
347
|
+
var __publicField$4 = (obj, key, value) => __defNormalProp$4(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
345
348
|
class DataSourcePicker extends React.PureComponent {
|
|
346
349
|
constructor(props) {
|
|
347
350
|
super(props);
|
|
348
|
-
__publicField$
|
|
349
|
-
__publicField$
|
|
350
|
-
__publicField$
|
|
351
|
+
__publicField$4(this, "dataSourceSrv", runtime.getDataSourceSrv());
|
|
352
|
+
__publicField$4(this, "state", {});
|
|
353
|
+
__publicField$4(this, "onChange", (item) => {
|
|
351
354
|
const dsSettings = this.dataSourceSrv.getInstanceSettings(item.value);
|
|
352
355
|
if (dsSettings) {
|
|
353
356
|
this.props.onChange(dsSettings);
|
|
@@ -427,14 +430,14 @@ class DataSourcePicker extends React.PureComponent {
|
|
|
427
430
|
));
|
|
428
431
|
}
|
|
429
432
|
}
|
|
430
|
-
__publicField$
|
|
433
|
+
__publicField$4(DataSourcePicker, "defaultProps", {
|
|
431
434
|
autoFocus: false,
|
|
432
435
|
openMenuOnFocus: false,
|
|
433
436
|
placeholder: "Select datasource"
|
|
434
437
|
});
|
|
435
438
|
|
|
436
439
|
const { FormField, Switch } = ui.LegacyForms;
|
|
437
|
-
const getStyles$
|
|
440
|
+
const getStyles$v = ui.stylesFactory(() => ({
|
|
438
441
|
firstRow: css.css`
|
|
439
442
|
display: flex;
|
|
440
443
|
`,
|
|
@@ -451,7 +454,7 @@ const getStyles$p = ui.stylesFactory(() => ({
|
|
|
451
454
|
}));
|
|
452
455
|
const DataLink = (props) => {
|
|
453
456
|
const { value, onChange, onDelete, suggestions, className } = props;
|
|
454
|
-
const styles = getStyles$
|
|
457
|
+
const styles = getStyles$v();
|
|
455
458
|
const [showInternalLink, setShowInternalLink] = useInternalLink(value.datasourceUid);
|
|
456
459
|
const handleChange = (field) => (event) => {
|
|
457
460
|
onChange({
|
|
@@ -568,7 +571,7 @@ function useInternalLink(datasourceUid) {
|
|
|
568
571
|
return [showInternalLink, setShowInternalLink];
|
|
569
572
|
}
|
|
570
573
|
|
|
571
|
-
const getStyles$
|
|
574
|
+
const getStyles$u = (theme) => ({
|
|
572
575
|
infoText: css.css`
|
|
573
576
|
padding-bottom: ${theme.v1.spacing.md};
|
|
574
577
|
color: ${theme.v1.colors.textWeak};
|
|
@@ -580,7 +583,7 @@ const getStyles$o = (theme) => ({
|
|
|
580
583
|
const DataLinks = (props) => {
|
|
581
584
|
const { value, onChange } = props;
|
|
582
585
|
const theme = ui.useTheme2();
|
|
583
|
-
const styles = getStyles$
|
|
586
|
+
const styles = getStyles$u(theme);
|
|
584
587
|
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) => {
|
|
585
588
|
return /* @__PURE__ */ React__default.default.createElement(
|
|
586
589
|
DataLink,
|
|
@@ -641,110 +644,21 @@ var QueryEditorExpressionType = /* @__PURE__ */ ((QueryEditorExpressionType2) =>
|
|
|
641
644
|
return QueryEditorExpressionType2;
|
|
642
645
|
})(QueryEditorExpressionType || {});
|
|
643
646
|
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
rawQuery += `FROM ${table} `;
|
|
660
|
-
}
|
|
661
|
-
if (sql.whereString) {
|
|
662
|
-
rawQuery += `WHERE ${sql.whereString} `;
|
|
663
|
-
}
|
|
664
|
-
if ((_b = (_a = sql.groupBy) == null ? void 0 : _a[0]) == null ? void 0 : _b.property.name) {
|
|
665
|
-
const groupBy = sql.groupBy.map((g) => g.property.name).filter((g) => !lodash.isEmpty(g));
|
|
666
|
-
rawQuery += `GROUP BY ${groupBy.join(", ")} `;
|
|
667
|
-
}
|
|
668
|
-
if ((_c = sql.orderBy) == null ? void 0 : _c.property.name) {
|
|
669
|
-
rawQuery += `ORDER BY ${sql.orderBy.property.name} `;
|
|
670
|
-
}
|
|
671
|
-
if (((_d = sql.orderBy) == null ? void 0 : _d.property.name) && sql.orderByDirection) {
|
|
672
|
-
rawQuery += `${sql.orderByDirection} `;
|
|
673
|
-
}
|
|
674
|
-
if (sql.limit !== void 0 && sql.limit >= 0) {
|
|
675
|
-
rawQuery += `LIMIT ${sql.limit} `;
|
|
676
|
-
}
|
|
677
|
-
return rawQuery;
|
|
678
|
-
}
|
|
679
|
-
function createSelectClause(sqlColumns) {
|
|
680
|
-
const columns = sqlColumns.map((c) => {
|
|
681
|
-
var _a, _b;
|
|
682
|
-
let rawColumn = "";
|
|
683
|
-
if (c.name) {
|
|
684
|
-
rawColumn += `${c.name}(${(_a = c.parameters) == null ? void 0 : _a.map((p) => `${p.name}`)})`;
|
|
685
|
-
} else {
|
|
686
|
-
rawColumn += `${(_b = c.parameters) == null ? void 0 : _b.map((p) => `${p.name}`)}`;
|
|
687
|
-
}
|
|
688
|
-
return rawColumn;
|
|
689
|
-
});
|
|
690
|
-
return `SELECT ${columns.join(", ")} `;
|
|
691
|
-
}
|
|
692
|
-
function haveColumns(columns) {
|
|
693
|
-
if (!columns) {
|
|
694
|
-
return false;
|
|
695
|
-
}
|
|
696
|
-
const haveColumn = columns.some((c) => {
|
|
697
|
-
var _a, _b;
|
|
698
|
-
return ((_a = c.parameters) == null ? void 0 : _a.length) || ((_b = c.parameters) == null ? void 0 : _b.some((p) => p.name));
|
|
699
|
-
});
|
|
700
|
-
const haveFunction = columns.some((c) => c.name);
|
|
701
|
-
return haveColumn || haveFunction;
|
|
702
|
-
}
|
|
703
|
-
function setGroupByField(field) {
|
|
704
|
-
return {
|
|
705
|
-
type: QueryEditorExpressionType.GroupBy,
|
|
706
|
-
property: {
|
|
707
|
-
type: QueryEditorPropertyType.String,
|
|
708
|
-
name: field
|
|
709
|
-
}
|
|
710
|
-
};
|
|
711
|
-
}
|
|
712
|
-
function setPropertyField(field) {
|
|
713
|
-
return {
|
|
714
|
-
type: QueryEditorExpressionType.Property,
|
|
715
|
-
property: {
|
|
716
|
-
type: QueryEditorPropertyType.String,
|
|
717
|
-
name: field
|
|
718
|
-
}
|
|
719
|
-
};
|
|
720
|
-
}
|
|
721
|
-
function createFunctionField(functionName) {
|
|
722
|
-
return {
|
|
723
|
-
type: QueryEditorExpressionType.Function,
|
|
724
|
-
name: functionName,
|
|
725
|
-
parameters: []
|
|
726
|
-
};
|
|
727
|
-
}
|
|
728
|
-
|
|
729
|
-
function applyQueryDefaults(q) {
|
|
730
|
-
let editorMode = (q == null ? void 0 : q.editorMode) || EditorMode.Builder;
|
|
731
|
-
if ((q == null ? void 0 : q.editorMode) === void 0 && (q == null ? void 0 : q.rawSql) !== void 0) {
|
|
732
|
-
editorMode = EditorMode.Code;
|
|
733
|
-
}
|
|
734
|
-
const result = {
|
|
735
|
-
...q,
|
|
736
|
-
refId: (q == null ? void 0 : q.refId) || "A",
|
|
737
|
-
format: (q == null ? void 0 : q.format) !== void 0 ? q.format : QueryFormat.Table,
|
|
738
|
-
rawSql: (q == null ? void 0 : q.rawSql) || "",
|
|
739
|
-
editorMode,
|
|
740
|
-
sql: (q == null ? void 0 : q.sql) || {
|
|
741
|
-
columns: [createFunctionField()],
|
|
742
|
-
groupBy: [setGroupByField()],
|
|
743
|
-
limit: 50
|
|
744
|
-
}
|
|
745
|
-
};
|
|
746
|
-
return result;
|
|
747
|
-
}
|
|
647
|
+
var TokenType = /* @__PURE__ */ ((TokenType2) => {
|
|
648
|
+
TokenType2["Parenthesis"] = "delimiter.parenthesis.sql";
|
|
649
|
+
TokenType2["Whitespace"] = "white.sql";
|
|
650
|
+
TokenType2["Keyword"] = "keyword.sql";
|
|
651
|
+
TokenType2["Delimiter"] = "delimiter.sql";
|
|
652
|
+
TokenType2["Operator"] = "operator.sql";
|
|
653
|
+
TokenType2["Identifier"] = "identifier.sql";
|
|
654
|
+
TokenType2["IdentifierQuote"] = "identifier.quote.sql";
|
|
655
|
+
TokenType2["Type"] = "type.sql";
|
|
656
|
+
TokenType2["Function"] = "predefined.sql";
|
|
657
|
+
TokenType2["Number"] = "number.sql";
|
|
658
|
+
TokenType2["String"] = "string.sql";
|
|
659
|
+
TokenType2["Variable"] = "variable.sql";
|
|
660
|
+
return TokenType2;
|
|
661
|
+
})(TokenType || {});
|
|
748
662
|
|
|
749
663
|
class LinkedToken {
|
|
750
664
|
constructor(type, value, range, previous, next) {
|
|
@@ -899,21 +813,6 @@ var MacroType = /* @__PURE__ */ ((MacroType2) => {
|
|
|
899
813
|
MacroType2[MacroType2["Table"] = 4] = "Table";
|
|
900
814
|
return MacroType2;
|
|
901
815
|
})(MacroType || {});
|
|
902
|
-
var TokenType = /* @__PURE__ */ ((TokenType2) => {
|
|
903
|
-
TokenType2["Parenthesis"] = "delimiter.parenthesis.sql";
|
|
904
|
-
TokenType2["Whitespace"] = "white.sql";
|
|
905
|
-
TokenType2["Keyword"] = "keyword.sql";
|
|
906
|
-
TokenType2["Delimiter"] = "delimiter.sql";
|
|
907
|
-
TokenType2["Operator"] = "operator.sql";
|
|
908
|
-
TokenType2["Identifier"] = "identifier.sql";
|
|
909
|
-
TokenType2["IdentifierQuote"] = "identifier.quote.sql";
|
|
910
|
-
TokenType2["Type"] = "type.sql";
|
|
911
|
-
TokenType2["Function"] = "predefined.sql";
|
|
912
|
-
TokenType2["Number"] = "number.sql";
|
|
913
|
-
TokenType2["String"] = "string.sql";
|
|
914
|
-
TokenType2["Variable"] = "variable.sql";
|
|
915
|
-
return TokenType2;
|
|
916
|
-
})(TokenType || {});
|
|
917
816
|
var StatementPosition = /* @__PURE__ */ ((StatementPosition2) => {
|
|
918
817
|
StatementPosition2["Unknown"] = "unknown";
|
|
919
818
|
StatementPosition2["SelectKeyword"] = "selectKeyword";
|
|
@@ -5456,6 +5355,91 @@ const QUERY_FORMAT_OPTIONS = [
|
|
|
5456
5355
|
const backWardToOption = (value) => ({ label: value, value });
|
|
5457
5356
|
const toOption = (_a = data.toOption) != null ? _a : backWardToOption;
|
|
5458
5357
|
|
|
5358
|
+
function getRawSqlFn(db) {
|
|
5359
|
+
return db.toRawSql ? db.toRawSql : (query) => toRawSql(query, Boolean(db.disableDatasets));
|
|
5360
|
+
}
|
|
5361
|
+
function toRawSql({ sql, dataset, catalog, table }, disableDatasets) {
|
|
5362
|
+
var _a, _b, _c, _d;
|
|
5363
|
+
let rawQuery = "";
|
|
5364
|
+
if (!sql || !haveColumns(sql.columns)) {
|
|
5365
|
+
return rawQuery;
|
|
5366
|
+
}
|
|
5367
|
+
rawQuery += createSelectClause(sql.columns);
|
|
5368
|
+
if (catalog && dataset && table) {
|
|
5369
|
+
rawQuery += `FROM ${catalog}.${dataset}.${table} `;
|
|
5370
|
+
} else if (!disableDatasets && dataset && table) {
|
|
5371
|
+
rawQuery += `FROM ${dataset}.${table} `;
|
|
5372
|
+
} else if (table) {
|
|
5373
|
+
rawQuery += `FROM ${table} `;
|
|
5374
|
+
}
|
|
5375
|
+
if (sql.whereString) {
|
|
5376
|
+
rawQuery += `WHERE ${sql.whereString} `;
|
|
5377
|
+
}
|
|
5378
|
+
if ((_b = (_a = sql.groupBy) == null ? void 0 : _a[0]) == null ? void 0 : _b.property.name) {
|
|
5379
|
+
const groupBy = sql.groupBy.map((g) => g.property.name).filter((g) => !lodash.isEmpty(g));
|
|
5380
|
+
rawQuery += `GROUP BY ${groupBy.join(", ")} `;
|
|
5381
|
+
}
|
|
5382
|
+
if ((_c = sql.orderBy) == null ? void 0 : _c.property.name) {
|
|
5383
|
+
rawQuery += `ORDER BY ${sql.orderBy.property.name} `;
|
|
5384
|
+
}
|
|
5385
|
+
if (((_d = sql.orderBy) == null ? void 0 : _d.property.name) && sql.orderByDirection) {
|
|
5386
|
+
rawQuery += `${sql.orderByDirection} `;
|
|
5387
|
+
}
|
|
5388
|
+
if (sql.limit !== void 0 && sql.limit >= 0) {
|
|
5389
|
+
rawQuery += `LIMIT ${sql.limit} `;
|
|
5390
|
+
}
|
|
5391
|
+
return rawQuery;
|
|
5392
|
+
}
|
|
5393
|
+
function createSelectClause(sqlColumns) {
|
|
5394
|
+
const columns = sqlColumns.map((c) => {
|
|
5395
|
+
var _a, _b;
|
|
5396
|
+
let rawColumn = "";
|
|
5397
|
+
if (c.name) {
|
|
5398
|
+
rawColumn += `${c.name}(${(_a = c.parameters) == null ? void 0 : _a.map((p) => `${p.name}`)})`;
|
|
5399
|
+
} else {
|
|
5400
|
+
rawColumn += `${(_b = c.parameters) == null ? void 0 : _b.map((p) => `${p.name}`)}`;
|
|
5401
|
+
}
|
|
5402
|
+
return rawColumn;
|
|
5403
|
+
});
|
|
5404
|
+
return `SELECT ${columns.join(", ")} `;
|
|
5405
|
+
}
|
|
5406
|
+
function haveColumns(columns) {
|
|
5407
|
+
if (!columns) {
|
|
5408
|
+
return false;
|
|
5409
|
+
}
|
|
5410
|
+
const haveColumn = columns.some((c) => {
|
|
5411
|
+
var _a, _b;
|
|
5412
|
+
return ((_a = c.parameters) == null ? void 0 : _a.length) || ((_b = c.parameters) == null ? void 0 : _b.some((p) => p.name));
|
|
5413
|
+
});
|
|
5414
|
+
const haveFunction = columns.some((c) => c.name);
|
|
5415
|
+
return haveColumn || haveFunction;
|
|
5416
|
+
}
|
|
5417
|
+
function setGroupByField(field) {
|
|
5418
|
+
return {
|
|
5419
|
+
type: QueryEditorExpressionType.GroupBy,
|
|
5420
|
+
property: {
|
|
5421
|
+
type: QueryEditorPropertyType.String,
|
|
5422
|
+
name: field
|
|
5423
|
+
}
|
|
5424
|
+
};
|
|
5425
|
+
}
|
|
5426
|
+
function setPropertyField(field) {
|
|
5427
|
+
return {
|
|
5428
|
+
type: QueryEditorExpressionType.Property,
|
|
5429
|
+
property: {
|
|
5430
|
+
type: QueryEditorPropertyType.String,
|
|
5431
|
+
name: field
|
|
5432
|
+
}
|
|
5433
|
+
};
|
|
5434
|
+
}
|
|
5435
|
+
function createFunctionField(functionName) {
|
|
5436
|
+
return {
|
|
5437
|
+
type: QueryEditorExpressionType.Function,
|
|
5438
|
+
name: functionName,
|
|
5439
|
+
parameters: []
|
|
5440
|
+
};
|
|
5441
|
+
}
|
|
5442
|
+
|
|
5459
5443
|
const EditorStack = ({ children, wrap: wrapItems = true, ...props }) => {
|
|
5460
5444
|
var _a, _b;
|
|
5461
5445
|
return /* @__PURE__ */ React__default.default.createElement(ui.Stack, { wrap: wrapItems ? "wrap" : void 0, direction: (_a = props.direction) != null ? _a : "row", gap: (_b = props.gap) != null ? _b : 2, ...props }, children);
|
|
@@ -5495,7 +5479,7 @@ const getButtonStyles = (theme) => ({
|
|
|
5495
5479
|
});
|
|
5496
5480
|
|
|
5497
5481
|
const InputGroup = ({ children }) => {
|
|
5498
|
-
const styles = ui.useStyles2(getStyles$
|
|
5482
|
+
const styles = ui.useStyles2(getStyles$t);
|
|
5499
5483
|
const modifiedChildren = React.Children.map(children, (child) => {
|
|
5500
5484
|
if (React.isValidElement(child) && child.props.invalid) {
|
|
5501
5485
|
return React.cloneElement(child, { className: css.cx(child.props.className, styles.invalidChild) });
|
|
@@ -5513,7 +5497,7 @@ const borderPriority = [
|
|
|
5513
5497
|
"focused"
|
|
5514
5498
|
// highest priority
|
|
5515
5499
|
];
|
|
5516
|
-
const getStyles$
|
|
5500
|
+
const getStyles$t = () => ({
|
|
5517
5501
|
root: css.css({
|
|
5518
5502
|
display: "flex",
|
|
5519
5503
|
// Style the direct children of the component
|
|
@@ -5596,10 +5580,10 @@ const EditorFieldGroup = ({ children }) => {
|
|
|
5596
5580
|
};
|
|
5597
5581
|
|
|
5598
5582
|
const EditorHeader = ({ children }) => {
|
|
5599
|
-
const styles = ui.useStyles2(getStyles$
|
|
5583
|
+
const styles = ui.useStyles2(getStyles$s);
|
|
5600
5584
|
return /* @__PURE__ */ React__default.default.createElement("div", { className: styles.root }, children);
|
|
5601
5585
|
};
|
|
5602
|
-
const getStyles$
|
|
5586
|
+
const getStyles$s = (theme) => ({
|
|
5603
5587
|
root: css.css({
|
|
5604
5588
|
display: "flex",
|
|
5605
5589
|
flexWrap: "wrap",
|
|
@@ -5612,12 +5596,12 @@ const getStyles$m = (theme) => ({
|
|
|
5612
5596
|
const EditorField$1 = (props) => {
|
|
5613
5597
|
var _a;
|
|
5614
5598
|
const { label, optional, tooltip, tooltipInteractive, children, width, ...fieldProps } = props;
|
|
5615
|
-
const styles = ui.useStyles2(getStyles$
|
|
5599
|
+
const styles = ui.useStyles2(getStyles$r, width);
|
|
5616
5600
|
const childInputId = (fieldProps == null ? void 0 : fieldProps.htmlFor) || ((_a = ui.ReactUtils) == null ? void 0 : _a.getChildId(children));
|
|
5617
5601
|
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 }));
|
|
5618
5602
|
return /* @__PURE__ */ React__default.default.createElement("div", { className: styles.root }, /* @__PURE__ */ React__default.default.createElement(ui.Field, { className: styles.field, label: labelEl, ...fieldProps }, children));
|
|
5619
5603
|
};
|
|
5620
|
-
const getStyles$
|
|
5604
|
+
const getStyles$r = (theme, width) => {
|
|
5621
5605
|
return {
|
|
5622
5606
|
root: css.css({
|
|
5623
5607
|
minWidth: theme.spacing(width != null ? width : 0)
|
|
@@ -5645,10 +5629,10 @@ const getStyles$l = (theme, width) => {
|
|
|
5645
5629
|
};
|
|
5646
5630
|
|
|
5647
5631
|
const EditorRow$1 = ({ children }) => {
|
|
5648
|
-
const styles = ui.useStyles2(getStyles$
|
|
5632
|
+
const styles = ui.useStyles2(getStyles$q);
|
|
5649
5633
|
return /* @__PURE__ */ React__default.default.createElement("div", { className: styles.root }, /* @__PURE__ */ React__default.default.createElement(EditorStack, { gap: 2 }, children));
|
|
5650
5634
|
};
|
|
5651
|
-
const getStyles$
|
|
5635
|
+
const getStyles$q = (theme) => {
|
|
5652
5636
|
return {
|
|
5653
5637
|
root: css.css({
|
|
5654
5638
|
padding: theme.spacing(1),
|
|
@@ -5663,10 +5647,10 @@ const EditorRows$1 = ({ children }) => {
|
|
|
5663
5647
|
};
|
|
5664
5648
|
|
|
5665
5649
|
const EditorSwitch = (props) => {
|
|
5666
|
-
const styles = getStyles$
|
|
5650
|
+
const styles = getStyles$p();
|
|
5667
5651
|
return /* @__PURE__ */ React__default.default.createElement("div", { className: styles.switch }, /* @__PURE__ */ React__default.default.createElement(ui.Switch, { ...props }));
|
|
5668
5652
|
};
|
|
5669
|
-
const getStyles$
|
|
5653
|
+
const getStyles$p = () => {
|
|
5670
5654
|
return {
|
|
5671
5655
|
switch: css.css({
|
|
5672
5656
|
display: "flex",
|
|
@@ -5688,7 +5672,7 @@ function InlineSelect({ label: labelProp, ...props }) {
|
|
|
5688
5672
|
ValueContainer,
|
|
5689
5673
|
SingleValue: ValueContainer
|
|
5690
5674
|
};
|
|
5691
|
-
return /* @__PURE__ */ React__default.default.createElement("div", { className: styles.root }, labelProp && /* @__PURE__ */ React__default.default.createElement("label", { className: styles.label, htmlFor: id }, labelProp, ":", "\xA0"), /* @__PURE__ */ React__default.default.createElement(ui.Select, {
|
|
5675
|
+
return /* @__PURE__ */ React__default.default.createElement("div", { className: styles.root }, labelProp && /* @__PURE__ */ React__default.default.createElement("label", { className: styles.label, htmlFor: id }, labelProp, ":", "\xA0"), /* @__PURE__ */ React__default.default.createElement(ui.Select, { inputId: id, ...props, components }));
|
|
5692
5676
|
}
|
|
5693
5677
|
const SelectContainer = (props) => {
|
|
5694
5678
|
const { children } = props;
|
|
@@ -5724,10 +5708,10 @@ const getSelectStyles = (theme) => ({
|
|
|
5724
5708
|
});
|
|
5725
5709
|
|
|
5726
5710
|
const Space = ({ v = 0, h = 0, layout = "block" }) => {
|
|
5727
|
-
const styles = ui.useStyles2(getStyles$
|
|
5711
|
+
const styles = ui.useStyles2(getStyles$o, v, h, layout);
|
|
5728
5712
|
return /* @__PURE__ */ React__default.default.createElement("span", { className: css.cx(styles.wrapper) });
|
|
5729
5713
|
};
|
|
5730
|
-
const getStyles$
|
|
5714
|
+
const getStyles$o = (theme, v, h, layout) => ({
|
|
5731
5715
|
wrapper: css.css([
|
|
5732
5716
|
{
|
|
5733
5717
|
paddingRight: theme.spacing(h != null ? h : 0),
|
|
@@ -5742,6 +5726,26 @@ const getStyles$i = (theme, v, h, layout) => ({
|
|
|
5742
5726
|
])
|
|
5743
5727
|
});
|
|
5744
5728
|
|
|
5729
|
+
function applyQueryDefaults(q) {
|
|
5730
|
+
let editorMode = (q == null ? void 0 : q.editorMode) || EditorMode.Builder;
|
|
5731
|
+
if ((q == null ? void 0 : q.editorMode) === void 0 && (q == null ? void 0 : q.rawSql) !== void 0) {
|
|
5732
|
+
editorMode = EditorMode.Code;
|
|
5733
|
+
}
|
|
5734
|
+
const result = {
|
|
5735
|
+
...q,
|
|
5736
|
+
refId: (q == null ? void 0 : q.refId) || "A",
|
|
5737
|
+
format: (q == null ? void 0 : q.format) !== void 0 ? q.format : QueryFormat.Table,
|
|
5738
|
+
rawSql: (q == null ? void 0 : q.rawSql) || "",
|
|
5739
|
+
editorMode,
|
|
5740
|
+
sql: (q == null ? void 0 : q.sql) || {
|
|
5741
|
+
columns: [createFunctionField()],
|
|
5742
|
+
groupBy: [setGroupByField()],
|
|
5743
|
+
limit: 50
|
|
5744
|
+
}
|
|
5745
|
+
};
|
|
5746
|
+
return result;
|
|
5747
|
+
}
|
|
5748
|
+
|
|
5745
5749
|
function ConfirmModal({ isOpen, onCancel, onDiscard, onCopy }) {
|
|
5746
5750
|
const buttonRef = React.useRef(null);
|
|
5747
5751
|
React.useEffect(() => {
|
|
@@ -6131,14 +6135,33 @@ function QueryHeader({
|
|
|
6131
6135
|
)))));
|
|
6132
6136
|
}
|
|
6133
6137
|
|
|
6134
|
-
function formatSQL(q) {
|
|
6135
|
-
|
|
6136
|
-
|
|
6138
|
+
function formatSQL(q, language = "sql") {
|
|
6139
|
+
const formatted = sqlFormatter.format(q, {
|
|
6140
|
+
language,
|
|
6141
|
+
paramTypes: {
|
|
6142
|
+
custom: [
|
|
6143
|
+
{
|
|
6144
|
+
regex: "\\$\\s*\\{[^}]*\\}|\\$\\s*__\\w+(?:\\([^)]*\\))?|\\$\\s*\\w+"
|
|
6145
|
+
}
|
|
6146
|
+
]
|
|
6147
|
+
}
|
|
6137
6148
|
});
|
|
6149
|
+
return formatted.replace(
|
|
6150
|
+
/(\$\s*\{[^}]*\})|(\$\s*__\w+(?:\([^)]*\))?)|(\$\s*\w+)/g,
|
|
6151
|
+
(m) => m.replace(/\s/g, "")
|
|
6152
|
+
);
|
|
6138
6153
|
}
|
|
6139
6154
|
|
|
6140
|
-
function QueryEditorRaw({
|
|
6141
|
-
|
|
6155
|
+
function QueryEditorRaw({
|
|
6156
|
+
children,
|
|
6157
|
+
onChange,
|
|
6158
|
+
query,
|
|
6159
|
+
width,
|
|
6160
|
+
height,
|
|
6161
|
+
completionProvider,
|
|
6162
|
+
language = "sql"
|
|
6163
|
+
}) {
|
|
6164
|
+
const queryRef = React.useRef(query);
|
|
6142
6165
|
React.useEffect(() => {
|
|
6143
6166
|
queryRef.current = query;
|
|
6144
6167
|
}, [query]);
|
|
@@ -6160,7 +6183,7 @@ function QueryEditorRaw({ children, onChange, query, width, height, completionPr
|
|
|
6160
6183
|
height,
|
|
6161
6184
|
query: query.rawSql,
|
|
6162
6185
|
onChange: onRawQueryChange,
|
|
6163
|
-
language: { id: "sql", completionProvider, formatter: formatSQL }
|
|
6186
|
+
language: { id: "sql", completionProvider, formatter: (q) => formatSQL(q, language) }
|
|
6164
6187
|
},
|
|
6165
6188
|
children
|
|
6166
6189
|
);
|
|
@@ -6265,6 +6288,10 @@ function QueryToolbox({ showTools, onFormatCode, onExpand, isExpanded, ...valida
|
|
|
6265
6288
|
if (!showTools && validationResult === void 0) {
|
|
6266
6289
|
style = { height: 0, padding: 0, visibility: "hidden" };
|
|
6267
6290
|
}
|
|
6291
|
+
const onFormatClick = () => {
|
|
6292
|
+
runtime.reportInteraction("grafana_sql_query_editor_format_click");
|
|
6293
|
+
onFormatCode == null ? void 0 : onFormatCode();
|
|
6294
|
+
};
|
|
6268
6295
|
return /* @__PURE__ */ React__default.default.createElement("div", { className: styles.container, style }, /* @__PURE__ */ React__default.default.createElement("div", null, validatorProps.onValidate && /* @__PURE__ */ React__default.default.createElement(
|
|
6269
6296
|
QueryValidator,
|
|
6270
6297
|
{
|
|
@@ -6274,7 +6301,7 @@ function QueryToolbox({ showTools, onFormatCode, onExpand, isExpanded, ...valida
|
|
|
6274
6301
|
validatorProps.onValidate(result);
|
|
6275
6302
|
}
|
|
6276
6303
|
}
|
|
6277
|
-
)), showTools && /* @__PURE__ */ React__default.default.createElement("div", null, /* @__PURE__ */ React__default.default.createElement(ui.HorizontalGroup, { spacing: "sm" }, onFormatCode && /* @__PURE__ */ React__default.default.createElement(ui.IconButton, { onClick:
|
|
6304
|
+
)), showTools && /* @__PURE__ */ React__default.default.createElement("div", null, /* @__PURE__ */ React__default.default.createElement(ui.HorizontalGroup, { spacing: "sm" }, onFormatCode && /* @__PURE__ */ React__default.default.createElement(ui.IconButton, { onClick: onFormatClick, name: "brackets-curly", size: "xs", tooltip: "Format query" }), onExpand && /* @__PURE__ */ React__default.default.createElement(
|
|
6278
6305
|
ui.IconButton,
|
|
6279
6306
|
{
|
|
6280
6307
|
onClick: () => onExpand(!isExpanded),
|
|
@@ -6285,9 +6312,18 @@ function QueryToolbox({ showTools, onFormatCode, onExpand, isExpanded, ...valida
|
|
|
6285
6312
|
), /* @__PURE__ */ React__default.default.createElement(ui.Tooltip, { content: "Hit CTRL/CMD+Return to run query" }, /* @__PURE__ */ React__default.default.createElement(ui.Icon, { className: styles.hint, name: "keyboard" })))));
|
|
6286
6313
|
}
|
|
6287
6314
|
|
|
6288
|
-
function RawEditor({
|
|
6315
|
+
function RawEditor({
|
|
6316
|
+
db,
|
|
6317
|
+
query,
|
|
6318
|
+
onChange,
|
|
6319
|
+
onRunQuery,
|
|
6320
|
+
onValidate,
|
|
6321
|
+
queryToValidate,
|
|
6322
|
+
range,
|
|
6323
|
+
language = "sql"
|
|
6324
|
+
}) {
|
|
6289
6325
|
const theme = ui.useTheme2();
|
|
6290
|
-
const styles = ui.useStyles2(getStyles$
|
|
6326
|
+
const styles = ui.useStyles2(getStyles$n);
|
|
6291
6327
|
const [isExpanded, setIsExpanded] = React.useState(false);
|
|
6292
6328
|
const [toolboxRef, toolboxMeasure] = reactUse.useMeasure();
|
|
6293
6329
|
const [editorRef, editorMeasure] = reactUse.useMeasure();
|
|
@@ -6299,6 +6335,7 @@ function RawEditor({ db, query, onChange, onRunQuery, onValidate, queryToValidat
|
|
|
6299
6335
|
completionProvider,
|
|
6300
6336
|
query,
|
|
6301
6337
|
width,
|
|
6338
|
+
language,
|
|
6302
6339
|
height: height ? height - toolboxMeasure.height : void 0,
|
|
6303
6340
|
onChange
|
|
6304
6341
|
},
|
|
@@ -6356,7 +6393,7 @@ function RawEditor({ db, query, onChange, onRunQuery, onValidate, queryToValidat
|
|
|
6356
6393
|
renderEditor(true)
|
|
6357
6394
|
));
|
|
6358
6395
|
}
|
|
6359
|
-
function getStyles$
|
|
6396
|
+
function getStyles$n(theme) {
|
|
6360
6397
|
return {
|
|
6361
6398
|
modal: css.css`
|
|
6362
6399
|
width: 95vw;
|
|
@@ -6369,23 +6406,23 @@ function getStyles$h(theme) {
|
|
|
6369
6406
|
};
|
|
6370
6407
|
}
|
|
6371
6408
|
|
|
6372
|
-
function Preview({ rawSql }) {
|
|
6409
|
+
function Preview({ rawSql, language = "sql" }) {
|
|
6373
6410
|
const [_, copyToClipboard] = reactUse.useCopyToClipboard();
|
|
6374
|
-
const styles = ui.useStyles2(getStyles$
|
|
6411
|
+
const styles = ui.useStyles2(getStyles$m);
|
|
6375
6412
|
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" }));
|
|
6376
6413
|
return /* @__PURE__ */ React__default.default.createElement(ui.Field, { label: labelElement, className: styles.grow }, /* @__PURE__ */ React__default.default.createElement(
|
|
6377
6414
|
ui.CodeEditor,
|
|
6378
6415
|
{
|
|
6379
6416
|
language: "sql",
|
|
6380
6417
|
height: 80,
|
|
6381
|
-
value: formatSQL(rawSql),
|
|
6418
|
+
value: formatSQL(rawSql, language),
|
|
6382
6419
|
monacoOptions: { scrollbar: { vertical: "hidden" }, scrollBeyondLastLine: false },
|
|
6383
6420
|
readOnly: true,
|
|
6384
6421
|
showMiniMap: false
|
|
6385
6422
|
}
|
|
6386
6423
|
));
|
|
6387
6424
|
}
|
|
6388
|
-
function getStyles$
|
|
6425
|
+
function getStyles$m(theme) {
|
|
6389
6426
|
return {
|
|
6390
6427
|
grow: css.css({ flexGrow: 1 }),
|
|
6391
6428
|
label: css.css({ fontSize: 12, fontWeight: theme.typography.fontWeightMedium }),
|
|
@@ -6504,7 +6541,7 @@ function SQLOrderByRow({ fields, query, onQueryChange, db }) {
|
|
|
6504
6541
|
const asteriskValue = { label: "*", value: "*" };
|
|
6505
6542
|
function SelectRow({ sql, columns, onSqlChange, functions }) {
|
|
6506
6543
|
var _a;
|
|
6507
|
-
const styles = ui.useStyles2(getStyles$
|
|
6544
|
+
const styles = ui.useStyles2(getStyles$l);
|
|
6508
6545
|
const columnsWithAsterisk = [asteriskValue, ...columns || []];
|
|
6509
6546
|
const onColumnChange = React.useCallback(
|
|
6510
6547
|
(item, index) => (column) => {
|
|
@@ -6600,7 +6637,7 @@ function SelectRow({ sql, columns, onSqlChange, functions }) {
|
|
|
6600
6637
|
}
|
|
6601
6638
|
));
|
|
6602
6639
|
}
|
|
6603
|
-
const getStyles$
|
|
6640
|
+
const getStyles$l = () => {
|
|
6604
6641
|
return { addButton: css.css({ alignSelf: "flex-start" }) };
|
|
6605
6642
|
};
|
|
6606
6643
|
function getColumnValue({ parameters }) {
|
|
@@ -6946,10 +6983,10 @@ function mapFieldsToTypes(columns) {
|
|
|
6946
6983
|
}
|
|
6947
6984
|
|
|
6948
6985
|
const EditorRow = ({ children }) => {
|
|
6949
|
-
const styles = ui.useStyles2(getStyles$
|
|
6986
|
+
const styles = ui.useStyles2(getStyles$k);
|
|
6950
6987
|
return /* @__PURE__ */ React__default.default.createElement("div", { className: styles.root }, /* @__PURE__ */ React__default.default.createElement(EditorStack, { gap: 2 }, children));
|
|
6951
6988
|
};
|
|
6952
|
-
const getStyles$
|
|
6989
|
+
const getStyles$k = (theme) => {
|
|
6953
6990
|
return {
|
|
6954
6991
|
root: css.css({
|
|
6955
6992
|
padding: theme.spacing(1),
|
|
@@ -6963,12 +7000,12 @@ const EditorField = (props) => {
|
|
|
6963
7000
|
var _a;
|
|
6964
7001
|
const { label, optional, tooltip, children, width, ...fieldProps } = props;
|
|
6965
7002
|
const theme = ui.useTheme2();
|
|
6966
|
-
const styles = getStyles$
|
|
7003
|
+
const styles = getStyles$j(theme, width);
|
|
6967
7004
|
const childInputId = (fieldProps == null ? void 0 : fieldProps.htmlFor) || ((_a = ui.ReactUtils) == null ? void 0 : _a.getChildId(children));
|
|
6968
7005
|
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 }));
|
|
6969
7006
|
return /* @__PURE__ */ React__default.default.createElement("div", { className: styles.root }, /* @__PURE__ */ React__default.default.createElement(ui.Field, { className: styles.field, label: labelEl, ...fieldProps }, children));
|
|
6970
7007
|
};
|
|
6971
|
-
const getStyles$
|
|
7008
|
+
const getStyles$j = ui.stylesFactory((theme, width) => {
|
|
6972
7009
|
return {
|
|
6973
7010
|
root: css.css({
|
|
6974
7011
|
minWidth: theme.spacing(width != null ? width : 0)
|
|
@@ -6999,12 +7036,20 @@ const EditorRows = ({ children }) => {
|
|
|
6999
7036
|
return /* @__PURE__ */ React__default.default.createElement(EditorStack, { gap: 0.5, direction: "column" }, children);
|
|
7000
7037
|
};
|
|
7001
7038
|
|
|
7002
|
-
const VisualEditor = ({
|
|
7039
|
+
const VisualEditor = ({
|
|
7040
|
+
query,
|
|
7041
|
+
db,
|
|
7042
|
+
queryRowFilter,
|
|
7043
|
+
onChange,
|
|
7044
|
+
onValidate,
|
|
7045
|
+
language = "sql",
|
|
7046
|
+
range
|
|
7047
|
+
}) => {
|
|
7003
7048
|
const state = reactUse.useAsync(async () => {
|
|
7004
7049
|
const fields = await db.fields(query);
|
|
7005
7050
|
return fields;
|
|
7006
7051
|
}, [db, query.dataset, query.table]);
|
|
7007
|
-
return /* @__PURE__ */ React__default.default.createElement(React__default.default.Fragment, null, /* @__PURE__ */ React__default.default.createElement(EditorRows, null, /* @__PURE__ */ React__default.default.createElement(EditorRow, null, /* @__PURE__ */ React__default.default.createElement(SQLSelectRow, { fields: state.value || [], query, onQueryChange: onChange, db })), queryRowFilter.filter && /* @__PURE__ */ React__default.default.createElement(EditorRow, null, /* @__PURE__ */ React__default.default.createElement(EditorField, { label: "Filter by column value", optional: true }, /* @__PURE__ */ React__default.default.createElement(SQLWhereRow, { fields: state.value || [], query, onQueryChange: onChange, db }))), queryRowFilter.group && /* @__PURE__ */ React__default.default.createElement(EditorRow, null, /* @__PURE__ */ React__default.default.createElement(EditorField, { label: "Group by column" }, /* @__PURE__ */ React__default.default.createElement(SQLGroupByRow, { fields: state.value || [], query, onQueryChange: onChange, db }))), queryRowFilter.order && /* @__PURE__ */ React__default.default.createElement(EditorRow, null, /* @__PURE__ */ React__default.default.createElement(SQLOrderByRow, { fields: state.value || [], query, onQueryChange: onChange, db })), queryRowFilter.preview && query.rawSql && /* @__PURE__ */ React__default.default.createElement(EditorRow, null, /* @__PURE__ */ React__default.default.createElement(Preview, { rawSql: query.rawSql }))), /* @__PURE__ */ React__default.default.createElement(QueryToolbox, { db, query, onValidate, range }));
|
|
7052
|
+
return /* @__PURE__ */ React__default.default.createElement(React__default.default.Fragment, null, /* @__PURE__ */ React__default.default.createElement(EditorRows, null, /* @__PURE__ */ React__default.default.createElement(EditorRow, null, /* @__PURE__ */ React__default.default.createElement(SQLSelectRow, { fields: state.value || [], query, onQueryChange: onChange, db })), queryRowFilter.filter && /* @__PURE__ */ React__default.default.createElement(EditorRow, null, /* @__PURE__ */ React__default.default.createElement(EditorField, { label: "Filter by column value", optional: true }, /* @__PURE__ */ React__default.default.createElement(SQLWhereRow, { fields: state.value || [], query, onQueryChange: onChange, db }))), queryRowFilter.group && /* @__PURE__ */ React__default.default.createElement(EditorRow, null, /* @__PURE__ */ React__default.default.createElement(EditorField, { label: "Group by column" }, /* @__PURE__ */ React__default.default.createElement(SQLGroupByRow, { fields: state.value || [], query, onQueryChange: onChange, db }))), queryRowFilter.order && /* @__PURE__ */ React__default.default.createElement(EditorRow, null, /* @__PURE__ */ React__default.default.createElement(SQLOrderByRow, { fields: state.value || [], query, onQueryChange: onChange, db })), queryRowFilter.preview && query.rawSql && /* @__PURE__ */ React__default.default.createElement(EditorRow, null, /* @__PURE__ */ React__default.default.createElement(Preview, { rawSql: query.rawSql, language }))), /* @__PURE__ */ React__default.default.createElement(QueryToolbox, { db, query, onValidate, range }));
|
|
7008
7053
|
};
|
|
7009
7054
|
|
|
7010
7055
|
const MACRO_NAMES = [
|
|
@@ -7023,20 +7068,20 @@ const MACRO_NAMES = [
|
|
|
7023
7068
|
"$__unixEpochGroupAlias"
|
|
7024
7069
|
];
|
|
7025
7070
|
|
|
7026
|
-
var __defProp$
|
|
7027
|
-
var __defNormalProp$
|
|
7028
|
-
var __publicField$
|
|
7071
|
+
var __defProp$3 = Object.defineProperty;
|
|
7072
|
+
var __defNormalProp$3 = (obj, key, value) => key in obj ? __defProp$3(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
7073
|
+
var __publicField$3 = (obj, key, value) => __defNormalProp$3(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
7029
7074
|
class SqlDatasource extends runtime.DataSourceWithBackend {
|
|
7030
7075
|
constructor(instanceSettings, templateSrv = runtime.getTemplateSrv()) {
|
|
7031
7076
|
super(instanceSettings);
|
|
7032
7077
|
this.templateSrv = templateSrv;
|
|
7033
|
-
__publicField$
|
|
7034
|
-
__publicField$
|
|
7035
|
-
__publicField$
|
|
7036
|
-
__publicField$
|
|
7037
|
-
__publicField$
|
|
7038
|
-
__publicField$
|
|
7039
|
-
__publicField$
|
|
7078
|
+
__publicField$3(this, "id");
|
|
7079
|
+
__publicField$3(this, "name");
|
|
7080
|
+
__publicField$3(this, "interval");
|
|
7081
|
+
__publicField$3(this, "db");
|
|
7082
|
+
__publicField$3(this, "dataset");
|
|
7083
|
+
__publicField$3(this, "annotations", {});
|
|
7084
|
+
__publicField$3(this, "interpolateVariable", (value, variable) => {
|
|
7040
7085
|
if (typeof value === "string") {
|
|
7041
7086
|
if (variable.multi || variable.includeAll) {
|
|
7042
7087
|
const result = this.getQueryModel().quoteLiteral(value);
|
|
@@ -7186,7 +7231,7 @@ const getSearchFilterScopedVar = (args) => {
|
|
|
7186
7231
|
};
|
|
7187
7232
|
};
|
|
7188
7233
|
|
|
7189
|
-
function SqlQueryEditor({ datasource, query, onChange, onRunQuery, range }) {
|
|
7234
|
+
function SqlQueryEditor({ datasource, query, onChange, onRunQuery, range, language = "sql" }) {
|
|
7190
7235
|
var _a, _b, _c, _d, _e, _f, _g;
|
|
7191
7236
|
const [isQueryRunnable, setIsQueryRunnable] = React.useState(true);
|
|
7192
7237
|
const db = datasource.getDB();
|
|
@@ -7262,6 +7307,7 @@ function SqlQueryEditor({ datasource, query, onChange, onRunQuery, range }) {
|
|
|
7262
7307
|
{
|
|
7263
7308
|
db,
|
|
7264
7309
|
query: queryWithDefaults,
|
|
7310
|
+
language,
|
|
7265
7311
|
onChange: (q) => onQueryChange(q, false),
|
|
7266
7312
|
queryRowFilter,
|
|
7267
7313
|
onValidate: setIsQueryRunnable,
|
|
@@ -7271,6 +7317,7 @@ function SqlQueryEditor({ datasource, query, onChange, onRunQuery, range }) {
|
|
|
7271
7317
|
RawEditor,
|
|
7272
7318
|
{
|
|
7273
7319
|
db,
|
|
7320
|
+
language,
|
|
7274
7321
|
query: queryWithDefaults,
|
|
7275
7322
|
queryToValidate,
|
|
7276
7323
|
onChange: onQueryChange,
|
|
@@ -7408,7 +7455,7 @@ const ConfigSubSection = ({ children, ...props }) => {
|
|
|
7408
7455
|
function ConfigDescriptionLink(props) {
|
|
7409
7456
|
const { description, suffix, feature } = props;
|
|
7410
7457
|
const text = `Learn more about ${feature}`;
|
|
7411
|
-
const styles = ui.useStyles2(getStyles$
|
|
7458
|
+
const styles = ui.useStyles2(getStyles$i);
|
|
7412
7459
|
return /* @__PURE__ */ React__default.default.createElement("span", { className: styles.container }, description, /* @__PURE__ */ React__default.default.createElement(
|
|
7413
7460
|
"a",
|
|
7414
7461
|
{
|
|
@@ -7420,7 +7467,7 @@ function ConfigDescriptionLink(props) {
|
|
|
7420
7467
|
text
|
|
7421
7468
|
));
|
|
7422
7469
|
}
|
|
7423
|
-
const getStyles$
|
|
7470
|
+
const getStyles$i = (theme) => {
|
|
7424
7471
|
return {
|
|
7425
7472
|
container: css.css({
|
|
7426
7473
|
color: theme.colors.text.secondary,
|
|
@@ -8389,6 +8436,2545 @@ const AdvancedHttpSettings = ({
|
|
|
8389
8436
|
));
|
|
8390
8437
|
};
|
|
8391
8438
|
|
|
8439
|
+
const SECURE_FIELD_CONFIGURED = "__CONFIGURED__";
|
|
8440
|
+
function resolveSecureKeyTemplate(template, item, index) {
|
|
8441
|
+
return template.replace(/\{index1\}/g, String(index + 1)).replace(/\{index\}/g, String(index)).replace(/\{item\.(\w+)\}/g, (_, key) => {
|
|
8442
|
+
var _a;
|
|
8443
|
+
return String((_a = item[key]) != null ? _a : "");
|
|
8444
|
+
});
|
|
8445
|
+
}
|
|
8446
|
+
function evaluateItemCondition(condition, item) {
|
|
8447
|
+
const trimmed = condition.trim();
|
|
8448
|
+
if (trimmed === "true") {
|
|
8449
|
+
return true;
|
|
8450
|
+
}
|
|
8451
|
+
const match = trimmed.match(/^item\.(\w+)\s*==\s*(.+)$/);
|
|
8452
|
+
if (!match) {
|
|
8453
|
+
return false;
|
|
8454
|
+
}
|
|
8455
|
+
const [, key, rawValue] = match;
|
|
8456
|
+
const actualValue = item[key];
|
|
8457
|
+
const expected = rawValue.trim();
|
|
8458
|
+
if (expected === "true") {
|
|
8459
|
+
return actualValue === true;
|
|
8460
|
+
}
|
|
8461
|
+
if (expected === "false") {
|
|
8462
|
+
return actualValue === false;
|
|
8463
|
+
}
|
|
8464
|
+
const unquoted = expected.replace(/^['"]|['"]$/g, "");
|
|
8465
|
+
return String(actualValue) === unquoted;
|
|
8466
|
+
}
|
|
8467
|
+
function findActiveSecureOverride(itemFields, item, index) {
|
|
8468
|
+
for (const field of itemFields) {
|
|
8469
|
+
if (!field.overrides) {
|
|
8470
|
+
continue;
|
|
8471
|
+
}
|
|
8472
|
+
for (const override of field.overrides) {
|
|
8473
|
+
if (!override.secureKey) {
|
|
8474
|
+
continue;
|
|
8475
|
+
}
|
|
8476
|
+
if (evaluateItemCondition(override.when, item)) {
|
|
8477
|
+
return {
|
|
8478
|
+
fieldKey: field.key,
|
|
8479
|
+
resolvedKey: resolveSecureKeyTemplate(override.secureKey, item, index)
|
|
8480
|
+
};
|
|
8481
|
+
}
|
|
8482
|
+
}
|
|
8483
|
+
}
|
|
8484
|
+
return null;
|
|
8485
|
+
}
|
|
8486
|
+
function patternToRegex(pattern) {
|
|
8487
|
+
const escaped = pattern.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
8488
|
+
return new RegExp("^" + escaped.replace("\\{index\\}", "(\\d+)") + "$");
|
|
8489
|
+
}
|
|
8490
|
+
function findIndicesForPattern(record, pattern) {
|
|
8491
|
+
const re = patternToRegex(pattern);
|
|
8492
|
+
const indices = [];
|
|
8493
|
+
for (const key of Object.keys(record)) {
|
|
8494
|
+
const m = key.match(re);
|
|
8495
|
+
if (m) {
|
|
8496
|
+
const n = Number(m[1]);
|
|
8497
|
+
if (!Number.isNaN(n)) {
|
|
8498
|
+
indices.push(n);
|
|
8499
|
+
}
|
|
8500
|
+
}
|
|
8501
|
+
}
|
|
8502
|
+
return indices.sort((a, b) => a - b);
|
|
8503
|
+
}
|
|
8504
|
+
function expandIndexedPair(field, ds) {
|
|
8505
|
+
var _a, _b, _c;
|
|
8506
|
+
const storage = field.storage;
|
|
8507
|
+
if ((storage == null ? void 0 : storage.type) !== "indexedPair" || !storage.key || !storage.value) {
|
|
8508
|
+
return [];
|
|
8509
|
+
}
|
|
8510
|
+
const source = storage.key.target === "jsonData" ? (_a = ds.jsonData) != null ? _a : {} : ds;
|
|
8511
|
+
const indices = findIndicesForPattern(source, storage.key.pattern);
|
|
8512
|
+
const items = [];
|
|
8513
|
+
for (const i of indices) {
|
|
8514
|
+
const nameKey = storage.key.pattern.replace("{index}", String(i));
|
|
8515
|
+
const valueKey = storage.value.pattern.replace("{index}", String(i));
|
|
8516
|
+
const nameVal = source[nameKey];
|
|
8517
|
+
if (nameVal === void 0 || nameVal === null) {
|
|
8518
|
+
continue;
|
|
8519
|
+
}
|
|
8520
|
+
const hasValue = storage.value.target === "secureJsonData" ? !!((_b = ds.secureJsonFields) == null ? void 0 : _b[valueKey]) : !!((_c = ds.jsonData) == null ? void 0 : _c[valueKey]);
|
|
8521
|
+
items.push({
|
|
8522
|
+
index: i,
|
|
8523
|
+
name: String(nameVal),
|
|
8524
|
+
value: hasValue ? SECURE_FIELD_CONFIGURED : ""
|
|
8525
|
+
});
|
|
8526
|
+
}
|
|
8527
|
+
return items;
|
|
8528
|
+
}
|
|
8529
|
+
function flattenIndexedPair(field, items, jsonData, secureJsonData, secureJsonFields) {
|
|
8530
|
+
var _a;
|
|
8531
|
+
const storage = field.storage;
|
|
8532
|
+
if ((storage == null ? void 0 : storage.type) !== "indexedPair" || !storage.key || !storage.value) {
|
|
8533
|
+
return;
|
|
8534
|
+
}
|
|
8535
|
+
const existingIndices = new Set(
|
|
8536
|
+
storage.key.target === "jsonData" ? findIndicesForPattern(jsonData, storage.key.pattern) : []
|
|
8537
|
+
);
|
|
8538
|
+
const usedIndices = /* @__PURE__ */ new Set();
|
|
8539
|
+
const startIdx = (_a = storage.startIndex) != null ? _a : 1;
|
|
8540
|
+
let nextIndex = existingIndices.size > 0 ? Math.max(...existingIndices) + 1 : startIdx;
|
|
8541
|
+
for (const item of items) {
|
|
8542
|
+
let idx = item.index;
|
|
8543
|
+
if (idx === 0) {
|
|
8544
|
+
idx = nextIndex++;
|
|
8545
|
+
}
|
|
8546
|
+
usedIndices.add(idx);
|
|
8547
|
+
const nameKey = storage.key.pattern.replace("{index}", String(idx));
|
|
8548
|
+
const valueKey = storage.value.pattern.replace("{index}", String(idx));
|
|
8549
|
+
if (storage.key.target === "jsonData") {
|
|
8550
|
+
jsonData[nameKey] = item.name;
|
|
8551
|
+
}
|
|
8552
|
+
if (storage.value.target === "secureJsonData") {
|
|
8553
|
+
if (item.value === SECURE_FIELD_CONFIGURED) {
|
|
8554
|
+
secureJsonFields[valueKey] = true;
|
|
8555
|
+
} else if (item.value) {
|
|
8556
|
+
secureJsonData[valueKey] = item.value;
|
|
8557
|
+
secureJsonFields[valueKey] = false;
|
|
8558
|
+
}
|
|
8559
|
+
} else if (storage.value.target === "jsonData") {
|
|
8560
|
+
jsonData[valueKey] = item.value;
|
|
8561
|
+
}
|
|
8562
|
+
}
|
|
8563
|
+
for (const idx of existingIndices) {
|
|
8564
|
+
if (usedIndices.has(idx)) {
|
|
8565
|
+
continue;
|
|
8566
|
+
}
|
|
8567
|
+
const nameKey = storage.key.pattern.replace("{index}", String(idx));
|
|
8568
|
+
const valueKey = storage.value.pattern.replace("{index}", String(idx));
|
|
8569
|
+
if (storage.key.target === "jsonData") {
|
|
8570
|
+
delete jsonData[nameKey];
|
|
8571
|
+
}
|
|
8572
|
+
if (storage.value.target === "secureJsonData") {
|
|
8573
|
+
delete secureJsonFields[valueKey];
|
|
8574
|
+
delete secureJsonData[valueKey];
|
|
8575
|
+
} else if (storage.value.target === "jsonData") {
|
|
8576
|
+
delete jsonData[valueKey];
|
|
8577
|
+
}
|
|
8578
|
+
}
|
|
8579
|
+
}
|
|
8580
|
+
function resolveRawPath(ref, ds) {
|
|
8581
|
+
var _a;
|
|
8582
|
+
const trimmed = ref.trim();
|
|
8583
|
+
if (trimmed.startsWith("jsonData.")) {
|
|
8584
|
+
return (_a = ds.jsonData) == null ? void 0 : _a[trimmed.slice(9)];
|
|
8585
|
+
}
|
|
8586
|
+
if (trimmed.startsWith("root.")) {
|
|
8587
|
+
return ds[trimmed.slice(5)];
|
|
8588
|
+
}
|
|
8589
|
+
return void 0;
|
|
8590
|
+
}
|
|
8591
|
+
async function fetchExistingValues(dsUid, fields) {
|
|
8592
|
+
var _a, _b, _c, _d, _e, _f;
|
|
8593
|
+
try {
|
|
8594
|
+
const ds = await runtime.getBackendSrv().get(`/api/datasources/uid/${dsUid}`, void 0, void 0, {
|
|
8595
|
+
showErrorAlert: false
|
|
8596
|
+
});
|
|
8597
|
+
const values = {};
|
|
8598
|
+
for (const field of fields) {
|
|
8599
|
+
if (((_a = field.storage) == null ? void 0 : _a.type) === "indexedPair") {
|
|
8600
|
+
values[field.key] = expandIndexedPair(field, ds);
|
|
8601
|
+
continue;
|
|
8602
|
+
}
|
|
8603
|
+
const fk = useDatasourceSchema.formKey(field);
|
|
8604
|
+
switch (field.target) {
|
|
8605
|
+
case "root":
|
|
8606
|
+
if (ds[field.key] !== void 0) {
|
|
8607
|
+
values[fk] = ds[field.key];
|
|
8608
|
+
}
|
|
8609
|
+
break;
|
|
8610
|
+
case "jsonData":
|
|
8611
|
+
if (field.section) {
|
|
8612
|
+
const sectionObj = (_b = ds.jsonData) == null ? void 0 : _b[field.section];
|
|
8613
|
+
if ((sectionObj == null ? void 0 : sectionObj[field.key]) !== void 0) {
|
|
8614
|
+
values[fk] = sectionObj[field.key];
|
|
8615
|
+
}
|
|
8616
|
+
} else if (((_c = ds.jsonData) == null ? void 0 : _c[field.key]) !== void 0) {
|
|
8617
|
+
values[fk] = ds.jsonData[field.key];
|
|
8618
|
+
}
|
|
8619
|
+
break;
|
|
8620
|
+
case "secureJsonData":
|
|
8621
|
+
if ((_d = ds.secureJsonFields) == null ? void 0 : _d[field.key]) {
|
|
8622
|
+
values[fk] = SECURE_FIELD_CONFIGURED;
|
|
8623
|
+
}
|
|
8624
|
+
break;
|
|
8625
|
+
}
|
|
8626
|
+
if (values[fk] === void 0 && ((_e = field.storage) == null ? void 0 : _e.type) === "computed" && field.storage.read) {
|
|
8627
|
+
const fallback = resolveRawPath(field.storage.read, ds);
|
|
8628
|
+
if (fallback !== void 0) {
|
|
8629
|
+
values[fk] = fallback;
|
|
8630
|
+
}
|
|
8631
|
+
}
|
|
8632
|
+
}
|
|
8633
|
+
for (const field of fields) {
|
|
8634
|
+
if (field.valueType !== "array" || !((_f = field.item) == null ? void 0 : _f.fields)) {
|
|
8635
|
+
continue;
|
|
8636
|
+
}
|
|
8637
|
+
const itemFields = field.item.fields;
|
|
8638
|
+
const hasSecureOverride = itemFields.some((f) => {
|
|
8639
|
+
var _a2;
|
|
8640
|
+
return (_a2 = f.overrides) == null ? void 0 : _a2.some((o) => o.secureKey);
|
|
8641
|
+
});
|
|
8642
|
+
if (!hasSecureOverride) {
|
|
8643
|
+
continue;
|
|
8644
|
+
}
|
|
8645
|
+
const fk = useDatasourceSchema.formKey(field);
|
|
8646
|
+
const arr = values[fk];
|
|
8647
|
+
if (!Array.isArray(arr)) {
|
|
8648
|
+
continue;
|
|
8649
|
+
}
|
|
8650
|
+
values[fk] = arr.map((item, idx) => {
|
|
8651
|
+
var _a2;
|
|
8652
|
+
const match = findActiveSecureOverride(itemFields, item, idx);
|
|
8653
|
+
if (match && ((_a2 = ds.secureJsonFields) == null ? void 0 : _a2[match.resolvedKey])) {
|
|
8654
|
+
return { ...item, [match.fieldKey]: SECURE_FIELD_CONFIGURED };
|
|
8655
|
+
}
|
|
8656
|
+
return item;
|
|
8657
|
+
});
|
|
8658
|
+
}
|
|
8659
|
+
return { values, readOnly: !!ds.readOnly };
|
|
8660
|
+
} catch (err) {
|
|
8661
|
+
const message = err instanceof Error ? err.message : "Failed to load datasource configuration";
|
|
8662
|
+
return { values: {}, readOnly: false, error: message };
|
|
8663
|
+
}
|
|
8664
|
+
}
|
|
8665
|
+
function buildDatasourceConfigPayload(data, fields, existing, isFieldVisible) {
|
|
8666
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
8667
|
+
const rootFields = {};
|
|
8668
|
+
const jsonData = { ...(_a = existing.jsonData) != null ? _a : {} };
|
|
8669
|
+
const secureJsonData = {};
|
|
8670
|
+
const secureJsonFields = { ...(_b = existing.secureJsonFields) != null ? _b : {} };
|
|
8671
|
+
for (const field of fields) {
|
|
8672
|
+
if (((_c = field.storage) == null ? void 0 : _c.type) === "indexedPair") {
|
|
8673
|
+
const items = Array.isArray(data[field.key]) ? data[field.key] : [];
|
|
8674
|
+
flattenIndexedPair(field, items, jsonData, secureJsonData, secureJsonFields);
|
|
8675
|
+
continue;
|
|
8676
|
+
}
|
|
8677
|
+
const isManagedByEffect = (_d = field.tags) == null ? void 0 : _d.some((t) => t.startsWith("managed-by:"));
|
|
8678
|
+
if (!isManagedByEffect && !isFieldVisible(field)) {
|
|
8679
|
+
continue;
|
|
8680
|
+
}
|
|
8681
|
+
const fk = useDatasourceSchema.formKey(field);
|
|
8682
|
+
const value = data[fk];
|
|
8683
|
+
if (field.target === "secureJsonData") {
|
|
8684
|
+
if (value === SECURE_FIELD_CONFIGURED) {
|
|
8685
|
+
secureJsonFields[field.key] = true;
|
|
8686
|
+
continue;
|
|
8687
|
+
}
|
|
8688
|
+
if (value && value !== "") {
|
|
8689
|
+
secureJsonData[field.key] = String(value);
|
|
8690
|
+
secureJsonFields[field.key] = false;
|
|
8691
|
+
} else {
|
|
8692
|
+
secureJsonFields[field.key] = false;
|
|
8693
|
+
}
|
|
8694
|
+
continue;
|
|
8695
|
+
}
|
|
8696
|
+
if (value === void 0 || value === "") {
|
|
8697
|
+
continue;
|
|
8698
|
+
}
|
|
8699
|
+
switch (field.target) {
|
|
8700
|
+
case "root":
|
|
8701
|
+
rootFields[field.key] = value;
|
|
8702
|
+
break;
|
|
8703
|
+
case "jsonData":
|
|
8704
|
+
if (field.section) {
|
|
8705
|
+
if (!jsonData[field.section] || typeof jsonData[field.section] !== "object") {
|
|
8706
|
+
jsonData[field.section] = {};
|
|
8707
|
+
}
|
|
8708
|
+
jsonData[field.section][field.key] = value;
|
|
8709
|
+
} else {
|
|
8710
|
+
jsonData[field.key] = value;
|
|
8711
|
+
}
|
|
8712
|
+
break;
|
|
8713
|
+
}
|
|
8714
|
+
}
|
|
8715
|
+
for (const field of fields) {
|
|
8716
|
+
if (field.valueType !== "array" || !((_e = field.item) == null ? void 0 : _e.fields) || field.target !== "jsonData") {
|
|
8717
|
+
continue;
|
|
8718
|
+
}
|
|
8719
|
+
const itemFields = field.item.fields;
|
|
8720
|
+
const hasSecureOverride = itemFields.some((f) => {
|
|
8721
|
+
var _a2;
|
|
8722
|
+
return (_a2 = f.overrides) == null ? void 0 : _a2.some((o) => o.secureKey);
|
|
8723
|
+
});
|
|
8724
|
+
if (!hasSecureOverride) {
|
|
8725
|
+
continue;
|
|
8726
|
+
}
|
|
8727
|
+
const arr = field.section ? (_f = jsonData[field.section]) == null ? void 0 : _f[field.key] : jsonData[field.key];
|
|
8728
|
+
if (!Array.isArray(arr)) {
|
|
8729
|
+
continue;
|
|
8730
|
+
}
|
|
8731
|
+
const secureKeyOverrides = [];
|
|
8732
|
+
for (const f of itemFields) {
|
|
8733
|
+
for (const o of (_g = f.overrides) != null ? _g : []) {
|
|
8734
|
+
if (o.secureKey) {
|
|
8735
|
+
secureKeyOverrides.push({ fieldKey: f.key, override: o });
|
|
8736
|
+
}
|
|
8737
|
+
}
|
|
8738
|
+
}
|
|
8739
|
+
const activeSecureKeys = /* @__PURE__ */ new Set();
|
|
8740
|
+
for (let i = 0; i < arr.length; i++) {
|
|
8741
|
+
const item = arr[i];
|
|
8742
|
+
const match = findActiveSecureOverride(itemFields, item, i);
|
|
8743
|
+
if (!match) {
|
|
8744
|
+
continue;
|
|
8745
|
+
}
|
|
8746
|
+
const resolvedKey = match.resolvedKey;
|
|
8747
|
+
activeSecureKeys.add(resolvedKey);
|
|
8748
|
+
const itemValue = item[match.fieldKey];
|
|
8749
|
+
if (itemValue === SECURE_FIELD_CONFIGURED) {
|
|
8750
|
+
secureJsonFields[resolvedKey] = true;
|
|
8751
|
+
} else if (itemValue && itemValue !== "") {
|
|
8752
|
+
secureJsonData[resolvedKey] = String(itemValue);
|
|
8753
|
+
secureJsonFields[resolvedKey] = false;
|
|
8754
|
+
item[match.fieldKey] = "";
|
|
8755
|
+
}
|
|
8756
|
+
}
|
|
8757
|
+
const existingSecureFields = (_h = existing.secureJsonFields) != null ? _h : {};
|
|
8758
|
+
for (const existingKey of Object.keys(existingSecureFields)) {
|
|
8759
|
+
const couldBeFromThisField = secureKeyOverrides.some((sko) => {
|
|
8760
|
+
const staticPrefix = sko.override.secureKey.split("{")[0];
|
|
8761
|
+
return staticPrefix && existingKey.startsWith(staticPrefix);
|
|
8762
|
+
});
|
|
8763
|
+
if (couldBeFromThisField && !activeSecureKeys.has(existingKey)) {
|
|
8764
|
+
secureJsonFields[existingKey] = false;
|
|
8765
|
+
secureJsonData[existingKey] = "";
|
|
8766
|
+
}
|
|
8767
|
+
}
|
|
8768
|
+
}
|
|
8769
|
+
return { rootFields, jsonData, secureJsonData, secureJsonFields };
|
|
8770
|
+
}
|
|
8771
|
+
async function submitDatasourceConfig(dsUid, data, fields, isFieldVisible) {
|
|
8772
|
+
const existing = await runtime.getBackendSrv().get(`/api/datasources/uid/${dsUid}`);
|
|
8773
|
+
const { rootFields, jsonData, secureJsonData, secureJsonFields } = buildDatasourceConfigPayload(
|
|
8774
|
+
data,
|
|
8775
|
+
fields,
|
|
8776
|
+
existing,
|
|
8777
|
+
isFieldVisible
|
|
8778
|
+
);
|
|
8779
|
+
await runtime.getBackendSrv().put(`/api/datasources/uid/${dsUid}`, {
|
|
8780
|
+
...existing,
|
|
8781
|
+
...rootFields,
|
|
8782
|
+
jsonData,
|
|
8783
|
+
secureJsonData,
|
|
8784
|
+
secureJsonFields
|
|
8785
|
+
});
|
|
8786
|
+
}
|
|
8787
|
+
|
|
8788
|
+
function evaluateEffectCondition(when, fieldValue) {
|
|
8789
|
+
var _a, _b;
|
|
8790
|
+
const m = when.match(/^value\s*(==|!=)\s*(?:'([^']*)'|"([^"]*)"|(.+))$/);
|
|
8791
|
+
if (!m) {
|
|
8792
|
+
return false;
|
|
8793
|
+
}
|
|
8794
|
+
const op = m[1];
|
|
8795
|
+
let target = (_b = (_a = m[2]) != null ? _a : m[3]) != null ? _b : m[4];
|
|
8796
|
+
if (target === "true") {
|
|
8797
|
+
target = true;
|
|
8798
|
+
} else if (target === "false") {
|
|
8799
|
+
target = false;
|
|
8800
|
+
} else if (typeof target === "string" && /^-?\d+(\.\d+)?$/.test(target)) {
|
|
8801
|
+
target = Number(target);
|
|
8802
|
+
}
|
|
8803
|
+
const eq = String(fieldValue) === String(target);
|
|
8804
|
+
return op === "==" ? eq : !eq;
|
|
8805
|
+
}
|
|
8806
|
+
function isFieldRequired(field, watchedValues, fieldById, celContext) {
|
|
8807
|
+
if (field.required) {
|
|
8808
|
+
return true;
|
|
8809
|
+
}
|
|
8810
|
+
if (field.requiredWhen) {
|
|
8811
|
+
if (celContext) {
|
|
8812
|
+
return useDatasourceSchema.evaluateCelExpression(field.requiredWhen, celContext);
|
|
8813
|
+
}
|
|
8814
|
+
const parsed = useDatasourceSchema.parseDependsOn(field.requiredWhen);
|
|
8815
|
+
if (parsed) {
|
|
8816
|
+
const depField = fieldById.get(parsed.field);
|
|
8817
|
+
const depKey = depField ? useDatasourceSchema.formKey(depField) : parsed.field;
|
|
8818
|
+
return useDatasourceSchema.evaluateDependsOn(parsed, useDatasourceSchema.getWatchedValue(watchedValues, depKey));
|
|
8819
|
+
}
|
|
8820
|
+
}
|
|
8821
|
+
return false;
|
|
8822
|
+
}
|
|
8823
|
+
function buildValidationRules(field, required) {
|
|
8824
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
8825
|
+
const rules = {};
|
|
8826
|
+
const label = (_a = field.label) != null ? _a : field.key;
|
|
8827
|
+
if (required) {
|
|
8828
|
+
if (field.target === "secureJsonData") {
|
|
8829
|
+
rules.validate = (value) => {
|
|
8830
|
+
if (value === SECURE_FIELD_CONFIGURED) {
|
|
8831
|
+
return true;
|
|
8832
|
+
}
|
|
8833
|
+
if (!value || value === "") {
|
|
8834
|
+
return `${label} is required`;
|
|
8835
|
+
}
|
|
8836
|
+
return true;
|
|
8837
|
+
};
|
|
8838
|
+
} else {
|
|
8839
|
+
rules.required = `${label} is required`;
|
|
8840
|
+
}
|
|
8841
|
+
}
|
|
8842
|
+
if (field.valueType === "array" && ((_b = field.item) == null ? void 0 : _b.valueType) === "object" && ((_c = field.item.fields) == null ? void 0 : _c.length)) {
|
|
8843
|
+
const requiredItemFields = field.item.fields.filter((f) => f.required);
|
|
8844
|
+
if (requiredItemFields.length > 0) {
|
|
8845
|
+
const existingValidate = rules.validate;
|
|
8846
|
+
rules.validate = (value) => {
|
|
8847
|
+
var _a2;
|
|
8848
|
+
if (existingValidate) {
|
|
8849
|
+
const r = existingValidate(value);
|
|
8850
|
+
if (r !== true) {
|
|
8851
|
+
return r;
|
|
8852
|
+
}
|
|
8853
|
+
}
|
|
8854
|
+
if (!Array.isArray(value)) {
|
|
8855
|
+
return true;
|
|
8856
|
+
}
|
|
8857
|
+
const itemErrors = {};
|
|
8858
|
+
for (let i = 0; i < value.length; i++) {
|
|
8859
|
+
const item = value[i];
|
|
8860
|
+
const missing = [];
|
|
8861
|
+
for (const rf of requiredItemFields) {
|
|
8862
|
+
const v = item[rf.key];
|
|
8863
|
+
if (v === void 0 || v === null || v === "") {
|
|
8864
|
+
missing.push((_a2 = rf.label) != null ? _a2 : rf.key);
|
|
8865
|
+
}
|
|
8866
|
+
}
|
|
8867
|
+
if (missing.length > 0) {
|
|
8868
|
+
itemErrors[i] = `${missing.join(", ")} required`;
|
|
8869
|
+
}
|
|
8870
|
+
}
|
|
8871
|
+
if (Object.keys(itemErrors).length === 0) {
|
|
8872
|
+
return true;
|
|
8873
|
+
}
|
|
8874
|
+
return `__ITEM_ERRORS__${JSON.stringify(itemErrors)}`;
|
|
8875
|
+
};
|
|
8876
|
+
}
|
|
8877
|
+
}
|
|
8878
|
+
if (field.validations) {
|
|
8879
|
+
for (const v of field.validations) {
|
|
8880
|
+
switch (v.type) {
|
|
8881
|
+
case "pattern":
|
|
8882
|
+
rules.pattern = {
|
|
8883
|
+
value: new RegExp(v.pattern),
|
|
8884
|
+
message: (_d = v.message) != null ? _d : `Invalid ${label}`
|
|
8885
|
+
};
|
|
8886
|
+
break;
|
|
8887
|
+
case "range":
|
|
8888
|
+
if (v.min !== void 0) {
|
|
8889
|
+
rules.min = { value: v.min, message: (_e = v.message) != null ? _e : `Minimum value is ${v.min}` };
|
|
8890
|
+
}
|
|
8891
|
+
if (v.max !== void 0) {
|
|
8892
|
+
rules.max = { value: v.max, message: (_f = v.message) != null ? _f : `Maximum value is ${v.max}` };
|
|
8893
|
+
}
|
|
8894
|
+
break;
|
|
8895
|
+
case "length":
|
|
8896
|
+
if (v.min !== void 0) {
|
|
8897
|
+
rules.minLength = { value: v.min, message: (_g = v.message) != null ? _g : `Minimum length is ${v.min}` };
|
|
8898
|
+
}
|
|
8899
|
+
if (v.max !== void 0) {
|
|
8900
|
+
rules.maxLength = { value: v.max, message: (_h = v.message) != null ? _h : `Maximum length is ${v.max}` };
|
|
8901
|
+
}
|
|
8902
|
+
break;
|
|
8903
|
+
}
|
|
8904
|
+
}
|
|
8905
|
+
}
|
|
8906
|
+
return rules;
|
|
8907
|
+
}
|
|
8908
|
+
const ITEM_ERRORS_PREFIX = "__ITEM_ERRORS__";
|
|
8909
|
+
function parseItemErrors(errorMessage) {
|
|
8910
|
+
if (!errorMessage || !errorMessage.startsWith(ITEM_ERRORS_PREFIX)) {
|
|
8911
|
+
return null;
|
|
8912
|
+
}
|
|
8913
|
+
try {
|
|
8914
|
+
return JSON.parse(errorMessage.slice(ITEM_ERRORS_PREFIX.length));
|
|
8915
|
+
} catch (e) {
|
|
8916
|
+
return null;
|
|
8917
|
+
}
|
|
8918
|
+
}
|
|
8919
|
+
|
|
8920
|
+
const PdcFieldNote = (props) => {
|
|
8921
|
+
const { enabled, description, configUrl } = props;
|
|
8922
|
+
const styles = ui.useStyles2(getStyles$h);
|
|
8923
|
+
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"));
|
|
8924
|
+
};
|
|
8925
|
+
const getStyles$h = (theme) => ({
|
|
8926
|
+
wrapper: css.css({
|
|
8927
|
+
display: "flex",
|
|
8928
|
+
alignItems: "center",
|
|
8929
|
+
justifyContent: "space-between",
|
|
8930
|
+
gap: theme.spacing(1),
|
|
8931
|
+
padding: `${theme.spacing(0.5)} ${theme.spacing(0.75)}`,
|
|
8932
|
+
fontSize: theme.typography.bodySmall.fontSize,
|
|
8933
|
+
color: theme.colors.text.secondary,
|
|
8934
|
+
backgroundColor: theme.colors.background.secondary,
|
|
8935
|
+
borderRadius: theme.shape.radius.default,
|
|
8936
|
+
border: `1px solid ${theme.colors.border.weak}`
|
|
8937
|
+
}),
|
|
8938
|
+
note: css.css({
|
|
8939
|
+
display: "inline-flex",
|
|
8940
|
+
alignItems: "center",
|
|
8941
|
+
gap: theme.spacing(0.5)
|
|
8942
|
+
})
|
|
8943
|
+
});
|
|
8944
|
+
|
|
8945
|
+
function SecureFieldInput(props) {
|
|
8946
|
+
var _a;
|
|
8947
|
+
const { formField, placeholder, disabled } = props;
|
|
8948
|
+
const isConfigured = formField.value === SECURE_FIELD_CONFIGURED;
|
|
8949
|
+
const [revealed, setRevealed] = React.useState(false);
|
|
8950
|
+
const styles = ui.useStyles2(getSecureFieldStyles);
|
|
8951
|
+
if (isConfigured) {
|
|
8952
|
+
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"));
|
|
8953
|
+
}
|
|
8954
|
+
return /* @__PURE__ */ React__default.default.createElement(
|
|
8955
|
+
ui.Input,
|
|
8956
|
+
{
|
|
8957
|
+
...formField,
|
|
8958
|
+
value: String((_a = formField.value) != null ? _a : ""),
|
|
8959
|
+
type: revealed ? "text" : "password",
|
|
8960
|
+
placeholder,
|
|
8961
|
+
disabled,
|
|
8962
|
+
suffix: /* @__PURE__ */ React__default.default.createElement(
|
|
8963
|
+
ui.Button,
|
|
8964
|
+
{
|
|
8965
|
+
variant: "secondary",
|
|
8966
|
+
fill: "text",
|
|
8967
|
+
size: "sm",
|
|
8968
|
+
icon: revealed ? "eye-slash" : "eye",
|
|
8969
|
+
"aria-label": revealed ? "Hide" : "Reveal",
|
|
8970
|
+
onClick: () => setRevealed((r) => !r),
|
|
8971
|
+
type: "button"
|
|
8972
|
+
}
|
|
8973
|
+
)
|
|
8974
|
+
}
|
|
8975
|
+
);
|
|
8976
|
+
}
|
|
8977
|
+
const getSecureFieldStyles = (theme) => ({
|
|
8978
|
+
configuredRow: css.css({
|
|
8979
|
+
display: "flex",
|
|
8980
|
+
alignItems: "center",
|
|
8981
|
+
gap: theme.spacing(1),
|
|
8982
|
+
whiteSpace: "nowrap"
|
|
8983
|
+
}),
|
|
8984
|
+
configuredBadge: css.css({
|
|
8985
|
+
display: "inline-flex",
|
|
8986
|
+
alignItems: "center",
|
|
8987
|
+
gap: theme.spacing(0.5),
|
|
8988
|
+
padding: `${theme.spacing(0.25)} ${theme.spacing(0.75)}`,
|
|
8989
|
+
borderRadius: theme.shape.radius.pill,
|
|
8990
|
+
backgroundColor: theme.colors.success.transparent,
|
|
8991
|
+
color: theme.colors.success.text,
|
|
8992
|
+
fontSize: theme.typography.bodySmall.fontSize,
|
|
8993
|
+
whiteSpace: "nowrap"
|
|
8994
|
+
})
|
|
8995
|
+
});
|
|
8996
|
+
|
|
8997
|
+
const ComplexFieldNote = (props) => {
|
|
8998
|
+
const { count, label } = props;
|
|
8999
|
+
const styles = ui.useStyles2(getStyles$g);
|
|
9000
|
+
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."));
|
|
9001
|
+
};
|
|
9002
|
+
const getStyles$g = (theme) => ({
|
|
9003
|
+
note: css.css({
|
|
9004
|
+
display: "inline-flex",
|
|
9005
|
+
alignItems: "center",
|
|
9006
|
+
gap: theme.spacing(0.5),
|
|
9007
|
+
padding: `${theme.spacing(0.5)} ${theme.spacing(0.75)}`,
|
|
9008
|
+
fontSize: theme.typography.bodySmall.fontSize,
|
|
9009
|
+
color: theme.colors.text.secondary,
|
|
9010
|
+
backgroundColor: theme.colors.background.secondary,
|
|
9011
|
+
borderRadius: theme.shape.radius.default,
|
|
9012
|
+
border: `1px solid ${theme.colors.border.weak}`
|
|
9013
|
+
})
|
|
9014
|
+
});
|
|
9015
|
+
|
|
9016
|
+
function FileUploadField(props) {
|
|
9017
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
9018
|
+
const { field, formField, disabled, setValue } = props;
|
|
9019
|
+
const [mode, setModeLocal] = React.useState("upload");
|
|
9020
|
+
const [error, setError] = React.useState(null);
|
|
9021
|
+
const theme = ui.useTheme2();
|
|
9022
|
+
const mapping = (_a = field.ui) == null ? void 0 : _a.fileMapping;
|
|
9023
|
+
const accept = (_c = (_b = field.ui) == null ? void 0 : _b.accept) != null ? _c : [".json"];
|
|
9024
|
+
const setMode = React.useCallback(
|
|
9025
|
+
(next) => {
|
|
9026
|
+
setModeLocal(next);
|
|
9027
|
+
formField.onChange(next);
|
|
9028
|
+
},
|
|
9029
|
+
[formField]
|
|
9030
|
+
);
|
|
9031
|
+
const processJson = React.useCallback(
|
|
9032
|
+
(text) => {
|
|
9033
|
+
const fileMapping = mapping != null ? mapping : {};
|
|
9034
|
+
try {
|
|
9035
|
+
const parsed = JSON.parse(text);
|
|
9036
|
+
if (typeof parsed !== "object" || parsed === null) {
|
|
9037
|
+
setError("Invalid JSON object");
|
|
9038
|
+
return;
|
|
9039
|
+
}
|
|
9040
|
+
const requiredKeys = Object.keys(fileMapping);
|
|
9041
|
+
const missingKeys = requiredKeys.filter((k) => parsed[k] === void 0);
|
|
9042
|
+
if (missingKeys.length > 0) {
|
|
9043
|
+
setError(`Missing keys: ${missingKeys.join(", ")}`);
|
|
9044
|
+
return;
|
|
9045
|
+
}
|
|
9046
|
+
for (const [jsonKey, targetFieldId] of Object.entries(fileMapping)) {
|
|
9047
|
+
if (parsed[jsonKey] !== void 0) {
|
|
9048
|
+
const parts = targetFieldId.split(".");
|
|
9049
|
+
const fk = parts.length === 2 ? parts[1] : targetFieldId;
|
|
9050
|
+
setValue(fk, parsed[jsonKey]);
|
|
9051
|
+
}
|
|
9052
|
+
}
|
|
9053
|
+
setError(null);
|
|
9054
|
+
setModeLocal("manual");
|
|
9055
|
+
formField.onChange("manual");
|
|
9056
|
+
} catch (e) {
|
|
9057
|
+
setError("Invalid JSON");
|
|
9058
|
+
}
|
|
9059
|
+
},
|
|
9060
|
+
[mapping, setValue, formField]
|
|
9061
|
+
);
|
|
9062
|
+
const styles = getStyles$f(theme);
|
|
9063
|
+
if (mode === "manual") {
|
|
9064
|
+
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"));
|
|
9065
|
+
}
|
|
9066
|
+
if (mode === "paste") {
|
|
9067
|
+
return /* @__PURE__ */ React__default.default.createElement("div", null, /* @__PURE__ */ React__default.default.createElement(
|
|
9068
|
+
ui.TextArea,
|
|
9069
|
+
{
|
|
9070
|
+
placeholder: (_e = (_d = field.ui) == null ? void 0 : _d.placeholder) != null ? _e : "Paste Google JWT token here",
|
|
9071
|
+
rows: (_g = (_f = field.ui) == null ? void 0 : _f.rows) != null ? _g : 10,
|
|
9072
|
+
onBlur: (e) => {
|
|
9073
|
+
const val = e.currentTarget.value;
|
|
9074
|
+
if (val.trim()) {
|
|
9075
|
+
processJson(val);
|
|
9076
|
+
}
|
|
9077
|
+
},
|
|
9078
|
+
disabled
|
|
9079
|
+
}
|
|
9080
|
+
), /* @__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));
|
|
9081
|
+
}
|
|
9082
|
+
return /* @__PURE__ */ React__default.default.createElement("div", null, /* @__PURE__ */ React__default.default.createElement(
|
|
9083
|
+
ui.FileDropzone,
|
|
9084
|
+
{
|
|
9085
|
+
options: { multiple: false, accept: accept.join(",") },
|
|
9086
|
+
readAs: "readAsText",
|
|
9087
|
+
onLoad: (result) => {
|
|
9088
|
+
if (typeof result === "string") {
|
|
9089
|
+
processJson(result);
|
|
9090
|
+
}
|
|
9091
|
+
}
|
|
9092
|
+
}
|
|
9093
|
+
), /* @__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));
|
|
9094
|
+
}
|
|
9095
|
+
function getStyles$f(theme) {
|
|
9096
|
+
return {
|
|
9097
|
+
buttonRow: css.css({
|
|
9098
|
+
marginTop: theme.spacing(1),
|
|
9099
|
+
display: "flex",
|
|
9100
|
+
alignItems: "center",
|
|
9101
|
+
gap: theme.spacing(0.5)
|
|
9102
|
+
}),
|
|
9103
|
+
separator: css.css({
|
|
9104
|
+
padding: `0 ${theme.spacing(0.5)}`,
|
|
9105
|
+
color: theme.colors.text.secondary
|
|
9106
|
+
}),
|
|
9107
|
+
error: css.css({
|
|
9108
|
+
color: theme.colors.error.text,
|
|
9109
|
+
fontSize: theme.typography.bodySmall.fontSize,
|
|
9110
|
+
marginTop: theme.spacing(0.5),
|
|
9111
|
+
display: "block"
|
|
9112
|
+
})
|
|
9113
|
+
};
|
|
9114
|
+
}
|
|
9115
|
+
|
|
9116
|
+
const IndexedPairEditor = (props) => {
|
|
9117
|
+
const { value, onChange, maxItems = 10, disabled, hideControls, itemLabel = "header" } = props;
|
|
9118
|
+
const styles = ui.useStyles2(getStyles$e);
|
|
9119
|
+
const items = Array.isArray(value) ? value : [];
|
|
9120
|
+
const addItem = () => {
|
|
9121
|
+
if (items.length >= maxItems) {
|
|
9122
|
+
return;
|
|
9123
|
+
}
|
|
9124
|
+
onChange([...items, { index: 0, name: "", value: "" }]);
|
|
9125
|
+
};
|
|
9126
|
+
const removeItem = (index) => {
|
|
9127
|
+
onChange(items.filter((_, i) => i !== index));
|
|
9128
|
+
};
|
|
9129
|
+
const updateItem = (index, key, val) => {
|
|
9130
|
+
const updated = items.map((item, i) => i === index ? { ...item, [key]: val } : item);
|
|
9131
|
+
onChange(updated);
|
|
9132
|
+
};
|
|
9133
|
+
return /* @__PURE__ */ React__default.default.createElement(ui.Stack, { direction: "column", gap: 0.5 }, items.map((item, i) => /* @__PURE__ */ React__default.default.createElement(
|
|
9134
|
+
IndexedPairRow,
|
|
9135
|
+
{
|
|
9136
|
+
key: item.index || `new-${i}`,
|
|
9137
|
+
item,
|
|
9138
|
+
index: i,
|
|
9139
|
+
disabled,
|
|
9140
|
+
onUpdate: updateItem,
|
|
9141
|
+
onRemove: removeItem,
|
|
9142
|
+
hideControls,
|
|
9143
|
+
itemLabel
|
|
9144
|
+
}
|
|
9145
|
+
)), !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"));
|
|
9146
|
+
};
|
|
9147
|
+
const IndexedPairRow = (props) => {
|
|
9148
|
+
const { item, index, disabled, onUpdate, onRemove, hideControls, itemLabel = "header" } = props;
|
|
9149
|
+
const styles = ui.useStyles2(getStyles$e);
|
|
9150
|
+
const secureStyles = ui.useStyles2(getSecureFieldStyles);
|
|
9151
|
+
const isConfigured = item.value === SECURE_FIELD_CONFIGURED;
|
|
9152
|
+
const [editing, setEditing] = React.useState(false);
|
|
9153
|
+
const [revealed, setRevealed] = React.useState(false);
|
|
9154
|
+
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(
|
|
9155
|
+
ui.Input,
|
|
9156
|
+
{
|
|
9157
|
+
value: item.name,
|
|
9158
|
+
placeholder: "key",
|
|
9159
|
+
disabled: disabled || hideControls,
|
|
9160
|
+
onChange: (e) => onUpdate(index, "name", e.currentTarget.value),
|
|
9161
|
+
onKeyDown: (e) => {
|
|
9162
|
+
if (e.key === "Enter") {
|
|
9163
|
+
e.preventDefault();
|
|
9164
|
+
}
|
|
9165
|
+
}
|
|
9166
|
+
}
|
|
9167
|
+
)), /* @__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(
|
|
9168
|
+
ui.Button,
|
|
9169
|
+
{
|
|
9170
|
+
variant: "secondary",
|
|
9171
|
+
fill: "text",
|
|
9172
|
+
size: "sm",
|
|
9173
|
+
onClick: () => {
|
|
9174
|
+
setEditing(true);
|
|
9175
|
+
onUpdate(index, "value", "");
|
|
9176
|
+
},
|
|
9177
|
+
type: "button"
|
|
9178
|
+
},
|
|
9179
|
+
"Reset"
|
|
9180
|
+
)) : /* @__PURE__ */ React__default.default.createElement(
|
|
9181
|
+
ui.Input,
|
|
9182
|
+
{
|
|
9183
|
+
value: item.value === SECURE_FIELD_CONFIGURED ? "" : item.value,
|
|
9184
|
+
placeholder: `${itemLabel} value`,
|
|
9185
|
+
disabled,
|
|
9186
|
+
type: revealed ? "text" : "password",
|
|
9187
|
+
onChange: (e) => onUpdate(index, "value", e.currentTarget.value),
|
|
9188
|
+
onKeyDown: (e) => {
|
|
9189
|
+
if (e.key === "Enter") {
|
|
9190
|
+
e.preventDefault();
|
|
9191
|
+
}
|
|
9192
|
+
},
|
|
9193
|
+
suffix: /* @__PURE__ */ React__default.default.createElement(
|
|
9194
|
+
ui.Button,
|
|
9195
|
+
{
|
|
9196
|
+
variant: "secondary",
|
|
9197
|
+
fill: "text",
|
|
9198
|
+
size: "sm",
|
|
9199
|
+
icon: revealed ? "eye-slash" : "eye",
|
|
9200
|
+
"aria-label": revealed ? "Hide" : "Reveal",
|
|
9201
|
+
onClick: () => setRevealed((r) => !r),
|
|
9202
|
+
type: "button"
|
|
9203
|
+
}
|
|
9204
|
+
)
|
|
9205
|
+
}
|
|
9206
|
+
)), !hideControls && /* @__PURE__ */ React__default.default.createElement(ui.Tooltip, { content: `Remove ${itemLabel}` }, /* @__PURE__ */ React__default.default.createElement(
|
|
9207
|
+
ui.Button,
|
|
9208
|
+
{
|
|
9209
|
+
variant: "secondary",
|
|
9210
|
+
fill: "text",
|
|
9211
|
+
size: "sm",
|
|
9212
|
+
icon: "trash-alt",
|
|
9213
|
+
"aria-label": `Remove ${itemLabel}`,
|
|
9214
|
+
disabled,
|
|
9215
|
+
onClick: () => onRemove(index),
|
|
9216
|
+
type: "button"
|
|
9217
|
+
}
|
|
9218
|
+
)));
|
|
9219
|
+
};
|
|
9220
|
+
const getStyles$e = (theme) => ({
|
|
9221
|
+
inputCell: css.css({
|
|
9222
|
+
flex: "1 1 0",
|
|
9223
|
+
minWidth: 0,
|
|
9224
|
+
overflow: "hidden"
|
|
9225
|
+
}),
|
|
9226
|
+
limitNote: css.css({
|
|
9227
|
+
fontSize: theme.typography.bodySmall.fontSize,
|
|
9228
|
+
color: theme.colors.text.secondary
|
|
9229
|
+
})
|
|
9230
|
+
});
|
|
9231
|
+
|
|
9232
|
+
function ObjectArrayEditor(props) {
|
|
9233
|
+
var _a, _b, _c, _d, _e, _f;
|
|
9234
|
+
const { field, value, onChange, disabled, errorMessage } = props;
|
|
9235
|
+
const styles = ui.useStyles2(getStyles$d);
|
|
9236
|
+
const itemFields = (_b = (_a = field.item) == null ? void 0 : _a.fields) != null ? _b : [];
|
|
9237
|
+
const layoutRows = computeLayoutRows(itemFields);
|
|
9238
|
+
const items = Array.isArray(value) ? value : [];
|
|
9239
|
+
const maxItems = (_e = (_d = (_c = field.validations) == null ? void 0 : _c.find((v) => v.type === "itemCount")) == null ? void 0 : _d.max) != null ? _e : 20;
|
|
9240
|
+
const label = (_f = field.label) != null ? _f : field.key;
|
|
9241
|
+
const itemErrors = parseItemErrors(errorMessage);
|
|
9242
|
+
const addItem = () => {
|
|
9243
|
+
var _a2, _b2;
|
|
9244
|
+
if (items.length >= maxItems) {
|
|
9245
|
+
return;
|
|
9246
|
+
}
|
|
9247
|
+
const empty = {};
|
|
9248
|
+
for (const f of itemFields) {
|
|
9249
|
+
if (f.valueType === "boolean") {
|
|
9250
|
+
empty[f.key] = (_a2 = f.defaultValue) != null ? _a2 : false;
|
|
9251
|
+
} else {
|
|
9252
|
+
empty[f.key] = (_b2 = f.defaultValue) != null ? _b2 : "";
|
|
9253
|
+
}
|
|
9254
|
+
}
|
|
9255
|
+
onChange([...items, empty]);
|
|
9256
|
+
};
|
|
9257
|
+
const removeItem = (index) => {
|
|
9258
|
+
onChange(items.filter((_, i) => i !== index));
|
|
9259
|
+
};
|
|
9260
|
+
const updateItem = (index, key, val) => {
|
|
9261
|
+
const updated = items.map((item, i) => i === index ? { ...item, [key]: val } : item);
|
|
9262
|
+
onChange(updated);
|
|
9263
|
+
};
|
|
9264
|
+
return /* @__PURE__ */ React__default.default.createElement(ui.Stack, { direction: "column", gap: 1 }, items.map((item, i) => /* @__PURE__ */ React__default.default.createElement(
|
|
9265
|
+
ObjectArrayItemRow,
|
|
9266
|
+
{
|
|
9267
|
+
key: i,
|
|
9268
|
+
item,
|
|
9269
|
+
index: i,
|
|
9270
|
+
itemFields,
|
|
9271
|
+
layoutRows,
|
|
9272
|
+
disabled: !!disabled,
|
|
9273
|
+
onUpdate: updateItem,
|
|
9274
|
+
onRemove: removeItem,
|
|
9275
|
+
showLabels: true,
|
|
9276
|
+
error: itemErrors == null ? void 0 : itemErrors[i]
|
|
9277
|
+
}
|
|
9278
|
+
)), 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"));
|
|
9279
|
+
}
|
|
9280
|
+
function computeLayoutRows(fields) {
|
|
9281
|
+
var _a;
|
|
9282
|
+
const hasExplicitRow = fields.some((f) => {
|
|
9283
|
+
var _a2;
|
|
9284
|
+
return ((_a2 = f.ui) == null ? void 0 : _a2.row) !== void 0;
|
|
9285
|
+
});
|
|
9286
|
+
if (!hasExplicitRow) {
|
|
9287
|
+
if (fields.length <= 3) {
|
|
9288
|
+
return [fields];
|
|
9289
|
+
}
|
|
9290
|
+
return fields.map((f) => [f]);
|
|
9291
|
+
}
|
|
9292
|
+
const rowMap = /* @__PURE__ */ new Map();
|
|
9293
|
+
const noRow = [];
|
|
9294
|
+
for (const f of fields) {
|
|
9295
|
+
if (((_a = f.ui) == null ? void 0 : _a.row) !== void 0) {
|
|
9296
|
+
const existing = rowMap.get(f.ui.row);
|
|
9297
|
+
if (existing) {
|
|
9298
|
+
existing.push(f);
|
|
9299
|
+
} else {
|
|
9300
|
+
rowMap.set(f.ui.row, [f]);
|
|
9301
|
+
}
|
|
9302
|
+
} else {
|
|
9303
|
+
noRow.push(f);
|
|
9304
|
+
}
|
|
9305
|
+
}
|
|
9306
|
+
const sortedKeys = [...rowMap.keys()].sort((a, b) => a - b);
|
|
9307
|
+
const rows = sortedKeys.map((k) => rowMap.get(k));
|
|
9308
|
+
for (const f of noRow) {
|
|
9309
|
+
rows.push([f]);
|
|
9310
|
+
}
|
|
9311
|
+
return rows;
|
|
9312
|
+
}
|
|
9313
|
+
function makeItemFormField(item, index, fieldKey, onUpdate) {
|
|
9314
|
+
return {
|
|
9315
|
+
name: `item-${index}-${fieldKey}`,
|
|
9316
|
+
value: item[fieldKey],
|
|
9317
|
+
onChange: (eventOrValue) => {
|
|
9318
|
+
if (eventOrValue != null && typeof eventOrValue === "object" && "target" in eventOrValue) {
|
|
9319
|
+
onUpdate(index, fieldKey, eventOrValue.target.value);
|
|
9320
|
+
} else {
|
|
9321
|
+
onUpdate(index, fieldKey, eventOrValue);
|
|
9322
|
+
}
|
|
9323
|
+
},
|
|
9324
|
+
onBlur: () => {
|
|
9325
|
+
}
|
|
9326
|
+
};
|
|
9327
|
+
}
|
|
9328
|
+
function effectiveItemField(field, isSecure) {
|
|
9329
|
+
if (!isSecure) {
|
|
9330
|
+
return field;
|
|
9331
|
+
}
|
|
9332
|
+
return { ...field, semanticType: "password" };
|
|
9333
|
+
}
|
|
9334
|
+
function ObjectArrayItemRow({
|
|
9335
|
+
item,
|
|
9336
|
+
index,
|
|
9337
|
+
itemFields,
|
|
9338
|
+
layoutRows,
|
|
9339
|
+
disabled,
|
|
9340
|
+
onUpdate,
|
|
9341
|
+
onRemove,
|
|
9342
|
+
showLabels,
|
|
9343
|
+
error
|
|
9344
|
+
}) {
|
|
9345
|
+
const styles = ui.useStyles2(getStyles$d);
|
|
9346
|
+
const secureOverride = findActiveSecureOverride(itemFields, item, index);
|
|
9347
|
+
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) => {
|
|
9348
|
+
var _a;
|
|
9349
|
+
const isSecureTarget = (secureOverride == null ? void 0 : secureOverride.fieldKey) === field.key;
|
|
9350
|
+
const eff = effectiveItemField(field, !!isSecureTarget);
|
|
9351
|
+
const formField = makeItemFormField(item, index, field.key, onUpdate);
|
|
9352
|
+
if (isSecureTarget && item[field.key] === SECURE_FIELD_CONFIGURED) {
|
|
9353
|
+
formField.value = SECURE_FIELD_CONFIGURED;
|
|
9354
|
+
}
|
|
9355
|
+
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));
|
|
9356
|
+
}), 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(
|
|
9357
|
+
ui.Button,
|
|
9358
|
+
{
|
|
9359
|
+
variant: "secondary",
|
|
9360
|
+
fill: "text",
|
|
9361
|
+
size: "sm",
|
|
9362
|
+
icon: "trash-alt",
|
|
9363
|
+
"aria-label": "Remove item",
|
|
9364
|
+
disabled,
|
|
9365
|
+
onClick: () => onRemove(index),
|
|
9366
|
+
type: "button"
|
|
9367
|
+
}
|
|
9368
|
+
))))), error && /* @__PURE__ */ React__default.default.createElement("span", { className: styles.itemError }, error));
|
|
9369
|
+
}
|
|
9370
|
+
const getStyles$d = (theme) => ({
|
|
9371
|
+
itemRow: css.css({
|
|
9372
|
+
display: "flex",
|
|
9373
|
+
flexDirection: "column",
|
|
9374
|
+
gap: theme.spacing(0.5),
|
|
9375
|
+
padding: theme.spacing(1),
|
|
9376
|
+
borderRadius: theme.shape.radius.default,
|
|
9377
|
+
border: `1px solid ${theme.colors.border.weak}`
|
|
9378
|
+
}),
|
|
9379
|
+
inputCell: css.css({
|
|
9380
|
+
flex: "1 1 120px",
|
|
9381
|
+
minWidth: 120,
|
|
9382
|
+
overflow: "hidden"
|
|
9383
|
+
}),
|
|
9384
|
+
boolCell: css.css({
|
|
9385
|
+
flex: "0 0 auto",
|
|
9386
|
+
minWidth: 0
|
|
9387
|
+
}),
|
|
9388
|
+
cellLabel: css.css({
|
|
9389
|
+
fontSize: theme.typography.bodySmall.fontSize,
|
|
9390
|
+
color: theme.colors.text.secondary,
|
|
9391
|
+
marginBottom: theme.spacing(0.25)
|
|
9392
|
+
}),
|
|
9393
|
+
required: css.css({
|
|
9394
|
+
color: theme.colors.error.text
|
|
9395
|
+
}),
|
|
9396
|
+
removeCellWithLabel: css.css({
|
|
9397
|
+
flex: "0 0 auto",
|
|
9398
|
+
display: "flex",
|
|
9399
|
+
alignItems: "flex-end",
|
|
9400
|
+
paddingBottom: theme.spacing(0.25)
|
|
9401
|
+
}),
|
|
9402
|
+
itemError: css.css({
|
|
9403
|
+
fontSize: theme.typography.bodySmall.fontSize,
|
|
9404
|
+
color: theme.colors.error.text
|
|
9405
|
+
}),
|
|
9406
|
+
limitNote: css.css({
|
|
9407
|
+
fontSize: theme.typography.bodySmall.fontSize,
|
|
9408
|
+
color: theme.colors.text.secondary
|
|
9409
|
+
})
|
|
9410
|
+
});
|
|
9411
|
+
|
|
9412
|
+
const StringArrayInput = (props) => {
|
|
9413
|
+
const { value, onChange, placeholder, disabled, itemLabel = "item" } = props;
|
|
9414
|
+
const styles = ui.useStyles2(getStyles$c);
|
|
9415
|
+
const items = Array.isArray(value) ? value : [];
|
|
9416
|
+
const lastInputRef = React.useRef(null);
|
|
9417
|
+
const shouldFocusLastRef = React.useRef(false);
|
|
9418
|
+
React.useEffect(() => {
|
|
9419
|
+
if (shouldFocusLastRef.current && lastInputRef.current) {
|
|
9420
|
+
lastInputRef.current.focus();
|
|
9421
|
+
shouldFocusLastRef.current = false;
|
|
9422
|
+
}
|
|
9423
|
+
}, [items.length]);
|
|
9424
|
+
const addItem = () => {
|
|
9425
|
+
shouldFocusLastRef.current = true;
|
|
9426
|
+
onChange([...items, ""]);
|
|
9427
|
+
};
|
|
9428
|
+
const removeItem = (index) => {
|
|
9429
|
+
onChange(items.filter((_, i) => i !== index));
|
|
9430
|
+
};
|
|
9431
|
+
const updateItem = (index, val) => {
|
|
9432
|
+
onChange(items.map((item, i) => i === index ? val : item));
|
|
9433
|
+
};
|
|
9434
|
+
const isItemValid = (index, val) => {
|
|
9435
|
+
const trimmed = val.trim();
|
|
9436
|
+
if (trimmed === "") {
|
|
9437
|
+
return false;
|
|
9438
|
+
}
|
|
9439
|
+
return !items.some((item, i) => i !== index && item.trim() === trimmed);
|
|
9440
|
+
};
|
|
9441
|
+
const handleEnter = (index, currentValue) => {
|
|
9442
|
+
if (!isItemValid(index, currentValue)) {
|
|
9443
|
+
return;
|
|
9444
|
+
}
|
|
9445
|
+
if (index === items.length - 1) {
|
|
9446
|
+
shouldFocusLastRef.current = true;
|
|
9447
|
+
onChange([...items, ""]);
|
|
9448
|
+
}
|
|
9449
|
+
};
|
|
9450
|
+
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(
|
|
9451
|
+
ui.Input,
|
|
9452
|
+
{
|
|
9453
|
+
ref: i === items.length - 1 ? lastInputRef : void 0,
|
|
9454
|
+
value: item,
|
|
9455
|
+
placeholder: placeholder != null ? placeholder : itemLabel,
|
|
9456
|
+
disabled,
|
|
9457
|
+
onChange: (e) => updateItem(i, e.currentTarget.value),
|
|
9458
|
+
onKeyDown: (e) => {
|
|
9459
|
+
if (e.key === "Enter") {
|
|
9460
|
+
e.preventDefault();
|
|
9461
|
+
handleEnter(i, e.currentTarget.value);
|
|
9462
|
+
}
|
|
9463
|
+
}
|
|
9464
|
+
}
|
|
9465
|
+
)), !disabled && /* @__PURE__ */ React__default.default.createElement(ui.Tooltip, { content: `Remove ${itemLabel}` }, /* @__PURE__ */ React__default.default.createElement(
|
|
9466
|
+
ui.Button,
|
|
9467
|
+
{
|
|
9468
|
+
variant: "secondary",
|
|
9469
|
+
fill: "text",
|
|
9470
|
+
size: "sm",
|
|
9471
|
+
icon: "trash-alt",
|
|
9472
|
+
"aria-label": `Remove ${itemLabel}`,
|
|
9473
|
+
onClick: () => removeItem(i),
|
|
9474
|
+
type: "button"
|
|
9475
|
+
}
|
|
9476
|
+
)))), !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")));
|
|
9477
|
+
};
|
|
9478
|
+
const getStyles$c = (theme) => ({
|
|
9479
|
+
inputCell: css.css({
|
|
9480
|
+
flex: "1 1 0",
|
|
9481
|
+
minWidth: 0,
|
|
9482
|
+
overflow: "hidden"
|
|
9483
|
+
})
|
|
9484
|
+
});
|
|
9485
|
+
|
|
9486
|
+
function renderFieldInput(field, formField, disabled, errorMessage, setValue) {
|
|
9487
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w;
|
|
9488
|
+
const value = formField.value;
|
|
9489
|
+
const placeholder = (_a = field.ui) == null ? void 0 : _a.placeholder;
|
|
9490
|
+
const label = (_b = field.label) != null ? _b : field.key;
|
|
9491
|
+
if (((_c = field.ui) == null ? void 0 : _c.component) === "fileUpload" && field.ui.fileMapping && setValue) {
|
|
9492
|
+
return /* @__PURE__ */ React__default.default.createElement(FileUploadField, { field, formField, disabled, setValue });
|
|
9493
|
+
}
|
|
9494
|
+
if (field.target === "secureJsonData" || field.semanticType === "password" || field.semanticType === "token") {
|
|
9495
|
+
return /* @__PURE__ */ React__default.default.createElement(SecureFieldInput, { formField, placeholder: placeholder != null ? placeholder : label, disabled, label });
|
|
9496
|
+
}
|
|
9497
|
+
if (((_d = field.ui) == null ? void 0 : _d.component) === "radio") {
|
|
9498
|
+
const options = ((_f = (_e = field.ui) == null ? void 0 : _e.options) != null ? _f : []).map((opt) => ({
|
|
9499
|
+
label: opt.label,
|
|
9500
|
+
value: String(opt.value),
|
|
9501
|
+
description: opt.description
|
|
9502
|
+
}));
|
|
9503
|
+
return /* @__PURE__ */ React__default.default.createElement("div", { style: { display: "flex" } }, /* @__PURE__ */ React__default.default.createElement(
|
|
9504
|
+
ui.RadioButtonGroup,
|
|
9505
|
+
{
|
|
9506
|
+
options,
|
|
9507
|
+
value: String(value != null ? value : ""),
|
|
9508
|
+
onChange: (v) => {
|
|
9509
|
+
if (field.valueType === "number") {
|
|
9510
|
+
const n = Number(v);
|
|
9511
|
+
formField.onChange(Number.isNaN(n) ? v : n);
|
|
9512
|
+
} else {
|
|
9513
|
+
formField.onChange(v);
|
|
9514
|
+
}
|
|
9515
|
+
},
|
|
9516
|
+
disabled
|
|
9517
|
+
}
|
|
9518
|
+
));
|
|
9519
|
+
}
|
|
9520
|
+
if (((_g = field.ui) == null ? void 0 : _g.component) === "select") {
|
|
9521
|
+
const options = ((_i = (_h = field.ui) == null ? void 0 : _h.options) != null ? _i : []).map((opt) => ({
|
|
9522
|
+
label: opt.label,
|
|
9523
|
+
value: String(opt.value),
|
|
9524
|
+
description: opt.description
|
|
9525
|
+
}));
|
|
9526
|
+
return /* @__PURE__ */ React__default.default.createElement(
|
|
9527
|
+
ui.Select,
|
|
9528
|
+
{
|
|
9529
|
+
options,
|
|
9530
|
+
value: options.find((o) => o.value === String(value != null ? value : "")),
|
|
9531
|
+
onChange: (v) => formField.onChange(v == null ? void 0 : v.value),
|
|
9532
|
+
disabled
|
|
9533
|
+
}
|
|
9534
|
+
);
|
|
9535
|
+
}
|
|
9536
|
+
if (field.valueType === "boolean") {
|
|
9537
|
+
return /* @__PURE__ */ React__default.default.createElement(ui.Switch, { value: !!value, onChange: (e) => formField.onChange(e.currentTarget.checked), disabled });
|
|
9538
|
+
}
|
|
9539
|
+
if (field.valueType === "number") {
|
|
9540
|
+
return /* @__PURE__ */ React__default.default.createElement(
|
|
9541
|
+
ui.Input,
|
|
9542
|
+
{
|
|
9543
|
+
...formField,
|
|
9544
|
+
value: value !== void 0 && value !== null ? Number(value) : "",
|
|
9545
|
+
type: "number",
|
|
9546
|
+
placeholder,
|
|
9547
|
+
disabled,
|
|
9548
|
+
onChange: (e) => {
|
|
9549
|
+
const n = e.currentTarget.valueAsNumber;
|
|
9550
|
+
formField.onChange(Number.isNaN(n) ? void 0 : n);
|
|
9551
|
+
}
|
|
9552
|
+
}
|
|
9553
|
+
);
|
|
9554
|
+
}
|
|
9555
|
+
if (field.semanticType === "url") {
|
|
9556
|
+
return /* @__PURE__ */ React__default.default.createElement(ui.Input, { ...formField, value: String(value != null ? value : ""), type: "url", placeholder, disabled });
|
|
9557
|
+
}
|
|
9558
|
+
if (((_j = field.ui) == null ? void 0 : _j.component) === "textarea") {
|
|
9559
|
+
return /* @__PURE__ */ React__default.default.createElement(
|
|
9560
|
+
ui.TextArea,
|
|
9561
|
+
{
|
|
9562
|
+
...formField,
|
|
9563
|
+
value: String(value != null ? value : ""),
|
|
9564
|
+
placeholder,
|
|
9565
|
+
disabled,
|
|
9566
|
+
rows: (_l = (_k = field.ui) == null ? void 0 : _k.rows) != null ? _l : 3
|
|
9567
|
+
}
|
|
9568
|
+
);
|
|
9569
|
+
}
|
|
9570
|
+
if (((_m = field.storage) == null ? void 0 : _m.type) === "indexedPair") {
|
|
9571
|
+
const items = Array.isArray(value) ? value : [];
|
|
9572
|
+
const maxItems = (_p = (_o = (_n = field.validations) == null ? void 0 : _n.find((v) => v.type === "itemCount")) == null ? void 0 : _o.max) != null ? _p : 10;
|
|
9573
|
+
const itemLabel = (_r = (_q = field.label) == null ? void 0 : _q.toLowerCase().replace(/s$/, "")) != null ? _r : "header";
|
|
9574
|
+
return /* @__PURE__ */ React__default.default.createElement(
|
|
9575
|
+
IndexedPairEditor,
|
|
9576
|
+
{
|
|
9577
|
+
value: items,
|
|
9578
|
+
onChange: formField.onChange,
|
|
9579
|
+
maxItems,
|
|
9580
|
+
disabled,
|
|
9581
|
+
itemLabel
|
|
9582
|
+
}
|
|
9583
|
+
);
|
|
9584
|
+
}
|
|
9585
|
+
if (field.valueType === "array" && ((_s = field.item) == null ? void 0 : _s.valueType) === "string") {
|
|
9586
|
+
return /* @__PURE__ */ React__default.default.createElement(
|
|
9587
|
+
StringArrayInput,
|
|
9588
|
+
{
|
|
9589
|
+
value: Array.isArray(value) ? value : [],
|
|
9590
|
+
onChange: formField.onChange,
|
|
9591
|
+
placeholder,
|
|
9592
|
+
disabled,
|
|
9593
|
+
itemLabel: label.toLowerCase().replace(/s$/, "")
|
|
9594
|
+
}
|
|
9595
|
+
);
|
|
9596
|
+
}
|
|
9597
|
+
if (field.valueType === "array" && ((_t = field.item) == null ? void 0 : _t.valueType) === "object" && ((_u = field.item.fields) == null ? void 0 : _u.length)) {
|
|
9598
|
+
return /* @__PURE__ */ React__default.default.createElement(
|
|
9599
|
+
ObjectArrayEditor,
|
|
9600
|
+
{
|
|
9601
|
+
field,
|
|
9602
|
+
value,
|
|
9603
|
+
onChange: formField.onChange,
|
|
9604
|
+
disabled,
|
|
9605
|
+
errorMessage
|
|
9606
|
+
}
|
|
9607
|
+
);
|
|
9608
|
+
}
|
|
9609
|
+
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")) {
|
|
9610
|
+
const count = Array.isArray(value) ? value.length : 0;
|
|
9611
|
+
return /* @__PURE__ */ React__default.default.createElement(ComplexFieldNote, { count, label });
|
|
9612
|
+
}
|
|
9613
|
+
return /* @__PURE__ */ React__default.default.createElement(ui.Input, { ...formField, value: String(value != null ? value : ""), placeholder, disabled });
|
|
9614
|
+
}
|
|
9615
|
+
|
|
9616
|
+
const getTabStyles = (theme) => ({
|
|
9617
|
+
root: css.css({
|
|
9618
|
+
display: "flex",
|
|
9619
|
+
gap: theme.spacing(3),
|
|
9620
|
+
position: "relative",
|
|
9621
|
+
background: theme.colors.background.canvas,
|
|
9622
|
+
padding: theme.spacing(2)
|
|
9623
|
+
}),
|
|
9624
|
+
// Sidebar
|
|
9625
|
+
sidebar: css.css({
|
|
9626
|
+
width: 250,
|
|
9627
|
+
flexShrink: 0,
|
|
9628
|
+
position: "sticky",
|
|
9629
|
+
top: theme.spacing(2),
|
|
9630
|
+
alignSelf: "flex-start",
|
|
9631
|
+
[theme.breakpoints.down("sm")]: { display: "none" }
|
|
9632
|
+
}),
|
|
9633
|
+
sidebarTitle: css.css({
|
|
9634
|
+
fontSize: theme.typography.body.fontSize,
|
|
9635
|
+
fontWeight: theme.typography.fontWeightMedium,
|
|
9636
|
+
color: theme.colors.text.primary,
|
|
9637
|
+
padding: `${theme.spacing(1)} 0`,
|
|
9638
|
+
marginBottom: theme.spacing(1)
|
|
9639
|
+
}),
|
|
9640
|
+
navList: css.css({
|
|
9641
|
+
listStyle: "none",
|
|
9642
|
+
margin: 0,
|
|
9643
|
+
padding: 0,
|
|
9644
|
+
position: "relative"
|
|
9645
|
+
}),
|
|
9646
|
+
navItem: css.css({
|
|
9647
|
+
display: "flex",
|
|
9648
|
+
alignItems: "flex-start",
|
|
9649
|
+
gap: theme.spacing(1.5),
|
|
9650
|
+
padding: `${theme.spacing(1)} 0`,
|
|
9651
|
+
cursor: "pointer",
|
|
9652
|
+
position: "relative"
|
|
9653
|
+
}),
|
|
9654
|
+
navItemActive: css.css({}),
|
|
9655
|
+
// Dot container: positions the dot and the connector line
|
|
9656
|
+
navDotWrap: css.css({
|
|
9657
|
+
position: "relative",
|
|
9658
|
+
display: "flex",
|
|
9659
|
+
alignItems: "center",
|
|
9660
|
+
justifyContent: "center",
|
|
9661
|
+
width: 12,
|
|
9662
|
+
flexShrink: 0,
|
|
9663
|
+
alignSelf: "flex-start",
|
|
9664
|
+
paddingTop: theme.spacing(0.5)
|
|
9665
|
+
}),
|
|
9666
|
+
navDot: css.css({
|
|
9667
|
+
width: 10,
|
|
9668
|
+
height: 10,
|
|
9669
|
+
borderRadius: "50%",
|
|
9670
|
+
border: `2px solid ${theme.colors.text.disabled}`,
|
|
9671
|
+
background: theme.colors.background.canvas,
|
|
9672
|
+
position: "relative",
|
|
9673
|
+
zIndex: 1
|
|
9674
|
+
}),
|
|
9675
|
+
navDotOptional: css.css({
|
|
9676
|
+
borderStyle: "dashed"
|
|
9677
|
+
}),
|
|
9678
|
+
navDotActive: css.css({
|
|
9679
|
+
background: theme.colors.primary.main,
|
|
9680
|
+
borderColor: theme.colors.primary.main,
|
|
9681
|
+
borderStyle: "solid"
|
|
9682
|
+
}),
|
|
9683
|
+
navDotValidated: css.css({
|
|
9684
|
+
background: theme.colors.success.main,
|
|
9685
|
+
borderColor: theme.colors.success.main,
|
|
9686
|
+
borderStyle: "solid"
|
|
9687
|
+
}),
|
|
9688
|
+
navDotError: css.css({
|
|
9689
|
+
background: theme.colors.error.main,
|
|
9690
|
+
borderColor: theme.colors.error.main,
|
|
9691
|
+
borderStyle: "solid"
|
|
9692
|
+
}),
|
|
9693
|
+
// Connector line running from dot center downward to next item
|
|
9694
|
+
navConnector: css.css({
|
|
9695
|
+
position: "absolute",
|
|
9696
|
+
left: 5,
|
|
9697
|
+
top: 16,
|
|
9698
|
+
bottom: -16,
|
|
9699
|
+
width: 2,
|
|
9700
|
+
background: theme.colors.border.medium,
|
|
9701
|
+
zIndex: 0
|
|
9702
|
+
}),
|
|
9703
|
+
navConnectorDashed: css.css({
|
|
9704
|
+
background: "none",
|
|
9705
|
+
borderLeft: `2px dashed ${theme.colors.border.weak}`,
|
|
9706
|
+
width: 0
|
|
9707
|
+
}),
|
|
9708
|
+
navLabel: css.css({
|
|
9709
|
+
fontSize: theme.typography.body.fontSize,
|
|
9710
|
+
color: theme.colors.text.secondary,
|
|
9711
|
+
lineHeight: 1.4
|
|
9712
|
+
}),
|
|
9713
|
+
navLabelActive: css.css({
|
|
9714
|
+
fontWeight: theme.typography.fontWeightMedium,
|
|
9715
|
+
color: theme.colors.text.primary
|
|
9716
|
+
}),
|
|
9717
|
+
// Main content
|
|
9718
|
+
main: css.css({
|
|
9719
|
+
flex: 1,
|
|
9720
|
+
minWidth: 0,
|
|
9721
|
+
width: 0,
|
|
9722
|
+
// forces flex child to respect flex-grow and fill remaining space
|
|
9723
|
+
display: "flex",
|
|
9724
|
+
flexDirection: "column",
|
|
9725
|
+
gap: theme.spacing(2)
|
|
9726
|
+
}),
|
|
9727
|
+
form: css.css({
|
|
9728
|
+
display: "flex",
|
|
9729
|
+
flexDirection: "column",
|
|
9730
|
+
gap: theme.spacing(2)
|
|
9731
|
+
}),
|
|
9732
|
+
requiredNotice: css.css({
|
|
9733
|
+
fontSize: theme.typography.bodySmall.fontSize,
|
|
9734
|
+
color: theme.colors.text.secondary,
|
|
9735
|
+
marginBottom: theme.spacing(0.5)
|
|
9736
|
+
}),
|
|
9737
|
+
// Section wrapper — card container around CollapsableSection
|
|
9738
|
+
section: css.css({
|
|
9739
|
+
border: `1px solid ${theme.colors.border.weak}`,
|
|
9740
|
+
borderRadius: theme.shape.radius.default,
|
|
9741
|
+
background: theme.colors.background.secondary,
|
|
9742
|
+
overflow: "hidden"
|
|
9743
|
+
}),
|
|
9744
|
+
// Override Collapse component styling
|
|
9745
|
+
collapseHeader: css.css({
|
|
9746
|
+
borderRadius: theme.shape.radius.default,
|
|
9747
|
+
background: "none",
|
|
9748
|
+
border: "none",
|
|
9749
|
+
marginBottom: 0,
|
|
9750
|
+
// Collapse header button: make label fill remaining space
|
|
9751
|
+
"& > button": {
|
|
9752
|
+
padding: `${theme.spacing(1.5)} ${theme.spacing(2)}`,
|
|
9753
|
+
width: "100%",
|
|
9754
|
+
justifyContent: "flex-start"
|
|
9755
|
+
},
|
|
9756
|
+
"& > button > div": {
|
|
9757
|
+
flex: 1,
|
|
9758
|
+
fontSize: theme.typography.h4.fontSize,
|
|
9759
|
+
fontWeight: theme.typography.fontWeightMedium,
|
|
9760
|
+
textAlign: "left"
|
|
9761
|
+
}
|
|
9762
|
+
}),
|
|
9763
|
+
sectionLabel: css.css({
|
|
9764
|
+
display: "flex",
|
|
9765
|
+
alignItems: "center",
|
|
9766
|
+
flex: 1
|
|
9767
|
+
}),
|
|
9768
|
+
sectionLabelText: css.css({
|
|
9769
|
+
flex: 1
|
|
9770
|
+
}),
|
|
9771
|
+
sectionHeader: css.css({
|
|
9772
|
+
display: "flex",
|
|
9773
|
+
alignItems: "center",
|
|
9774
|
+
gap: theme.spacing(1),
|
|
9775
|
+
padding: `${theme.spacing(1.5)} ${theme.spacing(2)}`,
|
|
9776
|
+
cursor: "pointer",
|
|
9777
|
+
userSelect: "none"
|
|
9778
|
+
}),
|
|
9779
|
+
sectionChevron: css.css({
|
|
9780
|
+
transition: "transform 0.2s ease"
|
|
9781
|
+
}),
|
|
9782
|
+
sectionChevronOpen: css.css({
|
|
9783
|
+
transform: "rotate(90deg)"
|
|
9784
|
+
}),
|
|
9785
|
+
sectionTitle: css.css({
|
|
9786
|
+
fontSize: theme.typography.h4.fontSize,
|
|
9787
|
+
fontWeight: theme.typography.fontWeightMedium,
|
|
9788
|
+
flex: 1,
|
|
9789
|
+
textAlign: "left"
|
|
9790
|
+
}),
|
|
9791
|
+
sectionBadge: css.css({
|
|
9792
|
+
fontSize: theme.typography.bodySmall.fontSize,
|
|
9793
|
+
fontWeight: theme.typography.fontWeightRegular,
|
|
9794
|
+
color: theme.colors.text.disabled,
|
|
9795
|
+
border: `1px solid ${theme.colors.border.weak}`,
|
|
9796
|
+
borderRadius: theme.shape.radius.pill,
|
|
9797
|
+
padding: `1px ${theme.spacing(0.75)}`,
|
|
9798
|
+
whiteSpace: "nowrap"
|
|
9799
|
+
}),
|
|
9800
|
+
sectionDescription: css.css({
|
|
9801
|
+
fontSize: theme.typography.bodySmall.fontSize,
|
|
9802
|
+
color: theme.colors.text.secondary,
|
|
9803
|
+
marginBottom: theme.spacing(1.5)
|
|
9804
|
+
}),
|
|
9805
|
+
sectionBody: css.css({
|
|
9806
|
+
padding: `0 ${theme.spacing(2)} ${theme.spacing(2)}`,
|
|
9807
|
+
display: "flex",
|
|
9808
|
+
flexDirection: "column",
|
|
9809
|
+
gap: theme.spacing(0.75)
|
|
9810
|
+
}),
|
|
9811
|
+
// Form bottom
|
|
9812
|
+
formButtons: css.css({
|
|
9813
|
+
display: "flex",
|
|
9814
|
+
gap: theme.spacing(1),
|
|
9815
|
+
paddingTop: theme.spacing(0.5)
|
|
9816
|
+
}),
|
|
9817
|
+
// Loading / error states
|
|
9818
|
+
loadingContainer: css.css({
|
|
9819
|
+
display: "flex",
|
|
9820
|
+
alignItems: "center",
|
|
9821
|
+
gap: theme.spacing(1),
|
|
9822
|
+
padding: theme.spacing(3),
|
|
9823
|
+
color: theme.colors.text.secondary
|
|
9824
|
+
}),
|
|
9825
|
+
overlay: css.css({
|
|
9826
|
+
position: "absolute",
|
|
9827
|
+
inset: 0,
|
|
9828
|
+
display: "flex",
|
|
9829
|
+
alignItems: "center",
|
|
9830
|
+
justifyContent: "center",
|
|
9831
|
+
gap: theme.spacing(1),
|
|
9832
|
+
background: theme.colors.background.secondary,
|
|
9833
|
+
borderRadius: theme.shape.radius.default,
|
|
9834
|
+
zIndex: 1,
|
|
9835
|
+
fontSize: theme.typography.bodySmall.fontSize,
|
|
9836
|
+
color: theme.colors.text.primary,
|
|
9837
|
+
opacity: 0.95
|
|
9838
|
+
}),
|
|
9839
|
+
readOnlyBanner: css.css({
|
|
9840
|
+
display: "inline-flex",
|
|
9841
|
+
alignItems: "center",
|
|
9842
|
+
gap: theme.spacing(0.5),
|
|
9843
|
+
padding: `${theme.spacing(0.25)} ${theme.spacing(0.75)}`,
|
|
9844
|
+
fontSize: theme.typography.bodySmall.fontSize,
|
|
9845
|
+
color: theme.colors.text.secondary,
|
|
9846
|
+
backgroundColor: theme.colors.background.secondary,
|
|
9847
|
+
borderRadius: theme.shape.radius.default,
|
|
9848
|
+
border: `1px solid ${theme.colors.border.weak}`,
|
|
9849
|
+
marginBottom: theme.spacing(1)
|
|
9850
|
+
})
|
|
9851
|
+
});
|
|
9852
|
+
const getWizardStyles = (theme) => ({
|
|
9853
|
+
container: css.css({
|
|
9854
|
+
position: "relative",
|
|
9855
|
+
display: "flex",
|
|
9856
|
+
flexDirection: "column",
|
|
9857
|
+
gap: theme.spacing(1),
|
|
9858
|
+
padding: theme.spacing(1.5),
|
|
9859
|
+
backgroundColor: theme.colors.background.secondary,
|
|
9860
|
+
borderRadius: theme.shape.radius.default,
|
|
9861
|
+
border: `1px solid ${theme.colors.border.weak}`,
|
|
9862
|
+
overflow: "hidden"
|
|
9863
|
+
}),
|
|
9864
|
+
overlay: css.css({
|
|
9865
|
+
position: "absolute",
|
|
9866
|
+
inset: 0,
|
|
9867
|
+
display: "flex",
|
|
9868
|
+
alignItems: "center",
|
|
9869
|
+
justifyContent: "center",
|
|
9870
|
+
gap: theme.spacing(1),
|
|
9871
|
+
background: theme.colors.background.secondary,
|
|
9872
|
+
borderRadius: theme.shape.radius.default,
|
|
9873
|
+
zIndex: 1,
|
|
9874
|
+
fontSize: theme.typography.bodySmall.fontSize,
|
|
9875
|
+
color: theme.colors.text.primary,
|
|
9876
|
+
opacity: 0.95
|
|
9877
|
+
}),
|
|
9878
|
+
readOnlyBanner: css.css({
|
|
9879
|
+
display: "inline-flex",
|
|
9880
|
+
alignItems: "center",
|
|
9881
|
+
gap: theme.spacing(0.5),
|
|
9882
|
+
padding: `${theme.spacing(0.25)} ${theme.spacing(0.75)}`,
|
|
9883
|
+
fontSize: theme.typography.bodySmall.fontSize,
|
|
9884
|
+
color: theme.colors.text.secondary,
|
|
9885
|
+
backgroundColor: theme.colors.background.secondary,
|
|
9886
|
+
borderRadius: theme.shape.radius.default,
|
|
9887
|
+
border: `1px solid ${theme.colors.border.weak}`
|
|
9888
|
+
}),
|
|
9889
|
+
navBar: css.css({
|
|
9890
|
+
display: "flex",
|
|
9891
|
+
alignItems: "center",
|
|
9892
|
+
justifyContent: "space-between"
|
|
9893
|
+
}),
|
|
9894
|
+
navTitle: css.css({
|
|
9895
|
+
display: "inline-flex",
|
|
9896
|
+
alignItems: "center",
|
|
9897
|
+
gap: theme.spacing(0.5),
|
|
9898
|
+
fontSize: theme.typography.body.fontSize,
|
|
9899
|
+
fontWeight: theme.typography.fontWeightBold,
|
|
9900
|
+
color: theme.colors.text.primary
|
|
9901
|
+
}),
|
|
9902
|
+
stepCount: css.css({
|
|
9903
|
+
fontSize: theme.typography.bodySmall.fontSize,
|
|
9904
|
+
fontWeight: theme.typography.fontWeightRegular,
|
|
9905
|
+
color: theme.colors.text.secondary
|
|
9906
|
+
}),
|
|
9907
|
+
navActions: css.css({
|
|
9908
|
+
display: "flex",
|
|
9909
|
+
alignItems: "center",
|
|
9910
|
+
gap: theme.spacing(0.25)
|
|
9911
|
+
}),
|
|
9912
|
+
form: css.css({
|
|
9913
|
+
display: "flex",
|
|
9914
|
+
flexDirection: "column",
|
|
9915
|
+
gap: theme.spacing(0.75)
|
|
9916
|
+
}),
|
|
9917
|
+
buttons: css.css({
|
|
9918
|
+
display: "flex",
|
|
9919
|
+
gap: theme.spacing(1),
|
|
9920
|
+
paddingTop: theme.spacing(0.25)
|
|
9921
|
+
}),
|
|
9922
|
+
fieldRow: css.css({
|
|
9923
|
+
display: "grid",
|
|
9924
|
+
gridTemplateColumns: "minmax(80px, 1fr) minmax(0, 2fr)",
|
|
9925
|
+
gap: theme.spacing(0.75),
|
|
9926
|
+
alignItems: "start"
|
|
9927
|
+
}),
|
|
9928
|
+
fieldRowCenter: css.css({
|
|
9929
|
+
display: "grid",
|
|
9930
|
+
gridTemplateColumns: "minmax(80px, 1fr) minmax(0, 2fr)",
|
|
9931
|
+
gap: theme.spacing(0.75),
|
|
9932
|
+
alignItems: "center",
|
|
9933
|
+
padding: `${theme.spacing(0.5)} 0`
|
|
9934
|
+
}),
|
|
9935
|
+
fieldLabelRow: css.css({
|
|
9936
|
+
display: "flex",
|
|
9937
|
+
alignItems: "center",
|
|
9938
|
+
gap: theme.spacing(0.5),
|
|
9939
|
+
paddingTop: theme.spacing(0.5)
|
|
9940
|
+
}),
|
|
9941
|
+
fieldLabelRowCompact: css.css({
|
|
9942
|
+
display: "flex",
|
|
9943
|
+
alignItems: "center",
|
|
9944
|
+
gap: theme.spacing(0.5)
|
|
9945
|
+
}),
|
|
9946
|
+
fieldLabel: css.css({
|
|
9947
|
+
fontSize: theme.typography.bodySmall.fontSize,
|
|
9948
|
+
fontWeight: theme.typography.fontWeightMedium,
|
|
9949
|
+
color: theme.colors.text.primary
|
|
9950
|
+
}),
|
|
9951
|
+
fieldRequired: css.css({
|
|
9952
|
+
color: theme.colors.error.text,
|
|
9953
|
+
marginLeft: 2
|
|
9954
|
+
}),
|
|
9955
|
+
fieldInfoIcon: css.css({
|
|
9956
|
+
color: theme.colors.text.disabled,
|
|
9957
|
+
cursor: "help",
|
|
9958
|
+
flexShrink: 0
|
|
9959
|
+
}),
|
|
9960
|
+
fieldInputCol: css.css({
|
|
9961
|
+
display: "flex",
|
|
9962
|
+
flexDirection: "column",
|
|
9963
|
+
gap: theme.spacing(0.25),
|
|
9964
|
+
minWidth: 0
|
|
9965
|
+
}),
|
|
9966
|
+
fieldError: css.css({
|
|
9967
|
+
fontSize: theme.typography.bodySmall.fontSize,
|
|
9968
|
+
color: theme.colors.error.text
|
|
9969
|
+
})
|
|
9970
|
+
});
|
|
9971
|
+
|
|
9972
|
+
function SchemaField({
|
|
9973
|
+
field,
|
|
9974
|
+
control,
|
|
9975
|
+
errors,
|
|
9976
|
+
disabled,
|
|
9977
|
+
dsUid,
|
|
9978
|
+
watchedValues,
|
|
9979
|
+
fieldById,
|
|
9980
|
+
celContext,
|
|
9981
|
+
setValue
|
|
9982
|
+
}) {
|
|
9983
|
+
const styles = ui.useStyles2(getWizardStyles);
|
|
9984
|
+
const activeOverride = useDatasourceSchema.resolveActiveOverride(field, watchedValues, fieldById);
|
|
9985
|
+
const fk = useDatasourceSchema.formKey(field);
|
|
9986
|
+
if (field.key === "pdcInjected" && field.target === "jsonData") {
|
|
9987
|
+
return /* @__PURE__ */ React__default.default.createElement(
|
|
9988
|
+
reactHookForm.Controller,
|
|
9989
|
+
{
|
|
9990
|
+
name: fk,
|
|
9991
|
+
control,
|
|
9992
|
+
render: ({ field: formField }) => /* @__PURE__ */ React__default.default.createElement(
|
|
9993
|
+
PdcFieldNote,
|
|
9994
|
+
{
|
|
9995
|
+
enabled: !!formField.value,
|
|
9996
|
+
description: field.description,
|
|
9997
|
+
configUrl: `/connections/datasources/edit/${dsUid}`
|
|
9998
|
+
}
|
|
9999
|
+
)
|
|
10000
|
+
}
|
|
10001
|
+
);
|
|
10002
|
+
}
|
|
10003
|
+
const required = isFieldRequired(field, watchedValues, fieldById, celContext);
|
|
10004
|
+
const validationRules = buildValidationRules(field, required);
|
|
10005
|
+
return /* @__PURE__ */ React__default.default.createElement(
|
|
10006
|
+
reactHookForm.Controller,
|
|
10007
|
+
{
|
|
10008
|
+
name: fk,
|
|
10009
|
+
control,
|
|
10010
|
+
rules: validationRules,
|
|
10011
|
+
render: ({ field: formField }) => {
|
|
10012
|
+
var _a, _b, _c, _d, _e;
|
|
10013
|
+
const errorMessage = (_a = errors[fk]) == null ? void 0 : _a.message;
|
|
10014
|
+
const label = (_b = field.label) != null ? _b : field.key;
|
|
10015
|
+
const description = (_c = activeOverride == null ? void 0 : activeOverride.description) != null ? _c : field.description;
|
|
10016
|
+
const effectiveField = activeOverride ? {
|
|
10017
|
+
...field,
|
|
10018
|
+
description,
|
|
10019
|
+
ui: {
|
|
10020
|
+
...field.ui,
|
|
10021
|
+
placeholder: (_e = activeOverride.placeholder) != null ? _e : (_d = field.ui) == null ? void 0 : _d.placeholder
|
|
10022
|
+
}
|
|
10023
|
+
} : field;
|
|
10024
|
+
const isReadOnly = !!(activeOverride == null ? void 0 : activeOverride.readOnly);
|
|
10025
|
+
const isBool = field.valueType === "boolean";
|
|
10026
|
+
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)));
|
|
10027
|
+
}
|
|
10028
|
+
}
|
|
10029
|
+
);
|
|
10030
|
+
}
|
|
10031
|
+
|
|
10032
|
+
const AuthorizationHeaderField = (props) => {
|
|
10033
|
+
const { headersFieldKey, control, disabled, watchedValues } = props;
|
|
10034
|
+
const styles = ui.useStyles2(getWizardStyles);
|
|
10035
|
+
const items = React.useMemo(
|
|
10036
|
+
() => Array.isArray(watchedValues[headersFieldKey]) ? watchedValues[headersFieldKey] : [],
|
|
10037
|
+
[watchedValues, headersFieldKey]
|
|
10038
|
+
);
|
|
10039
|
+
const authEntries = React.useMemo(() => {
|
|
10040
|
+
const entries = [];
|
|
10041
|
+
for (let i = 0; i < items.length; i++) {
|
|
10042
|
+
if (items[i].name.toLowerCase() === "authorization") {
|
|
10043
|
+
entries.push({ item: items[i], originalIdx: i });
|
|
10044
|
+
}
|
|
10045
|
+
}
|
|
10046
|
+
return entries;
|
|
10047
|
+
}, [items]);
|
|
10048
|
+
if (authEntries.length === 0) {
|
|
10049
|
+
return null;
|
|
10050
|
+
}
|
|
10051
|
+
const authItems = authEntries.map((e) => e.item);
|
|
10052
|
+
return /* @__PURE__ */ React__default.default.createElement(
|
|
10053
|
+
reactHookForm.Controller,
|
|
10054
|
+
{
|
|
10055
|
+
name: headersFieldKey,
|
|
10056
|
+
control,
|
|
10057
|
+
render: ({ field: formField }) => {
|
|
10058
|
+
const handleChange = (updatedAuthItems) => {
|
|
10059
|
+
const updated = [...items];
|
|
10060
|
+
for (let i = 0; i < authEntries.length; i++) {
|
|
10061
|
+
if (i < updatedAuthItems.length) {
|
|
10062
|
+
updated[authEntries[i].originalIdx] = updatedAuthItems[i];
|
|
10063
|
+
}
|
|
10064
|
+
}
|
|
10065
|
+
formField.onChange(updated);
|
|
10066
|
+
};
|
|
10067
|
+
return /* @__PURE__ */ React__default.default.createElement("div", { className: styles.fieldRow }, /* @__PURE__ */ React__default.default.createElement("div", { className: styles.fieldLabelRow }, /* @__PURE__ */ React__default.default.createElement("span", { className: styles.fieldLabel }, "Custom HTTP Headers"), /* @__PURE__ */ React__default.default.createElement(ui.Tooltip, { content: "Authorization HTTP header(s) sent with every request." }, /* @__PURE__ */ React__default.default.createElement(ui.Icon, { name: "info-circle", size: "xs", className: styles.fieldInfoIcon }))), /* @__PURE__ */ React__default.default.createElement("div", { className: styles.fieldInputCol }, /* @__PURE__ */ React__default.default.createElement(IndexedPairEditor, { value: authItems, onChange: handleChange, disabled, hideControls: true })));
|
|
10068
|
+
}
|
|
10069
|
+
}
|
|
10070
|
+
);
|
|
10071
|
+
};
|
|
10072
|
+
|
|
10073
|
+
function SidebarNav({ groups, activeIndex, sectionStates, onSelect }) {
|
|
10074
|
+
const styles = ui.useStyles2(getTabStyles);
|
|
10075
|
+
const visibleGroups = groups.filter((g) => g.group.id !== "_required");
|
|
10076
|
+
return /* @__PURE__ */ React__default.default.createElement("nav", { className: styles.sidebar }, /* @__PURE__ */ React__default.default.createElement("div", { className: styles.sidebarTitle }, "Connect data source"), /* @__PURE__ */ React__default.default.createElement("ul", { className: styles.navList }, visibleGroups.map((g, vi) => {
|
|
10077
|
+
var _a, _b;
|
|
10078
|
+
const origIndex = groups.indexOf(g);
|
|
10079
|
+
const state = (_a = sectionStates[origIndex]) != null ? _a : "draft";
|
|
10080
|
+
const isActive = origIndex === activeIndex;
|
|
10081
|
+
const isOptional = g.group.optional === true;
|
|
10082
|
+
const isLast = vi === visibleGroups.length - 1;
|
|
10083
|
+
const nextIsOptional = !isLast && ((_b = visibleGroups[vi + 1]) == null ? void 0 : _b.group.optional) === true;
|
|
10084
|
+
return /* @__PURE__ */ React__default.default.createElement("li", { key: g.group.id }, /* @__PURE__ */ React__default.default.createElement(
|
|
10085
|
+
"div",
|
|
10086
|
+
{
|
|
10087
|
+
className: css.cx(styles.navItem, isActive && styles.navItemActive),
|
|
10088
|
+
onClick: () => onSelect(origIndex),
|
|
10089
|
+
role: "button",
|
|
10090
|
+
tabIndex: 0,
|
|
10091
|
+
onKeyDown: (e) => {
|
|
10092
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
10093
|
+
e.preventDefault();
|
|
10094
|
+
onSelect(origIndex);
|
|
10095
|
+
}
|
|
10096
|
+
}
|
|
10097
|
+
},
|
|
10098
|
+
/* @__PURE__ */ React__default.default.createElement("div", { className: styles.navDotWrap }, /* @__PURE__ */ React__default.default.createElement(
|
|
10099
|
+
"span",
|
|
10100
|
+
{
|
|
10101
|
+
className: css.cx(
|
|
10102
|
+
styles.navDot,
|
|
10103
|
+
isOptional && styles.navDotOptional,
|
|
10104
|
+
isActive && styles.navDotActive,
|
|
10105
|
+
state === "validated" && !isActive && styles.navDotValidated,
|
|
10106
|
+
state === "error" && !isActive && styles.navDotError
|
|
10107
|
+
)
|
|
10108
|
+
}
|
|
10109
|
+
), !isLast && /* @__PURE__ */ React__default.default.createElement(
|
|
10110
|
+
"div",
|
|
10111
|
+
{
|
|
10112
|
+
className: css.cx(styles.navConnector, (isOptional || nextIsOptional) && styles.navConnectorDashed)
|
|
10113
|
+
}
|
|
10114
|
+
)),
|
|
10115
|
+
/* @__PURE__ */ React__default.default.createElement("span", { className: css.cx(styles.navLabel, isActive && styles.navLabelActive) }, g.group.title)
|
|
10116
|
+
));
|
|
10117
|
+
})));
|
|
10118
|
+
}
|
|
10119
|
+
|
|
10120
|
+
function TabLayout({ form, schema, dsUid, dsName, onRetest, healthError, renderActions }) {
|
|
10121
|
+
const styles = ui.useStyles2(getTabStyles);
|
|
10122
|
+
const sectionRefs = React.useRef(/* @__PURE__ */ new Map());
|
|
10123
|
+
const {
|
|
10124
|
+
resolvedGroups,
|
|
10125
|
+
fieldById,
|
|
10126
|
+
httpHeadersField,
|
|
10127
|
+
control,
|
|
10128
|
+
handleSubmit,
|
|
10129
|
+
errors,
|
|
10130
|
+
watchedValues,
|
|
10131
|
+
celContext,
|
|
10132
|
+
initializing,
|
|
10133
|
+
fetchError,
|
|
10134
|
+
submitting,
|
|
10135
|
+
submitError,
|
|
10136
|
+
readOnly,
|
|
10137
|
+
isFieldVisible,
|
|
10138
|
+
isFieldDisabled,
|
|
10139
|
+
isGroupValid,
|
|
10140
|
+
groupHasData,
|
|
10141
|
+
onSubmit,
|
|
10142
|
+
setValue
|
|
10143
|
+
} = form;
|
|
10144
|
+
const displayGroups = React.useMemo(() => resolvedGroups.filter((g) => g.group.id !== "_required"), [resolvedGroups]);
|
|
10145
|
+
const [expandedSections, setExpandedSections] = React.useState(() => {
|
|
10146
|
+
const expanded = /* @__PURE__ */ new Set();
|
|
10147
|
+
for (let i = 0; i < displayGroups.length; i++) {
|
|
10148
|
+
if (!displayGroups[i].group.optional) {
|
|
10149
|
+
expanded.add(i);
|
|
10150
|
+
}
|
|
10151
|
+
}
|
|
10152
|
+
return expanded;
|
|
10153
|
+
});
|
|
10154
|
+
const hasExpandedForData = React.useRef(false);
|
|
10155
|
+
React.useMemo(() => {
|
|
10156
|
+
if (initializing || hasExpandedForData.current) {
|
|
10157
|
+
return;
|
|
10158
|
+
}
|
|
10159
|
+
hasExpandedForData.current = true;
|
|
10160
|
+
setExpandedSections((prev) => {
|
|
10161
|
+
const next = new Set(prev);
|
|
10162
|
+
for (let i = 0; i < displayGroups.length; i++) {
|
|
10163
|
+
if (groupHasData(displayGroups[i])) {
|
|
10164
|
+
next.add(i);
|
|
10165
|
+
}
|
|
10166
|
+
}
|
|
10167
|
+
return next;
|
|
10168
|
+
});
|
|
10169
|
+
}, [initializing, displayGroups, groupHasData]);
|
|
10170
|
+
const [activeSection, setActiveSection] = React.useState(0);
|
|
10171
|
+
const toggleSection = React.useCallback((index) => {
|
|
10172
|
+
setExpandedSections((prev) => {
|
|
10173
|
+
const next = new Set(prev);
|
|
10174
|
+
if (next.has(index)) {
|
|
10175
|
+
next.delete(index);
|
|
10176
|
+
} else {
|
|
10177
|
+
next.add(index);
|
|
10178
|
+
}
|
|
10179
|
+
return next;
|
|
10180
|
+
});
|
|
10181
|
+
}, []);
|
|
10182
|
+
const scrollToSection = React.useCallback(
|
|
10183
|
+
(index) => {
|
|
10184
|
+
setActiveSection(index);
|
|
10185
|
+
if (!expandedSections.has(index)) {
|
|
10186
|
+
setExpandedSections((prev) => new Set(prev).add(index));
|
|
10187
|
+
}
|
|
10188
|
+
const el = sectionRefs.current.get(index);
|
|
10189
|
+
if (el) {
|
|
10190
|
+
el.scrollIntoView({ behavior: "smooth", block: "start" });
|
|
10191
|
+
}
|
|
10192
|
+
},
|
|
10193
|
+
[expandedSections]
|
|
10194
|
+
);
|
|
10195
|
+
const sectionStates = React.useMemo(() => {
|
|
10196
|
+
return displayGroups.map((g, i) => {
|
|
10197
|
+
if (i === activeSection) {
|
|
10198
|
+
return "active";
|
|
10199
|
+
}
|
|
10200
|
+
if (!isGroupValid(g)) {
|
|
10201
|
+
return "error";
|
|
10202
|
+
}
|
|
10203
|
+
if (groupHasData(g)) {
|
|
10204
|
+
return "validated";
|
|
10205
|
+
}
|
|
10206
|
+
return "draft";
|
|
10207
|
+
});
|
|
10208
|
+
}, [displayGroups, activeSection, isGroupValid, groupHasData]);
|
|
10209
|
+
if (initializing) {
|
|
10210
|
+
return /* @__PURE__ */ React__default.default.createElement("div", { className: styles.loadingContainer }, /* @__PURE__ */ React__default.default.createElement(ui.Spinner, { size: "sm", inline: true }), " Loading configuration\u2026");
|
|
10211
|
+
}
|
|
10212
|
+
if (fetchError) {
|
|
10213
|
+
return /* @__PURE__ */ React__default.default.createElement("div", null, /* @__PURE__ */ React__default.default.createElement(ui.Alert, { severity: "error", title: "Failed to load configuration" }, fetchError), /* @__PURE__ */ React__default.default.createElement("div", { className: styles.formButtons }, /* @__PURE__ */ React__default.default.createElement(
|
|
10214
|
+
ui.LinkButton,
|
|
10215
|
+
{
|
|
10216
|
+
variant: "secondary",
|
|
10217
|
+
size: "sm",
|
|
10218
|
+
icon: "external-link-alt",
|
|
10219
|
+
href: `/connections/datasources/edit/${dsUid}`
|
|
10220
|
+
},
|
|
10221
|
+
"Open datasource settings"
|
|
10222
|
+
)));
|
|
10223
|
+
}
|
|
10224
|
+
const allDisabled = submitting || readOnly;
|
|
10225
|
+
return /* @__PURE__ */ React__default.default.createElement("div", { className: styles.root }, submitting && /* @__PURE__ */ React__default.default.createElement("div", { className: styles.overlay }, /* @__PURE__ */ React__default.default.createElement(ui.Spinner, { size: "sm" }), /* @__PURE__ */ React__default.default.createElement("span", null, "Saving & testing\u2026")), /* @__PURE__ */ React__default.default.createElement(
|
|
10226
|
+
SidebarNav,
|
|
10227
|
+
{
|
|
10228
|
+
groups: displayGroups,
|
|
10229
|
+
activeIndex: activeSection,
|
|
10230
|
+
sectionStates,
|
|
10231
|
+
onSelect: scrollToSection
|
|
10232
|
+
}
|
|
10233
|
+
), /* @__PURE__ */ React__default.default.createElement("div", { className: styles.main }, readOnly && /* @__PURE__ */ React__default.default.createElement("div", { className: styles.readOnlyBanner }, /* @__PURE__ */ React__default.default.createElement(ui.Icon, { name: "lock", size: "xs" }), /* @__PURE__ */ React__default.default.createElement("span", null, "Read-only \u2014 managed externally")), /* @__PURE__ */ React__default.default.createElement("div", { className: styles.requiredNotice }, "Fields marked with * are required"), /* @__PURE__ */ React__default.default.createElement("form", { onSubmit: handleSubmit(onSubmit), className: styles.form }, displayGroups.map((g, i) => {
|
|
10234
|
+
const visibleFields = g.fields.filter(isFieldVisible);
|
|
10235
|
+
if (visibleFields.length === 0 && !httpHeadersField) {
|
|
10236
|
+
return null;
|
|
10237
|
+
}
|
|
10238
|
+
const showHeaders = httpHeadersField && (g.group.id === "auth" || g.group.id === "url-and-auth" || g.group.id === "_required" || g.group.fieldRefs.includes("httpHeaders"));
|
|
10239
|
+
const sectionLabel = /* @__PURE__ */ React__default.default.createElement("span", { className: styles.sectionLabel }, /* @__PURE__ */ React__default.default.createElement("span", { className: styles.sectionLabelText }, g.group.title), g.group.optional && /* @__PURE__ */ React__default.default.createElement("span", { className: styles.sectionBadge }, "Optional"));
|
|
10240
|
+
return /* @__PURE__ */ React__default.default.createElement(
|
|
10241
|
+
"div",
|
|
10242
|
+
{
|
|
10243
|
+
key: g.group.id,
|
|
10244
|
+
ref: (el) => {
|
|
10245
|
+
if (el) {
|
|
10246
|
+
sectionRefs.current.set(i, el);
|
|
10247
|
+
}
|
|
10248
|
+
},
|
|
10249
|
+
className: styles.section
|
|
10250
|
+
},
|
|
10251
|
+
/* @__PURE__ */ React__default.default.createElement(
|
|
10252
|
+
ui.Collapse,
|
|
10253
|
+
{
|
|
10254
|
+
label: sectionLabel,
|
|
10255
|
+
isOpen: expandedSections.has(i),
|
|
10256
|
+
collapsible: true,
|
|
10257
|
+
onToggle: () => {
|
|
10258
|
+
toggleSection(i);
|
|
10259
|
+
setActiveSection(i);
|
|
10260
|
+
},
|
|
10261
|
+
className: styles.collapseHeader
|
|
10262
|
+
},
|
|
10263
|
+
/* @__PURE__ */ React__default.default.createElement("div", { className: styles.sectionBody }, g.group.description && /* @__PURE__ */ React__default.default.createElement("div", { className: styles.sectionDescription }, g.group.description), visibleFields.map((field) => /* @__PURE__ */ React__default.default.createElement(
|
|
10264
|
+
SchemaField,
|
|
10265
|
+
{
|
|
10266
|
+
key: useDatasourceSchema.formKey(field),
|
|
10267
|
+
field,
|
|
10268
|
+
control,
|
|
10269
|
+
errors,
|
|
10270
|
+
disabled: allDisabled || isFieldDisabled(field),
|
|
10271
|
+
dsUid,
|
|
10272
|
+
watchedValues,
|
|
10273
|
+
fieldById,
|
|
10274
|
+
celContext,
|
|
10275
|
+
setValue
|
|
10276
|
+
}
|
|
10277
|
+
)), showHeaders && /* @__PURE__ */ React__default.default.createElement(
|
|
10278
|
+
AuthorizationHeaderField,
|
|
10279
|
+
{
|
|
10280
|
+
headersFieldKey: useDatasourceSchema.formKey(httpHeadersField),
|
|
10281
|
+
control,
|
|
10282
|
+
disabled: allDisabled,
|
|
10283
|
+
watchedValues
|
|
10284
|
+
}
|
|
10285
|
+
))
|
|
10286
|
+
)
|
|
10287
|
+
);
|
|
10288
|
+
}), submitError && /* @__PURE__ */ React__default.default.createElement(ui.Alert, { severity: "error", title: "Error" }, submitError), /* @__PURE__ */ React__default.default.createElement("div", { className: styles.formButtons }, 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, type: "submit" }, submitting ? "Saving\u2026" : "Save & Test"), healthError && (renderActions == null ? void 0 : renderActions({ dsUid, dsName, dsType: schema.pluginType, healthError }))))));
|
|
10289
|
+
}
|
|
10290
|
+
|
|
10291
|
+
function useDatasourceConfigForm({ schema, dsUid, onSuccess, onSaving }) {
|
|
10292
|
+
const [submitting, setSubmitting] = React.useState(false);
|
|
10293
|
+
const [submitError, setSubmitError] = React.useState(null);
|
|
10294
|
+
const [initializing, setInitializing] = React.useState(true);
|
|
10295
|
+
const [fetchError, setFetchError] = React.useState(null);
|
|
10296
|
+
const [detectedReadOnly, setDetectedReadOnly] = React.useState(false);
|
|
10297
|
+
const readOnly = detectedReadOnly;
|
|
10298
|
+
const resolvedGroups = React.useMemo(() => {
|
|
10299
|
+
const groups = useDatasourceSchema.resolveGroups(schema);
|
|
10300
|
+
const requiredGroup = useDatasourceSchema.resolveRequiredFieldsGroup(schema);
|
|
10301
|
+
if (!requiredGroup) {
|
|
10302
|
+
return groups;
|
|
10303
|
+
}
|
|
10304
|
+
return [requiredGroup, ...groups];
|
|
10305
|
+
}, [schema]);
|
|
10306
|
+
const fieldById = React.useMemo(() => {
|
|
10307
|
+
const m = /* @__PURE__ */ new Map();
|
|
10308
|
+
for (const f of schema.fields) {
|
|
10309
|
+
m.set(f.id, f);
|
|
10310
|
+
}
|
|
10311
|
+
return m;
|
|
10312
|
+
}, [schema.fields]);
|
|
10313
|
+
const httpHeadersField = React.useMemo(
|
|
10314
|
+
() => {
|
|
10315
|
+
var _a;
|
|
10316
|
+
return (_a = schema.fields.find((f) => {
|
|
10317
|
+
var _a2;
|
|
10318
|
+
return f.key === "httpHeaders" && ((_a2 = f.storage) == null ? void 0 : _a2.type) === "indexedPair";
|
|
10319
|
+
})) != null ? _a : null;
|
|
10320
|
+
},
|
|
10321
|
+
[schema.fields]
|
|
10322
|
+
);
|
|
10323
|
+
const allStorageFields = React.useMemo(
|
|
10324
|
+
() => schema.fields.filter((f) => f.kind !== "virtual" && !f.isItemField && f.target),
|
|
10325
|
+
[schema.fields]
|
|
10326
|
+
);
|
|
10327
|
+
const {
|
|
10328
|
+
control,
|
|
10329
|
+
handleSubmit,
|
|
10330
|
+
watch,
|
|
10331
|
+
reset,
|
|
10332
|
+
trigger,
|
|
10333
|
+
setValue,
|
|
10334
|
+
formState: { errors }
|
|
10335
|
+
} = reactHookForm.useForm({ mode: "onChange" });
|
|
10336
|
+
const fieldsWithEffects = React.useMemo(() => {
|
|
10337
|
+
const result = [];
|
|
10338
|
+
for (const field of schema.fields) {
|
|
10339
|
+
if (!field.effects || field.effects.length === 0) {
|
|
10340
|
+
continue;
|
|
10341
|
+
}
|
|
10342
|
+
const mapped = field.effects.map((eff) => ({
|
|
10343
|
+
when: eff.when,
|
|
10344
|
+
targets: Object.entries(eff.set).map(([targetId, val]) => {
|
|
10345
|
+
const targetField = fieldById.get(targetId);
|
|
10346
|
+
return { key: targetField ? useDatasourceSchema.formKey(targetField) : targetId, value: val };
|
|
10347
|
+
})
|
|
10348
|
+
}));
|
|
10349
|
+
result.push({ sourceKey: useDatasourceSchema.formKey(field), effects: mapped });
|
|
10350
|
+
}
|
|
10351
|
+
return result;
|
|
10352
|
+
}, [schema.fields, fieldById]);
|
|
10353
|
+
React.useEffect(() => {
|
|
10354
|
+
let cancelled = false;
|
|
10355
|
+
fetchExistingValues(dsUid, allStorageFields).then((result) => {
|
|
10356
|
+
if (cancelled) {
|
|
10357
|
+
return;
|
|
10358
|
+
}
|
|
10359
|
+
if (result.error) {
|
|
10360
|
+
setFetchError(result.error);
|
|
10361
|
+
setInitializing(false);
|
|
10362
|
+
return;
|
|
10363
|
+
}
|
|
10364
|
+
if (result.readOnly) {
|
|
10365
|
+
setDetectedReadOnly(true);
|
|
10366
|
+
}
|
|
10367
|
+
const defaults = {};
|
|
10368
|
+
for (const field of allStorageFields) {
|
|
10369
|
+
if (field.defaultValue !== void 0) {
|
|
10370
|
+
defaults[useDatasourceSchema.formKey(field)] = field.defaultValue;
|
|
10371
|
+
}
|
|
10372
|
+
}
|
|
10373
|
+
const merged = { ...defaults, ...result.values };
|
|
10374
|
+
const virtualValues = useDatasourceSchema.computeVirtualFieldValues(schema, merged);
|
|
10375
|
+
reset({ ...merged, ...virtualValues });
|
|
10376
|
+
setInitializing(false);
|
|
10377
|
+
});
|
|
10378
|
+
return () => {
|
|
10379
|
+
cancelled = true;
|
|
10380
|
+
};
|
|
10381
|
+
}, [dsUid, allStorageFields, schema, reset]);
|
|
10382
|
+
const watchedValues = watch();
|
|
10383
|
+
const prevEffectValuesRef = React.useRef({});
|
|
10384
|
+
React.useEffect(() => {
|
|
10385
|
+
if (initializing) {
|
|
10386
|
+
return;
|
|
10387
|
+
}
|
|
10388
|
+
for (const { sourceKey, effects } of fieldsWithEffects) {
|
|
10389
|
+
const currentVal = useDatasourceSchema.getWatchedValue(watchedValues, sourceKey);
|
|
10390
|
+
const prevVal = prevEffectValuesRef.current[sourceKey];
|
|
10391
|
+
if (currentVal === prevVal) {
|
|
10392
|
+
continue;
|
|
10393
|
+
}
|
|
10394
|
+
prevEffectValuesRef.current[sourceKey] = currentVal;
|
|
10395
|
+
for (const eff of effects) {
|
|
10396
|
+
if (evaluateEffectCondition(eff.when, currentVal)) {
|
|
10397
|
+
for (const { key, value } of eff.targets) {
|
|
10398
|
+
setValue(key, value);
|
|
10399
|
+
}
|
|
10400
|
+
break;
|
|
10401
|
+
}
|
|
10402
|
+
}
|
|
10403
|
+
}
|
|
10404
|
+
}, [watchedValues, fieldsWithEffects, initializing, setValue]);
|
|
10405
|
+
const fieldsWithOverrideDefaults = React.useMemo(() => {
|
|
10406
|
+
const result = [];
|
|
10407
|
+
for (const field of schema.fields) {
|
|
10408
|
+
if (!field.overrides || field.overrides.length === 0) {
|
|
10409
|
+
continue;
|
|
10410
|
+
}
|
|
10411
|
+
const ovs = field.overrides.filter((ov) => ov.defaultValue !== void 0).map((ov) => {
|
|
10412
|
+
const parsed = useDatasourceSchema.parseDependsOn(ov.when);
|
|
10413
|
+
if (!parsed) {
|
|
10414
|
+
return null;
|
|
10415
|
+
}
|
|
10416
|
+
const depField = fieldById.get(parsed.field);
|
|
10417
|
+
return {
|
|
10418
|
+
depKey: depField ? useDatasourceSchema.formKey(depField) : parsed.field,
|
|
10419
|
+
depValue: parsed.value,
|
|
10420
|
+
negate: parsed.negate,
|
|
10421
|
+
defaultValue: ov.defaultValue
|
|
10422
|
+
};
|
|
10423
|
+
}).filter(Boolean);
|
|
10424
|
+
if (ovs.length > 0) {
|
|
10425
|
+
result.push({ targetKey: useDatasourceSchema.formKey(field), fieldDefault: field.defaultValue, overrides: ovs });
|
|
10426
|
+
}
|
|
10427
|
+
}
|
|
10428
|
+
return result;
|
|
10429
|
+
}, [schema.fields, fieldById]);
|
|
10430
|
+
const prevOverrideDepRef = React.useRef({});
|
|
10431
|
+
React.useEffect(() => {
|
|
10432
|
+
var _a;
|
|
10433
|
+
if (initializing) {
|
|
10434
|
+
return;
|
|
10435
|
+
}
|
|
10436
|
+
for (const { targetKey, fieldDefault, overrides } of fieldsWithOverrideDefaults) {
|
|
10437
|
+
for (const ov of overrides) {
|
|
10438
|
+
const currentDepVal = String((_a = useDatasourceSchema.getWatchedValue(watchedValues, ov.depKey)) != null ? _a : "");
|
|
10439
|
+
const trackKey = `${targetKey}::${ov.depKey}`;
|
|
10440
|
+
const prevDepVal = prevOverrideDepRef.current[trackKey];
|
|
10441
|
+
if (currentDepVal === prevDepVal) {
|
|
10442
|
+
continue;
|
|
10443
|
+
}
|
|
10444
|
+
prevOverrideDepRef.current[trackKey] = currentDepVal;
|
|
10445
|
+
const active = useDatasourceSchema.evaluateDependsOn({ value: ov.depValue, negate: ov.negate }, currentDepVal);
|
|
10446
|
+
const wasActive = prevDepVal !== void 0 && useDatasourceSchema.evaluateDependsOn({ value: ov.depValue, negate: ov.negate }, prevDepVal);
|
|
10447
|
+
if (active) {
|
|
10448
|
+
setValue(targetKey, ov.defaultValue);
|
|
10449
|
+
} else if (wasActive && fieldDefault !== void 0) {
|
|
10450
|
+
setValue(targetKey, fieldDefault);
|
|
10451
|
+
}
|
|
10452
|
+
}
|
|
10453
|
+
}
|
|
10454
|
+
}, [watchedValues, fieldsWithOverrideDefaults, initializing, setValue]);
|
|
10455
|
+
const celContext = React.useMemo(() => {
|
|
10456
|
+
const ctx = {};
|
|
10457
|
+
for (const f of fieldById.values()) {
|
|
10458
|
+
const fk = useDatasourceSchema.formKey(f);
|
|
10459
|
+
const val = useDatasourceSchema.getWatchedValue(watchedValues, fk);
|
|
10460
|
+
if (val !== void 0) {
|
|
10461
|
+
const parts = f.id.split(".");
|
|
10462
|
+
let current = ctx;
|
|
10463
|
+
for (let i = 0; i < parts.length - 1; i++) {
|
|
10464
|
+
if (!(parts[i] in current) || typeof current[parts[i]] !== "object" || current[parts[i]] === null) {
|
|
10465
|
+
current[parts[i]] = {};
|
|
10466
|
+
}
|
|
10467
|
+
current = current[parts[i]];
|
|
10468
|
+
}
|
|
10469
|
+
current[parts[parts.length - 1]] = val;
|
|
10470
|
+
}
|
|
10471
|
+
}
|
|
10472
|
+
return ctx;
|
|
10473
|
+
}, [watchedValues, fieldById]);
|
|
10474
|
+
const isFieldVisible = React.useCallback(
|
|
10475
|
+
(field) => {
|
|
10476
|
+
function check(f, visited) {
|
|
10477
|
+
var _a;
|
|
10478
|
+
if (f.kind === "virtual" && !f.ui) {
|
|
10479
|
+
return false;
|
|
10480
|
+
}
|
|
10481
|
+
if ((_a = f.tags) == null ? void 0 : _a.some((t) => t.startsWith("managed-by:"))) {
|
|
10482
|
+
return false;
|
|
10483
|
+
}
|
|
10484
|
+
if (!f.dependsOn) {
|
|
10485
|
+
return true;
|
|
10486
|
+
}
|
|
10487
|
+
const refs = useDatasourceSchema.extractFieldRefs(f.dependsOn);
|
|
10488
|
+
for (const ref of refs) {
|
|
10489
|
+
const depField = fieldById.get(ref);
|
|
10490
|
+
if (depField && !visited.has(depField.id)) {
|
|
10491
|
+
visited.add(f.id);
|
|
10492
|
+
if (!check(depField, visited)) {
|
|
10493
|
+
return false;
|
|
10494
|
+
}
|
|
10495
|
+
}
|
|
10496
|
+
}
|
|
10497
|
+
return useDatasourceSchema.evaluateCelExpression(f.dependsOn, celContext);
|
|
10498
|
+
}
|
|
10499
|
+
return check(field, /* @__PURE__ */ new Set());
|
|
10500
|
+
},
|
|
10501
|
+
[celContext, fieldById]
|
|
10502
|
+
);
|
|
10503
|
+
const onSubmit = React.useCallback(
|
|
10504
|
+
async (data) => {
|
|
10505
|
+
setSubmitting(true);
|
|
10506
|
+
setSubmitError(null);
|
|
10507
|
+
onSaving == null ? void 0 : onSaving(true);
|
|
10508
|
+
const minDelay = new Promise((r) => setTimeout(r, 2e3));
|
|
10509
|
+
try {
|
|
10510
|
+
await submitDatasourceConfig(dsUid, data, allStorageFields, isFieldVisible);
|
|
10511
|
+
const [refreshed] = await Promise.all([fetchExistingValues(dsUid, allStorageFields), minDelay]);
|
|
10512
|
+
const defaults = {};
|
|
10513
|
+
for (const field of allStorageFields) {
|
|
10514
|
+
if (field.defaultValue !== void 0) {
|
|
10515
|
+
defaults[useDatasourceSchema.formKey(field)] = field.defaultValue;
|
|
10516
|
+
}
|
|
10517
|
+
}
|
|
10518
|
+
const merged = { ...defaults, ...refreshed.values };
|
|
10519
|
+
const virtualValues = useDatasourceSchema.computeVirtualFieldValues(schema, merged);
|
|
10520
|
+
reset({ ...merged, ...virtualValues });
|
|
10521
|
+
onSuccess("UPDATED", "Configuration saved.");
|
|
10522
|
+
} catch (err) {
|
|
10523
|
+
await minDelay;
|
|
10524
|
+
setSubmitError(err instanceof Error ? err.message : "Failed to update datasource");
|
|
10525
|
+
} finally {
|
|
10526
|
+
setSubmitting(false);
|
|
10527
|
+
onSaving == null ? void 0 : onSaving(false);
|
|
10528
|
+
}
|
|
10529
|
+
},
|
|
10530
|
+
[dsUid, allStorageFields, isFieldVisible, schema, reset, onSuccess, onSaving]
|
|
10531
|
+
);
|
|
10532
|
+
const isGroupValid = React.useCallback(
|
|
10533
|
+
(group) => {
|
|
10534
|
+
for (const field of group.fields) {
|
|
10535
|
+
if (!isFieldVisible(field)) {
|
|
10536
|
+
continue;
|
|
10537
|
+
}
|
|
10538
|
+
if (errors[useDatasourceSchema.formKey(field)]) {
|
|
10539
|
+
return false;
|
|
10540
|
+
}
|
|
10541
|
+
if (isFieldRequired(field, watchedValues, fieldById, celContext)) {
|
|
10542
|
+
const val = useDatasourceSchema.getWatchedValue(watchedValues, useDatasourceSchema.formKey(field));
|
|
10543
|
+
if (val === SECURE_FIELD_CONFIGURED) {
|
|
10544
|
+
continue;
|
|
10545
|
+
}
|
|
10546
|
+
if (val === void 0 || val === null || val === "") {
|
|
10547
|
+
return false;
|
|
10548
|
+
}
|
|
10549
|
+
}
|
|
10550
|
+
}
|
|
10551
|
+
return true;
|
|
10552
|
+
},
|
|
10553
|
+
[errors, watchedValues, fieldById, celContext, isFieldVisible]
|
|
10554
|
+
);
|
|
10555
|
+
const isFieldDisabled = React.useCallback(
|
|
10556
|
+
(field) => {
|
|
10557
|
+
if (!field.disabledWhen) {
|
|
10558
|
+
return false;
|
|
10559
|
+
}
|
|
10560
|
+
return useDatasourceSchema.evaluateCelExpression(field.disabledWhen, celContext);
|
|
10561
|
+
},
|
|
10562
|
+
[celContext]
|
|
10563
|
+
);
|
|
10564
|
+
const groupHasData = React.useCallback(
|
|
10565
|
+
(group) => {
|
|
10566
|
+
for (const field of group.fields) {
|
|
10567
|
+
const val = useDatasourceSchema.getWatchedValue(watchedValues, useDatasourceSchema.formKey(field));
|
|
10568
|
+
if (val === void 0 || val === null || val === "" || val === false) {
|
|
10569
|
+
continue;
|
|
10570
|
+
}
|
|
10571
|
+
if (val === field.defaultValue) {
|
|
10572
|
+
continue;
|
|
10573
|
+
}
|
|
10574
|
+
return true;
|
|
10575
|
+
}
|
|
10576
|
+
return false;
|
|
10577
|
+
},
|
|
10578
|
+
[watchedValues]
|
|
10579
|
+
);
|
|
10580
|
+
return {
|
|
10581
|
+
// Schema
|
|
10582
|
+
resolvedGroups,
|
|
10583
|
+
fieldById,
|
|
10584
|
+
httpHeadersField,
|
|
10585
|
+
// Form
|
|
10586
|
+
control,
|
|
10587
|
+
handleSubmit,
|
|
10588
|
+
trigger,
|
|
10589
|
+
errors,
|
|
10590
|
+
watchedValues,
|
|
10591
|
+
celContext,
|
|
10592
|
+
// State
|
|
10593
|
+
initializing,
|
|
10594
|
+
fetchError,
|
|
10595
|
+
submitting,
|
|
10596
|
+
submitError,
|
|
10597
|
+
readOnly,
|
|
10598
|
+
// Callbacks
|
|
10599
|
+
isFieldVisible,
|
|
10600
|
+
isFieldDisabled,
|
|
10601
|
+
isGroupValid,
|
|
10602
|
+
groupHasData,
|
|
10603
|
+
onSubmit,
|
|
10604
|
+
setValue
|
|
10605
|
+
};
|
|
10606
|
+
}
|
|
10607
|
+
|
|
10608
|
+
function DatasourceConfigWizard(props) {
|
|
10609
|
+
const { schema, dsUid, dsName, onSuccess, onSaving, onRetest, healthError, renderActions, mode = "tab" } = props;
|
|
10610
|
+
const form = useDatasourceConfigForm({ schema, dsUid, onSuccess, onSaving });
|
|
10611
|
+
if (mode === "tab") {
|
|
10612
|
+
return /* @__PURE__ */ React__default.default.createElement(
|
|
10613
|
+
TabLayout,
|
|
10614
|
+
{
|
|
10615
|
+
form,
|
|
10616
|
+
schema,
|
|
10617
|
+
dsUid,
|
|
10618
|
+
dsName,
|
|
10619
|
+
onRetest,
|
|
10620
|
+
healthError,
|
|
10621
|
+
renderActions
|
|
10622
|
+
}
|
|
10623
|
+
);
|
|
10624
|
+
}
|
|
10625
|
+
return /* @__PURE__ */ React__default.default.createElement(
|
|
10626
|
+
WizardLayout,
|
|
10627
|
+
{
|
|
10628
|
+
form,
|
|
10629
|
+
schema,
|
|
10630
|
+
dsUid,
|
|
10631
|
+
dsName,
|
|
10632
|
+
onRetest,
|
|
10633
|
+
healthError,
|
|
10634
|
+
renderActions
|
|
10635
|
+
}
|
|
10636
|
+
);
|
|
10637
|
+
}
|
|
10638
|
+
function WizardLayout({ form, schema, dsUid, dsName, onRetest, healthError, renderActions }) {
|
|
10639
|
+
var _a, _b, _c;
|
|
10640
|
+
const styles = ui.useStyles2(getWizardStyles);
|
|
10641
|
+
const [currentStep, setCurrentStep] = React.useState(0);
|
|
10642
|
+
const {
|
|
10643
|
+
resolvedGroups,
|
|
10644
|
+
fieldById,
|
|
10645
|
+
httpHeadersField,
|
|
10646
|
+
control,
|
|
10647
|
+
handleSubmit,
|
|
10648
|
+
trigger,
|
|
10649
|
+
errors,
|
|
10650
|
+
watchedValues,
|
|
10651
|
+
celContext,
|
|
10652
|
+
initializing,
|
|
10653
|
+
fetchError,
|
|
10654
|
+
submitting,
|
|
10655
|
+
submitError,
|
|
10656
|
+
readOnly,
|
|
10657
|
+
isFieldVisible,
|
|
10658
|
+
isFieldDisabled,
|
|
10659
|
+
onSubmit,
|
|
10660
|
+
setValue
|
|
10661
|
+
} = form;
|
|
10662
|
+
const arrowSteps = React.useMemo(() => {
|
|
10663
|
+
const requiredGroup = resolvedGroups.find((g) => g.group.id === "_required");
|
|
10664
|
+
if (!requiredGroup) {
|
|
10665
|
+
return new Set(resolvedGroups.map((_, i) => i));
|
|
10666
|
+
}
|
|
10667
|
+
const requiredFieldIds = new Set(requiredGroup.fields.map((f) => f.id));
|
|
10668
|
+
const steps = /* @__PURE__ */ new Set();
|
|
10669
|
+
for (let i = 0; i < resolvedGroups.length; i++) {
|
|
10670
|
+
const g = resolvedGroups[i];
|
|
10671
|
+
if (g.group.id === "_required" || g.fields.some((f) => !requiredFieldIds.has(f.id))) {
|
|
10672
|
+
steps.add(i);
|
|
10673
|
+
}
|
|
10674
|
+
}
|
|
10675
|
+
return steps;
|
|
10676
|
+
}, [resolvedGroups]);
|
|
10677
|
+
const currentResolved = resolvedGroups[currentStep];
|
|
10678
|
+
const isFirstStep = React.useMemo(() => {
|
|
10679
|
+
for (let i = 0; i < currentStep; i++) {
|
|
10680
|
+
if (arrowSteps.has(i)) {
|
|
10681
|
+
return false;
|
|
10682
|
+
}
|
|
10683
|
+
}
|
|
10684
|
+
return true;
|
|
10685
|
+
}, [currentStep, arrowSteps]);
|
|
10686
|
+
const isLastStep = React.useMemo(() => {
|
|
10687
|
+
for (let i = currentStep + 1; i < resolvedGroups.length; i++) {
|
|
10688
|
+
if (arrowSteps.has(i)) {
|
|
10689
|
+
return false;
|
|
10690
|
+
}
|
|
10691
|
+
}
|
|
10692
|
+
return true;
|
|
10693
|
+
}, [currentStep, arrowSteps, resolvedGroups.length]);
|
|
10694
|
+
const visibleFieldsForStep = React.useMemo(
|
|
10695
|
+
() => currentResolved ? currentResolved.fields.filter(isFieldVisible) : [],
|
|
10696
|
+
[currentResolved, isFieldVisible]
|
|
10697
|
+
);
|
|
10698
|
+
const currentGroupValid = React.useMemo(() => {
|
|
10699
|
+
if (!currentResolved) {
|
|
10700
|
+
return true;
|
|
10701
|
+
}
|
|
10702
|
+
for (const field of visibleFieldsForStep) {
|
|
10703
|
+
if (errors[useDatasourceSchema.formKey(field)]) {
|
|
10704
|
+
return false;
|
|
10705
|
+
}
|
|
10706
|
+
if (isFieldRequired(field, watchedValues, fieldById, celContext)) {
|
|
10707
|
+
const val = useDatasourceSchema.getWatchedValue(watchedValues, useDatasourceSchema.formKey(field));
|
|
10708
|
+
if (val === SECURE_FIELD_CONFIGURED) {
|
|
10709
|
+
continue;
|
|
10710
|
+
}
|
|
10711
|
+
if (val === void 0 || val === null || val === "") {
|
|
10712
|
+
return false;
|
|
10713
|
+
}
|
|
10714
|
+
}
|
|
10715
|
+
}
|
|
10716
|
+
return true;
|
|
10717
|
+
}, [currentResolved, errors, visibleFieldsForStep, watchedValues, fieldById, celContext]);
|
|
10718
|
+
const goNext = React.useCallback(async () => {
|
|
10719
|
+
if (!currentResolved) {
|
|
10720
|
+
return;
|
|
10721
|
+
}
|
|
10722
|
+
if (!readOnly) {
|
|
10723
|
+
const visibleKeys = visibleFieldsForStep.map((f) => useDatasourceSchema.formKey(f));
|
|
10724
|
+
const valid = await trigger(visibleKeys);
|
|
10725
|
+
if (!valid) {
|
|
10726
|
+
return;
|
|
10727
|
+
}
|
|
10728
|
+
}
|
|
10729
|
+
setCurrentStep((s) => {
|
|
10730
|
+
for (let i = s + 1; i < resolvedGroups.length; i++) {
|
|
10731
|
+
if (arrowSteps.has(i)) {
|
|
10732
|
+
return i;
|
|
10733
|
+
}
|
|
10734
|
+
}
|
|
10735
|
+
return s;
|
|
10736
|
+
});
|
|
10737
|
+
}, [currentResolved, visibleFieldsForStep, trigger, resolvedGroups.length, arrowSteps, readOnly]);
|
|
10738
|
+
const goPrev = React.useCallback(() => {
|
|
10739
|
+
setCurrentStep((s) => {
|
|
10740
|
+
for (let i = s - 1; i >= 0; i--) {
|
|
10741
|
+
if (arrowSteps.has(i)) {
|
|
10742
|
+
return i;
|
|
10743
|
+
}
|
|
10744
|
+
}
|
|
10745
|
+
return s;
|
|
10746
|
+
});
|
|
10747
|
+
}, [arrowSteps]);
|
|
10748
|
+
if (initializing) {
|
|
10749
|
+
return /* @__PURE__ */ React__default.default.createElement("div", { className: styles.container }, /* @__PURE__ */ React__default.default.createElement(ui.Spinner, { size: "sm", inline: true }), " Loading configuration...");
|
|
10750
|
+
}
|
|
10751
|
+
if (fetchError) {
|
|
10752
|
+
return /* @__PURE__ */ React__default.default.createElement("div", { className: styles.container }, /* @__PURE__ */ React__default.default.createElement(ui.Alert, { severity: "error", title: "Failed to load configuration" }, fetchError), /* @__PURE__ */ React__default.default.createElement("div", { className: styles.buttons }, /* @__PURE__ */ React__default.default.createElement(
|
|
10753
|
+
ui.LinkButton,
|
|
10754
|
+
{
|
|
10755
|
+
variant: "secondary",
|
|
10756
|
+
size: "sm",
|
|
10757
|
+
icon: "external-link-alt",
|
|
10758
|
+
href: `/connections/datasources/edit/${dsUid}`
|
|
10759
|
+
},
|
|
10760
|
+
"Open datasource settings"
|
|
10761
|
+
)));
|
|
10762
|
+
}
|
|
10763
|
+
const allDisabled = submitting || readOnly;
|
|
10764
|
+
if (resolvedGroups.length === 0) {
|
|
10765
|
+
return null;
|
|
10766
|
+
}
|
|
10767
|
+
const currentGroup = currentResolved == null ? void 0 : currentResolved.group;
|
|
10768
|
+
return /* @__PURE__ */ React__default.default.createElement("div", { className: styles.container }, submitting && /* @__PURE__ */ React__default.default.createElement("div", { className: styles.overlay }, /* @__PURE__ */ React__default.default.createElement(ui.Spinner, { size: "sm" }), /* @__PURE__ */ React__default.default.createElement("span", null, "Saving & testing\u2026")), readOnly && /* @__PURE__ */ React__default.default.createElement("div", { className: styles.readOnlyBanner }, /* @__PURE__ */ React__default.default.createElement(ui.Icon, { name: "lock", size: "xs" }), /* @__PURE__ */ React__default.default.createElement("span", null, "Read-only \u2014 managed externally")), /* @__PURE__ */ React__default.default.createElement("div", { className: styles.navBar }, currentGroup && /* @__PURE__ */ React__default.default.createElement(ui.Tooltip, { content: (_a = currentGroup.description) != null ? _a : currentGroup.title }, /* @__PURE__ */ React__default.default.createElement("span", { className: styles.navTitle }, currentGroup.title, /* @__PURE__ */ React__default.default.createElement("span", { className: styles.stepCount }, currentStep + 1, "/", resolvedGroups.length))), /* @__PURE__ */ React__default.default.createElement("div", { className: styles.navActions }, /* @__PURE__ */ React__default.default.createElement(ui.Tooltip, { content: isFirstStep ? "First step" : `Previous: ${(_b = resolvedGroups[currentStep - 1]) == null ? void 0 : _b.group.title}` }, /* @__PURE__ */ React__default.default.createElement(
|
|
10769
|
+
ui.Button,
|
|
10770
|
+
{
|
|
10771
|
+
variant: "secondary",
|
|
10772
|
+
fill: "text",
|
|
10773
|
+
size: "sm",
|
|
10774
|
+
icon: "angle-left",
|
|
10775
|
+
"aria-label": "Previous",
|
|
10776
|
+
onClick: goPrev,
|
|
10777
|
+
disabled: isFirstStep || submitting,
|
|
10778
|
+
type: "button"
|
|
10779
|
+
}
|
|
10780
|
+
)), /* @__PURE__ */ React__default.default.createElement(
|
|
10781
|
+
ui.Select,
|
|
10782
|
+
{
|
|
10783
|
+
options: resolvedGroups.map((g, i) => ({ label: g.group.title, value: i })),
|
|
10784
|
+
value: currentStep,
|
|
10785
|
+
onChange: (v) => {
|
|
10786
|
+
if (v) {
|
|
10787
|
+
setCurrentStep(v.value);
|
|
10788
|
+
}
|
|
10789
|
+
},
|
|
10790
|
+
disabled: submitting,
|
|
10791
|
+
width: 18
|
|
10792
|
+
}
|
|
10793
|
+
), /* @__PURE__ */ React__default.default.createElement(ui.Tooltip, { content: isLastStep ? "Last step" : `Next: ${(_c = resolvedGroups[currentStep + 1]) == null ? void 0 : _c.group.title}` }, /* @__PURE__ */ React__default.default.createElement(
|
|
10794
|
+
ui.Button,
|
|
10795
|
+
{
|
|
10796
|
+
variant: isLastStep || !readOnly && !currentGroupValid ? "secondary" : "primary",
|
|
10797
|
+
size: "sm",
|
|
10798
|
+
icon: "angle-right",
|
|
10799
|
+
"aria-label": "Next",
|
|
10800
|
+
onClick: goNext,
|
|
10801
|
+
disabled: isLastStep || submitting,
|
|
10802
|
+
type: "button"
|
|
10803
|
+
}
|
|
10804
|
+
)))), currentResolved && /* @__PURE__ */ React__default.default.createElement("form", { onSubmit: handleSubmit(onSubmit), className: styles.form }, visibleFieldsForStep.map((field) => /* @__PURE__ */ React__default.default.createElement(
|
|
10805
|
+
SchemaField,
|
|
10806
|
+
{
|
|
10807
|
+
key: useDatasourceSchema.formKey(field),
|
|
10808
|
+
field,
|
|
10809
|
+
control,
|
|
10810
|
+
errors,
|
|
10811
|
+
disabled: allDisabled || isFieldDisabled(field),
|
|
10812
|
+
dsUid,
|
|
10813
|
+
watchedValues,
|
|
10814
|
+
fieldById,
|
|
10815
|
+
celContext,
|
|
10816
|
+
setValue
|
|
10817
|
+
}
|
|
10818
|
+
)), (currentResolved.group.id === "_required" || currentResolved.group.id === "auth") && httpHeadersField && /* @__PURE__ */ React__default.default.createElement(
|
|
10819
|
+
AuthorizationHeaderField,
|
|
10820
|
+
{
|
|
10821
|
+
headersFieldKey: useDatasourceSchema.formKey(httpHeadersField),
|
|
10822
|
+
control,
|
|
10823
|
+
disabled: allDisabled,
|
|
10824
|
+
watchedValues
|
|
10825
|
+
}
|
|
10826
|
+
), 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 })))));
|
|
10827
|
+
}
|
|
10828
|
+
|
|
10829
|
+
var __defProp$2 = Object.defineProperty;
|
|
10830
|
+
var __defNormalProp$2 = (obj, key, value) => key in obj ? __defProp$2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
10831
|
+
var __publicField$2 = (obj, key, value) => __defNormalProp$2(obj, key + "" , value);
|
|
10832
|
+
class DatasourceErrorBoundary extends React.Component {
|
|
10833
|
+
constructor() {
|
|
10834
|
+
super(...arguments);
|
|
10835
|
+
__publicField$2(this, "state", { error: null });
|
|
10836
|
+
}
|
|
10837
|
+
static getDerivedStateFromError(error) {
|
|
10838
|
+
return { error };
|
|
10839
|
+
}
|
|
10840
|
+
componentDidCatch(error, info) {
|
|
10841
|
+
console.error("[DatasourceConfigWizard] Caught error:", error, info.componentStack);
|
|
10842
|
+
}
|
|
10843
|
+
render() {
|
|
10844
|
+
if (this.state.error) {
|
|
10845
|
+
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.");
|
|
10846
|
+
}
|
|
10847
|
+
return this.props.children;
|
|
10848
|
+
}
|
|
10849
|
+
}
|
|
10850
|
+
|
|
10851
|
+
const MAX_CONCURRENCY = 5;
|
|
10852
|
+
function useHealthChecks() {
|
|
10853
|
+
const [healthMap, setHealthMap] = React.useState({});
|
|
10854
|
+
const queueRef = React.useRef([]);
|
|
10855
|
+
const activeRef = React.useRef(0);
|
|
10856
|
+
const mountedRef = React.useRef(true);
|
|
10857
|
+
const everQueuedRef = React.useRef(/* @__PURE__ */ new Set());
|
|
10858
|
+
const checkOne = React.useCallback(async (uid) => {
|
|
10859
|
+
if (!mountedRef.current) {
|
|
10860
|
+
return;
|
|
10861
|
+
}
|
|
10862
|
+
setHealthMap((prev) => ({ ...prev, [uid]: { state: "checking" } }));
|
|
10863
|
+
try {
|
|
10864
|
+
const result = await runtime.getBackendSrv().get(
|
|
10865
|
+
`/api/datasources/uid/${uid}/health`,
|
|
10866
|
+
void 0,
|
|
10867
|
+
void 0,
|
|
10868
|
+
{ showErrorAlert: false }
|
|
10869
|
+
);
|
|
10870
|
+
if (!mountedRef.current) {
|
|
10871
|
+
return;
|
|
10872
|
+
}
|
|
10873
|
+
setHealthMap((prev) => {
|
|
10874
|
+
var _a;
|
|
10875
|
+
return {
|
|
10876
|
+
...prev,
|
|
10877
|
+
[uid]: { state: "done", status: (_a = result.status) != null ? _a : "OK", message: result.message }
|
|
10878
|
+
};
|
|
10879
|
+
});
|
|
10880
|
+
} catch (error) {
|
|
10881
|
+
if (!mountedRef.current) {
|
|
10882
|
+
return;
|
|
10883
|
+
}
|
|
10884
|
+
let status = "ERROR";
|
|
10885
|
+
let message = "";
|
|
10886
|
+
if (error && typeof error === "object" && "data" in error) {
|
|
10887
|
+
const data = error.data;
|
|
10888
|
+
if (data == null ? void 0 : data.status) {
|
|
10889
|
+
status = data.status;
|
|
10890
|
+
}
|
|
10891
|
+
if (data == null ? void 0 : data.message) {
|
|
10892
|
+
message = data.message;
|
|
10893
|
+
}
|
|
10894
|
+
}
|
|
10895
|
+
if (!message) {
|
|
10896
|
+
message = error instanceof Error ? error.message : String(error);
|
|
10897
|
+
}
|
|
10898
|
+
setHealthMap((prev) => ({
|
|
10899
|
+
...prev,
|
|
10900
|
+
[uid]: { state: "done", status, message }
|
|
10901
|
+
}));
|
|
10902
|
+
}
|
|
10903
|
+
}, []);
|
|
10904
|
+
const processQueue = React.useCallback(() => {
|
|
10905
|
+
while (activeRef.current < MAX_CONCURRENCY && queueRef.current.length > 0) {
|
|
10906
|
+
const uid = queueRef.current.shift();
|
|
10907
|
+
activeRef.current++;
|
|
10908
|
+
checkOne(uid).finally(() => {
|
|
10909
|
+
activeRef.current--;
|
|
10910
|
+
processQueue();
|
|
10911
|
+
});
|
|
10912
|
+
}
|
|
10913
|
+
}, [checkOne]);
|
|
10914
|
+
const checkUids = React.useCallback(
|
|
10915
|
+
(uids) => {
|
|
10916
|
+
const toCheck = [];
|
|
10917
|
+
for (const uid of uids) {
|
|
10918
|
+
if (everQueuedRef.current.has(uid)) {
|
|
10919
|
+
continue;
|
|
10920
|
+
}
|
|
10921
|
+
everQueuedRef.current.add(uid);
|
|
10922
|
+
toCheck.push(uid);
|
|
10923
|
+
}
|
|
10924
|
+
if (toCheck.length === 0) {
|
|
10925
|
+
return;
|
|
10926
|
+
}
|
|
10927
|
+
setHealthMap((prev) => {
|
|
10928
|
+
const next = { ...prev };
|
|
10929
|
+
for (const uid of toCheck) {
|
|
10930
|
+
next[uid] = { state: "pending" };
|
|
10931
|
+
}
|
|
10932
|
+
return next;
|
|
10933
|
+
});
|
|
10934
|
+
queueRef.current.push(...toCheck);
|
|
10935
|
+
processQueue();
|
|
10936
|
+
},
|
|
10937
|
+
[processQueue]
|
|
10938
|
+
);
|
|
10939
|
+
const retry = React.useCallback(
|
|
10940
|
+
(uid) => {
|
|
10941
|
+
everQueuedRef.current.delete(uid);
|
|
10942
|
+
everQueuedRef.current.add(uid);
|
|
10943
|
+
setHealthMap((prev) => ({ ...prev, [uid]: { state: "pending" } }));
|
|
10944
|
+
queueRef.current.push(uid);
|
|
10945
|
+
processQueue();
|
|
10946
|
+
},
|
|
10947
|
+
[processQueue]
|
|
10948
|
+
);
|
|
10949
|
+
return { healthMap, checkUids, retry };
|
|
10950
|
+
}
|
|
10951
|
+
|
|
10952
|
+
let pluginNameCache = null;
|
|
10953
|
+
function buildPluginNameCache() {
|
|
10954
|
+
var _a;
|
|
10955
|
+
if (pluginNameCache) {
|
|
10956
|
+
return pluginNameCache;
|
|
10957
|
+
}
|
|
10958
|
+
const map = /* @__PURE__ */ new Map();
|
|
10959
|
+
try {
|
|
10960
|
+
const list = runtime.getDataSourceSrv().getList();
|
|
10961
|
+
for (const ds of list) {
|
|
10962
|
+
if (((_a = ds.meta) == null ? void 0 : _a.name) && ds.type && !map.has(ds.type)) {
|
|
10963
|
+
map.set(ds.type, ds.meta.name);
|
|
10964
|
+
}
|
|
10965
|
+
}
|
|
10966
|
+
} catch (ex) {
|
|
10967
|
+
console.error(ex);
|
|
10968
|
+
}
|
|
10969
|
+
pluginNameCache = map;
|
|
10970
|
+
return map;
|
|
10971
|
+
}
|
|
10972
|
+
function resolvePluginName(pluginType) {
|
|
10973
|
+
var _a;
|
|
10974
|
+
const cache = buildPluginNameCache();
|
|
10975
|
+
return (_a = cache.get(pluginType)) != null ? _a : pluginType;
|
|
10976
|
+
}
|
|
10977
|
+
|
|
8392
10978
|
var __defProp$1 = Object.defineProperty;
|
|
8393
10979
|
var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
8394
10980
|
var __publicField$1 = (obj, key, value) => __defNormalProp$1(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
@@ -9842,6 +12428,34 @@ const convertUnits = (queryStats) => {
|
|
|
9842
12428
|
return text + suffix;
|
|
9843
12429
|
};
|
|
9844
12430
|
|
|
12431
|
+
exports.ROOT_CONFIG_FIELDS = useDatasourceSchema.ROOT_CONFIG_FIELDS;
|
|
12432
|
+
exports.buildCelContext = useDatasourceSchema.buildCelContext;
|
|
12433
|
+
exports.buildCloneDatasourcePayload = useDatasourceSchema.buildCloneDatasourcePayload;
|
|
12434
|
+
exports.buildCreateDatasourcePayload = useDatasourceSchema.buildCreateDatasourcePayload;
|
|
12435
|
+
exports.buildUpdateDatasourcePayload = useDatasourceSchema.buildUpdateDatasourcePayload;
|
|
12436
|
+
exports.clearExpressionCache = useDatasourceSchema.clearExpressionCache;
|
|
12437
|
+
exports.computeVirtualFieldValues = useDatasourceSchema.computeVirtualFieldValues;
|
|
12438
|
+
exports.configToYaml = useDatasourceSchema.configToYaml;
|
|
12439
|
+
exports.datasourceToProvisioningYaml = useDatasourceSchema.datasourceToProvisioningYaml;
|
|
12440
|
+
exports.evaluateCelDirect = useDatasourceSchema.evaluateCelDirect;
|
|
12441
|
+
exports.evaluateCelExpression = useDatasourceSchema.evaluateCelExpression;
|
|
12442
|
+
exports.evaluateComputedRead = useDatasourceSchema.evaluateComputedRead;
|
|
12443
|
+
exports.evaluateDependsOn = useDatasourceSchema.evaluateDependsOn;
|
|
12444
|
+
exports.extractFieldRefs = useDatasourceSchema.extractFieldRefs;
|
|
12445
|
+
exports.fetchConfigSchema = useDatasourceSchema.fetchConfigSchema;
|
|
12446
|
+
exports.formKey = useDatasourceSchema.formKey;
|
|
12447
|
+
exports.formatYamlDiff = useDatasourceSchema.formatYamlDiff;
|
|
12448
|
+
exports.generateLLMHint = useDatasourceSchema.generateLLMHint;
|
|
12449
|
+
exports.generateTroubleshootingFields = useDatasourceSchema.generateTroubleshootingFields;
|
|
12450
|
+
exports.getConfigSchema = useDatasourceSchema.getConfigSchema;
|
|
12451
|
+
exports.getWatchedValue = useDatasourceSchema.getWatchedValue;
|
|
12452
|
+
exports.isValidCelExpression = useDatasourceSchema.isValidCelExpression;
|
|
12453
|
+
exports.parseDependsOn = useDatasourceSchema.parseDependsOn;
|
|
12454
|
+
exports.resolveActiveOverride = useDatasourceSchema.resolveActiveOverride;
|
|
12455
|
+
exports.resolveGroups = useDatasourceSchema.resolveGroups;
|
|
12456
|
+
exports.resolveRequiredFieldsGroup = useDatasourceSchema.resolveRequiredFieldsGroup;
|
|
12457
|
+
exports.toProvisioningYaml = useDatasourceSchema.toProvisioningYaml;
|
|
12458
|
+
exports.useDatasourceSchema = useDatasourceSchema.useDatasourceSchema;
|
|
9845
12459
|
exports.AccessoryButton = AccessoryButton;
|
|
9846
12460
|
exports.AdvancedHttpSettings = AdvancedHttpSettings;
|
|
9847
12461
|
exports.Auth = Auth;
|
|
@@ -9861,6 +12475,8 @@ exports.DataLinks = DataLinks;
|
|
|
9861
12475
|
exports.DataSourceDescription = DataSourceDescription;
|
|
9862
12476
|
exports.DataSourcePicker = DataSourcePicker;
|
|
9863
12477
|
exports.DatasetSelector = DatasetSelector;
|
|
12478
|
+
exports.DatasourceConfigWizard = DatasourceConfigWizard;
|
|
12479
|
+
exports.DatasourceErrorBoundary = DatasourceErrorBoundary;
|
|
9864
12480
|
exports.DatePicker = DatePicker;
|
|
9865
12481
|
exports.DatePickerWithInput = DatePickerWithInput;
|
|
9866
12482
|
exports.DebounceInput = DebounceInput;
|
|
@@ -9914,5 +12530,7 @@ exports.formatDate = formatDate;
|
|
|
9914
12530
|
exports.getStandardSQLCompletionProvider = getStandardSQLCompletionProvider;
|
|
9915
12531
|
exports.grafanaStandardSQLLanguage = language;
|
|
9916
12532
|
exports.grafanaStandardSQLLanguageConf = conf;
|
|
12533
|
+
exports.resolvePluginName = resolvePluginName;
|
|
9917
12534
|
exports.toOption = toOption;
|
|
12535
|
+
exports.useHealthChecks = useHealthChecks;
|
|
9918
12536
|
//# sourceMappingURL=index.cjs.map
|