started redesign on dashbaord. changed vite basename to /Mobile, currently folkstone address
This commit is contained in:
2
.env
2
.env
@@ -1,5 +1,5 @@
|
|||||||
VITE_BASEURL=http://192.168.75.11/
|
VITE_BASEURL=http://192.168.75.11/
|
||||||
VITE_CAM_BASE=http://100.72.72.70
|
VITE_CAM_BASE=http://100.72.72.70:8080
|
||||||
VITE_FOLKESTONE_BASE=http://100.116.253.81
|
VITE_FOLKESTONE_BASE=http://100.116.253.81
|
||||||
VITE_TESTURL=http://100.82.205.44/SightingListRear/sightingSummary?mostRecentRef=-1
|
VITE_TESTURL=http://100.82.205.44/SightingListRear/sightingSummary?mostRecentRef=-1
|
||||||
VITE_OUTSIDE_BASEURL=http://100.82.205.44
|
VITE_OUTSIDE_BASEURL=http://100.82.205.44
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ const CameraSettings = ({ title, side }: { title: string; side: string }) => {
|
|||||||
console.log(updateCameraConfigError);
|
console.log(updateCameraConfigError);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card>
|
<Card className="px-4 py-4">
|
||||||
{isPending && <>Loading camera config</>}
|
{isPending && <>Loading camera config</>}
|
||||||
{isError && <>Error fetching camera config</>}
|
{isError && <>Error fetching camera config</>}
|
||||||
<div className="relative flex flex-col space-y-3 h-full">
|
<div className="relative flex flex-col space-y-3 h-full">
|
||||||
|
|||||||
@@ -1,16 +1,11 @@
|
|||||||
import clsx from "clsx";
|
import clsx from "clsx";
|
||||||
import Card from "../UI/Card";
|
import Card from "../UI/Card";
|
||||||
import CardHeader from "../UI/CardHeader";
|
|
||||||
import { faCamera } from "@fortawesome/free-regular-svg-icons";
|
|
||||||
import { useSwipeable } from "react-swipeable";
|
import { useSwipeable } from "react-swipeable";
|
||||||
import { useNavigate } from "react-router";
|
import { useNavigate } from "react-router";
|
||||||
import { useOverviewVideo } from "../../hooks/useOverviewVideo";
|
import { useOverviewVideo } from "../../hooks/useOverviewVideo";
|
||||||
import SightingOverview from "../SightingOverview/SightingOverview";
|
import SightingOverview from "../SightingOverview/SightingOverview";
|
||||||
import { useSightingFeedContext } from "../../context/SightingFeedContext";
|
|
||||||
|
|
||||||
type CardProps = React.HTMLAttributes<HTMLDivElement>;
|
const FrontCameraOverviewCard = () => {
|
||||||
|
|
||||||
const FrontCameraOverviewCard = ({ className }: CardProps) => {
|
|
||||||
useOverviewVideo();
|
useOverviewVideo();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const handlers = useSwipeable({
|
const handlers = useSwipeable({
|
||||||
@@ -18,23 +13,15 @@ const FrontCameraOverviewCard = ({ className }: CardProps) => {
|
|||||||
|
|
||||||
trackMouse: true,
|
trackMouse: true,
|
||||||
});
|
});
|
||||||
const { mostRecent } = useSightingFeedContext();
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card
|
<Card
|
||||||
className={clsx(
|
className={clsx(
|
||||||
"relative min-h-[40vh] md:min-h-[60vh] h-auto",
|
"relative min-h-[40vh] md:min-h-[60vh] max-h-[80vh] lg:w-[70%] overflow-y-hidden"
|
||||||
className
|
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<div className="flex flex-col space-y-3 h-full" {...handlers}>
|
<div className="lg:overflow-hidden" {...handlers}>
|
||||||
<CardHeader
|
|
||||||
title="Front Overview"
|
|
||||||
icon={faCamera}
|
|
||||||
sighting={mostRecent}
|
|
||||||
/>
|
|
||||||
<SightingOverview />
|
<SightingOverview />
|
||||||
{/* <SnapshotContainer side="TargetDetectionFront" /> */}
|
|
||||||
</div>
|
</div>
|
||||||
</Card>
|
</Card>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -14,7 +14,11 @@ const OverviewVideoContainer = ({
|
|||||||
settingsPage?: boolean;
|
settingsPage?: boolean;
|
||||||
}) => {
|
}) => {
|
||||||
return (
|
return (
|
||||||
<Card className={clsx("min-h-[40vh] md:min-h-[60vh] h-auto")}>
|
<Card
|
||||||
|
className={clsx(
|
||||||
|
"min-h-[40vh] md:min-h-[60vh] max-h-[80vh] h-auto overflow-y-hidden"
|
||||||
|
)}
|
||||||
|
>
|
||||||
<div className="relative flex flex-col space-y-3 h-full">
|
<div className="relative flex flex-col space-y-3 h-full">
|
||||||
<CardHeader title={title} icon={faCamera} />
|
<CardHeader title={title} icon={faCamera} />
|
||||||
<SnapshotContainer side={side} settingsPage={settingsPage} />
|
<SnapshotContainer side={side} settingsPage={settingsPage} />
|
||||||
|
|||||||
@@ -4,21 +4,53 @@ import { formatNumberPlate } from "../../utils/utils";
|
|||||||
type NumberPlateProps = {
|
type NumberPlateProps = {
|
||||||
vrm?: string | undefined;
|
vrm?: string | undefined;
|
||||||
motion?: boolean;
|
motion?: boolean;
|
||||||
|
size?: "xs" | "sm" | "md" | "lg";
|
||||||
};
|
};
|
||||||
|
|
||||||
const NumberPlate = ({ motion, vrm }: NumberPlateProps) => {
|
const NumberPlate = ({ motion, vrm, size }: NumberPlateProps) => {
|
||||||
|
let options = {
|
||||||
|
plateWidth: "w-[14rem]",
|
||||||
|
textSize: "text-2xl",
|
||||||
|
borderWidth: "border-6",
|
||||||
|
};
|
||||||
|
|
||||||
|
switch (size) {
|
||||||
|
case "xs":
|
||||||
|
options = {
|
||||||
|
plateWidth: "w-[8rem]",
|
||||||
|
textSize: "text-md",
|
||||||
|
borderWidth: "border-4",
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
case "sm":
|
||||||
|
options = {
|
||||||
|
plateWidth: "w-[10rem]",
|
||||||
|
textSize: "text-lg",
|
||||||
|
borderWidth: "border-4",
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
case "lg":
|
||||||
|
options = {
|
||||||
|
plateWidth: "w-[16rem]",
|
||||||
|
textSize: "text-3xl",
|
||||||
|
borderWidth: "border-6",
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={`relative w-[16rem] border-6 border-black rounded-xl text-nowrap
|
className={`relative ${options.plateWidth} ${
|
||||||
text-black px-6 py-2
|
options.borderWidth
|
||||||
${motion ? "bg-yellow-400" : "bg-white"}
|
} border-black rounded-xl text-nowrap
|
||||||
`}
|
text-black px-6 py-2
|
||||||
|
${motion ? "bg-yellow-400" : "bg-white"}`}
|
||||||
>
|
>
|
||||||
<div>
|
<div>
|
||||||
<div className="absolute inset-y-0 left-0 bg-blue-600 w-8 flex flex-col">
|
<div className="absolute inset-y-0 left-0 bg-blue-600 w-8 flex flex-col">
|
||||||
<GB />
|
<GB />
|
||||||
</div>
|
</div>
|
||||||
<p className="pl-4 font-extrabold text-3xl text-right">
|
<p className={`pl-4 font-extrabold ${options.textSize} text-right`}>
|
||||||
{vrm && formatNumberPlate(vrm)}
|
{vrm && formatNumberPlate(vrm)}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import { useCallback, useRef, useState } from "react";
|
import { useCallback, useRef, useState } from "react";
|
||||||
import { BLANK_IMG } from "../../utils/utils";
|
import { BLANK_IMG } from "../../utils/utils";
|
||||||
import SightingWidgetDetails from "../SightingsWidget/SightingWidgetDetails";
|
|
||||||
import { useOverviewOverlay } from "../../hooks/useOverviewOverlay";
|
import { useOverviewOverlay } from "../../hooks/useOverviewOverlay";
|
||||||
import { useSightingFeedContext } from "../../context/SightingFeedContext";
|
import { useSightingFeedContext } from "../../context/SightingFeedContext";
|
||||||
import { useHiDPICanvas } from "../../hooks/useHiDPICanvas";
|
import { useHiDPICanvas } from "../../hooks/useHiDPICanvas";
|
||||||
import NavigationArrow from "../UI/NavigationArrow";
|
import NavigationArrow from "../UI/NavigationArrow";
|
||||||
|
import NumberPlate from "../PlateStack/NumberPlate";
|
||||||
|
|
||||||
const SightingOverview = () => {
|
const SightingOverview = () => {
|
||||||
const [overlayMode, setOverlayMode] = useState<0 | 1 | 2>(0);
|
const [overlayMode, setOverlayMode] = useState<0 | 1 | 2>(0);
|
||||||
@@ -27,42 +27,34 @@ const SightingOverview = () => {
|
|||||||
if (isError) return <p>An error occurred, Cannot display footage</p>;
|
if (isError) return <p>An error occurred, Cannot display footage</p>;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col">
|
<div className="flex flex-col md:flex-row">
|
||||||
<div className="grid gap-3">
|
{mostRecent && (
|
||||||
<NavigationArrow side={side} />
|
<div className="z-30 px-1 pt-2">
|
||||||
<div className="inline-block w-full mx-auto">
|
<NumberPlate vrm={mostRecent?.vrm} size="sm" />
|
||||||
<div className="relative aspect-[1280/800]">
|
|
||||||
<img
|
|
||||||
ref={imgRef}
|
|
||||||
onLoad={() => {
|
|
||||||
sync();
|
|
||||||
setOverlayMode((m) => m);
|
|
||||||
}}
|
|
||||||
src={mostRecent?.overviewUrl || BLANK_IMG}
|
|
||||||
alt="overview"
|
|
||||||
className="absolute inset-0 w-full h-full object-contain cursor-pointer z-10 "
|
|
||||||
onClick={onOverviewClick}
|
|
||||||
style={{
|
|
||||||
display: mostRecent?.overviewUrl ? "block" : "none",
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<canvas
|
|
||||||
ref={canvasRef}
|
|
||||||
className="absolute inset-0 w-full h-full object-contain z-20 pointer-events-none "
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="text-xs opacity-80">
|
|
||||||
Overlay:{" "}
|
|
||||||
{overlayMode === 0
|
|
||||||
? "Off"
|
|
||||||
: overlayMode === 1
|
|
||||||
? "Plate box"
|
|
||||||
: "Track + box"}{" "}
|
|
||||||
(click image to toggle)
|
|
||||||
</div>
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<NavigationArrow side={side} />
|
||||||
|
<div className="w-full">
|
||||||
|
<img
|
||||||
|
ref={imgRef}
|
||||||
|
onLoad={() => {
|
||||||
|
sync();
|
||||||
|
setOverlayMode((m) => m);
|
||||||
|
}}
|
||||||
|
src={mostRecent?.overviewUrl || BLANK_IMG}
|
||||||
|
alt="overview"
|
||||||
|
className="absolute inset-0 object-contain cursor-pointer z-10 min-h-[100%] rounded-lg"
|
||||||
|
onClick={onOverviewClick}
|
||||||
|
style={{
|
||||||
|
display: mostRecent?.overviewUrl ? "block" : "none",
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<canvas
|
||||||
|
ref={canvasRef}
|
||||||
|
className="absolute inset-0 object-contain z-20 pointer-events-none "
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<SightingWidgetDetails effectiveSelected={mostRecent} />
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ type SightingHistoryProps = {
|
|||||||
pollMs?: number;
|
pollMs?: number;
|
||||||
autoSelectLatest?: boolean;
|
autoSelectLatest?: boolean;
|
||||||
title: string;
|
title: string;
|
||||||
className: string;
|
className?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function SightingHistoryWidget({
|
export default function SightingHistoryWidget({
|
||||||
@@ -113,7 +113,12 @@ export default function SightingHistoryWidget({
|
|||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Card className={clsx("overflow-y-auto h-100", className)}>
|
<Card
|
||||||
|
className={clsx(
|
||||||
|
"overflow-y-auto min-h-[40vh] md:min-h-[60vh] max-h-[80vh] lg:w-[40%]",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
>
|
||||||
<CardHeader title={title} />
|
<CardHeader title={title} />
|
||||||
<div className="flex flex-col gap-3 ">
|
<div className="flex flex-col gap-3 ">
|
||||||
{/* Rows */}
|
{/* Rows */}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ const Card = ({ children, className }: CardProps) => {
|
|||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={clsx(
|
className={clsx(
|
||||||
"bg-[#253445] rounded-lg mt-4 mx-2 px-4 py-4 shadow-2xl overflow-y-auto md:row-span-1",
|
"bg-[#253445] rounded-lg mt-4 mx-2 shadow-2xl overflow-x-hidden md:row-span-1 px-2",
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import NumberPlate from "../PlateStack/NumberPlate";
|
|||||||
import type { SightingType } from "../../types/types";
|
import type { SightingType } from "../../types/types";
|
||||||
|
|
||||||
type CameraOverviewHeaderProps = {
|
type CameraOverviewHeaderProps = {
|
||||||
title: string;
|
title?: string;
|
||||||
icon?: IconProp;
|
icon?: IconProp;
|
||||||
img?: string;
|
img?: string;
|
||||||
sighting?: SightingType | null;
|
sighting?: SightingType | null;
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import { useRef, useCallback, useEffect } from "react";
|
import { useRef, useCallback, useEffect } from "react";
|
||||||
import { useQuery } from "@tanstack/react-query";
|
import { useQuery } from "@tanstack/react-query";
|
||||||
import { CAM_BASE } from "../utils/config";
|
import { OUTSIDE_CAM_BASE } from "../utils/config";
|
||||||
|
|
||||||
const apiUrl = CAM_BASE;
|
const apiUrl = OUTSIDE_CAM_BASE;
|
||||||
|
|
||||||
async function fetchSnapshot(cameraSide: string) {
|
async function fetchSnapshot(cameraSide: string) {
|
||||||
const response = await fetch(`${apiUrl}/${cameraSide}-preview`);
|
const response = await fetch(`${apiUrl}/${cameraSide}-preview`);
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ Modal.setAppElement("#root");
|
|||||||
createRoot(document.getElementById("root")!).render(
|
createRoot(document.getElementById("root")!).render(
|
||||||
<StrictMode>
|
<StrictMode>
|
||||||
<QueryClientProvider client={queryClient}>
|
<QueryClientProvider client={queryClient}>
|
||||||
<BrowserRouter basename="/InCarTest">
|
<BrowserRouter basename="/Mobile">
|
||||||
<App />
|
<App />
|
||||||
</BrowserRouter>
|
</BrowserRouter>
|
||||||
</QueryClientProvider>
|
</QueryClientProvider>
|
||||||
|
|||||||
@@ -1,34 +1,18 @@
|
|||||||
import FrontCameraOverviewCard from "../components/FrontCameraOverview/FrontCameraOverviewCard";
|
import FrontCameraOverviewCard from "../components/FrontCameraOverview/FrontCameraOverviewCard";
|
||||||
import RearCameraOverviewCard from "../components/RearCameraOverview/RearCameraOverviewCard";
|
|
||||||
import SightingHistoryWidget from "../components/SightingsWidget/SightingWidget";
|
import SightingHistoryWidget from "../components/SightingsWidget/SightingWidget";
|
||||||
import { SightingFeedProvider } from "../context/providers/SightingFeedProvider";
|
import { SightingFeedProvider } from "../context/providers/SightingFeedProvider";
|
||||||
|
// import { OUTSIDE_CAM_BASE } from "../utils/config";
|
||||||
import { CAM_BASE } from "../utils/config";
|
|
||||||
|
|
||||||
const Dashboard = () => {
|
const Dashboard = () => {
|
||||||
const dev_REAR_URL = `${CAM_BASE}/SightingListRear/sightingSummary?mostRecentRef=`;
|
// const dev_OUTSIDE_URL = `${OUTSIDE_CAM_BASE}/SightingListFront/sightingSummary?mostRecentRef=`;
|
||||||
const dev_FRONT_URL = `${CAM_BASE}/SightingListFront/sightingSummary?mostRecentRef=`;
|
const folkestone_OUTSIDE_URL = `http://100.116.253.81/mergedHistory/sightingSummary?mostRecentRef=`;
|
||||||
|
|
||||||
console.log(CAM_BASE);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="mx-auto grid grid-cols-1 sm:grid-cols-1 lg:grid-cols-2 gap-2 px-1 sm:px-2 lg:px-0 w-full">
|
<SightingFeedProvider url={folkestone_OUTSIDE_URL} side="Front">
|
||||||
<SightingFeedProvider url={dev_FRONT_URL} side="Front">
|
<div className="mx-auto flex flex-col lg:flex-row gap-2 px-1 sm:px-2 lg:px-0 w-full min-h-screen">
|
||||||
<FrontCameraOverviewCard className="order-1" />
|
<FrontCameraOverviewCard />
|
||||||
<SightingHistoryWidget
|
<SightingHistoryWidget title="Sightings" />
|
||||||
className="order-3"
|
</div>
|
||||||
title="Front Camera Sightings"
|
</SightingFeedProvider>
|
||||||
/>
|
|
||||||
</SightingFeedProvider>
|
|
||||||
|
|
||||||
<SightingFeedProvider url={dev_REAR_URL} side="Rear">
|
|
||||||
<RearCameraOverviewCard className="order-2" />
|
|
||||||
<SightingHistoryWidget
|
|
||||||
className="order-4"
|
|
||||||
title="Rear Camera Sightings"
|
|
||||||
/>
|
|
||||||
</SightingFeedProvider>
|
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
const rawCamBase = import.meta.env.VITE_CAM_BASE;
|
const rawCamBase = import.meta.env.VITE_CAM_BASE;
|
||||||
|
|
||||||
export const CAM_BASE =
|
export const CAM_BASE =
|
||||||
rawCamBase && rawCamBase.trim().length > 0
|
rawCamBase && rawCamBase.trim().length > 0
|
||||||
? rawCamBase
|
? rawCamBase
|
||||||
: window.location.origin;
|
: window.location.origin;
|
||||||
|
|
||||||
|
export const OUTSIDE_CAM_BASE = import.meta.env.VITE_OUTSIDE_BASEURL;
|
||||||
|
|||||||
@@ -6,5 +6,5 @@ import tailwindcss from "@tailwindcss/vite";
|
|||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
plugins: [react(), tailwindcss()],
|
plugins: [react(), tailwindcss()],
|
||||||
server: { host: true },
|
server: { host: true },
|
||||||
base: "/InCarTest",
|
base: "/Mobile",
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user