Skip to content

Commit

Permalink
perf: improve healthbar display, will responsive with container size
Browse files Browse the repository at this point in the history
  • Loading branch information
moonrailgun committed Aug 17, 2024
1 parent 6fecde0 commit 3990b0a
Show file tree
Hide file tree
Showing 6 changed files with 108 additions and 24 deletions.
52 changes: 33 additions & 19 deletions src/client/components/HealthBar.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { useResizeObserver } from '@/hooks/useResizeObserver';
import clsx from 'clsx';
import React from 'react';

Expand All @@ -14,33 +15,46 @@ export interface HealthBarProps {
}
export const HealthBar: React.FC<HealthBarProps> = React.memo((props) => {
const size = props.size ?? 'small';
const [containerRef, containerRect] = useResizeObserver();

const cellCount = props.beats.length;
const cellNeedWidth = size === 'small' ? 8 : 12; // include gap

return (
<div
ref={containerRef}
className={clsx('flex', {
'gap-[3px]': size === 'small',
'gap-1': size === 'large',
})}
>
{props.beats.map((beat, i) => (
<div
key={i}
title={beat.title}
className={clsx(
'rounded-full transition-transform hover:scale-150',
{
'h-4 w-[5px]': size === 'small',
'h-8 w-2': size === 'large',
},
{
'bg-green-500': beat.status === 'health',
'bg-red-600': beat.status === 'error',
'bg-yellow-400': beat.status === 'warning',
'bg-gray-400': beat.status === 'none',
}
)}
/>
))}
{props.beats
.slice(
Math.floor(
Math.max(cellNeedWidth * cellCount - containerRect.width, 0) /
cellNeedWidth
),
cellCount
)
.map((beat, i) => (
<div
key={i}
title={beat.title}
className={clsx(
'rounded-full transition-transform hover:scale-150',
{
'h-4 w-[5px]': size === 'small',
'h-8 w-2': size === 'large',
},
{
'bg-green-500': beat.status === 'health',
'bg-red-600': beat.status === 'error',
'bg-yellow-400': beat.status === 'warning',
'bg-gray-400': beat.status === 'none',
}
)}
/>
))}
</div>
);
});
Expand Down
8 changes: 4 additions & 4 deletions src/client/components/monitor/MonitorHealthBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ export const MonitorHealthBar: React.FC<MonitorHealthBarProps> = React.memo(
</span>
)}

<div className="flex-1">
<div className="flex-1 overflow-hidden">
<HealthBar size={size} beats={beats} />
</div>

Expand All @@ -129,7 +129,7 @@ export const MonitorHealthBar: React.FC<MonitorHealthBarProps> = React.memo(
{last(beats)?.status === 'health' ? (
<div
className={clsx(
'rounded-full bg-green-500 px-4 py-1 text-lg font-bold text-white',
'ml-2 rounded-full bg-green-500 px-4 py-1 text-lg font-bold text-white',
{
'text-sm': size === 'small',
}
Expand All @@ -140,7 +140,7 @@ export const MonitorHealthBar: React.FC<MonitorHealthBarProps> = React.memo(
) : last(beats)?.status === 'error' ? (
<div
className={clsx(
'rounded-full bg-red-600 px-4 py-1 text-lg font-bold text-white',
'ml-2 rounded-full bg-red-600 px-4 py-1 text-lg font-bold text-white',
{
'text-sm': size === 'small',
}
Expand All @@ -151,7 +151,7 @@ export const MonitorHealthBar: React.FC<MonitorHealthBarProps> = React.memo(
) : (
<div
className={clsx(
'rounded-full bg-gray-400 px-4 py-1 text-lg font-bold text-white',
'ml-2 rounded-full bg-gray-400 px-4 py-1 text-lg font-bold text-white',
{
'text-sm': size === 'small',
}
Expand Down
File renamed without changes.
1 change: 0 additions & 1 deletion src/client/hooks/useGlobalRangeDate.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { CalendarOutlined } from '@ant-design/icons';
import dayjs, { Dayjs } from 'dayjs';
import { useMemo, useReducer } from 'react';
import { getMinimumUnit } from '@tianji/shared';
Expand Down
70 changes: 70 additions & 0 deletions src/client/hooks/useResizeObserver.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/**
* Copy from https://github.com/mantinedev/mantine/blob/master/packages/@mantine/hooks/src/use-resize-observer/use-resize-observer.ts
*/

import { useRef, useState, useMemo, useEffect } from 'react';

type ObserverRect = Omit<DOMRectReadOnly, 'toJSON'>;

const defaultState: ObserverRect = {
x: 0,
y: 0,
width: 0,
height: 0,
top: 0,
left: 0,
bottom: 0,
right: 0,
};

export function useResizeObserver<T extends HTMLElement = any>(
options?: ResizeObserverOptions
) {
const frameID = useRef(0);
const ref = useRef<T>(null);

const [rect, setRect] = useState<ObserverRect>(defaultState);

const observer = useMemo(
() =>
typeof window !== 'undefined'
? new ResizeObserver((entries: any) => {
const entry = entries[0];

if (entry) {
cancelAnimationFrame(frameID.current);

frameID.current = requestAnimationFrame(() => {
if (ref.current) {
setRect(entry.contentRect);
}
});
}
})
: null,
[]
);

useEffect(() => {
if (ref.current) {
observer?.observe(ref.current, options);
}

return () => {
observer?.disconnect();

if (frameID.current) {
cancelAnimationFrame(frameID.current);
}
};
}, [ref.current]);

return [ref, rect] as const;
}

export function useElementSize<T extends HTMLElement = any>(
options?: ResizeObserverOptions
) {
const [ref, { width, height }] = useResizeObserver<T>(options);
return { ref, width, height };
}
1 change: 1 addition & 0 deletions src/server/trpc/routers/workspace.ts
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ export const workspaceRouter = router({
workspaceId: z.string(),
})
)
.output(z.void())
.mutation(async ({ input, ctx }) => {
const { workspaceId } = input;
const userId = ctx.user.id;
Expand Down

0 comments on commit 3990b0a

Please sign in to comment.