Skip to content

Commit

Permalink
[grid] UI Overview add sort by Platform, Status, ID in oder ASC|DESC (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
VietND96 authored Oct 7, 2024
1 parent a12b597 commit 64ed1e1
Show file tree
Hide file tree
Showing 2 changed files with 127 additions and 66 deletions.
35 changes: 17 additions & 18 deletions javascript/grid-ui/src/components/Node/Node.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,49 +24,48 @@ import OsLogo from '../common/OsLogo'

function Node (props) {
const { node } = props
const nodeStatusDown = node.status === 'DOWN'
const getCardStyle = (status: string) => ({
height: '100%',
flexGrow: 1,
opacity: status === 'DOWN' ? 0.25 : 1,
bgcolor: (status === 'DOWN' || status === 'DRAINING') ? 'grey.A100' : ''
})

return (
<Card
sx={{
height: '100%',
flexGrow: 1,
bgcolor: nodeStatusDown ? 'grey.A100' : ''
}}
>
<Card sx={getCardStyle(node.status)}>
<CardContent sx={{ pl: 2, pr: 1 }}>
<Grid
container
justifyContent='space-between'
justifyContent="space-between"
spacing={1}
>
<Grid item xs={10}>
<Typography
color='textPrimary'
color="textPrimary"
gutterBottom
variant='h6'
variant="h6"
>
<Box fontWeight='fontWeightBold' mr={1} display='inline'>
<Box fontWeight="fontWeightBold" mr={1} display="inline">
URI:
</Box>
{node.uri}
</Typography>
</Grid>
<Grid item xs={2}>
<Typography
color='textPrimary'
color="textPrimary"
gutterBottom
variant='h6'
variant="h6"
>
<OsLogo osName={node.osInfo.name} />
<NodeDetailsDialog node={node} />
<OsLogo osName={node.osInfo.name}/>
<NodeDetailsDialog node={node}/>
</Typography>
</Grid>
<Grid item xs={12}>
<Stereotypes stereotypes={node.slotStereotypes} />
<Stereotypes stereotypes={node.slotStereotypes}/>
</Grid>
<Grid item xs={12}>
<NodeLoad node={node} />
<NodeLoad node={node}/>
</Grid>
</Grid>
</CardContent>
Expand Down
158 changes: 110 additions & 48 deletions javascript/grid-ui/src/screens/Overview/Overview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,16 @@ import Grid from '@mui/material/Grid'
import Paper from '@mui/material/Paper'
import { loader } from 'graphql.macro'
import React from 'react'
import { useState, useEffect, useMemo } from 'react'
import {
Box,
Checkbox,
FormControl,
FormControlLabel,
InputLabel,
MenuItem,
Select
} from '@mui/material'
import Node from '../../components/Node/Node'
import { useQuery } from '@apollo/client'
import NodeInfo from '../../models/node-info'
Expand All @@ -30,85 +40,137 @@ import StereotypeInfo from '../../models/stereotype-info'
import browserVersion from '../../util/browser-version'
import Capabilities from '../../models/capabilities'
import { GridConfig } from '../../config'
import {NODES_QUERY} from "../../graphql/nodes";
import { NODES_QUERY } from '../../graphql/nodes'

function Overview (): JSX.Element {
const { loading, error, data } = useQuery(NODES_QUERY, {
pollInterval: GridConfig.status.xhrPollingIntervalMillis,
fetchPolicy: 'network-only'
})

const [sortOption, setSortOption] = useState('osInfo.name')
const [sortOrder, setSortOrder] = useState(1)
const [sortedNodes, setSortedNodes] = useState<NodeInfo[]>([])
const [isDescending, setIsDescending] = useState(false)

const handleSortChange = (event: React.ChangeEvent<{ value: unknown }>) => {
setSortOption(event.target.value as string)
}

const handleOrderChange = (event: React.ChangeEvent<HTMLInputElement>) => {
setIsDescending(event.target.checked)
setSortOrder(event.target.checked ? -1 : 1)
}

const sortProperties = {
'osInfo.name': (a, b) => a.osInfo.name.localeCompare(b.osInfo.name),
'status': (a, b) => a.status.localeCompare(b.status),
'id': (a, b) => (a.id < b.id ? -1 : 1)
}

const sortNodes = useMemo(() => {
return (nodes: NodeInfo[], option: string, order: number) => {
const sortFn = sortProperties[option] || (() => 0)
return nodes.sort((a, b) => order * sortFn(a, b))
}
}, [sortOption, sortOrder])

useEffect(() => {
if (data) {
const unSortedNodes = data.nodesInfo.nodes.map((node) => {
const osInfo: OsInfo = {
name: node.osInfo.name,
version: node.osInfo.version,
arch: node.osInfo.arch
}

interface StereoTypeData {
stereotype: Capabilities;
slots: number;
}

const slotStereotypes = (JSON.parse(
node.stereotypes) as StereoTypeData[]).map((item) => {
const slotStereotype: StereotypeInfo = {
browserName: item.stereotype.browserName ?? '',
browserVersion: browserVersion(
item.stereotype.browserVersion ?? item.stereotype.version),
platformName: (item.stereotype.platformName
?? item.stereotype.platform) ?? '',
slotCount: item.slots,
rawData: item
}
return slotStereotype
})

const newNode: NodeInfo = {
uri: node.uri,
id: node.id,
status: node.status,
maxSession: node.maxSession,
slotCount: node.slotCount,
version: node.version,
osInfo: osInfo,
sessionCount: node.sessionCount ?? 0,
slotStereotypes: slotStereotypes
}
return newNode
})

setSortedNodes(sortNodes(unSortedNodes, sortOption, sortOrder))
}
}, [data, sortOption, sortOrder])

if (error !== undefined) {
const message = 'There has been an error while loading the Nodes from the Grid.'
const errorMessage = error?.networkError?.message
return (
<Grid container spacing={3}>
<Error message={message} errorMessage={errorMessage} />
<Error message={message} errorMessage={errorMessage}/>
</Grid>
)
}

if (loading) {
return (
<Grid container spacing={3}>
<Loading />
<Loading/>
</Grid>
)
}

const unSortedNodes = data.nodesInfo.nodes.map((node) => {
const osInfo: OsInfo = {
name: node.osInfo.name,
version: node.osInfo.version,
arch: node.osInfo.arch
}

interface StereoTypeData {
stereotype: Capabilities
slots: number
}

const slotStereotypes = (JSON.parse(
node.stereotypes) as StereoTypeData[]).map((item) => {
const slotStereotype: StereotypeInfo = {
browserName: item.stereotype.browserName ?? '',
browserVersion: browserVersion(
item.stereotype.browserVersion ?? item.stereotype.version),
platformName: (item.stereotype.platformName ??
item.stereotype.platform) ?? '',
slotCount: item.slots,
rawData: item
}
return slotStereotype
})
const newNode: NodeInfo = {
uri: node.uri,
id: node.id,
status: node.status,
maxSession: node.maxSession,
slotCount: node.slotCount,
version: node.version,
osInfo: osInfo,
sessionCount: node.sessionCount ?? 0,
slotStereotypes: slotStereotypes
}
return newNode
})

const nodes = unSortedNodes.sort((a, b) => (a.id < b.id ? -1 : 1))
if (nodes.length === 0) {
if (sortedNodes.length === 0) {
const shortMessage = 'The Grid has no registered Nodes yet.'
return (
<Grid container spacing={3}>
<NoData message={shortMessage} />
<NoData message={shortMessage}/>
</Grid>
)
}

return (
<Grid container>
{/* Nodes */}
{nodes.map((node, index) => {
<Grid item xs={12}
style={{ display: 'flex', justifyContent: 'flex-start' }}>
<FormControl variant="outlined" style={{ marginBottom: '16px' }}>
<InputLabel>Sort By</InputLabel>
<Box display="flex" alignItems="center">
<Select value={sortOption} onChange={handleSortChange}
label="Sort By" style={{ minWidth: '150px' }}>
<MenuItem value="osInfo.name">Platform</MenuItem>
<MenuItem value="status">Status</MenuItem>
<MenuItem value="id">ID</MenuItem>
</Select>
<FormControlLabel
control={<Checkbox checked={isDescending}
onChange={handleOrderChange}/>}
label="Descending"
style={{ marginLeft: '8px' }}
/>
</Box>
</FormControl>
</Grid>
{sortedNodes.map((node, index) => {
return (
<Grid
item
Expand All @@ -127,7 +189,7 @@ function Overview (): JSX.Element {
flexDirection: 'column'
}}
>
<Node node={node} />
<Node node={node}/>
</Paper>
</Grid>
)
Expand Down

0 comments on commit 64ed1e1

Please sign in to comment.