@@ -19,6 +19,12 @@ function getContainerName(hostname: string): string {
1919 // Match the docker naming scheme for deployment containers
2020 return `specify7-test-panel-${ hostname } -1` ;
2121}
22+
23+ function getWorkerContainerName ( hostname : string ) : string {
24+ // Match the docker naming scheme for worker containers
25+ return `specify7-test-panel-${ hostname } -worker-1` ;
26+ }
27+
2228export function DeploymentOptions ( {
2329 deployment,
2430 schemaVersions,
@@ -48,25 +54,33 @@ export function DeploymentOptions({
4854
4955 const [ listUsers , setListUsers ] = React . useState ( false ) ;
5056 const [ showLogs , setShowLogs ] = React . useState ( false ) ;
57+ const [ showWorkerLogs , setShowWorkerLogs ] = React . useState ( false ) ;
5158 const [ downloading , setDownloading ] = React . useState ( false ) ;
59+ const [ downloadingWorker , setDownloadingWorker ] = React . useState ( false ) ;
5260
53- const handleDownloadLogs = async ( ) => {
61+ const handleDownloadLogs = async ( containerType : 'main' | 'worker' = 'main' ) => {
5462 if ( ! deployment . hostname ) return ;
5563
56- setDownloading ( true ) ;
64+ const isWorker = containerType === 'worker' ;
65+ const setDownloadingState = isWorker ? setDownloadingWorker : setDownloading ;
66+
67+ setDownloadingState ( true ) ;
5768 try {
58- const containerName = getContainerName ( deployment . hostname ) ;
69+ const containerName = isWorker
70+ ? getWorkerContainerName ( deployment . hostname )
71+ : getContainerName ( deployment . hostname ) ;
72+
5973 const response = await fetch ( `/api/logs/${ encodeURIComponent ( containerName ) } ` ) ;
60- if ( ! response . ok ) throw new Error ( ' Failed to fetch logs for download' ) ;
74+ if ( ! response . ok ) throw new Error ( ` Failed to fetch ${ isWorker ? 'worker ' : '' } logs for download` ) ;
6175
6276 const logsText = await response . text ( ) ;
6377
6478 if ( ! logsText || logsText . trim ( ) === '' ) {
65- alert ( ' No logs available for this container' ) ;
79+ alert ( ` No ${ isWorker ? 'worker ' : '' } logs available for this container` ) ;
6680 return ;
6781 }
6882
69- const timestamp = new Date ( ) . toISOString ( ) . replace ( / [: . ] / g, '-' ) ;
83+ const timestamp = new Date ( ) . toISOString ( ) . slice ( 0 , 16 ) . replace ( / [ T : ] / g, '-' ) ;
7084 const filename = `${ containerName } -logs-${ timestamp } .txt` ;
7185
7286 const blob = new Blob ( [ logsText ] , { type : 'text/plain' } ) ;
@@ -80,10 +94,10 @@ export function DeploymentOptions({
8094 document . body . removeChild ( link ) ;
8195 URL . revokeObjectURL ( url ) ;
8296 } catch ( error ) {
83- console . error ( ' Failed to download logs:' , error ) ;
84- alert ( ' Failed to download logs. Please try again.' ) ;
97+ console . error ( ` Failed to download ${ isWorker ? 'worker ' : '' } logs:` , error ) ;
98+ alert ( ` Failed to download ${ isWorker ? 'worker ' : '' } logs. Please try again.` ) ;
8599 } finally {
86- setDownloading ( false ) ;
100+ setDownloadingState ( false ) ;
87101 }
88102 } ;
89103
@@ -109,7 +123,7 @@ export function DeploymentOptions({
109123 buttons = {
110124 < >
111125 < button
112- onClick = { handleDownloadLogs }
126+ onClick = { ( ) => handleDownloadLogs ( 'main' ) }
113127 disabled = { downloading }
114128 className = { infoButtonClassName }
115129 >
@@ -131,6 +145,38 @@ export function DeploymentOptions({
131145 < ContainerLogs deployment = { deployment } />
132146 </ ModalDialog >
133147 ) }
148+ { showWorkerLogs && (
149+ < ModalDialog
150+ title = "Worker Container Logs"
151+ onClose = { ( ) : void => setShowWorkerLogs ( false ) }
152+ buttons = {
153+ < >
154+ < button
155+ onClick = { ( ) => handleDownloadLogs ( 'worker' ) }
156+ disabled = { downloadingWorker }
157+ className = { infoButtonClassName }
158+ >
159+ { icons . download }
160+ < span className = "ml-2" >
161+ { downloadingWorker ? 'Downloading...' : 'Download Worker Logs' }
162+ </ span >
163+ </ button >
164+ < button
165+ className = { infoButtonClassName }
166+ type = "button"
167+ onClick = { ( ) : void => setShowWorkerLogs ( false ) }
168+ >
169+ Close
170+ </ button >
171+ </ >
172+ }
173+ >
174+ < ContainerLogs
175+ deployment = { deployment }
176+ containerName = { deployment . hostname ? getWorkerContainerName ( deployment . hostname ) : undefined }
177+ />
178+ </ ModalDialog >
179+ ) }
134180 < ModalDialog
135181 buttons = {
136182 < >
@@ -157,6 +203,13 @@ export function DeploymentOptions({
157203 >
158204 { localization . viewLogs ?? "View Logs" }
159205 </ button >
206+ < button
207+ className = { infoButtonClassName }
208+ type = "button"
209+ onClick = { ( ) : void => setShowWorkerLogs ( true ) }
210+ >
211+ View Worker Logs
212+ </ button >
160213 < button
161214 className = { infoButtonClassName }
162215 type = "button"
0 commit comments