import { baseUrl } from "@/api/baseUrl"; import ClassificationModelWizardDialog from "@/components/classification/ClassificationModelWizardDialog"; import ActivityIndicator from "@/components/indicators/activity-indicator"; import { ImageShadowOverlay } from "@/components/overlay/ImageShadowOverlay"; import { Button } from "@/components/ui/button"; import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group"; import useOptimisticState from "@/hooks/use-optimistic-state"; import { cn } from "@/lib/utils"; import { CustomClassificationModelConfig, FrigateConfig, } from "@/types/frigateConfig"; import { useEffect, useMemo, useState } from "react"; import { useTranslation } from "react-i18next"; import { FaFolderPlus } from "react-icons/fa"; import { MdModelTraining } from "react-icons/md"; import useSWR from "swr"; import Heading from "@/components/ui/heading"; import { useOverlayState } from "@/hooks/use-overlay-state"; const allModelTypes = ["objects", "states"] as const; type ModelType = (typeof allModelTypes)[number]; type ModelSelectionViewProps = { onClick: (model: CustomClassificationModelConfig) => void; }; export default function ModelSelectionView({ onClick, }: ModelSelectionViewProps) { const { t } = useTranslation(["views/classificationModel"]); const [page, setPage] = useOverlayState("objects", "objects"); const [pageToggle, setPageToggle] = useOptimisticState( page || "objects", setPage, 100, ); const { data: config, mutate: refreshConfig } = useSWR( "config", { revalidateOnFocus: false, }, ); // title useEffect(() => { document.title = t("documentTitle"); }, [t]); // data const classificationConfigs = useMemo(() => { if (!config) { return []; } return Object.values(config.classification.custom); }, [config]); const selectedClassificationConfigs = useMemo(() => { return classificationConfigs.filter((model) => { if (pageToggle == "objects" && model.object_config != undefined) { return true; } if (pageToggle == "states" && model.state_config != undefined) { return true; } return false; }); }, [classificationConfigs, pageToggle]); // new model wizard const [newModel, setNewModel] = useState(false); if (!config) { return ; } return (
{ setNewModel(false); refreshConfig(); }} />
{ if (value) { setPageToggle(value); } }} > {allModelTypes.map((item) => (
{t("menu." + item)}
))}
{selectedClassificationConfigs.length === 0 ? ( setNewModel(true)} modelType={pageToggle} /> ) : ( selectedClassificationConfigs.map((config) => ( onClick(config)} /> )) )}
); } function NoModelsView({ onCreateModel, modelType, }: { onCreateModel: () => void; modelType: ModelType; }) { const { t } = useTranslation(["views/classificationModel"]); const typeKey = modelType === "objects" ? "object" : "state"; return (
{t(`noModels.${typeKey}.title`)}
{t(`noModels.${typeKey}.description`)}
); } type ModelCardProps = { config: CustomClassificationModelConfig; onClick: () => void; }; function ModelCard({ config, onClick }: ModelCardProps) { const { data: dataset } = useSWR<{ [id: string]: string[]; }>(`classification/${config.name}/dataset`, { revalidateOnFocus: false }); const coverImage = useMemo(() => { if (!dataset) { return undefined; } const keys = Object.keys(dataset).filter((key) => key != "none"); const selectedKey = keys[0]; if (!dataset[selectedKey]) { return undefined; } return { name: selectedKey, img: dataset[selectedKey][0], }; }, [dataset]); return (
onClick()} >
{config.name}
); }