@@ -5,19 +5,35 @@ import {
55 useCallback ,
66 useContext ,
77 useEffect ,
8+ useMemo ,
89 useState
910} from "react" ;
10- import { CHANGE_BEAMLINE , CHANGE_SCREEN , LOAD_SCREENS } from "../store" ;
11+ import {
12+ BeamlineState ,
13+ CHANGE_BEAMLINE ,
14+ CHANGE_SCREEN ,
15+ LOAD_SCREENS
16+ } from "../store" ;
1117import DLSAppBar from "../components/AppBar" ;
1218import ScreenDisplay from "../components/ScreenDisplay" ;
1319import { parseScreenTree } from "../utils/parser" ;
14- import { FileContext } from "@diamondlightsource/cs-web-lib" ;
20+ import {
21+ buildUrl ,
22+ FileContext ,
23+ FileContextType ,
24+ FileDescription
25+ } from "@diamondlightsource/cs-web-lib" ;
1526import { RotatingLines } from "react-loader-spinner" ;
1627import { SynopticBreadcrumbs } from "../components/SynopticBreadcrumbs" ;
1728import { BeamlineTreeStateContext } from "../App" ;
18- import { useParams } from "react-router-dom" ;
19- import { buildUrl } from "../utils/urlUtils" ;
20- import { executeOpenPageActionWithUrlId } from "../utils/csWebLibActions" ;
29+ import { useParams , useSearchParams , useLocation } from "react-router-dom" ;
30+ import {
31+ executeOpenPageActionWithUrlId ,
32+ executeOpenPageAction
33+ } from "../utils/csWebLibActions" ;
34+
35+ const FILE_DESCRIPTION_SEARCH_PARAMETER_NAME = "file_description" ;
36+ const MACROS_SEARCH_PARAMETER_NAME = "macros" ;
2137
2238export const MenuContext = createContext < {
2339 menuOpen : boolean ;
@@ -28,7 +44,9 @@ export function SynopticPage() {
2844 const { state, dispatch } = useContext ( BeamlineTreeStateContext ) ;
2945 const params : { beamline ?: string ; screenUrlId ?: string } = useParams ( ) ;
3046 const fileContext = useContext ( FileContext ) ;
47+ const [ searchParams ] = useSearchParams ( ) ;
3148 const [ menuOpen , setMenuOpen ] = useState ( true ) ;
49+ const location = useLocation ( ) ;
3250
3351 useEffect ( ( ) => {
3452 // Only trigger once
@@ -81,27 +99,66 @@ export function SynopticPage() {
8199 // If we navigated directly to a beamline and/or screen, load in display
82100 const newBeamlineState = newBeamlines [ params . beamline ] ;
83101
84- executeOpenPageActionWithUrlId (
85- newBeamlineState ,
86- params . screenUrlId ,
87- params . beamline ,
88- fileContext
102+ const fileDescriptionParam = searchParams . get (
103+ FILE_DESCRIPTION_SEARCH_PARAMETER_NAME
89104 ) ;
105+ if ( fileDescriptionParam ) {
106+ // handle case where we have no JsonMap entry, which will contain a full screen file definition
107+ const fileDescription = JSON . parse (
108+ fileDescriptionParam
109+ ) as FileDescription ;
110+ executeOpenPageAction (
111+ fileDescription . path ,
112+ fileDescription . macros ,
113+ fileDescription . defaultProtocol ,
114+ fileContext ,
115+ location . pathname
116+ ) ;
117+ } else {
118+ const macrosParameter = searchParams . get ( MACROS_SEARCH_PARAMETER_NAME ) ;
119+ const macrosMap = macrosParameter
120+ ? JSON . parse ( macrosParameter )
121+ : undefined ;
122+ executeOpenPageActionWithUrlId (
123+ newBeamlineState ,
124+ params . screenUrlId ,
125+ params . beamline ,
126+ fileContext ,
127+ macrosMap
128+ ) ;
129+ }
90130 }
91131 } , [ ] ) ;
92132
133+ // override the default addTab method used by the cs-web-lib open tab actions
134+ const addTab = useCallback (
135+ addTabCallbackAction (
136+ state . beamlines ,
137+ state . currentBeamline ,
138+ window . location
139+ ) ,
140+ [ state . beamlines , state . currentBeamline , window . location ]
141+ ) ;
142+
143+ const updatedFileContext = useMemo (
144+ ( ) => ( { ...fileContext , addTab } ) ,
145+ [ fileContext , addTab ]
146+ ) ;
147+
93148 return (
94149 < >
95150 < Box sx = { { display : "flex" } } >
96151 { state . filesLoaded ? (
97152 < >
98- < MenuContext . Provider value = { { menuOpen, setMenuOpen } } >
99- < DLSAppBar fullScreen = { false } open = { menuOpen } >
100- < SynopticBreadcrumbs />
101- </ DLSAppBar >
102- < MiniMenuBar />
103- < ScreenDisplay />
104- </ MenuContext . Provider >
153+ < FileContext . Provider value = { updatedFileContext } >
154+ < MenuContext . Provider value = { { menuOpen, setMenuOpen } } >
155+ < DLSAppBar fullScreen = { false } open = { menuOpen } >
156+ < SynopticBreadcrumbs />
157+ </ DLSAppBar >
158+ < MiniMenuBar />
159+ < ScreenDisplay />
160+ </ MenuContext . Provider >
161+ </ FileContext . Provider >
105162 </ >
106163 ) : (
107164 < >
@@ -118,3 +175,51 @@ export function SynopticPage() {
118175 </ >
119176 ) ;
120177}
178+
179+ export const addTabCallbackAction =
180+ (
181+ beamlines : BeamlineState ,
182+ currentBeamline : string ,
183+ windowLocation : Location
184+ ) : FileContextType [ "addTab" ] =>
185+ ( fileLocation : string , tabName : string , fileDesc : FileDescription ) => {
186+ void fileLocation ; // unused, but required by the function interface.
187+ void tabName ; // unused, but required by the function interface.
188+
189+ // try and find a matching file entry in the JSON map
190+ const displayedPath = fileDesc ?. path ?. replace (
191+ beamlines [ currentBeamline ] . host ! ,
192+ ""
193+ ) ;
194+
195+ const allFiles = beamlines [ currentBeamline ] . filePathIds ;
196+ const currentFile = Object . values ( allFiles ) . find (
197+ values => values . file === displayedPath
198+ ) ;
199+
200+ // Build the URL for the new tab
201+ let newURL = new URL ( windowLocation . origin ) ;
202+ if ( currentFile ?. urlId ) {
203+ // we have a file mapping
204+ newURL . pathname = buildUrl (
205+ "" ,
206+ "synoptic" ,
207+ currentBeamline ,
208+ currentFile ?. urlId
209+ ) ;
210+ if ( fileDesc ?. macros ) {
211+ newURL . searchParams . append (
212+ MACROS_SEARCH_PARAMETER_NAME ,
213+ JSON . stringify ( fileDesc ?. macros )
214+ ) ;
215+ }
216+ } else {
217+ // No file mapping
218+ newURL = new URL ( windowLocation . href ) ;
219+ newURL . searchParams . append (
220+ FILE_DESCRIPTION_SEARCH_PARAMETER_NAME ,
221+ JSON . stringify ( fileDesc )
222+ ) ;
223+ }
224+ window . open ( newURL , "_blank" ) ;
225+ } ;
0 commit comments