From 78d37f203c79b586f1cb15275cfe4a99c51c7e19 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Dominik=20S=C3=BC=C3=9F?=
Date: Wed, 18 Dec 2024 13:59:04 +0100
Subject: [PATCH] refactor: use react-hook-form directly (#18)
---
.../common/AuthenticationEditor.tsx | 57 ++--
.../ComponentEditor/common/RelabelRules.tsx | 255 +++++++++---------
.../ComponentEditor/common/StaticTargets.tsx | 101 ++++---
.../ComponentEditor/common/TargetSelector.tsx | 25 +-
.../ComponentEditor/common/TlsBlock.tsx | 33 ++-
.../ComponentEditor/common/TlsConfig.tsx | 12 +-
.../components/DiscoveryEc2.tsx | 129 +++++----
.../components/DiscoveryKubernetes.tsx | 154 +++++------
.../components/DiscoveryRelabel.tsx | 15 +-
.../ComponentEditor/components/ImportGit.tsx | 18 +-
.../components/LocalFileMatch.tsx | 103 ++++---
.../components/LokiProcess.tsx | 189 ++++++-------
.../components/LokiRelabel.tsx | 18 +-
.../components/LokiSourceFile.tsx | 17 +-
.../components/LokiSourceJournal.tsx | 26 +-
.../components/LokiSourceWindowsEvent.tsx | 38 ++-
.../ComponentEditor/components/LokiWrite.tsx | 42 +--
.../components/OTelColExporterLoki.tsx | 8 +-
.../components/OTelColExporterPrometheus.tsx | 20 +-
.../components/OTelColProcessorBatch.tsx | 18 +-
.../components/OTelColReceiverOTLP.tsx | 11 +-
.../components/PrometheusExporterGithub.tsx | 27 +-
.../components/PrometheusExporterMysql.tsx | 17 +-
.../components/PrometheusExporterRedis.tsx | 97 ++++---
.../components/PrometheusExporterUnix.tsx | 39 ++-
.../components/PrometheusExporterWindows.tsx | 12 +-
.../components/PrometheusRelabel.tsx | 15 +-
.../components/PrometheusRemoteWrite.tsx | 93 +++----
.../components/PrometheusScrape.tsx | 57 ++--
.../components/PyroscopeScrape.tsx | 41 ++-
.../modules/GrafanaCloudAutoConfigure.tsx | 17 +-
src/components/ComponentEditor/index.tsx | 103 ++++---
.../inputs/GenericStringMap.tsx | 72 +++--
.../ComponentEditor/inputs/LabelsInput.tsx | 70 +++--
.../ComponentEditor/inputs/MultiBlock.tsx | 59 ++--
.../inputs/ReferenceMultiSelect.tsx | 6 +-
.../inputs/ReferenceSelect.tsx | 6 +-
.../ComponentEditor/inputs/TypedInput.tsx | 17 +-
src/lib/components.ts | 7 +-
39 files changed, 982 insertions(+), 1062 deletions(-)
diff --git a/src/components/ComponentEditor/common/AuthenticationEditor.tsx b/src/components/ComponentEditor/common/AuthenticationEditor.tsx
index 41e1a5f..ffcaa97 100644
--- a/src/components/ComponentEditor/common/AuthenticationEditor.tsx
+++ b/src/components/ComponentEditor/common/AuthenticationEditor.tsx
@@ -2,12 +2,11 @@ import { SelectableValue } from "@grafana/data";
import {
Alert,
FieldSet,
- FormAPI,
InlineField,
- InputControl,
MultiSelect,
RadioButtonGroup,
} from "@grafana/ui";
+import { Controller, useFormContext } from "react-hook-form";
import TypedInput from "../inputs/TypedInput";
type AuthenticationType =
@@ -18,16 +17,15 @@ type AuthenticationType =
| "authorization"
| "oauth2";
const Component = ({
- methods,
options,
defaultValue,
parent,
}: {
- methods: FormAPI>;
options?: AuthenticationType[];
defaultValue?: AuthenticationType;
parent?: string;
}) => {
+ const { watch, control } = useFormContext();
const commonOptions = {
labelWidth: 24,
};
@@ -38,12 +36,12 @@ const Component = ({
defaultValue = "none";
}
parent = parent ? parent + "." : "";
- const watchAuthType = methods.watch(`${parent}auth_type` as const);
+ const watchAuthType = watch(`${parent}auth_type` as const);
return (
-
- {({ fields, append, remove }) => (
- <>
- {fields.map((field, index) => (
-
-
- (
-
- )}
- />
-
-
-
-
-
-
-
- {
- remove(index);
- e.preventDefault();
- }}
- />
-
- ))}
- append({})} icon="plus">
- Add
-
- >
- )}
-
+ {fields.map((field, index) => (
+
+
+ (
+
+ )}
+ />
+
+
+
+
+
+
+
+ {
+ remove(index);
+ e.preventDefault();
+ }}
+ />
+
+ ))}
+ append({})} icon="plus">
+ Add
+
>
);
diff --git a/src/components/ComponentEditor/components/DiscoveryRelabel.tsx b/src/components/ComponentEditor/components/DiscoveryRelabel.tsx
index f80dc05..3b3304e 100644
--- a/src/components/ComponentEditor/components/DiscoveryRelabel.tsx
+++ b/src/components/ComponentEditor/components/DiscoveryRelabel.tsx
@@ -1,8 +1,13 @@
-import { FormAPI, InlineField } from "@grafana/ui";
+import { InlineField } from "@grafana/ui";
+import { useFormContext } from "react-hook-form";
import { RelabelRules, transformRules } from "../common/RelabelRules";
import ReferenceSelect from "../inputs/ReferenceSelect";
-const Component = ({ methods }: { methods: FormAPI> }) => {
+const Component = () => {
+ const {
+ formState: { errors },
+ control,
+ } = useFormContext();
return (
<>
> }) => {
tooltip="Targets to relabel"
labelWidth={22}
error="You must specify a list of destinations"
- invalid={!!methods.errors["targets"]}
+ invalid={!!errors["targets"]}
>
-
+
>
);
};
diff --git a/src/components/ComponentEditor/components/ImportGit.tsx b/src/components/ComponentEditor/components/ImportGit.tsx
index 11ad899..01db5ce 100644
--- a/src/components/ComponentEditor/components/ImportGit.tsx
+++ b/src/components/ComponentEditor/components/ImportGit.tsx
@@ -1,8 +1,10 @@
-import { FormAPI, InlineField } from "@grafana/ui";
+import { InlineField } from "@grafana/ui";
+import { useFormContext } from "react-hook-form";
import TypedInput from "../inputs/TypedInput";
-const Component = ({ methods }: { methods: FormAPI> }) => {
+const Component = () => {
+ const { control } = useFormContext();
return (
<>
> }) => {
tooltip="Source repository containing an alloy module"
labelWidth={20}
>
-
+
> }) => {
@@ -29,18 +31,14 @@ const Component = ({ methods }: { methods: FormAPI> }) => {
tooltip="Path of the alloy module file to import"
labelWidth={20}
>
-
+
-
+
>
);
diff --git a/src/components/ComponentEditor/components/LocalFileMatch.tsx b/src/components/ComponentEditor/components/LocalFileMatch.tsx
index 8e46452..9de6212 100644
--- a/src/components/ComponentEditor/components/LocalFileMatch.tsx
+++ b/src/components/ComponentEditor/components/LocalFileMatch.tsx
@@ -1,17 +1,24 @@
import {
Button,
- FieldArray,
FieldSet,
- FormAPI,
InlineField,
InlineFieldRow,
Input,
} from "@grafana/ui";
+import { useFieldArray, useFormContext } from "react-hook-form";
-const Component = ({ methods }: { methods: FormAPI> }) => {
+const Component = () => {
const commonOptions = {
labelWidth: 14,
};
+ const { control, register } = useFormContext<{
+ [key: string]: any;
+ path_targets: Array>;
+ }>();
+ const { fields, append, remove } = useFieldArray({
+ control,
+ name: "path_targets",
+ });
return (
<>
> }) => {
tooltip="How often to sync filesystem and targets"
{...commonOptions}
>
-
+
-
- {({ fields, append, remove }) => (
- <>
- {fields.map((field, index) => (
-
-
-
-
-
-
-
- {
- remove(index);
- e.preventDefault();
- }}
- />
-
- ))}
- append({})} icon="plus">
- Add
-
- >
- )}
-
+ {fields.map((field, index) => (
+
+
+
+
+
+
+
+ {
+ remove(index);
+ e.preventDefault();
+ }}
+ />
+
+ ))}
+ append({})} icon="plus">
+ Add
+
>
);
@@ -85,7 +84,7 @@ const LocalFileMatch = {
if (target["__path_exclude__"] === "")
delete target["__path_exclude__"];
return target;
- }
+ },
);
return data;
},
diff --git a/src/components/ComponentEditor/components/LokiProcess.tsx b/src/components/ComponentEditor/components/LokiProcess.tsx
index f2e7c16..b4c000c 100644
--- a/src/components/ComponentEditor/components/LokiProcess.tsx
+++ b/src/components/ComponentEditor/components/LokiProcess.tsx
@@ -4,17 +4,20 @@ import {
Alert,
Button,
Card,
- FieldArray,
FieldSet,
- FormAPI,
IconButton,
InlineField,
InlineSwitch,
- InputControl,
MultiSelect,
Select,
} from "@grafana/ui";
-import { get } from "react-hook-form";
+import {
+ Controller,
+ get,
+ useFieldArray,
+ useFormContext,
+ UseFormReturn,
+} from "react-hook-form";
import { useStyles } from "../../../theme";
import GenericStringMap from "../inputs/GenericStringMap";
import ReferenceMultiSelect from "../inputs/ReferenceMultiSelect";
@@ -35,7 +38,7 @@ const stages = [
value: "stage.drop",
label: "Drop",
description: "Configures a drop processing stage.",
- editor: (parent: string, methods: FormAPI>) => {
+ editor: (parent: string, methods: UseFormReturn) => {
return (
<>
>) => {
+ editor: (parent: string, methods: UseFormReturn) => {
return (
<>
>) => {
+ editor: (parent: string, methods: UseFormReturn) => {
return (
<>
- (
>) => {
+ editor: (parent: string, methods: UseFormReturn) => {
return (
<>
- (
>) => {
+ editor: (parent: string, methods: UseFormReturn) => {
return (
<>
>) => {
+ editor: (parent: string, methods: UseFormReturn) => {
return (
<>
>) => {
+ editor: (parent: string, methods: UseFormReturn) => {
return (
<>
>) => {
+ editor: (parent: string, methods: UseFormReturn) => {
return (
<>
>) => {
+ editor: (_parent: string, _methods: UseFormReturn) => {
return (
@@ -403,7 +406,7 @@ const stages = [
value: "stage.multiline",
label: "Multiline",
description: "Configures a multiline processing stage.",
- editor: (parent: string, methods: FormAPI>) => {
+ editor: (parent: string, methods: UseFormReturn) => {
return (
<>
>) => {
+ editor: (parent: string, methods: UseFormReturn) => {
return (
<>
>) => {
+ editor: (parent: string, methods: UseFormReturn) => {
return (
<>
- (
>) => {
+ editor: (parent: string, methods: UseFormReturn) => {
return (
<>
>) => {
+ editor: (parent: string, methods: UseFormReturn) => {
return (
<>
>) => {
+ editor: (parent: string, methods: UseFormReturn) => {
return (
<>
>) => {
+ editor: (parent: string, methods: UseFormReturn) => {
return (
<>
>) => {
+ editor: (parent: string, methods: UseFormReturn) => {
return (
<>
@@ -640,7 +643,7 @@ const stages = [
value: "stage.timestamp",
label: "Timestamp",
description: "Configures a timestamp processing stage.",
- editor: (parent: string, methods: FormAPI>) => {
+ editor: (parent: string, methods: UseFormReturn) => {
return (
<>
- (
>) => {
+ editor: (parent: string, methods: UseFormReturn) => {
return (
<>
({ [x.value]: x })));
-const Component = ({ methods }: { methods: FormAPI> }) => {
+const Component = () => {
+ const methods = useFormContext();
+ const { control, watch } = methods;
+ const { fields, append, remove, move } = useFieldArray({
+ control,
+ name: "stages",
+ });
const styles = useStyles(getStyles);
return (
<>
@@ -764,75 +773,67 @@ const Component = ({ methods }: { methods: FormAPI> }) => {
-
- {({ fields, append, remove, move, swap }) => (
- <>
- {fields.map((field, index) => {
- const stageType = methods.watch(
- `stages[${index}].comp-name` as const,
- );
- return (
-
-
- (
-
- )}
- control={methods.control}
- name={`stages[${index}].comp-name` as const}
- />
-
-
- {stageType && stageType.description}
-
-
- {stageType?.editor &&
- stageType.editor(`stages[${index}]` as const, methods)}
-
-
- {index !== 0 && (
- {
- move(index, index - 1);
- e.preventDefault();
- }}
- />
- )}
- {index < fields.length - 1 && (
- {
- move(index, index + 1);
- e.preventDefault();
- }}
- />
- )}
- {
- remove(index);
- e.preventDefault();
- }}
- />
-
-
- );
- })}
- append({})} icon="plus">
- Add
-
- >
- )}
-
+ {fields.map((field, index) => {
+ const stageType = watch(`stages[${index}].comp-name` as const);
+ return (
+
+
+ (
+
+ )}
+ control={control}
+ name={`stages[${index}].comp-name` as const}
+ />
+
+
+ {stageType && stageType.description}
+
+
+ {stageType?.editor &&
+ stageType.editor(`stages[${index}]` as const, methods)}
+
+
+ {index !== 0 && (
+ {
+ move(index, index - 1);
+ e.preventDefault();
+ }}
+ />
+ )}
+ {index < fields.length - 1 && (
+ {
+ move(index, index + 1);
+ e.preventDefault();
+ }}
+ />
+ )}
+ {
+ remove(index);
+ e.preventDefault();
+ }}
+ />
+
+
+ );
+ })}
+ append({})} icon="plus">
+ Add
+
>
);
diff --git a/src/components/ComponentEditor/components/LokiRelabel.tsx b/src/components/ComponentEditor/components/LokiRelabel.tsx
index 0107f37..b891ce4 100644
--- a/src/components/ComponentEditor/components/LokiRelabel.tsx
+++ b/src/components/ComponentEditor/components/LokiRelabel.tsx
@@ -1,8 +1,14 @@
-import { FormAPI, InlineField, Input } from "@grafana/ui";
+import { InlineField, Input } from "@grafana/ui";
import ReferenceMultiSelect from "../inputs/ReferenceMultiSelect";
import { RelabelRules, transformRules } from "../common/RelabelRules";
+import { useFormContext } from "react-hook-form";
-const Component = ({ methods }: { methods: FormAPI> }) => {
+const Component = () => {
+ const {
+ formState: { errors },
+ control,
+ register,
+ } = useFormContext();
return (
<>
> }) => {
tooltip="Where to forward log entries after relabeling."
labelWidth={22}
error="You must specify a list of destinations"
- invalid={!!methods.errors["targets"]}
+ invalid={!!errors["targets"]}
>
> }) => {
tooltip="The maximum number of elements to hold in the relabeling cache."
labelWidth={22}
>
-
+
-
+
>
);
};
diff --git a/src/components/ComponentEditor/components/LokiSourceFile.tsx b/src/components/ComponentEditor/components/LokiSourceFile.tsx
index 080e799..68938fb 100644
--- a/src/components/ComponentEditor/components/LokiSourceFile.tsx
+++ b/src/components/ComponentEditor/components/LokiSourceFile.tsx
@@ -1,8 +1,13 @@
-import { FormAPI, InlineField } from "@grafana/ui";
+import { InlineField } from "@grafana/ui";
import ReferenceSelect from "../inputs/ReferenceSelect";
import ReferenceMultiSelect from "../inputs/ReferenceMultiSelect";
+import { useFormContext } from "react-hook-form";
-const Component = ({ methods }: { methods: FormAPI> }) => {
+const Component = () => {
+ const {
+ formState: { errors },
+ control,
+ } = useFormContext();
return (
<>
> }) => {
tooltip="List of files to read from."
labelWidth={14}
error="You must specify the targets parameter"
- invalid={!!methods.errors["targets"]}
+ invalid={!!errors["targets"]}
>
> }) => {
tooltip="List of receivers to send log entries to."
labelWidth={14}
error="You must specify the destination"
- invalid={!!methods.errors["forward_to"]}
+ invalid={!!errors["forward_to"]}
>
>
diff --git a/src/components/ComponentEditor/components/LokiSourceJournal.tsx b/src/components/ComponentEditor/components/LokiSourceJournal.tsx
index 20fd383..71194e3 100644
--- a/src/components/ComponentEditor/components/LokiSourceJournal.tsx
+++ b/src/components/ComponentEditor/components/LokiSourceJournal.tsx
@@ -1,10 +1,16 @@
-import { FieldSet, FormAPI, InlineField, InlineSwitch } from "@grafana/ui";
+import { FieldSet, InlineField, InlineSwitch } from "@grafana/ui";
import ReferenceSelect from "../inputs/ReferenceSelect";
import ReferenceMultiSelect from "../inputs/ReferenceMultiSelect";
import TypedInput from "../inputs/TypedInput";
import LabelsInput from "../inputs/LabelsInput";
+import { useFormContext } from "react-hook-form";
-const Component = ({ methods }: { methods: FormAPI> }) => {
+const Component = () => {
+ const {
+ control,
+ register,
+ formState: { errors },
+ } = useFormContext();
const commonOptions = { labelWidth: 24 };
return (
<>
@@ -13,14 +19,14 @@ const Component = ({ methods }: { methods: FormAPI> }) => {
tooltip="Whether to forward the original journal entry as JSON."
{...commonOptions}
>
-
+
-
+
> }) => {
>
@@ -38,7 +44,7 @@ const Component = ({ methods }: { methods: FormAPI> }) => {
tooltip="Journal matches to filter. The + character is not supported, only logical AND matches will be added."
{...commonOptions}
>
-
+
> }) => {
@@ -57,18 +63,18 @@ const Component = ({ methods }: { methods: FormAPI> }) => {
tooltip="List of receivers to send log entries to."
{...commonOptions}
error="You must specify the destination"
- invalid={!!methods.errors["forward_to"]}
+ invalid={!!errors["forward_to"]}
>
-
+
>
);
diff --git a/src/components/ComponentEditor/components/LokiSourceWindowsEvent.tsx b/src/components/ComponentEditor/components/LokiSourceWindowsEvent.tsx
index 5aff589..49dc260 100644
--- a/src/components/ComponentEditor/components/LokiSourceWindowsEvent.tsx
+++ b/src/components/ComponentEditor/components/LokiSourceWindowsEvent.tsx
@@ -1,9 +1,15 @@
-import { FormAPI, InlineField, InlineSwitch } from "@grafana/ui";
+import { InlineField, InlineSwitch } from "@grafana/ui";
+import { useFormContext } from "react-hook-form";
import ReferenceMultiSelect from "../inputs/ReferenceMultiSelect";
import TypedInput from "../inputs/TypedInput";
-const Component = ({ methods }: { methods: FormAPI> }) => {
+const Component = () => {
const commonOptions = { labelWidth: 24 };
+ const {
+ control,
+ register,
+ formState: { errors },
+ } = useFormContext();
return (
<>
> }) => {
>
@@ -22,12 +28,12 @@ const Component = ({ methods }: { methods: FormAPI> }) => {
tooltip="List of receivers to send log entries to."
{...commonOptions}
error="You must specify the destination"
- invalid={!!methods.errors["forward_to"]}
+ invalid={!!errors["forward_to"]}
>
@@ -37,57 +43,49 @@ const Component = ({ methods }: { methods: FormAPI> }) => {
tooltip="Event log to read from."
{...commonOptions}
>
-
+
-
+
-
+
-
+
-
+
-
+
-
+
>
);
diff --git a/src/components/ComponentEditor/components/LokiWrite.tsx b/src/components/ComponentEditor/components/LokiWrite.tsx
index 1d91666..2099126 100644
--- a/src/components/ComponentEditor/components/LokiWrite.tsx
+++ b/src/components/ComponentEditor/components/LokiWrite.tsx
@@ -1,5 +1,4 @@
import {
- FormAPI,
Input,
Alert,
LinkButton,
@@ -8,15 +7,21 @@ import {
InlineField,
InlineSwitch,
} from "@grafana/ui";
+import { useFormContext } from "react-hook-form";
import AuthenticationEditor from "../common/AuthenticationEditor";
import TlsConfig from "../common/TlsConfig";
import MultiBlock from "../inputs/MultiBlock";
import TypedInput from "../inputs/TypedInput";
-const Component = ({ methods }: { methods: FormAPI> }) => {
+const Component = () => {
const commonOptions = {
labelWidth: 24,
};
+ const {
+ control,
+ register,
+ formState: { errors },
+ } = useFormContext();
return (
<>
@@ -33,7 +38,6 @@ const Component = ({ methods }: { methods: FormAPI> }) => {
> }) => {
label="Endpoint URL"
tooltip="Where to send metrics to"
error="An endpoint URL is required"
- invalid={!!methods.errors["endpoint"]?.url}
+ invalid={!!errors["endpoint"]?.url}
{...commonOptions}
>
@@ -68,7 +71,7 @@ const Component = ({ methods }: { methods: FormAPI> }) => {
>
@@ -80,7 +83,7 @@ const Component = ({ methods }: { methods: FormAPI> }) => {
>
@@ -91,7 +94,7 @@ const Component = ({ methods }: { methods: FormAPI> }) => {
>
@@ -102,7 +105,7 @@ const Component = ({ methods }: { methods: FormAPI> }) => {
>
@@ -113,7 +116,7 @@ const Component = ({ methods }: { methods: FormAPI> }) => {
>
@@ -123,9 +126,9 @@ const Component = ({ methods }: { methods: FormAPI> }) => {
{...commonOptions}
>
@@ -133,7 +136,6 @@ const Component = ({ methods }: { methods: FormAPI> }) => {
@@ -146,7 +148,7 @@ const Component = ({ methods }: { methods: FormAPI> }) => {
>
@@ -157,7 +159,7 @@ const Component = ({ methods }: { methods: FormAPI> }) => {
>
@@ -167,8 +169,8 @@ const Component = ({ methods }: { methods: FormAPI> }) => {
{...commonOptions}
>
@@ -179,9 +181,7 @@ const Component = ({ methods }: { methods: FormAPI> }) => {
{...commonOptions}
>
diff --git a/src/components/ComponentEditor/components/OTelColExporterLoki.tsx b/src/components/ComponentEditor/components/OTelColExporterLoki.tsx
index b0d72f8..0e91397 100644
--- a/src/components/ComponentEditor/components/OTelColExporterLoki.tsx
+++ b/src/components/ComponentEditor/components/OTelColExporterLoki.tsx
@@ -1,16 +1,18 @@
-import { FormAPI, InlineField, VerticalGroup } from "@grafana/ui";
+import { InlineField, VerticalGroup } from "@grafana/ui";
+import { useFormContext } from "react-hook-form";
import ReferenceMultiSelect from "../inputs/ReferenceMultiSelect";
-const Component = ({ methods }: { methods: FormAPI> }) => {
+const Component = () => {
const commonOptions = {
labelWidth: 25,
};
+ const { control } = useFormContext();
return (
<>
diff --git a/src/components/ComponentEditor/components/OTelColExporterPrometheus.tsx b/src/components/ComponentEditor/components/OTelColExporterPrometheus.tsx
index a8072d3..e8509f7 100644
--- a/src/components/ComponentEditor/components/OTelColExporterPrometheus.tsx
+++ b/src/components/ComponentEditor/components/OTelColExporterPrometheus.tsx
@@ -1,22 +1,18 @@
-import {
- FormAPI,
- InlineField,
- InlineSwitch,
- Input,
- VerticalGroup,
-} from "@grafana/ui";
+import { InlineField, InlineSwitch, Input, VerticalGroup } from "@grafana/ui";
+import { useFormContext } from "react-hook-form";
import ReferenceMultiSelect from "../inputs/ReferenceMultiSelect";
-const Component = ({ methods }: { methods: FormAPI> }) => {
+const Component = () => {
const commonOptions = {
labelWidth: 25,
};
+ const { control, register } = useFormContext();
return (
<>
@@ -26,21 +22,21 @@ const Component = ({ methods }: { methods: FormAPI> }) => {
tooltip="Whether to include target_info metrics."
{...commonOptions}
>
-
+
-
+
-
+
>
diff --git a/src/components/ComponentEditor/components/OTelColProcessorBatch.tsx b/src/components/ComponentEditor/components/OTelColProcessorBatch.tsx
index 3ac26b2..5238be9 100644
--- a/src/components/ComponentEditor/components/OTelColProcessorBatch.tsx
+++ b/src/components/ComponentEditor/components/OTelColProcessorBatch.tsx
@@ -1,10 +1,12 @@
-import { FormAPI, InlineField, Input, VerticalGroup } from "@grafana/ui";
+import { InlineField, Input, VerticalGroup } from "@grafana/ui";
+import { useFormContext } from "react-hook-form";
import ReferenceMultiSelect from "../inputs/ReferenceMultiSelect";
-const Component = ({ methods }: { methods: FormAPI> }) => {
+const Component = () => {
const commonOptions = {
labelWidth: 25,
};
+ const { register, control } = useFormContext();
return (
<>
@@ -13,7 +15,7 @@ const Component = ({ methods }: { methods: FormAPI> }) => {
tooltip="How long to wait before flushing the batch."
{...commonOptions}
>
-
+
> }) => {
>
@@ -33,7 +35,7 @@ const Component = ({ methods }: { methods: FormAPI> }) => {
>
> }) => {
diff --git a/src/components/ComponentEditor/components/OTelColReceiverOTLP.tsx b/src/components/ComponentEditor/components/OTelColReceiverOTLP.tsx
index 007a67f..867eb79 100644
--- a/src/components/ComponentEditor/components/OTelColReceiverOTLP.tsx
+++ b/src/components/ComponentEditor/components/OTelColReceiverOTLP.tsx
@@ -1,5 +1,4 @@
import {
- FormAPI,
HorizontalGroup,
InlineField,
Input,
@@ -7,15 +6,17 @@ import {
VerticalGroup,
} from "@grafana/ui";
import { useState } from "react";
+import { useFormContext } from "react-hook-form";
import TlsBlock from "../common/TlsBlock";
import ReferenceMultiSelect from "../inputs/ReferenceMultiSelect";
-const Component = ({ methods }: { methods: FormAPI> }) => {
+const Component = () => {
+ const methods = useFormContext();
const [httpEnableTLS, setHttpEnableTLS] = useState(
- methods.getValues().http?.tls
+ methods.getValues().http?.tls,
);
const [grpcEnableTLS, setGrpcEnableTLS] = useState(
- methods.getValues().grpc?.tls
+ methods.getValues().grpc?.tls,
);
const watchGrpcEnabled = methods.watch("grpc.enabled");
@@ -126,7 +127,6 @@ const Component = ({ methods }: { methods: FormAPI> }) => {
{grpcEnableTLS && (
> }) => {
{httpEnableTLS && (
>;
-}) => {
+const PrometheusExporterGithub = () => {
const commonOptions = {
labelWidth: 14,
};
+ const { register, control } = useFormContext();
return (
-
+
-
+
-
+
{["organizations", "users", "repositories"].map((type) => {
return (
- (
)}
defaultValue={[]}
- control={methods.control}
+ control={control}
name={type}
/>
diff --git a/src/components/ComponentEditor/components/PrometheusExporterMysql.tsx b/src/components/ComponentEditor/components/PrometheusExporterMysql.tsx
index 2629eaf..290bb35 100644
--- a/src/components/ComponentEditor/components/PrometheusExporterMysql.tsx
+++ b/src/components/ComponentEditor/components/PrometheusExporterMysql.tsx
@@ -1,21 +1,22 @@
-import { FormAPI, InlineField, Input } from "@grafana/ui";
+import { InlineField, Input } from "@grafana/ui";
+import { useFormContext } from "react-hook-form";
-const PrometheusExporterMysql = ({
- methods,
-}: {
- methods: FormAPI>;
-}) => {
+const PrometheusExporterMysql = () => {
+ const {
+ register,
+ formState: { errors },
+ } = useFormContext();
return (
<>
diff --git a/src/components/ComponentEditor/components/PrometheusExporterRedis.tsx b/src/components/ComponentEditor/components/PrometheusExporterRedis.tsx
index 7208426..bd4b860 100644
--- a/src/components/ComponentEditor/components/PrometheusExporterRedis.tsx
+++ b/src/components/ComponentEditor/components/PrometheusExporterRedis.tsx
@@ -1,31 +1,26 @@
-import {
- FormAPI,
- InlineField,
- InlineSwitch,
- Input,
- InputControl,
- MultiSelect,
-} from "@grafana/ui";
+import { InlineField, InlineSwitch, Input, MultiSelect } from "@grafana/ui";
+import { Controller, useFormContext } from "react-hook-form";
-const PrometheusExporterRedis = ({
- methods,
-}: {
- methods: FormAPI>;
-}) => {
+const PrometheusExporterRedis = () => {
const commonOptions = {
labelWidth: 26,
};
+ const {
+ register,
+ control,
+ formState: { errors },
+ } = useFormContext();
return (
<>
@@ -34,35 +29,35 @@ const PrometheusExporterRedis = ({
tooltip="User name to use for authentication (Redis ACL for Redis 6.0 and newer)."
{...commonOptions}
>
-
+
-
+
-
+
-
+
-
+
Advanced Options
-
+
-
+
-
+
-
+
-
+
-
+
-
+
- (
)}
defaultValue={[]}
- control={methods.control}
+ control={control}
name="check_keys"
/>
@@ -140,7 +135,7 @@ const PrometheusExporterRedis = ({
tooltip="List of Lua regular expressions (regex) for grouping keys."
{...commonOptions}
>
- (
)}
defaultValue={[]}
- control={methods.control}
+ control={control}
name="check_keys_groups"
/>
@@ -163,7 +158,7 @@ const PrometheusExporterRedis = ({
>
- (
)}
defaultValue={[]}
- control={methods.control}
+ control={control}
name="check_single_keys"
/>
@@ -208,7 +203,7 @@ const PrometheusExporterRedis = ({
tooltip="List of stream-patterns to export info about streams, groups, and consumers to search for with SCAN."
{...commonOptions}
>
- (
)}
defaultValue={[]}
- control={methods.control}
+ control={control}
name="check_streams"
/>
@@ -229,7 +224,7 @@ const PrometheusExporterRedis = ({
tooltip="List of single streams to export info about streams, groups, and consumers."
{...commonOptions}
>
- (
)}
defaultValue={[]}
- control={methods.control}
+ control={control}
name="check_single_streams"
/>
@@ -250,7 +245,7 @@ const PrometheusExporterRedis = ({
tooltip="List of individual keys to export counts for."
{...commonOptions}
>
- (
)}
defaultValue={[]}
- control={methods.control}
+ control={control}
name="count_keys"
/>
@@ -271,14 +266,14 @@ const PrometheusExporterRedis = ({
tooltip="Path to Lua Redis script for collecting extra metrics."
{...commonOptions}
>
-
+
- (
)}
defaultValue={[]}
- control={methods.control}
+ control={control}
name="script_paths"
/>
@@ -299,49 +294,49 @@ const PrometheusExporterRedis = ({
tooltip="Whether to scrape Client List specific metrics."
{...commonOptions}
>
-
+
-
+
-
+
-
+
-
+
-
+
-
+
>
);
diff --git a/src/components/ComponentEditor/components/PrometheusExporterUnix.tsx b/src/components/ComponentEditor/components/PrometheusExporterUnix.tsx
index d31abcf..475198d 100644
--- a/src/components/ComponentEditor/components/PrometheusExporterUnix.tsx
+++ b/src/components/ComponentEditor/components/PrometheusExporterUnix.tsx
@@ -1,12 +1,6 @@
import { SelectableValue } from "@grafana/data";
-import {
- FormAPI,
- InlineField,
- Input,
- InlineSwitch,
- InputControl,
- MultiSelect,
-} from "@grafana/ui";
+import { InlineField, Input, InlineSwitch, MultiSelect } from "@grafana/ui";
+import { Controller, useFormContext } from "react-hook-form";
const collectors = [
{
@@ -466,10 +460,11 @@ const collectors = [
},
];
-const Component = ({ methods }: { methods: FormAPI> }) => {
+const Component = () => {
const commonOptions = {
labelWidth: 25,
};
+ const { register, control } = useFormContext();
return (
<>
Basic Settings
@@ -478,12 +473,12 @@ const Component = ({ methods }: { methods: FormAPI> }) => {
tooltip="Overrides the default set of enabled collectors with the collectors listed."
{...commonOptions}
>
- (
)}
- control={methods.control}
+ control={control}
/>
> }) => {
tooltip=" Collectors to mark as enabled in addition to the default set."
{...commonOptions}
>
- (
> }) => {
options={collectors.filter((c) => !c.enabled)}
/>
)}
- control={methods.control}
+ control={control}
/>
> }) => {
tooltip=" Collectors from the default set to mark as disabled."
{...commonOptions}
>
- (
> }) => {
options={collectors.filter((c) => c.enabled)}
/>
)}
- control={methods.control}
+ control={control}
/>
> }) => {
tooltip="Whether metrics about the exporter itself should be reported."
{...commonOptions}
>
-
+
-
+
-
+
-
+
>
);
@@ -562,21 +557,21 @@ const PrometheusExporterUnix = {
typeof data["set_collectors"][0] === "object"
)
data["set_collectors"] = data["set_collectors"]?.map(
- (x: SelectableValue) => x.value
+ (x: SelectableValue) => x.value,
);
if (
Array.isArray(data["enable_collectors"]) &&
typeof data["enable_collectors"][0] === "object"
)
data["enable_collectors"] = data["enable_collectors"]?.map(
- (x: SelectableValue) => x.value
+ (x: SelectableValue) => x.value,
);
if (
Array.isArray(data["disable_collectors"]) &&
typeof data["disable_collectors"][0] === "object"
)
data["disable_collectors"] = data["disable_collectors"]?.map(
- (x: SelectableValue) => x.value
+ (x: SelectableValue) => x.value,
);
return data;
},
diff --git a/src/components/ComponentEditor/components/PrometheusExporterWindows.tsx b/src/components/ComponentEditor/components/PrometheusExporterWindows.tsx
index 4e7d0c2..ded2da2 100644
--- a/src/components/ComponentEditor/components/PrometheusExporterWindows.tsx
+++ b/src/components/ComponentEditor/components/PrometheusExporterWindows.tsx
@@ -1,5 +1,6 @@
import { SelectableValue } from "@grafana/data";
-import { FormAPI, InlineField, InputControl, MultiSelect } from "@grafana/ui";
+import { InlineField, MultiSelect } from "@grafana/ui";
+import { Controller, useFormContext } from "react-hook-form";
import TypedInput from "../inputs/TypedInput";
const collectors = [
@@ -168,7 +169,8 @@ const collectors = [
},
];
-const Component = ({ methods }: { methods: FormAPI> }) => {
+const Component = () => {
+ const { control } = useFormContext();
const commonOptions = {
labelWidth: 25,
};
@@ -180,12 +182,12 @@ const Component = ({ methods }: { methods: FormAPI> }) => {
tooltip="List of collectors to enable."
{...commonOptions}
>
- (
)}
- control={methods.control}
+ control={control}
/>
> }) => {
tooltip="Configure timeout for collecting metrics."
{...commonOptions}
>
-
+
>
);
diff --git a/src/components/ComponentEditor/components/PrometheusRelabel.tsx b/src/components/ComponentEditor/components/PrometheusRelabel.tsx
index d53a124..88a3dfa 100644
--- a/src/components/ComponentEditor/components/PrometheusRelabel.tsx
+++ b/src/components/ComponentEditor/components/PrometheusRelabel.tsx
@@ -1,8 +1,13 @@
-import { FormAPI, InlineField } from "@grafana/ui";
+import { InlineField } from "@grafana/ui";
import ReferenceMultiSelect from "../inputs/ReferenceMultiSelect";
import { RelabelRules, transformRules } from "../common/RelabelRules";
+import { useFormContext } from "react-hook-form";
-const Component = ({ methods }: { methods: FormAPI> }) => {
+const Component = () => {
+ const {
+ control,
+ formState: { errors },
+ } = useFormContext();
return (
<>
> }) => {
tooltip="Where the metrics should be forwarded to, after relabeling takes place."
labelWidth={22}
error="You must specify a list of destinations"
- invalid={!!methods.errors["targets"]}
+ invalid={!!errors["targets"]}
>
-
+
>
);
};
diff --git a/src/components/ComponentEditor/components/PrometheusRemoteWrite.tsx b/src/components/ComponentEditor/components/PrometheusRemoteWrite.tsx
index 6d1087b..95beccd 100644
--- a/src/components/ComponentEditor/components/PrometheusRemoteWrite.tsx
+++ b/src/components/ComponentEditor/components/PrometheusRemoteWrite.tsx
@@ -1,5 +1,4 @@
import {
- FormAPI,
Input,
Alert,
LinkButton,
@@ -8,12 +7,18 @@ import {
InlineField,
InlineSwitch,
} from "@grafana/ui";
+import { useFormContext } from "react-hook-form";
import AuthenticationEditor from "../common/AuthenticationEditor";
import TlsConfig from "../common/TlsConfig";
import MultiBlock from "../inputs/MultiBlock";
import TypedInput from "../inputs/TypedInput";
-const Component = ({ methods }: { methods: FormAPI> }) => {
+const Component = () => {
+ const {
+ control,
+ register,
+ formState: { errors },
+ } = useFormContext();
const commonOptions = {
labelWidth: 24,
};
@@ -33,7 +38,6 @@ const Component = ({ methods }: { methods: FormAPI> }) => {
> }) => {
label="Endpoint URL"
tooltip="Where to send metrics to"
error="An endpoint URL is required"
- invalid={!!methods.errors["endpoint"]?.url}
+ invalid={!!errors["endpoint"]?.url}
{...commonOptions}
>
@@ -67,9 +71,7 @@ const Component = ({ methods }: { methods: FormAPI> }) => {
{...commonOptions}
>
@@ -79,21 +81,19 @@ const Component = ({ methods }: { methods: FormAPI> }) => {
{...commonOptions}
>
@@ -105,8 +105,8 @@ const Component = ({ methods }: { methods: FormAPI> }) => {
{...commonOptions}
>
@@ -120,7 +120,7 @@ const Component = ({ methods }: { methods: FormAPI> }) => {
name={
`endpoint[${index}].metadata_config.send_interval` as const
}
- control={methods.control}
+ control={control}
defaultValue={field?.metadata_config?.send_interval}
/>
@@ -131,8 +131,8 @@ const Component = ({ methods }: { methods: FormAPI> }) => {
>
> }) => {
>
@@ -159,7 +159,7 @@ const Component = ({ methods }: { methods: FormAPI> }) => {
>
@@ -169,8 +169,8 @@ const Component = ({ methods }: { methods: FormAPI> }) => {
{...commonOptions}
>
@@ -181,9 +181,7 @@ const Component = ({ methods }: { methods: FormAPI> }) => {
{...commonOptions}
>
@@ -196,8 +194,8 @@ const Component = ({ methods }: { methods: FormAPI> }) => {
>
@@ -209,8 +207,8 @@ const Component = ({ methods }: { methods: FormAPI> }) => {
>
@@ -222,8 +220,8 @@ const Component = ({ methods }: { methods: FormAPI> }) => {
>
@@ -234,8 +232,8 @@ const Component = ({ methods }: { methods: FormAPI> }) => {
>
@@ -246,8 +244,8 @@ const Component = ({ methods }: { methods: FormAPI> }) => {
{...commonOptions}
>
@@ -258,8 +256,8 @@ const Component = ({ methods }: { methods: FormAPI> }) => {
{...commonOptions}
>
@@ -270,8 +268,8 @@ const Component = ({ methods }: { methods: FormAPI> }) => {
{...commonOptions}
>
@@ -282,8 +280,8 @@ const Component = ({ methods }: { methods: FormAPI> }) => {
{...commonOptions}
>
@@ -301,30 +299,21 @@ const Component = ({ methods }: { methods: FormAPI> }) => {
tooltip="How frequently to clean up the WAL."
{...commonOptions}
>
-
+
-
+
-
+
diff --git a/src/components/ComponentEditor/components/PrometheusScrape.tsx b/src/components/ComponentEditor/components/PrometheusScrape.tsx
index cd89f15..265d10a 100644
--- a/src/components/ComponentEditor/components/PrometheusScrape.tsx
+++ b/src/components/ComponentEditor/components/PrometheusScrape.tsx
@@ -1,7 +1,6 @@
import {
Collapse,
FieldSet,
- FormAPI,
InlineField,
InlineSwitch,
Input,
@@ -13,8 +12,14 @@ import AuthenticationEditor from "../common/AuthenticationEditor";
import { useState } from "react";
import TypedInput from "../inputs/TypedInput";
import TlsConfig from "../common/TlsConfig";
+import { useFormContext } from "react-hook-form";
-const Component = ({ methods }: { methods: FormAPI> }) => {
+const Component = () => {
+ const {
+ control,
+ register,
+ formState: { errors },
+ } = useFormContext();
const [tlsConfigOpen, setTlsConfigOpen] = useState(false);
const [limitConfigOpen, setLimitConfigOpen] = useState(false);
const [connConfigOpen, setConnConfigOpen] = useState(false);
@@ -29,13 +34,13 @@ const Component = ({ methods }: { methods: FormAPI> }) => {
label="Forward to"
tooltip="Receivers for the data scraped by this component"
error="You must specify the destination"
- invalid={!!methods.errors["forward_to"]}
+ invalid={!!errors["forward_to"]}
{...commonOptions}
>
> }) => {
tooltip="How frequently to scrape the targets of this scrape config."
{...commonOptions}
>
-
+
-
+
-
+
-
+
-
-
+
+
-
+
-
+
-
+
> }) => {
onToggle={() => setTlsConfigOpen(!tlsConfigOpen)}
collapsible
>
-
+
> }) => {
>
> }) => {
>
> }) => {
>
> }) => {
>
> }) => {
>
@@ -164,7 +169,7 @@ const Component = ({ methods }: { methods: FormAPI> }) => {
>
@@ -177,24 +182,20 @@ const Component = ({ methods }: { methods: FormAPI> }) => {
collapsible
>
-
+
-
+
-
+
-
+
diff --git a/src/components/ComponentEditor/components/PyroscopeScrape.tsx b/src/components/ComponentEditor/components/PyroscopeScrape.tsx
index 02f5202..f14f4da 100644
--- a/src/components/ComponentEditor/components/PyroscopeScrape.tsx
+++ b/src/components/ComponentEditor/components/PyroscopeScrape.tsx
@@ -1,10 +1,4 @@
-import {
- Collapse,
- FieldSet,
- FormAPI,
- InlineField,
- InlineSwitch,
-} from "@grafana/ui";
+import { Collapse, FieldSet, InlineField, InlineSwitch } from "@grafana/ui";
import ReferenceMultiSelect from "../inputs/ReferenceMultiSelect";
import TypedInput from "../inputs/TypedInput";
@@ -12,6 +6,7 @@ import AuthenticationEditor from "../common/AuthenticationEditor";
import TlsBlock from "../common/TlsBlock";
import { useState } from "react";
import TargetSelector from "../common/TargetSelector";
+import { useFormContext } from "react-hook-form";
const ProfileOptions = [
{ label: "Memory", name: "memory" },
@@ -23,7 +18,7 @@ const ProfileOptions = [
{ label: "Custom", name: "custom" },
];
-const Component = ({ methods }: { methods: FormAPI> }) => {
+const Component = () => {
const [tlsConfigOpen, setTlsConfigOpen] = useState(false);
const [profilingConfigOpen, setProfilingConfigOpen] = useState(false);
@@ -31,6 +26,11 @@ const Component = ({ methods }: { methods: FormAPI> }) => {
labelWidth: 14,
};
+ const {
+ control,
+ register,
+ formState: { errors },
+ } = useFormContext();
return (
<>
> }) => {
tooltip="Receivers for the data scraped by this component"
labelWidth={14}
error="You must specify the destination"
- invalid={!!methods.errors["forward_to"]}
+ invalid={!!errors["forward_to"]}
>
-
-
+
+
> }) => {
onToggle={() => setTlsConfigOpen(!tlsConfigOpen)}
collapsible
>
-
+
> }) => {
tooltip="The path prefix to use when scraping targets."
{...commonOptions}
>
-
+
{ProfileOptions.map((o) => (
{o.label}} key={o.name}>
@@ -88,8 +85,8 @@ const Component = ({ methods }: { methods: FormAPI> }) => {
{...commonOptions}
>
@@ -99,7 +96,7 @@ const Component = ({ methods }: { methods: FormAPI> }) => {
{...commonOptions}
>
diff --git a/src/components/ComponentEditor/components/modules/GrafanaCloudAutoConfigure.tsx b/src/components/ComponentEditor/components/modules/GrafanaCloudAutoConfigure.tsx
index c7cb28d..d45d017 100644
--- a/src/components/ComponentEditor/components/modules/GrafanaCloudAutoConfigure.tsx
+++ b/src/components/ComponentEditor/components/modules/GrafanaCloudAutoConfigure.tsx
@@ -1,10 +1,15 @@
-import { Alert, FormAPI, InlineField, VerticalGroup } from "@grafana/ui";
+import { Alert, InlineField, VerticalGroup } from "@grafana/ui";
+import { useFormContext } from "react-hook-form";
import TypedInput from "../../inputs/TypedInput";
-const Component = ({ methods }: { methods: FormAPI> }) => {
+const Component = () => {
const commonOptions = {
labelWidth: 25,
};
+ const {
+ control,
+ formState: { errors },
+ } = useFormContext();
return (
<>
@@ -12,12 +17,12 @@ const Component = ({ methods }: { methods: FormAPI> }) => {
label="Stack name"
tooltip="Name of your stack as shown in the Grafana Cloud Console"
error="The stack name is required"
- invalid={!!methods.errors["arguments"]?.stack_name}
+ invalid={!!errors["arguments"]?.stack_name}
{...commonOptions}
>
@@ -25,12 +30,12 @@ const Component = ({ methods }: { methods: FormAPI> }) => {
label="Token"
tooltip="Access policy token or API Key"
error="The token is required"
- invalid={!!methods.errors["arguments"]?.token}
+ invalid={!!errors["arguments"]?.token}
{...commonOptions}
>
diff --git a/src/components/ComponentEditor/index.tsx b/src/components/ComponentEditor/index.tsx
index 9ba9178..082ecf6 100644
--- a/src/components/ComponentEditor/index.tsx
+++ b/src/components/ComponentEditor/index.tsx
@@ -1,11 +1,4 @@
-import {
- Form,
- Field,
- Input,
- Button,
- FormAPI,
- HorizontalGroup,
-} from "@grafana/ui";
+import { Field, Input, Button, HorizontalGroup } from "@grafana/ui";
import { faro } from "@grafana/faro-web-sdk";
import { Block, toBlock } from "../../lib/river";
import PrometheusRemoteWrite from "./components/PrometheusRemoteWrite";
@@ -38,6 +31,7 @@ import PrometheusExporterWindows from "./components/PrometheusExporterWindows";
import LokiProcess from "./components/LokiProcess";
import { useComponentContext } from "../../state";
import ImportGit from "./components/ImportGit";
+import { FormProvider, useForm } from "react-hook-form";
interface ComponentEditorProps {
updateComponent: (component: Block) => void;
@@ -57,11 +51,7 @@ const ComponentEditor = ({
preTransform,
postTransform,
}: {
- Component: ({
- methods,
- }: {
- methods: FormAPI>;
- }) => JSX.Element;
+ Component: () => JSX.Element;
preTransform: (data: Record) => Record;
postTransform: (data: Record) => Record;
} = (() => {
@@ -155,47 +145,54 @@ const ComponentEditor = ({
formValues = preTransform(formValues);
if (spec && spec.multi) formValues["label"] = component.label;
+ let methods = useForm({
+ defaultValues: formValues,
+ });
+ const {
+ register,
+ handleSubmit,
+ formState: { errors },
+ } = methods;
+ const onSubmit = ({
+ label,
+ ...args
+ }: {
+ [key: string]: any;
+ label: string;
+ }) => {
+ const transformed = postTransform(args);
+ updateComponent(
+ toBlock(
+ component.name,
+ transformed,
+ label,
+ KnownComponents[component.name],
+ )!,
+ );
+ };
+
return (
-
+
+
+
);
};
diff --git a/src/components/ComponentEditor/inputs/GenericStringMap.tsx b/src/components/ComponentEditor/inputs/GenericStringMap.tsx
index 121711f..083c6c3 100644
--- a/src/components/ComponentEditor/inputs/GenericStringMap.tsx
+++ b/src/components/ComponentEditor/inputs/GenericStringMap.tsx
@@ -1,12 +1,11 @@
import {
Button,
- FieldArray,
FieldSet,
InlineField,
InlineFieldRow,
Input,
} from "@grafana/ui";
-import { Control } from "react-hook-form";
+import { Control, useFieldArray } from "react-hook-form";
const GenericStringMap = ({
control,
@@ -17,43 +16,42 @@ const GenericStringMap = ({
name: string;
title: string;
}) => {
+ const { fields, append, remove } = useFieldArray({
+ control,
+ name: `${name}` as const,
+ });
+
return (
{title}}>
-
- {({ fields, append, remove }) => (
- <>
- {fields.map((field, index) => (
-
-
-
-
-
-
-
- {
- remove(index);
- e.preventDefault();
- }}
- />
-
- ))}
- append({})} icon="plus" variant="secondary">
- Add
-
- >
- )}
-
+ {(fields as Array>).map((field, index) => (
+
+
+
+
+
+
+
+ {
+ remove(index);
+ e.preventDefault();
+ }}
+ />
+
+ ))}
+ append({})} icon="plus" variant="secondary">
+ Add
+
);
};
diff --git a/src/components/ComponentEditor/inputs/LabelsInput.tsx b/src/components/ComponentEditor/inputs/LabelsInput.tsx
index bde0f2e..ff5d7ce 100644
--- a/src/components/ComponentEditor/inputs/LabelsInput.tsx
+++ b/src/components/ComponentEditor/inputs/LabelsInput.tsx
@@ -1,12 +1,11 @@
import {
Button,
- FieldArray,
FieldSet,
InlineField,
InlineFieldRow,
Input,
} from "@grafana/ui";
-import { Control } from "react-hook-form";
+import { Control, useFieldArray } from "react-hook-form";
const LabelsInput = ({
control,
@@ -15,43 +14,40 @@ const LabelsInput = ({
control: Control>;
name: string;
}) => {
+ const { fields, append, remove } = useFieldArray({
+ name: `${name}` as const,
+ });
return (
Labels}>
-
- {({ fields, append, remove }) => (
- <>
- {fields.map((field, index) => (
-
-
-
-
-
-
-
- {
- remove(index);
- e.preventDefault();
- }}
- />
-
- ))}
- append({})} icon="plus" variant="secondary">
- Add
-
- >
- )}
-
+ {(fields as Array>).map((field, index) => (
+
+
+
+
+
+
+
+ {
+ remove(index);
+ e.preventDefault();
+ }}
+ />
+
+ ))}
+ append({})} icon="plus" variant="secondary">
+ Add
+
);
};
diff --git a/src/components/ComponentEditor/inputs/MultiBlock.tsx b/src/components/ComponentEditor/inputs/MultiBlock.tsx
index cb5f946..fd51a06 100644
--- a/src/components/ComponentEditor/inputs/MultiBlock.tsx
+++ b/src/components/ComponentEditor/inputs/MultiBlock.tsx
@@ -1,60 +1,47 @@
import { css } from "@emotion/css";
import { GrafanaTheme2 } from "@grafana/data";
-import {
- Button,
- Card,
- FieldArray,
- FieldSet,
- FormAPI,
- IconButton,
-} from "@grafana/ui";
+import { Button, Card, FieldSet, IconButton } from "@grafana/ui";
+import { useFieldArray } from "react-hook-form";
import { useStyles } from "../../../theme";
const MultiBlock = ({
- methods,
name,
title,
children,
newBlock,
}: {
- methods: FormAPI>;
name: string;
title: string;
children: (
field: Record,
- index: number
+ index: number,
) => React.ReactNode[] | React.ReactNode;
newBlock?: any;
}) => {
+ const { fields, append, remove } = useFieldArray({ name });
const styles = useStyles(getStyles);
newBlock = newBlock ?? {};
return (
-
- {({ fields, append, remove }) => (
- <>
- {fields.map((field, index) => (
-
- {children(field, index)}
-
- {
- remove(index);
- e.preventDefault();
- }}
- />
-
-
- ))}
- append(newBlock)} icon="plus">
- Add
-
- >
- )}
-
+ {fields.map((field, index) => (
+
+ {children(field, index)}
+
+ {
+ remove(index);
+ e.preventDefault();
+ }}
+ />
+
+
+ ))}
+ append(newBlock)} icon="plus">
+ Add
+
);
};
diff --git a/src/components/ComponentEditor/inputs/ReferenceMultiSelect.tsx b/src/components/ComponentEditor/inputs/ReferenceMultiSelect.tsx
index 27d394a..0dc0584 100644
--- a/src/components/ComponentEditor/inputs/ReferenceMultiSelect.tsx
+++ b/src/components/ComponentEditor/inputs/ReferenceMultiSelect.tsx
@@ -1,6 +1,6 @@
import { SelectableValue } from "@grafana/data";
-import { InputControl, MultiSelect } from "@grafana/ui";
-import { get } from "react-hook-form";
+import { MultiSelect } from "@grafana/ui";
+import { Controller, get } from "react-hook-form";
import { useState } from "react";
import { useComponentContext } from "../../../state";
@@ -26,7 +26,7 @@ const ReferenceMultiSelect = ({
exportName,
);
return (
- (
(