@grafana/plugin-ui 0.14.0-dev.1 → 0.14.1-dsconfig.0d5c985
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 +2932 -377
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/index.d.cts +564 -38
- package/dist/esm/components/ConfigEditor/ConfigSection/ConfigDescriptionLink.js +2 -2
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/AuthorizationHeaderField.js +53 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/AuthorizationHeaderField.js.map +1 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/ComplexFieldNote.js +24 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/ComplexFieldNote.js.map +1 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/DatasourceConfigWizard.js +229 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/DatasourceConfigWizard.js.map +1 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/IndexedPairEditor.js +124 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/IndexedPairEditor.js.map +1 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/PdcFieldNote.js +34 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/PdcFieldNote.js.map +1 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/SchemaField.js +60 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/SchemaField.js.map +1 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/SecureFieldInput.js +61 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/SecureFieldInput.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/StringArrayInput.js +84 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/StringArrayInput.js.map +1 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/TabLayout.js +176 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/TabLayout.js.map +1 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/fieldUtils.js +88 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/fieldUtils.js.map +1 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/renderFieldInput.js +106 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/renderFieldInput.js.map +1 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/tabStyles.js +241 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/tabStyles.js.map +1 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/useDatasourceConfigForm.js +284 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/useDatasourceConfigForm.js.map +1 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/wizardStyles.js +124 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/wizardStyles.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/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/schema/config.js +235 -0
- package/dist/esm/datasource/schema/config.js.map +1 -0
- package/dist/esm/datasource/schema/datasource.js +228 -0
- package/dist/esm/datasource/schema/datasource.js.map +1 -0
- package/dist/esm/datasource/schema/llmHints.js +54 -0
- package/dist/esm/datasource/schema/llmHints.js.map +1 -0
- package/dist/esm/datasource/schema/provisioningYaml.js +358 -0
- package/dist/esm/datasource/schema/provisioningYaml.js.map +1 -0
- package/dist/esm/index.d.ts +564 -38
- package/dist/esm/index.js +7 -1
- package/dist/esm/index.js.map +1 -1
- package/package.json +30 -11
package/dist/cjs/index.cjs
CHANGED
|
@@ -11,23 +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 reactHookForm = require('react-hook-form');
|
|
20
21
|
var dnd = require('@hello-pangea/dnd');
|
|
21
22
|
var reactPopperTooltip = require('react-popper-tooltip');
|
|
22
23
|
var Prism = require('prismjs');
|
|
24
|
+
var yaml = require('js-yaml');
|
|
23
25
|
|
|
24
26
|
function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; }
|
|
25
27
|
|
|
26
28
|
var React__default = /*#__PURE__*/_interopDefaultCompat(React);
|
|
27
29
|
var Calendar__default = /*#__PURE__*/_interopDefaultCompat(Calendar);
|
|
28
30
|
var AutoSizer__default = /*#__PURE__*/_interopDefaultCompat(AutoSizer);
|
|
29
|
-
var sqlFormatter__default = /*#__PURE__*/_interopDefaultCompat(sqlFormatter);
|
|
30
31
|
var Prism__default = /*#__PURE__*/_interopDefaultCompat(Prism);
|
|
32
|
+
var yaml__default = /*#__PURE__*/_interopDefaultCompat(yaml);
|
|
31
33
|
|
|
32
34
|
const QueryEditorRow = (props) => {
|
|
33
35
|
var _a, _b;
|
|
@@ -76,7 +78,7 @@ function Segment(props) {
|
|
|
76
78
|
);
|
|
77
79
|
}
|
|
78
80
|
|
|
79
|
-
const getStyles$
|
|
81
|
+
const getStyles$v = (theme) => {
|
|
80
82
|
const containerBorder = theme.isDark ? theme.v1.palette.dark9 : theme.v1.palette.gray5;
|
|
81
83
|
return {
|
|
82
84
|
container: css.css`
|
|
@@ -226,7 +228,7 @@ const getBodyStyles = (theme) => {
|
|
|
226
228
|
|
|
227
229
|
const DatePicker = React.memo((props) => {
|
|
228
230
|
const theme = ui.useTheme2();
|
|
229
|
-
const styles = getStyles$
|
|
231
|
+
const styles = getStyles$v(theme);
|
|
230
232
|
const { isOpen, onClose } = props;
|
|
231
233
|
if (!isOpen) {
|
|
232
234
|
return null;
|
|
@@ -256,7 +258,7 @@ const Body = React.memo(({ value, onChange }) => {
|
|
|
256
258
|
});
|
|
257
259
|
Body.displayName = "Body";
|
|
258
260
|
|
|
259
|
-
function getStyles$
|
|
261
|
+
function getStyles$u() {
|
|
260
262
|
return {
|
|
261
263
|
input: css.css({
|
|
262
264
|
/* hides the native Calendar picker icon given when using type=date */
|
|
@@ -272,7 +274,7 @@ const formatDate = (date) => date.toISOString().split("T")[0];
|
|
|
272
274
|
const DatePickerWithInput = (props) => {
|
|
273
275
|
const { value, onChange, className, ...rest } = props;
|
|
274
276
|
const [open, setOpen] = React.useState(false);
|
|
275
|
-
const styles = getStyles$
|
|
277
|
+
const styles = getStyles$u();
|
|
276
278
|
return /* @__PURE__ */ React__default.default.createElement(React__default.default.Fragment, null, /* @__PURE__ */ React__default.default.createElement(
|
|
277
279
|
ui.Input,
|
|
278
280
|
{
|
|
@@ -434,7 +436,7 @@ __publicField$3(DataSourcePicker, "defaultProps", {
|
|
|
434
436
|
});
|
|
435
437
|
|
|
436
438
|
const { FormField, Switch } = ui.LegacyForms;
|
|
437
|
-
const getStyles$
|
|
439
|
+
const getStyles$t = ui.stylesFactory(() => ({
|
|
438
440
|
firstRow: css.css`
|
|
439
441
|
display: flex;
|
|
440
442
|
`,
|
|
@@ -451,7 +453,7 @@ const getStyles$p = ui.stylesFactory(() => ({
|
|
|
451
453
|
}));
|
|
452
454
|
const DataLink = (props) => {
|
|
453
455
|
const { value, onChange, onDelete, suggestions, className } = props;
|
|
454
|
-
const styles = getStyles$
|
|
456
|
+
const styles = getStyles$t();
|
|
455
457
|
const [showInternalLink, setShowInternalLink] = useInternalLink(value.datasourceUid);
|
|
456
458
|
const handleChange = (field) => (event) => {
|
|
457
459
|
onChange({
|
|
@@ -568,7 +570,7 @@ function useInternalLink(datasourceUid) {
|
|
|
568
570
|
return [showInternalLink, setShowInternalLink];
|
|
569
571
|
}
|
|
570
572
|
|
|
571
|
-
const getStyles$
|
|
573
|
+
const getStyles$s = (theme) => ({
|
|
572
574
|
infoText: css.css`
|
|
573
575
|
padding-bottom: ${theme.v1.spacing.md};
|
|
574
576
|
color: ${theme.v1.colors.textWeak};
|
|
@@ -580,7 +582,7 @@ const getStyles$o = (theme) => ({
|
|
|
580
582
|
const DataLinks = (props) => {
|
|
581
583
|
const { value, onChange } = props;
|
|
582
584
|
const theme = ui.useTheme2();
|
|
583
|
-
const styles = getStyles$
|
|
585
|
+
const styles = getStyles$s(theme);
|
|
584
586
|
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
587
|
return /* @__PURE__ */ React__default.default.createElement(
|
|
586
588
|
DataLink,
|
|
@@ -641,110 +643,21 @@ var QueryEditorExpressionType = /* @__PURE__ */ ((QueryEditorExpressionType2) =>
|
|
|
641
643
|
return QueryEditorExpressionType2;
|
|
642
644
|
})(QueryEditorExpressionType || {});
|
|
643
645
|
|
|
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
|
-
}
|
|
646
|
+
var TokenType = /* @__PURE__ */ ((TokenType2) => {
|
|
647
|
+
TokenType2["Parenthesis"] = "delimiter.parenthesis.sql";
|
|
648
|
+
TokenType2["Whitespace"] = "white.sql";
|
|
649
|
+
TokenType2["Keyword"] = "keyword.sql";
|
|
650
|
+
TokenType2["Delimiter"] = "delimiter.sql";
|
|
651
|
+
TokenType2["Operator"] = "operator.sql";
|
|
652
|
+
TokenType2["Identifier"] = "identifier.sql";
|
|
653
|
+
TokenType2["IdentifierQuote"] = "identifier.quote.sql";
|
|
654
|
+
TokenType2["Type"] = "type.sql";
|
|
655
|
+
TokenType2["Function"] = "predefined.sql";
|
|
656
|
+
TokenType2["Number"] = "number.sql";
|
|
657
|
+
TokenType2["String"] = "string.sql";
|
|
658
|
+
TokenType2["Variable"] = "variable.sql";
|
|
659
|
+
return TokenType2;
|
|
660
|
+
})(TokenType || {});
|
|
748
661
|
|
|
749
662
|
class LinkedToken {
|
|
750
663
|
constructor(type, value, range, previous, next) {
|
|
@@ -899,21 +812,6 @@ var MacroType = /* @__PURE__ */ ((MacroType2) => {
|
|
|
899
812
|
MacroType2[MacroType2["Table"] = 4] = "Table";
|
|
900
813
|
return MacroType2;
|
|
901
814
|
})(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
815
|
var StatementPosition = /* @__PURE__ */ ((StatementPosition2) => {
|
|
918
816
|
StatementPosition2["Unknown"] = "unknown";
|
|
919
817
|
StatementPosition2["SelectKeyword"] = "selectKeyword";
|
|
@@ -5456,6 +5354,91 @@ const QUERY_FORMAT_OPTIONS = [
|
|
|
5456
5354
|
const backWardToOption = (value) => ({ label: value, value });
|
|
5457
5355
|
const toOption = (_a = data.toOption) != null ? _a : backWardToOption;
|
|
5458
5356
|
|
|
5357
|
+
function getRawSqlFn(db) {
|
|
5358
|
+
return db.toRawSql ? db.toRawSql : (query) => toRawSql(query, Boolean(db.disableDatasets));
|
|
5359
|
+
}
|
|
5360
|
+
function toRawSql({ sql, dataset, catalog, table }, disableDatasets) {
|
|
5361
|
+
var _a, _b, _c, _d;
|
|
5362
|
+
let rawQuery = "";
|
|
5363
|
+
if (!sql || !haveColumns(sql.columns)) {
|
|
5364
|
+
return rawQuery;
|
|
5365
|
+
}
|
|
5366
|
+
rawQuery += createSelectClause(sql.columns);
|
|
5367
|
+
if (catalog && dataset && table) {
|
|
5368
|
+
rawQuery += `FROM ${catalog}.${dataset}.${table} `;
|
|
5369
|
+
} else if (!disableDatasets && dataset && table) {
|
|
5370
|
+
rawQuery += `FROM ${dataset}.${table} `;
|
|
5371
|
+
} else if (table) {
|
|
5372
|
+
rawQuery += `FROM ${table} `;
|
|
5373
|
+
}
|
|
5374
|
+
if (sql.whereString) {
|
|
5375
|
+
rawQuery += `WHERE ${sql.whereString} `;
|
|
5376
|
+
}
|
|
5377
|
+
if ((_b = (_a = sql.groupBy) == null ? void 0 : _a[0]) == null ? void 0 : _b.property.name) {
|
|
5378
|
+
const groupBy = sql.groupBy.map((g) => g.property.name).filter((g) => !lodash.isEmpty(g));
|
|
5379
|
+
rawQuery += `GROUP BY ${groupBy.join(", ")} `;
|
|
5380
|
+
}
|
|
5381
|
+
if ((_c = sql.orderBy) == null ? void 0 : _c.property.name) {
|
|
5382
|
+
rawQuery += `ORDER BY ${sql.orderBy.property.name} `;
|
|
5383
|
+
}
|
|
5384
|
+
if (((_d = sql.orderBy) == null ? void 0 : _d.property.name) && sql.orderByDirection) {
|
|
5385
|
+
rawQuery += `${sql.orderByDirection} `;
|
|
5386
|
+
}
|
|
5387
|
+
if (sql.limit !== void 0 && sql.limit >= 0) {
|
|
5388
|
+
rawQuery += `LIMIT ${sql.limit} `;
|
|
5389
|
+
}
|
|
5390
|
+
return rawQuery;
|
|
5391
|
+
}
|
|
5392
|
+
function createSelectClause(sqlColumns) {
|
|
5393
|
+
const columns = sqlColumns.map((c) => {
|
|
5394
|
+
var _a, _b;
|
|
5395
|
+
let rawColumn = "";
|
|
5396
|
+
if (c.name) {
|
|
5397
|
+
rawColumn += `${c.name}(${(_a = c.parameters) == null ? void 0 : _a.map((p) => `${p.name}`)})`;
|
|
5398
|
+
} else {
|
|
5399
|
+
rawColumn += `${(_b = c.parameters) == null ? void 0 : _b.map((p) => `${p.name}`)}`;
|
|
5400
|
+
}
|
|
5401
|
+
return rawColumn;
|
|
5402
|
+
});
|
|
5403
|
+
return `SELECT ${columns.join(", ")} `;
|
|
5404
|
+
}
|
|
5405
|
+
function haveColumns(columns) {
|
|
5406
|
+
if (!columns) {
|
|
5407
|
+
return false;
|
|
5408
|
+
}
|
|
5409
|
+
const haveColumn = columns.some((c) => {
|
|
5410
|
+
var _a, _b;
|
|
5411
|
+
return ((_a = c.parameters) == null ? void 0 : _a.length) || ((_b = c.parameters) == null ? void 0 : _b.some((p) => p.name));
|
|
5412
|
+
});
|
|
5413
|
+
const haveFunction = columns.some((c) => c.name);
|
|
5414
|
+
return haveColumn || haveFunction;
|
|
5415
|
+
}
|
|
5416
|
+
function setGroupByField(field) {
|
|
5417
|
+
return {
|
|
5418
|
+
type: QueryEditorExpressionType.GroupBy,
|
|
5419
|
+
property: {
|
|
5420
|
+
type: QueryEditorPropertyType.String,
|
|
5421
|
+
name: field
|
|
5422
|
+
}
|
|
5423
|
+
};
|
|
5424
|
+
}
|
|
5425
|
+
function setPropertyField(field) {
|
|
5426
|
+
return {
|
|
5427
|
+
type: QueryEditorExpressionType.Property,
|
|
5428
|
+
property: {
|
|
5429
|
+
type: QueryEditorPropertyType.String,
|
|
5430
|
+
name: field
|
|
5431
|
+
}
|
|
5432
|
+
};
|
|
5433
|
+
}
|
|
5434
|
+
function createFunctionField(functionName) {
|
|
5435
|
+
return {
|
|
5436
|
+
type: QueryEditorExpressionType.Function,
|
|
5437
|
+
name: functionName,
|
|
5438
|
+
parameters: []
|
|
5439
|
+
};
|
|
5440
|
+
}
|
|
5441
|
+
|
|
5459
5442
|
const EditorStack = ({ children, wrap: wrapItems = true, ...props }) => {
|
|
5460
5443
|
var _a, _b;
|
|
5461
5444
|
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 +5478,7 @@ const getButtonStyles = (theme) => ({
|
|
|
5495
5478
|
});
|
|
5496
5479
|
|
|
5497
5480
|
const InputGroup = ({ children }) => {
|
|
5498
|
-
const styles = ui.useStyles2(getStyles$
|
|
5481
|
+
const styles = ui.useStyles2(getStyles$r);
|
|
5499
5482
|
const modifiedChildren = React.Children.map(children, (child) => {
|
|
5500
5483
|
if (React.isValidElement(child) && child.props.invalid) {
|
|
5501
5484
|
return React.cloneElement(child, { className: css.cx(child.props.className, styles.invalidChild) });
|
|
@@ -5513,7 +5496,7 @@ const borderPriority = [
|
|
|
5513
5496
|
"focused"
|
|
5514
5497
|
// highest priority
|
|
5515
5498
|
];
|
|
5516
|
-
const getStyles$
|
|
5499
|
+
const getStyles$r = () => ({
|
|
5517
5500
|
root: css.css({
|
|
5518
5501
|
display: "flex",
|
|
5519
5502
|
// Style the direct children of the component
|
|
@@ -5596,10 +5579,10 @@ const EditorFieldGroup = ({ children }) => {
|
|
|
5596
5579
|
};
|
|
5597
5580
|
|
|
5598
5581
|
const EditorHeader = ({ children }) => {
|
|
5599
|
-
const styles = ui.useStyles2(getStyles$
|
|
5582
|
+
const styles = ui.useStyles2(getStyles$q);
|
|
5600
5583
|
return /* @__PURE__ */ React__default.default.createElement("div", { className: styles.root }, children);
|
|
5601
5584
|
};
|
|
5602
|
-
const getStyles$
|
|
5585
|
+
const getStyles$q = (theme) => ({
|
|
5603
5586
|
root: css.css({
|
|
5604
5587
|
display: "flex",
|
|
5605
5588
|
flexWrap: "wrap",
|
|
@@ -5612,12 +5595,12 @@ const getStyles$m = (theme) => ({
|
|
|
5612
5595
|
const EditorField$1 = (props) => {
|
|
5613
5596
|
var _a;
|
|
5614
5597
|
const { label, optional, tooltip, tooltipInteractive, children, width, ...fieldProps } = props;
|
|
5615
|
-
const styles = ui.useStyles2(getStyles$
|
|
5598
|
+
const styles = ui.useStyles2(getStyles$p, width);
|
|
5616
5599
|
const childInputId = (fieldProps == null ? void 0 : fieldProps.htmlFor) || ((_a = ui.ReactUtils) == null ? void 0 : _a.getChildId(children));
|
|
5617
5600
|
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
5601
|
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
5602
|
};
|
|
5620
|
-
const getStyles$
|
|
5603
|
+
const getStyles$p = (theme, width) => {
|
|
5621
5604
|
return {
|
|
5622
5605
|
root: css.css({
|
|
5623
5606
|
minWidth: theme.spacing(width != null ? width : 0)
|
|
@@ -5645,10 +5628,10 @@ const getStyles$l = (theme, width) => {
|
|
|
5645
5628
|
};
|
|
5646
5629
|
|
|
5647
5630
|
const EditorRow$1 = ({ children }) => {
|
|
5648
|
-
const styles = ui.useStyles2(getStyles$
|
|
5631
|
+
const styles = ui.useStyles2(getStyles$o);
|
|
5649
5632
|
return /* @__PURE__ */ React__default.default.createElement("div", { className: styles.root }, /* @__PURE__ */ React__default.default.createElement(EditorStack, { gap: 2 }, children));
|
|
5650
5633
|
};
|
|
5651
|
-
const getStyles$
|
|
5634
|
+
const getStyles$o = (theme) => {
|
|
5652
5635
|
return {
|
|
5653
5636
|
root: css.css({
|
|
5654
5637
|
padding: theme.spacing(1),
|
|
@@ -5663,10 +5646,10 @@ const EditorRows$1 = ({ children }) => {
|
|
|
5663
5646
|
};
|
|
5664
5647
|
|
|
5665
5648
|
const EditorSwitch = (props) => {
|
|
5666
|
-
const styles = getStyles$
|
|
5649
|
+
const styles = getStyles$n();
|
|
5667
5650
|
return /* @__PURE__ */ React__default.default.createElement("div", { className: styles.switch }, /* @__PURE__ */ React__default.default.createElement(ui.Switch, { ...props }));
|
|
5668
5651
|
};
|
|
5669
|
-
const getStyles$
|
|
5652
|
+
const getStyles$n = () => {
|
|
5670
5653
|
return {
|
|
5671
5654
|
switch: css.css({
|
|
5672
5655
|
display: "flex",
|
|
@@ -5688,7 +5671,7 @@ function InlineSelect({ label: labelProp, ...props }) {
|
|
|
5688
5671
|
ValueContainer,
|
|
5689
5672
|
SingleValue: ValueContainer
|
|
5690
5673
|
};
|
|
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, {
|
|
5674
|
+
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
5675
|
}
|
|
5693
5676
|
const SelectContainer = (props) => {
|
|
5694
5677
|
const { children } = props;
|
|
@@ -5724,10 +5707,10 @@ const getSelectStyles = (theme) => ({
|
|
|
5724
5707
|
});
|
|
5725
5708
|
|
|
5726
5709
|
const Space = ({ v = 0, h = 0, layout = "block" }) => {
|
|
5727
|
-
const styles = ui.useStyles2(getStyles$
|
|
5710
|
+
const styles = ui.useStyles2(getStyles$m, v, h, layout);
|
|
5728
5711
|
return /* @__PURE__ */ React__default.default.createElement("span", { className: css.cx(styles.wrapper) });
|
|
5729
5712
|
};
|
|
5730
|
-
const getStyles$
|
|
5713
|
+
const getStyles$m = (theme, v, h, layout) => ({
|
|
5731
5714
|
wrapper: css.css([
|
|
5732
5715
|
{
|
|
5733
5716
|
paddingRight: theme.spacing(h != null ? h : 0),
|
|
@@ -5742,6 +5725,26 @@ const getStyles$i = (theme, v, h, layout) => ({
|
|
|
5742
5725
|
])
|
|
5743
5726
|
});
|
|
5744
5727
|
|
|
5728
|
+
function applyQueryDefaults(q) {
|
|
5729
|
+
let editorMode = (q == null ? void 0 : q.editorMode) || EditorMode.Builder;
|
|
5730
|
+
if ((q == null ? void 0 : q.editorMode) === void 0 && (q == null ? void 0 : q.rawSql) !== void 0) {
|
|
5731
|
+
editorMode = EditorMode.Code;
|
|
5732
|
+
}
|
|
5733
|
+
const result = {
|
|
5734
|
+
...q,
|
|
5735
|
+
refId: (q == null ? void 0 : q.refId) || "A",
|
|
5736
|
+
format: (q == null ? void 0 : q.format) !== void 0 ? q.format : QueryFormat.Table,
|
|
5737
|
+
rawSql: (q == null ? void 0 : q.rawSql) || "",
|
|
5738
|
+
editorMode,
|
|
5739
|
+
sql: (q == null ? void 0 : q.sql) || {
|
|
5740
|
+
columns: [createFunctionField()],
|
|
5741
|
+
groupBy: [setGroupByField()],
|
|
5742
|
+
limit: 50
|
|
5743
|
+
}
|
|
5744
|
+
};
|
|
5745
|
+
return result;
|
|
5746
|
+
}
|
|
5747
|
+
|
|
5745
5748
|
function ConfirmModal({ isOpen, onCancel, onDiscard, onCopy }) {
|
|
5746
5749
|
const buttonRef = React.useRef(null);
|
|
5747
5750
|
React.useEffect(() => {
|
|
@@ -6131,13 +6134,32 @@ function QueryHeader({
|
|
|
6131
6134
|
)))));
|
|
6132
6135
|
}
|
|
6133
6136
|
|
|
6134
|
-
function formatSQL(q) {
|
|
6135
|
-
|
|
6136
|
-
|
|
6137
|
+
function formatSQL(q, language = "sql") {
|
|
6138
|
+
const formatted = sqlFormatter.format(q, {
|
|
6139
|
+
language,
|
|
6140
|
+
paramTypes: {
|
|
6141
|
+
custom: [
|
|
6142
|
+
{
|
|
6143
|
+
regex: "\\$\\s*\\{[^}]*\\}|\\$\\s*__\\w+(?:\\([^)]*\\))?|\\$\\s*\\w+"
|
|
6144
|
+
}
|
|
6145
|
+
]
|
|
6146
|
+
}
|
|
6137
6147
|
});
|
|
6148
|
+
return formatted.replace(
|
|
6149
|
+
/(\$\s*\{[^}]*\})|(\$\s*__\w+(?:\([^)]*\))?)|(\$\s*\w+)/g,
|
|
6150
|
+
(m) => m.replace(/\s/g, "")
|
|
6151
|
+
);
|
|
6138
6152
|
}
|
|
6139
6153
|
|
|
6140
|
-
function QueryEditorRaw({
|
|
6154
|
+
function QueryEditorRaw({
|
|
6155
|
+
children,
|
|
6156
|
+
onChange,
|
|
6157
|
+
query,
|
|
6158
|
+
width,
|
|
6159
|
+
height,
|
|
6160
|
+
completionProvider,
|
|
6161
|
+
language = "sql"
|
|
6162
|
+
}) {
|
|
6141
6163
|
const queryRef = React.useRef(query);
|
|
6142
6164
|
React.useEffect(() => {
|
|
6143
6165
|
queryRef.current = query;
|
|
@@ -6160,7 +6182,7 @@ function QueryEditorRaw({ children, onChange, query, width, height, completionPr
|
|
|
6160
6182
|
height,
|
|
6161
6183
|
query: query.rawSql,
|
|
6162
6184
|
onChange: onRawQueryChange,
|
|
6163
|
-
language: { id: "sql", completionProvider, formatter: formatSQL }
|
|
6185
|
+
language: { id: "sql", completionProvider, formatter: (q) => formatSQL(q, language) }
|
|
6164
6186
|
},
|
|
6165
6187
|
children
|
|
6166
6188
|
);
|
|
@@ -6265,6 +6287,10 @@ function QueryToolbox({ showTools, onFormatCode, onExpand, isExpanded, ...valida
|
|
|
6265
6287
|
if (!showTools && validationResult === void 0) {
|
|
6266
6288
|
style = { height: 0, padding: 0, visibility: "hidden" };
|
|
6267
6289
|
}
|
|
6290
|
+
const onFormatClick = () => {
|
|
6291
|
+
runtime.reportInteraction("grafana_sql_query_editor_format_click");
|
|
6292
|
+
onFormatCode == null ? void 0 : onFormatCode();
|
|
6293
|
+
};
|
|
6268
6294
|
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
6295
|
QueryValidator,
|
|
6270
6296
|
{
|
|
@@ -6274,7 +6300,7 @@ function QueryToolbox({ showTools, onFormatCode, onExpand, isExpanded, ...valida
|
|
|
6274
6300
|
validatorProps.onValidate(result);
|
|
6275
6301
|
}
|
|
6276
6302
|
}
|
|
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:
|
|
6303
|
+
)), 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
6304
|
ui.IconButton,
|
|
6279
6305
|
{
|
|
6280
6306
|
onClick: () => onExpand(!isExpanded),
|
|
@@ -6285,10 +6311,19 @@ function QueryToolbox({ showTools, onFormatCode, onExpand, isExpanded, ...valida
|
|
|
6285
6311
|
), /* @__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
6312
|
}
|
|
6287
6313
|
|
|
6288
|
-
function RawEditor({
|
|
6289
|
-
|
|
6290
|
-
|
|
6291
|
-
|
|
6314
|
+
function RawEditor({
|
|
6315
|
+
db,
|
|
6316
|
+
query,
|
|
6317
|
+
onChange,
|
|
6318
|
+
onRunQuery,
|
|
6319
|
+
onValidate,
|
|
6320
|
+
queryToValidate,
|
|
6321
|
+
range,
|
|
6322
|
+
language = "sql"
|
|
6323
|
+
}) {
|
|
6324
|
+
const theme = ui.useTheme2();
|
|
6325
|
+
const styles = ui.useStyles2(getStyles$l);
|
|
6326
|
+
const [isExpanded, setIsExpanded] = React.useState(false);
|
|
6292
6327
|
const [toolboxRef, toolboxMeasure] = reactUse.useMeasure();
|
|
6293
6328
|
const [editorRef, editorMeasure] = reactUse.useMeasure();
|
|
6294
6329
|
const completionProvider = React.useMemo(() => db.getSqlCompletionProvider(), [db]);
|
|
@@ -6299,6 +6334,7 @@ function RawEditor({ db, query, onChange, onRunQuery, onValidate, queryToValidat
|
|
|
6299
6334
|
completionProvider,
|
|
6300
6335
|
query,
|
|
6301
6336
|
width,
|
|
6337
|
+
language,
|
|
6302
6338
|
height: height ? height - toolboxMeasure.height : void 0,
|
|
6303
6339
|
onChange
|
|
6304
6340
|
},
|
|
@@ -6356,7 +6392,7 @@ function RawEditor({ db, query, onChange, onRunQuery, onValidate, queryToValidat
|
|
|
6356
6392
|
renderEditor(true)
|
|
6357
6393
|
));
|
|
6358
6394
|
}
|
|
6359
|
-
function getStyles$
|
|
6395
|
+
function getStyles$l(theme) {
|
|
6360
6396
|
return {
|
|
6361
6397
|
modal: css.css`
|
|
6362
6398
|
width: 95vw;
|
|
@@ -6369,23 +6405,23 @@ function getStyles$h(theme) {
|
|
|
6369
6405
|
};
|
|
6370
6406
|
}
|
|
6371
6407
|
|
|
6372
|
-
function Preview({ rawSql }) {
|
|
6408
|
+
function Preview({ rawSql, language = "sql" }) {
|
|
6373
6409
|
const [_, copyToClipboard] = reactUse.useCopyToClipboard();
|
|
6374
|
-
const styles = ui.useStyles2(getStyles$
|
|
6410
|
+
const styles = ui.useStyles2(getStyles$k);
|
|
6375
6411
|
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
6412
|
return /* @__PURE__ */ React__default.default.createElement(ui.Field, { label: labelElement, className: styles.grow }, /* @__PURE__ */ React__default.default.createElement(
|
|
6377
6413
|
ui.CodeEditor,
|
|
6378
6414
|
{
|
|
6379
6415
|
language: "sql",
|
|
6380
6416
|
height: 80,
|
|
6381
|
-
value: formatSQL(rawSql),
|
|
6417
|
+
value: formatSQL(rawSql, language),
|
|
6382
6418
|
monacoOptions: { scrollbar: { vertical: "hidden" }, scrollBeyondLastLine: false },
|
|
6383
6419
|
readOnly: true,
|
|
6384
6420
|
showMiniMap: false
|
|
6385
6421
|
}
|
|
6386
6422
|
));
|
|
6387
6423
|
}
|
|
6388
|
-
function getStyles$
|
|
6424
|
+
function getStyles$k(theme) {
|
|
6389
6425
|
return {
|
|
6390
6426
|
grow: css.css({ flexGrow: 1 }),
|
|
6391
6427
|
label: css.css({ fontSize: 12, fontWeight: theme.typography.fontWeightMedium }),
|
|
@@ -6504,7 +6540,7 @@ function SQLOrderByRow({ fields, query, onQueryChange, db }) {
|
|
|
6504
6540
|
const asteriskValue = { label: "*", value: "*" };
|
|
6505
6541
|
function SelectRow({ sql, columns, onSqlChange, functions }) {
|
|
6506
6542
|
var _a;
|
|
6507
|
-
const styles = ui.useStyles2(getStyles$
|
|
6543
|
+
const styles = ui.useStyles2(getStyles$j);
|
|
6508
6544
|
const columnsWithAsterisk = [asteriskValue, ...columns || []];
|
|
6509
6545
|
const onColumnChange = React.useCallback(
|
|
6510
6546
|
(item, index) => (column) => {
|
|
@@ -6600,7 +6636,7 @@ function SelectRow({ sql, columns, onSqlChange, functions }) {
|
|
|
6600
6636
|
}
|
|
6601
6637
|
));
|
|
6602
6638
|
}
|
|
6603
|
-
const getStyles$
|
|
6639
|
+
const getStyles$j = () => {
|
|
6604
6640
|
return { addButton: css.css({ alignSelf: "flex-start" }) };
|
|
6605
6641
|
};
|
|
6606
6642
|
function getColumnValue({ parameters }) {
|
|
@@ -6946,10 +6982,10 @@ function mapFieldsToTypes(columns) {
|
|
|
6946
6982
|
}
|
|
6947
6983
|
|
|
6948
6984
|
const EditorRow = ({ children }) => {
|
|
6949
|
-
const styles = ui.useStyles2(getStyles$
|
|
6985
|
+
const styles = ui.useStyles2(getStyles$i);
|
|
6950
6986
|
return /* @__PURE__ */ React__default.default.createElement("div", { className: styles.root }, /* @__PURE__ */ React__default.default.createElement(EditorStack, { gap: 2 }, children));
|
|
6951
6987
|
};
|
|
6952
|
-
const getStyles$
|
|
6988
|
+
const getStyles$i = (theme) => {
|
|
6953
6989
|
return {
|
|
6954
6990
|
root: css.css({
|
|
6955
6991
|
padding: theme.spacing(1),
|
|
@@ -6963,12 +6999,12 @@ const EditorField = (props) => {
|
|
|
6963
6999
|
var _a;
|
|
6964
7000
|
const { label, optional, tooltip, children, width, ...fieldProps } = props;
|
|
6965
7001
|
const theme = ui.useTheme2();
|
|
6966
|
-
const styles = getStyles$
|
|
7002
|
+
const styles = getStyles$h(theme, width);
|
|
6967
7003
|
const childInputId = (fieldProps == null ? void 0 : fieldProps.htmlFor) || ((_a = ui.ReactUtils) == null ? void 0 : _a.getChildId(children));
|
|
6968
7004
|
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
7005
|
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
7006
|
};
|
|
6971
|
-
const getStyles$
|
|
7007
|
+
const getStyles$h = ui.stylesFactory((theme, width) => {
|
|
6972
7008
|
return {
|
|
6973
7009
|
root: css.css({
|
|
6974
7010
|
minWidth: theme.spacing(width != null ? width : 0)
|
|
@@ -6999,12 +7035,20 @@ const EditorRows = ({ children }) => {
|
|
|
6999
7035
|
return /* @__PURE__ */ React__default.default.createElement(EditorStack, { gap: 0.5, direction: "column" }, children);
|
|
7000
7036
|
};
|
|
7001
7037
|
|
|
7002
|
-
const VisualEditor = ({
|
|
7038
|
+
const VisualEditor = ({
|
|
7039
|
+
query,
|
|
7040
|
+
db,
|
|
7041
|
+
queryRowFilter,
|
|
7042
|
+
onChange,
|
|
7043
|
+
onValidate,
|
|
7044
|
+
language = "sql",
|
|
7045
|
+
range
|
|
7046
|
+
}) => {
|
|
7003
7047
|
const state = reactUse.useAsync(async () => {
|
|
7004
7048
|
const fields = await db.fields(query);
|
|
7005
7049
|
return fields;
|
|
7006
7050
|
}, [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 }));
|
|
7051
|
+
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
7052
|
};
|
|
7009
7053
|
|
|
7010
7054
|
const MACRO_NAMES = [
|
|
@@ -7186,7 +7230,7 @@ const getSearchFilterScopedVar = (args) => {
|
|
|
7186
7230
|
};
|
|
7187
7231
|
};
|
|
7188
7232
|
|
|
7189
|
-
function SqlQueryEditor({ datasource, query, onChange, onRunQuery, range }) {
|
|
7233
|
+
function SqlQueryEditor({ datasource, query, onChange, onRunQuery, range, language = "sql" }) {
|
|
7190
7234
|
var _a, _b, _c, _d, _e, _f, _g;
|
|
7191
7235
|
const [isQueryRunnable, setIsQueryRunnable] = React.useState(true);
|
|
7192
7236
|
const db = datasource.getDB();
|
|
@@ -7262,6 +7306,7 @@ function SqlQueryEditor({ datasource, query, onChange, onRunQuery, range }) {
|
|
|
7262
7306
|
{
|
|
7263
7307
|
db,
|
|
7264
7308
|
query: queryWithDefaults,
|
|
7309
|
+
language,
|
|
7265
7310
|
onChange: (q) => onQueryChange(q, false),
|
|
7266
7311
|
queryRowFilter,
|
|
7267
7312
|
onValidate: setIsQueryRunnable,
|
|
@@ -7271,6 +7316,7 @@ function SqlQueryEditor({ datasource, query, onChange, onRunQuery, range }) {
|
|
|
7271
7316
|
RawEditor,
|
|
7272
7317
|
{
|
|
7273
7318
|
db,
|
|
7319
|
+
language,
|
|
7274
7320
|
query: queryWithDefaults,
|
|
7275
7321
|
queryToValidate,
|
|
7276
7322
|
onChange: onQueryChange,
|
|
@@ -7408,7 +7454,7 @@ const ConfigSubSection = ({ children, ...props }) => {
|
|
|
7408
7454
|
function ConfigDescriptionLink(props) {
|
|
7409
7455
|
const { description, suffix, feature } = props;
|
|
7410
7456
|
const text = `Learn more about ${feature}`;
|
|
7411
|
-
const styles = ui.useStyles2(getStyles$
|
|
7457
|
+
const styles = ui.useStyles2(getStyles$g);
|
|
7412
7458
|
return /* @__PURE__ */ React__default.default.createElement("span", { className: styles.container }, description, /* @__PURE__ */ React__default.default.createElement(
|
|
7413
7459
|
"a",
|
|
7414
7460
|
{
|
|
@@ -7420,7 +7466,7 @@ function ConfigDescriptionLink(props) {
|
|
|
7420
7466
|
text
|
|
7421
7467
|
));
|
|
7422
7468
|
}
|
|
7423
|
-
const getStyles$
|
|
7469
|
+
const getStyles$g = (theme) => {
|
|
7424
7470
|
return {
|
|
7425
7471
|
container: css.css({
|
|
7426
7472
|
color: theme.colors.text.secondary,
|
|
@@ -8389,229 +8435,2315 @@ const AdvancedHttpSettings = ({
|
|
|
8389
8435
|
));
|
|
8390
8436
|
};
|
|
8391
8437
|
|
|
8392
|
-
|
|
8393
|
-
|
|
8394
|
-
|
|
8395
|
-
|
|
8396
|
-
|
|
8397
|
-
|
|
8398
|
-
|
|
8399
|
-
|
|
8400
|
-
|
|
8401
|
-
|
|
8402
|
-
|
|
8403
|
-
|
|
8404
|
-
|
|
8405
|
-
|
|
8406
|
-
|
|
8407
|
-
|
|
8408
|
-
}
|
|
8409
|
-
}
|
|
8410
|
-
`
|
|
8411
|
-
};
|
|
8412
|
-
});
|
|
8413
|
-
const CustomHeaderRow = ({ header, onBlur, onChange, onRemove, onReset }) => {
|
|
8414
|
-
const styles = getCustomHeaderRowStyles();
|
|
8415
|
-
return /* @__PURE__ */ React__default.default.createElement("div", { className: styles.layout }, /* @__PURE__ */ React__default.default.createElement(
|
|
8416
|
-
ui.LegacyForms.FormField,
|
|
8438
|
+
function resolveGroups(schema) {
|
|
8439
|
+
const fieldMap = /* @__PURE__ */ new Map();
|
|
8440
|
+
for (const f of schema.fields) {
|
|
8441
|
+
fieldMap.set(f.id, f);
|
|
8442
|
+
}
|
|
8443
|
+
if (schema.groups && schema.groups.length > 0) {
|
|
8444
|
+
return schema.groups.slice().sort((a, b) => {
|
|
8445
|
+
var _a, _b;
|
|
8446
|
+
return ((_a = a.order) != null ? _a : 0) - ((_b = b.order) != null ? _b : 0);
|
|
8447
|
+
}).map((g) => ({
|
|
8448
|
+
group: g,
|
|
8449
|
+
fields: g.fieldRefs.map((ref) => fieldMap.get(ref)).filter((f) => f != null)
|
|
8450
|
+
}));
|
|
8451
|
+
}
|
|
8452
|
+
const allFields = schema.fields.filter((f) => f.kind !== "virtual" && !f.isItemField);
|
|
8453
|
+
return [
|
|
8417
8454
|
{
|
|
8418
|
-
|
|
8419
|
-
|
|
8420
|
-
placeholder: "X-Custom-Header",
|
|
8421
|
-
labelWidth: 5,
|
|
8422
|
-
value: header.name || "",
|
|
8423
|
-
onChange: (e) => onChange({ ...header, name: e.target.value }),
|
|
8424
|
-
onBlur
|
|
8455
|
+
group: { id: "default", title: "Configuration", fieldRefs: allFields.map((f) => f.id) },
|
|
8456
|
+
fields: allFields
|
|
8425
8457
|
}
|
|
8426
|
-
|
|
8427
|
-
|
|
8428
|
-
|
|
8429
|
-
|
|
8430
|
-
|
|
8431
|
-
|
|
8432
|
-
|
|
8433
|
-
|
|
8434
|
-
|
|
8435
|
-
|
|
8436
|
-
|
|
8437
|
-
|
|
8438
|
-
onChange: (e) => onChange({ ...header, value: e.target.value }),
|
|
8439
|
-
onBlur
|
|
8458
|
+
];
|
|
8459
|
+
}
|
|
8460
|
+
function resolveRequiredFieldsGroup(schema) {
|
|
8461
|
+
var _a;
|
|
8462
|
+
const fieldMap = /* @__PURE__ */ new Map();
|
|
8463
|
+
for (const f of schema.fields) {
|
|
8464
|
+
fieldMap.set(f.id, f);
|
|
8465
|
+
}
|
|
8466
|
+
const requiredIds = /* @__PURE__ */ new Set();
|
|
8467
|
+
for (const f of schema.fields) {
|
|
8468
|
+
if (f.required) {
|
|
8469
|
+
requiredIds.add(f.id);
|
|
8440
8470
|
}
|
|
8441
|
-
|
|
8442
|
-
|
|
8443
|
-
|
|
8444
|
-
|
|
8445
|
-
|
|
8446
|
-
|
|
8447
|
-
size: "xs",
|
|
8448
|
-
onClick: (_e) => onRemove(header.id)
|
|
8449
|
-
},
|
|
8450
|
-
/* @__PURE__ */ React__default.default.createElement(ui.Icon, { name: "trash-alt" })
|
|
8451
|
-
));
|
|
8452
|
-
};
|
|
8453
|
-
CustomHeaderRow.displayName = "CustomHeaderRow";
|
|
8454
|
-
class CustomHeadersSettings extends React.PureComponent {
|
|
8455
|
-
constructor(props) {
|
|
8456
|
-
super(props);
|
|
8457
|
-
__publicField$1(this, "state", {
|
|
8458
|
-
headers: []
|
|
8459
|
-
});
|
|
8460
|
-
__publicField$1(this, "updateSettings", () => {
|
|
8461
|
-
const { headers } = this.state;
|
|
8462
|
-
const newJsonData = Object.fromEntries(
|
|
8463
|
-
Object.entries(this.props.dataSourceConfig.jsonData).filter(([key, val]) => !key.startsWith("httpHeaderName"))
|
|
8464
|
-
);
|
|
8465
|
-
const newSecureJsonData = Object.fromEntries(
|
|
8466
|
-
Object.entries(this.props.dataSourceConfig.secureJsonData || {}).filter(
|
|
8467
|
-
([key, val]) => !key.startsWith("httpHeaderValue")
|
|
8468
|
-
)
|
|
8469
|
-
);
|
|
8470
|
-
for (const [index, header] of headers.entries()) {
|
|
8471
|
-
newJsonData[`httpHeaderName${index + 1}`] = header.name;
|
|
8472
|
-
if (!header.configured) {
|
|
8473
|
-
newSecureJsonData[`httpHeaderValue${index + 1}`] = header.value;
|
|
8474
|
-
}
|
|
8471
|
+
}
|
|
8472
|
+
const authGroup = (_a = schema.groups) == null ? void 0 : _a.find((g) => g.id === "auth");
|
|
8473
|
+
if (authGroup) {
|
|
8474
|
+
for (const ref of authGroup.fieldRefs) {
|
|
8475
|
+
if (fieldMap.has(ref)) {
|
|
8476
|
+
requiredIds.add(ref);
|
|
8475
8477
|
}
|
|
8476
|
-
|
|
8477
|
-
...this.props.dataSourceConfig,
|
|
8478
|
-
jsonData: newJsonData,
|
|
8479
|
-
secureJsonData: newSecureJsonData
|
|
8480
|
-
});
|
|
8481
|
-
});
|
|
8482
|
-
__publicField$1(this, "onHeaderAdd", () => {
|
|
8483
|
-
this.setState((prevState) => {
|
|
8484
|
-
return {
|
|
8485
|
-
headers: [...prevState.headers, { id: lodash.uniqueId(), name: "", value: "", configured: false }]
|
|
8486
|
-
};
|
|
8487
|
-
});
|
|
8488
|
-
});
|
|
8489
|
-
__publicField$1(this, "onHeaderChange", (headerIndex, value) => {
|
|
8490
|
-
this.setState(({ headers }) => {
|
|
8491
|
-
return {
|
|
8492
|
-
headers: headers.map((item, index) => {
|
|
8493
|
-
if (headerIndex !== index) {
|
|
8494
|
-
return item;
|
|
8495
|
-
}
|
|
8496
|
-
return { ...value };
|
|
8497
|
-
})
|
|
8498
|
-
};
|
|
8499
|
-
});
|
|
8500
|
-
});
|
|
8501
|
-
__publicField$1(this, "onHeaderReset", (headerId) => {
|
|
8502
|
-
this.setState(({ headers }) => {
|
|
8503
|
-
return {
|
|
8504
|
-
headers: headers.map((h, i) => {
|
|
8505
|
-
if (h.id !== headerId) {
|
|
8506
|
-
return h;
|
|
8507
|
-
}
|
|
8508
|
-
return {
|
|
8509
|
-
...h,
|
|
8510
|
-
value: "",
|
|
8511
|
-
configured: false
|
|
8512
|
-
};
|
|
8513
|
-
})
|
|
8514
|
-
};
|
|
8515
|
-
});
|
|
8516
|
-
});
|
|
8517
|
-
__publicField$1(this, "onHeaderRemove", (headerId) => {
|
|
8518
|
-
this.setState(
|
|
8519
|
-
({ headers }) => ({
|
|
8520
|
-
headers: headers.filter((h) => h.id !== headerId)
|
|
8521
|
-
}),
|
|
8522
|
-
this.updateSettings
|
|
8523
|
-
);
|
|
8524
|
-
});
|
|
8525
|
-
const { jsonData, secureJsonData, secureJsonFields } = this.props.dataSourceConfig;
|
|
8526
|
-
this.state = {
|
|
8527
|
-
headers: Object.keys(jsonData).sort().filter((key) => key.startsWith("httpHeaderName")).map((key, index) => {
|
|
8528
|
-
return {
|
|
8529
|
-
id: lodash.uniqueId(),
|
|
8530
|
-
name: jsonData[key],
|
|
8531
|
-
value: secureJsonData !== void 0 ? secureJsonData[key] : "",
|
|
8532
|
-
configured: secureJsonFields && secureJsonFields[`httpHeaderValue${index + 1}`] || false
|
|
8533
|
-
};
|
|
8534
|
-
})
|
|
8535
|
-
};
|
|
8478
|
+
}
|
|
8536
8479
|
}
|
|
8537
|
-
|
|
8538
|
-
|
|
8539
|
-
|
|
8540
|
-
|
|
8541
|
-
|
|
8542
|
-
|
|
8543
|
-
|
|
8544
|
-
|
|
8545
|
-
|
|
8546
|
-
|
|
8547
|
-
|
|
8548
|
-
onRemove: this.onHeaderRemove,
|
|
8549
|
-
onReset: this.onHeaderReset
|
|
8480
|
+
if (requiredIds.size === 0) {
|
|
8481
|
+
return null;
|
|
8482
|
+
}
|
|
8483
|
+
const includeIds = /* @__PURE__ */ new Set();
|
|
8484
|
+
for (const id of requiredIds) {
|
|
8485
|
+
includeIds.add(id);
|
|
8486
|
+
const f = fieldMap.get(id);
|
|
8487
|
+
if (f == null ? void 0 : f.dependsOn) {
|
|
8488
|
+
const parsed = parseDependsOn(f.dependsOn);
|
|
8489
|
+
if (parsed && fieldMap.has(parsed.field)) {
|
|
8490
|
+
includeIds.add(parsed.field);
|
|
8550
8491
|
}
|
|
8551
|
-
|
|
8552
|
-
ui.Button,
|
|
8553
|
-
{
|
|
8554
|
-
variant: "secondary",
|
|
8555
|
-
icon: "plus",
|
|
8556
|
-
type: "button",
|
|
8557
|
-
onClick: (e) => {
|
|
8558
|
-
this.onHeaderAdd();
|
|
8559
|
-
}
|
|
8560
|
-
},
|
|
8561
|
-
"Add header"
|
|
8562
|
-
)));
|
|
8492
|
+
}
|
|
8563
8493
|
}
|
|
8564
|
-
|
|
8565
|
-
|
|
8566
|
-
|
|
8567
|
-
|
|
8568
|
-
|
|
8569
|
-
|
|
8570
|
-
}
|
|
8571
|
-
const BINARY_OPERATIONS_KEY = "Binary operations";
|
|
8572
|
-
|
|
8573
|
-
var __defProp = Object.defineProperty;
|
|
8574
|
-
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
8575
|
-
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
8576
|
-
class QueryModellerBase {
|
|
8577
|
-
constructor(operationDefinitions, innerQueryPlaceholder) {
|
|
8578
|
-
__publicField(this, "operationsRegistry");
|
|
8579
|
-
__publicField(this, "categories", []);
|
|
8580
|
-
__publicField(this, "innerQueryPlaceholder");
|
|
8581
|
-
this.operationsRegistry = new data.Registry(() => operationDefinitions);
|
|
8582
|
-
this.innerQueryPlaceholder = innerQueryPlaceholder || "<query>";
|
|
8494
|
+
for (const f of schema.fields) {
|
|
8495
|
+
if (f.dependsOn && !includeIds.has(f.id)) {
|
|
8496
|
+
const parsed = parseDependsOn(f.dependsOn);
|
|
8497
|
+
if (parsed && requiredIds.has(parsed.field)) {
|
|
8498
|
+
includeIds.add(f.id);
|
|
8499
|
+
}
|
|
8500
|
+
}
|
|
8583
8501
|
}
|
|
8584
|
-
|
|
8585
|
-
|
|
8502
|
+
const virtualFields = schema.fields.filter((f) => includeIds.has(f.id));
|
|
8503
|
+
if (virtualFields.length === 0) {
|
|
8504
|
+
return null;
|
|
8586
8505
|
}
|
|
8587
|
-
|
|
8588
|
-
|
|
8506
|
+
return {
|
|
8507
|
+
group: {
|
|
8508
|
+
id: "_required",
|
|
8509
|
+
title: "Required",
|
|
8510
|
+
fieldRefs: virtualFields.map((f) => f.id)
|
|
8511
|
+
},
|
|
8512
|
+
fields: virtualFields
|
|
8513
|
+
};
|
|
8514
|
+
}
|
|
8515
|
+
function formKey(field) {
|
|
8516
|
+
return field.section ? `${field.section}.${field.key}` : field.key;
|
|
8517
|
+
}
|
|
8518
|
+
function parseDependsOn(expr) {
|
|
8519
|
+
var _a, _b;
|
|
8520
|
+
const m = expr.match(/^(.+?)\s*==\s*(?:'([^']*)'|"([^"]*)"|(.+))$/);
|
|
8521
|
+
if (!m) {
|
|
8522
|
+
return null;
|
|
8589
8523
|
}
|
|
8590
|
-
|
|
8591
|
-
|
|
8524
|
+
return { field: m[1].trim(), value: ((_b = (_a = m[2]) != null ? _a : m[3]) != null ? _b : m[4]).trim() };
|
|
8525
|
+
}
|
|
8526
|
+
function resolveActiveOverride(field, watchedValues, fieldById) {
|
|
8527
|
+
var _a;
|
|
8528
|
+
if (!field.overrides || field.overrides.length === 0) {
|
|
8529
|
+
return void 0;
|
|
8592
8530
|
}
|
|
8593
|
-
|
|
8594
|
-
|
|
8531
|
+
for (const ov of field.overrides) {
|
|
8532
|
+
const parsed = parseDependsOn(ov.when);
|
|
8533
|
+
if (!parsed) {
|
|
8534
|
+
continue;
|
|
8535
|
+
}
|
|
8536
|
+
const depField = fieldById.get(parsed.field);
|
|
8537
|
+
const depKey = depField ? formKey(depField) : parsed.field;
|
|
8538
|
+
if (String((_a = watchedValues[depKey]) != null ? _a : "") === parsed.value) {
|
|
8539
|
+
return ov;
|
|
8540
|
+
}
|
|
8595
8541
|
}
|
|
8596
|
-
|
|
8597
|
-
|
|
8542
|
+
return void 0;
|
|
8543
|
+
}
|
|
8544
|
+
function resolveFieldValue(ref, values, fields) {
|
|
8545
|
+
if (ref in values) {
|
|
8546
|
+
return values[ref];
|
|
8598
8547
|
}
|
|
8599
|
-
|
|
8600
|
-
|
|
8601
|
-
|
|
8602
|
-
|
|
8603
|
-
|
|
8548
|
+
const field = fields.find((f) => f.id === ref);
|
|
8549
|
+
if (field) {
|
|
8550
|
+
const fk = formKey(field);
|
|
8551
|
+
if (fk in values) {
|
|
8552
|
+
return values[fk];
|
|
8553
|
+
}
|
|
8604
8554
|
}
|
|
8555
|
+
return void 0;
|
|
8605
8556
|
}
|
|
8606
|
-
|
|
8607
|
-
|
|
8608
|
-
|
|
8609
|
-
|
|
8610
|
-
|
|
8611
|
-
|
|
8612
|
-
|
|
8613
|
-
|
|
8614
|
-
|
|
8557
|
+
function evaluateComputedRead(expr, values, fields) {
|
|
8558
|
+
function evalExpr(s) {
|
|
8559
|
+
var _a;
|
|
8560
|
+
s = s.trim();
|
|
8561
|
+
if (s.startsWith("(") && findMatchingParen(s, 0) === s.length - 1) {
|
|
8562
|
+
s = s.slice(1, -1).trim();
|
|
8563
|
+
}
|
|
8564
|
+
const qIdx = findTopLevel(s, "?");
|
|
8565
|
+
if (qIdx !== -1) {
|
|
8566
|
+
const condition = s.slice(0, qIdx).trim();
|
|
8567
|
+
const rest = s.slice(qIdx + 1);
|
|
8568
|
+
const cIdx = findTopLevel(rest, ":");
|
|
8569
|
+
if (cIdx !== -1) {
|
|
8570
|
+
const trueExpr = rest.slice(0, cIdx).trim();
|
|
8571
|
+
const falseExpr = rest.slice(cIdx + 1).trim();
|
|
8572
|
+
return evalCondition(condition) ? evalExpr(trueExpr) : evalExpr(falseExpr);
|
|
8573
|
+
}
|
|
8574
|
+
}
|
|
8575
|
+
const strMatch = (_a = s.match(/^'([^']*)'$/)) != null ? _a : s.match(/^"([^"]*)"$/);
|
|
8576
|
+
if (strMatch) {
|
|
8577
|
+
return strMatch[1];
|
|
8578
|
+
}
|
|
8579
|
+
if (s === "true") {
|
|
8580
|
+
return true;
|
|
8581
|
+
}
|
|
8582
|
+
if (s === "false") {
|
|
8583
|
+
return false;
|
|
8584
|
+
}
|
|
8585
|
+
if (/^-?\d+(\.\d+)?$/.test(s)) {
|
|
8586
|
+
return Number(s);
|
|
8587
|
+
}
|
|
8588
|
+
return resolveFieldValue(s, values, fields);
|
|
8589
|
+
}
|
|
8590
|
+
function evalCondition(cond) {
|
|
8591
|
+
const eqMatch = cond.match(/^(.+?)\s*(==|!=)\s*(.+)$/);
|
|
8592
|
+
if (eqMatch) {
|
|
8593
|
+
const left = evalExpr(eqMatch[1]);
|
|
8594
|
+
const right = evalExpr(eqMatch[3]);
|
|
8595
|
+
const eq = String(left) === String(right);
|
|
8596
|
+
return eqMatch[2] === "==" ? eq : !eq;
|
|
8597
|
+
}
|
|
8598
|
+
return !!evalExpr(cond);
|
|
8599
|
+
}
|
|
8600
|
+
function findMatchingParen(s, start) {
|
|
8601
|
+
let depth = 0;
|
|
8602
|
+
for (let i = start; i < s.length; i++) {
|
|
8603
|
+
if (s[i] === "(") {
|
|
8604
|
+
depth++;
|
|
8605
|
+
} else if (s[i] === ")") {
|
|
8606
|
+
depth--;
|
|
8607
|
+
if (depth === 0) {
|
|
8608
|
+
return i;
|
|
8609
|
+
}
|
|
8610
|
+
}
|
|
8611
|
+
}
|
|
8612
|
+
return -1;
|
|
8613
|
+
}
|
|
8614
|
+
function findTopLevel(s, char) {
|
|
8615
|
+
let depth = 0;
|
|
8616
|
+
let inStr = null;
|
|
8617
|
+
for (let i = 0; i < s.length; i++) {
|
|
8618
|
+
const c = s[i];
|
|
8619
|
+
if (inStr) {
|
|
8620
|
+
if (c === inStr) {
|
|
8621
|
+
inStr = null;
|
|
8622
|
+
}
|
|
8623
|
+
continue;
|
|
8624
|
+
}
|
|
8625
|
+
if (c === "'" || c === '"') {
|
|
8626
|
+
inStr = c;
|
|
8627
|
+
continue;
|
|
8628
|
+
}
|
|
8629
|
+
if (c === "(") {
|
|
8630
|
+
depth++;
|
|
8631
|
+
continue;
|
|
8632
|
+
}
|
|
8633
|
+
if (c === ")") {
|
|
8634
|
+
depth--;
|
|
8635
|
+
continue;
|
|
8636
|
+
}
|
|
8637
|
+
if (depth === 0 && c === char) {
|
|
8638
|
+
return i;
|
|
8639
|
+
}
|
|
8640
|
+
}
|
|
8641
|
+
return -1;
|
|
8642
|
+
}
|
|
8643
|
+
try {
|
|
8644
|
+
return evalExpr(expr);
|
|
8645
|
+
} catch (e) {
|
|
8646
|
+
return void 0;
|
|
8647
|
+
}
|
|
8648
|
+
}
|
|
8649
|
+
function computeVirtualFieldValues(schema, existingValues) {
|
|
8650
|
+
var _a;
|
|
8651
|
+
const virtualValues = {};
|
|
8652
|
+
for (const field of schema.fields) {
|
|
8653
|
+
if (field.kind !== "virtual") {
|
|
8654
|
+
continue;
|
|
8655
|
+
}
|
|
8656
|
+
const fk = formKey(field);
|
|
8657
|
+
if (((_a = field.storage) == null ? void 0 : _a.type) === "computed" && field.storage.read) {
|
|
8658
|
+
const val = evaluateComputedRead(field.storage.read, existingValues, schema.fields);
|
|
8659
|
+
if (val !== void 0) {
|
|
8660
|
+
virtualValues[fk] = val;
|
|
8661
|
+
} else if (field.defaultValue !== void 0) {
|
|
8662
|
+
virtualValues[fk] = field.defaultValue;
|
|
8663
|
+
}
|
|
8664
|
+
} else if (field.defaultValue !== void 0) {
|
|
8665
|
+
virtualValues[fk] = field.defaultValue;
|
|
8666
|
+
}
|
|
8667
|
+
}
|
|
8668
|
+
return virtualValues;
|
|
8669
|
+
}
|
|
8670
|
+
|
|
8671
|
+
const SECURE_FIELD_CONFIGURED = "__CONFIGURED__";
|
|
8672
|
+
function patternToRegex(pattern) {
|
|
8673
|
+
const escaped = pattern.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
8674
|
+
return new RegExp("^" + escaped.replace("\\{index\\}", "(\\d+)") + "$");
|
|
8675
|
+
}
|
|
8676
|
+
function findIndicesForPattern(record, pattern) {
|
|
8677
|
+
const re = patternToRegex(pattern);
|
|
8678
|
+
const indices = [];
|
|
8679
|
+
for (const key of Object.keys(record)) {
|
|
8680
|
+
const m = key.match(re);
|
|
8681
|
+
if (m) {
|
|
8682
|
+
const n = Number(m[1]);
|
|
8683
|
+
if (!Number.isNaN(n)) {
|
|
8684
|
+
indices.push(n);
|
|
8685
|
+
}
|
|
8686
|
+
}
|
|
8687
|
+
}
|
|
8688
|
+
return indices.sort((a, b) => a - b);
|
|
8689
|
+
}
|
|
8690
|
+
function expandIndexedPair(field, ds) {
|
|
8691
|
+
var _a, _b, _c;
|
|
8692
|
+
const storage = field.storage;
|
|
8693
|
+
if ((storage == null ? void 0 : storage.type) !== "indexedPair" || !storage.key || !storage.value) {
|
|
8694
|
+
return [];
|
|
8695
|
+
}
|
|
8696
|
+
const source = storage.key.target === "jsonData" ? (_a = ds.jsonData) != null ? _a : {} : ds;
|
|
8697
|
+
const indices = findIndicesForPattern(source, storage.key.pattern);
|
|
8698
|
+
const items = [];
|
|
8699
|
+
for (const i of indices) {
|
|
8700
|
+
const nameKey = storage.key.pattern.replace("{index}", String(i));
|
|
8701
|
+
const valueKey = storage.value.pattern.replace("{index}", String(i));
|
|
8702
|
+
const nameVal = source[nameKey];
|
|
8703
|
+
if (nameVal === void 0 || nameVal === null) {
|
|
8704
|
+
continue;
|
|
8705
|
+
}
|
|
8706
|
+
const hasValue = storage.value.target === "secureJsonData" ? !!((_b = ds.secureJsonFields) == null ? void 0 : _b[valueKey]) : !!((_c = ds.jsonData) == null ? void 0 : _c[valueKey]);
|
|
8707
|
+
items.push({
|
|
8708
|
+
index: i,
|
|
8709
|
+
name: String(nameVal),
|
|
8710
|
+
value: hasValue ? SECURE_FIELD_CONFIGURED : ""
|
|
8711
|
+
});
|
|
8712
|
+
}
|
|
8713
|
+
return items;
|
|
8714
|
+
}
|
|
8715
|
+
function flattenIndexedPair(field, items, jsonData, secureJsonData, secureJsonFields) {
|
|
8716
|
+
var _a;
|
|
8717
|
+
const storage = field.storage;
|
|
8718
|
+
if ((storage == null ? void 0 : storage.type) !== "indexedPair" || !storage.key || !storage.value) {
|
|
8719
|
+
return;
|
|
8720
|
+
}
|
|
8721
|
+
const existingIndices = new Set(
|
|
8722
|
+
storage.key.target === "jsonData" ? findIndicesForPattern(jsonData, storage.key.pattern) : []
|
|
8723
|
+
);
|
|
8724
|
+
const usedIndices = /* @__PURE__ */ new Set();
|
|
8725
|
+
const startIdx = (_a = storage.startIndex) != null ? _a : 1;
|
|
8726
|
+
let nextIndex = existingIndices.size > 0 ? Math.max(...existingIndices) + 1 : startIdx;
|
|
8727
|
+
for (const item of items) {
|
|
8728
|
+
let idx = item.index;
|
|
8729
|
+
if (idx === 0) {
|
|
8730
|
+
idx = nextIndex++;
|
|
8731
|
+
}
|
|
8732
|
+
usedIndices.add(idx);
|
|
8733
|
+
const nameKey = storage.key.pattern.replace("{index}", String(idx));
|
|
8734
|
+
const valueKey = storage.value.pattern.replace("{index}", String(idx));
|
|
8735
|
+
if (storage.key.target === "jsonData") {
|
|
8736
|
+
jsonData[nameKey] = item.name;
|
|
8737
|
+
}
|
|
8738
|
+
if (storage.value.target === "secureJsonData") {
|
|
8739
|
+
if (item.value === SECURE_FIELD_CONFIGURED) {
|
|
8740
|
+
secureJsonFields[valueKey] = true;
|
|
8741
|
+
} else if (item.value) {
|
|
8742
|
+
secureJsonData[valueKey] = item.value;
|
|
8743
|
+
secureJsonFields[valueKey] = false;
|
|
8744
|
+
}
|
|
8745
|
+
} else if (storage.value.target === "jsonData") {
|
|
8746
|
+
jsonData[valueKey] = item.value;
|
|
8747
|
+
}
|
|
8748
|
+
}
|
|
8749
|
+
for (const idx of existingIndices) {
|
|
8750
|
+
if (usedIndices.has(idx)) {
|
|
8751
|
+
continue;
|
|
8752
|
+
}
|
|
8753
|
+
const nameKey = storage.key.pattern.replace("{index}", String(idx));
|
|
8754
|
+
const valueKey = storage.value.pattern.replace("{index}", String(idx));
|
|
8755
|
+
if (storage.key.target === "jsonData") {
|
|
8756
|
+
delete jsonData[nameKey];
|
|
8757
|
+
}
|
|
8758
|
+
if (storage.value.target === "secureJsonData") {
|
|
8759
|
+
delete secureJsonFields[valueKey];
|
|
8760
|
+
delete secureJsonData[valueKey];
|
|
8761
|
+
} else if (storage.value.target === "jsonData") {
|
|
8762
|
+
delete jsonData[valueKey];
|
|
8763
|
+
}
|
|
8764
|
+
}
|
|
8765
|
+
}
|
|
8766
|
+
function resolveRawPath(ref, ds) {
|
|
8767
|
+
var _a;
|
|
8768
|
+
const trimmed = ref.trim();
|
|
8769
|
+
if (trimmed.startsWith("jsonData.")) {
|
|
8770
|
+
return (_a = ds.jsonData) == null ? void 0 : _a[trimmed.slice(9)];
|
|
8771
|
+
}
|
|
8772
|
+
if (trimmed.startsWith("root.")) {
|
|
8773
|
+
return ds[trimmed.slice(5)];
|
|
8774
|
+
}
|
|
8775
|
+
return void 0;
|
|
8776
|
+
}
|
|
8777
|
+
async function fetchExistingValues(dsUid, fields) {
|
|
8778
|
+
var _a, _b, _c, _d, _e;
|
|
8779
|
+
try {
|
|
8780
|
+
const ds = await runtime.getBackendSrv().get(`/api/datasources/uid/${dsUid}`, void 0, void 0, {
|
|
8781
|
+
showErrorAlert: false
|
|
8782
|
+
});
|
|
8783
|
+
const values = {};
|
|
8784
|
+
for (const field of fields) {
|
|
8785
|
+
if (((_a = field.storage) == null ? void 0 : _a.type) === "indexedPair") {
|
|
8786
|
+
values[field.key] = expandIndexedPair(field, ds);
|
|
8787
|
+
continue;
|
|
8788
|
+
}
|
|
8789
|
+
const fk = formKey(field);
|
|
8790
|
+
switch (field.target) {
|
|
8791
|
+
case "root":
|
|
8792
|
+
if (ds[field.key] !== void 0) {
|
|
8793
|
+
values[fk] = ds[field.key];
|
|
8794
|
+
}
|
|
8795
|
+
break;
|
|
8796
|
+
case "jsonData":
|
|
8797
|
+
if (field.section) {
|
|
8798
|
+
const sectionObj = (_b = ds.jsonData) == null ? void 0 : _b[field.section];
|
|
8799
|
+
if ((sectionObj == null ? void 0 : sectionObj[field.key]) !== void 0) {
|
|
8800
|
+
values[fk] = sectionObj[field.key];
|
|
8801
|
+
}
|
|
8802
|
+
} else if (((_c = ds.jsonData) == null ? void 0 : _c[field.key]) !== void 0) {
|
|
8803
|
+
values[fk] = ds.jsonData[field.key];
|
|
8804
|
+
}
|
|
8805
|
+
break;
|
|
8806
|
+
case "secureJsonData":
|
|
8807
|
+
if ((_d = ds.secureJsonFields) == null ? void 0 : _d[field.key]) {
|
|
8808
|
+
values[fk] = SECURE_FIELD_CONFIGURED;
|
|
8809
|
+
}
|
|
8810
|
+
break;
|
|
8811
|
+
}
|
|
8812
|
+
if (values[fk] === void 0 && ((_e = field.storage) == null ? void 0 : _e.type) === "computed" && field.storage.read) {
|
|
8813
|
+
const fallback = resolveRawPath(field.storage.read, ds);
|
|
8814
|
+
if (fallback !== void 0) {
|
|
8815
|
+
values[fk] = fallback;
|
|
8816
|
+
}
|
|
8817
|
+
}
|
|
8818
|
+
}
|
|
8819
|
+
return { values, readOnly: !!ds.readOnly };
|
|
8820
|
+
} catch (err) {
|
|
8821
|
+
const message = err instanceof Error ? err.message : "Failed to load datasource configuration";
|
|
8822
|
+
return { values: {}, readOnly: false, error: message };
|
|
8823
|
+
}
|
|
8824
|
+
}
|
|
8825
|
+
function buildDatasourceConfigPayload(data, fields, existing, isFieldVisible) {
|
|
8826
|
+
var _a, _b, _c, _d;
|
|
8827
|
+
const rootFields = {};
|
|
8828
|
+
const jsonData = { ...(_a = existing.jsonData) != null ? _a : {} };
|
|
8829
|
+
const secureJsonData = {};
|
|
8830
|
+
const secureJsonFields = { ...(_b = existing.secureJsonFields) != null ? _b : {} };
|
|
8831
|
+
for (const field of fields) {
|
|
8832
|
+
if (((_c = field.storage) == null ? void 0 : _c.type) === "indexedPair") {
|
|
8833
|
+
const items = Array.isArray(data[field.key]) ? data[field.key] : [];
|
|
8834
|
+
flattenIndexedPair(field, items, jsonData, secureJsonData, secureJsonFields);
|
|
8835
|
+
continue;
|
|
8836
|
+
}
|
|
8837
|
+
const isManagedByEffect = (_d = field.tags) == null ? void 0 : _d.some((t) => t.startsWith("managed-by:"));
|
|
8838
|
+
if (!isManagedByEffect && !isFieldVisible(field)) {
|
|
8839
|
+
continue;
|
|
8840
|
+
}
|
|
8841
|
+
const fk = formKey(field);
|
|
8842
|
+
const value = data[fk];
|
|
8843
|
+
if (field.target === "secureJsonData") {
|
|
8844
|
+
if (value === SECURE_FIELD_CONFIGURED) {
|
|
8845
|
+
secureJsonFields[field.key] = true;
|
|
8846
|
+
continue;
|
|
8847
|
+
}
|
|
8848
|
+
if (value && value !== "") {
|
|
8849
|
+
secureJsonData[field.key] = String(value);
|
|
8850
|
+
secureJsonFields[field.key] = false;
|
|
8851
|
+
} else {
|
|
8852
|
+
secureJsonFields[field.key] = false;
|
|
8853
|
+
}
|
|
8854
|
+
continue;
|
|
8855
|
+
}
|
|
8856
|
+
if (value === void 0 || value === "") {
|
|
8857
|
+
continue;
|
|
8858
|
+
}
|
|
8859
|
+
switch (field.target) {
|
|
8860
|
+
case "root":
|
|
8861
|
+
rootFields[field.key] = value;
|
|
8862
|
+
break;
|
|
8863
|
+
case "jsonData":
|
|
8864
|
+
if (field.section) {
|
|
8865
|
+
if (!jsonData[field.section] || typeof jsonData[field.section] !== "object") {
|
|
8866
|
+
jsonData[field.section] = {};
|
|
8867
|
+
}
|
|
8868
|
+
jsonData[field.section][field.key] = value;
|
|
8869
|
+
} else {
|
|
8870
|
+
jsonData[field.key] = value;
|
|
8871
|
+
}
|
|
8872
|
+
break;
|
|
8873
|
+
}
|
|
8874
|
+
}
|
|
8875
|
+
return { rootFields, jsonData, secureJsonData, secureJsonFields };
|
|
8876
|
+
}
|
|
8877
|
+
async function submitDatasourceConfig(dsUid, data, fields, isFieldVisible) {
|
|
8878
|
+
const existing = await runtime.getBackendSrv().get(`/api/datasources/uid/${dsUid}`);
|
|
8879
|
+
const { rootFields, jsonData, secureJsonData, secureJsonFields } = buildDatasourceConfigPayload(
|
|
8880
|
+
data,
|
|
8881
|
+
fields,
|
|
8882
|
+
existing,
|
|
8883
|
+
isFieldVisible
|
|
8884
|
+
);
|
|
8885
|
+
await runtime.getBackendSrv().put(`/api/datasources/uid/${dsUid}`, {
|
|
8886
|
+
...existing,
|
|
8887
|
+
...rootFields,
|
|
8888
|
+
jsonData,
|
|
8889
|
+
secureJsonData,
|
|
8890
|
+
secureJsonFields
|
|
8891
|
+
});
|
|
8892
|
+
}
|
|
8893
|
+
|
|
8894
|
+
function evaluateEffectCondition(when, fieldValue) {
|
|
8895
|
+
var _a, _b;
|
|
8896
|
+
const m = when.match(/^value\s*(==|!=)\s*(?:'([^']*)'|"([^"]*)"|(.+))$/);
|
|
8897
|
+
if (!m) {
|
|
8898
|
+
return false;
|
|
8899
|
+
}
|
|
8900
|
+
const op = m[1];
|
|
8901
|
+
let target = (_b = (_a = m[2]) != null ? _a : m[3]) != null ? _b : m[4];
|
|
8902
|
+
if (target === "true") {
|
|
8903
|
+
target = true;
|
|
8904
|
+
} else if (target === "false") {
|
|
8905
|
+
target = false;
|
|
8906
|
+
} else if (typeof target === "string" && /^-?\d+(\.\d+)?$/.test(target)) {
|
|
8907
|
+
target = Number(target);
|
|
8908
|
+
}
|
|
8909
|
+
const eq = String(fieldValue) === String(target);
|
|
8910
|
+
return op === "==" ? eq : !eq;
|
|
8911
|
+
}
|
|
8912
|
+
function isFieldRequired(field, watchedValues, fieldById) {
|
|
8913
|
+
var _a;
|
|
8914
|
+
if (field.required) {
|
|
8915
|
+
return true;
|
|
8916
|
+
}
|
|
8917
|
+
if (field.requiredWhen) {
|
|
8918
|
+
const parsed = parseDependsOn(field.requiredWhen);
|
|
8919
|
+
if (parsed) {
|
|
8920
|
+
const depField = fieldById.get(parsed.field);
|
|
8921
|
+
const depKey = depField ? formKey(depField) : parsed.field;
|
|
8922
|
+
return String((_a = watchedValues[depKey]) != null ? _a : "") === parsed.value;
|
|
8923
|
+
}
|
|
8924
|
+
}
|
|
8925
|
+
return false;
|
|
8926
|
+
}
|
|
8927
|
+
function buildValidationRules(field, required) {
|
|
8928
|
+
var _a, _b, _c, _d, _e, _f;
|
|
8929
|
+
const rules = {};
|
|
8930
|
+
const label = (_a = field.label) != null ? _a : field.key;
|
|
8931
|
+
if (required) {
|
|
8932
|
+
if (field.target === "secureJsonData") {
|
|
8933
|
+
rules.validate = (value) => {
|
|
8934
|
+
if (value === SECURE_FIELD_CONFIGURED) {
|
|
8935
|
+
return true;
|
|
8936
|
+
}
|
|
8937
|
+
if (!value || value === "") {
|
|
8938
|
+
return `${label} is required`;
|
|
8939
|
+
}
|
|
8940
|
+
return true;
|
|
8941
|
+
};
|
|
8942
|
+
} else {
|
|
8943
|
+
rules.required = `${label} is required`;
|
|
8944
|
+
}
|
|
8945
|
+
}
|
|
8946
|
+
if (field.validations) {
|
|
8947
|
+
for (const v of field.validations) {
|
|
8948
|
+
switch (v.type) {
|
|
8949
|
+
case "pattern":
|
|
8950
|
+
rules.pattern = {
|
|
8951
|
+
value: new RegExp(v.pattern),
|
|
8952
|
+
message: (_b = v.message) != null ? _b : `Invalid ${label}`
|
|
8953
|
+
};
|
|
8954
|
+
break;
|
|
8955
|
+
case "range":
|
|
8956
|
+
if (v.min !== void 0) {
|
|
8957
|
+
rules.min = { value: v.min, message: (_c = v.message) != null ? _c : `Minimum value is ${v.min}` };
|
|
8958
|
+
}
|
|
8959
|
+
if (v.max !== void 0) {
|
|
8960
|
+
rules.max = { value: v.max, message: (_d = v.message) != null ? _d : `Maximum value is ${v.max}` };
|
|
8961
|
+
}
|
|
8962
|
+
break;
|
|
8963
|
+
case "length":
|
|
8964
|
+
if (v.min !== void 0) {
|
|
8965
|
+
rules.minLength = { value: v.min, message: (_e = v.message) != null ? _e : `Minimum length is ${v.min}` };
|
|
8966
|
+
}
|
|
8967
|
+
if (v.max !== void 0) {
|
|
8968
|
+
rules.maxLength = { value: v.max, message: (_f = v.message) != null ? _f : `Maximum length is ${v.max}` };
|
|
8969
|
+
}
|
|
8970
|
+
break;
|
|
8971
|
+
}
|
|
8972
|
+
}
|
|
8973
|
+
}
|
|
8974
|
+
return rules;
|
|
8975
|
+
}
|
|
8976
|
+
|
|
8977
|
+
function PdcFieldNote({
|
|
8978
|
+
enabled,
|
|
8979
|
+
description,
|
|
8980
|
+
configUrl
|
|
8981
|
+
}) {
|
|
8982
|
+
const styles = ui.useStyles2(getStyles$f);
|
|
8983
|
+
return /* @__PURE__ */ React__default.default.createElement("div", { className: styles.wrapper }, /* @__PURE__ */ React__default.default.createElement("div", { className: styles.note }, /* @__PURE__ */ React__default.default.createElement(ui.Icon, { name: "shield", size: "xs" }), /* @__PURE__ */ React__default.default.createElement("span", null, "Private data source connect: ", /* @__PURE__ */ React__default.default.createElement("strong", null, enabled ? "Enabled" : "Disabled")), description && /* @__PURE__ */ React__default.default.createElement(ui.Tooltip, { content: description }, /* @__PURE__ */ React__default.default.createElement(ui.Icon, { name: "info-circle", size: "xs" }))), /* @__PURE__ */ React__default.default.createElement(ui.LinkButton, { variant: "secondary", size: "sm", icon: "external-link-alt", href: configUrl }, "Configure in settings"));
|
|
8984
|
+
}
|
|
8985
|
+
const getStyles$f = (theme) => ({
|
|
8986
|
+
wrapper: css.css({
|
|
8987
|
+
display: "flex",
|
|
8988
|
+
alignItems: "center",
|
|
8989
|
+
justifyContent: "space-between",
|
|
8990
|
+
gap: theme.spacing(1),
|
|
8991
|
+
padding: `${theme.spacing(0.5)} ${theme.spacing(0.75)}`,
|
|
8992
|
+
fontSize: theme.typography.bodySmall.fontSize,
|
|
8993
|
+
color: theme.colors.text.secondary,
|
|
8994
|
+
backgroundColor: theme.colors.background.secondary,
|
|
8995
|
+
borderRadius: theme.shape.radius.default,
|
|
8996
|
+
border: `1px solid ${theme.colors.border.weak}`
|
|
8997
|
+
}),
|
|
8998
|
+
note: css.css({
|
|
8999
|
+
display: "inline-flex",
|
|
9000
|
+
alignItems: "center",
|
|
9001
|
+
gap: theme.spacing(0.5)
|
|
9002
|
+
})
|
|
9003
|
+
});
|
|
9004
|
+
|
|
9005
|
+
function SecureFieldInput({
|
|
9006
|
+
formField,
|
|
9007
|
+
placeholder,
|
|
9008
|
+
disabled,
|
|
9009
|
+
label
|
|
9010
|
+
}) {
|
|
9011
|
+
var _a;
|
|
9012
|
+
const isConfigured = formField.value === SECURE_FIELD_CONFIGURED;
|
|
9013
|
+
const [revealed, setRevealed] = React.useState(false);
|
|
9014
|
+
const styles = ui.useStyles2(getSecureFieldStyles);
|
|
9015
|
+
if (isConfigured) {
|
|
9016
|
+
return /* @__PURE__ */ React__default.default.createElement("div", { className: styles.configuredRow }, /* @__PURE__ */ React__default.default.createElement("span", { className: styles.configuredBadge }, /* @__PURE__ */ React__default.default.createElement(ui.Icon, { name: "lock", size: "xs" }), label, " configured"), !disabled && /* @__PURE__ */ React__default.default.createElement(ui.Button, { variant: "secondary", fill: "text", size: "sm", onClick: () => formField.onChange(""), type: "button" }, "Reset"));
|
|
9017
|
+
}
|
|
9018
|
+
return /* @__PURE__ */ React__default.default.createElement(
|
|
9019
|
+
ui.Input,
|
|
9020
|
+
{
|
|
9021
|
+
...formField,
|
|
9022
|
+
value: String((_a = formField.value) != null ? _a : ""),
|
|
9023
|
+
type: revealed ? "text" : "password",
|
|
9024
|
+
placeholder,
|
|
9025
|
+
disabled,
|
|
9026
|
+
suffix: /* @__PURE__ */ React__default.default.createElement(
|
|
9027
|
+
ui.Button,
|
|
9028
|
+
{
|
|
9029
|
+
variant: "secondary",
|
|
9030
|
+
fill: "text",
|
|
9031
|
+
size: "sm",
|
|
9032
|
+
icon: revealed ? "eye-slash" : "eye",
|
|
9033
|
+
"aria-label": revealed ? "Hide" : "Reveal",
|
|
9034
|
+
onClick: () => setRevealed((r) => !r),
|
|
9035
|
+
type: "button"
|
|
9036
|
+
}
|
|
9037
|
+
)
|
|
9038
|
+
}
|
|
9039
|
+
);
|
|
9040
|
+
}
|
|
9041
|
+
const getSecureFieldStyles = (theme) => ({
|
|
9042
|
+
configuredRow: css.css({
|
|
9043
|
+
display: "flex",
|
|
9044
|
+
alignItems: "center",
|
|
9045
|
+
gap: theme.spacing(1)
|
|
9046
|
+
}),
|
|
9047
|
+
configuredBadge: css.css({
|
|
9048
|
+
display: "inline-flex",
|
|
9049
|
+
alignItems: "center",
|
|
9050
|
+
gap: theme.spacing(0.5),
|
|
9051
|
+
padding: `${theme.spacing(0.25)} ${theme.spacing(0.75)}`,
|
|
9052
|
+
borderRadius: theme.shape.radius.pill,
|
|
9053
|
+
backgroundColor: theme.colors.success.transparent,
|
|
9054
|
+
color: theme.colors.success.text,
|
|
9055
|
+
fontSize: theme.typography.bodySmall.fontSize
|
|
9056
|
+
})
|
|
9057
|
+
});
|
|
9058
|
+
|
|
9059
|
+
function StringArrayInput({
|
|
9060
|
+
value,
|
|
9061
|
+
onChange,
|
|
9062
|
+
placeholder,
|
|
9063
|
+
disabled
|
|
9064
|
+
}) {
|
|
9065
|
+
const [draft, setDraft] = React.useState("");
|
|
9066
|
+
const styles = ui.useStyles2(getStyles$e);
|
|
9067
|
+
const addTag = () => {
|
|
9068
|
+
const trimmed = draft.trim();
|
|
9069
|
+
if (trimmed && !value.includes(trimmed)) {
|
|
9070
|
+
onChange([...value, trimmed]);
|
|
9071
|
+
}
|
|
9072
|
+
setDraft("");
|
|
9073
|
+
};
|
|
9074
|
+
const removeTag = (tag) => {
|
|
9075
|
+
onChange(value.filter((v) => v !== tag));
|
|
9076
|
+
};
|
|
9077
|
+
return /* @__PURE__ */ React__default.default.createElement("div", { className: styles.container }, value.length > 0 && /* @__PURE__ */ React__default.default.createElement("div", { className: styles.tags }, value.map((tag) => /* @__PURE__ */ React__default.default.createElement("span", { key: tag, className: styles.tag }, tag, !disabled && /* @__PURE__ */ React__default.default.createElement(
|
|
9078
|
+
"button",
|
|
9079
|
+
{
|
|
9080
|
+
type: "button",
|
|
9081
|
+
className: styles.tagRemove,
|
|
9082
|
+
onClick: () => removeTag(tag),
|
|
9083
|
+
"aria-label": `Remove ${tag}`
|
|
9084
|
+
},
|
|
9085
|
+
/* @__PURE__ */ React__default.default.createElement(ui.Icon, { name: "times", size: "xs" })
|
|
9086
|
+
)))), /* @__PURE__ */ React__default.default.createElement(
|
|
9087
|
+
ui.Input,
|
|
9088
|
+
{
|
|
9089
|
+
value: draft,
|
|
9090
|
+
onChange: (e) => setDraft(e.currentTarget.value),
|
|
9091
|
+
onKeyDown: (e) => {
|
|
9092
|
+
if (e.key === "Enter") {
|
|
9093
|
+
e.preventDefault();
|
|
9094
|
+
addTag();
|
|
9095
|
+
}
|
|
9096
|
+
},
|
|
9097
|
+
onBlur: addTag,
|
|
9098
|
+
placeholder,
|
|
9099
|
+
disabled
|
|
9100
|
+
}
|
|
9101
|
+
));
|
|
9102
|
+
}
|
|
9103
|
+
const getStyles$e = (theme) => ({
|
|
9104
|
+
container: css.css({
|
|
9105
|
+
display: "flex",
|
|
9106
|
+
flexDirection: "column",
|
|
9107
|
+
gap: theme.spacing(0.5)
|
|
9108
|
+
}),
|
|
9109
|
+
tags: css.css({
|
|
9110
|
+
display: "flex",
|
|
9111
|
+
flexWrap: "wrap",
|
|
9112
|
+
gap: theme.spacing(0.5)
|
|
9113
|
+
}),
|
|
9114
|
+
tag: css.css({
|
|
9115
|
+
display: "inline-flex",
|
|
9116
|
+
alignItems: "center",
|
|
9117
|
+
gap: theme.spacing(0.25),
|
|
9118
|
+
padding: `${theme.spacing(0.25)} ${theme.spacing(0.75)}`,
|
|
9119
|
+
borderRadius: theme.shape.radius.pill,
|
|
9120
|
+
backgroundColor: theme.colors.background.secondary,
|
|
9121
|
+
border: `1px solid ${theme.colors.border.weak}`,
|
|
9122
|
+
fontSize: theme.typography.bodySmall.fontSize,
|
|
9123
|
+
color: theme.colors.text.primary
|
|
9124
|
+
}),
|
|
9125
|
+
tagRemove: css.css({
|
|
9126
|
+
display: "inline-flex",
|
|
9127
|
+
alignItems: "center",
|
|
9128
|
+
padding: 0,
|
|
9129
|
+
border: "none",
|
|
9130
|
+
backgroundColor: "transparent",
|
|
9131
|
+
cursor: "pointer",
|
|
9132
|
+
color: theme.colors.text.secondary,
|
|
9133
|
+
"&:hover": { color: theme.colors.text.primary }
|
|
9134
|
+
})
|
|
9135
|
+
});
|
|
9136
|
+
|
|
9137
|
+
function IndexedPairRow({
|
|
9138
|
+
item,
|
|
9139
|
+
index,
|
|
9140
|
+
disabled,
|
|
9141
|
+
onUpdate,
|
|
9142
|
+
onRemove,
|
|
9143
|
+
hideControls
|
|
9144
|
+
}) {
|
|
9145
|
+
const styles = ui.useStyles2(getStyles$d);
|
|
9146
|
+
const secureStyles = ui.useStyles2(getSecureFieldStyles);
|
|
9147
|
+
const isConfigured = item.value === SECURE_FIELD_CONFIGURED;
|
|
9148
|
+
const [editing, setEditing] = React.useState(false);
|
|
9149
|
+
const [revealed, setRevealed] = React.useState(false);
|
|
9150
|
+
return /* @__PURE__ */ React__default.default.createElement(ui.Stack, { direction: "row", gap: 1 }, /* @__PURE__ */ React__default.default.createElement("div", { className: styles.inputCell }, /* @__PURE__ */ React__default.default.createElement(
|
|
9151
|
+
ui.Input,
|
|
9152
|
+
{
|
|
9153
|
+
value: item.name,
|
|
9154
|
+
placeholder: "Header name",
|
|
9155
|
+
disabled: disabled || hideControls,
|
|
9156
|
+
onChange: (e) => onUpdate(index, "name", e.currentTarget.value)
|
|
9157
|
+
}
|
|
9158
|
+
)), /* @__PURE__ */ React__default.default.createElement("div", { className: styles.inputCell }, isConfigured && !editing ? /* @__PURE__ */ React__default.default.createElement(ui.Stack, { direction: "row", gap: 1, alignItems: "center" }, /* @__PURE__ */ React__default.default.createElement("span", { className: secureStyles.configuredBadge }, /* @__PURE__ */ React__default.default.createElement(ui.Icon, { name: "lock", size: "xs" }), "Configured"), !disabled && /* @__PURE__ */ React__default.default.createElement(
|
|
9159
|
+
ui.Button,
|
|
9160
|
+
{
|
|
9161
|
+
variant: "secondary",
|
|
9162
|
+
fill: "text",
|
|
9163
|
+
size: "sm",
|
|
9164
|
+
onClick: () => {
|
|
9165
|
+
setEditing(true);
|
|
9166
|
+
onUpdate(index, "value", "");
|
|
9167
|
+
},
|
|
9168
|
+
type: "button"
|
|
9169
|
+
},
|
|
9170
|
+
"Reset"
|
|
9171
|
+
)) : /* @__PURE__ */ React__default.default.createElement(
|
|
9172
|
+
ui.Input,
|
|
9173
|
+
{
|
|
9174
|
+
value: item.value === SECURE_FIELD_CONFIGURED ? "" : item.value,
|
|
9175
|
+
placeholder: "Header value",
|
|
9176
|
+
disabled,
|
|
9177
|
+
type: revealed ? "text" : "password",
|
|
9178
|
+
onChange: (e) => onUpdate(index, "value", e.currentTarget.value),
|
|
9179
|
+
suffix: /* @__PURE__ */ React__default.default.createElement(
|
|
9180
|
+
ui.Button,
|
|
9181
|
+
{
|
|
9182
|
+
variant: "secondary",
|
|
9183
|
+
fill: "text",
|
|
9184
|
+
size: "sm",
|
|
9185
|
+
icon: revealed ? "eye-slash" : "eye",
|
|
9186
|
+
"aria-label": revealed ? "Hide" : "Reveal",
|
|
9187
|
+
onClick: () => setRevealed((r) => !r),
|
|
9188
|
+
type: "button"
|
|
9189
|
+
}
|
|
9190
|
+
)
|
|
9191
|
+
}
|
|
9192
|
+
)), !hideControls && /* @__PURE__ */ React__default.default.createElement(ui.Tooltip, { content: "Remove header" }, /* @__PURE__ */ React__default.default.createElement(
|
|
9193
|
+
ui.Button,
|
|
9194
|
+
{
|
|
9195
|
+
variant: "secondary",
|
|
9196
|
+
fill: "text",
|
|
9197
|
+
size: "sm",
|
|
9198
|
+
icon: "trash-alt",
|
|
9199
|
+
"aria-label": "Remove header",
|
|
9200
|
+
disabled,
|
|
9201
|
+
onClick: () => onRemove(index),
|
|
9202
|
+
type: "button"
|
|
9203
|
+
}
|
|
9204
|
+
)));
|
|
9205
|
+
}
|
|
9206
|
+
function IndexedPairEditor({
|
|
9207
|
+
value,
|
|
9208
|
+
onChange,
|
|
9209
|
+
maxItems = 10,
|
|
9210
|
+
disabled,
|
|
9211
|
+
hideControls
|
|
9212
|
+
}) {
|
|
9213
|
+
const styles = ui.useStyles2(getStyles$d);
|
|
9214
|
+
const items = Array.isArray(value) ? value : [];
|
|
9215
|
+
const addItem = () => {
|
|
9216
|
+
if (items.length >= maxItems) {
|
|
9217
|
+
return;
|
|
9218
|
+
}
|
|
9219
|
+
onChange([...items, { index: 0, name: "", value: "" }]);
|
|
9220
|
+
};
|
|
9221
|
+
const removeItem = (index) => {
|
|
9222
|
+
onChange(items.filter((_, i) => i !== index));
|
|
9223
|
+
};
|
|
9224
|
+
const updateItem = (index, key, val) => {
|
|
9225
|
+
const updated = items.map((item, i) => i === index ? { ...item, [key]: val } : item);
|
|
9226
|
+
onChange(updated);
|
|
9227
|
+
};
|
|
9228
|
+
return /* @__PURE__ */ React__default.default.createElement(ui.Stack, { direction: "column", gap: 0.5 }, items.map((item, i) => /* @__PURE__ */ React__default.default.createElement(
|
|
9229
|
+
IndexedPairRow,
|
|
9230
|
+
{
|
|
9231
|
+
key: item.index || `new-${i}`,
|
|
9232
|
+
item,
|
|
9233
|
+
index: i,
|
|
9234
|
+
disabled,
|
|
9235
|
+
onUpdate: updateItem,
|
|
9236
|
+
onRemove: removeItem,
|
|
9237
|
+
hideControls
|
|
9238
|
+
}
|
|
9239
|
+
)), !hideControls && items.length < maxItems && /* @__PURE__ */ React__default.default.createElement("div", null, /* @__PURE__ */ React__default.default.createElement(ui.Button, { variant: "secondary", size: "sm", icon: "plus", disabled, onClick: addItem, type: "button" }, "Add header")), !hideControls && items.length >= maxItems && /* @__PURE__ */ React__default.default.createElement("span", { className: styles.limitNote }, "Maximum ", maxItems, " headers reached"));
|
|
9240
|
+
}
|
|
9241
|
+
const getStyles$d = (theme) => ({
|
|
9242
|
+
inputCell: css.css({
|
|
9243
|
+
flex: "1 1 0",
|
|
9244
|
+
minWidth: 0,
|
|
9245
|
+
overflow: "hidden"
|
|
9246
|
+
}),
|
|
9247
|
+
limitNote: css.css({
|
|
9248
|
+
fontSize: theme.typography.bodySmall.fontSize,
|
|
9249
|
+
color: theme.colors.text.secondary
|
|
9250
|
+
})
|
|
9251
|
+
});
|
|
9252
|
+
|
|
9253
|
+
function ComplexFieldNote({ count, label }) {
|
|
9254
|
+
const styles = ui.useStyles2(getStyles$c);
|
|
9255
|
+
return /* @__PURE__ */ React__default.default.createElement("div", { className: styles.note }, /* @__PURE__ */ React__default.default.createElement(ui.Icon, { name: "info-circle", size: "xs" }), /* @__PURE__ */ React__default.default.createElement("span", null, count > 0 ? `${count} ${label.toLowerCase()} configured.` : `No ${label.toLowerCase()} configured.`, " Configure in Grafana UI."));
|
|
9256
|
+
}
|
|
9257
|
+
const getStyles$c = (theme) => ({
|
|
9258
|
+
note: css.css({
|
|
9259
|
+
display: "inline-flex",
|
|
9260
|
+
alignItems: "center",
|
|
9261
|
+
gap: theme.spacing(0.5),
|
|
9262
|
+
padding: `${theme.spacing(0.5)} ${theme.spacing(0.75)}`,
|
|
9263
|
+
fontSize: theme.typography.bodySmall.fontSize,
|
|
9264
|
+
color: theme.colors.text.secondary,
|
|
9265
|
+
backgroundColor: theme.colors.background.secondary,
|
|
9266
|
+
borderRadius: theme.shape.radius.default,
|
|
9267
|
+
border: `1px solid ${theme.colors.border.weak}`
|
|
9268
|
+
})
|
|
9269
|
+
});
|
|
9270
|
+
|
|
9271
|
+
function renderFieldInput(field, formField, disabled) {
|
|
9272
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r;
|
|
9273
|
+
const value = formField.value;
|
|
9274
|
+
const placeholder = (_a = field.ui) == null ? void 0 : _a.placeholder;
|
|
9275
|
+
const label = (_b = field.label) != null ? _b : field.key;
|
|
9276
|
+
if (field.target === "secureJsonData" || field.semanticType === "password" || field.semanticType === "token") {
|
|
9277
|
+
return /* @__PURE__ */ React__default.default.createElement(SecureFieldInput, { formField, placeholder: placeholder != null ? placeholder : label, disabled, label });
|
|
9278
|
+
}
|
|
9279
|
+
if (field.valueType === "boolean") {
|
|
9280
|
+
return /* @__PURE__ */ React__default.default.createElement(ui.Switch, { value: !!value, onChange: (e) => formField.onChange(e.currentTarget.checked), disabled });
|
|
9281
|
+
}
|
|
9282
|
+
if (field.valueType === "number") {
|
|
9283
|
+
return /* @__PURE__ */ React__default.default.createElement(
|
|
9284
|
+
ui.Input,
|
|
9285
|
+
{
|
|
9286
|
+
...formField,
|
|
9287
|
+
value: value !== void 0 && value !== null ? Number(value) : "",
|
|
9288
|
+
type: "number",
|
|
9289
|
+
placeholder,
|
|
9290
|
+
disabled,
|
|
9291
|
+
onChange: (e) => {
|
|
9292
|
+
const n = e.currentTarget.valueAsNumber;
|
|
9293
|
+
formField.onChange(Number.isNaN(n) ? void 0 : n);
|
|
9294
|
+
}
|
|
9295
|
+
}
|
|
9296
|
+
);
|
|
9297
|
+
}
|
|
9298
|
+
if (((_c = field.ui) == null ? void 0 : _c.component) === "radio") {
|
|
9299
|
+
const options = ((_e = (_d = field.ui) == null ? void 0 : _d.options) != null ? _e : []).map((opt) => ({
|
|
9300
|
+
label: opt.label,
|
|
9301
|
+
value: String(opt.value),
|
|
9302
|
+
description: opt.description
|
|
9303
|
+
}));
|
|
9304
|
+
return /* @__PURE__ */ React__default.default.createElement("div", { style: { display: "flex" } }, /* @__PURE__ */ React__default.default.createElement(
|
|
9305
|
+
ui.RadioButtonGroup,
|
|
9306
|
+
{
|
|
9307
|
+
options,
|
|
9308
|
+
value: String(value != null ? value : ""),
|
|
9309
|
+
onChange: (v) => formField.onChange(v),
|
|
9310
|
+
disabled
|
|
9311
|
+
}
|
|
9312
|
+
));
|
|
9313
|
+
}
|
|
9314
|
+
if (((_f = field.ui) == null ? void 0 : _f.component) === "select") {
|
|
9315
|
+
const options = ((_h = (_g = field.ui) == null ? void 0 : _g.options) != null ? _h : []).map((opt) => ({
|
|
9316
|
+
label: opt.label,
|
|
9317
|
+
value: String(opt.value),
|
|
9318
|
+
description: opt.description
|
|
9319
|
+
}));
|
|
9320
|
+
return /* @__PURE__ */ React__default.default.createElement(
|
|
9321
|
+
ui.Select,
|
|
9322
|
+
{
|
|
9323
|
+
options,
|
|
9324
|
+
value: options.find((o) => o.value === String(value != null ? value : "")),
|
|
9325
|
+
onChange: (v) => formField.onChange(v == null ? void 0 : v.value),
|
|
9326
|
+
disabled
|
|
9327
|
+
}
|
|
9328
|
+
);
|
|
9329
|
+
}
|
|
9330
|
+
if (field.semanticType === "url") {
|
|
9331
|
+
return /* @__PURE__ */ React__default.default.createElement(ui.Input, { ...formField, value: String(value != null ? value : ""), type: "url", placeholder, disabled });
|
|
9332
|
+
}
|
|
9333
|
+
if (((_i = field.ui) == null ? void 0 : _i.component) === "textarea") {
|
|
9334
|
+
return /* @__PURE__ */ React__default.default.createElement(
|
|
9335
|
+
ui.TextArea,
|
|
9336
|
+
{
|
|
9337
|
+
...formField,
|
|
9338
|
+
value: String(value != null ? value : ""),
|
|
9339
|
+
placeholder,
|
|
9340
|
+
disabled,
|
|
9341
|
+
rows: (_k = (_j = field.ui) == null ? void 0 : _j.rows) != null ? _k : 3
|
|
9342
|
+
}
|
|
9343
|
+
);
|
|
9344
|
+
}
|
|
9345
|
+
if (field.valueType === "array" && ((_l = field.item) == null ? void 0 : _l.valueType) === "string") {
|
|
9346
|
+
return /* @__PURE__ */ React__default.default.createElement(
|
|
9347
|
+
StringArrayInput,
|
|
9348
|
+
{
|
|
9349
|
+
value: Array.isArray(value) ? value : [],
|
|
9350
|
+
onChange: formField.onChange,
|
|
9351
|
+
placeholder: placeholder != null ? placeholder : `Add ${label.toLowerCase()}\u2026`,
|
|
9352
|
+
disabled
|
|
9353
|
+
}
|
|
9354
|
+
);
|
|
9355
|
+
}
|
|
9356
|
+
if (((_m = field.storage) == null ? void 0 : _m.type) === "indexedPair") {
|
|
9357
|
+
const items = Array.isArray(value) ? value : [];
|
|
9358
|
+
const maxItems = (_p = (_o = (_n = field.validations) == null ? void 0 : _n.find((v) => v.type === "itemCount")) == null ? void 0 : _o.max) != null ? _p : 10;
|
|
9359
|
+
return /* @__PURE__ */ React__default.default.createElement(IndexedPairEditor, { value: items, onChange: formField.onChange, maxItems, disabled });
|
|
9360
|
+
}
|
|
9361
|
+
if (field.valueType === "object" || field.valueType === "map" || field.valueType === "array" && (((_q = field.item) == null ? void 0 : _q.valueType) === "object" || ((_r = field.item) == null ? void 0 : _r.valueType) === "map")) {
|
|
9362
|
+
const count = Array.isArray(value) ? value.length : 0;
|
|
9363
|
+
return /* @__PURE__ */ React__default.default.createElement(ComplexFieldNote, { count, label });
|
|
9364
|
+
}
|
|
9365
|
+
return /* @__PURE__ */ React__default.default.createElement(ui.Input, { ...formField, value: String(value != null ? value : ""), placeholder, disabled });
|
|
9366
|
+
}
|
|
9367
|
+
|
|
9368
|
+
const getWizardStyles = (theme) => ({
|
|
9369
|
+
container: css.css({
|
|
9370
|
+
position: "relative",
|
|
9371
|
+
display: "flex",
|
|
9372
|
+
flexDirection: "column",
|
|
9373
|
+
gap: theme.spacing(1),
|
|
9374
|
+
padding: theme.spacing(1.5),
|
|
9375
|
+
backgroundColor: theme.colors.background.secondary,
|
|
9376
|
+
borderRadius: theme.shape.radius.default,
|
|
9377
|
+
border: `1px solid ${theme.colors.border.weak}`,
|
|
9378
|
+
overflow: "hidden"
|
|
9379
|
+
}),
|
|
9380
|
+
overlay: css.css({
|
|
9381
|
+
position: "absolute",
|
|
9382
|
+
inset: 0,
|
|
9383
|
+
display: "flex",
|
|
9384
|
+
alignItems: "center",
|
|
9385
|
+
justifyContent: "center",
|
|
9386
|
+
gap: theme.spacing(1),
|
|
9387
|
+
background: theme.colors.background.secondary,
|
|
9388
|
+
borderRadius: theme.shape.radius.default,
|
|
9389
|
+
zIndex: 1,
|
|
9390
|
+
fontSize: theme.typography.bodySmall.fontSize,
|
|
9391
|
+
color: theme.colors.text.primary,
|
|
9392
|
+
opacity: 0.95
|
|
9393
|
+
}),
|
|
9394
|
+
readOnlyBanner: css.css({
|
|
9395
|
+
display: "inline-flex",
|
|
9396
|
+
alignItems: "center",
|
|
9397
|
+
gap: theme.spacing(0.5),
|
|
9398
|
+
padding: `${theme.spacing(0.25)} ${theme.spacing(0.75)}`,
|
|
9399
|
+
fontSize: theme.typography.bodySmall.fontSize,
|
|
9400
|
+
color: theme.colors.text.secondary,
|
|
9401
|
+
backgroundColor: theme.colors.background.secondary,
|
|
9402
|
+
borderRadius: theme.shape.radius.default,
|
|
9403
|
+
border: `1px solid ${theme.colors.border.weak}`
|
|
9404
|
+
}),
|
|
9405
|
+
navBar: css.css({
|
|
9406
|
+
display: "flex",
|
|
9407
|
+
alignItems: "center",
|
|
9408
|
+
justifyContent: "space-between"
|
|
9409
|
+
}),
|
|
9410
|
+
navTitle: css.css({
|
|
9411
|
+
display: "inline-flex",
|
|
9412
|
+
alignItems: "center",
|
|
9413
|
+
gap: theme.spacing(0.5),
|
|
9414
|
+
fontSize: theme.typography.body.fontSize,
|
|
9415
|
+
fontWeight: theme.typography.fontWeightBold,
|
|
9416
|
+
color: theme.colors.text.primary
|
|
9417
|
+
}),
|
|
9418
|
+
stepCount: css.css({
|
|
9419
|
+
fontSize: "11px",
|
|
9420
|
+
fontWeight: "normal",
|
|
9421
|
+
color: theme.colors.text.secondary
|
|
9422
|
+
}),
|
|
9423
|
+
navActions: css.css({
|
|
9424
|
+
display: "flex",
|
|
9425
|
+
alignItems: "center",
|
|
9426
|
+
gap: theme.spacing(0.25)
|
|
9427
|
+
}),
|
|
9428
|
+
form: css.css({
|
|
9429
|
+
display: "flex",
|
|
9430
|
+
flexDirection: "column",
|
|
9431
|
+
gap: theme.spacing(0.75)
|
|
9432
|
+
}),
|
|
9433
|
+
buttons: css.css({
|
|
9434
|
+
display: "flex",
|
|
9435
|
+
gap: theme.spacing(1),
|
|
9436
|
+
paddingTop: theme.spacing(0.25)
|
|
9437
|
+
}),
|
|
9438
|
+
fieldRow: css.css({
|
|
9439
|
+
display: "grid",
|
|
9440
|
+
gridTemplateColumns: "minmax(80px, 1fr) minmax(0, 2fr)",
|
|
9441
|
+
gap: theme.spacing(0.75),
|
|
9442
|
+
alignItems: "start"
|
|
9443
|
+
}),
|
|
9444
|
+
fieldRowCenter: css.css({
|
|
9445
|
+
display: "grid",
|
|
9446
|
+
gridTemplateColumns: "minmax(80px, 1fr) minmax(0, 2fr)",
|
|
9447
|
+
gap: theme.spacing(0.75),
|
|
9448
|
+
alignItems: "center",
|
|
9449
|
+
padding: `${theme.spacing(0.5)} 0`
|
|
9450
|
+
}),
|
|
9451
|
+
fieldLabelRow: css.css({
|
|
9452
|
+
display: "flex",
|
|
9453
|
+
alignItems: "center",
|
|
9454
|
+
gap: theme.spacing(0.5),
|
|
9455
|
+
paddingTop: theme.spacing(0.5)
|
|
9456
|
+
}),
|
|
9457
|
+
fieldLabelRowCompact: css.css({
|
|
9458
|
+
display: "flex",
|
|
9459
|
+
alignItems: "center",
|
|
9460
|
+
gap: theme.spacing(0.5)
|
|
9461
|
+
}),
|
|
9462
|
+
fieldLabel: css.css({
|
|
9463
|
+
fontSize: theme.typography.bodySmall.fontSize,
|
|
9464
|
+
fontWeight: theme.typography.fontWeightMedium,
|
|
9465
|
+
color: theme.colors.text.primary
|
|
9466
|
+
}),
|
|
9467
|
+
fieldRequired: css.css({
|
|
9468
|
+
color: theme.colors.error.text,
|
|
9469
|
+
marginLeft: 2
|
|
9470
|
+
}),
|
|
9471
|
+
fieldInfoIcon: css.css({
|
|
9472
|
+
color: theme.colors.text.disabled,
|
|
9473
|
+
cursor: "help",
|
|
9474
|
+
flexShrink: 0
|
|
9475
|
+
}),
|
|
9476
|
+
fieldInputCol: css.css({
|
|
9477
|
+
display: "flex",
|
|
9478
|
+
flexDirection: "column",
|
|
9479
|
+
gap: theme.spacing(0.25),
|
|
9480
|
+
minWidth: 0
|
|
9481
|
+
}),
|
|
9482
|
+
fieldError: css.css({
|
|
9483
|
+
fontSize: "11px",
|
|
9484
|
+
color: theme.colors.error.text
|
|
9485
|
+
})
|
|
9486
|
+
});
|
|
9487
|
+
|
|
9488
|
+
function SchemaField({ field, control, errors, disabled, dsUid, watchedValues, fieldById }) {
|
|
9489
|
+
const styles = ui.useStyles2(getWizardStyles);
|
|
9490
|
+
const activeOverride = resolveActiveOverride(field, watchedValues, fieldById);
|
|
9491
|
+
const fk = formKey(field);
|
|
9492
|
+
if (field.key === "pdcInjected" && field.target === "jsonData") {
|
|
9493
|
+
return /* @__PURE__ */ React__default.default.createElement(
|
|
9494
|
+
reactHookForm.Controller,
|
|
9495
|
+
{
|
|
9496
|
+
name: fk,
|
|
9497
|
+
control,
|
|
9498
|
+
render: ({ field: formField }) => /* @__PURE__ */ React__default.default.createElement(
|
|
9499
|
+
PdcFieldNote,
|
|
9500
|
+
{
|
|
9501
|
+
enabled: !!formField.value,
|
|
9502
|
+
description: field.description,
|
|
9503
|
+
configUrl: `/connections/datasources/edit/${dsUid}`
|
|
9504
|
+
}
|
|
9505
|
+
)
|
|
9506
|
+
}
|
|
9507
|
+
);
|
|
9508
|
+
}
|
|
9509
|
+
const required = isFieldRequired(field, watchedValues, fieldById);
|
|
9510
|
+
const validationRules = buildValidationRules(field, required);
|
|
9511
|
+
return /* @__PURE__ */ React__default.default.createElement(
|
|
9512
|
+
reactHookForm.Controller,
|
|
9513
|
+
{
|
|
9514
|
+
name: fk,
|
|
9515
|
+
control,
|
|
9516
|
+
rules: validationRules,
|
|
9517
|
+
render: ({ field: formField }) => {
|
|
9518
|
+
var _a, _b, _c, _d, _e;
|
|
9519
|
+
const errorMessage = (_a = errors[fk]) == null ? void 0 : _a.message;
|
|
9520
|
+
const label = (_b = field.label) != null ? _b : field.key;
|
|
9521
|
+
const description = (_c = activeOverride == null ? void 0 : activeOverride.description) != null ? _c : field.description;
|
|
9522
|
+
const effectiveField = activeOverride ? {
|
|
9523
|
+
...field,
|
|
9524
|
+
ui: {
|
|
9525
|
+
...field.ui,
|
|
9526
|
+
placeholder: (_e = activeOverride.placeholder) != null ? _e : (_d = field.ui) == null ? void 0 : _d.placeholder
|
|
9527
|
+
}
|
|
9528
|
+
} : field;
|
|
9529
|
+
const isReadOnly = !!(activeOverride == null ? void 0 : activeOverride.readOnly);
|
|
9530
|
+
const isBool = field.valueType === "boolean";
|
|
9531
|
+
return /* @__PURE__ */ React__default.default.createElement("div", { className: isBool ? styles.fieldRowCenter : styles.fieldRow }, /* @__PURE__ */ React__default.default.createElement("div", { className: isBool ? styles.fieldLabelRowCompact : styles.fieldLabelRow }, /* @__PURE__ */ React__default.default.createElement("span", { className: styles.fieldLabel }, label, required && /* @__PURE__ */ React__default.default.createElement("span", { className: styles.fieldRequired }, "*")), description && /* @__PURE__ */ React__default.default.createElement(ui.Tooltip, { content: description }, /* @__PURE__ */ React__default.default.createElement(ui.Icon, { name: "info-circle", size: "xs", className: styles.fieldInfoIcon }))), /* @__PURE__ */ React__default.default.createElement("div", { className: styles.fieldInputCol }, renderFieldInput(effectiveField, formField, disabled || isReadOnly), errorMessage && /* @__PURE__ */ React__default.default.createElement("span", { className: styles.fieldError }, errorMessage)));
|
|
9532
|
+
}
|
|
9533
|
+
}
|
|
9534
|
+
);
|
|
9535
|
+
}
|
|
9536
|
+
|
|
9537
|
+
function AuthorizationHeaderField({
|
|
9538
|
+
headersFieldKey,
|
|
9539
|
+
control,
|
|
9540
|
+
disabled,
|
|
9541
|
+
watchedValues
|
|
9542
|
+
}) {
|
|
9543
|
+
const styles = ui.useStyles2(getWizardStyles);
|
|
9544
|
+
const items = React.useMemo(
|
|
9545
|
+
() => Array.isArray(watchedValues[headersFieldKey]) ? watchedValues[headersFieldKey] : [],
|
|
9546
|
+
[watchedValues, headersFieldKey]
|
|
9547
|
+
);
|
|
9548
|
+
const authEntries = React.useMemo(() => {
|
|
9549
|
+
const entries = [];
|
|
9550
|
+
for (let i = 0; i < items.length; i++) {
|
|
9551
|
+
if (items[i].name.toLowerCase() === "authorization") {
|
|
9552
|
+
entries.push({ item: items[i], originalIdx: i });
|
|
9553
|
+
}
|
|
9554
|
+
}
|
|
9555
|
+
return entries;
|
|
9556
|
+
}, [items]);
|
|
9557
|
+
if (authEntries.length === 0) {
|
|
9558
|
+
return null;
|
|
9559
|
+
}
|
|
9560
|
+
const authItems = authEntries.map((e) => e.item);
|
|
9561
|
+
return /* @__PURE__ */ React__default.default.createElement(
|
|
9562
|
+
reactHookForm.Controller,
|
|
9563
|
+
{
|
|
9564
|
+
name: headersFieldKey,
|
|
9565
|
+
control,
|
|
9566
|
+
render: ({ field: formField }) => {
|
|
9567
|
+
const handleChange = (updatedAuthItems) => {
|
|
9568
|
+
const updated = [...items];
|
|
9569
|
+
for (let i = 0; i < authEntries.length; i++) {
|
|
9570
|
+
if (i < updatedAuthItems.length) {
|
|
9571
|
+
updated[authEntries[i].originalIdx] = updatedAuthItems[i];
|
|
9572
|
+
}
|
|
9573
|
+
}
|
|
9574
|
+
formField.onChange(updated);
|
|
9575
|
+
};
|
|
9576
|
+
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 })));
|
|
9577
|
+
}
|
|
9578
|
+
}
|
|
9579
|
+
);
|
|
9580
|
+
}
|
|
9581
|
+
|
|
9582
|
+
const getTabStyles = (theme) => ({
|
|
9583
|
+
root: css.css({
|
|
9584
|
+
display: "flex",
|
|
9585
|
+
gap: theme.spacing(3),
|
|
9586
|
+
position: "relative",
|
|
9587
|
+
background: theme.colors.background.canvas,
|
|
9588
|
+
padding: theme.spacing(2)
|
|
9589
|
+
}),
|
|
9590
|
+
// Sidebar
|
|
9591
|
+
sidebar: css.css({
|
|
9592
|
+
width: 250,
|
|
9593
|
+
flexShrink: 0,
|
|
9594
|
+
position: "sticky",
|
|
9595
|
+
top: theme.spacing(2),
|
|
9596
|
+
alignSelf: "flex-start",
|
|
9597
|
+
[theme.breakpoints.down("sm")]: { display: "none" }
|
|
9598
|
+
}),
|
|
9599
|
+
sidebarTitle: css.css({
|
|
9600
|
+
fontSize: theme.typography.body.fontSize,
|
|
9601
|
+
fontWeight: theme.typography.fontWeightMedium,
|
|
9602
|
+
color: theme.colors.text.primary,
|
|
9603
|
+
padding: `${theme.spacing(1)} 0`,
|
|
9604
|
+
marginBottom: theme.spacing(1)
|
|
9605
|
+
}),
|
|
9606
|
+
navList: css.css({
|
|
9607
|
+
listStyle: "none",
|
|
9608
|
+
margin: 0,
|
|
9609
|
+
padding: 0,
|
|
9610
|
+
position: "relative"
|
|
9611
|
+
}),
|
|
9612
|
+
navItem: css.css({
|
|
9613
|
+
display: "flex",
|
|
9614
|
+
alignItems: "flex-start",
|
|
9615
|
+
gap: theme.spacing(1.5),
|
|
9616
|
+
padding: `${theme.spacing(1)} 0`,
|
|
9617
|
+
cursor: "pointer",
|
|
9618
|
+
position: "relative"
|
|
9619
|
+
}),
|
|
9620
|
+
navItemActive: css.css({}),
|
|
9621
|
+
// Dot container: positions the dot and the connector line
|
|
9622
|
+
navDotWrap: css.css({
|
|
9623
|
+
position: "relative",
|
|
9624
|
+
display: "flex",
|
|
9625
|
+
alignItems: "center",
|
|
9626
|
+
justifyContent: "center",
|
|
9627
|
+
width: 12,
|
|
9628
|
+
flexShrink: 0,
|
|
9629
|
+
alignSelf: "flex-start",
|
|
9630
|
+
paddingTop: 4
|
|
9631
|
+
}),
|
|
9632
|
+
navDot: css.css({
|
|
9633
|
+
width: 10,
|
|
9634
|
+
height: 10,
|
|
9635
|
+
borderRadius: "50%",
|
|
9636
|
+
border: `2px solid ${theme.colors.text.disabled}`,
|
|
9637
|
+
background: theme.colors.background.canvas,
|
|
9638
|
+
position: "relative",
|
|
9639
|
+
zIndex: 1
|
|
9640
|
+
}),
|
|
9641
|
+
navDotOptional: css.css({
|
|
9642
|
+
borderStyle: "dashed"
|
|
9643
|
+
}),
|
|
9644
|
+
navDotActive: css.css({
|
|
9645
|
+
background: theme.colors.primary.main,
|
|
9646
|
+
borderColor: theme.colors.primary.main,
|
|
9647
|
+
borderStyle: "solid"
|
|
9648
|
+
}),
|
|
9649
|
+
navDotValidated: css.css({
|
|
9650
|
+
background: theme.colors.success.main,
|
|
9651
|
+
borderColor: theme.colors.success.main,
|
|
9652
|
+
borderStyle: "solid"
|
|
9653
|
+
}),
|
|
9654
|
+
navDotError: css.css({
|
|
9655
|
+
background: theme.colors.error.main,
|
|
9656
|
+
borderColor: theme.colors.error.main,
|
|
9657
|
+
borderStyle: "solid"
|
|
9658
|
+
}),
|
|
9659
|
+
// Connector line running from dot center downward to next item
|
|
9660
|
+
navConnector: css.css({
|
|
9661
|
+
position: "absolute",
|
|
9662
|
+
left: 5,
|
|
9663
|
+
top: 16,
|
|
9664
|
+
bottom: -16,
|
|
9665
|
+
width: 2,
|
|
9666
|
+
background: theme.colors.border.medium,
|
|
9667
|
+
zIndex: 0
|
|
9668
|
+
}),
|
|
9669
|
+
navConnectorDashed: css.css({
|
|
9670
|
+
background: "none",
|
|
9671
|
+
borderLeft: `2px dashed ${theme.colors.border.weak}`,
|
|
9672
|
+
width: 0
|
|
9673
|
+
}),
|
|
9674
|
+
navLabel: css.css({
|
|
9675
|
+
fontSize: theme.typography.body.fontSize,
|
|
9676
|
+
color: "rgba(204, 204, 220, 0.65)",
|
|
9677
|
+
lineHeight: 1.4
|
|
9678
|
+
}),
|
|
9679
|
+
navLabelActive: css.css({
|
|
9680
|
+
fontWeight: theme.typography.fontWeightMedium,
|
|
9681
|
+
color: theme.colors.text.primary
|
|
9682
|
+
}),
|
|
9683
|
+
// Main content
|
|
9684
|
+
main: css.css({
|
|
9685
|
+
flex: 1,
|
|
9686
|
+
minWidth: 0,
|
|
9687
|
+
width: 0,
|
|
9688
|
+
// forces flex child to respect flex-grow and fill remaining space
|
|
9689
|
+
display: "flex",
|
|
9690
|
+
flexDirection: "column",
|
|
9691
|
+
gap: theme.spacing(2)
|
|
9692
|
+
}),
|
|
9693
|
+
form: css.css({
|
|
9694
|
+
display: "flex",
|
|
9695
|
+
flexDirection: "column",
|
|
9696
|
+
gap: theme.spacing(2)
|
|
9697
|
+
}),
|
|
9698
|
+
requiredNotice: css.css({
|
|
9699
|
+
fontSize: theme.typography.bodySmall.fontSize,
|
|
9700
|
+
color: theme.colors.text.secondary,
|
|
9701
|
+
marginBottom: theme.spacing(0.5)
|
|
9702
|
+
}),
|
|
9703
|
+
// Section wrapper — card container around CollapsableSection
|
|
9704
|
+
section: css.css({
|
|
9705
|
+
border: `1px solid ${theme.colors.border.weak}`,
|
|
9706
|
+
borderRadius: theme.shape.radius.default,
|
|
9707
|
+
background: theme.colors.background.secondary,
|
|
9708
|
+
overflow: "hidden"
|
|
9709
|
+
}),
|
|
9710
|
+
// Override Collapse component styling
|
|
9711
|
+
collapseHeader: css.css({
|
|
9712
|
+
borderRadius: theme.shape.radius.default,
|
|
9713
|
+
background: "none",
|
|
9714
|
+
border: "none",
|
|
9715
|
+
marginBottom: 0,
|
|
9716
|
+
// Collapse header button: make label fill remaining space
|
|
9717
|
+
"& > button": {
|
|
9718
|
+
padding: `${theme.spacing(1.5)} ${theme.spacing(2)}`,
|
|
9719
|
+
width: "100%",
|
|
9720
|
+
justifyContent: "flex-start"
|
|
9721
|
+
},
|
|
9722
|
+
"& > button > div": {
|
|
9723
|
+
flex: 1,
|
|
9724
|
+
fontSize: theme.typography.h4.fontSize,
|
|
9725
|
+
fontWeight: theme.typography.fontWeightMedium,
|
|
9726
|
+
textAlign: "left"
|
|
9727
|
+
}
|
|
9728
|
+
}),
|
|
9729
|
+
sectionLabel: css.css({
|
|
9730
|
+
display: "flex",
|
|
9731
|
+
alignItems: "center",
|
|
9732
|
+
flex: 1
|
|
9733
|
+
}),
|
|
9734
|
+
sectionLabelText: css.css({
|
|
9735
|
+
flex: 1
|
|
9736
|
+
}),
|
|
9737
|
+
sectionHeader: css.css({
|
|
9738
|
+
display: "flex",
|
|
9739
|
+
alignItems: "center",
|
|
9740
|
+
gap: theme.spacing(1),
|
|
9741
|
+
padding: `${theme.spacing(1.5)} ${theme.spacing(2)}`,
|
|
9742
|
+
cursor: "pointer",
|
|
9743
|
+
userSelect: "none"
|
|
9744
|
+
}),
|
|
9745
|
+
sectionChevron: css.css({
|
|
9746
|
+
transition: "transform 0.2s ease"
|
|
9747
|
+
}),
|
|
9748
|
+
sectionChevronOpen: css.css({
|
|
9749
|
+
transform: "rotate(90deg)"
|
|
9750
|
+
}),
|
|
9751
|
+
sectionTitle: css.css({
|
|
9752
|
+
fontSize: theme.typography.h4.fontSize,
|
|
9753
|
+
fontWeight: theme.typography.fontWeightMedium,
|
|
9754
|
+
flex: 1,
|
|
9755
|
+
textAlign: "left"
|
|
9756
|
+
}),
|
|
9757
|
+
sectionBadge: css.css({
|
|
9758
|
+
fontSize: "11px",
|
|
9759
|
+
fontWeight: "normal",
|
|
9760
|
+
color: theme.colors.text.disabled,
|
|
9761
|
+
border: `1px solid ${theme.colors.border.weak}`,
|
|
9762
|
+
borderRadius: theme.shape.radius.pill,
|
|
9763
|
+
padding: `1px ${theme.spacing(0.75)}`,
|
|
9764
|
+
whiteSpace: "nowrap"
|
|
9765
|
+
}),
|
|
9766
|
+
sectionDescription: css.css({
|
|
9767
|
+
fontSize: theme.typography.bodySmall.fontSize,
|
|
9768
|
+
color: theme.colors.text.secondary,
|
|
9769
|
+
marginBottom: theme.spacing(1.5)
|
|
9770
|
+
}),
|
|
9771
|
+
sectionBody: css.css({
|
|
9772
|
+
padding: `0 ${theme.spacing(2)} ${theme.spacing(2)}`,
|
|
9773
|
+
display: "flex",
|
|
9774
|
+
flexDirection: "column",
|
|
9775
|
+
gap: theme.spacing(0.75)
|
|
9776
|
+
}),
|
|
9777
|
+
// Form bottom
|
|
9778
|
+
formButtons: css.css({
|
|
9779
|
+
display: "flex",
|
|
9780
|
+
gap: theme.spacing(1),
|
|
9781
|
+
paddingTop: theme.spacing(0.5)
|
|
9782
|
+
}),
|
|
9783
|
+
// Loading / error states
|
|
9784
|
+
loadingContainer: css.css({
|
|
9785
|
+
display: "flex",
|
|
9786
|
+
alignItems: "center",
|
|
9787
|
+
gap: theme.spacing(1),
|
|
9788
|
+
padding: theme.spacing(3),
|
|
9789
|
+
color: theme.colors.text.secondary
|
|
9790
|
+
}),
|
|
9791
|
+
overlay: css.css({
|
|
9792
|
+
position: "absolute",
|
|
9793
|
+
inset: 0,
|
|
9794
|
+
display: "flex",
|
|
9795
|
+
alignItems: "center",
|
|
9796
|
+
justifyContent: "center",
|
|
9797
|
+
gap: theme.spacing(1),
|
|
9798
|
+
background: theme.colors.background.secondary,
|
|
9799
|
+
borderRadius: theme.shape.radius.default,
|
|
9800
|
+
zIndex: 1,
|
|
9801
|
+
fontSize: theme.typography.bodySmall.fontSize,
|
|
9802
|
+
color: theme.colors.text.primary,
|
|
9803
|
+
opacity: 0.95
|
|
9804
|
+
}),
|
|
9805
|
+
readOnlyBanner: css.css({
|
|
9806
|
+
display: "inline-flex",
|
|
9807
|
+
alignItems: "center",
|
|
9808
|
+
gap: theme.spacing(0.5),
|
|
9809
|
+
padding: `${theme.spacing(0.25)} ${theme.spacing(0.75)}`,
|
|
9810
|
+
fontSize: theme.typography.bodySmall.fontSize,
|
|
9811
|
+
color: theme.colors.text.secondary,
|
|
9812
|
+
backgroundColor: theme.colors.background.secondary,
|
|
9813
|
+
borderRadius: theme.shape.radius.default,
|
|
9814
|
+
border: `1px solid ${theme.colors.border.weak}`,
|
|
9815
|
+
marginBottom: theme.spacing(1)
|
|
9816
|
+
})
|
|
9817
|
+
});
|
|
9818
|
+
|
|
9819
|
+
function SidebarNav({ groups, activeIndex, sectionStates, onSelect }) {
|
|
9820
|
+
const styles = ui.useStyles2(getTabStyles);
|
|
9821
|
+
const visibleGroups = groups.filter((g) => g.group.id !== "_required");
|
|
9822
|
+
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) => {
|
|
9823
|
+
var _a, _b;
|
|
9824
|
+
const origIndex = groups.indexOf(g);
|
|
9825
|
+
const state = (_a = sectionStates[origIndex]) != null ? _a : "draft";
|
|
9826
|
+
const isActive = origIndex === activeIndex;
|
|
9827
|
+
const isOptional = g.group.optional === true;
|
|
9828
|
+
const isLast = vi === visibleGroups.length - 1;
|
|
9829
|
+
const nextIsOptional = !isLast && ((_b = visibleGroups[vi + 1]) == null ? void 0 : _b.group.optional) === true;
|
|
9830
|
+
return /* @__PURE__ */ React__default.default.createElement("li", { key: g.group.id }, /* @__PURE__ */ React__default.default.createElement(
|
|
9831
|
+
"div",
|
|
9832
|
+
{
|
|
9833
|
+
className: css.cx(styles.navItem, isActive && styles.navItemActive),
|
|
9834
|
+
onClick: () => onSelect(origIndex),
|
|
9835
|
+
role: "button",
|
|
9836
|
+
tabIndex: 0,
|
|
9837
|
+
onKeyDown: (e) => {
|
|
9838
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
9839
|
+
e.preventDefault();
|
|
9840
|
+
onSelect(origIndex);
|
|
9841
|
+
}
|
|
9842
|
+
}
|
|
9843
|
+
},
|
|
9844
|
+
/* @__PURE__ */ React__default.default.createElement("div", { className: styles.navDotWrap }, /* @__PURE__ */ React__default.default.createElement(
|
|
9845
|
+
"span",
|
|
9846
|
+
{
|
|
9847
|
+
className: css.cx(
|
|
9848
|
+
styles.navDot,
|
|
9849
|
+
isOptional && styles.navDotOptional,
|
|
9850
|
+
isActive && styles.navDotActive,
|
|
9851
|
+
state === "validated" && !isActive && styles.navDotValidated,
|
|
9852
|
+
state === "error" && !isActive && styles.navDotError
|
|
9853
|
+
)
|
|
9854
|
+
}
|
|
9855
|
+
), !isLast && /* @__PURE__ */ React__default.default.createElement(
|
|
9856
|
+
"div",
|
|
9857
|
+
{
|
|
9858
|
+
className: css.cx(styles.navConnector, (isOptional || nextIsOptional) && styles.navConnectorDashed)
|
|
9859
|
+
}
|
|
9860
|
+
)),
|
|
9861
|
+
/* @__PURE__ */ React__default.default.createElement("span", { className: css.cx(styles.navLabel, isActive && styles.navLabelActive) }, g.group.title)
|
|
9862
|
+
));
|
|
9863
|
+
})));
|
|
9864
|
+
}
|
|
9865
|
+
|
|
9866
|
+
function TabLayout({ form, schema, dsUid, dsName, onRetest, healthError, renderActions }) {
|
|
9867
|
+
const styles = ui.useStyles2(getTabStyles);
|
|
9868
|
+
const sectionRefs = React.useRef(/* @__PURE__ */ new Map());
|
|
9869
|
+
const {
|
|
9870
|
+
resolvedGroups,
|
|
9871
|
+
fieldById,
|
|
9872
|
+
httpHeadersField,
|
|
9873
|
+
control,
|
|
9874
|
+
handleSubmit,
|
|
9875
|
+
errors,
|
|
9876
|
+
watchedValues,
|
|
9877
|
+
initializing,
|
|
9878
|
+
fetchError,
|
|
9879
|
+
submitting,
|
|
9880
|
+
submitError,
|
|
9881
|
+
readOnly,
|
|
9882
|
+
isFieldVisible,
|
|
9883
|
+
isGroupValid,
|
|
9884
|
+
groupHasData,
|
|
9885
|
+
onSubmit
|
|
9886
|
+
} = form;
|
|
9887
|
+
const displayGroups = React.useMemo(() => resolvedGroups.filter((g) => g.group.id !== "_required"), [resolvedGroups]);
|
|
9888
|
+
const [expandedSections, setExpandedSections] = React.useState(() => {
|
|
9889
|
+
const expanded = /* @__PURE__ */ new Set();
|
|
9890
|
+
for (let i = 0; i < displayGroups.length; i++) {
|
|
9891
|
+
if (!displayGroups[i].group.optional) {
|
|
9892
|
+
expanded.add(i);
|
|
9893
|
+
}
|
|
9894
|
+
}
|
|
9895
|
+
return expanded;
|
|
9896
|
+
});
|
|
9897
|
+
const hasExpandedForData = React.useRef(false);
|
|
9898
|
+
React.useMemo(() => {
|
|
9899
|
+
if (initializing || hasExpandedForData.current) {
|
|
9900
|
+
return;
|
|
9901
|
+
}
|
|
9902
|
+
hasExpandedForData.current = true;
|
|
9903
|
+
setExpandedSections((prev) => {
|
|
9904
|
+
const next = new Set(prev);
|
|
9905
|
+
for (let i = 0; i < displayGroups.length; i++) {
|
|
9906
|
+
if (groupHasData(displayGroups[i])) {
|
|
9907
|
+
next.add(i);
|
|
9908
|
+
}
|
|
9909
|
+
}
|
|
9910
|
+
return next;
|
|
9911
|
+
});
|
|
9912
|
+
}, [initializing, displayGroups, groupHasData]);
|
|
9913
|
+
const [activeSection, setActiveSection] = React.useState(0);
|
|
9914
|
+
const toggleSection = React.useCallback((index) => {
|
|
9915
|
+
setExpandedSections((prev) => {
|
|
9916
|
+
const next = new Set(prev);
|
|
9917
|
+
if (next.has(index)) {
|
|
9918
|
+
next.delete(index);
|
|
9919
|
+
} else {
|
|
9920
|
+
next.add(index);
|
|
9921
|
+
}
|
|
9922
|
+
return next;
|
|
9923
|
+
});
|
|
9924
|
+
}, []);
|
|
9925
|
+
const scrollToSection = React.useCallback(
|
|
9926
|
+
(index) => {
|
|
9927
|
+
setActiveSection(index);
|
|
9928
|
+
if (!expandedSections.has(index)) {
|
|
9929
|
+
setExpandedSections((prev) => new Set(prev).add(index));
|
|
9930
|
+
}
|
|
9931
|
+
const el = sectionRefs.current.get(index);
|
|
9932
|
+
if (el) {
|
|
9933
|
+
el.scrollIntoView({ behavior: "smooth", block: "start" });
|
|
9934
|
+
}
|
|
9935
|
+
},
|
|
9936
|
+
[expandedSections]
|
|
9937
|
+
);
|
|
9938
|
+
const sectionStates = React.useMemo(() => {
|
|
9939
|
+
return displayGroups.map((g, i) => {
|
|
9940
|
+
if (i === activeSection) {
|
|
9941
|
+
return "active";
|
|
9942
|
+
}
|
|
9943
|
+
if (!isGroupValid(g)) {
|
|
9944
|
+
return "error";
|
|
9945
|
+
}
|
|
9946
|
+
if (groupHasData(g)) {
|
|
9947
|
+
return "validated";
|
|
9948
|
+
}
|
|
9949
|
+
return "draft";
|
|
9950
|
+
});
|
|
9951
|
+
}, [displayGroups, activeSection, isGroupValid, groupHasData]);
|
|
9952
|
+
if (initializing) {
|
|
9953
|
+
return /* @__PURE__ */ React__default.default.createElement("div", { className: styles.loadingContainer }, /* @__PURE__ */ React__default.default.createElement(ui.Spinner, { size: "sm", inline: true }), " Loading configuration\u2026");
|
|
9954
|
+
}
|
|
9955
|
+
if (fetchError) {
|
|
9956
|
+
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(
|
|
9957
|
+
ui.LinkButton,
|
|
9958
|
+
{
|
|
9959
|
+
variant: "secondary",
|
|
9960
|
+
size: "sm",
|
|
9961
|
+
icon: "external-link-alt",
|
|
9962
|
+
href: `/connections/datasources/edit/${dsUid}`
|
|
9963
|
+
},
|
|
9964
|
+
"Open datasource settings"
|
|
9965
|
+
)));
|
|
9966
|
+
}
|
|
9967
|
+
const allDisabled = submitting || readOnly;
|
|
9968
|
+
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(
|
|
9969
|
+
SidebarNav,
|
|
9970
|
+
{
|
|
9971
|
+
groups: displayGroups,
|
|
9972
|
+
activeIndex: activeSection,
|
|
9973
|
+
sectionStates,
|
|
9974
|
+
onSelect: scrollToSection
|
|
9975
|
+
}
|
|
9976
|
+
), /* @__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) => {
|
|
9977
|
+
const visibleFields = g.fields.filter(isFieldVisible);
|
|
9978
|
+
if (visibleFields.length === 0 && !httpHeadersField) {
|
|
9979
|
+
return null;
|
|
9980
|
+
}
|
|
9981
|
+
const showHeaders = httpHeadersField && (g.group.id === "auth" || g.group.id === "url-and-auth" || g.group.id === "_required" || g.group.fieldRefs.includes("httpHeaders"));
|
|
9982
|
+
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"));
|
|
9983
|
+
return /* @__PURE__ */ React__default.default.createElement(
|
|
9984
|
+
"div",
|
|
9985
|
+
{
|
|
9986
|
+
key: g.group.id,
|
|
9987
|
+
ref: (el) => {
|
|
9988
|
+
if (el) {
|
|
9989
|
+
sectionRefs.current.set(i, el);
|
|
9990
|
+
}
|
|
9991
|
+
},
|
|
9992
|
+
className: styles.section
|
|
9993
|
+
},
|
|
9994
|
+
/* @__PURE__ */ React__default.default.createElement(
|
|
9995
|
+
ui.Collapse,
|
|
9996
|
+
{
|
|
9997
|
+
label: sectionLabel,
|
|
9998
|
+
isOpen: expandedSections.has(i),
|
|
9999
|
+
collapsible: true,
|
|
10000
|
+
onToggle: () => {
|
|
10001
|
+
toggleSection(i);
|
|
10002
|
+
setActiveSection(i);
|
|
10003
|
+
},
|
|
10004
|
+
className: styles.collapseHeader
|
|
10005
|
+
},
|
|
10006
|
+
/* @__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(
|
|
10007
|
+
SchemaField,
|
|
10008
|
+
{
|
|
10009
|
+
key: formKey(field),
|
|
10010
|
+
field,
|
|
10011
|
+
control,
|
|
10012
|
+
errors,
|
|
10013
|
+
disabled: allDisabled,
|
|
10014
|
+
dsUid,
|
|
10015
|
+
watchedValues,
|
|
10016
|
+
fieldById
|
|
10017
|
+
}
|
|
10018
|
+
)), showHeaders && /* @__PURE__ */ React__default.default.createElement(
|
|
10019
|
+
AuthorizationHeaderField,
|
|
10020
|
+
{
|
|
10021
|
+
headersFieldKey: formKey(httpHeadersField),
|
|
10022
|
+
control,
|
|
10023
|
+
disabled: allDisabled,
|
|
10024
|
+
watchedValues
|
|
10025
|
+
}
|
|
10026
|
+
))
|
|
10027
|
+
)
|
|
10028
|
+
);
|
|
10029
|
+
}), 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 }))))));
|
|
10030
|
+
}
|
|
10031
|
+
|
|
10032
|
+
function useDatasourceConfigForm({ schema, dsUid, onSuccess, onSaving }) {
|
|
10033
|
+
const [submitting, setSubmitting] = React.useState(false);
|
|
10034
|
+
const [submitError, setSubmitError] = React.useState(null);
|
|
10035
|
+
const [initializing, setInitializing] = React.useState(true);
|
|
10036
|
+
const [fetchError, setFetchError] = React.useState(null);
|
|
10037
|
+
const [detectedReadOnly, setDetectedReadOnly] = React.useState(false);
|
|
10038
|
+
const readOnly = detectedReadOnly;
|
|
10039
|
+
const resolvedGroups = React.useMemo(() => {
|
|
10040
|
+
const groups = resolveGroups(schema);
|
|
10041
|
+
const requiredGroup = resolveRequiredFieldsGroup(schema);
|
|
10042
|
+
if (!requiredGroup) {
|
|
10043
|
+
return groups;
|
|
10044
|
+
}
|
|
10045
|
+
return [requiredGroup, ...groups];
|
|
10046
|
+
}, [schema]);
|
|
10047
|
+
const fieldById = React.useMemo(() => {
|
|
10048
|
+
const m = /* @__PURE__ */ new Map();
|
|
10049
|
+
for (const f of schema.fields) {
|
|
10050
|
+
m.set(f.id, f);
|
|
10051
|
+
}
|
|
10052
|
+
return m;
|
|
10053
|
+
}, [schema.fields]);
|
|
10054
|
+
const httpHeadersField = React.useMemo(
|
|
10055
|
+
() => {
|
|
10056
|
+
var _a;
|
|
10057
|
+
return (_a = schema.fields.find((f) => {
|
|
10058
|
+
var _a2;
|
|
10059
|
+
return f.key === "httpHeaders" && ((_a2 = f.storage) == null ? void 0 : _a2.type) === "indexedPair";
|
|
10060
|
+
})) != null ? _a : null;
|
|
10061
|
+
},
|
|
10062
|
+
[schema.fields]
|
|
10063
|
+
);
|
|
10064
|
+
const allStorageFields = React.useMemo(
|
|
10065
|
+
() => schema.fields.filter((f) => f.kind !== "virtual" && !f.isItemField && f.target),
|
|
10066
|
+
[schema.fields]
|
|
10067
|
+
);
|
|
10068
|
+
const {
|
|
10069
|
+
control,
|
|
10070
|
+
handleSubmit,
|
|
10071
|
+
watch,
|
|
10072
|
+
reset,
|
|
10073
|
+
trigger,
|
|
10074
|
+
setValue,
|
|
10075
|
+
formState: { errors }
|
|
10076
|
+
} = reactHookForm.useForm({ mode: "onChange" });
|
|
10077
|
+
const fieldsWithEffects = React.useMemo(() => {
|
|
10078
|
+
const result = [];
|
|
10079
|
+
for (const field of schema.fields) {
|
|
10080
|
+
if (!field.effects || field.effects.length === 0) {
|
|
10081
|
+
continue;
|
|
10082
|
+
}
|
|
10083
|
+
const mapped = field.effects.map((eff) => ({
|
|
10084
|
+
when: eff.when,
|
|
10085
|
+
targets: Object.entries(eff.set).map(([targetId, val]) => {
|
|
10086
|
+
const targetField = fieldById.get(targetId);
|
|
10087
|
+
return { key: targetField ? formKey(targetField) : targetId, value: val };
|
|
10088
|
+
})
|
|
10089
|
+
}));
|
|
10090
|
+
result.push({ sourceKey: formKey(field), effects: mapped });
|
|
10091
|
+
}
|
|
10092
|
+
return result;
|
|
10093
|
+
}, [schema.fields, fieldById]);
|
|
10094
|
+
React.useEffect(() => {
|
|
10095
|
+
let cancelled = false;
|
|
10096
|
+
fetchExistingValues(dsUid, allStorageFields).then((result) => {
|
|
10097
|
+
if (cancelled) {
|
|
10098
|
+
return;
|
|
10099
|
+
}
|
|
10100
|
+
if (result.error) {
|
|
10101
|
+
setFetchError(result.error);
|
|
10102
|
+
setInitializing(false);
|
|
10103
|
+
return;
|
|
10104
|
+
}
|
|
10105
|
+
if (result.readOnly) {
|
|
10106
|
+
setDetectedReadOnly(true);
|
|
10107
|
+
}
|
|
10108
|
+
const defaults = {};
|
|
10109
|
+
for (const field of allStorageFields) {
|
|
10110
|
+
if (field.defaultValue !== void 0) {
|
|
10111
|
+
defaults[formKey(field)] = field.defaultValue;
|
|
10112
|
+
}
|
|
10113
|
+
}
|
|
10114
|
+
const merged = { ...defaults, ...result.values };
|
|
10115
|
+
const virtualValues = computeVirtualFieldValues(schema, merged);
|
|
10116
|
+
reset({ ...merged, ...virtualValues });
|
|
10117
|
+
setInitializing(false);
|
|
10118
|
+
});
|
|
10119
|
+
return () => {
|
|
10120
|
+
cancelled = true;
|
|
10121
|
+
};
|
|
10122
|
+
}, [dsUid, allStorageFields, schema, reset]);
|
|
10123
|
+
const watchedValues = watch();
|
|
10124
|
+
const prevEffectValuesRef = React.useRef({});
|
|
10125
|
+
React.useEffect(() => {
|
|
10126
|
+
if (initializing) {
|
|
10127
|
+
return;
|
|
10128
|
+
}
|
|
10129
|
+
for (const { sourceKey, effects } of fieldsWithEffects) {
|
|
10130
|
+
const currentVal = watchedValues[sourceKey];
|
|
10131
|
+
const prevVal = prevEffectValuesRef.current[sourceKey];
|
|
10132
|
+
if (currentVal === prevVal) {
|
|
10133
|
+
continue;
|
|
10134
|
+
}
|
|
10135
|
+
prevEffectValuesRef.current[sourceKey] = currentVal;
|
|
10136
|
+
for (const eff of effects) {
|
|
10137
|
+
if (evaluateEffectCondition(eff.when, currentVal)) {
|
|
10138
|
+
for (const { key, value } of eff.targets) {
|
|
10139
|
+
setValue(key, value);
|
|
10140
|
+
}
|
|
10141
|
+
break;
|
|
10142
|
+
}
|
|
10143
|
+
}
|
|
10144
|
+
}
|
|
10145
|
+
}, [watchedValues, fieldsWithEffects, initializing, setValue]);
|
|
10146
|
+
const fieldsWithOverrideDefaults = React.useMemo(() => {
|
|
10147
|
+
const result = [];
|
|
10148
|
+
for (const field of schema.fields) {
|
|
10149
|
+
if (!field.overrides || field.overrides.length === 0) {
|
|
10150
|
+
continue;
|
|
10151
|
+
}
|
|
10152
|
+
const ovs = field.overrides.filter((ov) => ov.defaultValue !== void 0).map((ov) => {
|
|
10153
|
+
const parsed = parseDependsOn(ov.when);
|
|
10154
|
+
if (!parsed) {
|
|
10155
|
+
return null;
|
|
10156
|
+
}
|
|
10157
|
+
const depField = fieldById.get(parsed.field);
|
|
10158
|
+
return {
|
|
10159
|
+
depKey: depField ? formKey(depField) : parsed.field,
|
|
10160
|
+
depValue: parsed.value,
|
|
10161
|
+
defaultValue: ov.defaultValue
|
|
10162
|
+
};
|
|
10163
|
+
}).filter(Boolean);
|
|
10164
|
+
if (ovs.length > 0) {
|
|
10165
|
+
result.push({ targetKey: formKey(field), fieldDefault: field.defaultValue, overrides: ovs });
|
|
10166
|
+
}
|
|
10167
|
+
}
|
|
10168
|
+
return result;
|
|
10169
|
+
}, [schema.fields, fieldById]);
|
|
10170
|
+
const prevOverrideDepRef = React.useRef({});
|
|
10171
|
+
React.useEffect(() => {
|
|
10172
|
+
var _a;
|
|
10173
|
+
if (initializing) {
|
|
10174
|
+
return;
|
|
10175
|
+
}
|
|
10176
|
+
for (const { targetKey, fieldDefault, overrides } of fieldsWithOverrideDefaults) {
|
|
10177
|
+
for (const ov of overrides) {
|
|
10178
|
+
const currentDepVal = String((_a = watchedValues[ov.depKey]) != null ? _a : "");
|
|
10179
|
+
const trackKey = `${targetKey}::${ov.depKey}`;
|
|
10180
|
+
const prevDepVal = prevOverrideDepRef.current[trackKey];
|
|
10181
|
+
if (currentDepVal === prevDepVal) {
|
|
10182
|
+
continue;
|
|
10183
|
+
}
|
|
10184
|
+
prevOverrideDepRef.current[trackKey] = currentDepVal;
|
|
10185
|
+
if (currentDepVal === ov.depValue) {
|
|
10186
|
+
setValue(targetKey, ov.defaultValue);
|
|
10187
|
+
} else if (prevDepVal === ov.depValue && fieldDefault !== void 0) {
|
|
10188
|
+
setValue(targetKey, fieldDefault);
|
|
10189
|
+
}
|
|
10190
|
+
}
|
|
10191
|
+
}
|
|
10192
|
+
}, [watchedValues, fieldsWithOverrideDefaults, initializing, setValue]);
|
|
10193
|
+
const isFieldVisible = React.useCallback(
|
|
10194
|
+
(field) => {
|
|
10195
|
+
var _a, _b;
|
|
10196
|
+
if (field.kind === "virtual" && !field.ui) {
|
|
10197
|
+
return false;
|
|
10198
|
+
}
|
|
10199
|
+
if ((_a = field.tags) == null ? void 0 : _a.some((t) => t.startsWith("managed-by:"))) {
|
|
10200
|
+
return false;
|
|
10201
|
+
}
|
|
10202
|
+
if (!field.dependsOn) {
|
|
10203
|
+
return true;
|
|
10204
|
+
}
|
|
10205
|
+
const parsed = parseDependsOn(field.dependsOn);
|
|
10206
|
+
if (!parsed) {
|
|
10207
|
+
return true;
|
|
10208
|
+
}
|
|
10209
|
+
const depField = fieldById.get(parsed.field);
|
|
10210
|
+
const depKey = depField ? formKey(depField) : parsed.field;
|
|
10211
|
+
return String((_b = watchedValues[depKey]) != null ? _b : "") === parsed.value;
|
|
10212
|
+
},
|
|
10213
|
+
[watchedValues, fieldById]
|
|
10214
|
+
);
|
|
10215
|
+
const onSubmit = React.useCallback(
|
|
10216
|
+
async (data) => {
|
|
10217
|
+
setSubmitting(true);
|
|
10218
|
+
setSubmitError(null);
|
|
10219
|
+
onSaving == null ? void 0 : onSaving(true);
|
|
10220
|
+
const minDelay = new Promise((r) => setTimeout(r, 2e3));
|
|
10221
|
+
try {
|
|
10222
|
+
await submitDatasourceConfig(dsUid, data, allStorageFields, isFieldVisible);
|
|
10223
|
+
const [refreshed] = await Promise.all([fetchExistingValues(dsUid, allStorageFields), minDelay]);
|
|
10224
|
+
const defaults = {};
|
|
10225
|
+
for (const field of allStorageFields) {
|
|
10226
|
+
if (field.defaultValue !== void 0) {
|
|
10227
|
+
defaults[formKey(field)] = field.defaultValue;
|
|
10228
|
+
}
|
|
10229
|
+
}
|
|
10230
|
+
const merged = { ...defaults, ...refreshed.values };
|
|
10231
|
+
const virtualValues = computeVirtualFieldValues(schema, merged);
|
|
10232
|
+
reset({ ...merged, ...virtualValues });
|
|
10233
|
+
onSuccess("UPDATED", "Configuration saved.");
|
|
10234
|
+
} catch (err) {
|
|
10235
|
+
await minDelay;
|
|
10236
|
+
setSubmitError(err instanceof Error ? err.message : "Failed to update datasource");
|
|
10237
|
+
} finally {
|
|
10238
|
+
setSubmitting(false);
|
|
10239
|
+
onSaving == null ? void 0 : onSaving(false);
|
|
10240
|
+
}
|
|
10241
|
+
},
|
|
10242
|
+
[dsUid, allStorageFields, isFieldVisible, schema, reset, onSuccess, onSaving]
|
|
10243
|
+
);
|
|
10244
|
+
const isGroupValid = React.useCallback(
|
|
10245
|
+
(group) => {
|
|
10246
|
+
for (const field of group.fields) {
|
|
10247
|
+
if (!isFieldVisible(field)) {
|
|
10248
|
+
continue;
|
|
10249
|
+
}
|
|
10250
|
+
if (errors[formKey(field)]) {
|
|
10251
|
+
return false;
|
|
10252
|
+
}
|
|
10253
|
+
if (isFieldRequired(field, watchedValues, fieldById)) {
|
|
10254
|
+
const val = watchedValues[formKey(field)];
|
|
10255
|
+
if (val === SECURE_FIELD_CONFIGURED) {
|
|
10256
|
+
continue;
|
|
10257
|
+
}
|
|
10258
|
+
if (val === void 0 || val === null || val === "") {
|
|
10259
|
+
return false;
|
|
10260
|
+
}
|
|
10261
|
+
}
|
|
10262
|
+
}
|
|
10263
|
+
return true;
|
|
10264
|
+
},
|
|
10265
|
+
[errors, watchedValues, fieldById, isFieldVisible]
|
|
10266
|
+
);
|
|
10267
|
+
const groupHasData = React.useCallback(
|
|
10268
|
+
(group) => {
|
|
10269
|
+
for (const field of group.fields) {
|
|
10270
|
+
const val = watchedValues[formKey(field)];
|
|
10271
|
+
if (val === void 0 || val === null || val === "" || val === false) {
|
|
10272
|
+
continue;
|
|
10273
|
+
}
|
|
10274
|
+
if (val === field.defaultValue) {
|
|
10275
|
+
continue;
|
|
10276
|
+
}
|
|
10277
|
+
return true;
|
|
10278
|
+
}
|
|
10279
|
+
return false;
|
|
10280
|
+
},
|
|
10281
|
+
[watchedValues]
|
|
10282
|
+
);
|
|
10283
|
+
return {
|
|
10284
|
+
// Schema
|
|
10285
|
+
resolvedGroups,
|
|
10286
|
+
fieldById,
|
|
10287
|
+
httpHeadersField,
|
|
10288
|
+
// Form
|
|
10289
|
+
control,
|
|
10290
|
+
handleSubmit,
|
|
10291
|
+
trigger,
|
|
10292
|
+
errors,
|
|
10293
|
+
watchedValues,
|
|
10294
|
+
// State
|
|
10295
|
+
initializing,
|
|
10296
|
+
fetchError,
|
|
10297
|
+
submitting,
|
|
10298
|
+
submitError,
|
|
10299
|
+
readOnly,
|
|
10300
|
+
// Callbacks
|
|
10301
|
+
isFieldVisible,
|
|
10302
|
+
isGroupValid,
|
|
10303
|
+
groupHasData,
|
|
10304
|
+
onSubmit
|
|
10305
|
+
};
|
|
10306
|
+
}
|
|
10307
|
+
|
|
10308
|
+
function DatasourceConfigWizard(props) {
|
|
10309
|
+
const { schema, dsUid, dsName, onSuccess, onSaving, onRetest, healthError, renderActions, mode = "tab" } = props;
|
|
10310
|
+
const form = useDatasourceConfigForm({ schema, dsUid, onSuccess, onSaving });
|
|
10311
|
+
if (mode === "tab") {
|
|
10312
|
+
return /* @__PURE__ */ React__default.default.createElement(
|
|
10313
|
+
TabLayout,
|
|
10314
|
+
{
|
|
10315
|
+
form,
|
|
10316
|
+
schema,
|
|
10317
|
+
dsUid,
|
|
10318
|
+
dsName,
|
|
10319
|
+
onRetest,
|
|
10320
|
+
healthError,
|
|
10321
|
+
renderActions
|
|
10322
|
+
}
|
|
10323
|
+
);
|
|
10324
|
+
}
|
|
10325
|
+
return /* @__PURE__ */ React__default.default.createElement(
|
|
10326
|
+
WizardLayout,
|
|
10327
|
+
{
|
|
10328
|
+
form,
|
|
10329
|
+
schema,
|
|
10330
|
+
dsUid,
|
|
10331
|
+
dsName,
|
|
10332
|
+
onRetest,
|
|
10333
|
+
healthError,
|
|
10334
|
+
renderActions
|
|
10335
|
+
}
|
|
10336
|
+
);
|
|
10337
|
+
}
|
|
10338
|
+
function WizardLayout({ form, schema, dsUid, dsName, onRetest, healthError, renderActions }) {
|
|
10339
|
+
var _a, _b, _c;
|
|
10340
|
+
const styles = ui.useStyles2(getWizardStyles);
|
|
10341
|
+
const [currentStep, setCurrentStep] = React.useState(0);
|
|
10342
|
+
const {
|
|
10343
|
+
resolvedGroups,
|
|
10344
|
+
fieldById,
|
|
10345
|
+
httpHeadersField,
|
|
10346
|
+
control,
|
|
10347
|
+
handleSubmit,
|
|
10348
|
+
trigger,
|
|
10349
|
+
errors,
|
|
10350
|
+
watchedValues,
|
|
10351
|
+
initializing,
|
|
10352
|
+
fetchError,
|
|
10353
|
+
submitting,
|
|
10354
|
+
submitError,
|
|
10355
|
+
readOnly,
|
|
10356
|
+
isFieldVisible,
|
|
10357
|
+
onSubmit
|
|
10358
|
+
} = form;
|
|
10359
|
+
const arrowSteps = React.useMemo(() => {
|
|
10360
|
+
const requiredGroup = resolvedGroups.find((g) => g.group.id === "_required");
|
|
10361
|
+
if (!requiredGroup) {
|
|
10362
|
+
return new Set(resolvedGroups.map((_, i) => i));
|
|
10363
|
+
}
|
|
10364
|
+
const requiredFieldIds = new Set(requiredGroup.fields.map((f) => f.id));
|
|
10365
|
+
const steps = /* @__PURE__ */ new Set();
|
|
10366
|
+
for (let i = 0; i < resolvedGroups.length; i++) {
|
|
10367
|
+
const g = resolvedGroups[i];
|
|
10368
|
+
if (g.group.id === "_required" || g.fields.some((f) => !requiredFieldIds.has(f.id))) {
|
|
10369
|
+
steps.add(i);
|
|
10370
|
+
}
|
|
10371
|
+
}
|
|
10372
|
+
return steps;
|
|
10373
|
+
}, [resolvedGroups]);
|
|
10374
|
+
const currentResolved = resolvedGroups[currentStep];
|
|
10375
|
+
const isFirstStep = React.useMemo(() => {
|
|
10376
|
+
for (let i = 0; i < currentStep; i++) {
|
|
10377
|
+
if (arrowSteps.has(i)) {
|
|
10378
|
+
return false;
|
|
10379
|
+
}
|
|
10380
|
+
}
|
|
10381
|
+
return true;
|
|
10382
|
+
}, [currentStep, arrowSteps]);
|
|
10383
|
+
const isLastStep = React.useMemo(() => {
|
|
10384
|
+
for (let i = currentStep + 1; i < resolvedGroups.length; i++) {
|
|
10385
|
+
if (arrowSteps.has(i)) {
|
|
10386
|
+
return false;
|
|
10387
|
+
}
|
|
10388
|
+
}
|
|
10389
|
+
return true;
|
|
10390
|
+
}, [currentStep, arrowSteps, resolvedGroups.length]);
|
|
10391
|
+
const visibleFieldsForStep = React.useMemo(
|
|
10392
|
+
() => currentResolved ? currentResolved.fields.filter(isFieldVisible) : [],
|
|
10393
|
+
[currentResolved, isFieldVisible]
|
|
10394
|
+
);
|
|
10395
|
+
const currentGroupValid = React.useMemo(() => {
|
|
10396
|
+
if (!currentResolved) {
|
|
10397
|
+
return true;
|
|
10398
|
+
}
|
|
10399
|
+
for (const field of visibleFieldsForStep) {
|
|
10400
|
+
if (errors[formKey(field)]) {
|
|
10401
|
+
return false;
|
|
10402
|
+
}
|
|
10403
|
+
if (isFieldRequired(field, watchedValues, fieldById)) {
|
|
10404
|
+
const val = watchedValues[formKey(field)];
|
|
10405
|
+
if (val === SECURE_FIELD_CONFIGURED) {
|
|
10406
|
+
continue;
|
|
10407
|
+
}
|
|
10408
|
+
if (val === void 0 || val === null || val === "") {
|
|
10409
|
+
return false;
|
|
10410
|
+
}
|
|
10411
|
+
}
|
|
10412
|
+
}
|
|
10413
|
+
return true;
|
|
10414
|
+
}, [currentResolved, errors, visibleFieldsForStep, watchedValues, fieldById]);
|
|
10415
|
+
const goNext = React.useCallback(async () => {
|
|
10416
|
+
if (!currentResolved) {
|
|
10417
|
+
return;
|
|
10418
|
+
}
|
|
10419
|
+
if (!readOnly) {
|
|
10420
|
+
const visibleKeys = visibleFieldsForStep.map((f) => formKey(f));
|
|
10421
|
+
const valid = await trigger(visibleKeys);
|
|
10422
|
+
if (!valid) {
|
|
10423
|
+
return;
|
|
10424
|
+
}
|
|
10425
|
+
}
|
|
10426
|
+
setCurrentStep((s) => {
|
|
10427
|
+
for (let i = s + 1; i < resolvedGroups.length; i++) {
|
|
10428
|
+
if (arrowSteps.has(i)) {
|
|
10429
|
+
return i;
|
|
10430
|
+
}
|
|
10431
|
+
}
|
|
10432
|
+
return s;
|
|
10433
|
+
});
|
|
10434
|
+
}, [currentResolved, visibleFieldsForStep, trigger, resolvedGroups.length, arrowSteps, readOnly]);
|
|
10435
|
+
const goPrev = React.useCallback(() => {
|
|
10436
|
+
setCurrentStep((s) => {
|
|
10437
|
+
for (let i = s - 1; i >= 0; i--) {
|
|
10438
|
+
if (arrowSteps.has(i)) {
|
|
10439
|
+
return i;
|
|
10440
|
+
}
|
|
10441
|
+
}
|
|
10442
|
+
return s;
|
|
10443
|
+
});
|
|
10444
|
+
}, [arrowSteps]);
|
|
10445
|
+
if (initializing) {
|
|
10446
|
+
return /* @__PURE__ */ React__default.default.createElement("div", { className: styles.container }, /* @__PURE__ */ React__default.default.createElement(ui.Spinner, { size: "sm", inline: true }), " Loading configuration...");
|
|
10447
|
+
}
|
|
10448
|
+
if (fetchError) {
|
|
10449
|
+
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(
|
|
10450
|
+
ui.LinkButton,
|
|
10451
|
+
{
|
|
10452
|
+
variant: "secondary",
|
|
10453
|
+
size: "sm",
|
|
10454
|
+
icon: "external-link-alt",
|
|
10455
|
+
href: `/connections/datasources/edit/${dsUid}`
|
|
10456
|
+
},
|
|
10457
|
+
"Open datasource settings"
|
|
10458
|
+
)));
|
|
10459
|
+
}
|
|
10460
|
+
const allDisabled = submitting || readOnly;
|
|
10461
|
+
if (resolvedGroups.length === 0) {
|
|
10462
|
+
return null;
|
|
10463
|
+
}
|
|
10464
|
+
const currentGroup = currentResolved == null ? void 0 : currentResolved.group;
|
|
10465
|
+
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(
|
|
10466
|
+
ui.Button,
|
|
10467
|
+
{
|
|
10468
|
+
variant: "secondary",
|
|
10469
|
+
fill: "text",
|
|
10470
|
+
size: "sm",
|
|
10471
|
+
icon: "angle-left",
|
|
10472
|
+
"aria-label": "Previous",
|
|
10473
|
+
onClick: goPrev,
|
|
10474
|
+
disabled: isFirstStep || submitting,
|
|
10475
|
+
type: "button"
|
|
10476
|
+
}
|
|
10477
|
+
)), /* @__PURE__ */ React__default.default.createElement(
|
|
10478
|
+
ui.Select,
|
|
10479
|
+
{
|
|
10480
|
+
options: resolvedGroups.map((g, i) => ({ label: g.group.title, value: i })),
|
|
10481
|
+
value: currentStep,
|
|
10482
|
+
onChange: (v) => {
|
|
10483
|
+
if (v) {
|
|
10484
|
+
setCurrentStep(v.value);
|
|
10485
|
+
}
|
|
10486
|
+
},
|
|
10487
|
+
disabled: submitting,
|
|
10488
|
+
width: 18
|
|
10489
|
+
}
|
|
10490
|
+
), /* @__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(
|
|
10491
|
+
ui.Button,
|
|
10492
|
+
{
|
|
10493
|
+
variant: isLastStep || !readOnly && !currentGroupValid ? "secondary" : "primary",
|
|
10494
|
+
size: "sm",
|
|
10495
|
+
icon: "angle-right",
|
|
10496
|
+
"aria-label": "Next",
|
|
10497
|
+
onClick: goNext,
|
|
10498
|
+
disabled: isLastStep || submitting,
|
|
10499
|
+
type: "button"
|
|
10500
|
+
}
|
|
10501
|
+
)))), currentResolved && /* @__PURE__ */ React__default.default.createElement("form", { onSubmit: handleSubmit(onSubmit), className: styles.form }, visibleFieldsForStep.map((field) => /* @__PURE__ */ React__default.default.createElement(
|
|
10502
|
+
SchemaField,
|
|
10503
|
+
{
|
|
10504
|
+
key: formKey(field),
|
|
10505
|
+
field,
|
|
10506
|
+
control,
|
|
10507
|
+
errors,
|
|
10508
|
+
disabled: allDisabled,
|
|
10509
|
+
dsUid,
|
|
10510
|
+
watchedValues,
|
|
10511
|
+
fieldById
|
|
10512
|
+
}
|
|
10513
|
+
)), (currentResolved.group.id === "_required" || currentResolved.group.id === "auth") && httpHeadersField && /* @__PURE__ */ React__default.default.createElement(
|
|
10514
|
+
AuthorizationHeaderField,
|
|
10515
|
+
{
|
|
10516
|
+
headersFieldKey: formKey(httpHeadersField),
|
|
10517
|
+
control,
|
|
10518
|
+
disabled: allDisabled,
|
|
10519
|
+
watchedValues
|
|
10520
|
+
}
|
|
10521
|
+
), submitError && /* @__PURE__ */ React__default.default.createElement(ui.Alert, { severity: "error", title: "Error" }, submitError), /* @__PURE__ */ React__default.default.createElement("div", { className: styles.buttons }, readOnly ? /* @__PURE__ */ React__default.default.createElement(ui.Button, { variant: "primary", size: "sm", icon: "sync", onClick: onRetest, type: "button" }, "Test") : /* @__PURE__ */ React__default.default.createElement(ui.Button, { variant: "primary", size: "sm", disabled: submitting || !currentGroupValid, type: "submit" }, submitting ? "Saving..." : "Save & Test"), healthError && (renderActions == null ? void 0 : renderActions({ dsUid, dsName, dsType: schema.pluginType, healthError })))));
|
|
10522
|
+
}
|
|
10523
|
+
|
|
10524
|
+
var __defProp$1 = Object.defineProperty;
|
|
10525
|
+
var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
10526
|
+
var __publicField$1 = (obj, key, value) => __defNormalProp$1(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
10527
|
+
const getCustomHeaderRowStyles = ui.stylesFactory(() => {
|
|
10528
|
+
return {
|
|
10529
|
+
layout: css.css`
|
|
10530
|
+
display: flex;
|
|
10531
|
+
align-items: center;
|
|
10532
|
+
margin-bottom: 4px;
|
|
10533
|
+
> * {
|
|
10534
|
+
margin-left: 4px;
|
|
10535
|
+
margin-bottom: 0;
|
|
10536
|
+
height: 100%;
|
|
10537
|
+
&:first-child,
|
|
10538
|
+
&:last-child {
|
|
10539
|
+
margin-left: 0;
|
|
10540
|
+
}
|
|
10541
|
+
}
|
|
10542
|
+
`
|
|
10543
|
+
};
|
|
10544
|
+
});
|
|
10545
|
+
const CustomHeaderRow = ({ header, onBlur, onChange, onRemove, onReset }) => {
|
|
10546
|
+
const styles = getCustomHeaderRowStyles();
|
|
10547
|
+
return /* @__PURE__ */ React__default.default.createElement("div", { className: styles.layout }, /* @__PURE__ */ React__default.default.createElement(
|
|
10548
|
+
ui.LegacyForms.FormField,
|
|
10549
|
+
{
|
|
10550
|
+
label: "Header",
|
|
10551
|
+
name: "name",
|
|
10552
|
+
placeholder: "X-Custom-Header",
|
|
10553
|
+
labelWidth: 5,
|
|
10554
|
+
value: header.name || "",
|
|
10555
|
+
onChange: (e) => onChange({ ...header, name: e.target.value }),
|
|
10556
|
+
onBlur
|
|
10557
|
+
}
|
|
10558
|
+
), /* @__PURE__ */ React__default.default.createElement(
|
|
10559
|
+
ui.LegacyForms.SecretFormField,
|
|
10560
|
+
{
|
|
10561
|
+
label: "Value",
|
|
10562
|
+
"aria-label": "Value",
|
|
10563
|
+
name: "value",
|
|
10564
|
+
isConfigured: header.configured,
|
|
10565
|
+
value: header.value,
|
|
10566
|
+
labelWidth: 5,
|
|
10567
|
+
inputWidth: header.configured ? 11 : 12,
|
|
10568
|
+
placeholder: "Header Value",
|
|
10569
|
+
onReset: () => onReset(header.id),
|
|
10570
|
+
onChange: (e) => onChange({ ...header, value: e.target.value }),
|
|
10571
|
+
onBlur
|
|
10572
|
+
}
|
|
10573
|
+
), /* @__PURE__ */ React__default.default.createElement(
|
|
10574
|
+
ui.Button,
|
|
10575
|
+
{
|
|
10576
|
+
type: "button",
|
|
10577
|
+
"aria-label": "Remove header",
|
|
10578
|
+
variant: "secondary",
|
|
10579
|
+
size: "xs",
|
|
10580
|
+
onClick: (_e) => onRemove(header.id)
|
|
10581
|
+
},
|
|
10582
|
+
/* @__PURE__ */ React__default.default.createElement(ui.Icon, { name: "trash-alt" })
|
|
10583
|
+
));
|
|
10584
|
+
};
|
|
10585
|
+
CustomHeaderRow.displayName = "CustomHeaderRow";
|
|
10586
|
+
class CustomHeadersSettings extends React.PureComponent {
|
|
10587
|
+
constructor(props) {
|
|
10588
|
+
super(props);
|
|
10589
|
+
__publicField$1(this, "state", {
|
|
10590
|
+
headers: []
|
|
10591
|
+
});
|
|
10592
|
+
__publicField$1(this, "updateSettings", () => {
|
|
10593
|
+
const { headers } = this.state;
|
|
10594
|
+
const newJsonData = Object.fromEntries(
|
|
10595
|
+
Object.entries(this.props.dataSourceConfig.jsonData).filter(([key, val]) => !key.startsWith("httpHeaderName"))
|
|
10596
|
+
);
|
|
10597
|
+
const newSecureJsonData = Object.fromEntries(
|
|
10598
|
+
Object.entries(this.props.dataSourceConfig.secureJsonData || {}).filter(
|
|
10599
|
+
([key, val]) => !key.startsWith("httpHeaderValue")
|
|
10600
|
+
)
|
|
10601
|
+
);
|
|
10602
|
+
for (const [index, header] of headers.entries()) {
|
|
10603
|
+
newJsonData[`httpHeaderName${index + 1}`] = header.name;
|
|
10604
|
+
if (!header.configured) {
|
|
10605
|
+
newSecureJsonData[`httpHeaderValue${index + 1}`] = header.value;
|
|
10606
|
+
}
|
|
10607
|
+
}
|
|
10608
|
+
this.props.onChange({
|
|
10609
|
+
...this.props.dataSourceConfig,
|
|
10610
|
+
jsonData: newJsonData,
|
|
10611
|
+
secureJsonData: newSecureJsonData
|
|
10612
|
+
});
|
|
10613
|
+
});
|
|
10614
|
+
__publicField$1(this, "onHeaderAdd", () => {
|
|
10615
|
+
this.setState((prevState) => {
|
|
10616
|
+
return {
|
|
10617
|
+
headers: [...prevState.headers, { id: lodash.uniqueId(), name: "", value: "", configured: false }]
|
|
10618
|
+
};
|
|
10619
|
+
});
|
|
10620
|
+
});
|
|
10621
|
+
__publicField$1(this, "onHeaderChange", (headerIndex, value) => {
|
|
10622
|
+
this.setState(({ headers }) => {
|
|
10623
|
+
return {
|
|
10624
|
+
headers: headers.map((item, index) => {
|
|
10625
|
+
if (headerIndex !== index) {
|
|
10626
|
+
return item;
|
|
10627
|
+
}
|
|
10628
|
+
return { ...value };
|
|
10629
|
+
})
|
|
10630
|
+
};
|
|
10631
|
+
});
|
|
10632
|
+
});
|
|
10633
|
+
__publicField$1(this, "onHeaderReset", (headerId) => {
|
|
10634
|
+
this.setState(({ headers }) => {
|
|
10635
|
+
return {
|
|
10636
|
+
headers: headers.map((h, i) => {
|
|
10637
|
+
if (h.id !== headerId) {
|
|
10638
|
+
return h;
|
|
10639
|
+
}
|
|
10640
|
+
return {
|
|
10641
|
+
...h,
|
|
10642
|
+
value: "",
|
|
10643
|
+
configured: false
|
|
10644
|
+
};
|
|
10645
|
+
})
|
|
10646
|
+
};
|
|
10647
|
+
});
|
|
10648
|
+
});
|
|
10649
|
+
__publicField$1(this, "onHeaderRemove", (headerId) => {
|
|
10650
|
+
this.setState(
|
|
10651
|
+
({ headers }) => ({
|
|
10652
|
+
headers: headers.filter((h) => h.id !== headerId)
|
|
10653
|
+
}),
|
|
10654
|
+
this.updateSettings
|
|
10655
|
+
);
|
|
10656
|
+
});
|
|
10657
|
+
const { jsonData, secureJsonData, secureJsonFields } = this.props.dataSourceConfig;
|
|
10658
|
+
this.state = {
|
|
10659
|
+
headers: Object.keys(jsonData).sort().filter((key) => key.startsWith("httpHeaderName")).map((key, index) => {
|
|
10660
|
+
return {
|
|
10661
|
+
id: lodash.uniqueId(),
|
|
10662
|
+
name: jsonData[key],
|
|
10663
|
+
value: secureJsonData !== void 0 ? secureJsonData[key] : "",
|
|
10664
|
+
configured: secureJsonFields && secureJsonFields[`httpHeaderValue${index + 1}`] || false
|
|
10665
|
+
};
|
|
10666
|
+
})
|
|
10667
|
+
};
|
|
10668
|
+
}
|
|
10669
|
+
render() {
|
|
10670
|
+
const { headers } = this.state;
|
|
10671
|
+
return /* @__PURE__ */ React__default.default.createElement("div", { className: "gf-form-group" }, /* @__PURE__ */ React__default.default.createElement("div", { className: "gf-form" }, /* @__PURE__ */ React__default.default.createElement("h6", null, "Custom HTTP Headers")), /* @__PURE__ */ React__default.default.createElement("div", null, headers.map((header, i) => /* @__PURE__ */ React__default.default.createElement(
|
|
10672
|
+
CustomHeaderRow,
|
|
10673
|
+
{
|
|
10674
|
+
key: header.id,
|
|
10675
|
+
header,
|
|
10676
|
+
onChange: (h) => {
|
|
10677
|
+
this.onHeaderChange(i, h);
|
|
10678
|
+
},
|
|
10679
|
+
onBlur: this.updateSettings,
|
|
10680
|
+
onRemove: this.onHeaderRemove,
|
|
10681
|
+
onReset: this.onHeaderReset
|
|
10682
|
+
}
|
|
10683
|
+
))), /* @__PURE__ */ React__default.default.createElement("div", { className: "gf-form" }, /* @__PURE__ */ React__default.default.createElement(
|
|
10684
|
+
ui.Button,
|
|
10685
|
+
{
|
|
10686
|
+
variant: "secondary",
|
|
10687
|
+
icon: "plus",
|
|
10688
|
+
type: "button",
|
|
10689
|
+
onClick: (e) => {
|
|
10690
|
+
this.onHeaderAdd();
|
|
10691
|
+
}
|
|
10692
|
+
},
|
|
10693
|
+
"Add header"
|
|
10694
|
+
)));
|
|
10695
|
+
}
|
|
10696
|
+
}
|
|
10697
|
+
|
|
10698
|
+
var QueryEditorMode = /* @__PURE__ */ ((QueryEditorMode2) => {
|
|
10699
|
+
QueryEditorMode2["Code"] = "code";
|
|
10700
|
+
QueryEditorMode2["Builder"] = "builder";
|
|
10701
|
+
return QueryEditorMode2;
|
|
10702
|
+
})(QueryEditorMode || {});
|
|
10703
|
+
const BINARY_OPERATIONS_KEY = "Binary operations";
|
|
10704
|
+
|
|
10705
|
+
var __defProp = Object.defineProperty;
|
|
10706
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
10707
|
+
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
10708
|
+
class QueryModellerBase {
|
|
10709
|
+
constructor(operationDefinitions, innerQueryPlaceholder) {
|
|
10710
|
+
__publicField(this, "operationsRegistry");
|
|
10711
|
+
__publicField(this, "categories", []);
|
|
10712
|
+
__publicField(this, "innerQueryPlaceholder");
|
|
10713
|
+
this.operationsRegistry = new data.Registry(() => operationDefinitions);
|
|
10714
|
+
this.innerQueryPlaceholder = innerQueryPlaceholder || "<query>";
|
|
10715
|
+
}
|
|
10716
|
+
setOperationCategories(categories) {
|
|
10717
|
+
this.categories = categories;
|
|
10718
|
+
}
|
|
10719
|
+
getOperationsForCategory(category) {
|
|
10720
|
+
return this.operationsRegistry.list().filter((op) => op.category === category && !op.hideFromList);
|
|
10721
|
+
}
|
|
10722
|
+
getAlternativeOperations(key) {
|
|
10723
|
+
return this.operationsRegistry.list().filter((op) => op.alternativesKey && op.alternativesKey === key);
|
|
10724
|
+
}
|
|
10725
|
+
getCategories() {
|
|
10726
|
+
return this.categories;
|
|
10727
|
+
}
|
|
10728
|
+
getOperationDefinition(id) {
|
|
10729
|
+
return this.operationsRegistry.getIfExists(id);
|
|
10730
|
+
}
|
|
10731
|
+
hasBinaryOp(query) {
|
|
10732
|
+
return query.operations.find((op) => {
|
|
10733
|
+
const def = this.getOperationDefinition(op.id);
|
|
10734
|
+
return (def == null ? void 0 : def.category) === BINARY_OPERATIONS_KEY;
|
|
10735
|
+
}) !== void 0;
|
|
10736
|
+
}
|
|
10737
|
+
}
|
|
10738
|
+
|
|
10739
|
+
const CONFLICTING_LABEL_FILTER_ERROR_MESSAGE = "You have conflicting label filters";
|
|
10740
|
+
function LabelFilterItem({
|
|
10741
|
+
item,
|
|
10742
|
+
items,
|
|
10743
|
+
defaultOp,
|
|
10744
|
+
onChange,
|
|
10745
|
+
onDelete,
|
|
10746
|
+
onGetLabelNames,
|
|
8615
10747
|
onGetLabelValues,
|
|
8616
10748
|
invalidLabel,
|
|
8617
10749
|
invalidValue,
|
|
@@ -9842,6 +11974,411 @@ const convertUnits = (queryStats) => {
|
|
|
9842
11974
|
return text + suffix;
|
|
9843
11975
|
};
|
|
9844
11976
|
|
|
11977
|
+
function generateLLMHint(schema) {
|
|
11978
|
+
var _a, _b, _c, _d;
|
|
11979
|
+
const hints = [];
|
|
11980
|
+
for (const field of schema.fields) {
|
|
11981
|
+
if (((_a = field.ui) == null ? void 0 : _a.component) !== "select" || field.target !== "jsonData" || field.kind === "virtual") {
|
|
11982
|
+
continue;
|
|
11983
|
+
}
|
|
11984
|
+
const options = (_c = (_b = field.ui) == null ? void 0 : _b.options) != null ? _c : [];
|
|
11985
|
+
const values = options.map((opt) => {
|
|
11986
|
+
const isDefault = field.defaultValue != null && String(opt.value) === String(field.defaultValue);
|
|
11987
|
+
return isDefault ? `"${opt.value}" (default)` : `"${opt.value}"`;
|
|
11988
|
+
}).join(", ");
|
|
11989
|
+
if (values) {
|
|
11990
|
+
hints.push(`- ${(_d = field.label) != null ? _d : field.key}: jsonData.${field.key} \u2014 values: ${values}`);
|
|
11991
|
+
}
|
|
11992
|
+
}
|
|
11993
|
+
return hints.join("\n");
|
|
11994
|
+
}
|
|
11995
|
+
function generateTroubleshootingFields(schema) {
|
|
11996
|
+
var _a, _b, _c;
|
|
11997
|
+
const result = [];
|
|
11998
|
+
for (const field of schema.fields) {
|
|
11999
|
+
if (field.kind === "virtual" || field.isItemField) {
|
|
12000
|
+
continue;
|
|
12001
|
+
}
|
|
12002
|
+
const entry = {
|
|
12003
|
+
label: (_a = field.label) != null ? _a : field.key,
|
|
12004
|
+
key: field.target === "root" ? field.key : `${field.target}.${field.key}`,
|
|
12005
|
+
target: (_b = field.target) != null ? _b : "jsonData",
|
|
12006
|
+
type: field.valueType,
|
|
12007
|
+
required: !!field.required
|
|
12008
|
+
};
|
|
12009
|
+
if (field.description) {
|
|
12010
|
+
entry.description = field.description;
|
|
12011
|
+
}
|
|
12012
|
+
if (field.defaultValue != null) {
|
|
12013
|
+
entry.defaultValue = field.defaultValue;
|
|
12014
|
+
}
|
|
12015
|
+
if (((_c = field.ui) == null ? void 0 : _c.options) && field.ui.options.length > 0) {
|
|
12016
|
+
entry.options = field.ui.options.map((o) => String(o.value));
|
|
12017
|
+
}
|
|
12018
|
+
if (field.section) {
|
|
12019
|
+
entry.section = field.section;
|
|
12020
|
+
}
|
|
12021
|
+
if (field.dependsOn) {
|
|
12022
|
+
entry.dependsOn = field.dependsOn;
|
|
12023
|
+
}
|
|
12024
|
+
result.push(entry);
|
|
12025
|
+
}
|
|
12026
|
+
return result;
|
|
12027
|
+
}
|
|
12028
|
+
|
|
12029
|
+
function yamlIndent(depth) {
|
|
12030
|
+
return " ".repeat(depth);
|
|
12031
|
+
}
|
|
12032
|
+
function yamlString(value) {
|
|
12033
|
+
if (value === null || value === void 0) {
|
|
12034
|
+
return '""';
|
|
12035
|
+
}
|
|
12036
|
+
const s = String(value);
|
|
12037
|
+
if (s === "") {
|
|
12038
|
+
return '""';
|
|
12039
|
+
}
|
|
12040
|
+
return yaml__default.default.dump(s, { lineWidth: -1 }).trimEnd();
|
|
12041
|
+
}
|
|
12042
|
+
function yamlValue(value, depth) {
|
|
12043
|
+
if (value === null || value === void 0) {
|
|
12044
|
+
return '""';
|
|
12045
|
+
}
|
|
12046
|
+
if (typeof value === "boolean") {
|
|
12047
|
+
return value ? "true" : "false";
|
|
12048
|
+
}
|
|
12049
|
+
if (typeof value === "number") {
|
|
12050
|
+
return String(value);
|
|
12051
|
+
}
|
|
12052
|
+
if (typeof value === "string") {
|
|
12053
|
+
return yamlString(value);
|
|
12054
|
+
}
|
|
12055
|
+
if (Array.isArray(value)) {
|
|
12056
|
+
if (value.length === 0) {
|
|
12057
|
+
return "[]";
|
|
12058
|
+
}
|
|
12059
|
+
const lines = value.map((item) => {
|
|
12060
|
+
if (typeof item === "object" && item !== null && !Array.isArray(item)) {
|
|
12061
|
+
const entries = Object.entries(item);
|
|
12062
|
+
if (entries.length === 0) {
|
|
12063
|
+
return `${yamlIndent(depth)}- {}`;
|
|
12064
|
+
}
|
|
12065
|
+
const [firstKey, firstVal] = entries[0];
|
|
12066
|
+
const firstLine = `${yamlIndent(depth)}- ${yamlString(firstKey)}: ${yamlValue(firstVal, depth + 2)}`;
|
|
12067
|
+
const rest = entries.slice(1).map(([k, v]) => `${yamlIndent(depth + 1)}${yamlString(k)}: ${yamlValue(v, depth + 2)}`);
|
|
12068
|
+
return [firstLine, ...rest].join("\n");
|
|
12069
|
+
}
|
|
12070
|
+
return `${yamlIndent(depth)}- ${yamlValue(item, depth + 1)}`;
|
|
12071
|
+
});
|
|
12072
|
+
return "\n" + lines.join("\n");
|
|
12073
|
+
}
|
|
12074
|
+
if (typeof value === "object") {
|
|
12075
|
+
const entries = Object.entries(value);
|
|
12076
|
+
if (entries.length === 0) {
|
|
12077
|
+
return "{}";
|
|
12078
|
+
}
|
|
12079
|
+
const lines = entries.map(([k, v]) => `${yamlIndent(depth)}${yamlString(k)}: ${yamlValue(v, depth + 1)}`);
|
|
12080
|
+
return "\n" + lines.join("\n");
|
|
12081
|
+
}
|
|
12082
|
+
return yamlString(value);
|
|
12083
|
+
}
|
|
12084
|
+
function isCertField(field) {
|
|
12085
|
+
var _a;
|
|
12086
|
+
const k = field.key.toLowerCase();
|
|
12087
|
+
return field.target === "secureJsonData" && (k.includes("cert") || k.includes("key") || ((_a = field.ui) == null ? void 0 : _a.component) === "textarea");
|
|
12088
|
+
}
|
|
12089
|
+
function isExcludedFromProvisioning(field) {
|
|
12090
|
+
var _a, _b;
|
|
12091
|
+
if (field.kind === "virtual") {
|
|
12092
|
+
return true;
|
|
12093
|
+
}
|
|
12094
|
+
if (field.isItemField) {
|
|
12095
|
+
return true;
|
|
12096
|
+
}
|
|
12097
|
+
if (((_a = field.tags) == null ? void 0 : _a.some((t) => t.startsWith("managed-by:"))) && field.target !== "root") {
|
|
12098
|
+
return true;
|
|
12099
|
+
}
|
|
12100
|
+
if (((_b = field.storage) == null ? void 0 : _b.type) === "indexedPair") {
|
|
12101
|
+
return true;
|
|
12102
|
+
}
|
|
12103
|
+
return false;
|
|
12104
|
+
}
|
|
12105
|
+
function secretPlaceholder(field) {
|
|
12106
|
+
if (isCertField(field)) {
|
|
12107
|
+
return "|\n xxxxxx";
|
|
12108
|
+
}
|
|
12109
|
+
return "xxxxxx";
|
|
12110
|
+
}
|
|
12111
|
+
function templateValue(field) {
|
|
12112
|
+
var _a;
|
|
12113
|
+
if (field.defaultValue !== void 0) {
|
|
12114
|
+
return field.defaultValue;
|
|
12115
|
+
}
|
|
12116
|
+
if (((_a = field.ui) == null ? void 0 : _a.options) && field.ui.options.length > 0) {
|
|
12117
|
+
return field.ui.options[0].value;
|
|
12118
|
+
}
|
|
12119
|
+
switch (field.valueType) {
|
|
12120
|
+
case "string":
|
|
12121
|
+
return "";
|
|
12122
|
+
case "number":
|
|
12123
|
+
return 0;
|
|
12124
|
+
case "boolean":
|
|
12125
|
+
return false;
|
|
12126
|
+
case "array":
|
|
12127
|
+
return [];
|
|
12128
|
+
case "object":
|
|
12129
|
+
case "map":
|
|
12130
|
+
return {};
|
|
12131
|
+
default:
|
|
12132
|
+
return "";
|
|
12133
|
+
}
|
|
12134
|
+
}
|
|
12135
|
+
function fieldComment(field, indent) {
|
|
12136
|
+
var _a, _b, _c;
|
|
12137
|
+
const parts = [];
|
|
12138
|
+
const label = (_a = field.label) != null ? _a : field.key;
|
|
12139
|
+
let line = label;
|
|
12140
|
+
if (field.required) {
|
|
12141
|
+
line += " (REQUIRED)";
|
|
12142
|
+
}
|
|
12143
|
+
if (field.description) {
|
|
12144
|
+
line += ` \u2014 ${field.description}`;
|
|
12145
|
+
}
|
|
12146
|
+
parts.push(`${indent}# ${line}`);
|
|
12147
|
+
const options = (_b = field.ui) == null ? void 0 : _b.options;
|
|
12148
|
+
if (options && options.length > 0) {
|
|
12149
|
+
const vals = options.map((o) => String(o.value)).join(", ");
|
|
12150
|
+
parts.push(`${indent}# Allowed values: ${vals}`);
|
|
12151
|
+
}
|
|
12152
|
+
const allowedValuesRule = (_c = field.validations) == null ? void 0 : _c.find(
|
|
12153
|
+
(v) => v.type === "allowedValues"
|
|
12154
|
+
);
|
|
12155
|
+
if (allowedValuesRule && !options) {
|
|
12156
|
+
const vals = allowedValuesRule.values.map((v) => String(v)).join(", ");
|
|
12157
|
+
parts.push(`${indent}# Allowed values: ${vals}`);
|
|
12158
|
+
}
|
|
12159
|
+
if (field.dependsOn) {
|
|
12160
|
+
parts.push(`${indent}# Only when: ${field.dependsOn}`);
|
|
12161
|
+
}
|
|
12162
|
+
return parts.join("\n");
|
|
12163
|
+
}
|
|
12164
|
+
function toProvisioningYaml(schema, values, options) {
|
|
12165
|
+
var _a, _b, _c, _d, _e, _f;
|
|
12166
|
+
const isTemplate = !values;
|
|
12167
|
+
const showComments = (_a = options == null ? void 0 : options.comments) != null ? _a : isTemplate;
|
|
12168
|
+
const indent2 = " ";
|
|
12169
|
+
const indent3 = " ";
|
|
12170
|
+
const groups = resolveGroups(schema);
|
|
12171
|
+
const rootFields = [];
|
|
12172
|
+
const jsonDataFieldsByGroup = [];
|
|
12173
|
+
const secureJsonDataFieldsByGroup = [];
|
|
12174
|
+
const virtualFieldsWithOptions = [];
|
|
12175
|
+
for (const { group, fields } of groups) {
|
|
12176
|
+
const jd = [];
|
|
12177
|
+
const sd = [];
|
|
12178
|
+
for (const field of fields) {
|
|
12179
|
+
if (field.kind === "virtual" && ((_b = field.ui) == null ? void 0 : _b.options) && field.ui.options.length > 0) {
|
|
12180
|
+
virtualFieldsWithOptions.push(field);
|
|
12181
|
+
continue;
|
|
12182
|
+
}
|
|
12183
|
+
if (isExcludedFromProvisioning(field)) {
|
|
12184
|
+
continue;
|
|
12185
|
+
}
|
|
12186
|
+
switch (field.target) {
|
|
12187
|
+
case "root":
|
|
12188
|
+
rootFields.push(field);
|
|
12189
|
+
break;
|
|
12190
|
+
case "jsonData":
|
|
12191
|
+
jd.push(field);
|
|
12192
|
+
break;
|
|
12193
|
+
case "secureJsonData":
|
|
12194
|
+
sd.push(field);
|
|
12195
|
+
break;
|
|
12196
|
+
}
|
|
12197
|
+
}
|
|
12198
|
+
if (jd.length > 0) {
|
|
12199
|
+
jsonDataFieldsByGroup.push({ group, fields: jd });
|
|
12200
|
+
}
|
|
12201
|
+
if (sd.length > 0) {
|
|
12202
|
+
secureJsonDataFieldsByGroup.push({ group, fields: sd });
|
|
12203
|
+
}
|
|
12204
|
+
}
|
|
12205
|
+
const allSecureJsonDataFields = secureJsonDataFieldsByGroup.flatMap((g) => g.fields);
|
|
12206
|
+
const groupedFieldIds = new Set(groups.flatMap(({ group }) => group.fieldRefs));
|
|
12207
|
+
for (const field of schema.fields) {
|
|
12208
|
+
if (field.target === "root" && !groupedFieldIds.has(field.id) && !isExcludedFromProvisioning(field)) {
|
|
12209
|
+
rootFields.push(field);
|
|
12210
|
+
}
|
|
12211
|
+
}
|
|
12212
|
+
const lines = [];
|
|
12213
|
+
lines.push("apiVersion: 1");
|
|
12214
|
+
lines.push("");
|
|
12215
|
+
lines.push("datasources:");
|
|
12216
|
+
lines.push(`${indent2.slice(2)}- name: ${yamlString((_d = (_c = options == null ? void 0 : options.name) != null ? _c : values == null ? void 0 : values.name) != null ? _d : `my-${schema.pluginType}`)}`);
|
|
12217
|
+
lines.push(`${indent2}type: ${schema.pluginType}`);
|
|
12218
|
+
if (!isTemplate && (values == null ? void 0 : values.uid)) {
|
|
12219
|
+
lines.push(`${indent2}uid: ${yamlString(values.uid)}`);
|
|
12220
|
+
}
|
|
12221
|
+
const ALREADY_EMITTED_ROOT = /* @__PURE__ */ new Set(["name", "type", "uid"]);
|
|
12222
|
+
for (const field of rootFields) {
|
|
12223
|
+
if (ALREADY_EMITTED_ROOT.has(field.key)) {
|
|
12224
|
+
continue;
|
|
12225
|
+
}
|
|
12226
|
+
const val = values ? values[field.key] : templateValue(field);
|
|
12227
|
+
if (val === void 0 || val === null) {
|
|
12228
|
+
continue;
|
|
12229
|
+
}
|
|
12230
|
+
if (!isTemplate && val === false) {
|
|
12231
|
+
continue;
|
|
12232
|
+
}
|
|
12233
|
+
if (showComments) {
|
|
12234
|
+
lines.push(fieldComment(field, indent2));
|
|
12235
|
+
}
|
|
12236
|
+
lines.push(`${indent2}${field.key}: ${yamlValue(val, 3)}`);
|
|
12237
|
+
}
|
|
12238
|
+
if (showComments) {
|
|
12239
|
+
for (const vf of virtualFieldsWithOptions) {
|
|
12240
|
+
const label = (_e = vf.label) != null ? _e : vf.key;
|
|
12241
|
+
const opts = vf.ui.options.map((o) => `${String(o.value)} (${o.label})`).join(", ");
|
|
12242
|
+
lines.push(`${indent2}# ${label}: ${opts}`);
|
|
12243
|
+
if (vf.description) {
|
|
12244
|
+
lines.push(`${indent2}# ${vf.description}`);
|
|
12245
|
+
}
|
|
12246
|
+
}
|
|
12247
|
+
}
|
|
12248
|
+
const emittedJsonDataKeys = /* @__PURE__ */ new Set();
|
|
12249
|
+
const emittedSecureJsonDataKeys = /* @__PURE__ */ new Set();
|
|
12250
|
+
const jsonDataValues = values == null ? void 0 : values.jsonData;
|
|
12251
|
+
const hasJsonDataFromSchema = jsonDataFieldsByGroup.length > 0;
|
|
12252
|
+
const hasJsonDataFromValues = !isTemplate && jsonDataValues && Object.keys(jsonDataValues).length > 0;
|
|
12253
|
+
if (hasJsonDataFromSchema || hasJsonDataFromValues) {
|
|
12254
|
+
lines.push(`${indent2}jsonData:`);
|
|
12255
|
+
for (const { group, fields: groupFields } of jsonDataFieldsByGroup) {
|
|
12256
|
+
if (showComments && jsonDataFieldsByGroup.length > 1) {
|
|
12257
|
+
lines.push(`${indent3}# --- ${group.title} ---`);
|
|
12258
|
+
}
|
|
12259
|
+
for (const field of groupFields) {
|
|
12260
|
+
const val = values ? getNestedValue(values, "jsonData", field) : templateValue(field);
|
|
12261
|
+
if (val === void 0 || val === null) {
|
|
12262
|
+
continue;
|
|
12263
|
+
}
|
|
12264
|
+
if (!isTemplate && field.defaultValue !== void 0 && val === field.defaultValue) {
|
|
12265
|
+
continue;
|
|
12266
|
+
}
|
|
12267
|
+
emittedJsonDataKeys.add(field.key);
|
|
12268
|
+
if (showComments) {
|
|
12269
|
+
lines.push(fieldComment(field, indent3));
|
|
12270
|
+
}
|
|
12271
|
+
const rendered = yamlValue(val, 4);
|
|
12272
|
+
if (rendered.startsWith("\n")) {
|
|
12273
|
+
lines.push(`${indent3}${field.key}:${rendered}`);
|
|
12274
|
+
} else {
|
|
12275
|
+
lines.push(`${indent3}${field.key}: ${rendered}`);
|
|
12276
|
+
}
|
|
12277
|
+
}
|
|
12278
|
+
}
|
|
12279
|
+
if (!isTemplate && jsonDataValues) {
|
|
12280
|
+
for (const [key, val] of Object.entries(jsonDataValues)) {
|
|
12281
|
+
if (emittedJsonDataKeys.has(key)) {
|
|
12282
|
+
continue;
|
|
12283
|
+
}
|
|
12284
|
+
if (val === void 0 || val === null) {
|
|
12285
|
+
continue;
|
|
12286
|
+
}
|
|
12287
|
+
const rendered = yamlValue(val, 4);
|
|
12288
|
+
if (rendered.startsWith("\n")) {
|
|
12289
|
+
lines.push(`${indent3}${key}:${rendered}`);
|
|
12290
|
+
} else {
|
|
12291
|
+
lines.push(`${indent3}${key}: ${rendered}`);
|
|
12292
|
+
}
|
|
12293
|
+
}
|
|
12294
|
+
}
|
|
12295
|
+
}
|
|
12296
|
+
const secureJsonFields = (_f = values == null ? void 0 : values.secureJsonFields) != null ? _f : {};
|
|
12297
|
+
const inferredSecureKeys = !isTemplate ? inferSecureJsonDataKeys(jsonDataValues) : [];
|
|
12298
|
+
const activeSecureFields = isTemplate ? allSecureJsonDataFields : allSecureJsonDataFields.filter((f) => secureJsonFields[f.key] === true);
|
|
12299
|
+
if (activeSecureFields.length > 0 || inferredSecureKeys.length > 0) {
|
|
12300
|
+
lines.push(`${indent2}secureJsonData:`);
|
|
12301
|
+
for (const field of activeSecureFields) {
|
|
12302
|
+
emittedSecureJsonDataKeys.add(field.key);
|
|
12303
|
+
if (showComments) {
|
|
12304
|
+
lines.push(fieldComment(field, indent3));
|
|
12305
|
+
}
|
|
12306
|
+
lines.push(`${indent3}${field.key}: ${secretPlaceholder(field)}`);
|
|
12307
|
+
}
|
|
12308
|
+
for (const key of inferredSecureKeys) {
|
|
12309
|
+
if (emittedSecureJsonDataKeys.has(key)) {
|
|
12310
|
+
continue;
|
|
12311
|
+
}
|
|
12312
|
+
lines.push(`${indent3}${key}: xxxxxx`);
|
|
12313
|
+
}
|
|
12314
|
+
}
|
|
12315
|
+
return lines.join("\n");
|
|
12316
|
+
}
|
|
12317
|
+
function inferSecureJsonDataKeys(jsonData) {
|
|
12318
|
+
if (!jsonData) {
|
|
12319
|
+
return [];
|
|
12320
|
+
}
|
|
12321
|
+
const keys = [];
|
|
12322
|
+
for (const key of Object.keys(jsonData)) {
|
|
12323
|
+
const match = key.match(/^httpHeaderName(\d+)$/);
|
|
12324
|
+
if (match) {
|
|
12325
|
+
keys.push(`httpHeaderValue${match[1]}`);
|
|
12326
|
+
}
|
|
12327
|
+
}
|
|
12328
|
+
return keys;
|
|
12329
|
+
}
|
|
12330
|
+
function getNestedValue(values, target, field) {
|
|
12331
|
+
const nested = values[target];
|
|
12332
|
+
if (nested && typeof nested === "object") {
|
|
12333
|
+
return nested[field.key];
|
|
12334
|
+
}
|
|
12335
|
+
return void 0;
|
|
12336
|
+
}
|
|
12337
|
+
function datasourceToProvisioningYaml(ds, schema) {
|
|
12338
|
+
if (schema) {
|
|
12339
|
+
return toProvisioningYaml(schema, ds, { comments: false });
|
|
12340
|
+
}
|
|
12341
|
+
const lines = [];
|
|
12342
|
+
lines.push("apiVersion: 1");
|
|
12343
|
+
lines.push("");
|
|
12344
|
+
lines.push("datasources:");
|
|
12345
|
+
lines.push(` - name: ${yamlString(ds.name)}`);
|
|
12346
|
+
if (ds.uid) {
|
|
12347
|
+
lines.push(` uid: ${yamlString(ds.uid)}`);
|
|
12348
|
+
}
|
|
12349
|
+
lines.push(` type: ${yamlString(ds.type)}`);
|
|
12350
|
+
if (ds.url) {
|
|
12351
|
+
lines.push(` url: ${yamlString(ds.url)}`);
|
|
12352
|
+
}
|
|
12353
|
+
if (ds.database) {
|
|
12354
|
+
lines.push(` database: ${yamlString(ds.database)}`);
|
|
12355
|
+
}
|
|
12356
|
+
if (ds.isDefault) {
|
|
12357
|
+
lines.push(" isDefault: true");
|
|
12358
|
+
}
|
|
12359
|
+
if (ds.basicAuth) {
|
|
12360
|
+
lines.push(" basicAuth: true");
|
|
12361
|
+
if (ds.basicAuthUser) {
|
|
12362
|
+
lines.push(` basicAuthUser: ${yamlString(ds.basicAuthUser)}`);
|
|
12363
|
+
}
|
|
12364
|
+
}
|
|
12365
|
+
const jsonData = ds.jsonData;
|
|
12366
|
+
if (jsonData && Object.keys(jsonData).length > 0) {
|
|
12367
|
+
lines.push(" jsonData:");
|
|
12368
|
+
for (const [key, val] of Object.entries(jsonData)) {
|
|
12369
|
+
const rendered = yamlValue(val, 4);
|
|
12370
|
+
if (rendered.startsWith("\n")) {
|
|
12371
|
+
lines.push(` ${key}:${rendered}`);
|
|
12372
|
+
} else {
|
|
12373
|
+
lines.push(` ${key}: ${rendered}`);
|
|
12374
|
+
}
|
|
12375
|
+
}
|
|
12376
|
+
}
|
|
12377
|
+
lines.push(" # secureJsonData: (secrets are not exported \u2014 add manually)");
|
|
12378
|
+
lines.push(" # mySecret: xxxxxx");
|
|
12379
|
+
return lines.join("\n");
|
|
12380
|
+
}
|
|
12381
|
+
|
|
9845
12382
|
exports.AccessoryButton = AccessoryButton;
|
|
9846
12383
|
exports.AdvancedHttpSettings = AdvancedHttpSettings;
|
|
9847
12384
|
exports.Auth = Auth;
|
|
@@ -9861,6 +12398,7 @@ exports.DataLinks = DataLinks;
|
|
|
9861
12398
|
exports.DataSourceDescription = DataSourceDescription;
|
|
9862
12399
|
exports.DataSourcePicker = DataSourcePicker;
|
|
9863
12400
|
exports.DatasetSelector = DatasetSelector;
|
|
12401
|
+
exports.DatasourceConfigWizard = DatasourceConfigWizard;
|
|
9864
12402
|
exports.DatePicker = DatePicker;
|
|
9865
12403
|
exports.DatePickerWithInput = DatePickerWithInput;
|
|
9866
12404
|
exports.DebounceInput = DebounceInput;
|
|
@@ -9896,6 +12434,7 @@ exports.QueryModellerBase = QueryModellerBase;
|
|
|
9896
12434
|
exports.QueryOptionGroup = QueryOptionGroup;
|
|
9897
12435
|
exports.RawQuery = RawQuery;
|
|
9898
12436
|
exports.RunQueryButton = RunQueryButton;
|
|
12437
|
+
exports.SECURE_FIELD_CONFIGURED = SECURE_FIELD_CONFIGURED;
|
|
9899
12438
|
exports.SQLEditor = SQLEditor;
|
|
9900
12439
|
exports.SQLEditorMode = SQLEditorMode;
|
|
9901
12440
|
exports.SQLEditorTestUtils = SQLEditorTestUtils;
|
|
@@ -9909,10 +12448,26 @@ exports.SuggestionKind = SuggestionKind;
|
|
|
9909
12448
|
exports.TLSSettings = TLSSettings;
|
|
9910
12449
|
exports.TableSelector = TableSelector;
|
|
9911
12450
|
exports.TokenType = TokenType;
|
|
12451
|
+
exports.buildDatasourceConfigPayload = buildDatasourceConfigPayload;
|
|
12452
|
+
exports.computeVirtualFieldValues = computeVirtualFieldValues;
|
|
9912
12453
|
exports.convertLegacyAuthProps = convertLegacyAuthProps;
|
|
12454
|
+
exports.datasourceToProvisioningYaml = datasourceToProvisioningYaml;
|
|
12455
|
+
exports.evaluateComputedRead = evaluateComputedRead;
|
|
12456
|
+
exports.expandIndexedPair = expandIndexedPair;
|
|
12457
|
+
exports.fetchExistingValues = fetchExistingValues;
|
|
12458
|
+
exports.flattenIndexedPair = flattenIndexedPair;
|
|
12459
|
+
exports.formKey = formKey;
|
|
9913
12460
|
exports.formatDate = formatDate;
|
|
12461
|
+
exports.generateLLMHint = generateLLMHint;
|
|
12462
|
+
exports.generateTroubleshootingFields = generateTroubleshootingFields;
|
|
9914
12463
|
exports.getStandardSQLCompletionProvider = getStandardSQLCompletionProvider;
|
|
9915
12464
|
exports.grafanaStandardSQLLanguage = language;
|
|
9916
12465
|
exports.grafanaStandardSQLLanguageConf = conf;
|
|
12466
|
+
exports.parseDependsOn = parseDependsOn;
|
|
12467
|
+
exports.resolveActiveOverride = resolveActiveOverride;
|
|
12468
|
+
exports.resolveGroups = resolveGroups;
|
|
12469
|
+
exports.resolveRequiredFieldsGroup = resolveRequiredFieldsGroup;
|
|
12470
|
+
exports.submitDatasourceConfig = submitDatasourceConfig;
|
|
9917
12471
|
exports.toOption = toOption;
|
|
12472
|
+
exports.toProvisioningYaml = toProvisioningYaml;
|
|
9918
12473
|
//# sourceMappingURL=index.cjs.map
|