From 64ed1e108a0bb3df5f09a59d97199402b1faf7b4 Mon Sep 17 00:00:00 2001 From: Viet Nguyen Duc Date: Mon, 7 Oct 2024 15:15:28 +0000 Subject: [PATCH] [grid] UI Overview add sort by Platform, Status, ID in oder ASC|DESC (#14571) --- .../grid-ui/src/components/Node/Node.tsx | 35 ++-- .../grid-ui/src/screens/Overview/Overview.tsx | 158 ++++++++++++------ 2 files changed, 127 insertions(+), 66 deletions(-) diff --git a/javascript/grid-ui/src/components/Node/Node.tsx b/javascript/grid-ui/src/components/Node/Node.tsx index f61b2ec550288..79b2ced05f2a9 100644 --- a/javascript/grid-ui/src/components/Node/Node.tsx +++ b/javascript/grid-ui/src/components/Node/Node.tsx @@ -24,29 +24,28 @@ 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 ( - + - + URI: {node.uri} @@ -54,19 +53,19 @@ function Node (props) { - - + + - + - + diff --git a/javascript/grid-ui/src/screens/Overview/Overview.tsx b/javascript/grid-ui/src/screens/Overview/Overview.tsx index c51b10140305a..4ff654adad294 100644 --- a/javascript/grid-ui/src/screens/Overview/Overview.tsx +++ b/javascript/grid-ui/src/screens/Overview/Overview.tsx @@ -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' @@ -30,7 +40,7 @@ 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, { @@ -38,12 +48,85 @@ function Overview (): JSX.Element { fetchPolicy: 'network-only' }) + const [sortOption, setSortOption] = useState('osInfo.name') + const [sortOrder, setSortOrder] = useState(1) + const [sortedNodes, setSortedNodes] = useState([]) + const [isDescending, setIsDescending] = useState(false) + + const handleSortChange = (event: React.ChangeEvent<{ value: unknown }>) => { + setSortOption(event.target.value as string) + } + + const handleOrderChange = (event: React.ChangeEvent) => { + 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 ( - + ) } @@ -51,64 +134,43 @@ function Overview (): JSX.Element { if (loading) { return ( - + ) } - 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 ( - + ) } return ( - {/* Nodes */} - {nodes.map((node, index) => { + + + Sort By + + + } + label="Descending" + style={{ marginLeft: '8px' }} + /> + + + + {sortedNodes.map((node, index) => { return ( - + )