- added endpoints for dns and other

This commit is contained in:
2025-11-04 17:04:19 +00:00
parent 647fd201a3
commit 861f2dd31d
9 changed files with 261 additions and 84 deletions

View File

@@ -4,7 +4,7 @@ import BearerTypeFields from "./BearerTypeFields";
const BearerTypeCard = () => {
return (
<Card className="p-4">
<Card className="p-4 h-60">
<CardHeader title="Bearer Type" />
<BearerTypeFields />
</Card>

View File

@@ -37,7 +37,7 @@ const ChannelCard = ({ touched, isSubmitting, isBof2ConstantsLoading, isDispatch
}, [backOfficeQuery.isSuccess, mapped, setFieldValue]);
return (
<Card className="p-4">
<Card className="p-4 overflow-y-auto ">
<CardHeader title={`Channel (${values?.format})`} />
{!isBof2ConstantsLoading && !isDispatcherLoading && !isBackOfficeQueryLoading ? (
<ChannelFields

View File

@@ -118,6 +118,7 @@ const ChannelFields = ({ touched, isSubmitting, format }: ChannelFieldsProps) =>
{format?.toLowerCase() === "bof2" && (
<>
<div className="space-y-3">
<div className="border-b border-gray-500 my-3">
<h2 className="font-bold">{values.format} Constants</h2>
</div>
@@ -133,7 +134,6 @@ const ChannelFields = ({ touched, isSubmitting, format }: ChannelFieldsProps) =>
} rounded-lg w-full md:w-60`}
/>
</FormGroup>
<FormGroup>
<label htmlFor="SCID">Source ID / Camera ID</label>
<Field
@@ -146,7 +146,6 @@ const ChannelFields = ({ touched, isSubmitting, format }: ChannelFieldsProps) =>
} rounded-lg w-full md:w-60`}
/>
</FormGroup>
<FormGroup>
<label htmlFor="timestampSource">Timestamp Source</label>
<Field
@@ -171,6 +170,36 @@ const ChannelFields = ({ touched, isSubmitting, format }: ChannelFieldsProps) =>
<option value={"Decimal Degrees"}>Decimal degrees</option>
</Field>
</FormGroup>
</div>
<div className="space-y-3">
<div className="border-b border-gray-500 my-3">
<h2 className="font-bold">{values.format} Lane ID Config</h2>
</div>
<FormGroup>
<label htmlFor="LID1">Lane ID 1</label>
<Field
name={"LID1"}
type="text"
id="LID1"
placeholder="10"
className={`p-1.5 border ${
errors.readTimeoutSeconds && touched.readTimeoutSeconds ? "border-red-500" : "border-gray-400 "
} rounded-lg w-full md:w-60`}
/>
</FormGroup>
<FormGroup>
<label htmlFor="LID2">Lane ID 2</label>
<Field
name={"LID2"}
type="text"
id="LID2"
placeholder="20"
className={`p-1.5 border ${
errors.readTimeoutSeconds && touched.readTimeoutSeconds ? "border-red-500" : "border-gray-400 "
} rounded-lg w-full md:w-60`}
/>
</FormGroup>
</div>
</>
)}
</div>

View File

@@ -7,6 +7,7 @@ import type {
InitialValuesForm,
InitialValuesFormErrors,
OptionalBOF2Constants,
OptionalBOF2LaneIDs,
} from "../../../types/types";
import { useQueryClient } from "@tanstack/react-query";
import { useUpdateBackOfficeConfig } from "../../../hooks/useBackOfficeConfig";
@@ -14,7 +15,8 @@ import { useFormVaidate } from "../../../hooks/useFormValidate";
const SettingForms = () => {
const qc = useQueryClient();
const { dispatcherQuery, dispatcherMutation, backOfficeDispatcherMutation } = useCameraOutput();
const { dispatcherQuery, dispatcherMutation, backOfficeDispatcherMutation, bof2LandMutation, laneIdQuery } =
useCameraOutput();
const { backOfficeMutation } = useUpdateBackOfficeConfig();
const { bof2ConstantsQuery } = useGetDispatcherConfig();
const { validateMutation } = useFormVaidate();
@@ -22,6 +24,9 @@ const SettingForms = () => {
const format = dispatcherQuery?.data?.propFormat?.value;
const enabled = dispatcherQuery?.data?.propEnabled?.value;
const LID1 = laneIdQuery?.data?.propLaneID1?.value;
const LID2 = laneIdQuery?.data?.propLaneID2?.value;
const FFID = bof2ConstantsQuery?.data?.propFeedIdentifier?.value;
const SCID = bof2ConstantsQuery?.data?.propSourceIdentifier?.value;
const GPSFormat = bof2ConstantsQuery?.data?.propGpsFormat?.value;
@@ -30,7 +35,7 @@ const SettingForms = () => {
const isDispatcherLoading = dispatcherQuery?.isFetching;
const isBof2ConstantsLoading = bof2ConstantsQuery?.isFetching;
const initialValues: BearerTypeFieldType & InitialValuesForm & OptionalBOF2Constants = {
const initialValues: BearerTypeFieldType & InitialValuesForm & OptionalBOF2Constants & OptionalBOF2LaneIDs = {
format: format ?? "JSON",
enabled: enabled === "true",
backOfficeURL: "",
@@ -44,6 +49,10 @@ const SettingForms = () => {
SCID: SCID ?? "",
timestampSource: timestampSource ?? "",
GPSFormat: GPSFormat ?? "",
//BOF2 - optional Lane IDs
LID1: LID1 ?? "",
LID2: LID2 ?? "",
};
const validateValues = (values: InitialValuesForm): InitialValuesFormErrors => {
@@ -65,7 +74,9 @@ const SettingForms = () => {
return errors;
};
const handleSubmit = async (values: BearerTypeFieldType & InitialValuesForm & OptionalBOF2Constants) => {
const handleSubmit = async (
values: BearerTypeFieldType & InitialValuesForm & OptionalBOF2Constants & OptionalBOF2LaneIDs
) => {
const validResponse = await validateMutation.mutateAsync(values);
const dispatcherData = {
@@ -88,6 +99,13 @@ const SettingForms = () => {
timestampSource: values.timestampSource,
GPSFormat: values.GPSFormat,
};
const bof2LaneData: OptionalBOF2LaneIDs = {
LID1: values.LID1,
LID2: values.LID2,
LID3: values.LID3,
};
await bof2LandMutation.mutateAsync(bof2LaneData);
await backOfficeDispatcherMutation.mutateAsync(bof2ConstantsData);
}
} else {

View File

@@ -2,6 +2,8 @@ import { toast } from "sonner";
import type { SystemValues } from "../../../types/types";
import { CAM_BASE } from "../../../utils/config";
const camBase = import.meta.env.MODE !== "development" ? CAM_BASE : "";
export async function handleSystemSave(values: SystemValues) {
const payload = {
// Build JSON
@@ -18,7 +20,7 @@ export async function handleSystemSave(values: SystemValues) {
};
try {
const response = await fetch(`${CAM_BASE}/api/update-config`, {
const response = await fetch(`${camBase}/api/update-config`, {
method: "POST",
headers: {
"Content-Type": "application/json",
@@ -29,11 +31,7 @@ export async function handleSystemSave(values: SystemValues) {
if (!response.ok) {
const text = await response.text().catch(() => "");
throw new Error(
`HTTP ${response.status} ${response.statusText}${
text ? ` - ${text}` : ""
}`
);
throw new Error(`HTTP ${response.status} ${response.statusText}${text ? ` - ${text}` : ""}`);
}
} catch (err) {
if (err instanceof Error) {
@@ -47,7 +45,7 @@ export async function handleSystemSave(values: SystemValues) {
}
export async function handleSystemRecall() {
const url = `${CAM_BASE}/api/fetch-config?id=GLOBAL--Device`;
const url = `${camBase}/api/fetch-config?id=GLOBAL--Device`;
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), 7000);
@@ -61,11 +59,7 @@ export async function handleSystemRecall() {
if (!response.ok) {
const text = await response.text().catch(() => "");
throw new Error(
`HTTP ${response.status} ${response.statusText}${
text ? ` - ${text}` : ""
}`
);
throw new Error(`HTTP ${response.status} ${response.statusText}${text ? ` - ${text}` : ""}`);
}
const data = await response.json();
@@ -76,9 +70,7 @@ export async function handleSystemRecall() {
const sntpIntervalRaw = data?.propSNTPIntervalMinutes?.value;
let sntpInterval =
typeof sntpIntervalRaw === "number"
? sntpIntervalRaw
: Number.parseInt(String(sntpIntervalRaw).trim(), 10);
typeof sntpIntervalRaw === "number" ? sntpIntervalRaw : Number.parseInt(String(sntpIntervalRaw).trim(), 10);
if (!Number.isFinite(sntpInterval)) {
sntpInterval = 60;

View File

@@ -4,21 +4,30 @@ import { useReboots } from "../../../hooks/useReboots";
import { timezones } from "./timezones";
import SystemFileUpload from "./SystemFileUpload";
import type { SystemValues, SystemValuesErrors } from "../../../types/types";
import { useSystemConfig } from "../../../hooks/useSystemConfig";
import { useDNSSettings, useSystemConfig } from "../../../hooks/useSystemConfig";
const SystemConfigFields = () => {
const { saveSystemSettings, systemSettingsData, saveSystemSettingsLoading } = useSystemConfig();
const { softRebootMutation, hardRebootMutation } = useReboots();
const { dnsQuery, dnsMutation } = useDNSSettings();
console.log(dnsQuery?.data);
const dnsPrimary = dnsQuery?.data?.propNameServerPrimary?.value;
const dnsSecondary = dnsQuery?.data?.propNameServerSecondary?.value;
const initialvalues: SystemValues = {
deviceName: systemSettingsData?.deviceName ?? "",
timeZone: systemSettingsData?.timeZone ?? "",
sntpServer: systemSettingsData?.sntpServer ?? "",
sntpInterval: systemSettingsData?.sntpInterval ?? 60,
serverPrimary: dnsPrimary ?? "",
serverSecondary: dnsSecondary ?? "",
softwareUpdate: null,
};
const handleSubmit = (values: SystemValues) => saveSystemSettings(values);
const handleSubmit = async (values: SystemValues) => {
saveSystemSettings(values);
await dnsMutation.mutateAsync(values);
};
const validateValues = (values: SystemValues) => {
const errors: SystemValuesErrors = {};
@@ -102,6 +111,34 @@ const SystemConfigFields = () => {
autoComplete="off"
/>
</FormGroup>
<FormGroup>
<label htmlFor="serverPrimary" className="font-medium whitespace-nowrap md:w-1/2 text-left">
Server Primary
</label>
<Field
id="serverPrimary"
name="serverPrimary"
type="text"
className="p-2 border border-gray-400 rounded-lg w-full max-w-xs"
placeholder="Enter DNS primary address"
autoComplete="off"
/>
</FormGroup>
<FormGroup>
<label htmlFor="serverSecondary" className="font-medium whitespace-nowrap md:w-1/2 text-left">
Server Secondary
</label>
<Field
id="serverSecondary"
name="serverSecondary"
type="text"
className="p-2 border border-gray-400 rounded-lg w-full max-w-xs"
placeholder="Enter DNS secondary address"
autoComplete="off"
/>
</FormGroup>
<FormGroup>
<label htmlFor="sntpInterval" className="font-medium whitespace-nowrap md:w-1/2 text-left">
SNTP Interval minutes

View File

@@ -2,7 +2,7 @@ import { useMutation, useQuery } from "@tanstack/react-query";
import { CAM_BASE } from "../utils/config";
import { useEffect } from "react";
import { toast } from "sonner";
import type { BearerTypeFieldType, OptionalBOF2Constants } from "../types/types";
import type { BearerTypeFieldType, OptionalBOF2Constants, OptionalBOF2LaneIDs } from "../types/types";
const getDispatcherConfig = async () => {
const response = await fetch(`${CAM_BASE}/api/fetch-config?id=Dispatcher`);
@@ -63,11 +63,40 @@ const updateBackOfficeDispatcher = async (data: OptionalBOF2Constants) => {
};
const getBof2DispatcherData = async () => {
const response = await fetch(`http://100.118.196.113:8080/api/fetch-config?id=Dispatcher-bof2-constants`);
const response = await fetch(`${CAM_BASE}/api/fetch-config?id=Dispatcher-bof2-constants`);
if (!response.ok) throw new Error("Cannot get BOF2 dispatcher config");
return response.json();
};
const updateBOF2LaneId = async (data: OptionalBOF2LaneIDs) => {
const bof2LaneIds = {
id: "SightingAmmendA-lane-ids",
fields: [
{
property: "propLaneID1",
value: data?.LID1,
},
{
property: "propLaneID2",
value: data?.LID2,
},
],
};
const response = await fetch(`${CAM_BASE}/api/update-config?id=SightingAmmendA-lane-ids`, {
method: "post",
body: JSON.stringify(bof2LaneIds),
});
if (!response.ok) throw new Error("cannot send to lane IDs");
return response.json();
};
const getBOF2LaneId = async () => {
const response = await fetch(`${CAM_BASE}/api/fetch-config?id=SightingAmmendA-lane-ids`);
if (!response.ok) throw new Error("Canot get Lane Ids");
return response.json();
};
export const useCameraOutput = () => {
const dispatcherQuery = useQuery({
queryKey: ["dispatcher"],
@@ -95,6 +124,16 @@ export const useCameraOutput = () => {
},
});
const bof2LandMutation = useMutation({
mutationKey: ["updateBOF2LaneId"],
mutationFn: updateBOF2LaneId,
});
const laneIdQuery = useQuery({
queryKey: ["getBOF2LaneId"],
queryFn: getBOF2LaneId,
});
useEffect(() => {
if (dispatcherQuery.isError) toast.error(dispatcherQuery.error.message);
}, [dispatcherQuery?.error?.message, dispatcherQuery.isError]);
@@ -103,6 +142,8 @@ export const useCameraOutput = () => {
dispatcherQuery,
dispatcherMutation,
backOfficeDispatcherMutation,
bof2LandMutation,
laneIdQuery,
};
};

View File

@@ -1,11 +1,41 @@
import { useMutation, useQuery } from "@tanstack/react-query";
import { sendBlobFileUpload } from "../components/SettingForms/System/Upload";
import { toast } from "sonner";
import {
handleSystemSave,
handleSystemRecall,
} from "../components/SettingForms/System/SettingSaveRecall";
import { handleSystemSave, handleSystemRecall } from "../components/SettingForms/System/SettingSaveRecall";
import { useEffect } from "react";
import { CAM_BASE } from "../utils/config";
import type { DNSSettingsType } from "../types/types";
const camBase = import.meta.env.MODE !== "development" ? CAM_BASE : "";
const getDNSSettings = async () => {
const response = await fetch(`${camBase}/api/fetch-config?id=GLOBAL--NetworkConfig`);
if (!response.ok) throw new Error("Cannot get DNS Settings");
return response.json();
};
const updateDNSSettings = async (data: DNSSettingsType) => {
const dnsSettingsPayload = {
id: "GLOBAL--NetworkConfig",
fields: [
{
property: "propNameServerPrimary",
value: data?.serverPrimary,
},
{
property: "propNameServerSecondary",
value: data?.serverSecondary,
},
],
};
const response = await fetch(`${camBase}/api/update-config?id=GLOBAL--NetworkConfig`, {
method: "post",
body: JSON.stringify(dnsSettingsPayload),
});
if (!response.ok) throw new Error("cannot send to dns endpoint");
return response.json();
};
export const useSystemConfig = () => {
const uploadSettingsMutation = useMutation({
@@ -51,3 +81,20 @@ export const useSystemConfig = () => {
saveSystemSettingsLoading: saveSystemSettings.isPending,
};
};
export const useDNSSettings = () => {
const dnsQuery = useQuery({
queryKey: ["getDNSSettings"],
queryFn: getDNSSettings,
});
const dnsMutation = useMutation({
mutationKey: ["updateDNSSettings"],
mutationFn: updateDNSSettings,
});
return {
dnsQuery,
dnsMutation,
};
};

View File

@@ -69,10 +69,16 @@ export type InitialValuesFormErrors = {
};
export type OptionalBOF2Constants = {
FFID?: "";
SCID?: "";
timestampSource?: "";
GPSFormat?: "";
FFID?: string;
SCID?: string;
timestampSource?: string;
GPSFormat?: string;
};
export type OptionalBOF2LaneIDs = {
LID1?: string;
LID2?: string;
LID3?: string;
};
export type NPEDFieldType = {
@@ -157,6 +163,13 @@ export type SystemValues = {
sntpInterval: number;
timeZone: string;
softwareUpdate?: File | null;
serverPrimary?: string;
serverSecondary?: string;
};
export type DNSSettingsType = {
serverPrimary?: string;
serverSecondary?: string;
};
export type SystemValuesErrors = {