add tags filter to main page
This commit is contained in:
parent
f50bfa6cb6
commit
12b508661a
@ -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>
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -18,6 +18,8 @@ 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(() => {
|
||||||
@ -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({
|
||||||
|
|||||||
@ -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}
|
||||||
|
/>
|
||||||
|
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user