Skip to content

Commit 6e9d5e5

Browse files
authored
Merge pull request #31 from DiamondLightSource/open_new_tab_on_add_tab_action
Open new tab on add tab click action
2 parents 9b1619c + e048786 commit 6e9d5e5

File tree

11 files changed

+421
-231
lines changed

11 files changed

+421
-231
lines changed

package-lock.json

Lines changed: 10 additions & 10 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "daedalus",
33
"private": true,
4-
"version": "0.0.10",
4+
"version": "0.0.11",
55
"type": "module",
66
"scripts": {
77
"dev": "vite",
@@ -15,7 +15,7 @@
1515
"preview": "vite preview"
1616
},
1717
"dependencies": {
18-
"@diamondlightsource/cs-web-lib": "^0.9.9",
18+
"@diamondlightsource/cs-web-lib": "^0.9.10",
1919
"@emotion/react": "^11.11.4",
2020
"@emotion/styled": "^11.11.5",
2121
"@mui/icons-material": "^5.15.17",

src/components/ScreenTreeView.tsx

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { FileContext } from "@diamondlightsource/cs-web-lib";
55
import { BeamlineTreeStateContext } from "../App";
66
import { MenuContext } from "../routes/SynopticPage";
77
import { executeOpenPageActionWithFileGuid } from "../utils/csWebLibActions";
8+
import { FileIDs } from "../store";
89

910
export default function ScreenTreeView() {
1011
const { state } = useContext(BeamlineTreeStateContext);
@@ -33,6 +34,11 @@ export default function ScreenTreeView() {
3334
return currentBeamline?.screenTree ?? [];
3435
}, [state.currentBeamline, state.beamlines]);
3536

37+
const currentFileMetadata: FileIDs = useMemo(() => {
38+
const currentBeamline = state.beamlines[state.currentBeamline];
39+
return currentBeamline?.filePathIds ?? [];
40+
}, [state.currentBeamline, state.beamlines]);
41+
3642
// When beamline is updated, trigger refresh of expanded screens to fully expand all
3743
useEffect(() => {
3844
const getAllScreensWithChildrenItemIds = async (
@@ -65,8 +71,16 @@ export default function ScreenTreeView() {
6571
onExpandedItemsChange={(_event, itemIds) =>
6672
handleExpandedScreensChange(itemIds)
6773
}
68-
onItemClick={(_event, itemId) => handleClick(itemId)}
74+
onItemClick={(_event, itemId) => {
75+
if (!itemId || currentFileMetadata[itemId]?.exists === false) {
76+
return;
77+
}
78+
handleClick(itemId);
79+
}}
6980
expansionTrigger="iconContainer"
81+
isItemDisabled={item =>
82+
currentFileMetadata[item.id]?.exists === false
83+
}
7084
/>
7185
) : (
7286
<></>

src/routes/SynopticPage.tsx

Lines changed: 122 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -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";
1117
import DLSAppBar from "../components/AppBar";
1218
import ScreenDisplay from "../components/ScreenDisplay";
1319
import { 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";
1526
import { RotatingLines } from "react-loader-spinner";
1627
import { SynopticBreadcrumbs } from "../components/SynopticBreadcrumbs";
1728
import { 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

2238
export 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+
};

src/store.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,7 @@ export type FileMetadata = {
196196
file: string;
197197
urlId: string;
198198
macros?: Macros[];
199+
exists?: boolean;
199200
};
200201

201202
export type FileIDs = {

0 commit comments

Comments
 (0)