13 Commits

19 changed files with 103 additions and 29 deletions

View File

@@ -6,6 +6,7 @@ import { Form, Formik } from "formik";
import { useIntegrationsContext } from "../../context/IntegrationsContext"; import { useIntegrationsContext } from "../../context/IntegrationsContext";
import { useCameraBlackboard } from "../../hooks/useCameraBlackboard"; import { useCameraBlackboard } from "../../hooks/useCameraBlackboard";
import type { CategoryPopups } from "../../types/types"; import type { CategoryPopups } from "../../types/types";
import { toast } from "sonner";
const NPEDCategoryPopup = () => { const NPEDCategoryPopup = () => {
const { state, dispatch } = useIntegrationsContext(); const { state, dispatch } = useIntegrationsContext();
@@ -24,11 +25,18 @@ const NPEDCategoryPopup = () => {
}; };
const handleSubmit = async (values: CategoryPopups) => { const handleSubmit = async (values: CategoryPopups) => {
await mutation.mutateAsync({ const result = await mutation.mutateAsync({
operation: "INSERT", operation: "INSERT",
value: values, value: values,
path: "CategoryPopup", path: "CategoryPopup",
}); });
await mutation.mutateAsync({
operation: "SAVE",
path: "",
value: null
})
if (result?.reason === "OK") toast.success("Pop up settings saved");
dispatch({ type: "NPEDCATENABLED", payload: values }); dispatch({ type: "NPEDCATENABLED", payload: values });
}; };

View File

@@ -62,7 +62,11 @@ const SessionCard = () => {
path: "sessionStats", path: "sessionStats",
value: dedupedSightings, value: dedupedSightings,
}); });
await mutation.mutateAsync({
operation: "SAVE",
path: "",
value: null,
});
if (result.reason === "OK") toast.success("Session saved"); if (result.reason === "OK") toast.success("Session saved");
}; };

View File

@@ -234,7 +234,7 @@ const ChannelFields = ({ touched, isSubmitting, format }: ChannelFieldsProps) =>
<button <button
type="submit" type="submit"
className="w-1/4 text-white bg-green-700 hover:bg-green-800 font-small rounded-lg text-sm px-2 py-2.5" className="w-full md:w-1/4 text-white bg-green-700 hover:bg-green-800 font-small rounded-lg text-sm px-2 py-2.5"
> >
{isSubmitting ? "Saving..." : "Save Changes"} {isSubmitting ? "Saving..." : "Save Changes"}
</button> </button>

View File

@@ -6,7 +6,7 @@ import NPEDIcon from "/NPED.svg";
const NPEDCard = () => { const NPEDCard = () => {
return ( return (
<Card className="p-4"> <Card className="p-4">
<CardHeader title={"NPED Config"} img={NPEDIcon} /> <CardHeader title={"NPED"} img={NPEDIcon} />
<NPEDFields /> <NPEDFields />
</Card> </Card>
); );

View File

@@ -102,14 +102,14 @@ const NPEDFields = () => {
{!state.npedUser?.propClientID?.value ? ( {!state.npedUser?.propClientID?.value ? (
<button <button
type="submit" type="submit"
className="w-1/4 text-white bg-green-700 hover:bg-green-800 font-small rounded-lg text-sm px-2 py-2.5 hover:cursor-pointer" className="w-full md:w-1/4 text-white bg-green-700 hover:bg-green-800 font-small rounded-lg text-sm px-2 py-2.5 hover:cursor-pointer"
> >
{isSubmitting ? "Logging in..." : "Login"} {isSubmitting ? "Logging in..." : "Login"}
</button> </button>
) : ( ) : (
<button <button
type="button" type="button"
className="w-1/4 border-red-700 bg-red-800 text-white font-small rounded-lg text-sm px-2 py-2.5 hover:cursor-pointer" className="w-full md:w-1/4 border-red-700 bg-red-800 text-white font-small rounded-lg text-sm px-2 py-2.5 hover:cursor-pointer"
onClick={handleLogoutClick} onClick={handleLogoutClick}
> >
Logout Logout

View File

@@ -47,7 +47,7 @@ const NPEDHotlist = () => {
/> />
<button <button
type="submit" type="submit"
className="w-1/4 text-white bg-green-700 hover:bg-green-800 font-small rounded-lg text-sm px-2 py-2.5" className="w-full md:w-1/4 text-white bg-green-700 hover:bg-green-800 font-small rounded-lg text-sm px-2 py-2.5"
// disabled={errors ? true : false} // disabled={errors ? true : false}
> >
Upload Upload

View File

@@ -39,6 +39,11 @@ const SoundSettingsFields = () => {
path: "soundSettings", path: "soundSettings",
value: updatedValues, value: updatedValues,
}); });
await mutation.mutateAsync({
operation: "SAVE",
path: "",
value: null,
});
if (result.reason !== "OK") { if (result.reason !== "OK") {
toast.error("Cannot update sound settings"); toast.error("Cannot update sound settings");
} else { } else {
@@ -139,7 +144,7 @@ const SoundSettingsFields = () => {
</div> </div>
<button <button
type="submit" type="submit"
className="w-1/4 text-white bg-green-700 hover:bg-green-800 font-small rounded-lg text-sm px-2 py-2.5" className="w-full md:w-1/4 text-white bg-green-700 hover:bg-green-800 font-small rounded-lg text-sm px-2 py-2.5"
> >
Save Settings Save Settings
</button> </button>

View File

@@ -46,7 +46,11 @@ const SoundUpload = () => {
if (result.reason !== "OK") { if (result.reason !== "OK") {
toast.error("Cannot update sound settings"); toast.error("Cannot update sound settings");
} }
await mutation.mutateAsync({
operation: "SAVE",
path: "",
value: null,
});
dispatch({ type: "ADD", payload: values }); dispatch({ type: "ADD", payload: values });
}; };
@@ -96,7 +100,7 @@ const SoundUpload = () => {
{errors.soundFile && <p className="text-red-500 text-sm mt-1">Not an mp3 file</p>} {errors.soundFile && <p className="text-red-500 text-sm mt-1">Not an mp3 file</p>}
<button <button
type="submit" type="submit"
className="w-1/4 text-white bg-green-700 hover:bg-green-800 font-small rounded-lg text-sm px-2 py-2.5 mt-[5%]" className="w-full md:w-1/4 text-white bg-green-700 hover:bg-green-800 font-small rounded-lg text-sm px-2 py-2.5 mt-[5%]"
disabled={errors.soundFile ? true : false} disabled={errors.soundFile ? true : false}
> >
Upload Upload

View File

@@ -167,7 +167,7 @@ const SystemConfigFields = () => {
</FormGroup> </FormGroup>
<button <button
type="submit" type="submit"
className="w-1/4 text-white bg-green-700 hover:bg-green-800 font-small rounded-lg text-sm px-2 py-2.5" className="w-full md:w-1/4 text-white bg-green-700 hover:bg-green-800 font-small rounded-lg text-sm px-2 py-2.5"
disabled={isSubmitting} disabled={isSubmitting}
> >
{saveSystemSettingsLoading ? "Saving..." : "Save System Settings"} {saveSystemSettingsLoading ? "Saving..." : "Save System Settings"}

View File

@@ -52,7 +52,7 @@ const SystemFileUpload = ({ name, selectedFile }: SystemFileUploadProps) => {
</FormGroup> </FormGroup>
<button <button
type="button" type="button"
className="w-1/4 text-white bg-green-700 hover:bg-green-800 font-small rounded-lg text-sm px-2 py-2.5 disabled:opacity-50 disabled:cursor-not-allowed" className="w-full md:w-1/4 text-white bg-green-700 hover:bg-green-800 font-small rounded-lg text-sm px-2 py-2.5 disabled:opacity-50 disabled:cursor-not-allowed"
disabled={!selectedFile} disabled={!selectedFile}
onClick={handleFileUploadClick} onClick={handleFileUploadClick}
> >

View File

@@ -178,7 +178,7 @@ const ModemSettings = () => {
)} )}
<button <button
type="submit" type="submit"
className="w-1/4 text-white bg-green-700 hover:bg-green-800 font-small rounded-lg text-sm px-2 py-2.5" className="w-full md:w-1/4 text-white bg-green-700 hover:bg-green-800 font-small rounded-lg text-sm px-2 py-2.5"
> >
{isSubmitting || modemMutation.isPending ? "Saving..." : "Save Modem settings"} {isSubmitting || modemMutation.isPending ? "Saving..." : "Save Modem settings"}
</button> </button>

View File

@@ -25,7 +25,7 @@ const SightingModal = ({ isSightingModalOpen, handleClose, sighting, onDelete }:
const { query, mutation } = useCameraBlackboard(); const { query, mutation } = useCameraBlackboard();
const hotlistNames = getHotlistName(sighting?.metadata?.hotlistMatches); const hotlistNames = getHotlistName(sighting?.metadata?.hotlistMatches);
const handleAcknowledgeButton = () => { const handleAcknowledgeButton = async () => {
try { try {
if (!sighting) { if (!sighting) {
toast.error("Cannot add sighting to alert list"); toast.error("Cannot add sighting to alert list");
@@ -33,17 +33,27 @@ const SightingModal = ({ isSightingModalOpen, handleClose, sighting, onDelete }:
return; return;
} }
if (!query.data.alertHistory) { if (!query.data.alertHistory) {
mutation.mutate({ await mutation.mutateAsync({
operation: "INSERT", operation: "INSERT",
path: "alertHistory", path: "alertHistory",
value: [sighting], value: [sighting],
}); });
await mutation.mutateAsync({
operation: "SAVE",
path: "",
value: null,
});
} else { } else {
mutation.mutate({ await mutation.mutateAsync({
operation: "APPEND", operation: "APPEND",
path: "alertHistory", path: "alertHistory",
value: sighting, value: sighting,
}); });
await mutation.mutateAsync({
operation: "SAVE",
path: "",
value: null,
});
toast.success("Sighting Successfully added to alert list"); toast.success("Sighting Successfully added to alert list");
} }

View File

@@ -1,15 +1,26 @@
import { Link } from "react-router"; import { Link } from "react-router";
import Logo from "/MAV.svg"; import Logo from "/MAV.svg";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faGear, faHome, faListCheck, faMaximize, faMinimize, faRotate } from "@fortawesome/free-solid-svg-icons"; import {
faBars,
faGear,
faHome,
faListCheck,
faMaximize,
faMinimize,
faRotate,
} from "@fortawesome/free-solid-svg-icons";
import { useState } from "react"; import { useState } from "react";
import SoundBtn from "./SoundBtn"; import SoundBtn from "./SoundBtn";
import { useIntegrationsContext } from "../../context/IntegrationsContext"; import { useIntegrationsContext } from "../../context/IntegrationsContext";
export default function Header() { export default function Header() {
const [isFullscreen, setIsFullscreen] = useState(false); const [isFullscreen, setIsFullscreen] = useState(false);
const [isMenuOpen, setIsMenuOpen] = useState(false);
const { state } = useIntegrationsContext(); const { state } = useIntegrationsContext();
const toggleMenu = () => setIsMenuOpen(!isMenuOpen);
const sessionStarted = state.sessionStarted; const sessionStarted = state.sessionStarted;
const sessionPaused = state.sessionPaused; const sessionPaused = state.sessionPaused;
@@ -36,7 +47,7 @@ export default function Header() {
</Link> </Link>
</div> </div>
<div className="flex flex-col lg:flex-row items-center space-x-24 justify-items-center"> <div className="flex flex-col lg:flex-row items-center space-x-24 justify-items-center">
<div className="flex flex-row lg:flex-row space-x-2"> <div className="flex flex-row lg:flex-row space-x-2 mx-10 p-2 md:p-0 items-center">
{sessionStarted && sessionPaused ? ( {sessionStarted && sessionPaused ? (
<p className="text-gray-400 font-bold">Session Paused</p> <p className="text-gray-400 font-bold">Session Paused</p>
) : ( ) : (
@@ -44,7 +55,7 @@ export default function Header() {
)} )}
</div> </div>
<div className="flex flex-row space-x-8"> <div className="flex flex-row space-x-6 md:space-x-8 items-center">
<Link to={"/"}> <Link to={"/"}>
<FontAwesomeIcon className="text-white" icon={faHome} size="2x" /> <FontAwesomeIcon className="text-white" icon={faHome} size="2x" />
</Link> </Link>
@@ -59,15 +70,35 @@ export default function Header() {
<FontAwesomeIcon icon={faRotate} size="2x" /> <FontAwesomeIcon icon={faRotate} size="2x" />
</div> </div>
<SoundBtn /> <SoundBtn />
<Link to={"/session-settings"}> <div className="md:hidden">
<FontAwesomeIcon icon={faBars} size="2x" onClick={toggleMenu} />
</div>
<Link className="hidden md:flex" to={"/session-settings"}>
<FontAwesomeIcon className="text-white" icon={faListCheck} size="2x" /> <FontAwesomeIcon className="text-white" icon={faListCheck} size="2x" />
</Link> </Link>
<Link to={"/system-settings"}> <Link className="hidden md:flex" to={"/system-settings"}>
<FontAwesomeIcon className="text-white" icon={faGear} size="2x" /> <FontAwesomeIcon className="text-white" icon={faGear} size="2x" />
</Link> </Link>
</div> </div>
</div> </div>
{isMenuOpen && (
<div className="md:hidden">
<ul className="flex flex-row gap-5">
<li onClick={() => setIsMenuOpen(false)}>
<Link to={"/session-settings"}>
<FontAwesomeIcon className="text-white" icon={faListCheck} size="2x" />
</Link>
</li>
<li onClick={() => setIsMenuOpen(false)}>
<Link to={"/system-settings"}>
<FontAwesomeIcon className="text-white" icon={faGear} size="2x" />
</Link>
</li>
</ul>
</div>
)}
</div> </div>
); );
} }

View File

@@ -16,6 +16,11 @@ const SoundBtn = () => {
path: "soundEnabled", path: "soundEnabled",
value: { enabled: newEnabled }, value: { enabled: newEnabled },
}); });
await mutation.mutateAsync({
operation: "SAVE",
path: "",
value: null,
});
}; };
useEffect(() => { useEffect(() => {
setEnabled(query?.data?.soundEnabled?.enabled); setEnabled(query?.data?.soundEnabled?.enabled);
@@ -23,10 +28,7 @@ const SoundBtn = () => {
return ( return (
<button onClick={handleClick}> <button onClick={handleClick}>
<FontAwesomeIcon <FontAwesomeIcon icon={enabled ? faVolumeHigh : faVolumeXmark} size="2x" />
icon={enabled ? faVolumeHigh : faVolumeXmark}
size="2x"
/>
</button> </button>
); );
}; };

View File

@@ -16,6 +16,11 @@ export const IntegrationsProvider = ({ children }: IntegrationsProviderType) =>
const fetchData = async () => { const fetchData = async () => {
try { try {
await mutation.mutateAsync({
operation: "Load",
path: "",
value: null,
});
const result = await mutation.mutateAsync({ const result = await mutation.mutateAsync({
operation: "VIEW", operation: "VIEW",
path: "sessionStats", path: "sessionStats",

View File

@@ -20,6 +20,11 @@ const SoundContextProvider = ({ children }: SoundContextProviderProps) => {
operation: "VIEW", operation: "VIEW",
path: "soundSettings", path: "soundSettings",
}); });
await mutation.mutateAsync({
operation: "LOAD",
path: "",
value: null,
});
if (!result.result || typeof result.result !== "object") { if (!result.result || typeof result.result !== "object") {
dispatch({ type: "UPDATE", payload: state }); dispatch({ type: "UPDATE", payload: state });

View File

@@ -33,7 +33,7 @@ body {
} }
.arrow-outline path { .arrow-outline path {
stroke: black; /* outline color */ stroke: black;
stroke-width: 20px; /* thickness of outline (tweak this) */ stroke-width: 20px;
stroke-linejoin: round; stroke-linejoin: round;
} }

View File

@@ -22,7 +22,7 @@ const SystemSettings = () => {
<Tab>System</Tab> <Tab>System</Tab>
<Tab>Output</Tab> <Tab>Output</Tab>
<Tab>Integrations</Tab> <Tab>Integrations</Tab>
<Tab>WiFi and Modem</Tab> <Tab>WiFi & Modem</Tab>
<Tab>Sound</Tab> <Tab>Sound</Tab>
</TabList> </TabList>
<TabPanel> <TabPanel>

View File

@@ -282,7 +282,7 @@ export type CameraConfig = {
export type CameraBlackBoardOptions = { export type CameraBlackBoardOptions = {
operation?: string; operation?: string;
path?: string; path?: string;
value?: object | string | number | (string | number)[]; value?: object | string | number | (string | number)[] | null;
}; };
export type CameraBlackboardResponse = { export type CameraBlackboardResponse = {