Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16,398 changes: 8,282 additions & 8,116 deletions frontend/package-lock.json

Large diffs are not rendered by default.

150 changes: 75 additions & 75 deletions frontend/package.json
Original file line number Diff line number Diff line change
@@ -1,77 +1,77 @@
{
"name": "frontend",
"private": true,
"version": "v0.7.2-beta.dwd",
"type": "module",
"scripts": {
"dev": "vite --host",
"build": "tsc -b && vite build",
"regenerate-schemas": "openapi-typescript http://localhost:5000/openapi.json -o ./src/schemas/dwe_os_2.d.ts",
"lint": "eslint .",
"preview": "vite preview",
"schema-pull": "openapi-typescript http://localhost:5000/openapi.json -o ./src/schemas/dwe_os_2.d.ts"
},
"dependencies": {
"@radix-ui/react-accordion": "^1.2.10",
"@radix-ui/react-alert-dialog": "^1.1.15",
"@radix-ui/react-checkbox": "^1.2.3",
"@radix-ui/react-dialog": "^1.1.6",
"@radix-ui/react-dropdown-menu": "^2.1.2",
"@radix-ui/react-label": "^2.1.8",
"@radix-ui/react-progress": "^1.1.8",
"@radix-ui/react-radio-group": "^1.3.6",
"@radix-ui/react-scroll-area": "^1.2.6",
"@radix-ui/react-select": "^2.1.6",
"@radix-ui/react-separator": "^1.1.8",
"@radix-ui/react-slider": "^1.3.3",
"@radix-ui/react-slot": "^1.2.4",
"@radix-ui/react-switch": "^1.2.3",
"@radix-ui/react-tabs": "^1.1.9",
"@radix-ui/react-toast": "^1.2.6",
"@radix-ui/react-toggle": "^1.1.10",
"@radix-ui/react-tooltip": "^1.1.4",
"@xterm/addon-canvas": "^0.7.0",
"@xterm/addon-fit": "^0.10.0",
"@xterm/addon-image": "^0.8.0",
"@xterm/addon-unicode11": "^0.8.0",
"@xterm/addon-web-links": "^0.11.0",
"@xterm/addon-webgl": "^0.18.0",
"@xterm/xterm": "^5.5.0",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"cmdk": "^1.1.1",
"immer": "^11.1.8",
"lucide-react": "^0.456.0",
"motion": "^12.23.26",
"next-themes": "^0.4.6",
"openapi-fetch": "^0.13.5",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-markdown": "^10.1.0",
"react-router-dom": "^6.28.0",
"socket.io-client": "^4.8.1",
"sonner": "^2.0.7",
"tailwind-merge": "^2.5.4",
"tailwindcss-animate": "^1.0.7",
"valtio": "^2.3.2",
"zustand": "^5.0.13"
},
"devDependencies": {
"@eslint/js": "^9.13.0",
"@types/node": "^22.9.0",
"@types/react": "^18.3.12",
"@types/react-dom": "^18.3.1",
"@vitejs/plugin-react": "^4.3.3",
"autoprefixer": "^10.4.20",
"eslint": "^9.13.0",
"eslint-plugin-react-hooks": "^5.0.0",
"eslint-plugin-react-refresh": "^0.4.14",
"globals": "^15.11.0",
"openapi-typescript": "^7.6.1",
"postcss": "^8.4.49",
"tailwindcss": "^3.4.14",
"typescript": "~5.6.2",
"typescript-eslint": "^8.11.0",
"vite": "^5.4.10"
}
"name": "frontend",
"private": true,
"version": "v0.7.2-beta.dwd",
"type": "module",
"scripts": {
"dev": "vite --host",
"build": "tsc -b && vite build",
"regenerate-schemas": "openapi-typescript http://localhost:5000/openapi.json -o ./src/schemas/dwe_os_2.d.ts",
"lint": "eslint .",
"preview": "vite preview",
"schema-pull": "openapi-typescript http://localhost:5000/openapi.json -o ./src/schemas/dwe_os_2.d.ts"
},
"dependencies": {
"@radix-ui/react-accordion": "^1.2.10",
"@radix-ui/react-alert-dialog": "^1.1.15",
"@radix-ui/react-checkbox": "^1.2.3",
"@radix-ui/react-dialog": "^1.1.6",
"@radix-ui/react-dropdown-menu": "^2.1.2",
"@radix-ui/react-label": "^2.1.8",
"@radix-ui/react-progress": "^1.1.8",
"@radix-ui/react-radio-group": "^1.3.6",
"@radix-ui/react-scroll-area": "^1.2.6",
"@radix-ui/react-select": "^2.1.6",
"@radix-ui/react-separator": "^1.1.8",
"@radix-ui/react-slider": "^1.3.3",
"@radix-ui/react-slot": "^1.2.4",
"@radix-ui/react-switch": "^1.2.3",
"@radix-ui/react-tabs": "^1.1.9",
"@radix-ui/react-toast": "^1.2.6",
"@radix-ui/react-toggle": "^1.1.10",
"@radix-ui/react-tooltip": "^1.1.4",
"@xterm/addon-canvas": "^0.7.0",
"@xterm/addon-fit": "^0.10.0",
"@xterm/addon-image": "^0.8.0",
"@xterm/addon-unicode11": "^0.8.0",
"@xterm/addon-web-links": "^0.11.0",
"@xterm/addon-webgl": "^0.18.0",
"@xterm/xterm": "^5.5.0",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"cmdk": "^1.1.1",
"immer": "^11.1.8",
"lucide-react": "^1.20.0",
"motion": "^12.23.26",
"next-themes": "^0.4.6",
"openapi-fetch": "^0.13.5",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-markdown": "^10.1.0",
"react-router-dom": "^6.28.0",
"socket.io-client": "^4.8.1",
"sonner": "^2.0.7",
"tailwind-merge": "^2.5.4",
"tailwindcss-animate": "^1.0.7",
"valtio": "^2.3.2",
"zustand": "^5.0.13"
},
"devDependencies": {
"@eslint/js": "^9.13.0",
"@types/node": "^22.9.0",
"@types/react": "^18.3.12",
"@types/react-dom": "^18.3.1",
"@vitejs/plugin-react": "^4.3.3",
"autoprefixer": "^10.4.20",
"eslint": "^9.13.0",
"eslint-plugin-react-hooks": "^5.0.0",
"eslint-plugin-react-refresh": "^0.4.14",
"globals": "^15.11.0",
"openapi-typescript": "^7.6.1",
"postcss": "^8.4.49",
"tailwindcss": "^3.4.14",
"typescript": "~5.6.2",
"typescript-eslint": "^8.11.0",
"vite": "^6.4.3"
}
}
60 changes: 29 additions & 31 deletions frontend/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,46 +12,36 @@ import {
SidebarTrigger,
} from "@/components/ui/sidebar";

import { Outlet, useLocation } from "react-router-dom";
import { ThemeProvider } from "@/components/themes/theme-provider";
import { ModeToggle } from "./components/themes/mode-toggle";
import { CommandPalette } from "./components/dwe/app/command-palette";
import { io, Socket } from "socket.io-client";
import { useEffect, useRef, useState } from "react";
import WebsocketContext from "./contexts/WebsocketContext";
import {
TOUR_STEP_IDS,
TourDialog,
TourProvider,
useTour,
} from "@/components/tour";
import { Toaster } from "@/components/ui/sonner";
import { SystemDropdown } from "./components/dwe/system/system-dropdown";
import { CircleHelpIcon } from "lucide-react";
import { useEffect, useRef, useState } from "react";
import { Outlet, useLocation } from "react-router-dom";
import { io, Socket } from "socket.io-client";
import { API_CLIENT } from "./api";
import { TourAlertDialog, TourProvider, useTour } from "@/components/tour/tour";
import { getSteps } from "./components/tour/tour-steps";
import { CommandPalette } from "./components/dwe/app/command-palette";
import { SystemDropdown } from "./components/dwe/system/system-dropdown";
import { ModeToggle } from "./components/themes/mode-toggle";
import FeaturesContext from "./contexts/FeaturesContext";
import WebsocketContext from "./contexts/WebsocketContext";
import { useLogSocketToasts } from "./hooks/use-log-socket-toasts";
import { components } from "./schemas/dwe_os_2";

type WelcomeTourProps = { features: components["schemas"]["FeatureSupport"] };
function WelcomeTourManager(props: WelcomeTourProps) {
const [openTour, setOpenTour] = useState(false);
const { setSteps } = useTour();

useEffect(() => {
setSteps(getSteps(props.features));
const timer = setTimeout(() => {
setOpenTour(true);
}, 100);

return () => clearTimeout(timer);
}, [setSteps, props.features]);

return <TourAlertDialog isOpen={openTour} setIsOpen={setOpenTour} />;
}

function AppContent() {
const [features, setFeatures] = useState<
components["schemas"]["FeatureSupport"] | undefined
>(undefined);

const location = useLocation();

const { startTour } = useTour();

const getPageTitle = (pathname: string) => {
switch (pathname) {
case "/":
Expand Down Expand Up @@ -87,35 +77,42 @@ function AppContent() {
<SidebarProvider>
<SidebarLeft />
<SidebarInset>
<header className="sticky top-0 flex h-14 shrink-0 items-center gap-2 bg-background z-50">
<header className="sticky top-0 z-25 flex h-14 shrink-0 items-center gap-2 bg-background">
<div className="flex flex-1 items-center gap-2 px-3">
<SidebarTrigger />
<h1 className="text-xl font-bold sm:ml-2 text-nowrap">DWE OS</h1>
<Separator orientation="vertical" className="mx-2 h-4" />
<Breadcrumb>
<BreadcrumbList>
<BreadcrumbItem>
<BreadcrumbPage className="italic text-muted-foreground font-bold">
<BreadcrumbPage className="italic font-bold text-muted-foreground">
{pageTitle}
</BreadcrumbPage>
</BreadcrumbItem>
</BreadcrumbList>
</Breadcrumb>
<Separator orientation="vertical" className="mx-2 h-4" />
<ModeToggle />
<div className="ml-auto flex items-center">
<div className="flex items-center ml-auto">
<button
data-tour-id={TOUR_STEP_IDS.TOUR_PAGE_BTN}
onClick={() => startTour(true)}
className="text-sm text-muted-foreground hover:text-foreground p-2"
title="Page Tour"
>
<CircleHelpIcon className="w-5 h-5" />
</button>
<CommandPalette />
<SystemDropdown />
</div>
</div>
</header>
<div className="flex flex-1 flex-col gap-4 p-4 overflow-x-hidden">
<div className="flex flex-col flex-1 gap-4 p-4 overflow-x-hidden">
<FeaturesContext.Provider value={features}>
<Outlet />
</FeaturesContext.Provider>
</div>
</SidebarInset>
{features && <WelcomeTourManager features={features} />}
</SidebarProvider>
);
}
Expand Down Expand Up @@ -159,6 +156,7 @@ function App() {
<WebsocketContext.Provider value={{ socket: socket.current, connected }}>
<TourProvider>
<AppContent />
<TourDialog />
</TourProvider>
</WebsocketContext.Provider>
<Toaster richColors />
Expand Down
10 changes: 5 additions & 5 deletions frontend/src/components/dwe/app/command-palette.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { TOUR_STEP_IDS } from "@/components/tour/tour-constants";
import {
Command,
CommandDialog,
Expand All @@ -7,10 +8,9 @@ import {
CommandItem,
CommandList,
} from "@/components/ui/command";
import { TOUR_STEP_IDS } from "@/lib/tour-constants";
import { Info } from "lucide-react";
import { useState } from "react";
import { useNavigate } from "react-router-dom";
import { Info } from "lucide-react";

export function CommandPalette() {
const [open, setOpen] = useState(false);
Expand All @@ -22,7 +22,7 @@ export function CommandPalette() {
};

return (
<div id={TOUR_STEP_IDS.HELP_SWITCH}>
<div data-tour-id={TOUR_STEP_IDS.HELP_SWITCH}>
<button
onClick={() => setOpen(true)}
className="text-sm text-muted-foreground hover:text-foreground p-2"
Expand All @@ -40,8 +40,8 @@ export function CommandPalette() {
runCommand(() =>
window.open(
"https://docs.dwe.ai/software/dwe-os/guides/streaming",
"_blank"
)
"_blank",
),
)
}
>
Expand Down
41 changes: 26 additions & 15 deletions frontend/src/components/dwe/cameras/camera-controls.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,34 +4,41 @@ import { useMemo } from "react";

import {
Aperture,
MonitorCog,
ImageIcon,
CircleEllipsis,
Cog,
ImageIcon,
MonitorCog,
} from "lucide-react";

import IntegerControl from "./controls/integer-control";
import BooleanControl from "./controls/boolean-control";
import MenuControl from "./controls/menu-control";
import { components } from "@/schemas/dwe_os_2";
import CameraControlMap from "./cam-control-map.json";
import { TOUR_STEP_IDS } from "@/components/tour/tour-constants";
import {
Accordion,
AccordionContent,
AccordionItem,
AccordionTrigger,
} from "@/components/ui/accordion";
import { components } from "@/schemas/dwe_os_2";
import { useDeviceStore } from "@/store/devices";
import CameraControlMap from "./cam-control-map.json";
import BooleanControl from "./controls/boolean-control";
import IntegerControl from "./controls/integer-control";
import MenuControl from "./controls/menu-control";
import { translateControls, UIControlModel } from "./stream/sensor-controls";
import { TOUR_STEP_IDS } from "@/lib/tour-constants";

type ControlModel = components["schemas"]["ControlModel"];

const groupIcons: { [key: string]: React.ReactNode } = {
"Sensor Controls": <Cog className="h-4 w-4" />,
"Exposure Controls": <Aperture className="h-4 w-4" />,
"Image Controls": <ImageIcon className="h-4 w-4" />,
"Advanced Controls": <Cog className="h-4 w-4" />,
"System Controls": <MonitorCog className="h-4 w-4" />,
"Exposure Controls": <Aperture className="h-4 w-4" />,
"Image Processing": <ImageIcon className="h-4 w-4" />,
};

const groupIDs: { [key: string]: string } = {
"Advanced Controls": TOUR_STEP_IDS.ADVANCED_CONTROLS,
"System Controls": TOUR_STEP_IDS.SYSTEM_CONTROLS,
"Exposure Controls": TOUR_STEP_IDS.EXPOSURE_CONTROLS,
"Image Processing": TOUR_STEP_IDS.IMAGE_PROCESSING,
};

const ControlWrapper = ({
Expand Down Expand Up @@ -117,16 +124,20 @@ export const CameraControls = ({

return (
<div
className="grid gap-4 py-4 overflow-y-auto"
id={TOUR_STEP_IDS.DEVICE_SETTINGS}
className="grid gap-4overflow-y-auto"
data-tour-id={TOUR_STEP_IDS.DEVICE_SETTINGS}
>
<Accordion
type="single"
collapsible
defaultValue={visibleCategories[0][0]}
// defaultValue={visibleCategories[0][0]}
>
{visibleCategories.map(([category, controlNames]) => (
<AccordionItem value={category} key={category}>
<AccordionItem
value={category}
key={category}
data-tour-id={groupIDs[category]}
>
<AccordionTrigger>
<div className="flex items-center gap-2">
{groupIcons[category] ?? <CircleEllipsis className="h-4 w-4" />}
Expand Down
Loading