fix PieChart rendering issues by giving default height.

This commit is contained in:
Francis Cao
2026-05-18 23:06:47 -07:00
parent c6b2364a41
commit a7a0d73dd7
6 changed files with 5 additions and 32 deletions
+1 -8
View File
@@ -13,7 +13,7 @@ ChartJS.defaults.font.family = 'Inter';
export interface ChartProps extends BoxProps {
type?: 'bar' | 'bubble' | 'doughnut' | 'pie' | 'line' | 'polarArea' | 'radar' | 'scatter';
chartData?: ChartData & { focusLabel?: string };
chartData?: ChartData<any, any, unknown> & { focusLabel?: string };
chartOptions?: ChartOptions;
updateMode?: UpdateMode;
animationDuration?: number;
@@ -66,8 +66,6 @@ export function Chart({
const handleLegendClick = (item: LegendItem) => {
if (onLegendClick && type === 'bar') {
// Controlled mode: caller owns the hidden state. We report the click
// and let the parent push a new hiddenLabels set on the next render.
const { datasetIndex } = item;
const ds = chart.current.data.datasets[datasetIndex];
onLegendClick(ds.label, !hiddenLabels?.has(ds.label));
@@ -124,16 +122,11 @@ export function Chart({
});
}
// Re-apply caller-driven hidden flags after focusLabel handling so a
// dataset stays hidden across data changes (e.g. date-range switches)
// even though Chart.js regenerates dataset meta on every replace.
if (hiddenLabels) {
chart.current.data.datasets.forEach((ds: { hidden: boolean; label: any }) => {
if (hiddenLabels.has(ds.label)) {
ds.hidden = true;
} else if (!chartData.focusLabel) {
// Explicitly reset so un-hiding a label is always reflected,
// regardless of whether the focusLabel pass ran above.
ds.hidden = false;
}
});
+2 -2
View File
@@ -6,7 +6,7 @@ export interface PieChartProps extends ChartProps {
type?: 'doughnut' | 'pie';
}
export function PieChart({ type = 'pie', ...props }: PieChartProps) {
export function PieChart({ type = 'pie', height = '300px', ...props }: PieChartProps) {
const [tooltip, setTooltip] = useState(null);
const handleTooltip = ({ tooltip }) => {
@@ -24,7 +24,7 @@ export function PieChart({ type = 'pie', ...props }: PieChartProps) {
return (
<>
<Chart {...props} type={type} onTooltip={handleTooltip} />
<Chart {...props} type={type} height={height} onTooltip={handleTooltip} />
{tooltip && <ChartTooltip {...tooltip} />}
</>
);
+2 -7
View File
@@ -58,16 +58,11 @@ export function DataGrid({
const showPager = allowPaging && data && data.count > 0;
const { isMobile } = useMobile();
const [userDisplayMode, setUserDisplayMode] = useState<DisplayMode | null>(() => {
// localStorage can hold anything (extensions, manual edits, schema drift),
// so accept only the two values we know how to render and otherwise fall
// back to the useMobile-driven default.
const stored = getItem(DISPLAY_MODE_STORAGE_KEY);
return stored === 'table' || stored === 'cards' ? stored : null;
});
// Effective mode: explicit user choice wins, otherwise fall back to the
// mobile-driven default (cards on small viewports, table elsewhere).
const displayMode: DisplayMode | undefined = userDisplayMode ?? (isMobile ? 'cards' : undefined);
const displayMode: DisplayMode | undefined = isMobile ? 'cards' : userDisplayMode ?? undefined;
const handleToggleDisplayMode = () => {
const next: DisplayMode = displayMode === 'cards' ? 'table' : 'cards';
@@ -116,7 +111,7 @@ export function DataGrid({
)}
<Row alignItems="center" gap style={{ marginLeft: 'auto' }}>
{renderActions?.()}
{viewToggleButton}
{!isMobile && viewToggleButton}
</Row>
</Row>
<LoadingPanel
-7
View File
@@ -62,13 +62,6 @@ export function EventsChart({ websiteId, focusLabel, limit }: EventsChartProps)
],
};
} else {
// Each label has a preferred palette slot derived from a hash of the
// label, so the same event tends to get the same color across reloads
// and date-range changes. We walk labels in hash order and, when two
// labels prefer the same slot, the later one steps to the next free
// slot, so the visible set of <=12 events all get distinct colors.
// The right shift on hex6 sidesteps the FNV-1a low-bit bias mod 12
// (the FNV prime is close to 2^24).
const colorByKey: Record<string, string> = {};
const used = new Set<string>();
const hashOf = Object.fromEntries(
-5
View File
@@ -16,11 +16,6 @@ export const IP_ADDRESS_HEADERS = [
'x-forwarded',
];
/**
* Normalize IP strings to a canonical form:
* - strips IPv4-mapped IPv6 (e.g. ::ffff:192.0.2.1 -> 192.0.2.1)
* - keeps valid IPv4/IPv6 as-is (canonically formatted by ipaddr.js)
*/
function normalizeIp(ip?: string | null) {
if (!ip) return ip;
-3
View File
@@ -130,9 +130,6 @@ export async function deleteUser(userId: string) {
const teamIds = teams.map(a => a.id);
// Cloud mode keeps owned teams (and their team-owned content), so cleanup
// only covers user-direct rows. Non-cloud hard-deletes owned teams below,
// so we must also clean up team-owned content.
const ownedFilter = cloudMode
? { userId }
: { OR: [{ userId }, { teamId: { in: teamIds } }] };