Use MobilePage for camera group editor (#13710)

* Use MobilePage for camera group editor

* alignment

* clear editing group name
This commit is contained in:
Josh Hawkins 2024-09-12 16:06:56 -05:00 committed by GitHub
parent 644ea7be4a
commit 1f9ba1d625
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 114 additions and 51 deletions

View File

@ -7,8 +7,13 @@ import { Button } from "../ui/button";
import { useCallback, useMemo, useState } from "react";
import { Tooltip, TooltipContent, TooltipTrigger } from "../ui/tooltip";
import { LuPencil, LuPlus } from "react-icons/lu";
import { Dialog, DialogContent, DialogTitle } from "../ui/dialog";
import { Drawer, DrawerContent } from "../ui/drawer";
import {
Dialog,
DialogContent,
DialogDescription,
DialogHeader,
DialogTitle,
} from "../ui/dialog";
import { Input } from "../ui/input";
import { Separator } from "../ui/separator";
import {
@ -24,6 +29,7 @@ import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuPortal,
DropdownMenuTrigger,
} from "../ui/dropdown-menu";
import {
@ -53,6 +59,13 @@ import { cn } from "@/lib/utils";
import * as LuIcons from "react-icons/lu";
import IconPicker, { IconName, IconRenderer } from "../icons/IconPicker";
import { isValidIconName } from "@/utils/iconUtil";
import {
MobilePage,
MobilePageContent,
MobilePageDescription,
MobilePageHeader,
MobilePageTitle,
} from "../mobile/MobilePage";
type CameraGroupSelectorProps = {
className?: string;
@ -278,6 +291,7 @@ function NewGroupDialog({
const onSave = () => {
setOpen(false);
setEditState("none");
setEditingGroupName("");
};
const onCancel = () => {
@ -290,8 +304,11 @@ function NewGroupDialog({
setEditState("edit");
}, []);
const Overlay = isDesktop ? Dialog : Drawer;
const Content = isDesktop ? DialogContent : DrawerContent;
const Overlay = isDesktop ? Dialog : MobilePage;
const Content = isDesktop ? DialogContent : MobilePageContent;
const Header = isDesktop ? DialogHeader : MobilePageHeader;
const Description = isDesktop ? DialogDescription : MobilePageDescription;
const Title = isDesktop ? DialogTitle : MobilePageTitle;
return (
<>
@ -308,16 +325,36 @@ function NewGroupDialog({
}}
>
<Content
className={`min-w-0 ${isMobile ? "max-h-[90%] w-full rounded-t-2xl p-3" : "max-h-dvh w-6/12 overflow-y-hidden"}`}
className={cn(
"scrollbar-container overflow-y-auto",
isDesktop && "my-4 flex max-h-dvh w-6/12 flex-col",
isMobile && "px-4",
)}
>
<div className="scrollbar-container my-4 flex flex-col overflow-y-auto">
{editState === "none" && (
<>
<div className="flex flex-row items-center justify-between py-2">
<DialogTitle>Camera Groups</DialogTitle>
{editState === "none" && (
<>
<Header
className={cn(isDesktop && "mt-5", "justify-center")}
onClose={() => setOpen(false)}
>
<Title>Camera Groups</Title>
<Description className="sr-only">
Edit camera groups
</Description>
<div
className={cn(
"absolute",
isDesktop && "right-6 top-10",
isMobile && "absolute right-0 top-4",
)}
>
<Button
variant="secondary"
className="size-6 rounded-md bg-secondary-foreground p-1 text-background"
size="sm"
className={cn(
isDesktop &&
"size-6 rounded-md bg-secondary-foreground p-1 text-background",
isMobile && "text-secondary-foreground",
)}
onClick={() => {
setEditState("add");
}}
@ -325,6 +362,8 @@ function NewGroupDialog({
<LuPlus />
</Button>
</div>
</Header>
<div className="flex flex-col gap-4 md:gap-3">
{currentGroups.map((group) => (
<CameraGroupRow
key={group[0]}
@ -333,27 +372,36 @@ function NewGroupDialog({
onEditGroup={() => onEditGroup(group)}
/>
))}
</>
)}
</div>
</>
)}
{editState != "none" && (
<>
<div className="mb-3 flex flex-row items-center justify-between">
<DialogTitle>
{editState == "add" ? "Add" : "Edit"} Camera Group
</DialogTitle>
</div>
<CameraGroupEdit
currentGroups={currentGroups}
editingGroup={editingGroup}
isLoading={isLoading}
setIsLoading={setIsLoading}
onSave={onSave}
onCancel={onCancel}
/>
</>
)}
</div>
{editState != "none" && (
<>
<Header
className="mt-2"
onClose={() => {
setEditState("none");
setEditingGroupName("");
}}
>
<Title>
{editState == "add" ? "Add" : "Edit"} Camera Group
</Title>
<Description className="sr-only">
Edit camera groups
</Description>
</Header>
<CameraGroupEdit
currentGroups={currentGroups}
editingGroup={editingGroup}
isLoading={isLoading}
setIsLoading={setIsLoading}
onSave={onSave}
onCancel={onCancel}
/>
</>
)}
</Content>
</Overlay>
</>
@ -372,6 +420,12 @@ export function EditGroupDialog({
currentGroups,
activeGroup,
}: EditGroupDialogProps) {
const Overlay = isDesktop ? Dialog : MobilePage;
const Content = isDesktop ? DialogContent : MobilePageContent;
const Header = isDesktop ? DialogHeader : MobilePageHeader;
const Description = isDesktop ? DialogDescription : MobilePageDescription;
const Title = isDesktop ? DialogTitle : MobilePageTitle;
// editing group and state
const editingGroup = useMemo(() => {
@ -391,19 +445,24 @@ export function EditGroupDialog({
position="top-center"
closeButton={true}
/>
<Dialog
<Overlay
open={open}
onOpenChange={(open) => {
setOpen(open);
}}
>
<DialogContent
className={`min-w-0 ${isMobile ? "max-h-[90%] w-full rounded-t-2xl p-3" : "max-h-dvh w-6/12 overflow-y-hidden"}`}
<Content
className={cn(
"min-w-0",
isDesktop && "max-h-dvh w-6/12 overflow-y-hidden",
)}
>
<div className="scrollbar-container my-4 flex flex-col overflow-y-auto">
<div className="mb-3 flex flex-row items-center justify-between">
<DialogTitle>Edit Camera Group</DialogTitle>
</div>
<div className="scrollbar-container flex flex-col overflow-y-auto md:my-4">
<Header className="mt-2" onClose={() => setOpen(false)}>
<Title>Edit Camera Group</Title>
<Description className="sr-only">Edit camera group</Description>
</Header>
<CameraGroupEdit
currentGroups={currentGroups}
editingGroup={editingGroup}
@ -413,8 +472,8 @@ export function EditGroupDialog({
onCancel={() => setOpen(false)}
/>
</div>
</DialogContent>
</Dialog>
</Content>
</Overlay>
</>
);
}
@ -440,7 +499,7 @@ export function CameraGroupRow({
<>
<div
key={group[0]}
className="transition-background my-1.5 flex flex-row items-center justify-between rounded-lg duration-100 md:p-1"
className="transition-background flex flex-row items-center justify-between rounded-lg duration-100 md:p-1"
>
<div className={`flex items-center`}>
<p className="cursor-default">{group[0]}</p>
@ -472,12 +531,16 @@ export function CameraGroupRow({
<DropdownMenuTrigger>
<HiOutlineDotsVertical className="size-5" />
</DropdownMenuTrigger>
<DropdownMenuContent>
<DropdownMenuItem onClick={onEditGroup}>Edit</DropdownMenuItem>
<DropdownMenuItem onClick={() => setDeleteDialogOpen(true)}>
Delete
</DropdownMenuItem>
</DropdownMenuContent>
<DropdownMenuPortal>
<DropdownMenuContent>
<DropdownMenuItem onClick={onEditGroup}>
Edit
</DropdownMenuItem>
<DropdownMenuItem onClick={() => setDeleteDialogOpen(true)}>
Delete
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenuPortal>
</DropdownMenu>
</>
)}
@ -659,7 +722,7 @@ export function CameraGroupEdit({
/>
<Separator className="my-2 flex bg-secondary" />
<div className="scrollbar-container max-h-[25dvh] overflow-y-auto md:max-h-[40dvh]">
<div className="scrollbar-container max-h-[40dvh] overflow-y-auto">
<FormField
control={form.control}
name="cameras"

View File

@ -32,7 +32,7 @@ export function MobilePage({ children, open, onOpenChange }: MobilePageProps) {
{isVisible && (
<motion.div
className={cn(
"fixed inset-0 z-[100] mb-12 bg-background",
"fixed inset-0 z-50 mb-12 bg-background",
isPWA && "mb-16",
"landscape:mb-14 landscape:md:mb-16",
)}

View File

@ -641,7 +641,7 @@ function DetectionReview({
>
{filter?.before == undefined && (
<NewReviewData
className="pointer-events-none absolute left-1/2 z-50 -translate-x-1/2"
className="pointer-events-none absolute left-1/2 z-[49] -translate-x-1/2"
contentRef={contentRef}
reviewItems={currentItems}
itemsToReview={loading ? 0 : itemsToReview}