@grafana/plugin-ui 0.15.1 → 0.16.0-dsconfig.a155abe
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 +11687 -2012
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/index.d.cts +719 -2
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/DatasourceConfigWizard.js +217 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/DatasourceConfigWizard.js.map +1 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/DatasourceErrorBoundary.js +27 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/DatasourceErrorBoundary.js.map +1 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/FieldInput.js +135 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/FieldInput.js.map +1 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/SchemaField.js +80 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/SchemaField.js.map +1 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/SidebarNav.js +54 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/SidebarNav.js.map +1 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/TabLayout.js +155 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/TabLayout.js.map +1 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/cel.js +75 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/cel.js.map +1 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/config.js +262 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/config.js.map +1 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/datasource.js +354 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/datasource.js.map +1 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/fieldUtils.js +138 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/fieldUtils.js.map +1 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/hooks/formInterpreter.js +93 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/hooks/formInterpreter.js.map +1 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/hooks/useDatasourceConfigForm.js +253 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/hooks/useDatasourceConfigForm.js.map +1 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/hooks/useHealthChecks.js +106 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/hooks/useHealthChecks.js.map +1 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/inputs/AuthorizationHeaderField.js +52 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/inputs/AuthorizationHeaderField.js.map +1 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/inputs/ComplexFieldNote.js +26 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/inputs/ComplexFieldNote.js.map +1 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/inputs/FileUploadField.js +106 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/inputs/FileUploadField.js.map +1 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/inputs/IndexedPairEditor.js +124 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/inputs/IndexedPairEditor.js.map +1 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/inputs/ObjectArrayEditor.js +190 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/inputs/ObjectArrayEditor.js.map +1 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/inputs/PdcFieldNote.js +31 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/inputs/PdcFieldNote.js.map +1 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/inputs/PrimitiveInputs.js +103 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/inputs/PrimitiveInputs.js.map +1 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/inputs/SecureFieldInput.js +59 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/inputs/SecureFieldInput.js.map +1 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/inputs/StringArrayInput.js +80 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/inputs/StringArrayInput.js.map +1 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/layoutParts.js +82 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/layoutParts.js.map +1 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/resolvePluginName.js +30 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/resolvePluginName.js.map +1 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/styles.js +340 -0
- package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/styles.js.map +1 -0
- package/dist/esm/index.d.ts +719 -2
- package/dist/esm/index.js +11 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/node_modules/js-yaml/dist/js-yaml.js +3043 -0
- package/dist/esm/node_modules/js-yaml/dist/js-yaml.js.map +1 -0
- package/dist/esm/node_modules/react-hook-form/dist/index.esm.js +2766 -0
- package/dist/esm/node_modules/react-hook-form/dist/index.esm.js.map +1 -0
- package/dist/esm/node_modules/semver/classes/range.js +24 -4
- package/dist/esm/node_modules/semver/classes/range.js.map +1 -1
- package/dist/esm/node_modules/semver/classes/semver.js +19 -2
- package/dist/esm/node_modules/semver/classes/semver.js.map +1 -1
- package/dist/esm/node_modules/semver/functions/diff.js +1 -1
- package/dist/esm/node_modules/semver/functions/diff.js.map +1 -1
- package/dist/esm/node_modules/semver/functions/truncate.js +62 -0
- package/dist/esm/node_modules/semver/functions/truncate.js.map +1 -0
- package/dist/esm/node_modules/semver/index.js +3 -0
- package/dist/esm/node_modules/semver/index.js.map +1 -1
- package/dist/esm/node_modules/semver/internal/re.js +3 -3
- package/dist/esm/node_modules/semver/internal/re.js.map +1 -1
- package/dist/esm/node_modules/semver/ranges/subset.js +3 -3
- package/dist/esm/node_modules/semver/ranges/subset.js.map +1 -1
- package/dist/esm/node_modules/tslib/tslib.es6.js.map +1 -1
- package/dist/esm/schema/utils/constants.js +4 -0
- package/dist/esm/schema/utils/constants.js.map +1 -0
- package/dist/esm/schema/utils/dsconfig.js +97 -0
- package/dist/esm/schema/utils/dsconfig.js.map +1 -0
- package/dist/esm/schema/utils/llm.js +54 -0
- package/dist/esm/schema/utils/llm.js.map +1 -0
- package/dist/esm/schema/utils/packs.js +113 -0
- package/dist/esm/schema/utils/packs.js.map +1 -0
- package/dist/esm/schema/utils/provisioning.js +434 -0
- package/dist/esm/schema/utils/provisioning.js.map +1 -0
- package/dist/esm/schema/utils/registry.js +30 -0
- package/dist/esm/schema/utils/registry.js.map +1 -0
- package/dist/esm/schema/utils/useDatasourceSchema.js +39 -0
- package/dist/esm/schema/utils/useDatasourceSchema.js.map +1 -0
- package/package.json +12 -9
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { formKey, getWatchedValue } from '../config.js';
|
|
2
|
+
import { evaluateCelExpression, extractFieldRefs } from '../cel.js';
|
|
3
|
+
import { isFieldRequired } from '../fieldUtils.js';
|
|
4
|
+
import { SECURE_FIELD_CONFIGURED } from '../datasource.js';
|
|
5
|
+
|
|
6
|
+
function buildFieldCelContext(fieldById, watchedValues) {
|
|
7
|
+
const ctx = {};
|
|
8
|
+
for (const f of fieldById.values()) {
|
|
9
|
+
const fk = formKey(f);
|
|
10
|
+
const val = getWatchedValue(watchedValues, fk);
|
|
11
|
+
if (val !== undefined) {
|
|
12
|
+
const parts = f.id.split(".");
|
|
13
|
+
let current = ctx;
|
|
14
|
+
for (let i = 0; i < parts.length - 1; i++) {
|
|
15
|
+
if (!(parts[i] in current) || typeof current[parts[i]] !== "object" || current[parts[i]] === null) {
|
|
16
|
+
current[parts[i]] = {};
|
|
17
|
+
}
|
|
18
|
+
current = current[parts[i]];
|
|
19
|
+
}
|
|
20
|
+
current[parts[parts.length - 1]] = val;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
return ctx;
|
|
24
|
+
}
|
|
25
|
+
function isFieldVisible(field, fieldById, celContext) {
|
|
26
|
+
function check(f, visited) {
|
|
27
|
+
var _a;
|
|
28
|
+
if (f.kind === "virtual" && !f.ui) {
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
if ((_a = f.tags) == null ? undefined : _a.some((t) => t.startsWith("managed-by:"))) {
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
if (!f.dependsOn) {
|
|
35
|
+
return true;
|
|
36
|
+
}
|
|
37
|
+
const refs = extractFieldRefs(f.dependsOn);
|
|
38
|
+
for (const ref of refs) {
|
|
39
|
+
const depField = fieldById.get(ref);
|
|
40
|
+
if (depField && !visited.has(depField.id)) {
|
|
41
|
+
visited.add(f.id);
|
|
42
|
+
if (!check(depField, visited)) {
|
|
43
|
+
return false;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return evaluateCelExpression(f.dependsOn, celContext);
|
|
48
|
+
}
|
|
49
|
+
return check(field, /* @__PURE__ */ new Set());
|
|
50
|
+
}
|
|
51
|
+
function isFieldDisabled(field, celContext) {
|
|
52
|
+
if (!field.disabledWhen) {
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
return evaluateCelExpression(field.disabledWhen, celContext);
|
|
56
|
+
}
|
|
57
|
+
function isGroupValid(group, args) {
|
|
58
|
+
const { watchedValues, fieldById, celContext, errors, isVisible } = args;
|
|
59
|
+
for (const field of group.fields) {
|
|
60
|
+
if (!isVisible(field)) {
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
if (errors[formKey(field)]) {
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
66
|
+
if (isFieldRequired(field, watchedValues, fieldById, celContext)) {
|
|
67
|
+
const val = getWatchedValue(watchedValues, formKey(field));
|
|
68
|
+
if (val === SECURE_FIELD_CONFIGURED) {
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
|
+
if (val === undefined || val === null || val === "") {
|
|
72
|
+
return false;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return true;
|
|
77
|
+
}
|
|
78
|
+
function groupHasData(group, watchedValues) {
|
|
79
|
+
for (const field of group.fields) {
|
|
80
|
+
const val = getWatchedValue(watchedValues, formKey(field));
|
|
81
|
+
if (val === undefined || val === null || val === "" || val === false) {
|
|
82
|
+
continue;
|
|
83
|
+
}
|
|
84
|
+
if (val === field.defaultValue) {
|
|
85
|
+
continue;
|
|
86
|
+
}
|
|
87
|
+
return true;
|
|
88
|
+
}
|
|
89
|
+
return false;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export { buildFieldCelContext, groupHasData, isFieldDisabled, isFieldVisible, isGroupValid };
|
|
93
|
+
//# sourceMappingURL=formInterpreter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"formInterpreter.js","sources":["../../../../../../src/components/ConfigEditor/DatasourceConfigWizard/hooks/formInterpreter.ts"],"sourcesContent":["/**\n * Pure \"interpreter\" helpers for the datasource config form.\n *\n * These derive UI state (CEL context, field visibility/disabled, group\n * validity/data) purely from a schema snapshot + current form values, with no\n * React or form-library dependency. `useDatasourceConfigForm` wires them into\n * memoized callbacks; keeping them pure makes the logic independently testable.\n */\n\nimport type { ConfigField } from '../../../../schema/schema';\nimport { formKey, getWatchedValue, type ResolvedGroup } from '../config';\nimport { extractFieldRefs, evaluateCelExpression } from '../cel';\nimport { isFieldRequired } from '../fieldUtils';\nimport { SECURE_FIELD_CONFIGURED } from '../datasource';\n\n/**\n * Build a CEL-compatible nested context from flat watched values + field ID mappings.\n * Field IDs like \"jsonData.auth_method\" become { jsonData: { auth_method: value } }.\n */\nexport function buildFieldCelContext(\n fieldById: Map<string, ConfigField>,\n watchedValues: Record<string, unknown>\n): Record<string, unknown> {\n const ctx: Record<string, unknown> = {};\n for (const f of fieldById.values()) {\n const fk = formKey(f);\n const val = getWatchedValue(watchedValues, fk);\n if (val !== undefined) {\n // Set by field ID path (e.g. \"jsonData.oauth2.oauth2_type\")\n const parts = f.id.split('.');\n let current = ctx as Record<string, unknown>;\n for (let i = 0; i < parts.length - 1; i++) {\n if (!(parts[i] in current) || typeof current[parts[i]] !== 'object' || current[parts[i]] === null) {\n current[parts[i]] = {};\n }\n current = current[parts[i]] as Record<string, unknown>;\n }\n current[parts[parts.length - 1]] = val;\n }\n }\n return ctx;\n}\n\n/**\n * Whether a field should be shown. Hidden when it's a virtual field without UI,\n * managed by an effect, or its (transitive) `dependsOn` chain evaluates falsy.\n */\nexport function isFieldVisible(\n field: ConfigField,\n fieldById: Map<string, ConfigField>,\n celContext: Record<string, unknown>\n): boolean {\n // Inner recursive helper with a visited set to guard against circular deps.\n function check(f: ConfigField, visited: Set<string>): boolean {\n if (f.kind === 'virtual' && !f.ui) {\n return false;\n }\n if (f.tags?.some((t) => t.startsWith('managed-by:'))) {\n return false;\n }\n if (!f.dependsOn) {\n return true;\n }\n\n // Transitive visibility: all referenced dependency fields must themselves be visible.\n const refs = extractFieldRefs(f.dependsOn);\n for (const ref of refs) {\n const depField = fieldById.get(ref);\n if (depField && !visited.has(depField.id)) {\n visited.add(f.id);\n if (!check(depField, visited)) {\n return false;\n }\n }\n }\n\n // Evaluate the full CEL expression\n return evaluateCelExpression(f.dependsOn, celContext);\n }\n return check(field, new Set<string>());\n}\n\n/** Whether a field is currently disabled via its `disabledWhen` CEL expression. */\nexport function isFieldDisabled(field: ConfigField, celContext: Record<string, unknown>): boolean {\n if (!field.disabledWhen) {\n return false;\n }\n return evaluateCelExpression(field.disabledWhen, celContext);\n}\n\n/** Check whether all visible required fields in a group have a value (and no errors). */\nexport function isGroupValid(\n group: ResolvedGroup,\n args: {\n watchedValues: Record<string, unknown>;\n fieldById: Map<string, ConfigField>;\n celContext: Record<string, unknown>;\n errors: Record<string, unknown>;\n isVisible: (field: ConfigField) => boolean;\n }\n): boolean {\n const { watchedValues, fieldById, celContext, errors, isVisible } = args;\n for (const field of group.fields) {\n if (!isVisible(field)) {\n continue;\n }\n if (errors[formKey(field)]) {\n return false;\n }\n if (isFieldRequired(field, watchedValues, fieldById, celContext)) {\n const val = getWatchedValue(watchedValues, formKey(field));\n if (val === SECURE_FIELD_CONFIGURED) {\n continue;\n }\n if (val === undefined || val === null || val === '') {\n return false;\n }\n }\n }\n return true;\n}\n\n/** Whether a group has any field with a non-default, non-empty value. */\nexport function groupHasData(group: ResolvedGroup, watchedValues: Record<string, unknown>): boolean {\n for (const field of group.fields) {\n const val = getWatchedValue(watchedValues, formKey(field));\n if (val === undefined || val === null || val === '' || val === false) {\n continue;\n }\n if (val === field.defaultValue) {\n continue;\n }\n return true;\n }\n return false;\n}\n"],"names":[],"mappings":"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"}
|
package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/hooks/useDatasourceConfigForm.js
ADDED
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
import { useState, useMemo, useEffect, useRef, useCallback } from 'react';
|
|
2
|
+
import { useForm } from '../../../../node_modules/react-hook-form/dist/index.esm.js';
|
|
3
|
+
import { resolveGroups, resolveRequiredFieldsGroup, formKey, computeVirtualFieldValues, getWatchedValue, parseDependsOn, evaluateDependsOn } from '../config.js';
|
|
4
|
+
import { fetchExistingValues, submitDatasourceConfig } from '../datasource.js';
|
|
5
|
+
import { evaluateEffectCondition } from '../fieldUtils.js';
|
|
6
|
+
import { buildFieldCelContext, isFieldVisible, isGroupValid, isFieldDisabled, groupHasData } from './formInterpreter.js';
|
|
7
|
+
|
|
8
|
+
function useDatasourceConfigForm({ schema, dsUid, onSuccess, onSaving }) {
|
|
9
|
+
const [submitting, setSubmitting] = useState(false);
|
|
10
|
+
const [submitError, setSubmitError] = useState(null);
|
|
11
|
+
const [initializing, setInitializing] = useState(true);
|
|
12
|
+
const [fetchError, setFetchError] = useState(null);
|
|
13
|
+
const [detectedReadOnly, setDetectedReadOnly] = useState(false);
|
|
14
|
+
const readOnly = detectedReadOnly;
|
|
15
|
+
const resolvedGroups = useMemo(() => {
|
|
16
|
+
const groups = resolveGroups(schema);
|
|
17
|
+
const requiredGroup = resolveRequiredFieldsGroup(schema);
|
|
18
|
+
if (!requiredGroup) {
|
|
19
|
+
return groups;
|
|
20
|
+
}
|
|
21
|
+
return [requiredGroup, ...groups];
|
|
22
|
+
}, [schema]);
|
|
23
|
+
const fieldById = useMemo(() => {
|
|
24
|
+
const m = /* @__PURE__ */ new Map();
|
|
25
|
+
for (const f of schema.fields) {
|
|
26
|
+
m.set(f.id, f);
|
|
27
|
+
}
|
|
28
|
+
return m;
|
|
29
|
+
}, [schema.fields]);
|
|
30
|
+
const httpHeadersField = useMemo(
|
|
31
|
+
() => {
|
|
32
|
+
var _a;
|
|
33
|
+
return (_a = schema.fields.find((f) => {
|
|
34
|
+
var _a2;
|
|
35
|
+
return f.key === "httpHeaders" && ((_a2 = f.storage) == null ? undefined : _a2.type) === "indexedPair";
|
|
36
|
+
})) != null ? _a : null;
|
|
37
|
+
},
|
|
38
|
+
[schema.fields]
|
|
39
|
+
);
|
|
40
|
+
const allStorageFields = useMemo(
|
|
41
|
+
() => schema.fields.filter((f) => f.kind !== "virtual" && !f.isItemField && f.target),
|
|
42
|
+
[schema.fields]
|
|
43
|
+
);
|
|
44
|
+
const {
|
|
45
|
+
control,
|
|
46
|
+
handleSubmit,
|
|
47
|
+
watch,
|
|
48
|
+
reset,
|
|
49
|
+
trigger,
|
|
50
|
+
setValue,
|
|
51
|
+
formState: { errors }
|
|
52
|
+
} = useForm({ mode: "onChange" });
|
|
53
|
+
const fieldsWithEffects = useMemo(() => {
|
|
54
|
+
const result = [];
|
|
55
|
+
for (const field of schema.fields) {
|
|
56
|
+
if (!field.effects || field.effects.length === 0) {
|
|
57
|
+
continue;
|
|
58
|
+
}
|
|
59
|
+
const mapped = field.effects.map((eff) => ({
|
|
60
|
+
when: eff.when,
|
|
61
|
+
targets: Object.entries(eff.set).map(([targetId, val]) => {
|
|
62
|
+
const targetField = fieldById.get(targetId);
|
|
63
|
+
return { key: targetField ? formKey(targetField) : targetId, value: val };
|
|
64
|
+
})
|
|
65
|
+
}));
|
|
66
|
+
result.push({ sourceKey: formKey(field), effects: mapped });
|
|
67
|
+
}
|
|
68
|
+
return result;
|
|
69
|
+
}, [schema.fields, fieldById]);
|
|
70
|
+
useEffect(() => {
|
|
71
|
+
let cancelled = false;
|
|
72
|
+
fetchExistingValues(dsUid, allStorageFields).then((result) => {
|
|
73
|
+
if (cancelled) {
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
if (result.error) {
|
|
77
|
+
setFetchError(result.error);
|
|
78
|
+
setInitializing(false);
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
if (result.readOnly) {
|
|
82
|
+
setDetectedReadOnly(true);
|
|
83
|
+
}
|
|
84
|
+
const defaults = {};
|
|
85
|
+
for (const field of allStorageFields) {
|
|
86
|
+
if (field.defaultValue !== undefined) {
|
|
87
|
+
defaults[formKey(field)] = field.defaultValue;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
const merged = { ...defaults, ...result.values };
|
|
91
|
+
const virtualValues = computeVirtualFieldValues(schema, merged);
|
|
92
|
+
reset({ ...merged, ...virtualValues });
|
|
93
|
+
setInitializing(false);
|
|
94
|
+
});
|
|
95
|
+
return () => {
|
|
96
|
+
cancelled = true;
|
|
97
|
+
};
|
|
98
|
+
}, [dsUid, allStorageFields, schema, reset]);
|
|
99
|
+
const watchedValues = watch();
|
|
100
|
+
const prevEffectValuesRef = useRef({});
|
|
101
|
+
useEffect(() => {
|
|
102
|
+
if (initializing) {
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
for (const { sourceKey, effects } of fieldsWithEffects) {
|
|
106
|
+
const currentVal = getWatchedValue(watchedValues, sourceKey);
|
|
107
|
+
const prevVal = prevEffectValuesRef.current[sourceKey];
|
|
108
|
+
if (currentVal === prevVal) {
|
|
109
|
+
continue;
|
|
110
|
+
}
|
|
111
|
+
prevEffectValuesRef.current[sourceKey] = currentVal;
|
|
112
|
+
for (const eff of effects) {
|
|
113
|
+
if (evaluateEffectCondition(eff.when, currentVal)) {
|
|
114
|
+
for (const { key, value } of eff.targets) {
|
|
115
|
+
setValue(key, value);
|
|
116
|
+
}
|
|
117
|
+
break;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}, [watchedValues, fieldsWithEffects, initializing, setValue]);
|
|
122
|
+
const fieldsWithOverrideDefaults = useMemo(() => {
|
|
123
|
+
const result = [];
|
|
124
|
+
for (const field of schema.fields) {
|
|
125
|
+
if (!field.overrides || field.overrides.length === 0) {
|
|
126
|
+
continue;
|
|
127
|
+
}
|
|
128
|
+
const ovs = field.overrides.filter((ov) => ov.defaultValue !== undefined).map((ov) => {
|
|
129
|
+
const parsed = parseDependsOn(ov.when);
|
|
130
|
+
if (!parsed) {
|
|
131
|
+
return null;
|
|
132
|
+
}
|
|
133
|
+
const depField = fieldById.get(parsed.field);
|
|
134
|
+
return {
|
|
135
|
+
depKey: depField ? formKey(depField) : parsed.field,
|
|
136
|
+
depValue: parsed.value,
|
|
137
|
+
negate: parsed.negate,
|
|
138
|
+
defaultValue: ov.defaultValue
|
|
139
|
+
};
|
|
140
|
+
}).filter(Boolean);
|
|
141
|
+
if (ovs.length > 0) {
|
|
142
|
+
result.push({ targetKey: formKey(field), fieldDefault: field.defaultValue, overrides: ovs });
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
return result;
|
|
146
|
+
}, [schema.fields, fieldById]);
|
|
147
|
+
const prevOverrideDepRef = useRef({});
|
|
148
|
+
useEffect(() => {
|
|
149
|
+
var _a;
|
|
150
|
+
if (initializing) {
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
for (const { targetKey, fieldDefault, overrides } of fieldsWithOverrideDefaults) {
|
|
154
|
+
for (const ov of overrides) {
|
|
155
|
+
const currentDepVal = String((_a = getWatchedValue(watchedValues, ov.depKey)) != null ? _a : "");
|
|
156
|
+
const trackKey = `${targetKey}::${ov.depKey}`;
|
|
157
|
+
const prevDepVal = prevOverrideDepRef.current[trackKey];
|
|
158
|
+
if (currentDepVal === prevDepVal) {
|
|
159
|
+
continue;
|
|
160
|
+
}
|
|
161
|
+
prevOverrideDepRef.current[trackKey] = currentDepVal;
|
|
162
|
+
const active = evaluateDependsOn({ value: ov.depValue, negate: ov.negate }, currentDepVal);
|
|
163
|
+
const wasActive = prevDepVal !== undefined && evaluateDependsOn({ value: ov.depValue, negate: ov.negate }, prevDepVal);
|
|
164
|
+
if (active) {
|
|
165
|
+
setValue(targetKey, ov.defaultValue);
|
|
166
|
+
} else if (wasActive && fieldDefault !== undefined) {
|
|
167
|
+
setValue(targetKey, fieldDefault);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}, [watchedValues, fieldsWithOverrideDefaults, initializing, setValue]);
|
|
172
|
+
const celContext = useMemo(() => buildFieldCelContext(fieldById, watchedValues), [watchedValues, fieldById]);
|
|
173
|
+
const isFieldVisible$1 = useCallback(
|
|
174
|
+
(field) => isFieldVisible(field, fieldById, celContext),
|
|
175
|
+
[celContext, fieldById]
|
|
176
|
+
);
|
|
177
|
+
const onSubmit = useCallback(
|
|
178
|
+
async (data) => {
|
|
179
|
+
setSubmitting(true);
|
|
180
|
+
setSubmitError(null);
|
|
181
|
+
onSaving == null ? undefined : onSaving(true);
|
|
182
|
+
const minDelay = new Promise((r) => setTimeout(r, 2e3));
|
|
183
|
+
try {
|
|
184
|
+
await submitDatasourceConfig(dsUid, data, allStorageFields, isFieldVisible$1);
|
|
185
|
+
const [refreshed] = await Promise.all([fetchExistingValues(dsUid, allStorageFields), minDelay]);
|
|
186
|
+
const defaults = {};
|
|
187
|
+
for (const field of allStorageFields) {
|
|
188
|
+
if (field.defaultValue !== void 0) {
|
|
189
|
+
defaults[formKey(field)] = field.defaultValue;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
const merged = { ...defaults, ...refreshed.values };
|
|
193
|
+
const virtualValues = computeVirtualFieldValues(schema, merged);
|
|
194
|
+
reset({ ...merged, ...virtualValues });
|
|
195
|
+
onSuccess("UPDATED", "Configuration saved.");
|
|
196
|
+
} catch (err) {
|
|
197
|
+
await minDelay;
|
|
198
|
+
setSubmitError(err instanceof Error ? err.message : "Failed to update datasource");
|
|
199
|
+
} finally {
|
|
200
|
+
setSubmitting(false);
|
|
201
|
+
onSaving == null ? undefined : onSaving(false);
|
|
202
|
+
}
|
|
203
|
+
},
|
|
204
|
+
[dsUid, allStorageFields, isFieldVisible$1, schema, reset, onSuccess, onSaving]
|
|
205
|
+
);
|
|
206
|
+
const isGroupValid$1 = useCallback(
|
|
207
|
+
(group) => isGroupValid(group, {
|
|
208
|
+
watchedValues,
|
|
209
|
+
fieldById,
|
|
210
|
+
celContext,
|
|
211
|
+
errors,
|
|
212
|
+
isVisible: isFieldVisible$1
|
|
213
|
+
}),
|
|
214
|
+
[errors, watchedValues, fieldById, celContext, isFieldVisible$1]
|
|
215
|
+
);
|
|
216
|
+
const isFieldDisabled$1 = useCallback(
|
|
217
|
+
(field) => isFieldDisabled(field, celContext),
|
|
218
|
+
[celContext]
|
|
219
|
+
);
|
|
220
|
+
const groupHasData$1 = useCallback(
|
|
221
|
+
(group) => groupHasData(group, watchedValues),
|
|
222
|
+
[watchedValues]
|
|
223
|
+
);
|
|
224
|
+
return {
|
|
225
|
+
// Schema
|
|
226
|
+
resolvedGroups,
|
|
227
|
+
fieldById,
|
|
228
|
+
httpHeadersField,
|
|
229
|
+
// Form
|
|
230
|
+
control,
|
|
231
|
+
handleSubmit,
|
|
232
|
+
trigger,
|
|
233
|
+
errors,
|
|
234
|
+
watchedValues,
|
|
235
|
+
celContext,
|
|
236
|
+
// State
|
|
237
|
+
initializing,
|
|
238
|
+
fetchError,
|
|
239
|
+
submitting,
|
|
240
|
+
submitError,
|
|
241
|
+
readOnly,
|
|
242
|
+
// Callbacks
|
|
243
|
+
isFieldVisible: isFieldVisible$1,
|
|
244
|
+
isFieldDisabled: isFieldDisabled$1,
|
|
245
|
+
isGroupValid: isGroupValid$1,
|
|
246
|
+
groupHasData: groupHasData$1,
|
|
247
|
+
onSubmit,
|
|
248
|
+
setValue
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
export { useDatasourceConfigForm };
|
|
253
|
+
//# sourceMappingURL=useDatasourceConfigForm.js.map
|
package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/hooks/useDatasourceConfigForm.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useDatasourceConfigForm.js","sources":["../../../../../../src/components/ConfigEditor/DatasourceConfigWizard/hooks/useDatasourceConfigForm.ts"],"sourcesContent":["import { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport { useForm } from 'react-hook-form';\nimport type { ConfigField, DatasourceConfigSchema } from '../../../../schema/schema';\nimport {\n resolveGroups,\n resolveRequiredFieldsGroup,\n parseDependsOn,\n evaluateDependsOn,\n computeVirtualFieldValues,\n formKey,\n getWatchedValue,\n type ResolvedGroup,\n} from '../config';\nimport { fetchExistingValues, submitDatasourceConfig, type FormValues } from '../datasource';\nimport { evaluateEffectCondition } from '../fieldUtils';\nimport {\n buildFieldCelContext,\n isFieldVisible as isFieldVisibleImpl,\n isFieldDisabled as isFieldDisabledImpl,\n isGroupValid as isGroupValidImpl,\n groupHasData as groupHasDataImpl,\n} from './formInterpreter';\n\nexport type DatasourceConfigFormOptions = {\n schema: DatasourceConfigSchema;\n dsUid: string;\n onSuccess: (status: string, message?: string) => void;\n onSaving?: (saving: boolean) => void;\n};\n\nexport type { ResolvedGroup };\n\nexport function useDatasourceConfigForm({ schema, dsUid, onSuccess, onSaving }: DatasourceConfigFormOptions) {\n const [submitting, setSubmitting] = useState(false);\n const [submitError, setSubmitError] = useState<string | null>(null);\n const [initializing, setInitializing] = useState(true);\n const [fetchError, setFetchError] = useState<string | null>(null);\n const [detectedReadOnly, setDetectedReadOnly] = useState(false);\n const readOnly = detectedReadOnly;\n\n const resolvedGroups: ResolvedGroup[] = useMemo(() => {\n const groups = resolveGroups(schema);\n const requiredGroup = resolveRequiredFieldsGroup(schema);\n if (!requiredGroup) {\n return groups;\n }\n return [requiredGroup, ...groups];\n }, [schema]);\n\n const fieldById = useMemo(() => {\n const m = new Map<string, ConfigField>();\n for (const f of schema.fields) {\n m.set(f.id, f);\n }\n return m;\n }, [schema.fields]);\n\n const httpHeadersField = useMemo(\n () => schema.fields.find((f) => f.key === 'httpHeaders' && f.storage?.type === 'indexedPair') ?? null,\n [schema.fields]\n );\n\n const allStorageFields = useMemo(\n () => schema.fields.filter((f) => f.kind !== 'virtual' && !f.isItemField && f.target),\n [schema.fields]\n );\n\n const {\n control,\n handleSubmit,\n watch,\n reset,\n trigger,\n setValue,\n formState: { errors },\n } = useForm<FormValues>({ mode: 'onChange' });\n\n const fieldsWithEffects = useMemo(() => {\n const result: Array<{\n sourceKey: string;\n effects: Array<{ when: string; targets: Array<{ key: string; value: unknown }> }>;\n }> = [];\n for (const field of schema.fields) {\n if (!field.effects || field.effects.length === 0) {\n continue;\n }\n const mapped = field.effects.map((eff) => ({\n when: eff.when,\n targets: Object.entries(eff.set).map(([targetId, val]) => {\n const targetField = fieldById.get(targetId);\n return { key: targetField ? formKey(targetField) : targetId, value: val };\n }),\n }));\n result.push({ sourceKey: formKey(field), effects: mapped });\n }\n return result;\n }, [schema.fields, fieldById]);\n\n // Load existing values on mount\n useEffect(() => {\n let cancelled = false;\n fetchExistingValues(dsUid, allStorageFields).then((result) => {\n if (cancelled) {\n return;\n }\n if (result.error) {\n setFetchError(result.error);\n setInitializing(false);\n return;\n }\n if (result.readOnly) {\n setDetectedReadOnly(true);\n }\n const defaults: FormValues = {};\n for (const field of allStorageFields) {\n if (field.defaultValue !== undefined) {\n defaults[formKey(field)] = field.defaultValue;\n }\n }\n const merged = { ...defaults, ...result.values };\n const virtualValues = computeVirtualFieldValues(schema, merged);\n reset({ ...merged, ...virtualValues });\n setInitializing(false);\n });\n return () => {\n cancelled = true;\n };\n }, [dsUid, allStorageFields, schema, reset]);\n\n const watchedValues = watch();\n\n // Apply field effects\n const prevEffectValuesRef = useRef<Record<string, unknown>>({});\n useEffect(() => {\n if (initializing) {\n return;\n }\n for (const { sourceKey, effects } of fieldsWithEffects) {\n const currentVal = getWatchedValue(watchedValues, sourceKey);\n const prevVal = prevEffectValuesRef.current[sourceKey];\n if (currentVal === prevVal) {\n continue;\n }\n prevEffectValuesRef.current[sourceKey] = currentVal;\n for (const eff of effects) {\n if (evaluateEffectCondition(eff.when, currentVal)) {\n for (const { key, value } of eff.targets) {\n setValue(key, value);\n }\n break;\n }\n }\n }\n }, [watchedValues, fieldsWithEffects, initializing, setValue]);\n\n // Override defaults\n const fieldsWithOverrideDefaults = useMemo(() => {\n const result: Array<{\n targetKey: string;\n fieldDefault: unknown;\n overrides: Array<{ depKey: string; depValue: string; negate: boolean; defaultValue: unknown }>;\n }> = [];\n for (const field of schema.fields) {\n if (!field.overrides || field.overrides.length === 0) {\n continue;\n }\n const ovs = field.overrides\n .filter((ov) => ov.defaultValue !== undefined)\n .map((ov) => {\n const parsed = parseDependsOn(ov.when);\n if (!parsed) {\n return null;\n }\n const depField = fieldById.get(parsed.field);\n return {\n depKey: depField ? formKey(depField) : parsed.field,\n depValue: parsed.value,\n negate: parsed.negate,\n defaultValue: ov.defaultValue,\n };\n })\n .filter(Boolean) as Array<{ depKey: string; depValue: string; negate: boolean; defaultValue: unknown }>;\n if (ovs.length > 0) {\n result.push({ targetKey: formKey(field), fieldDefault: field.defaultValue, overrides: ovs });\n }\n }\n return result;\n }, [schema.fields, fieldById]);\n\n const prevOverrideDepRef = useRef<Record<string, string>>({});\n useEffect(() => {\n if (initializing) {\n return;\n }\n for (const { targetKey, fieldDefault, overrides } of fieldsWithOverrideDefaults) {\n for (const ov of overrides) {\n const currentDepVal = String(getWatchedValue(watchedValues, ov.depKey) ?? '');\n const trackKey = `${targetKey}::${ov.depKey}`;\n const prevDepVal = prevOverrideDepRef.current[trackKey];\n if (currentDepVal === prevDepVal) {\n continue;\n }\n prevOverrideDepRef.current[trackKey] = currentDepVal;\n const active = evaluateDependsOn({ value: ov.depValue, negate: ov.negate }, currentDepVal);\n const wasActive =\n prevDepVal !== undefined && evaluateDependsOn({ value: ov.depValue, negate: ov.negate }, prevDepVal);\n if (active) {\n setValue(targetKey, ov.defaultValue);\n } else if (wasActive && fieldDefault !== undefined) {\n setValue(targetKey, fieldDefault);\n }\n }\n }\n }, [watchedValues, fieldsWithOverrideDefaults, initializing, setValue]);\n\n // Build a CEL-compatible nested context from flat watched values + field ID mappings.\n const celContext = useMemo(() => buildFieldCelContext(fieldById, watchedValues), [watchedValues, fieldById]);\n\n const isFieldVisible = useCallback(\n (field: ConfigField): boolean => isFieldVisibleImpl(field, fieldById, celContext),\n [celContext, fieldById]\n );\n\n const onSubmit = useCallback(\n async (data: FormValues) => {\n setSubmitting(true);\n setSubmitError(null);\n onSaving?.(true);\n const minDelay = new Promise((r) => setTimeout(r, 2000));\n\n try {\n await submitDatasourceConfig(dsUid, data, allStorageFields, isFieldVisible);\n const [refreshed] = await Promise.all([fetchExistingValues(dsUid, allStorageFields), minDelay]);\n const defaults: FormValues = {};\n for (const field of allStorageFields) {\n if (field.defaultValue !== undefined) {\n defaults[formKey(field)] = field.defaultValue;\n }\n }\n const merged = { ...defaults, ...refreshed.values };\n const virtualValues = computeVirtualFieldValues(schema, merged);\n reset({ ...merged, ...virtualValues });\n onSuccess('UPDATED', 'Configuration saved.');\n } catch (err: unknown) {\n await minDelay;\n setSubmitError(err instanceof Error ? err.message : 'Failed to update datasource');\n } finally {\n setSubmitting(false);\n onSaving?.(false);\n }\n },\n [dsUid, allStorageFields, isFieldVisible, schema, reset, onSuccess, onSaving]\n );\n\n const isGroupValid = useCallback(\n (group: ResolvedGroup): boolean =>\n isGroupValidImpl(group, {\n watchedValues,\n fieldById,\n celContext,\n errors: errors as Record<string, unknown>,\n isVisible: isFieldVisible,\n }),\n [errors, watchedValues, fieldById, celContext, isFieldVisible]\n );\n\n const isFieldDisabled = useCallback(\n (field: ConfigField): boolean => isFieldDisabledImpl(field, celContext),\n [celContext]\n );\n\n const groupHasData = useCallback(\n (group: ResolvedGroup): boolean => groupHasDataImpl(group, watchedValues),\n [watchedValues]\n );\n\n return {\n // Schema\n resolvedGroups,\n fieldById,\n httpHeadersField,\n // Form\n control,\n handleSubmit,\n trigger,\n errors,\n watchedValues,\n celContext,\n // State\n initializing,\n fetchError,\n submitting,\n submitError,\n readOnly,\n // Callbacks\n isFieldVisible,\n isFieldDisabled,\n isGroupValid,\n groupHasData,\n onSubmit,\n setValue,\n };\n}\n"],"names":["_a","isFieldVisible","isFieldVisibleImpl","isGroupValid","isGroupValidImpl","isFieldDisabled","isFieldDisabledImpl","groupHasData","groupHasDataImpl"],"mappings":"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"}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { useState, useRef, useCallback } from 'react';
|
|
2
|
+
import { getBackendSrv } from '@grafana/runtime';
|
|
3
|
+
|
|
4
|
+
const MAX_CONCURRENCY = 5;
|
|
5
|
+
function useHealthChecks() {
|
|
6
|
+
const [healthMap, setHealthMap] = useState({});
|
|
7
|
+
const queueRef = useRef([]);
|
|
8
|
+
const activeRef = useRef(0);
|
|
9
|
+
const mountedRef = useRef(true);
|
|
10
|
+
const everQueuedRef = useRef(/* @__PURE__ */ new Set());
|
|
11
|
+
const checkOne = useCallback(async (uid) => {
|
|
12
|
+
if (!mountedRef.current) {
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
setHealthMap((prev) => ({ ...prev, [uid]: { state: "checking" } }));
|
|
16
|
+
try {
|
|
17
|
+
const result = await getBackendSrv().get(
|
|
18
|
+
`/api/datasources/uid/${uid}/health`,
|
|
19
|
+
void 0,
|
|
20
|
+
void 0,
|
|
21
|
+
{ showErrorAlert: false }
|
|
22
|
+
);
|
|
23
|
+
if (!mountedRef.current) {
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
setHealthMap((prev) => {
|
|
27
|
+
var _a;
|
|
28
|
+
return {
|
|
29
|
+
...prev,
|
|
30
|
+
[uid]: { state: "done", status: (_a = result.status) != null ? _a : "OK", message: result.message }
|
|
31
|
+
};
|
|
32
|
+
});
|
|
33
|
+
} catch (error) {
|
|
34
|
+
if (!mountedRef.current) {
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
let status = "ERROR";
|
|
38
|
+
let message = "";
|
|
39
|
+
if (error && typeof error === "object" && "data" in error) {
|
|
40
|
+
const data = error.data;
|
|
41
|
+
if (data == null ? undefined : data.status) {
|
|
42
|
+
status = data.status;
|
|
43
|
+
}
|
|
44
|
+
if (data == null ? undefined : data.message) {
|
|
45
|
+
message = data.message;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
if (!message) {
|
|
49
|
+
message = error instanceof Error ? error.message : String(error);
|
|
50
|
+
}
|
|
51
|
+
setHealthMap((prev) => ({
|
|
52
|
+
...prev,
|
|
53
|
+
[uid]: { state: "done", status, message }
|
|
54
|
+
}));
|
|
55
|
+
}
|
|
56
|
+
}, []);
|
|
57
|
+
const processQueue = useCallback(() => {
|
|
58
|
+
while (activeRef.current < MAX_CONCURRENCY && queueRef.current.length > 0) {
|
|
59
|
+
const uid = queueRef.current.shift();
|
|
60
|
+
activeRef.current++;
|
|
61
|
+
checkOne(uid).finally(() => {
|
|
62
|
+
activeRef.current--;
|
|
63
|
+
processQueue();
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
}, [checkOne]);
|
|
67
|
+
const checkUids = useCallback(
|
|
68
|
+
(uids) => {
|
|
69
|
+
const toCheck = [];
|
|
70
|
+
for (const uid of uids) {
|
|
71
|
+
if (everQueuedRef.current.has(uid)) {
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
everQueuedRef.current.add(uid);
|
|
75
|
+
toCheck.push(uid);
|
|
76
|
+
}
|
|
77
|
+
if (toCheck.length === 0) {
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
setHealthMap((prev) => {
|
|
81
|
+
const next = { ...prev };
|
|
82
|
+
for (const uid of toCheck) {
|
|
83
|
+
next[uid] = { state: "pending" };
|
|
84
|
+
}
|
|
85
|
+
return next;
|
|
86
|
+
});
|
|
87
|
+
queueRef.current.push(...toCheck);
|
|
88
|
+
processQueue();
|
|
89
|
+
},
|
|
90
|
+
[processQueue]
|
|
91
|
+
);
|
|
92
|
+
const retry = useCallback(
|
|
93
|
+
(uid) => {
|
|
94
|
+
everQueuedRef.current.delete(uid);
|
|
95
|
+
everQueuedRef.current.add(uid);
|
|
96
|
+
setHealthMap((prev) => ({ ...prev, [uid]: { state: "pending" } }));
|
|
97
|
+
queueRef.current.push(uid);
|
|
98
|
+
processQueue();
|
|
99
|
+
},
|
|
100
|
+
[processQueue]
|
|
101
|
+
);
|
|
102
|
+
return { healthMap, checkUids, retry };
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export { useHealthChecks };
|
|
106
|
+
//# sourceMappingURL=useHealthChecks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useHealthChecks.js","sources":["../../../../../../src/components/ConfigEditor/DatasourceConfigWizard/hooks/useHealthChecks.ts"],"sourcesContent":["import { useCallback, useRef, useState } from 'react';\nimport { getBackendSrv } from '@grafana/runtime';\nimport type { TestDataSourceResponse } from '@grafana/data';\n\nconst MAX_CONCURRENCY = 5;\n\nexport type HealthState = 'pending' | 'checking' | 'done';\n\nexport interface DatasourceHealth {\n state: HealthState;\n status?: string;\n message?: string;\n}\n\n/**\n * Health check hook — on-demand only.\n * Call `checkUids(uids)` to trigger checks for specific UIDs.\n * Call `retry(uid)` to force re-check a single UID.\n * UIDs that have already been checked (or are in-flight) are automatically skipped.\n */\nexport function useHealthChecks() {\n const [healthMap, setHealthMap] = useState<Record<string, DatasourceHealth>>({});\n const queueRef = useRef<string[]>([]);\n const activeRef = useRef(0);\n const mountedRef = useRef(true);\n // Permanent set of UIDs that have ever been queued — prevents re-checking on re-render.\n // Only `retry()` removes from this set to allow explicit re-check.\n const everQueuedRef = useRef(new Set<string>());\n\n const checkOne = useCallback(async (uid: string) => {\n if (!mountedRef.current) {\n return;\n }\n setHealthMap((prev) => ({ ...prev, [uid]: { state: 'checking' } }));\n\n try {\n const result: TestDataSourceResponse = await getBackendSrv().get(\n `/api/datasources/uid/${uid}/health`,\n undefined,\n undefined,\n { showErrorAlert: false }\n );\n if (!mountedRef.current) {\n return;\n }\n setHealthMap((prev) => ({\n ...prev,\n [uid]: { state: 'done', status: result.status ?? 'OK', message: result.message },\n }));\n } catch (error: unknown) {\n if (!mountedRef.current) {\n return;\n }\n let status = 'ERROR';\n let message = '';\n if (error && typeof error === 'object' && 'data' in error) {\n const data = (error as { data?: { status?: string; message?: string } }).data;\n if (data?.status) {\n status = data.status;\n }\n if (data?.message) {\n message = data.message;\n }\n }\n if (!message) {\n message = error instanceof Error ? error.message : String(error);\n }\n setHealthMap((prev) => ({\n ...prev,\n [uid]: { state: 'done', status, message },\n }));\n }\n }, []);\n\n const processQueue = useCallback(() => {\n while (activeRef.current < MAX_CONCURRENCY && queueRef.current.length > 0) {\n const uid = queueRef.current.shift()!;\n activeRef.current++;\n checkOne(uid).finally(() => {\n activeRef.current--;\n processQueue();\n });\n }\n }, [checkOne]);\n\n /**\n * Queue health checks for a batch of UIDs.\n * Skips UIDs that have ever been queued before (idempotent — safe to call repeatedly).\n */\n const checkUids = useCallback(\n (uids: string[]) => {\n const toCheck: string[] = [];\n for (const uid of uids) {\n if (everQueuedRef.current.has(uid)) {\n continue;\n }\n everQueuedRef.current.add(uid);\n toCheck.push(uid);\n }\n if (toCheck.length === 0) {\n return;\n }\n setHealthMap((prev) => {\n const next = { ...prev };\n for (const uid of toCheck) {\n next[uid] = { state: 'pending' };\n }\n return next;\n });\n queueRef.current.push(...toCheck);\n processQueue();\n },\n [processQueue]\n );\n\n /**\n * Force re-check a single UID (e.g. after wizard save).\n * Clears the \"ever queued\" flag so checkUids won't block it.\n */\n const retry = useCallback(\n (uid: string) => {\n // Remove from everQueued so it can be re-queued\n everQueuedRef.current.delete(uid);\n // Re-add immediately\n everQueuedRef.current.add(uid);\n setHealthMap((prev) => ({ ...prev, [uid]: { state: 'pending' } }));\n queueRef.current.push(uid);\n processQueue();\n },\n [processQueue]\n );\n\n return { healthMap, checkUids, retry };\n}\n"],"names":[],"mappings":"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"}
|
package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/inputs/AuthorizationHeaderField.js
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import React, { useMemo } from 'react';
|
|
2
|
+
import { useWatch, Controller } from '../../../../node_modules/react-hook-form/dist/index.esm.js';
|
|
3
|
+
import { useStyles2, Tooltip, Icon } from '@grafana/ui';
|
|
4
|
+
import { IndexedPairEditor } from './IndexedPairEditor.js';
|
|
5
|
+
import { getFieldStyles } from '../styles.js';
|
|
6
|
+
import '@grafana/runtime';
|
|
7
|
+
import '@marcbachmann/cel-js';
|
|
8
|
+
|
|
9
|
+
const AuthorizationHeaderField = (props) => {
|
|
10
|
+
const { headersFieldKey, control, disabled } = props;
|
|
11
|
+
const styles = useStyles2(getFieldStyles);
|
|
12
|
+
const watchedHeaders = useWatch({ control, name: headersFieldKey });
|
|
13
|
+
const items = useMemo(
|
|
14
|
+
() => Array.isArray(watchedHeaders) ? watchedHeaders : [],
|
|
15
|
+
[watchedHeaders]
|
|
16
|
+
);
|
|
17
|
+
const authEntries = useMemo(() => {
|
|
18
|
+
const entries = [];
|
|
19
|
+
for (let i = 0; i < items.length; i++) {
|
|
20
|
+
if (items[i].name.toLowerCase() === "authorization") {
|
|
21
|
+
entries.push({ item: items[i], originalIdx: i });
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return entries;
|
|
25
|
+
}, [items]);
|
|
26
|
+
if (authEntries.length === 0) {
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
const authItems = authEntries.map((e) => e.item);
|
|
30
|
+
return /* @__PURE__ */ React.createElement(
|
|
31
|
+
Controller,
|
|
32
|
+
{
|
|
33
|
+
name: headersFieldKey,
|
|
34
|
+
control,
|
|
35
|
+
render: ({ field: formField }) => {
|
|
36
|
+
const handleChange = (updatedAuthItems) => {
|
|
37
|
+
const updated = [...items];
|
|
38
|
+
for (let i = 0; i < authEntries.length; i++) {
|
|
39
|
+
if (i < updatedAuthItems.length) {
|
|
40
|
+
updated[authEntries[i].originalIdx] = updatedAuthItems[i];
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
formField.onChange(updated);
|
|
44
|
+
};
|
|
45
|
+
return /* @__PURE__ */ React.createElement("div", { className: styles.fieldRow }, /* @__PURE__ */ React.createElement("div", { className: styles.fieldLabelRow }, /* @__PURE__ */ React.createElement("span", { className: styles.fieldLabel }, "Custom HTTP Headers"), /* @__PURE__ */ React.createElement(Tooltip, { content: "Authorization HTTP header(s) sent with every request." }, /* @__PURE__ */ React.createElement(Icon, { name: "info-circle", size: "xs", className: styles.fieldInfoIcon }))), /* @__PURE__ */ React.createElement("div", { className: styles.fieldInputCol }, /* @__PURE__ */ React.createElement(IndexedPairEditor, { value: authItems, onChange: handleChange, disabled, hideControls: true })));
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
);
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
export { AuthorizationHeaderField };
|
|
52
|
+
//# sourceMappingURL=AuthorizationHeaderField.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AuthorizationHeaderField.js","sources":["../../../../../../src/components/ConfigEditor/DatasourceConfigWizard/inputs/AuthorizationHeaderField.tsx"],"sourcesContent":["import React, { useMemo } from 'react';\nimport { type useForm, Controller, useWatch } from 'react-hook-form';\nimport { useStyles2, Icon, Tooltip } from '@grafana/ui';\nimport { IndexedPairEditor } from './IndexedPairEditor';\nimport { getFieldStyles } from '../styles';\nimport { type IndexedPairItem, type FormValues } from '../datasource';\n\ntype Props = {\n headersFieldKey: string;\n control: ReturnType<typeof useForm<FormValues>>['control'];\n disabled?: boolean;\n};\n\nexport const AuthorizationHeaderField = (props: Props) => {\n const { headersFieldKey, control, disabled } = props;\n const styles = useStyles2(getFieldStyles);\n // Subscribe to just this field rather than receiving the whole watched-values\n // blob; keeps the component self-contained and consistent with RHF idioms.\n const watchedHeaders = useWatch({ control, name: headersFieldKey });\n const items = useMemo(\n () => (Array.isArray(watchedHeaders) ? watchedHeaders : []) as IndexedPairItem[],\n [watchedHeaders]\n );\n\n const authEntries = useMemo(() => {\n const entries: Array<{ item: IndexedPairItem; originalIdx: number }> = [];\n for (let i = 0; i < items.length; i++) {\n if (items[i].name.toLowerCase() === 'authorization') {\n entries.push({ item: items[i], originalIdx: i });\n }\n }\n return entries;\n }, [items]);\n\n if (authEntries.length === 0) {\n return null;\n }\n\n const authItems = authEntries.map((e) => e.item);\n\n return (\n <Controller\n name={headersFieldKey}\n control={control}\n render={({ field: formField }) => {\n const handleChange = (updatedAuthItems: IndexedPairItem[]) => {\n const updated = [...items];\n for (let i = 0; i < authEntries.length; i++) {\n if (i < updatedAuthItems.length) {\n updated[authEntries[i].originalIdx] = updatedAuthItems[i];\n }\n }\n formField.onChange(updated);\n };\n\n return (\n <div className={styles.fieldRow}>\n <div className={styles.fieldLabelRow}>\n <span className={styles.fieldLabel}>Custom HTTP Headers</span>\n <Tooltip content=\"Authorization HTTP header(s) sent with every request.\">\n <Icon name=\"info-circle\" size=\"xs\" className={styles.fieldInfoIcon} />\n </Tooltip>\n </div>\n <div className={styles.fieldInputCol}>\n <IndexedPairEditor value={authItems} onChange={handleChange} disabled={disabled} hideControls />\n </div>\n </div>\n );\n }}\n />\n );\n};\n"],"names":[],"mappings":";;;;;;;;AAaa,MAAA,wBAAA,GAA2B,CAAC,KAAiB,KAAA;AACxD,EAAA,MAAM,EAAE,eAAA,EAAiB,OAAS,EAAA,QAAA,EAAa,GAAA,KAAA;AAC/C,EAAM,MAAA,MAAA,GAAS,WAAW,cAAc,CAAA;AAGxC,EAAA,MAAM,iBAAiB,QAAS,CAAA,EAAE,OAAS,EAAA,IAAA,EAAM,iBAAiB,CAAA;AAClE,EAAA,MAAM,KAAQ,GAAA,OAAA;AAAA,IACZ,MAAO,KAAM,CAAA,OAAA,CAAQ,cAAc,CAAA,GAAI,iBAAiB,EAAC;AAAA,IACzD,CAAC,cAAc;AAAA,GACjB;AAEA,EAAM,MAAA,WAAA,GAAc,QAAQ,MAAM;AAChC,IAAA,MAAM,UAAiE,EAAC;AACxE,IAAA,KAAA,IAAS,CAAI,GAAA,CAAA,EAAG,CAAI,GAAA,KAAA,CAAM,QAAQ,CAAK,EAAA,EAAA;AACrC,MAAA,IAAI,MAAM,CAAC,CAAA,CAAE,IAAK,CAAA,WAAA,OAAkB,eAAiB,EAAA;AACnD,QAAQ,OAAA,CAAA,IAAA,CAAK,EAAE,IAAM,EAAA,KAAA,CAAM,CAAC,CAAG,EAAA,WAAA,EAAa,GAAG,CAAA;AAAA;AACjD;AAEF,IAAO,OAAA,OAAA;AAAA,GACT,EAAG,CAAC,KAAK,CAAC,CAAA;AAEV,EAAI,IAAA,WAAA,CAAY,WAAW,CAAG,EAAA;AAC5B,IAAO,OAAA,IAAA;AAAA;AAGT,EAAA,MAAM,YAAY,WAAY,CAAA,GAAA,CAAI,CAAC,CAAA,KAAM,EAAE,IAAI,CAAA;AAE/C,EACE,uBAAA,KAAA,CAAA,aAAA;AAAA,IAAC,UAAA;AAAA,IAAA;AAAA,MACC,IAAM,EAAA,eAAA;AAAA,MACN,OAAA;AAAA,MACA,MAAQ,EAAA,CAAC,EAAE,KAAA,EAAO,WAAgB,KAAA;AAChC,QAAM,MAAA,YAAA,GAAe,CAAC,gBAAwC,KAAA;AAC5D,UAAM,MAAA,OAAA,GAAU,CAAC,GAAG,KAAK,CAAA;AACzB,UAAA,KAAA,IAAS,CAAI,GAAA,CAAA,EAAG,CAAI,GAAA,WAAA,CAAY,QAAQ,CAAK,EAAA,EAAA;AAC3C,YAAI,IAAA,CAAA,GAAI,iBAAiB,MAAQ,EAAA;AAC/B,cAAA,OAAA,CAAQ,YAAY,CAAC,CAAA,CAAE,WAAW,CAAA,GAAI,iBAAiB,CAAC,CAAA;AAAA;AAC1D;AAEF,UAAA,SAAA,CAAU,SAAS,OAAO,CAAA;AAAA,SAC5B;AAEA,QACE,uBAAA,KAAA,CAAA,aAAA,CAAC,SAAI,SAAW,EAAA,MAAA,CAAO,4BACpB,KAAA,CAAA,aAAA,CAAA,KAAA,EAAA,EAAI,SAAW,EAAA,MAAA,CAAO,aACrB,EAAA,kBAAA,KAAA,CAAA,aAAA,CAAC,UAAK,SAAW,EAAA,MAAA,CAAO,cAAY,qBAAmB,CAAA,sCACtD,OAAQ,EAAA,EAAA,OAAA,EAAQ,uDACf,EAAA,kBAAA,KAAA,CAAA,aAAA,CAAC,IAAK,EAAA,EAAA,IAAA,EAAK,eAAc,IAAK,EAAA,IAAA,EAAK,WAAW,MAAO,CAAA,aAAA,EAAe,CACtE,CACF,CAAA,kBACC,KAAA,CAAA,aAAA,CAAA,KAAA,EAAA,EAAI,SAAW,EAAA,MAAA,CAAO,iCACpB,KAAA,CAAA,aAAA,CAAA,iBAAA,EAAA,EAAkB,OAAO,SAAW,EAAA,QAAA,EAAU,cAAc,QAAoB,EAAA,YAAA,EAAY,IAAC,EAAA,CAChG,CACF,CAAA;AAAA;AAEJ;AAAA,GACF;AAEJ;;;;"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { css } from '@emotion/css';
|
|
3
|
+
import '@grafana/data';
|
|
4
|
+
import { useStyles2, Icon } from '@grafana/ui';
|
|
5
|
+
|
|
6
|
+
const ComplexFieldNote = (props) => {
|
|
7
|
+
const { count, label } = props;
|
|
8
|
+
const styles = useStyles2(getStyles);
|
|
9
|
+
return /* @__PURE__ */ React.createElement("div", { className: styles.note }, /* @__PURE__ */ React.createElement(Icon, { name: "info-circle", size: "xs" }), /* @__PURE__ */ React.createElement("span", null, count > 0 ? `${count} ${label.toLowerCase()} configured.` : `No ${label.toLowerCase()} configured.`, " Configure in Grafana UI."));
|
|
10
|
+
};
|
|
11
|
+
const getStyles = (theme) => ({
|
|
12
|
+
note: css({
|
|
13
|
+
display: "inline-flex",
|
|
14
|
+
alignItems: "center",
|
|
15
|
+
gap: theme.spacing(0.5),
|
|
16
|
+
padding: `${theme.spacing(0.5)} ${theme.spacing(0.75)}`,
|
|
17
|
+
fontSize: theme.typography.bodySmall.fontSize,
|
|
18
|
+
color: theme.colors.text.secondary,
|
|
19
|
+
backgroundColor: theme.colors.background.secondary,
|
|
20
|
+
borderRadius: theme.shape.radius.default,
|
|
21
|
+
border: `1px solid ${theme.colors.border.weak}`
|
|
22
|
+
})
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
export { ComplexFieldNote };
|
|
26
|
+
//# sourceMappingURL=ComplexFieldNote.js.map
|
package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/inputs/ComplexFieldNote.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ComplexFieldNote.js","sources":["../../../../../../src/components/ConfigEditor/DatasourceConfigWizard/inputs/ComplexFieldNote.tsx"],"sourcesContent":["import React from 'react';\nimport { css } from '@emotion/css';\nimport { type GrafanaTheme2 } from '@grafana/data';\nimport { useStyles2, Icon } from '@grafana/ui';\n\ntype Props = { count: number; label: string };\n\nexport const ComplexFieldNote = (props: Props) => {\n const { count, label } = props;\n const styles = useStyles2(getStyles);\n return (\n <div className={styles.note}>\n <Icon name=\"info-circle\" size=\"xs\" />\n <span>\n {count > 0 ? `${count} ${label.toLowerCase()} configured.` : `No ${label.toLowerCase()} configured.`} Configure\n in Grafana UI.\n </span>\n </div>\n );\n};\n\nconst getStyles = (theme: GrafanaTheme2) => ({\n note: css({\n display: 'inline-flex',\n alignItems: 'center',\n gap: theme.spacing(0.5),\n padding: `${theme.spacing(0.5)} ${theme.spacing(0.75)}`,\n fontSize: theme.typography.bodySmall.fontSize,\n color: theme.colors.text.secondary,\n backgroundColor: theme.colors.background.secondary,\n borderRadius: theme.shape.radius.default,\n border: `1px solid ${theme.colors.border.weak}`,\n }),\n});\n"],"names":[],"mappings":";;;;;AAOa,MAAA,gBAAA,GAAmB,CAAC,KAAiB,KAAA;AAChD,EAAM,MAAA,EAAE,KAAO,EAAA,KAAA,EAAU,GAAA,KAAA;AACzB,EAAM,MAAA,MAAA,GAAS,WAAW,SAAS,CAAA;AACnC,EAAA,uBACG,KAAA,CAAA,aAAA,CAAA,KAAA,EAAA,EAAI,SAAW,EAAA,MAAA,CAAO,IACrB,EAAA,kBAAA,KAAA,CAAA,aAAA,CAAC,IAAK,EAAA,EAAA,IAAA,EAAK,aAAc,EAAA,IAAA,EAAK,IAAK,EAAA,CAAA,kBAClC,KAAA,CAAA,aAAA,CAAA,MAAA,EAAA,IAAA,EACE,KAAQ,GAAA,CAAA,GAAI,CAAG,EAAA,KAAK,CAAI,CAAA,EAAA,KAAA,CAAM,WAAY,EAAC,CAAiB,YAAA,CAAA,GAAA,CAAA,GAAA,EAAM,KAAM,CAAA,WAAA,EAAa,CAAA,YAAA,CAAA,EAAe,2BAEvG,CACF,CAAA;AAEJ;AAEA,MAAM,SAAA,GAAY,CAAC,KAA0B,MAAA;AAAA,EAC3C,MAAM,GAAI,CAAA;AAAA,IACR,OAAS,EAAA,aAAA;AAAA,IACT,UAAY,EAAA,QAAA;AAAA,IACZ,GAAA,EAAK,KAAM,CAAA,OAAA,CAAQ,GAAG,CAAA;AAAA,IACtB,OAAA,EAAS,CAAG,EAAA,KAAA,CAAM,OAAQ,CAAA,GAAG,CAAC,CAAI,CAAA,EAAA,KAAA,CAAM,OAAQ,CAAA,IAAI,CAAC,CAAA,CAAA;AAAA,IACrD,QAAA,EAAU,KAAM,CAAA,UAAA,CAAW,SAAU,CAAA,QAAA;AAAA,IACrC,KAAA,EAAO,KAAM,CAAA,MAAA,CAAO,IAAK,CAAA,SAAA;AAAA,IACzB,eAAA,EAAiB,KAAM,CAAA,MAAA,CAAO,UAAW,CAAA,SAAA;AAAA,IACzC,YAAA,EAAc,KAAM,CAAA,KAAA,CAAM,MAAO,CAAA,OAAA;AAAA,IACjC,MAAQ,EAAA,CAAA,UAAA,EAAa,KAAM,CAAA,MAAA,CAAO,OAAO,IAAI,CAAA;AAAA,GAC9C;AACH,CAAA,CAAA;;;;"}
|