Feature/move list to client (#50)
This commit is contained in:
committed by
GitHub
parent
c2abdaadf2
commit
668434d246
@@ -62,10 +62,10 @@ export function PreviousDiffIndicator({
|
||||
|
||||
const renderIcon = () => {
|
||||
if (state === 'positive') {
|
||||
return <ArrowUpIcon strokeWidth={3} size={12} color="#000" />;
|
||||
return <ArrowUpIcon strokeWidth={3} size={10} color="#000" />;
|
||||
}
|
||||
if (state === 'negative') {
|
||||
return <ArrowDownIcon strokeWidth={3} size={12} color="#000" />;
|
||||
return <ArrowDownIcon strokeWidth={3} size={10} color="#000" />;
|
||||
}
|
||||
return null;
|
||||
};
|
||||
@@ -74,7 +74,7 @@ export function PreviousDiffIndicator({
|
||||
<>
|
||||
<div
|
||||
className={cn(
|
||||
'flex items-center gap-1 font-medium',
|
||||
'font-mono flex items-center gap-1 font-medium',
|
||||
size === 'lg' && 'gap-2',
|
||||
className
|
||||
)}
|
||||
|
||||
@@ -89,21 +89,21 @@ export function MetricCard({
|
||||
)}
|
||||
</AutoSizer>
|
||||
</div>
|
||||
<div className="relative">
|
||||
<div className="col relative gap-2">
|
||||
<div className="flex items-center justify-between gap-2">
|
||||
<div className="flex min-w-0 items-center gap-2 text-left font-semibold">
|
||||
<span className="overflow-hidden text-ellipsis whitespace-nowrap text-muted-foreground">
|
||||
<div className="flex min-w-0 items-center gap-2 text-left">
|
||||
<span className="truncate text-muted-foreground">
|
||||
<SerieName name={serie.names} />
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-end justify-between">
|
||||
<div className="overflow-hidden text-ellipsis whitespace-nowrap text-2xl font-bold">
|
||||
<div className="font-mono truncate text-3xl font-bold">
|
||||
{renderValue(serie.metrics[metric], 'ml-1 font-light text-xl')}
|
||||
</div>
|
||||
<PreviousDiffIndicator
|
||||
{...previous}
|
||||
className="text-xs text-muted-foreground"
|
||||
className="text-sm text-muted-foreground"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -37,7 +37,7 @@ export function ReportBarChart({ data }: ReportBarChartProps) {
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
'flex flex-col text-xs',
|
||||
'flex flex-col text-sm',
|
||||
editMode ? 'card gap-2 p-4 text-base' : '-m-3 gap-1'
|
||||
)}
|
||||
>
|
||||
@@ -60,9 +60,9 @@ export function ReportBarChart({ data }: ReportBarChartProps) {
|
||||
: {})}
|
||||
>
|
||||
<div
|
||||
className="absolute bottom-0 left-0 top-0 rounded bg-def-200"
|
||||
className="absolute bottom-0.5 left-1 right-1 top-0.5 rounded bg-def-200"
|
||||
style={{
|
||||
width: `${(serie.metrics.sum / maxCount) * 100}%`,
|
||||
width: `calc(${(serie.metrics.sum / maxCount) * 100}% - 8px)`,
|
||||
}}
|
||||
/>
|
||||
<div className="relative z-10 flex w-full flex-1 items-center gap-4 overflow-hidden px-3 py-2">
|
||||
@@ -70,7 +70,7 @@ export function ReportBarChart({ data }: ReportBarChartProps) {
|
||||
<SerieIcon name={serie.names[0]} />
|
||||
<SerieName name={serie.names} />
|
||||
</div>
|
||||
<div className="flex flex-shrink-0 items-center justify-end gap-4">
|
||||
<div className="font-mono flex flex-shrink-0 items-center justify-end gap-4">
|
||||
<PreviousDiffIndicator
|
||||
{...serie.metrics.previous?.[metric]}
|
||||
/>
|
||||
|
||||
@@ -42,7 +42,7 @@ export function ReportChartTooltip({
|
||||
const hidden = sorted.slice(limit);
|
||||
|
||||
return (
|
||||
<div className="flex min-w-[180px] flex-col gap-2 rounded-xl border bg-card p-3 text-sm shadow-xl">
|
||||
<div className="flex min-w-[180px] flex-col gap-2 rounded-xl border bg-card p-3 shadow-xl">
|
||||
{visible.map((item, index) => {
|
||||
// If we have a <Cell /> component, payload can be nested
|
||||
const payload = item.payload.payload ?? item.payload;
|
||||
@@ -65,20 +65,22 @@ export function ReportChartTooltip({
|
||||
className="w-[3px] rounded-full"
|
||||
style={{ background: data.color }}
|
||||
/>
|
||||
<div className="flex flex-1 flex-col">
|
||||
<div className="col flex-1 gap-1">
|
||||
<div className="flex items-center gap-1">
|
||||
<SerieIcon name={data.names} />
|
||||
<SerieName name={data.names} />
|
||||
</div>
|
||||
<div className="flex justify-between gap-8">
|
||||
<div>{number.formatWithUnit(data.count, unit)}</div>
|
||||
|
||||
<div className="flex gap-1">
|
||||
<PreviousDiffIndicator {...data.previous}>
|
||||
{!!data.previous &&
|
||||
`(${number.formatWithUnit(data.previous.value, unit)})`}
|
||||
</PreviousDiffIndicator>
|
||||
<div className="font-mono flex justify-between gap-8 font-medium">
|
||||
<div className="row gap-1">
|
||||
{number.formatWithUnit(data.count, unit)}
|
||||
{!!data.previous && (
|
||||
<span className="text-muted-foreground">
|
||||
({number.formatWithUnit(data.previous.value, unit)})
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<PreviousDiffIndicator {...data.previous} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
'use client';
|
||||
|
||||
import React, { useCallback, useMemo } from 'react';
|
||||
import React, { useCallback } from 'react';
|
||||
import { useFormatDateInterval } from '@/hooks/useFormatDateInterval';
|
||||
import { useNumber } from '@/hooks/useNumerFormatter';
|
||||
import { useRechartDataModel } from '@/hooks/useRechartDataModel';
|
||||
@@ -10,24 +10,19 @@ import type { IChartData } from '@/trpc/client';
|
||||
import { cn } from '@/utils/cn';
|
||||
import { getChartColor } from '@/utils/theme';
|
||||
import { isSameDay, isSameHour, isSameMonth } from 'date-fns';
|
||||
import { SplineIcon } from 'lucide-react';
|
||||
import { last, pathOr } from 'ramda';
|
||||
import { last } from 'ramda';
|
||||
import {
|
||||
Area,
|
||||
CartesianGrid,
|
||||
ComposedChart,
|
||||
Legend,
|
||||
Line,
|
||||
LineChart,
|
||||
ReferenceLine,
|
||||
Tooltip,
|
||||
XAxis,
|
||||
YAxis,
|
||||
} from 'recharts';
|
||||
|
||||
import type { IServiceReference } from '@openpanel/db';
|
||||
import type { IChartLineType, IInterval } from '@openpanel/validation';
|
||||
|
||||
import { getYAxisWidth } from './chart-utils';
|
||||
import { useChartContext } from './ChartProvider';
|
||||
import { ReportChartTooltip } from './ReportChartTooltip';
|
||||
|
||||
@@ -48,6 +48,7 @@ interface ChartRootShortcutProps {
|
||||
chartType?: IChartProps['chartType'];
|
||||
interval?: IChartProps['interval'];
|
||||
events: IChartProps['events'];
|
||||
breakdowns?: IChartProps['breakdowns'];
|
||||
}
|
||||
|
||||
export const ChartRootShortcut = ({
|
||||
@@ -57,12 +58,13 @@ export const ChartRootShortcut = ({
|
||||
chartType = 'linear',
|
||||
interval = 'day',
|
||||
events,
|
||||
breakdowns,
|
||||
}: ChartRootShortcutProps) => {
|
||||
return (
|
||||
<ChartRoot
|
||||
projectId={projectId}
|
||||
range={range}
|
||||
breakdowns={[]}
|
||||
breakdowns={breakdowns ?? []}
|
||||
previous={previous}
|
||||
chartType={chartType}
|
||||
interval={interval}
|
||||
|
||||
@@ -132,7 +132,7 @@ export function FunnelSteps({
|
||||
</div>
|
||||
{finalStep ? (
|
||||
<div className={cn('flex flex-col items-center p-4')}>
|
||||
<div className="text-xs font-medium uppercase">
|
||||
<div className="text-sm font-medium uppercase">
|
||||
Conversion
|
||||
</div>
|
||||
<div
|
||||
@@ -143,13 +143,13 @@ export function FunnelSteps({
|
||||
>
|
||||
{round(step.percent, 1)}%
|
||||
</div>
|
||||
<div className="mt-0 text-sm font-medium uppercase text-muted-foreground">
|
||||
<div className="mt-0 font-medium uppercase text-muted-foreground">
|
||||
Converted {step.current} of {totalSessions} sessions
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<div className={cn('flex flex-col items-center p-4')}>
|
||||
<div className="text-xs font-medium uppercase">Dropoff</div>
|
||||
<div className="text-sm font-medium uppercase">Dropoff</div>
|
||||
<div
|
||||
className={cn(
|
||||
'text-3xl font-bold uppercase',
|
||||
@@ -158,7 +158,7 @@ export function FunnelSteps({
|
||||
>
|
||||
{round(step.dropoff.percent, 1)}%
|
||||
</div>
|
||||
<div className="mt-0 text-sm font-medium uppercase text-muted-foreground">
|
||||
<div className="mt-0 font-medium uppercase text-muted-foreground">
|
||||
Lost {step.dropoff.count} sessions
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,17 +1,14 @@
|
||||
'use client';
|
||||
|
||||
import { ColorSquare } from '@/components/color-square';
|
||||
import { AutoSizer } from '@/components/react-virtualized-auto-sizer';
|
||||
import { TooltipComplete } from '@/components/tooltip-complete';
|
||||
import { Progress } from '@/components/ui/progress';
|
||||
import { Widget, WidgetBody } from '@/components/widget';
|
||||
import type { RouterOutputs } from '@/trpc/client';
|
||||
import { cn } from '@/utils/cn';
|
||||
import { round } from '@/utils/math';
|
||||
import { getChartColor } from '@/utils/theme';
|
||||
import { AlertCircleIcon, TrendingUp } from 'lucide-react';
|
||||
import { AlertCircleIcon } from 'lucide-react';
|
||||
import { last } from 'ramda';
|
||||
import { Cell, Pie, PieChart } from 'recharts';
|
||||
|
||||
import { getPreviousMetric } from '@openpanel/common';
|
||||
import { alphabetIds } from '@openpanel/constants';
|
||||
@@ -40,7 +37,7 @@ function InsightCard({
|
||||
}) {
|
||||
return (
|
||||
<div className="flex flex-col rounded-lg border border-border p-4 py-3">
|
||||
<span className="text-sm">{title}</span>
|
||||
<span className="">{title}</span>
|
||||
<div className="whitespace-nowrap text-lg">{children}</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -54,7 +54,7 @@ export function EventPropertiesCombobox({
|
||||
>
|
||||
<button
|
||||
className={cn(
|
||||
'flex items-center gap-1 rounded-md border border-border p-1 px-2 text-xs font-medium leading-none',
|
||||
'flex items-center gap-1 rounded-md border border-border p-1 px-2 text-sm font-medium leading-none',
|
||||
!event.property && 'border-destructive text-destructive'
|
||||
)}
|
||||
>
|
||||
|
||||
@@ -106,7 +106,7 @@ export function ReportEvents() {
|
||||
</div>
|
||||
|
||||
{/* Segment and Filter buttons */}
|
||||
<div className="flex gap-2 p-2 pt-0 text-sm">
|
||||
<div className="flex gap-2 p-2 pt-0 ">
|
||||
<DropdownMenuComposed
|
||||
onChange={(segment) => {
|
||||
dispatch(
|
||||
@@ -148,7 +148,7 @@ export function ReportEvents() {
|
||||
]}
|
||||
label="Segment"
|
||||
>
|
||||
<button className="flex items-center gap-1 rounded-md border border-border bg-card p-1 px-2 text-xs font-medium leading-none">
|
||||
<button className="flex items-center gap-1 rounded-md border border-border bg-card p-1 px-2 text-sm font-medium leading-none">
|
||||
{event.segment === 'user' ? (
|
||||
<>
|
||||
<Users size={12} /> Unique users
|
||||
@@ -216,7 +216,7 @@ export function ReportEvents() {
|
||||
/>
|
||||
</div>
|
||||
<label
|
||||
className="mt-4 flex cursor-pointer select-none items-center gap-2 text-sm font-medium"
|
||||
className="mt-4 flex cursor-pointer select-none items-center gap-2 font-medium"
|
||||
htmlFor="previous"
|
||||
>
|
||||
<Checkbox
|
||||
|
||||
@@ -103,7 +103,7 @@ export function FilterItem({ filter, event }: FilterProps) {
|
||||
<ColorSquare className="bg-emerald-500">
|
||||
<SlidersHorizontal size={10} />
|
||||
</ColorSquare>
|
||||
<div className="flex flex-1 text-sm">
|
||||
<div className="flex flex-1 ">
|
||||
<RenderDots truncate>{filter.name}</RenderDots>
|
||||
</div>
|
||||
<Button variant="ghost" size="sm" onClick={removeFilter}>
|
||||
|
||||
@@ -63,7 +63,7 @@ export function FiltersCombobox({ event }: FiltersComboboxProps) {
|
||||
);
|
||||
}}
|
||||
>
|
||||
<button className="flex items-center gap-1 rounded-md border border-border bg-card p-1 px-2 text-xs font-medium leading-none">
|
||||
<button className="flex items-center gap-1 rounded-md border border-border bg-card p-1 px-2 text-sm font-medium leading-none">
|
||||
<FilterIcon size={12} /> Add filter
|
||||
</button>
|
||||
</Combobox>
|
||||
|
||||
Reference in New Issue
Block a user