@@ -15,7 +15,16 @@ import {
1515 AlertIcon ,
1616 AlertTitle ,
1717 AlertDescription ,
18+ Button ,
19+ useToast ,
1820} from '@chakra-ui/react' ;
21+ import { FaSync } from 'react-icons/fa' ;
22+
23+ interface MediaPathConfig {
24+ path : string ;
25+ original_path ?: string ;
26+ original_extension ?: string ;
27+ }
1928
2029interface SystemConfig {
2130 server : {
@@ -27,7 +36,7 @@ interface SystemConfig {
2736 max_connections : number ;
2837 } ;
2938 media : {
30- source_paths : string [ ] ;
39+ source_paths : MediaPathConfig [ ] ;
3140 export_base_path : string ;
3241 thumbnail_path : string ;
3342 } ;
@@ -37,6 +46,8 @@ const SystemInfoPage: React.FC = () => {
3746 const [ config , setConfig ] = useState < SystemConfig | null > ( null ) ;
3847 const [ loading , setLoading ] = useState < boolean > ( true ) ;
3948 const [ error , setError ] = useState < string | null > ( null ) ;
49+ const [ rescanLoading , setRescanLoading ] = useState < boolean > ( false ) ;
50+ const toast = useToast ( ) ;
4051
4152 useEffect ( ( ) => {
4253 const fetchSystemInfo = async ( ) => {
@@ -57,6 +68,39 @@ const SystemInfoPage: React.FC = () => {
5768 fetchSystemInfo ( ) ;
5869 } , [ ] ) ;
5970
71+ const handleRescan = async ( ) => {
72+ setRescanLoading ( true ) ;
73+ try {
74+ const response = await fetch ( '/api/scan' , {
75+ method : 'POST' ,
76+ } ) ;
77+
78+ if ( ! response . ok ) {
79+ throw new Error ( `Error rescanning library: ${ response . statusText } ` ) ;
80+ }
81+
82+ const data = await response . json ( ) ;
83+
84+ toast ( {
85+ title : 'Library Rescanned' ,
86+ description : `Successfully rescanned library. Found ${ data . new_videos_count } new videos.` ,
87+ status : 'success' ,
88+ duration : 5000 ,
89+ isClosable : true ,
90+ } ) ;
91+ } catch ( err ) {
92+ toast ( {
93+ title : 'Rescan Failed' ,
94+ description : err instanceof Error ? err . message : 'An unknown error occurred' ,
95+ status : 'error' ,
96+ duration : 5000 ,
97+ isClosable : true ,
98+ } ) ;
99+ } finally {
100+ setRescanLoading ( false ) ;
101+ }
102+ } ;
103+
60104 if ( loading ) {
61105 return (
62106 < Box textAlign = "center" py = { 10 } >
@@ -84,7 +128,7 @@ const SystemInfoPage: React.FC = () => {
84128 System Information
85129 </ Heading >
86130
87- < SimpleGrid columns = { { base : 1 , md : 2 , lg : 3 } } spacing = { 10 } >
131+ < SimpleGrid columns = { { base : 1 , md : 2 , lg : 3 } } spacing = { 10 } mb = { 8 } >
88132 { /* Server Configuration */ }
89133 < Card >
90134 < CardHeader >
@@ -134,9 +178,9 @@ const SystemInfoPage: React.FC = () => {
134178 < VStack align = "stretch" spacing = { 3 } >
135179 < Box >
136180 < Text fontWeight = "bold" mb = { 1 } > Source Paths:</ Text >
137- { config ?. media . source_paths . map ( ( path , index ) => (
138- < Text key = { index } fontSize = "sm" isTruncated title = { path } >
139- { path }
181+ { config ?. media . source_paths . map ( ( pathConfig , index ) => (
182+ < Text key = { index } fontSize = "sm" isTruncated title = { pathConfig . path } >
183+ { pathConfig . path }
140184 </ Text >
141185 ) ) }
142186 </ Box >
@@ -158,6 +202,22 @@ const SystemInfoPage: React.FC = () => {
158202 </ CardBody >
159203 </ Card >
160204 </ SimpleGrid >
205+
206+ < Box textAlign = "center" mt = { 6 } >
207+ < Button
208+ colorScheme = "blue"
209+ size = "lg"
210+ onClick = { handleRescan }
211+ isLoading = { rescanLoading }
212+ loadingText = "Rescanning..."
213+ leftIcon = { < FaSync /> }
214+ >
215+ Rescan Library
216+ </ Button >
217+ < Text mt = { 2 } fontSize = "sm" color = "gray.600" >
218+ Rescans existing library to capture any new metadata or fields that have been added
219+ </ Text >
220+ </ Box >
161221 </ Box >
162222 ) ;
163223} ;
0 commit comments