@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,217 @@
|
|
|
1
|
+
import React, { useState, useMemo, useCallback } from 'react';
|
|
2
|
+
import { useStyles2, Spinner, Icon, Tooltip, Button, Select } from '@grafana/ui';
|
|
3
|
+
import { formKey, getWatchedValue, isAuthGroupId } from './config.js';
|
|
4
|
+
import { SECURE_FIELD_CONFIGURED } from './datasource.js';
|
|
5
|
+
import { isFieldRequired } from './fieldUtils.js';
|
|
6
|
+
import { FetchErrorState, GroupFields, FormFooter } from './layoutParts.js';
|
|
7
|
+
import { TabLayout } from './TabLayout.js';
|
|
8
|
+
import { getWizardStyles } from './styles.js';
|
|
9
|
+
import { useDatasourceConfigForm } from './hooks/useDatasourceConfigForm.js';
|
|
10
|
+
|
|
11
|
+
function DatasourceConfigWizard(props) {
|
|
12
|
+
const { schema, dsUid, dsName, onSuccess, onSaving, onRetest, healthError, renderActions, mode = "tab" } = props;
|
|
13
|
+
const form = useDatasourceConfigForm({ schema, dsUid, onSuccess, onSaving });
|
|
14
|
+
if (mode === "tab") {
|
|
15
|
+
return /* @__PURE__ */ React.createElement(
|
|
16
|
+
TabLayout,
|
|
17
|
+
{
|
|
18
|
+
form,
|
|
19
|
+
schema,
|
|
20
|
+
dsUid,
|
|
21
|
+
dsName,
|
|
22
|
+
onRetest,
|
|
23
|
+
healthError,
|
|
24
|
+
renderActions
|
|
25
|
+
}
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
return /* @__PURE__ */ React.createElement(
|
|
29
|
+
WizardLayout,
|
|
30
|
+
{
|
|
31
|
+
form,
|
|
32
|
+
schema,
|
|
33
|
+
dsUid,
|
|
34
|
+
dsName,
|
|
35
|
+
onRetest,
|
|
36
|
+
healthError,
|
|
37
|
+
renderActions
|
|
38
|
+
}
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
function WizardLayout({ form, schema, dsUid, dsName, onRetest, healthError, renderActions }) {
|
|
42
|
+
var _a, _b, _c;
|
|
43
|
+
const styles = useStyles2(getWizardStyles);
|
|
44
|
+
const [currentStep, setCurrentStep] = useState(0);
|
|
45
|
+
const {
|
|
46
|
+
resolvedGroups,
|
|
47
|
+
fieldById,
|
|
48
|
+
handleSubmit,
|
|
49
|
+
trigger,
|
|
50
|
+
errors,
|
|
51
|
+
watchedValues,
|
|
52
|
+
celContext,
|
|
53
|
+
initializing,
|
|
54
|
+
fetchError,
|
|
55
|
+
submitting,
|
|
56
|
+
readOnly,
|
|
57
|
+
isFieldVisible,
|
|
58
|
+
onSubmit
|
|
59
|
+
} = form;
|
|
60
|
+
const arrowSteps = useMemo(() => {
|
|
61
|
+
const requiredGroup = resolvedGroups.find((g) => g.group.id === "_required");
|
|
62
|
+
if (!requiredGroup) {
|
|
63
|
+
return new Set(resolvedGroups.map((_, i) => i));
|
|
64
|
+
}
|
|
65
|
+
const requiredFieldIds = new Set(requiredGroup.fields.map((f) => f.id));
|
|
66
|
+
const steps = /* @__PURE__ */ new Set();
|
|
67
|
+
for (let i = 0; i < resolvedGroups.length; i++) {
|
|
68
|
+
const g = resolvedGroups[i];
|
|
69
|
+
if (g.group.id === "_required" || g.fields.some((f) => !requiredFieldIds.has(f.id))) {
|
|
70
|
+
steps.add(i);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
return steps;
|
|
74
|
+
}, [resolvedGroups]);
|
|
75
|
+
const currentResolved = resolvedGroups[currentStep];
|
|
76
|
+
const isFirstStep = useMemo(() => {
|
|
77
|
+
for (let i = 0; i < currentStep; i++) {
|
|
78
|
+
if (arrowSteps.has(i)) {
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return true;
|
|
83
|
+
}, [currentStep, arrowSteps]);
|
|
84
|
+
const isLastStep = useMemo(() => {
|
|
85
|
+
for (let i = currentStep + 1; i < resolvedGroups.length; i++) {
|
|
86
|
+
if (arrowSteps.has(i)) {
|
|
87
|
+
return false;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return true;
|
|
91
|
+
}, [currentStep, arrowSteps, resolvedGroups.length]);
|
|
92
|
+
const visibleFieldsForStep = useMemo(
|
|
93
|
+
() => currentResolved ? currentResolved.fields.filter(isFieldVisible) : [],
|
|
94
|
+
[currentResolved, isFieldVisible]
|
|
95
|
+
);
|
|
96
|
+
const currentGroupValid = useMemo(() => {
|
|
97
|
+
if (!currentResolved) {
|
|
98
|
+
return true;
|
|
99
|
+
}
|
|
100
|
+
for (const field of visibleFieldsForStep) {
|
|
101
|
+
if (errors[formKey(field)]) {
|
|
102
|
+
return false;
|
|
103
|
+
}
|
|
104
|
+
if (isFieldRequired(field, watchedValues, fieldById, celContext)) {
|
|
105
|
+
const val = getWatchedValue(watchedValues, formKey(field));
|
|
106
|
+
if (val === SECURE_FIELD_CONFIGURED) {
|
|
107
|
+
continue;
|
|
108
|
+
}
|
|
109
|
+
if (val === undefined || val === null || val === "") {
|
|
110
|
+
return false;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
return true;
|
|
115
|
+
}, [currentResolved, errors, visibleFieldsForStep, watchedValues, fieldById, celContext]);
|
|
116
|
+
const goNext = useCallback(async () => {
|
|
117
|
+
if (!currentResolved) {
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
if (!readOnly) {
|
|
121
|
+
const visibleKeys = visibleFieldsForStep.map((f) => formKey(f));
|
|
122
|
+
const valid = await trigger(visibleKeys);
|
|
123
|
+
if (!valid) {
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
setCurrentStep((s) => {
|
|
128
|
+
for (let i = s + 1; i < resolvedGroups.length; i++) {
|
|
129
|
+
if (arrowSteps.has(i)) {
|
|
130
|
+
return i;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
return s;
|
|
134
|
+
});
|
|
135
|
+
}, [currentResolved, visibleFieldsForStep, trigger, resolvedGroups.length, arrowSteps, readOnly]);
|
|
136
|
+
const goPrev = useCallback(() => {
|
|
137
|
+
setCurrentStep((s) => {
|
|
138
|
+
for (let i = s - 1; i >= 0; i--) {
|
|
139
|
+
if (arrowSteps.has(i)) {
|
|
140
|
+
return i;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
return s;
|
|
144
|
+
});
|
|
145
|
+
}, [arrowSteps]);
|
|
146
|
+
if (initializing) {
|
|
147
|
+
return /* @__PURE__ */ React.createElement("div", { className: styles.container }, /* @__PURE__ */ React.createElement(Spinner, { size: "sm", inline: true }), " Loading configuration...");
|
|
148
|
+
}
|
|
149
|
+
if (fetchError) {
|
|
150
|
+
return /* @__PURE__ */ React.createElement("div", { className: styles.container }, /* @__PURE__ */ React.createElement(FetchErrorState, { error: fetchError, dsUid, buttonClassName: styles.buttons }));
|
|
151
|
+
}
|
|
152
|
+
if (resolvedGroups.length === 0) {
|
|
153
|
+
return null;
|
|
154
|
+
}
|
|
155
|
+
const currentGroup = currentResolved == null ? undefined : currentResolved.group;
|
|
156
|
+
return /* @__PURE__ */ React.createElement("div", { className: styles.container }, submitting && /* @__PURE__ */ React.createElement("div", { className: styles.overlay }, /* @__PURE__ */ React.createElement(Spinner, { size: "sm" }), /* @__PURE__ */ React.createElement("span", null, "Saving & testing\u2026")), readOnly && /* @__PURE__ */ React.createElement("div", { className: styles.readOnlyBanner }, /* @__PURE__ */ React.createElement(Icon, { name: "lock", size: "xs" }), /* @__PURE__ */ React.createElement("span", null, "Read-only \u2014 managed externally")), /* @__PURE__ */ React.createElement("div", { className: styles.navBar }, currentGroup && /* @__PURE__ */ React.createElement(Tooltip, { content: (_a = currentGroup.description) != null ? _a : currentGroup.title }, /* @__PURE__ */ React.createElement("span", { className: styles.navTitle }, currentGroup.title, /* @__PURE__ */ React.createElement("span", { className: styles.stepCount }, currentStep + 1, "/", resolvedGroups.length))), /* @__PURE__ */ React.createElement("div", { className: styles.navActions }, /* @__PURE__ */ React.createElement(Tooltip, { content: isFirstStep ? "First step" : `Previous: ${(_b = resolvedGroups[currentStep - 1]) == null ? undefined : _b.group.title}` }, /* @__PURE__ */ React.createElement(
|
|
157
|
+
Button,
|
|
158
|
+
{
|
|
159
|
+
variant: "secondary",
|
|
160
|
+
fill: "text",
|
|
161
|
+
size: "sm",
|
|
162
|
+
icon: "angle-left",
|
|
163
|
+
"aria-label": "Previous",
|
|
164
|
+
onClick: goPrev,
|
|
165
|
+
disabled: isFirstStep || submitting,
|
|
166
|
+
type: "button"
|
|
167
|
+
}
|
|
168
|
+
)), /* @__PURE__ */ React.createElement(
|
|
169
|
+
Select,
|
|
170
|
+
{
|
|
171
|
+
options: resolvedGroups.map((g, i) => ({ label: g.group.title, value: i })),
|
|
172
|
+
value: currentStep,
|
|
173
|
+
onChange: (v) => {
|
|
174
|
+
if (v) {
|
|
175
|
+
setCurrentStep(v.value);
|
|
176
|
+
}
|
|
177
|
+
},
|
|
178
|
+
disabled: submitting,
|
|
179
|
+
width: 18
|
|
180
|
+
}
|
|
181
|
+
), /* @__PURE__ */ React.createElement(Tooltip, { content: isLastStep ? "Last step" : `Next: ${(_c = resolvedGroups[currentStep + 1]) == null ? undefined : _c.group.title}` }, /* @__PURE__ */ React.createElement(
|
|
182
|
+
Button,
|
|
183
|
+
{
|
|
184
|
+
variant: isLastStep || !readOnly && !currentGroupValid ? "secondary" : "primary",
|
|
185
|
+
size: "sm",
|
|
186
|
+
icon: "angle-right",
|
|
187
|
+
"aria-label": "Next",
|
|
188
|
+
onClick: goNext,
|
|
189
|
+
disabled: isLastStep || submitting,
|
|
190
|
+
type: "button"
|
|
191
|
+
}
|
|
192
|
+
)))), currentResolved && /* @__PURE__ */ React.createElement("form", { onSubmit: handleSubmit(onSubmit), className: styles.form }, /* @__PURE__ */ React.createElement(
|
|
193
|
+
GroupFields,
|
|
194
|
+
{
|
|
195
|
+
group: currentResolved,
|
|
196
|
+
form,
|
|
197
|
+
dsUid,
|
|
198
|
+
showAuthHeaders: currentResolved.group.id === "_required" || isAuthGroupId(currentResolved.group.id)
|
|
199
|
+
}
|
|
200
|
+
), /* @__PURE__ */ React.createElement(
|
|
201
|
+
FormFooter,
|
|
202
|
+
{
|
|
203
|
+
form,
|
|
204
|
+
schema,
|
|
205
|
+
dsUid,
|
|
206
|
+
dsName,
|
|
207
|
+
onRetest,
|
|
208
|
+
healthError,
|
|
209
|
+
renderActions,
|
|
210
|
+
saveDisabled: submitting || !currentGroupValid,
|
|
211
|
+
className: styles.buttons
|
|
212
|
+
}
|
|
213
|
+
)));
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
export { DatasourceConfigWizard };
|
|
217
|
+
//# sourceMappingURL=DatasourceConfigWizard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DatasourceConfigWizard.js","sources":["../../../../../src/components/ConfigEditor/DatasourceConfigWizard/DatasourceConfigWizard.tsx"],"sourcesContent":["import React, { type ReactNode, useCallback, useMemo, useState } from 'react';\nimport { useStyles2, Button, Select, Icon, Tooltip, Spinner } from '@grafana/ui';\nimport type { DatasourceConfigSchema } from '../../../schema/schema';\nimport { formKey, getWatchedValue, isAuthGroupId } from './config';\nimport { SECURE_FIELD_CONFIGURED } from './datasource';\nimport { isFieldRequired } from './fieldUtils';\nimport { GroupFields, FormFooter, FetchErrorState } from './layoutParts';\nimport { TabLayout } from './TabLayout';\nimport { getWizardStyles } from './styles';\nimport { useDatasourceConfigForm } from './hooks/useDatasourceConfigForm';\n\nexport type DatasourceConfigWizardProps = {\n schema: DatasourceConfigSchema;\n dsUid: string;\n dsName: string;\n onSuccess: (status: string, message?: string) => void;\n onSaving?: (saving: boolean) => void;\n onRetest?: () => void;\n onFollowup?: (intent: string) => void;\n healthError?: string;\n mode?: 'tab' | 'wizard';\n /** Optional render prop for custom action buttons (e.g. analyze/troubleshoot). */\n renderActions?: (props: { dsUid: string; dsName: string; dsType: string; healthError?: string }) => ReactNode;\n};\n\nexport function DatasourceConfigWizard(props: DatasourceConfigWizardProps) {\n const { schema, dsUid, dsName, onSuccess, onSaving, onRetest, healthError, renderActions, mode = 'tab' } = props;\n\n const form = useDatasourceConfigForm({ schema, dsUid, onSuccess, onSaving });\n\n if (mode === 'tab') {\n return (\n <TabLayout\n form={form}\n schema={schema}\n dsUid={dsUid}\n dsName={dsName}\n onRetest={onRetest}\n healthError={healthError}\n renderActions={renderActions}\n />\n );\n }\n\n return (\n <WizardLayout\n form={form}\n schema={schema}\n dsUid={dsUid}\n dsName={dsName}\n onRetest={onRetest}\n healthError={healthError}\n renderActions={renderActions}\n />\n );\n}\n\ntype LayoutProps = {\n form: ReturnType<typeof useDatasourceConfigForm>;\n schema: DatasourceConfigSchema;\n dsUid: string;\n dsName: string;\n onRetest?: () => void;\n healthError?: string;\n renderActions?: (props: { dsUid: string; dsName: string; dsType: string; healthError?: string }) => ReactNode;\n};\n\nfunction WizardLayout({ form, schema, dsUid, dsName, onRetest, healthError, renderActions }: LayoutProps) {\n const styles = useStyles2(getWizardStyles);\n const [currentStep, setCurrentStep] = useState(0);\n\n const {\n resolvedGroups,\n fieldById,\n handleSubmit,\n trigger,\n errors,\n watchedValues,\n celContext,\n initializing,\n fetchError,\n submitting,\n readOnly,\n isFieldVisible,\n onSubmit,\n } = form;\n\n const arrowSteps = useMemo(() => {\n const requiredGroup = resolvedGroups.find((g) => g.group.id === '_required');\n if (!requiredGroup) {\n return new Set(resolvedGroups.map((_, i) => i));\n }\n const requiredFieldIds = new Set(requiredGroup.fields.map((f) => f.id));\n const steps = new Set<number>();\n for (let i = 0; i < resolvedGroups.length; i++) {\n const g = resolvedGroups[i];\n if (g.group.id === '_required' || g.fields.some((f) => !requiredFieldIds.has(f.id))) {\n steps.add(i);\n }\n }\n return steps;\n }, [resolvedGroups]);\n\n const currentResolved = resolvedGroups[currentStep];\n\n const isFirstStep = useMemo(() => {\n for (let i = 0; i < currentStep; i++) {\n if (arrowSteps.has(i)) {\n return false;\n }\n }\n return true;\n }, [currentStep, arrowSteps]);\n\n const isLastStep = useMemo(() => {\n for (let i = currentStep + 1; i < resolvedGroups.length; i++) {\n if (arrowSteps.has(i)) {\n return false;\n }\n }\n return true;\n }, [currentStep, arrowSteps, resolvedGroups.length]);\n\n const visibleFieldsForStep = useMemo(\n () => (currentResolved ? currentResolved.fields.filter(isFieldVisible) : []),\n [currentResolved, isFieldVisible]\n );\n\n const currentGroupValid = useMemo(() => {\n if (!currentResolved) {\n return true;\n }\n for (const field of visibleFieldsForStep) {\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 }, [currentResolved, errors, visibleFieldsForStep, watchedValues, fieldById, celContext]);\n\n const goNext = useCallback(async () => {\n if (!currentResolved) {\n return;\n }\n if (!readOnly) {\n const visibleKeys = visibleFieldsForStep.map((f) => formKey(f));\n const valid = await trigger(visibleKeys);\n if (!valid) {\n return;\n }\n }\n setCurrentStep((s) => {\n for (let i = s + 1; i < resolvedGroups.length; i++) {\n if (arrowSteps.has(i)) {\n return i;\n }\n }\n return s;\n });\n }, [currentResolved, visibleFieldsForStep, trigger, resolvedGroups.length, arrowSteps, readOnly]);\n\n const goPrev = useCallback(() => {\n setCurrentStep((s) => {\n for (let i = s - 1; i >= 0; i--) {\n if (arrowSteps.has(i)) {\n return i;\n }\n }\n return s;\n });\n }, [arrowSteps]);\n\n if (initializing) {\n return (\n <div className={styles.container}>\n <Spinner size=\"sm\" inline /> Loading configuration...\n </div>\n );\n }\n\n if (fetchError) {\n return (\n <div className={styles.container}>\n <FetchErrorState error={fetchError} dsUid={dsUid} buttonClassName={styles.buttons} />\n </div>\n );\n }\n\n if (resolvedGroups.length === 0) {\n return null;\n }\n\n const currentGroup = currentResolved?.group;\n\n return (\n <div className={styles.container}>\n {submitting && (\n <div className={styles.overlay}>\n <Spinner size=\"sm\" />\n <span>Saving & testing…</span>\n </div>\n )}\n {readOnly && (\n <div className={styles.readOnlyBanner}>\n <Icon name=\"lock\" size=\"xs\" />\n <span>Read-only — managed externally</span>\n </div>\n )}\n <div className={styles.navBar}>\n {currentGroup && (\n <Tooltip content={currentGroup.description ?? currentGroup.title}>\n <span className={styles.navTitle}>\n {currentGroup.title}\n <span className={styles.stepCount}>\n {currentStep + 1}/{resolvedGroups.length}\n </span>\n </span>\n </Tooltip>\n )}\n <div className={styles.navActions}>\n <Tooltip content={isFirstStep ? 'First step' : `Previous: ${resolvedGroups[currentStep - 1]?.group.title}`}>\n <Button\n variant=\"secondary\"\n fill=\"text\"\n size=\"sm\"\n icon=\"angle-left\"\n aria-label=\"Previous\"\n onClick={goPrev}\n disabled={isFirstStep || submitting}\n type=\"button\"\n />\n </Tooltip>\n <Select\n options={resolvedGroups.map((g, i) => ({ label: g.group.title, value: i }))}\n value={currentStep}\n onChange={(v) => {\n if (v) {\n setCurrentStep(v.value!);\n }\n }}\n disabled={submitting}\n width={18}\n />\n <Tooltip content={isLastStep ? 'Last step' : `Next: ${resolvedGroups[currentStep + 1]?.group.title}`}>\n <Button\n variant={isLastStep || (!readOnly && !currentGroupValid) ? 'secondary' : 'primary'}\n size=\"sm\"\n icon=\"angle-right\"\n aria-label=\"Next\"\n onClick={goNext}\n disabled={isLastStep || submitting}\n type=\"button\"\n />\n </Tooltip>\n </div>\n </div>\n\n {currentResolved && (\n <form onSubmit={handleSubmit(onSubmit)} className={styles.form}>\n <GroupFields\n group={currentResolved}\n form={form}\n dsUid={dsUid}\n showAuthHeaders={currentResolved.group.id === '_required' || isAuthGroupId(currentResolved.group.id)}\n />\n <FormFooter\n form={form}\n schema={schema}\n dsUid={dsUid}\n dsName={dsName}\n onRetest={onRetest}\n healthError={healthError}\n renderActions={renderActions}\n saveDisabled={submitting || !currentGroupValid}\n className={styles.buttons}\n />\n </form>\n )}\n </div>\n );\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import React, { Component } from 'react';
|
|
2
|
+
import { Alert } from '@grafana/ui';
|
|
3
|
+
|
|
4
|
+
var __defProp = Object.defineProperty;
|
|
5
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
6
|
+
var __publicField = (obj, key, value) => __defNormalProp(obj, key + "" , value);
|
|
7
|
+
class DatasourceErrorBoundary extends Component {
|
|
8
|
+
constructor() {
|
|
9
|
+
super(...arguments);
|
|
10
|
+
__publicField(this, "state", { error: null });
|
|
11
|
+
}
|
|
12
|
+
static getDerivedStateFromError(error) {
|
|
13
|
+
return { error };
|
|
14
|
+
}
|
|
15
|
+
componentDidCatch(error, info) {
|
|
16
|
+
console.error("[DatasourceConfigWizard] Caught error:", error, info.componentStack);
|
|
17
|
+
}
|
|
18
|
+
render() {
|
|
19
|
+
if (this.state.error) {
|
|
20
|
+
return /* @__PURE__ */ React.createElement(Alert, { severity: "warning", title: "Configuration wizard unavailable" }, "Could not load the configuration wizard", this.props.dsName ? ` for ${this.props.dsName}` : "", ". Use the Settings link to configure this datasource manually.");
|
|
21
|
+
}
|
|
22
|
+
return this.props.children;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export { DatasourceErrorBoundary };
|
|
27
|
+
//# sourceMappingURL=DatasourceErrorBoundary.js.map
|
package/dist/esm/components/ConfigEditor/DatasourceConfigWizard/DatasourceErrorBoundary.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DatasourceErrorBoundary.js","sources":["../../../../../src/components/ConfigEditor/DatasourceConfigWizard/DatasourceErrorBoundary.tsx"],"sourcesContent":["import React, { Component, type ReactNode, type ErrorInfo } from 'react';\nimport { Alert } from '@grafana/ui';\n\n/** Lightweight error boundary scoped to datasource config widgets — won't crash the host UI. */\nexport class DatasourceErrorBoundary extends Component<\n { children: ReactNode; dsName?: string },\n { error: Error | null }\n> {\n state: { error: Error | null } = { error: null };\n\n static getDerivedStateFromError(error: Error) {\n return { error };\n }\n\n componentDidCatch(error: Error, info: ErrorInfo) {\n console.error('[DatasourceConfigWizard] Caught error:', error, info.componentStack);\n }\n\n render() {\n if (this.state.error) {\n return (\n <Alert severity=\"warning\" title=\"Configuration wizard unavailable\">\n Could not load the configuration wizard\n {this.props.dsName ? ` for ${this.props.dsName}` : ''}. Use the Settings link to configure this datasource\n manually.\n </Alert>\n );\n }\n return this.props.children;\n }\n}\n"],"names":[],"mappings":";;;;;;AAIO,MAAM,gCAAgC,SAG3C,CAAA;AAAA,EAHK,WAAA,GAAA;AAAA,IAAA,KAAA,CAAA,GAAA,SAAA,CAAA;AAIL,IAAiC,aAAA,CAAA,IAAA,EAAA,OAAA,EAAA,EAAE,OAAO,IAAK,EAAA,CAAA;AAAA;AAAA,EAE/C,OAAO,yBAAyB,KAAc,EAAA;AAC5C,IAAA,OAAO,EAAE,KAAM,EAAA;AAAA;AACjB,EAEA,iBAAA,CAAkB,OAAc,IAAiB,EAAA;AAC/C,IAAA,OAAA,CAAQ,KAAM,CAAA,wCAAA,EAA0C,KAAO,EAAA,IAAA,CAAK,cAAc,CAAA;AAAA;AACpF,EAEA,MAAS,GAAA;AACP,IAAI,IAAA,IAAA,CAAK,MAAM,KAAO,EAAA;AACpB,MAAA,2CACG,KAAM,EAAA,EAAA,QAAA,EAAS,SAAU,EAAA,KAAA,EAAM,sCAAmC,yCAEhE,EAAA,IAAA,CAAK,KAAM,CAAA,MAAA,GAAS,QAAQ,IAAK,CAAA,KAAA,CAAM,MAAM,CAAA,CAAA,GAAK,IAAG,gEAExD,CAAA;AAAA;AAGJ,IAAA,OAAO,KAAK,KAAM,CAAA,QAAA;AAAA;AAEtB;;;;"}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { SecureFieldInput } from './inputs/SecureFieldInput.js';
|
|
3
|
+
import { StringArrayInput } from './inputs/StringArrayInput.js';
|
|
4
|
+
import { IndexedPairEditor } from './inputs/IndexedPairEditor.js';
|
|
5
|
+
import { FileUploadField } from './inputs/FileUploadField.js';
|
|
6
|
+
import { ObjectArrayEditor } from './inputs/ObjectArrayEditor.js';
|
|
7
|
+
import { ComplexFieldNote } from './inputs/ComplexFieldNote.js';
|
|
8
|
+
import { RadioInput, SelectInput, BooleanInput, NumberInput, TextAreaInput, TextInput } from './inputs/PrimitiveInputs.js';
|
|
9
|
+
|
|
10
|
+
function resolveFieldInputKind(field, hasSetValue) {
|
|
11
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
|
|
12
|
+
if (((_a = field.ui) == null ? undefined : _a.component) === "fileUpload" && field.ui.fileMapping && hasSetValue) {
|
|
13
|
+
return "fileUpload";
|
|
14
|
+
}
|
|
15
|
+
if (field.target === "secureJsonData") {
|
|
16
|
+
return "secure";
|
|
17
|
+
}
|
|
18
|
+
if (((_b = field.ui) == null ? undefined : _b.component) === "radio") {
|
|
19
|
+
return "radio";
|
|
20
|
+
}
|
|
21
|
+
if (((_c = field.ui) == null ? undefined : _c.component) === "select") {
|
|
22
|
+
return "select";
|
|
23
|
+
}
|
|
24
|
+
if (field.valueType === "boolean") {
|
|
25
|
+
return "boolean";
|
|
26
|
+
}
|
|
27
|
+
if (field.valueType === "number") {
|
|
28
|
+
return "number";
|
|
29
|
+
}
|
|
30
|
+
if (((_d = field.ui) == null ? undefined : _d.component) === "textarea") {
|
|
31
|
+
return "textarea";
|
|
32
|
+
}
|
|
33
|
+
if (((_e = field.storage) == null ? undefined : _e.type) === "indexedPair") {
|
|
34
|
+
return "indexedPair";
|
|
35
|
+
}
|
|
36
|
+
if (field.valueType === "array" && ((_f = field.item) == null ? undefined : _f.valueType) === "string") {
|
|
37
|
+
return "stringArray";
|
|
38
|
+
}
|
|
39
|
+
if (field.valueType === "array" && ((_g = field.item) == null ? undefined : _g.valueType) === "object" && ((_h = field.item.fields) == null ? undefined : _h.length)) {
|
|
40
|
+
return "objectArray";
|
|
41
|
+
}
|
|
42
|
+
if (field.valueType === "object" || field.valueType === "map" || field.valueType === "array" && (((_i = field.item) == null ? undefined : _i.valueType) === "object" || ((_j = field.item) == null ? undefined : _j.valueType) === "map")) {
|
|
43
|
+
return "complex";
|
|
44
|
+
}
|
|
45
|
+
return "text";
|
|
46
|
+
}
|
|
47
|
+
function SecureInput({ field, formField, disabled }) {
|
|
48
|
+
var _a, _b, _c;
|
|
49
|
+
const label = (_a = field.label) != null ? _a : field.key;
|
|
50
|
+
return /* @__PURE__ */ React.createElement(
|
|
51
|
+
SecureFieldInput,
|
|
52
|
+
{
|
|
53
|
+
formField,
|
|
54
|
+
placeholder: (_c = (_b = field.ui) == null ? undefined : _b.placeholder) != null ? _c : label,
|
|
55
|
+
disabled,
|
|
56
|
+
label
|
|
57
|
+
}
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
function FileUploadInput({ field, formField, disabled, setValue }) {
|
|
61
|
+
if (!setValue) {
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
return /* @__PURE__ */ React.createElement(FileUploadField, { field, formField, disabled, setValue });
|
|
65
|
+
}
|
|
66
|
+
function IndexedPairInput({ field, formField, disabled }) {
|
|
67
|
+
var _a, _b, _c, _d, _e;
|
|
68
|
+
const items = Array.isArray(formField.value) ? formField.value : [];
|
|
69
|
+
const maxItems = (_c = (_b = (_a = field.validations) == null ? undefined : _a.find((v) => v.type === "itemCount")) == null ? undefined : _b.max) != null ? _c : 10;
|
|
70
|
+
const itemLabel = (_e = (_d = field.label) == null ? undefined : _d.toLowerCase().replace(/s$/, "")) != null ? _e : "header";
|
|
71
|
+
return /* @__PURE__ */ React.createElement(
|
|
72
|
+
IndexedPairEditor,
|
|
73
|
+
{
|
|
74
|
+
value: items,
|
|
75
|
+
onChange: formField.onChange,
|
|
76
|
+
maxItems,
|
|
77
|
+
disabled,
|
|
78
|
+
itemLabel
|
|
79
|
+
}
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
function StringArrayField({ field, formField, disabled }) {
|
|
83
|
+
var _a, _b;
|
|
84
|
+
const label = (_a = field.label) != null ? _a : field.key;
|
|
85
|
+
return /* @__PURE__ */ React.createElement(
|
|
86
|
+
StringArrayInput,
|
|
87
|
+
{
|
|
88
|
+
value: Array.isArray(formField.value) ? formField.value : [],
|
|
89
|
+
onChange: formField.onChange,
|
|
90
|
+
placeholder: (_b = field.ui) == null ? undefined : _b.placeholder,
|
|
91
|
+
disabled,
|
|
92
|
+
itemLabel: label.toLowerCase().replace(/s$/, "")
|
|
93
|
+
}
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
function ObjectArrayInput({ field, formField, disabled, errorMessage }) {
|
|
97
|
+
return /* @__PURE__ */ React.createElement(
|
|
98
|
+
ObjectArrayEditor,
|
|
99
|
+
{
|
|
100
|
+
field,
|
|
101
|
+
value: formField.value,
|
|
102
|
+
onChange: formField.onChange,
|
|
103
|
+
disabled,
|
|
104
|
+
errorMessage
|
|
105
|
+
}
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
function ComplexInput({ field, formField }) {
|
|
109
|
+
var _a;
|
|
110
|
+
const label = (_a = field.label) != null ? _a : field.key;
|
|
111
|
+
const count = Array.isArray(formField.value) ? formField.value.length : 0;
|
|
112
|
+
return /* @__PURE__ */ React.createElement(ComplexFieldNote, { count, label });
|
|
113
|
+
}
|
|
114
|
+
const FIELD_INPUTS = {
|
|
115
|
+
fileUpload: FileUploadInput,
|
|
116
|
+
secure: SecureInput,
|
|
117
|
+
radio: RadioInput,
|
|
118
|
+
select: SelectInput,
|
|
119
|
+
boolean: BooleanInput,
|
|
120
|
+
number: NumberInput,
|
|
121
|
+
textarea: TextAreaInput,
|
|
122
|
+
indexedPair: IndexedPairInput,
|
|
123
|
+
stringArray: StringArrayField,
|
|
124
|
+
objectArray: ObjectArrayInput,
|
|
125
|
+
complex: ComplexInput,
|
|
126
|
+
text: TextInput
|
|
127
|
+
};
|
|
128
|
+
function FieldInput(props) {
|
|
129
|
+
const kind = resolveFieldInputKind(props.field, props.setValue !== undefined);
|
|
130
|
+
const Component = FIELD_INPUTS[kind];
|
|
131
|
+
return /* @__PURE__ */ React.createElement(Component, { ...props });
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
export { FieldInput, resolveFieldInputKind };
|
|
135
|
+
//# sourceMappingURL=FieldInput.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FieldInput.js","sources":["../../../../../src/components/ConfigEditor/DatasourceConfigWizard/FieldInput.tsx"],"sourcesContent":["import React from 'react';\nimport type { ConfigField } from '../../../schema/schema';\nimport type { IndexedPairItem } from './datasource';\nimport type { FieldInputProps } from './inputs/types';\nimport { SecureFieldInput } from './inputs/SecureFieldInput';\nimport { StringArrayInput } from './inputs/StringArrayInput';\nimport { IndexedPairEditor } from './inputs/IndexedPairEditor';\nimport { FileUploadField } from './inputs/FileUploadField';\nimport { ObjectArrayEditor } from './inputs/ObjectArrayEditor';\nimport { ComplexFieldNote } from './inputs/ComplexFieldNote';\nimport { TextInput, NumberInput, BooleanInput, TextAreaInput, SelectInput, RadioInput } from './inputs/PrimitiveInputs';\n\nexport type { FieldInputProps };\n\n/** Discriminant identifying which input component renders a field. */\nexport type FieldInputKind =\n | 'fileUpload'\n | 'secure'\n | 'radio'\n | 'select'\n | 'boolean'\n | 'number'\n | 'textarea'\n | 'indexedPair'\n | 'stringArray'\n | 'objectArray'\n | 'complex'\n | 'text';\n\n/**\n * Resolve a field to its input kind.\n *\n * Order matters: earlier rules win. Cross-cutting storage concerns (secure\n * storage, indexed-pair storage) intentionally take precedence over\n * `valueType`, and an explicit `ui.component` (radio/select/textarea) takes\n * precedence over the type-derived default. `fileUpload` requires `setValue`\n * because it distributes parsed values across sibling fields.\n */\nexport function resolveFieldInputKind(field: ConfigField, hasSetValue: boolean): FieldInputKind {\n if (field.ui?.component === 'fileUpload' && field.ui.fileMapping && hasSetValue) {\n return 'fileUpload';\n }\n if (field.target === 'secureJsonData') {\n return 'secure';\n }\n if (field.ui?.component === 'radio') {\n return 'radio';\n }\n if (field.ui?.component === 'select') {\n return 'select';\n }\n if (field.valueType === 'boolean') {\n return 'boolean';\n }\n if (field.valueType === 'number') {\n return 'number';\n }\n if (field.ui?.component === 'textarea') {\n return 'textarea';\n }\n if (field.storage?.type === 'indexedPair') {\n return 'indexedPair';\n }\n if (field.valueType === 'array' && field.item?.valueType === 'string') {\n return 'stringArray';\n }\n if (field.valueType === 'array' && field.item?.valueType === 'object' && field.item.fields?.length) {\n return 'objectArray';\n }\n if (\n field.valueType === 'object' ||\n field.valueType === 'map' ||\n (field.valueType === 'array' && (field.item?.valueType === 'object' || field.item?.valueType === 'map'))\n ) {\n return 'complex';\n }\n return 'text';\n}\n\n// ── Adapters: map the normalized FieldInputProps onto each leaf component's own API ──\n\n/** Password/token stored in secureJsonData. */\nfunction SecureInput({ field, formField, disabled }: FieldInputProps) {\n const label = field.label ?? field.key;\n return (\n <SecureFieldInput\n formField={formField}\n placeholder={field.ui?.placeholder ?? label}\n disabled={disabled}\n label={label}\n />\n );\n}\n\n/** JSON file upload that distributes parsed keys across sibling fields. */\nfunction FileUploadInput({ field, formField, disabled, setValue }: FieldInputProps) {\n // Only reachable when setValue exists (see resolveFieldInputKind), but guard anyway.\n if (!setValue) {\n return null;\n }\n return <FileUploadField field={field} formField={formField} disabled={disabled} setValue={setValue} />;\n}\n\n/** Editable key/value list backed by indexed storage (e.g. HTTP headers). */\nfunction IndexedPairInput({ field, formField, disabled }: FieldInputProps) {\n const items = Array.isArray(formField.value) ? (formField.value as IndexedPairItem[]) : [];\n const maxItems =\n field.validations?.find((v): v is { type: 'itemCount'; max?: number } => v.type === 'itemCount')?.max ?? 10;\n const itemLabel = field.label?.toLowerCase().replace(/s$/, '') ?? 'header';\n return (\n <IndexedPairEditor\n value={items}\n onChange={formField.onChange}\n maxItems={maxItems}\n disabled={disabled}\n itemLabel={itemLabel}\n />\n );\n}\n\n/** Row-based editor for an array of strings. */\nfunction StringArrayField({ field, formField, disabled }: FieldInputProps) {\n const label = field.label ?? field.key;\n return (\n <StringArrayInput\n value={Array.isArray(formField.value) ? (formField.value as string[]) : []}\n onChange={formField.onChange}\n placeholder={field.ui?.placeholder}\n disabled={disabled}\n itemLabel={label.toLowerCase().replace(/s$/, '')}\n />\n );\n}\n\n/** Inline editor for an array of objects with defined item fields. */\nfunction ObjectArrayInput({ field, formField, disabled, errorMessage }: FieldInputProps) {\n return (\n <ObjectArrayEditor\n field={field}\n value={formField.value}\n onChange={formField.onChange}\n disabled={disabled}\n errorMessage={errorMessage}\n />\n );\n}\n\n/** Read-only note for complex shapes not editable in the wizard. */\nfunction ComplexInput({ field, formField }: FieldInputProps) {\n const label = field.label ?? field.key;\n const count = Array.isArray(formField.value) ? formField.value.length : 0;\n return <ComplexFieldNote count={count} label={label} />;\n}\n\n/** Registry mapping each resolved kind to its renderer. */\nconst FIELD_INPUTS: Record<FieldInputKind, React.ComponentType<FieldInputProps>> = {\n fileUpload: FileUploadInput,\n secure: SecureInput,\n radio: RadioInput,\n select: SelectInput,\n boolean: BooleanInput,\n number: NumberInput,\n textarea: TextAreaInput,\n indexedPair: IndexedPairInput,\n stringArray: StringArrayField,\n objectArray: ObjectArrayInput,\n complex: ComplexInput,\n text: TextInput,\n};\n\n/**\n * Render the appropriate input for a schema field.\n *\n * Replaces the former `renderFieldInput` switch with a resolver + component\n * registry: each input is an independently testable component, and adding a\n * new input means extending the registry rather than editing a growing\n * conditional.\n */\nexport function FieldInput(props: FieldInputProps) {\n const kind = resolveFieldInputKind(props.field, props.setValue !== undefined);\n const Component = FIELD_INPUTS[kind];\n return <Component {...props} />;\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Controller } from '../../../node_modules/react-hook-form/dist/index.esm.js';
|
|
3
|
+
import { useStyles2, Tooltip, Icon } from '@grafana/ui';
|
|
4
|
+
import { resolveActiveOverride, formKey } from './config.js';
|
|
5
|
+
import { isFieldRequired, buildValidationRules, parseItemErrors } from './fieldUtils.js';
|
|
6
|
+
import { PdcFieldNote } from './inputs/PdcFieldNote.js';
|
|
7
|
+
import { FieldInput } from './FieldInput.js';
|
|
8
|
+
import { getFieldStyles } from './styles.js';
|
|
9
|
+
|
|
10
|
+
function SchemaField({
|
|
11
|
+
field,
|
|
12
|
+
control,
|
|
13
|
+
errors,
|
|
14
|
+
disabled,
|
|
15
|
+
dsUid,
|
|
16
|
+
watchedValues,
|
|
17
|
+
fieldById,
|
|
18
|
+
celContext,
|
|
19
|
+
setValue
|
|
20
|
+
}) {
|
|
21
|
+
const styles = useStyles2(getFieldStyles);
|
|
22
|
+
const activeOverride = resolveActiveOverride(field, watchedValues, fieldById);
|
|
23
|
+
const fk = formKey(field);
|
|
24
|
+
if (field.key === "pdcInjected" && field.target === "jsonData") {
|
|
25
|
+
return /* @__PURE__ */ React.createElement(
|
|
26
|
+
Controller,
|
|
27
|
+
{
|
|
28
|
+
name: fk,
|
|
29
|
+
control,
|
|
30
|
+
render: ({ field: formField }) => /* @__PURE__ */ React.createElement(
|
|
31
|
+
PdcFieldNote,
|
|
32
|
+
{
|
|
33
|
+
enabled: !!formField.value,
|
|
34
|
+
description: field.description,
|
|
35
|
+
configUrl: `/connections/datasources/edit/${dsUid}`
|
|
36
|
+
}
|
|
37
|
+
)
|
|
38
|
+
}
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
const required = isFieldRequired(field, watchedValues, fieldById, celContext);
|
|
42
|
+
const validationRules = buildValidationRules(field, required);
|
|
43
|
+
return /* @__PURE__ */ React.createElement(
|
|
44
|
+
Controller,
|
|
45
|
+
{
|
|
46
|
+
name: fk,
|
|
47
|
+
control,
|
|
48
|
+
rules: validationRules,
|
|
49
|
+
render: ({ field: formField }) => {
|
|
50
|
+
var _a, _b, _c, _d, _e;
|
|
51
|
+
const errorMessage = (_a = errors[fk]) == null ? undefined : _a.message;
|
|
52
|
+
const label = (_b = field.label) != null ? _b : field.key;
|
|
53
|
+
const description = (_c = activeOverride == null ? undefined : activeOverride.description) != null ? _c : field.description;
|
|
54
|
+
const effectiveField = activeOverride ? {
|
|
55
|
+
...field,
|
|
56
|
+
description,
|
|
57
|
+
ui: {
|
|
58
|
+
...field.ui,
|
|
59
|
+
placeholder: (_e = activeOverride.placeholder) != null ? _e : (_d = field.ui) == null ? undefined : _d.placeholder
|
|
60
|
+
}
|
|
61
|
+
} : field;
|
|
62
|
+
const isReadOnly = !!(activeOverride == null ? undefined : activeOverride.readOnly);
|
|
63
|
+
const isBool = field.valueType === "boolean";
|
|
64
|
+
return /* @__PURE__ */ React.createElement("div", { className: isBool ? styles.fieldRowCenter : styles.fieldRow }, /* @__PURE__ */ React.createElement("div", { className: isBool ? styles.fieldLabelRowCompact : styles.fieldLabelRow }, /* @__PURE__ */ React.createElement("span", { className: styles.fieldLabel }, label, required && /* @__PURE__ */ React.createElement("span", { className: styles.fieldRequired }, "*")), description && /* @__PURE__ */ React.createElement(Tooltip, { content: description }, /* @__PURE__ */ React.createElement(Icon, { name: "info-circle", size: "xs", className: styles.fieldInfoIcon }))), /* @__PURE__ */ React.createElement("div", { className: styles.fieldInputCol }, /* @__PURE__ */ React.createElement(
|
|
65
|
+
FieldInput,
|
|
66
|
+
{
|
|
67
|
+
field: effectiveField,
|
|
68
|
+
formField,
|
|
69
|
+
disabled: disabled || isReadOnly,
|
|
70
|
+
errorMessage,
|
|
71
|
+
setValue
|
|
72
|
+
}
|
|
73
|
+
), errorMessage && !parseItemErrors(errorMessage) && /* @__PURE__ */ React.createElement("span", { className: styles.fieldError }, errorMessage)));
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export { SchemaField };
|
|
80
|
+
//# sourceMappingURL=SchemaField.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SchemaField.js","sources":["../../../../../src/components/ConfigEditor/DatasourceConfigWizard/SchemaField.tsx"],"sourcesContent":["import React from 'react';\nimport { type useForm, Controller } from 'react-hook-form';\nimport { useStyles2, Icon, Tooltip } from '@grafana/ui';\nimport type { ConfigField } from '../../../schema/schema';\nimport { resolveActiveOverride, formKey } from './config';\nimport type { FormValues } from './datasource';\nimport { isFieldRequired, buildValidationRules, parseItemErrors } from './fieldUtils';\nimport { PdcFieldNote } from './inputs/PdcFieldNote';\nimport { FieldInput } from './FieldInput';\nimport { getFieldStyles } from './styles';\n\nexport type SchemaFieldProps = {\n field: ConfigField;\n control: ReturnType<typeof useForm<FormValues>>['control'];\n errors: ReturnType<typeof useForm<FormValues>>['formState']['errors'];\n disabled?: boolean;\n dsUid: string;\n watchedValues: Record<string, unknown>;\n fieldById: Map<string, ConfigField>;\n celContext?: Record<string, unknown>;\n setValue?: (name: string, value: unknown) => void;\n};\n\nexport function SchemaField({\n field,\n control,\n errors,\n disabled,\n dsUid,\n watchedValues,\n fieldById,\n celContext,\n setValue,\n}: SchemaFieldProps) {\n const styles = useStyles2(getFieldStyles);\n\n const activeOverride = resolveActiveOverride(field, watchedValues, fieldById);\n const fk = formKey(field);\n\n if (field.key === 'pdcInjected' && field.target === 'jsonData') {\n return (\n <Controller\n name={fk}\n control={control}\n render={({ field: formField }) => (\n <PdcFieldNote\n enabled={!!formField.value}\n description={field.description}\n configUrl={`/connections/datasources/edit/${dsUid}`}\n />\n )}\n />\n );\n }\n\n const required = isFieldRequired(field, watchedValues, fieldById, celContext);\n const validationRules = buildValidationRules(field, required);\n\n return (\n <Controller\n name={fk}\n control={control}\n rules={validationRules}\n render={({ field: formField }) => {\n const errorMessage = errors[fk]?.message as string | undefined;\n const label = field.label ?? field.key;\n const description = activeOverride?.description ?? field.description;\n const effectiveField = activeOverride\n ? {\n ...field,\n description,\n ui: {\n ...field.ui,\n placeholder: activeOverride.placeholder ?? field.ui?.placeholder,\n } as ConfigField['ui'],\n }\n : field;\n const isReadOnly = !!activeOverride?.readOnly;\n const isBool = field.valueType === 'boolean';\n\n return (\n <div className={isBool ? styles.fieldRowCenter : styles.fieldRow}>\n <div className={isBool ? styles.fieldLabelRowCompact : styles.fieldLabelRow}>\n <span className={styles.fieldLabel}>\n {label}\n {required && <span className={styles.fieldRequired}>*</span>}\n </span>\n {description && (\n <Tooltip content={description}>\n <Icon name=\"info-circle\" size=\"xs\" className={styles.fieldInfoIcon} />\n </Tooltip>\n )}\n </div>\n <div className={styles.fieldInputCol}>\n <FieldInput\n field={effectiveField}\n formField={formField}\n disabled={disabled || isReadOnly}\n errorMessage={errorMessage}\n setValue={setValue}\n />\n {/* Show global error only if it's NOT a per-item error (those render inline) */}\n {errorMessage && !parseItemErrors(errorMessage) && (\n <span className={styles.fieldError}>{errorMessage}</span>\n )}\n </div>\n </div>\n );\n }}\n />\n );\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { cx } from '@emotion/css';
|
|
3
|
+
import { useStyles2 } from '@grafana/ui';
|
|
4
|
+
import { getTabStyles } from './styles.js';
|
|
5
|
+
|
|
6
|
+
function SidebarNav({ groups, activeIndex, sectionStates, onSelect }) {
|
|
7
|
+
const styles = useStyles2(getTabStyles);
|
|
8
|
+
const visibleGroups = groups.filter((g) => g.group.id !== "_required");
|
|
9
|
+
return /* @__PURE__ */ React.createElement("nav", { className: styles.sidebar }, /* @__PURE__ */ React.createElement("div", { className: styles.sidebarTitle }, "Connect data source"), /* @__PURE__ */ React.createElement("ul", { className: styles.navList }, visibleGroups.map((g, vi) => {
|
|
10
|
+
var _a, _b;
|
|
11
|
+
const origIndex = groups.indexOf(g);
|
|
12
|
+
const state = (_a = sectionStates[origIndex]) != null ? _a : "draft";
|
|
13
|
+
const isActive = origIndex === activeIndex;
|
|
14
|
+
const isOptional = g.group.optional === true;
|
|
15
|
+
const isLast = vi === visibleGroups.length - 1;
|
|
16
|
+
const nextIsOptional = !isLast && ((_b = visibleGroups[vi + 1]) == null ? undefined : _b.group.optional) === true;
|
|
17
|
+
return /* @__PURE__ */ React.createElement("li", { key: g.group.id }, /* @__PURE__ */ React.createElement(
|
|
18
|
+
"div",
|
|
19
|
+
{
|
|
20
|
+
className: cx(styles.navItem, isActive && styles.navItemActive),
|
|
21
|
+
onClick: () => onSelect(origIndex),
|
|
22
|
+
role: "button",
|
|
23
|
+
tabIndex: 0,
|
|
24
|
+
onKeyDown: (e) => {
|
|
25
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
26
|
+
e.preventDefault();
|
|
27
|
+
onSelect(origIndex);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
/* @__PURE__ */ React.createElement("div", { className: styles.navDotWrap }, /* @__PURE__ */ React.createElement(
|
|
32
|
+
"span",
|
|
33
|
+
{
|
|
34
|
+
className: cx(
|
|
35
|
+
styles.navDot,
|
|
36
|
+
isOptional && styles.navDotOptional,
|
|
37
|
+
isActive && styles.navDotActive,
|
|
38
|
+
state === "validated" && !isActive && styles.navDotValidated,
|
|
39
|
+
state === "error" && !isActive && styles.navDotError
|
|
40
|
+
)
|
|
41
|
+
}
|
|
42
|
+
), !isLast && /* @__PURE__ */ React.createElement(
|
|
43
|
+
"div",
|
|
44
|
+
{
|
|
45
|
+
className: cx(styles.navConnector, (isOptional || nextIsOptional) && styles.navConnectorDashed)
|
|
46
|
+
}
|
|
47
|
+
)),
|
|
48
|
+
/* @__PURE__ */ React.createElement("span", { className: cx(styles.navLabel, isActive && styles.navLabelActive) }, g.group.title)
|
|
49
|
+
));
|
|
50
|
+
})));
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export { SidebarNav };
|
|
54
|
+
//# sourceMappingURL=SidebarNav.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SidebarNav.js","sources":["../../../../../src/components/ConfigEditor/DatasourceConfigWizard/SidebarNav.tsx"],"sourcesContent":["import React from 'react';\nimport { cx } from '@emotion/css';\nimport { useStyles2 } from '@grafana/ui';\nimport type { ResolvedGroup } from './hooks/useDatasourceConfigForm';\nimport { getTabStyles } from './styles';\n\nexport type SectionState = 'active' | 'draft' | 'validated' | 'error';\n\ntype SidebarNavProps = {\n groups: ResolvedGroup[];\n activeIndex: number;\n sectionStates: SectionState[];\n onSelect: (index: number) => void;\n};\n\nexport function SidebarNav({ groups, activeIndex, sectionStates, onSelect }: SidebarNavProps) {\n const styles = useStyles2(getTabStyles);\n\n // Filter out _required synthetic group\n const visibleGroups = groups.filter((g) => g.group.id !== '_required');\n\n return (\n <nav className={styles.sidebar}>\n <div className={styles.sidebarTitle}>Connect data source</div>\n <ul className={styles.navList}>\n {visibleGroups.map((g, vi) => {\n // Map back to original index for state/selection\n const origIndex = groups.indexOf(g);\n const state = sectionStates[origIndex] ?? 'draft';\n const isActive = origIndex === activeIndex;\n const isOptional = g.group.optional === true;\n const isLast = vi === visibleGroups.length - 1;\n // Next item determines connector style\n const nextIsOptional = !isLast && visibleGroups[vi + 1]?.group.optional === true;\n\n return (\n <li key={g.group.id}>\n <div\n className={cx(styles.navItem, isActive && styles.navItemActive)}\n onClick={() => onSelect(origIndex)}\n role=\"button\"\n tabIndex={0}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n onSelect(origIndex);\n }\n }}\n >\n <div className={styles.navDotWrap}>\n <span\n className={cx(\n styles.navDot,\n isOptional && styles.navDotOptional,\n isActive && styles.navDotActive,\n state === 'validated' && !isActive && styles.navDotValidated,\n state === 'error' && !isActive && styles.navDotError\n )}\n />\n {!isLast && (\n <div\n className={cx(styles.navConnector, (isOptional || nextIsOptional) && styles.navConnectorDashed)}\n />\n )}\n </div>\n <span className={cx(styles.navLabel, isActive && styles.navLabelActive)}>{g.group.title}</span>\n </div>\n </li>\n );\n })}\n </ul>\n </nav>\n );\n}\n"],"names":[],"mappings":"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"}
|