Skip to content

Commit

Permalink
refactor(web): use defaultvalues in react-hook-form
Browse files Browse the repository at this point in the history
  • Loading branch information
JosephKav committed Apr 4, 2024
1 parent 2b1c408 commit 9859c7c
Show file tree
Hide file tree
Showing 17 changed files with 361 additions and 232 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ const BooleanWithDefault: FC<Props> = ({

return (
<Col
xs={12}
className="pt-1 pb-1"
style={{ display: "flex", alignItems: "center" }}
>
Expand Down
6 changes: 2 additions & 4 deletions web/ui/react-app/src/components/generic/form-key-val-map.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -60,17 +60,15 @@ const FormKeyValMap: FC<Props> = ({
// useDefaults when the fieldValues are undefined or the same as the defaults
const useDefaults = useMemo(
() =>
(!isEmptyArray(defaults) &&
diffObjects(fieldValues ?? fields ?? [], defaults)) ??
false,
isEmptyArray(defaults) ? false : !diffObjects(fieldValues, defaults),
[fieldValues, defaults]
);
// trigger validation on change of defaults being used/not
useEffect(() => {
trigger(name);

// Give the defaults back if the field is empty
if ((fieldValues ?? fields ?? []).length === 0)
if ((fieldValues ?? []).length === 0)
defaults?.forEach(() => {
addItem();
});
Expand Down
10 changes: 5 additions & 5 deletions web/ui/react-app/src/components/generic/form-list.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,17 +46,17 @@ const FormList: FC<Props> = ({
// useDefaults when the fieldValues are undefined or the same as the defaults
const useDefaults = useMemo(
() =>
(!isEmptyArray(defaults) &&
diffObjects(fieldValues ?? fields ?? [], defaults)) ??
false,
isEmptyArray(defaults)
? false
: !diffObjects(fieldValues ?? [], defaults),
[fieldValues, defaults]
);
// trigger validation on change of defaults being used/not
useEffect(() => {
trigger(name);

// Give the defaults back if the field is empty
if ((fieldValues ?? fields ?? [])?.length === 0)
if ((fieldValues ?? [])?.length === 0)
defaults?.forEach(() => {
addItem();
});
Expand All @@ -70,7 +70,7 @@ const FormList: FC<Props> = ({
// on load, ensure we don't have another types actions
// and give the defaults if not overridden
useEffect(() => {
for (const item of fieldValues ?? fields ?? []) {
for (const item of fieldValues ?? []) {
const keys = Object.keys(item);
if (keys.length > 1 || !keys.includes("arg")) {
setValue(name, []);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,12 +53,8 @@ const sendableTimeout = (
let timeout = differenceInMilliseconds(nextRunnable, now);
// if we're already after nextRunnable, just wait a second
if (now > nextRunnable) timeout = 1000;
const timer = setTimeout(function () {
setSendable(true);
}, timeout);
return () => {
clearTimeout(timer);
};
const timer = setTimeout(() => setSendable(true), timeout);
return () => clearTimeout(timer);
}
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ export const Loading: FC<Props> = ({ name }) => {
"Options:",
"Latest Version:",
"Deployed Version:",
"Commands:",
"WebHooks:",
"Command:",
"WebHook:",
"Notify:",
"Dashboard:",
];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,9 @@ const NtfyActions: FC<Props> = ({ name, label, tooltip, defaults }) => {
// useDefaults when the fieldValues are unset or the same as the defaults
const useDefaults = useMemo(
() =>
!isEmptyArray(defaults) &&
diffObjects(fieldValues ?? fields ?? [], defaults, [".action"]),
isEmptyArray(defaults)
? false
: !diffObjects(fieldValues, defaults, [".action"]),
[fieldValues, defaults]
);

Expand All @@ -71,7 +72,7 @@ const NtfyActions: FC<Props> = ({ name, label, tooltip, defaults }) => {
trigger(name);

// Give the defaults back if the field is empty
if ((fieldValues ?? fields ?? [])?.length === 0) {
if ((fieldValues ?? []).length === 0) {
trimmedDefaults.forEach((dflt) => {
append(dflt, { shouldFocus: false });
});
Expand All @@ -82,7 +83,7 @@ const NtfyActions: FC<Props> = ({ name, label, tooltip, defaults }) => {
// and give the defaults if not overridden
useEffect(() => {
// ensure we don't have another types actions
for (const item of fieldValues ?? fields ?? []) {
for (const item of fieldValues ?? []) {
if (isEmptyOrNull(item.action)) {
setValue(name, []);
break;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,11 +56,9 @@ const OpsGenieTargets: FC<Props> = ({ name, label, tooltip, defaults }) => {
// useDefaults when the fieldValues are undefined or the same as the defaults
const useDefaults = useMemo(
() =>
!isEmptyArray(defaults) &&
diffObjects(fieldValues ?? fields ?? [], defaults, [
".type",
".sub_type",
]),
isEmptyArray(defaults)
? false
: !diffObjects(fieldValues, defaults, [".type", ".sub_type"]),
[fieldValues, defaults]
);
const trimmedDefaults = useMemo(
Expand All @@ -71,7 +69,7 @@ const OpsGenieTargets: FC<Props> = ({ name, label, tooltip, defaults }) => {
trigger(name);

// Give the defaults back if the field is empty
if ((fieldValues ?? fields ?? [])?.length === 0)
if ((fieldValues ?? [])?.length === 0)
trimmedDefaults?.forEach((dflt) => {
append(dflt, { shouldFocus: false });
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,11 @@ const Notify: FC<Props> = ({
else if (itemType && (NotifyTypesConst as string[]).includes(itemName))
setValue(`${name}.type`, itemName);
// Trigger validation on name/type
setTimeout(() => {
const timeout = setTimeout(() => {
if (itemName !== "") trigger(`${name}.name`);
trigger(`${name}.type`);
}, 25);
return () => clearTimeout(timeout);
}, [itemName]);
const header = useMemo(
() => `${name.split(".").slice(-1)}: (${itemType}) ${itemName}`,
Expand Down
54 changes: 6 additions & 48 deletions web/ui/react-app/src/components/modals/service-edit/service.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
import { FC, useEffect, useMemo, useState } from "react";
import { FormGroup, Stack } from "react-bootstrap";
import {
ServiceEditAPIType,
ServiceEditOtherData,
ServiceEditType,
} from "types/service-edit";
import { ServiceEditOtherData, ServiceEditType } from "types/service-edit";

import EditServiceCommands from "components/modals/service-edit/commands";
import EditServiceDashboard from "components/modals/service-edit/dashboard";
Expand All @@ -13,17 +8,15 @@ import EditServiceLatestVersion from "components/modals/service-edit/latest-vers
import EditServiceNotifys from "components/modals/service-edit/notifys";
import EditServiceOptions from "components/modals/service-edit/options";
import EditServiceWebHooks from "components/modals/service-edit/webhooks";
import { FC } from "react";
import { FormItem } from "components/generic/form";
import { Loading } from "./loading";
import { WebHookType } from "types/config";
import { convertAPIServiceDataEditToUI } from "components/modals/service-edit/util";
import { fetchJSON } from "utils";
import { useFormContext } from "react-hook-form";
import { useQuery } from "@tanstack/react-query";
import { useWebSocket } from "contexts/websocket";

interface Props {
name: string;
defaultData: ServiceEditType;
otherOptionsData: ServiceEditOtherData;
}

/**
Expand All @@ -32,45 +25,10 @@ interface Props {
* @param name - The name of the service
* @returns The form fields for creating/editing a service
*/
const EditService: FC<Props> = ({ name }) => {
const { reset } = useFormContext();
const [loading, setLoading] = useState(true);

const { data: otherOptionsData, isFetched: isFetchedOtherOptionsData } =
useQuery({
queryKey: ["service/edit", "detail"],
queryFn: () =>
fetchJSON<ServiceEditOtherData>({ url: "api/v1/service/edit" }),
});
const { data: serviceData, isSuccess: isSuccessServiceData } = useQuery({
queryKey: ["service/edit", { id: name }],
queryFn: () =>
fetchJSON<ServiceEditAPIType>({ url: `api/v1/service/edit/${name}` }),
enabled: !!name,
refetchOnMount: "always",
});

const defaultData: ServiceEditType = useMemo(
() => convertAPIServiceDataEditToUI(name, serviceData, otherOptionsData),
[serviceData, otherOptionsData]
);
const EditService: FC<Props> = ({ name, defaultData, otherOptionsData }) => {
const { monitorData } = useWebSocket();

useEffect(() => {
// If we're loading and have finished fetching the service data
// (or don't have name = resetting for close)
if (
(loading && isSuccessServiceData && isFetchedOtherOptionsData) ||
!name
) {
reset(defaultData);
setTimeout(() => setLoading(false), 100);
}
}, [defaultData]);

return loading ? (
<Loading name={name} />
) : (
return (
<Stack gap={3}>
<FormGroup className="mb-2">
<FormItem
Expand Down
Loading

0 comments on commit 9859c7c

Please sign in to comment.