refactor(web): enhance OpsDashboard and ChartContainer for improved metrics logging and responsiveness
Build, Test, and Push CFDM Docker Image / test (push) Successful in 3m46s
Build, Test, and Push CFDM Docker Image / build-and-push (push) Successful in 1m56s
Build, Test, and Push CFDM Docker Image / update-wiki (push) Successful in 6s
Build, Test, and Push CFDM Docker Image / create-release (push) Has been skipped
Build, Test, and Push CFDM Docker Image / test (push) Successful in 3m46s
Build, Test, and Push CFDM Docker Image / build-and-push (push) Successful in 1m56s
Build, Test, and Push CFDM Docker Image / update-wiki (push) Successful in 6s
Build, Test, and Push CFDM Docker Image / create-release (push) Has been skipped
- Refactored OpsDashboard to encapsulate layout metrics logging in a dedicated function, improving code clarity and maintainability. - Updated metrics logging to include SVG dimensions for better analytics. - Enhanced ChartContainer to utilize ResizeObserver for dynamic sizing, ensuring charts render correctly within their containers. Co-authored-by: Cursor <[email protected]>
This commit is contained in:
@@ -48,9 +48,7 @@ function ChartContainer({
|
||||
...props
|
||||
}: React.ComponentProps<"div"> & {
|
||||
config: ChartConfig
|
||||
children: React.ComponentProps<
|
||||
typeof RechartsPrimitive.ResponsiveContainer
|
||||
>["children"]
|
||||
children: React.ReactNode
|
||||
initialDimension?: {
|
||||
width: number
|
||||
height: number
|
||||
@@ -58,28 +56,53 @@ function ChartContainer({
|
||||
}) {
|
||||
const uniqueId = React.useId()
|
||||
const chartId = `chart-${id ?? uniqueId.replace(/:/g, "")}`
|
||||
const containerRef = React.useRef<HTMLDivElement>(null)
|
||||
const [size, setSize] = React.useState(initialDimension)
|
||||
|
||||
React.useEffect(() => {
|
||||
const el = containerRef.current
|
||||
if (!el || typeof ResizeObserver === "undefined") return
|
||||
|
||||
const update = () => {
|
||||
const width = Math.max(1, Math.floor(el.clientWidth))
|
||||
const height = Math.max(1, Math.floor(el.clientHeight))
|
||||
setSize((prev) =>
|
||||
prev.width === width && prev.height === height
|
||||
? prev
|
||||
: { width, height },
|
||||
)
|
||||
}
|
||||
|
||||
update()
|
||||
const ro = new ResizeObserver(update)
|
||||
ro.observe(el)
|
||||
return () => ro.disconnect()
|
||||
}, [])
|
||||
|
||||
// Recharts 3 ResponsiveContainer часто оставляет inner 0×0 (см. debug dashboard).
|
||||
// Рендерим chart с явными width/height по размеру контейнера.
|
||||
const sizedChildren = React.Children.map(children, (child) => {
|
||||
if (!React.isValidElement(child)) return child
|
||||
return React.cloneElement(
|
||||
child as React.ReactElement<{ width?: number; height?: number }>,
|
||||
{ width: size.width, height: size.height },
|
||||
)
|
||||
})
|
||||
|
||||
return (
|
||||
<ChartContext.Provider value={{ config }}>
|
||||
<div
|
||||
ref={containerRef}
|
||||
data-slot="chart"
|
||||
data-chart={chartId}
|
||||
className={cn(
|
||||
// relative + block: flex на контейнере даёт Recharts ResponsiveContainer 0×0
|
||||
"relative block w-full text-xs [&_.recharts-cartesian-axis-tick_text]:fill-muted-foreground [&_.recharts-cartesian-grid_line[stroke='#ccc']]:stroke-border/50 [&_.recharts-curve.recharts-tooltip-cursor]:stroke-border [&_.recharts-dot[stroke='#fff']]:stroke-transparent [&_.recharts-layer]:outline-hidden [&_.recharts-polar-grid_[stroke='#ccc']]:stroke-border [&_.recharts-radial-bar-background-sector]:fill-muted [&_.recharts-rectangle.recharts-tooltip-cursor]:fill-muted [&_.recharts-reference-line_[stroke='#ccc']]:stroke-border [&_.recharts-sector]:outline-hidden [&_.recharts-sector[stroke='#fff']]:stroke-transparent [&_.recharts-surface]:outline-hidden",
|
||||
"relative block w-full min-h-0 text-xs [&_.recharts-cartesian-axis-tick_text]:fill-muted-foreground [&_.recharts-cartesian-grid_line[stroke='#ccc']]:stroke-border/50 [&_.recharts-curve.recharts-tooltip-cursor]:stroke-border [&_.recharts-dot[stroke='#fff']]:stroke-transparent [&_.recharts-layer]:outline-hidden [&_.recharts-polar-grid_[stroke='#ccc']]:stroke-border [&_.recharts-radial-bar-background-sector]:fill-muted [&_.recharts-rectangle.recharts-tooltip-cursor]:fill-muted [&_.recharts-reference-line_[stroke='#ccc']]:stroke-border [&_.recharts-sector]:outline-hidden [&_.recharts-sector[stroke='#fff']]:stroke-transparent [&_.recharts-surface]:outline-hidden",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
<ChartStyle id={chartId} config={config} />
|
||||
<RechartsPrimitive.ResponsiveContainer
|
||||
width="100%"
|
||||
height="100%"
|
||||
minWidth={0}
|
||||
initialDimension={initialDimension}
|
||||
>
|
||||
{children}
|
||||
</RechartsPrimitive.ResponsiveContainer>
|
||||
{sizedChildren}
|
||||
</div>
|
||||
</ChartContext.Provider>
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user