add tags filter to main page

This commit is contained in:
NlightN22 2024-09-30 16:05:38 +07:00
parent f50bfa6cb6
commit 12b508661a
5 changed files with 51 additions and 16 deletions

View File

@ -15,14 +15,16 @@ import { SideBarContext } from '../widgets/sidebars/SideBarContext';
import RetryErrorPage from './RetryErrorPage'; import RetryErrorPage from './RetryErrorPage';
import { IconSearch } from '@tabler/icons-react'; import { IconSearch } from '@tabler/icons-react';
import ClearableTextInput from '../shared/components/inputs/ClearableTextInput'; import ClearableTextInput from '../shared/components/inputs/ClearableTextInput';
import { CameraTag } from '../types/tags';
const MainPage = () => { const MainPage = () => {
const { t } = useTranslation() const { t } = useTranslation()
const { mainStore } = useContext(Context) const { mainStore } = useContext(Context)
const { setChildrenComponent } = useContext(SideBarContext) const { setChildrenComponent } = useContext(SideBarContext)
const { selectedHostId } = mainStore const { selectedHostId, selectedTags } = mainStore
const [searchQuery, setSearchQuery] = useState<string>() const [searchQuery, setSearchQuery] = useState<string>()
const [filteredCameras, setFilteredCameras] = useState<GetCameraWHostWConfig[]>() const [filteredCameras, setFilteredCameras] = useState<GetCameraWHostWConfig[]>()
const [filteredTags, setFilteredTags] = useState<CameraTag[]>()
const realmUser = useRealmUser() const realmUser = useRealmUser()
if (!isProduction) console.log('Realmuser:', realmUser) if (!isProduction) console.log('Realmuser:', realmUser)
@ -46,11 +48,12 @@ const MainPage = () => {
const filterCameras = (camera: GetCameraWHostWConfig) => { const filterCameras = (camera: GetCameraWHostWConfig) => {
const matchesHostId = selectedHostId ? camera.frigateHost?.id === selectedHostId : true const matchesHostId = selectedHostId ? camera.frigateHost?.id === selectedHostId : true
const matchesSearchQuery = searchQuery ? camera.name.toLowerCase().includes(searchQuery.toLowerCase()) : true const matchesSearchQuery = searchQuery ? camera.name.toLowerCase().includes(searchQuery.toLowerCase()) : true
return matchesHostId && matchesSearchQuery const matchesTags = selectedTags.length === 0 || camera.tags.some( tag => selectedTags.includes(tag.id))
return matchesHostId && matchesSearchQuery && matchesTags
} }
setFilteredCameras(cameras.filter(filterCameras)) setFilteredCameras(cameras.filter(filterCameras))
}, [searchQuery, cameras, selectedHostId]) }, [searchQuery, cameras, selectedHostId, selectedTags])
const cards = useMemo(() => { const cards = useMemo(() => {
@ -100,8 +103,7 @@ const MainPage = () => {
</Flex> </Flex>
<Flex justify='center' h='100%' direction='column' w='100%' > <Flex justify='center' h='100%' direction='column' w='100%' >
<Grid mt='sm' justify="center" mb='sm' align='stretch'> <Grid mt='sm' justify="center" mb='sm' align='stretch'>
{/* TODO DELETE SLICE TO WORK */} {cards}
{cards.slice(0, 5)}
</Grid> </Grid>
</Flex> </Flex>
</Flex> </Flex>

View File

@ -1,6 +1,6 @@
import { SelectItem } from '@mantine/core'; import { SelectItem } from '@mantine/core';
import { t } from 'i18next'; import { t } from 'i18next';
import { useState } from 'react'; import { useEffect, useState } from 'react';
import { z } from 'zod'; import { z } from 'zod';
import CreatableMultiSelect from './CreatableMultiSelect'; import CreatableMultiSelect from './CreatableMultiSelect';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
@ -13,13 +13,23 @@ import { notifications } from '@mantine/notifications';
import { IconAlertCircle } from '@tabler/icons-react'; import { IconAlertCircle } from '@tabler/icons-react';
interface UserTagsFilterProps {
onChange?(tagIds: string[]): void
}
const UserTagsFilter = () => {
const UserTagsFilter: React.FC<UserTagsFilterProps> = ({
onChange
}) => {
const { t } = useTranslation() const { t } = useTranslation()
const queryClient = useQueryClient() const queryClient = useQueryClient()
const [selectedList, setSelectedList] = useState<string[]>([]) const [selectedList, setSelectedList] = useState<string[]>([])
useEffect(() => {
if (onChange) onChange(selectedList)
}, [selectedList])
const { data, isPending, isError, refetch } = useQuery({ const { data, isPending, isError, refetch } = useQuery({
queryKey: [frigateQueryKeys.getUserTags], queryKey: [frigateQueryKeys.getUserTags],
queryFn: frigateApi.getUserTags queryFn: frigateApi.getUserTags

View File

@ -1,4 +1,5 @@
import { makeAutoObservable } from "mobx"; import { makeAutoObservable } from "mobx";
import { CameraTag } from "../../types/tags";
export class MainStore { export class MainStore {
@ -10,6 +11,15 @@ export class MainStore {
this._selectedHostId = value; this._selectedHostId = value;
} }
private _selectedTags: string[] = [];
public get selectedTags(): string[] {
return this._selectedTags;
}
public set selectedTags(value: string[]) {
this._selectedTags = value;
}
constructor() { constructor() {
makeAutoObservable(this) makeAutoObservable(this)
} }

View File

@ -18,11 +18,13 @@ const CameraTagsList: React.FC<CameraTagsListProps> = ({
camera camera
}) => { }) => {
const queryClient = useQueryClient()
const [tagsList, setTagsList] = useState<CameraTag[]>(camera.tags) const [tagsList, setTagsList] = useState<CameraTag[]>(camera.tags)
useEffect(()=>{ useEffect(() => {
setTagsList(camera.tags) setTagsList(camera.tags)
},[camera]) }, [camera])
const { mutate: addTagToCamera } = useMutation({ const { mutate: addTagToCamera } = useMutation({
@ -35,6 +37,7 @@ const CameraTagsList: React.FC<CameraTagsListProps> = ({
}), }),
onSuccess: (data) => { onSuccess: (data) => {
setTagsList(data.tags) setTagsList(data.tags)
queryClient.invalidateQueries({ queryKey: [frigateQueryKeys.getCamerasWHost] })
}, },
onError: (e) => { onError: (e) => {
if (e && e.message) { if (e && e.message) {
@ -51,7 +54,6 @@ const CameraTagsList: React.FC<CameraTagsListProps> = ({
} }
}) })
const { mutate: deleteTagFromCamera } = useMutation({ const { mutate: deleteTagFromCamera } = useMutation({
mutationFn: (tagId: string) => frigateApi.deleteTagFromCamera(camera.id, tagId) mutationFn: (tagId: string) => frigateApi.deleteTagFromCamera(camera.id, tagId)
.catch(error => { .catch(error => {
@ -60,7 +62,11 @@ const CameraTagsList: React.FC<CameraTagsListProps> = ({
} }
return Promise.reject(error) return Promise.reject(error)
}), }),
onSuccess: (data) => setTagsList(data.tags), onSuccess: (data) => {
setTagsList(data.tags)
queryClient.invalidateQueries({ queryKey: [frigateQueryKeys.getCamerasWHost] })
}
,
onError: (e) => { onError: (e) => {
if (e && e.message) { if (e && e.message) {
notifications.show({ notifications.show({
@ -95,7 +101,7 @@ const CameraTagsList: React.FC<CameraTagsListProps> = ({
onClose={handleDeleteTagClick} onClose={handleDeleteTagClick}
/> />
)) ))
: <></> : <></>
} }
<AddBadge <AddBadge
onClick={handleAddTagClick} onClick={handleAddTagClick}

View File

@ -16,21 +16,28 @@ const MainFiltersRightSide = () => {
const { mainStore } = useContext(Context) const { mainStore } = useContext(Context)
const { selectedHostId } = mainStore const { selectedHostId } = mainStore
const handleSelect = (value: string) => { const handleSelectHost = (value: string) => {
if (!isProduction) console.log('handleSelect value', value) if (!isProduction) console.log('handleSelectHost value', value)
mainStore.selectedHostId = value mainStore.selectedHostId = value
} }
const handleSelectTags = (tags: string[]) => {
if (!isProduction) console.log('handleSelectTags value', tags)
mainStore.selectedTags = tags
}
return ( return (
<> <>
<HostSelect <HostSelect
label={t('selectHost')} label={t('selectHost')}
valueId={selectedHostId} valueId={selectedHostId}
defaultId={selectedHostId} defaultId={selectedHostId}
onChange={handleSelect} onChange={handleSelectHost}
/> />
<UserTagsFilter /> <UserTagsFilter
onChange={handleSelectTags}
/>
</> </>
); );