Merge branch 'Pouzor:main' into bug/bezier-label
This commit is contained in:
@@ -66,7 +66,7 @@ export function BaseNode({ id, data, selected, icon: typeIcon, width, height }:
|
||||
minWidth={140}
|
||||
minHeight={50}
|
||||
lineStyle={{ borderColor: 'transparent' }}
|
||||
handleStyle={{ borderColor: colors.border, background: colors.border, width: 8, height: 8 }}
|
||||
handleStyle={{ borderColor: colors.border, background: colors.border, width: 16, height: 16 }}
|
||||
/>
|
||||
<Handle
|
||||
type="source"
|
||||
@@ -76,6 +76,13 @@ export function BaseNode({ id, data, selected, icon: typeIcon, width, height }:
|
||||
/>
|
||||
<Handle type="target" position={Position.Top} id="top-t" style={{ opacity: 0, width: 12, height: 12 }} />
|
||||
|
||||
{/* Status dot — absolute to avoid affecting node auto-width */}
|
||||
<div
|
||||
className="absolute top-2 right-2 w-1.5 h-1.5 rounded-full"
|
||||
style={{ backgroundColor: statusColor }}
|
||||
title={data.status}
|
||||
/>
|
||||
|
||||
{/* Main row */}
|
||||
<div className="flex flex-row items-center gap-2.5 px-2.5 py-2 min-w-0 overflow-hidden">
|
||||
{/* Icon */}
|
||||
@@ -121,7 +128,7 @@ export function BaseNode({ id, data, selected, icon: typeIcon, width, height }:
|
||||
return (
|
||||
<div key={prop.key} className="flex items-center gap-1 font-mono text-[10px] min-w-0 overflow-hidden" style={{ color: theme.colors.nodeSubtextColor }}>
|
||||
{Icon && <Icon size={9} className="shrink-0" />}
|
||||
<span className="truncate max-w-[60px] shrink-0" title={prop.key}>{prop.key}</span>
|
||||
<span className="truncate max-w-15 shrink-0" title={prop.key}>{prop.key}</span>
|
||||
<span className="truncate min-w-0" title={prop.value}>· {prop.value}</span>
|
||||
</div>
|
||||
)
|
||||
@@ -139,7 +146,7 @@ export function BaseNode({ id, data, selected, icon: typeIcon, width, height }:
|
||||
<div className="flex items-center gap-1 font-mono text-[10px]" style={{ color: theme.colors.nodeSubtextColor }}>
|
||||
<Cpu size={9} className="shrink-0" />
|
||||
{data.cpu_model && (
|
||||
<span className="truncate max-w-[80px]" title={data.cpu_model}>{data.cpu_model}</span>
|
||||
<span className="truncate max-w-20" title={data.cpu_model}>{data.cpu_model}</span>
|
||||
)}
|
||||
{data.cpu_count != null && (
|
||||
<span className="shrink-0">{data.cpu_model ? `· ${data.cpu_count}c` : `${data.cpu_count} cores`}</span>
|
||||
@@ -166,13 +173,6 @@ export function BaseNode({ id, data, selected, icon: typeIcon, width, height }:
|
||||
</>
|
||||
)}
|
||||
|
||||
{/* Status dot */}
|
||||
<div
|
||||
className="absolute top-1.5 right-1.5 w-1.5 h-1.5 rounded-full shrink-0"
|
||||
style={{ backgroundColor: statusColor }}
|
||||
title={data.status}
|
||||
/>
|
||||
|
||||
{(BOTTOM_HANDLE_POSITIONS[data.bottom_handles ?? 1] ?? BOTTOM_HANDLE_POSITIONS[1]).map((leftPct, idx) => {
|
||||
const sourceId = BOTTOM_HANDLE_IDS[idx]
|
||||
const targetId = idx === 0 ? 'bottom-t' : `bottom-${idx + 1}-t`
|
||||
|
||||
@@ -5,6 +5,8 @@ import type { NodeData } from '@/types'
|
||||
import { resolveNodeColors } from '@/utils/nodeColors'
|
||||
import { resolveNodeIcon } from '@/utils/nodeIcons'
|
||||
import { resolvePropertyIcon } from '@/utils/propertyIcons'
|
||||
import { useCanvasStore } from '@/stores/canvasStore'
|
||||
import { maskIp, splitIps } from '@/utils/maskIp'
|
||||
import { useThemeStore } from '@/stores/themeStore'
|
||||
import { THEMES } from '@/utils/themes'
|
||||
import { BaseNode } from './BaseNode'
|
||||
@@ -13,6 +15,7 @@ export function ProxmoxGroupNode(props: NodeProps<Node<NodeData>>) {
|
||||
const { data, selected } = props
|
||||
|
||||
const activeTheme = useThemeStore((s) => s.activeTheme)
|
||||
const hideIp = useCanvasStore((s) => s.hideIp)
|
||||
const theme = THEMES[activeTheme]
|
||||
const colors = resolveNodeColors(data, activeTheme)
|
||||
|
||||
@@ -53,7 +56,7 @@ export function ProxmoxGroupNode(props: NodeProps<Node<NodeData>>) {
|
||||
minHeight={160}
|
||||
isVisible={selected}
|
||||
lineStyle={{ borderColor: glow, opacity: 0.6 }}
|
||||
handleStyle={{ borderColor: glow, backgroundColor: theme.colors.nodeCardBackground }}
|
||||
handleStyle={{ borderColor: glow, backgroundColor: theme.colors.nodeCardBackground, width: 6, height: 6 }}
|
||||
/>
|
||||
|
||||
{/* Group border */}
|
||||
@@ -71,7 +74,7 @@ export function ProxmoxGroupNode(props: NodeProps<Node<NodeData>>) {
|
||||
>
|
||||
{/* Header bar */}
|
||||
<div
|
||||
className="flex items-center gap-2 px-2.5 py-1.5 shrink-0"
|
||||
className="flex flex-row items-start gap-2 px-2.5 py-1.5 shrink-0"
|
||||
style={{
|
||||
background: isOnline ? `${glow}18` : `${theme.colors.nodeIconBackground}88`,
|
||||
borderBottom: `1px solid ${isOnline ? `${glow}33` : theme.colors.handleBackground}`,
|
||||
@@ -93,18 +96,19 @@ export function ProxmoxGroupNode(props: NodeProps<Node<NodeData>>) {
|
||||
>
|
||||
{data.label}
|
||||
</span>
|
||||
{data.ip && (
|
||||
{data.ip && splitIps(data.ip).map((ip) => (
|
||||
<span
|
||||
key={ip}
|
||||
className="font-mono text-[9px] truncate"
|
||||
style={{ color: theme.colors.nodeSubtextColor }}
|
||||
>
|
||||
{data.ip}
|
||||
{hideIp ? maskIp(ip) : ip}
|
||||
</span>
|
||||
)}
|
||||
))}
|
||||
</div>
|
||||
{/* Status dot */}
|
||||
<div
|
||||
className="w-1.5 h-1.5 rounded-full shrink-0"
|
||||
className="ml-auto w-1.5 h-1.5 rounded-full shrink-0"
|
||||
style={{ backgroundColor: statusColor }}
|
||||
title={data.status}
|
||||
/>
|
||||
@@ -125,7 +129,7 @@ export function ProxmoxGroupNode(props: NodeProps<Node<NodeData>>) {
|
||||
}}
|
||||
>
|
||||
{Icon && <Icon size={9} className="shrink-0" />}
|
||||
<span className="truncate max-w-[60px] shrink-0" title={prop.key}>{prop.key}</span>
|
||||
<span className="truncate max-w-15 shrink-0" title={prop.key}>{prop.key}</span>
|
||||
<span className="truncate min-w-0" title={prop.value}>· {prop.value}</span>
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { type NodeProps, type Node } from '@xyflow/react'
|
||||
import {
|
||||
Globe, Router, Network, Server, Layers, Box, Container,
|
||||
HardDrive, Cpu, Wifi, Circle, Cctv, Printer, Monitor, PlugZap, Anchor,
|
||||
HardDrive, Cpu, Wifi, Circle, Cctv, Printer, Monitor, PlugZap, Anchor, Package,
|
||||
} from 'lucide-react'
|
||||
import { BaseNode } from './BaseNode'
|
||||
import type { NodeData } from '@/types'
|
||||
@@ -22,5 +22,6 @@ export const CameraNode = (props: N) => <BaseNode {...props} icon={Cctv} />
|
||||
export const PrinterNode = (props: N) => <BaseNode {...props} icon={Printer} />
|
||||
export const ComputerNode = (props: N) => <BaseNode {...props} icon={Monitor} />
|
||||
export const CplNode = (props: N) => <BaseNode {...props} icon={PlugZap} />
|
||||
export const DockerNode = (props: N) => <BaseNode {...props} icon={Anchor} />
|
||||
export const DockerHostNode = (props: N) => <BaseNode {...props} icon={Anchor} />
|
||||
export const DockerContainerNode = (props: N) => <BaseNode {...props} icon={Package} />
|
||||
export const GenericNode = (props: N) => <BaseNode {...props} icon={Circle} />
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { IspNode, RouterNode, SwitchNode, ServerNode, VmNode, LxcNode, NasNode, IotNode, ApNode, CameraNode, PrinterNode, ComputerNode, CplNode, DockerNode, GenericNode } from './index'
|
||||
import { IspNode, RouterNode, SwitchNode, ServerNode, VmNode, LxcNode, NasNode, IotNode, ApNode, CameraNode, PrinterNode, ComputerNode, CplNode, DockerHostNode, DockerContainerNode, GenericNode } from './index'
|
||||
import { ProxmoxGroupNode } from './ProxmoxGroupNode'
|
||||
import { GroupRectNode } from './GroupRectNode'
|
||||
import { GroupNode } from './GroupNode'
|
||||
@@ -18,7 +18,8 @@ export const nodeTypes = {
|
||||
printer: PrinterNode,
|
||||
computer: ComputerNode,
|
||||
cpl: CplNode,
|
||||
docker: DockerNode,
|
||||
docker_host: DockerHostNode,
|
||||
docker_container: DockerContainerNode,
|
||||
generic: GenericNode,
|
||||
groupRect: GroupRectNode,
|
||||
group: GroupNode,
|
||||
|
||||
Reference in New Issue
Block a user