5
5
*/
6
6
7
7
import { PageSection } from "@patternfly/react-core" ;
8
- import { App } from "antd " ;
9
- import type React from "react " ;
8
+ import config from "config " ;
9
+ import { access } from "fs " ;
10
10
import { useEffect , useState } from "react" ;
11
11
import {
12
+ genUUID ,
12
13
getRoot ,
13
14
getRootID ,
15
+ getState ,
14
16
type ModuleToFunc ,
17
+ StateType ,
15
18
useReducer ,
16
19
} from "react-reducer-utils" ;
17
- import { useLonk } from "../../api/lonk/index.ts" ;
20
+ import { useLocation , useSearchParams } from "react-router-dom" ;
21
+ import type { Lonk , LonkMessageData } from "../../api/lonk/types.ts" ;
18
22
import type { PACSqueryCore } from "../../api/pfdcm/index.ts" ;
19
23
import * as DoPacs from "../../reducers/pacs" ;
20
24
import ErrorScreen from "./components/ErrorScreen.tsx" ;
21
25
import PacsLoadingScreen from "./components/PacsLoadingScreen.tsx" ;
22
- import { getSeriesDescription } from "./components/utils.ts" ;
23
26
import { DEFAULT_PREFERENCES } from "./defaultPreferences.ts" ;
24
27
import styles from "./PacsApp.module.css" ;
25
28
import PacsView from "./PacsView.tsx" ;
26
- import { type PacsState , SeriesPullState } from "./types.ts" ;
29
+ import { type PacsState , QUERY_PROMPT , SearchMode } from "./types.ts" ;
27
30
import { createFeedWithSeriesInstanceUID , errorCodeIsNot4xx } from "./utils.ts" ;
28
31
29
32
type TDoPacs = ModuleToFunc < typeof DoPacs > ;
@@ -76,22 +79,25 @@ export default () => {
76
79
// ========================================
77
80
// CLIENTS AND MISC
78
81
// ========================================
79
- const { message } = App . useApp ( ) ;
80
-
81
- const [ statePacs , doPacs ] = useReducer < DoPacs . State , TDoPacs > ( DoPacs ) ;
82
+ const [ statePacs , doPacs ] = useReducer < DoPacs . State , TDoPacs > (
83
+ DoPacs ,
84
+ StateType . LOCAL ,
85
+ ) ;
86
+ const [ searchParams , setSearchParams ] = useSearchParams ( ) ;
87
+ const location = useLocation ( ) ;
88
+ const [ pacsID , _ ] = useState ( genUUID ( ) ) ;
82
89
83
- const pacsID = getRootID ( statePacs ) ;
84
- const pacs = getRoot ( statePacs ) ?? DoPacs . defaultState ;
90
+ const pacs = getState ( statePacs , pacsID ) ?? DoPacs . defaultState ;
85
91
86
92
const {
87
93
expandedStudyUids,
88
94
expandedSeries,
89
95
studies,
90
96
services,
97
+ service,
91
98
isGetServices,
92
- seriesMap,
93
99
isLoadingStudies,
94
- wsUrl ,
100
+ isExpandedAllDone ,
95
101
} = pacs ;
96
102
97
103
// ========================================
@@ -101,7 +107,7 @@ export default () => {
101
107
/**
102
108
* Indicates a fatal error with the WebSocket.
103
109
*/
104
- const [ wsError , setWsError ] = useState < React . ReactNode | null > ( null ) ;
110
+ const [ wsError , setWsError ] = useState ( "" ) ;
105
111
// TODO create a settings component for changing preferences
106
112
const [ preferences , setPreferences ] = useState ( DEFAULT_PREFERENCES ) ;
107
113
@@ -115,78 +121,6 @@ export default () => {
115
121
const state : PacsState = { preferences, studies } ;
116
122
117
123
const error = wsError || pacs . errmsg ;
118
- // ========================================
119
- // LONK WEBSOCKET
120
- // ========================================
121
- const lonk = useLonk ( {
122
- url : wsUrl ,
123
- onDone : async ( pacs_name : string , SeriesInstanceUID : string ) => {
124
- doPacs . updateReceiveState ( pacsID , pacs_name , SeriesInstanceUID , {
125
- pullState : SeriesPullState . WAITING_OR_COMPLETE ,
126
- done : true ,
127
- } ) ;
128
- doPacs . queryCubeSeriesStateBySeriesUID (
129
- pacsID ,
130
- pacs_name ,
131
- SeriesInstanceUID ,
132
- ) ;
133
-
134
- await createFeedWithSeriesInstanceUID ( SeriesInstanceUID ) ;
135
-
136
- return ;
137
- } ,
138
- onProgress : (
139
- pacs_name : string ,
140
- SeriesInstanceUID : string ,
141
- ndicom : number ,
142
- ) => {
143
- doPacs . updateReceiveState (
144
- pacsID ,
145
- pacs_name ,
146
- SeriesInstanceUID ,
147
- { receivedCount : ndicom } ,
148
- ( theOrig : number , theNew : number ) => theOrig < theNew ,
149
- ) ;
150
- } ,
151
- onLonkError : (
152
- pacs_name : string ,
153
- SeriesInstanceUID : string ,
154
- error : string ,
155
- ) => {
156
- doPacs . pushReceiveStateError ( pacsID , pacs_name , SeriesInstanceUID , error ) ;
157
-
158
- const desc = getSeriesDescription (
159
- pacs_name ,
160
- SeriesInstanceUID ,
161
- seriesMap ,
162
- ) ;
163
- message . error (
164
- < > There was an error while receiving the series "{ desc } "</ > ,
165
- ) ;
166
- } ,
167
- onMessageError : ( data : any , error : string ) => {
168
- message . error (
169
- < >
170
- A < em > LONK</ em > error occurred, please check the console.
171
- </ > ,
172
- ) ;
173
- } ,
174
- heartbeat : false ,
175
- retryOnError : true ,
176
- reconnectAttempts : 3 ,
177
- reconnectInterval : 3000 ,
178
- shouldReconnect : errorCodeIsNot4xx ,
179
- onReconnectStop : ( ) => {
180
- console . error ( "PacsApp.lonk: onReconnectStop" ) ;
181
- setWsError ( < > The WebSocket is disconnected.</ > ) ;
182
- } ,
183
- onWebsocketError : ( ) => {
184
- console . error ( "PacsApp.lonk: onWebsocketError" ) ;
185
- message . error (
186
- < > There was an error with the WebSocket. Reconnecting…</ > ,
187
- ) ;
188
- } ,
189
- } ) ;
190
124
191
125
// ========================================
192
126
// CALLBACKS
@@ -216,35 +150,83 @@ export default () => {
216
150
// ========================================
217
151
218
152
// init
219
- // biome-ignore lint/correctness/useExhaustiveDependencies: doPacs.init
220
153
useEffect ( ( ) => {
154
+ doPacs . init ( pacsID ) ;
155
+
156
+ doPacs . updateServiceQueryBySearchParams ( pacsID , location , searchParams ) ;
157
+ } , [
158
+ pacsID ,
159
+ doPacs . init ,
160
+ doPacs . updateServiceQueryBySearchParams ,
161
+ location ,
162
+ searchParams ,
163
+ ] ) ;
164
+
165
+ useEffect ( ( ) => {
166
+ if ( ! pacsID ) {
167
+ return ;
168
+ }
169
+
170
+ if ( ! location . pathname . startsWith ( "/pacs" ) ) {
171
+ return ;
172
+ }
173
+
221
174
// set document title.
222
175
const originalTitle = document . title ;
223
176
document . title = "ChRIS PACS" ;
224
177
225
- // doPacs
226
- doPacs . init ( ) ;
178
+ doPacs . updateServiceQueryBySearchParams ( pacsID , location , searchParams ) ;
227
179
228
180
return ( ) => {
229
181
document . title = originalTitle ;
230
182
} ;
231
- } , [ ] ) ;
183
+ } , [
184
+ pacsID ,
185
+ location ,
186
+ location . pathname ,
187
+ searchParams ,
188
+ doPacs . updateServiceQueryBySearchParams ,
189
+ ] ) ;
232
190
233
191
// Subscribe to all expanded series
234
192
// biome-ignore lint/correctness/useExhaustiveDependencies: updateReceiveState
235
193
useEffect ( ( ) => {
236
- for ( const { pacs_name, SeriesInstanceUID } of expandedSeries ) {
237
- lonk
238
- . subscribe ( pacs_name , SeriesInstanceUID )
239
- . then ( ( { pacs_name, SeriesInstanceUID } ) => {
240
- doPacs . updateReceiveState ( pacsID , pacs_name , SeriesInstanceUID , {
241
- subscribed : true ,
242
- } ) ;
243
- } ) ;
194
+ if ( wsError ) {
195
+ return ;
244
196
}
197
+
198
+ if ( isExpandedAllDone ) {
199
+ return ;
200
+ }
201
+
202
+ if ( ! expandedSeries . length ) {
203
+ return ;
204
+ }
205
+
206
+ const series_uids = expandedSeries
207
+ . map ( ( each ) => each . SeriesInstanceUID )
208
+ . join ( "," ) ;
209
+
210
+ const url = `${ config . API_ROOT } /pacs/sse/?pacs_name=${ service } &series_uids=${ series_uids } ` ;
211
+ const eventSource = new EventSource ( url ) ;
212
+
213
+ eventSource . onmessage = ( event ) => {
214
+ const data : Lonk < LonkMessageData > = JSON . parse ( event . data ) ;
215
+ doPacs . processLonkMsg ( pacsID , data ) ;
216
+ } ;
217
+
218
+ eventSource . onerror = ( err ) => {
219
+ console . error ( "PacsApp.eventSource.onerror: err:" , err ) ;
220
+ setWsError ( `event error: ${ err } ` ) ;
221
+ } ;
222
+
223
+ return ( ) => {
224
+ console . info ( "PacsApp.eventSource: to return" ) ;
225
+ eventSource . close ( ) ;
226
+ } ;
245
227
// Note: we are subscribing to series, but never unsubscribing.
246
228
// This is mostly harmless.
247
- } , [ expandedSeries ] ) ;
229
+ } , [ expandedSeries , wsError , isExpandedAllDone ] ) ;
248
230
249
231
// ========================================
250
232
// RENDER
0 commit comments