Skip to content

Commit afba64e

Browse files
committed
[grid] UI Overview is able to see live preview per Node
Signed-off-by: Viet Nguyen Duc <[email protected]>
1 parent 8eca1f9 commit afba64e

File tree

2 files changed

+134
-4
lines changed

2 files changed

+134
-4
lines changed

javascript/grid-ui/src/components/Node/Node.tsx

Lines changed: 121 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,92 @@
1515
// specific language governing permissions and limitations
1616
// under the License.
1717

18-
import { Box, Card, CardContent, Grid, Typography } from '@mui/material'
19-
import React from 'react'
18+
import { Box, Card, CardContent, Dialog, DialogActions, DialogContent, DialogTitle, Grid, IconButton, Typography, Button, keyframes, styled } from '@mui/material'
19+
import React, { useState, useRef } from 'react'
20+
import { Videocam as VideocamIcon } from '@mui/icons-material'
2021
import NodeDetailsDialog from './NodeDetailsDialog'
2122
import NodeLoad from './NodeLoad'
2223
import Stereotypes from './Stereotypes'
2324
import OsLogo from '../common/OsLogo'
25+
import LiveView from '../LiveView/LiveView'
26+
27+
const pulse = keyframes`
28+
0% {
29+
box-shadow: 0 0 0 0 rgba(25, 118, 210, 0.7);
30+
transform: scale(1);
31+
}
32+
50% {
33+
box-shadow: 0 0 0 5px rgba(25, 118, 210, 0);
34+
transform: scale(1.05);
35+
}
36+
100% {
37+
box-shadow: 0 0 0 0 rgba(25, 118, 210, 0);
38+
transform: scale(1);
39+
}
40+
`
41+
42+
const LiveIconButton = styled(IconButton)(({ theme }) => ({
43+
marginLeft: theme.spacing(1),
44+
position: 'relative',
45+
'&::after': {
46+
content: '""',
47+
position: 'absolute',
48+
width: '100%',
49+
height: '100%',
50+
borderRadius: '50%',
51+
animation: `${pulse} 2s infinite`,
52+
zIndex: 0
53+
}
54+
}))
55+
56+
function getVncUrl(session, origin) {
57+
try {
58+
const parsed = JSON.parse(session.capabilities)
59+
let vnc = parsed['se:vnc'] ?? ''
60+
if (vnc.length > 0) {
61+
try {
62+
const url = new URL(origin)
63+
const vncUrl = new URL(vnc)
64+
url.pathname = vncUrl.pathname
65+
url.protocol = url.protocol === 'https:' ? 'wss:' : 'ws:'
66+
return url.href
67+
} catch (error) {
68+
console.log(error)
69+
return ''
70+
}
71+
}
72+
return ''
73+
} catch (e) {
74+
return ''
75+
}
76+
}
2477

2578
function Node (props) {
26-
const { node } = props
79+
const { node, sessions = [], origin } = props
80+
const [liveViewSessionId, setLiveViewSessionId] = useState('')
81+
const liveViewRef = useRef<{ disconnect: () => void }>(null)
82+
83+
const vncSession = sessions.find(session => {
84+
try {
85+
const capabilities = JSON.parse(session.capabilities)
86+
return capabilities['se:vnc'] !== undefined && capabilities['se:vnc'] !== ''
87+
} catch (e) {
88+
return false
89+
}
90+
})
91+
92+
const handleLiveViewIconClick = () => {
93+
if (vncSession) {
94+
setLiveViewSessionId(vncSession.id)
95+
}
96+
}
97+
98+
const handleDialogClose = () => {
99+
if (liveViewRef.current) {
100+
liveViewRef.current.disconnect()
101+
}
102+
setLiveViewSessionId('')
103+
}
27104
const getCardStyle = (status: string) => ({
28105
height: '100%',
29106
flexGrow: 1,
@@ -32,6 +109,7 @@ function Node (props) {
32109
})
33110

34111
return (
112+
<>
35113
<Card sx={getCardStyle(node.status)}>
36114
<CardContent sx={{ pl: 2, pr: 1 }}>
37115
<Grid
@@ -62,14 +140,54 @@ function Node (props) {
62140
</Typography>
63141
</Grid>
64142
<Grid item xs={12}>
143+
<Box display="flex" alignItems="center">
65144
<Stereotypes stereotypes={node.slotStereotypes}/>
145+
{vncSession && (
146+
<LiveIconButton onClick={handleLiveViewIconClick} size='medium' color="primary">
147+
<VideocamIcon data-testid="VideocamIcon" />
148+
</LiveIconButton>
149+
)}
150+
</Box>
66151
</Grid>
67152
<Grid item xs={12}>
68153
<NodeLoad node={node}/>
69154
</Grid>
70155
</Grid>
71156
</CardContent>
72157
</Card>
158+
{vncSession && liveViewSessionId && (
159+
<Dialog
160+
onClose={handleDialogClose}
161+
aria-labelledby='live-view-dialog'
162+
open={liveViewSessionId === vncSession.id}
163+
fullWidth
164+
maxWidth='xl'
165+
fullScreen
166+
>
167+
<DialogTitle id='live-view-dialog'>
168+
<Typography gutterBottom component='span' sx={{ paddingX: '10px' }}>
169+
<Box fontWeight='fontWeightBold' mr={1} display='inline'>
170+
Node Session Live View
171+
</Box>
172+
{node.uri}
173+
</Typography>
174+
</DialogTitle>
175+
<DialogContent dividers sx={{ height: '600px' }}>
176+
<LiveView
177+
ref={liveViewRef as any}
178+
url={getVncUrl(vncSession, origin)}
179+
scaleViewport
180+
onClose={handleDialogClose}
181+
/>
182+
</DialogContent>
183+
<DialogActions>
184+
<Button onClick={handleDialogClose} color='primary' variant='contained'>
185+
Close
186+
</Button>
187+
</DialogActions>
188+
</Dialog>
189+
)}
190+
</>
73191
)
74192
}
75193

javascript/grid-ui/src/screens/Overview/Overview.tsx

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,12 +41,18 @@ import browserVersion from '../../util/browser-version'
4141
import Capabilities from '../../models/capabilities'
4242
import { GridConfig } from '../../config'
4343
import { NODES_QUERY } from '../../graphql/nodes'
44+
import { GRID_SESSIONS_QUERY } from '../../graphql/sessions'
4445

4546
function Overview (): JSX.Element {
4647
const { loading, error, data } = useQuery(NODES_QUERY, {
4748
pollInterval: GridConfig.status.xhrPollingIntervalMillis,
4849
fetchPolicy: 'network-only'
4950
})
51+
52+
const { data: sessionsData } = useQuery(GRID_SESSIONS_QUERY, {
53+
pollInterval: GridConfig.status.xhrPollingIntervalMillis,
54+
fetchPolicy: 'network-only'
55+
})
5056

5157
function compareSlotStereotypes(a: NodeInfo, b: NodeInfo, attribute: string): number {
5258
const joinA = a.slotStereotypes.length === 1
@@ -217,7 +223,13 @@ function Overview (): JSX.Element {
217223
flexDirection: 'column'
218224
}}
219225
>
220-
<Node node={node}/>
226+
<Node
227+
node={node}
228+
sessions={sessionsData?.sessionsInfo?.sessions?.filter(
229+
session => session.nodeId === node.id
230+
) || []}
231+
origin={window.location.origin}
232+
/>
221233
</Paper>
222234
</Grid>
223235
)

0 commit comments

Comments
 (0)