Skip to content

Commit

Permalink
Merge pull request #154
Browse files Browse the repository at this point in the history
fix(123): fix status rendering on links in workspace

* refactor(123): refactor status rendering utility

* refactor(123): refactor the color selection based on connection and r…

* test(123): add tests for status rendering in workspace

* fix(123): fix handling of runtime status

* chore(123): update dependencies
  • Loading branch information
vanch3d authored Oct 12, 2023
1 parent cca5718 commit 8c1d7e7
Show file tree
Hide file tree
Showing 6 changed files with 76 additions and 12 deletions.
1 change: 1 addition & 0 deletions hivemq-edge/src/frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
"@types/d3-hierarchy": "^3.1.3",
"axios": "^1.4.0",
"chakra-react-select": "^4.7.2",
"csstype": "^3.1.2",
"d3-array": "^3.2.4",
"d3-hierarchy": "^3.1.2",
"form-data": "^4.0.0",
Expand Down
3 changes: 3 additions & 0 deletions hivemq-edge/src/frontend/pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ export const MOCK_THEME: Partial<WithCSSVar<Dict>> = {
error: {
500: '#E53E3E',
},
stateless: {
500: '#38A169',
},
},
},
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { Adapter, Bridge, Status, Listener, ProtocolAdapter } from '@/api/__gene

import { EdgeTypes, IdStubs, NodeTypes } from '../types.ts'
import { getBridgeTopics, discoverAdapterTopics } from '../utils/topics-utils.ts'
import { getThemeForStatus } from '@/modules/EdgeVisualisation/utils/status-utils.ts'

export const CONFIG_ADAPTER_WIDTH = 245

Expand Down Expand Up @@ -34,7 +35,10 @@ export const createBridgeNode = (
positionStorage?: Record<string, XYPosition>
) => {
const idBridge = `${IdStubs.BRIDGE_NODE}@${bridge.id}`
const isConnected = bridge.status?.connection === Status.connection.CONNECTED
const isConnected =
bridge.status?.connection === Status.connection.CONNECTED ||
(bridge.status?.runtime === Status.runtime.STARTED && bridge.status?.connection === Status.connection.STATELESS)

const { local, remote } = getBridgeTopics(bridge)

const nodeBridge: Node<Bridge, NodeTypes.BRIDGE_NODE> = {
Expand All @@ -58,12 +62,12 @@ export const createBridgeNode = (
type: MarkerType.ArrowClosed,
width: 20,
height: 20,
color: isConnected ? theme.colors.status.connected[500] : theme.colors.status.disconnected[500],
color: getThemeForStatus(theme, bridge.status),
},
animated: isConnected && !!remote.length,
style: {
strokeWidth: isConnected ? 1.5 : 0.5,
stroke: isConnected ? theme.colors.status.connected[500] : theme.colors.status.disconnected[500],
stroke: getThemeForStatus(theme, bridge.status),
},
}

Expand All @@ -89,12 +93,12 @@ export const createBridgeNode = (
type: MarkerType.ArrowClosed,
width: 20,
height: 20,
color: isConnected ? theme.colors.status.connected[500] : theme.colors.status.disconnected[500],
color: getThemeForStatus(theme, bridge.status),
},
animated: isConnected && !!local.length,
style: {
strokeWidth: isConnected ? 1.5 : 0.5,
stroke: isConnected ? theme.colors.status.connected[500] : theme.colors.status.disconnected[500],
stroke: getThemeForStatus(theme, bridge.status),
},
}

Expand Down Expand Up @@ -144,7 +148,9 @@ export const createAdapterNode = (
positionStorage?: Record<string, XYPosition>
) => {
const idAdapter = `${IdStubs.ADAPTER_NODE}@${adapter.id}`
const isConnected = adapter.status?.connection === Status.connection.CONNECTED
const isConnected =
adapter.status?.connection === Status.connection.CONNECTED ||
(adapter.status?.runtime === Status.runtime.STARTED && adapter.status?.connection === Status.connection.STATELESS)
const topics = discoverAdapterTopics(type, adapter.config as GenericObjectType)

const posX = nbAdapter % MAX_ADAPTERS
Expand All @@ -162,6 +168,7 @@ export const createAdapterNode = (
},
}

console.log('XXXXXXX idAdapter', adapter.status)
const edgeConnector: Edge = {
id: `${IdStubs.CONNECTOR}-${IdStubs.EDGE_NODE}-${idAdapter}`,
target: IdStubs.EDGE_NODE,
Expand All @@ -172,12 +179,12 @@ export const createAdapterNode = (
type: MarkerType.ArrowClosed,
width: 20,
height: 20,
color: isConnected ? theme.colors.status.connected[500] : theme.colors.status.disconnected[500],
color: getThemeForStatus(theme, adapter.status),
},
animated: isConnected && !!topics.length,
style: {
strokeWidth: isConnected ? 1.5 : 0.5,
stroke: isConnected ? theme.colors.status.connected[500] : theme.colors.status.disconnected[500],
stroke: getThemeForStatus(theme, adapter.status),
},
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
import { expect } from 'vitest'
import { Node, NodeProps } from 'reactflow'
import * as CSS from 'csstype'
import { ResponsiveValue, ThemeTypings } from '@chakra-ui/react'

import { MOCK_NODE_ADAPTER, MOCK_NODE_BRIDGE, MOCK_NODE_LISTENER } from '@/__test-utils__/react-flow/nodes.ts'
import { MOCK_ADAPTER_ID } from '@/__test-utils__/mocks.ts'
import { MOCK_THEME } from '@/__test-utils__/react-flow/utils.ts'

import { Adapter, Bridge, Status } from '@/api/__generated__'
import { mockBridgeId } from '@/api/hooks/useGetBridges/__handlers__'

import { MOCK_NODE_ADAPTER, MOCK_NODE_BRIDGE, MOCK_NODE_LISTENER } from '@/__test-utils__/react-flow/nodes.ts'
import { updateNodeStatus } from '@/modules/EdgeVisualisation/utils/status-utils.ts'
import { getThemeForStatus, updateNodeStatus } from '@/modules/EdgeVisualisation/utils/status-utils.ts'
import { NodeTypes } from '@/modules/EdgeVisualisation/types.ts'
import { mockBridgeId } from '@/api/hooks/useGetBridges/__handlers__'
import { MOCK_ADAPTER_ID } from '@/__test-utils__/mocks.ts'

const disconnectedBridge: NodeProps<Bridge> = {
...MOCK_NODE_BRIDGE,
Expand Down Expand Up @@ -97,3 +101,27 @@ describe('updateNodeStatus', () => {
expect(updatedNodes).toStrictEqual(expected)
})
})

type Token<CSSType, ThemeKey = unknown> = ThemeKey extends keyof ThemeTypings
? ResponsiveValue<CSSType | ThemeTypings[ThemeKey]>
: ResponsiveValue<CSSType>

interface StatusSuite {
status?: Status
expected: Token<CSS.Property.Color, 'colors'>
}

describe('getThemeForStatus', () => {
it.each<StatusSuite>([
{ status: undefined, expected: '#E53E3E' },
{ status: { runtime: Status.runtime.STOPPED }, expected: '#E53E3E' },
{ status: { connection: Status.connection.CONNECTED }, expected: '#38A169' },
{ status: { connection: Status.connection.DISCONNECTED }, expected: '#718096' },
{ status: { connection: Status.connection.ERROR }, expected: '#E53E3E' },
{ status: { connection: Status.connection.UNKNOWN }, expected: '#E53E3E' },
{ status: { connection: Status.connection.STATELESS }, expected: '#38A169' },
])('should return $expected for $status', ({ status, expected }) => {
const color = getThemeForStatus(MOCK_THEME, status)
expect(color).toBe(expected)
})
})
Original file line number Diff line number Diff line change
@@ -1,7 +1,29 @@
import { Node } from 'reactflow'
import { WithCSSVar } from '@chakra-ui/react'
import { Dict } from '@chakra-ui/utils'

import { Adapter, Bridge, Status } from '@/api/__generated__'
import { NodeTypes } from '@/modules/EdgeVisualisation/types.ts'

/**
* @param theme
* @param status
*
* TODO[NVL] Unify the styling with ConnectionStatusBadge
* @see ConnectionStatusBadge
*/
export const getThemeForStatus = (theme: Partial<WithCSSVar<Dict>>, status: Status | undefined) => {
if (status?.runtime === Status.runtime.STOPPED) return theme.colors.status.error[500]

if (status?.connection === Status.connection.CONNECTED) return theme.colors.status.connected[500]
if (status?.connection === Status.connection.DISCONNECTED) return theme.colors.status.disconnected[500]
if (status?.connection === Status.connection.STATELESS) return theme.colors.status.stateless[500]

// if (status?.connection === Status.connection.ERROR) return theme.colors.status.error[500]
// if (status?.connection === Status.connection.UNKNOWN) return theme.colors.status.error[500]
return theme.colors.status.error[500]
}

export const updateNodeStatus = (currentNodes: Node[], updates: Status[]) => {
return currentNodes.map((n): Node<Bridge> => {
if (n.type === NodeTypes.BRIDGE_NODE) {
Expand Down

0 comments on commit 8c1d7e7

Please sign in to comment.