add 30 min active user histogram
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
import {
|
||||
createContext,
|
||||
memo,
|
||||
Suspense,
|
||||
useContext,
|
||||
useEffect,
|
||||
useMemo,
|
||||
@@ -12,6 +13,7 @@ import type { IChartSerie } from '@/server/api/routers/chart';
|
||||
import type { IChartInput } from '@/types';
|
||||
|
||||
import { ChartLoading } from './ChartLoading';
|
||||
import { MetricCardLoading } from './MetricCard';
|
||||
|
||||
export interface ChartContextType extends IChartInput {
|
||||
editMode?: boolean;
|
||||
@@ -47,10 +49,10 @@ export function ChartProvider({
|
||||
<ChartContext.Provider
|
||||
value={useMemo(
|
||||
() => ({
|
||||
...props,
|
||||
editMode: editMode ?? false,
|
||||
previous: previous ?? false,
|
||||
hideID: hideID ?? false,
|
||||
...props,
|
||||
}),
|
||||
[editMode, previous, hideID, props]
|
||||
)}
|
||||
@@ -64,20 +66,34 @@ export function withChartProivder<ComponentProps>(
|
||||
WrappedComponent: React.FC<ComponentProps>
|
||||
) {
|
||||
const WithChartProvider = (props: ComponentProps & ChartContextType) => {
|
||||
const [mounted, setMounted] = useState(props.chartType === 'metric');
|
||||
const [mounted, setMounted] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
setMounted(true);
|
||||
}, []);
|
||||
|
||||
if (!mounted) {
|
||||
return <ChartLoading />;
|
||||
return props.chartType === 'metric' ? (
|
||||
<MetricCardLoading />
|
||||
) : (
|
||||
<ChartLoading />
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<ChartProvider {...props}>
|
||||
<WrappedComponent {...props} />
|
||||
</ChartProvider>
|
||||
<Suspense
|
||||
fallback={
|
||||
props.chartType === 'metric' ? (
|
||||
<MetricCardLoading />
|
||||
) : (
|
||||
<ChartLoading />
|
||||
)
|
||||
}
|
||||
>
|
||||
<ChartProvider {...props}>
|
||||
<WrappedComponent {...props} />
|
||||
</ChartProvider>
|
||||
</Suspense>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -23,13 +23,11 @@ export function LazyChart(props: ReportChartProps & ChartContextType) {
|
||||
|
||||
return (
|
||||
<div ref={ref}>
|
||||
<Suspense fallback={<ChartLoading />}>
|
||||
{once.current || inViewport ? (
|
||||
<Chart {...props} editMode={false} />
|
||||
) : (
|
||||
<ChartLoading />
|
||||
)}
|
||||
</Suspense>
|
||||
{once.current || inViewport ? (
|
||||
<Chart {...props} editMode={false} />
|
||||
) : (
|
||||
<ChartLoading />
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ import { getYAxisWidth } from './chart-utils';
|
||||
import { useChartContext } from './ChartProvider';
|
||||
import { ReportChartTooltip } from './ReportChartTooltip';
|
||||
import { ReportTable } from './ReportTable';
|
||||
import { ResponsiveContainer } from './ResponsiveContainer';
|
||||
|
||||
interface ReportAreaChartProps {
|
||||
data: IChartData;
|
||||
@@ -39,83 +40,72 @@ export function ReportAreaChart({
|
||||
|
||||
return (
|
||||
<>
|
||||
<div
|
||||
className={cn(
|
||||
'max-sm:-mx-3 aspect-video w-full max-h-[300px] min-h-[200px]',
|
||||
editMode && 'border border-border bg-white rounded-md p-4'
|
||||
)}
|
||||
>
|
||||
<AutoSizer disableHeight>
|
||||
{({ width }) => (
|
||||
<AreaChart
|
||||
width={width}
|
||||
height={Math.min(Math.max(width * 0.5625, 250), 300)}
|
||||
data={rechartData}
|
||||
>
|
||||
<Tooltip content={<ReportChartTooltip />} />
|
||||
<XAxis
|
||||
axisLine={false}
|
||||
fontSize={12}
|
||||
dataKey="date"
|
||||
tickFormatter={(m: string) => formatDate(m)}
|
||||
tickLine={false}
|
||||
allowDuplicatedCategory={false}
|
||||
/>
|
||||
<YAxis
|
||||
width={getYAxisWidth(data.metrics.max)}
|
||||
fontSize={12}
|
||||
axisLine={false}
|
||||
tickLine={false}
|
||||
allowDecimals={false}
|
||||
/>
|
||||
<ResponsiveContainer>
|
||||
{({ width, height }) => (
|
||||
<AreaChart width={width} height={height} data={rechartData}>
|
||||
<Tooltip content={<ReportChartTooltip />} />
|
||||
<XAxis
|
||||
axisLine={false}
|
||||
fontSize={12}
|
||||
dataKey="date"
|
||||
tickFormatter={(m: string) => formatDate(m)}
|
||||
tickLine={false}
|
||||
allowDuplicatedCategory={false}
|
||||
/>
|
||||
<YAxis
|
||||
width={getYAxisWidth(data.metrics.max)}
|
||||
fontSize={12}
|
||||
axisLine={false}
|
||||
tickLine={false}
|
||||
allowDecimals={false}
|
||||
/>
|
||||
|
||||
{series.map((serie) => {
|
||||
const color = getChartColor(serie.index);
|
||||
return (
|
||||
<React.Fragment key={serie.name}>
|
||||
<defs>
|
||||
<linearGradient
|
||||
id={`color${color}`}
|
||||
x1="0"
|
||||
y1="0"
|
||||
x2="0"
|
||||
y2="1"
|
||||
>
|
||||
<stop
|
||||
offset="0%"
|
||||
stopColor={color}
|
||||
stopOpacity={0.8}
|
||||
></stop>
|
||||
<stop
|
||||
offset="100%"
|
||||
stopColor={color}
|
||||
stopOpacity={0.1}
|
||||
></stop>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<Area
|
||||
key={serie.name}
|
||||
type={lineType}
|
||||
isAnimationActive={true}
|
||||
strokeWidth={2}
|
||||
dataKey={`${serie.index}:count`}
|
||||
stroke={color}
|
||||
fill={`url(#color${color})`}
|
||||
stackId={'1'}
|
||||
fillOpacity={1}
|
||||
/>
|
||||
</React.Fragment>
|
||||
);
|
||||
})}
|
||||
<CartesianGrid
|
||||
strokeDasharray="3 3"
|
||||
horizontal={true}
|
||||
vertical={false}
|
||||
/>
|
||||
</AreaChart>
|
||||
)}
|
||||
</AutoSizer>
|
||||
</div>
|
||||
{series.map((serie) => {
|
||||
const color = getChartColor(serie.index);
|
||||
return (
|
||||
<React.Fragment key={serie.name}>
|
||||
<defs>
|
||||
<linearGradient
|
||||
id={`color${color}`}
|
||||
x1="0"
|
||||
y1="0"
|
||||
x2="0"
|
||||
y2="1"
|
||||
>
|
||||
<stop
|
||||
offset="0%"
|
||||
stopColor={color}
|
||||
stopOpacity={0.8}
|
||||
></stop>
|
||||
<stop
|
||||
offset="100%"
|
||||
stopColor={color}
|
||||
stopOpacity={0.1}
|
||||
></stop>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<Area
|
||||
key={serie.name}
|
||||
type={lineType}
|
||||
isAnimationActive={true}
|
||||
strokeWidth={2}
|
||||
dataKey={`${serie.index}:count`}
|
||||
stroke={color}
|
||||
fill={`url(#color${color})`}
|
||||
stackId={'1'}
|
||||
fillOpacity={1}
|
||||
/>
|
||||
</React.Fragment>
|
||||
);
|
||||
})}
|
||||
<CartesianGrid
|
||||
strokeDasharray="3 3"
|
||||
horizontal={true}
|
||||
vertical={false}
|
||||
/>
|
||||
</AreaChart>
|
||||
)}
|
||||
</ResponsiveContainer>
|
||||
{editMode && (
|
||||
<ReportTable
|
||||
data={data}
|
||||
|
||||
@@ -19,9 +19,8 @@ export function ReportChartTooltip({
|
||||
active,
|
||||
payload,
|
||||
}: ReportLineChartTooltipProps) {
|
||||
const { unit } = useChartContext();
|
||||
const { unit, interval } = useChartContext();
|
||||
const getLabel = useMappings();
|
||||
const interval = useSelector((state) => state.report.interval);
|
||||
const formatDate = useFormatDateInterval(interval);
|
||||
const number = useNumber();
|
||||
if (!active || !payload) {
|
||||
|
||||
@@ -13,6 +13,7 @@ import { getYAxisWidth } from './chart-utils';
|
||||
import { useChartContext } from './ChartProvider';
|
||||
import { ReportChartTooltip } from './ReportChartTooltip';
|
||||
import { ReportTable } from './ReportTable';
|
||||
import { ResponsiveContainer } from './ResponsiveContainer';
|
||||
|
||||
interface ReportHistogramChartProps {
|
||||
data: IChartData;
|
||||
@@ -43,61 +44,52 @@ export function ReportHistogramChart({
|
||||
|
||||
return (
|
||||
<>
|
||||
<div
|
||||
className={cn(
|
||||
'max-sm:-mx-3 aspect-video w-full max-h-[300px] min-h-[200px]',
|
||||
editMode && 'border border-border bg-white rounded-md p-4'
|
||||
)}
|
||||
>
|
||||
<AutoSizer disableHeight>
|
||||
{({ width }) => (
|
||||
<BarChart
|
||||
width={width}
|
||||
height={Math.min(Math.max(width * 0.5625, 250), 300)}
|
||||
data={rechartData}
|
||||
>
|
||||
<CartesianGrid strokeDasharray="3 3" vertical={false} />
|
||||
<Tooltip content={<ReportChartTooltip />} cursor={<BarHover />} />
|
||||
<XAxis
|
||||
fontSize={12}
|
||||
dataKey="date"
|
||||
tickFormatter={formatDate}
|
||||
tickLine={false}
|
||||
axisLine={false}
|
||||
/>
|
||||
<YAxis
|
||||
fontSize={12}
|
||||
axisLine={false}
|
||||
tickLine={false}
|
||||
width={getYAxisWidth(data.metrics.max)}
|
||||
/>
|
||||
{series.map((serie) => {
|
||||
return (
|
||||
<React.Fragment key={serie.name}>
|
||||
{previous && (
|
||||
<Bar
|
||||
key={`${serie.name}:prev`}
|
||||
name={`${serie.name}:prev`}
|
||||
dataKey={`${serie.index}:prev:count`}
|
||||
fill={getChartColor(serie.index)}
|
||||
fillOpacity={0.2}
|
||||
radius={8}
|
||||
/>
|
||||
)}
|
||||
<ResponsiveContainer>
|
||||
{({ width, height }) => (
|
||||
<BarChart width={width} height={height} data={rechartData}>
|
||||
<CartesianGrid strokeDasharray="3 3" vertical={false} />
|
||||
<Tooltip content={<ReportChartTooltip />} cursor={<BarHover />} />
|
||||
<XAxis
|
||||
fontSize={12}
|
||||
dataKey="date"
|
||||
tickFormatter={formatDate}
|
||||
tickLine={false}
|
||||
axisLine={false}
|
||||
/>
|
||||
<YAxis
|
||||
fontSize={12}
|
||||
axisLine={false}
|
||||
tickLine={false}
|
||||
width={getYAxisWidth(data.metrics.max)}
|
||||
allowDecimals={false}
|
||||
domain={[0, data.metrics.max]}
|
||||
/>
|
||||
{series.map((serie) => {
|
||||
return (
|
||||
<React.Fragment key={serie.name}>
|
||||
{previous && (
|
||||
<Bar
|
||||
key={serie.name}
|
||||
name={serie.name}
|
||||
dataKey={`${serie.index}:count`}
|
||||
key={`${serie.name}:prev`}
|
||||
name={`${serie.name}:prev`}
|
||||
dataKey={`${serie.index}:prev:count`}
|
||||
fill={getChartColor(serie.index)}
|
||||
fillOpacity={0.2}
|
||||
radius={8}
|
||||
/>
|
||||
</React.Fragment>
|
||||
);
|
||||
})}
|
||||
</BarChart>
|
||||
)}
|
||||
</AutoSizer>
|
||||
</div>
|
||||
)}
|
||||
<Bar
|
||||
key={serie.name}
|
||||
name={serie.name}
|
||||
dataKey={`${serie.index}:count`}
|
||||
fill={getChartColor(serie.index)}
|
||||
radius={8}
|
||||
/>
|
||||
</React.Fragment>
|
||||
);
|
||||
})}
|
||||
</BarChart>
|
||||
)}
|
||||
</ResponsiveContainer>
|
||||
{editMode && (
|
||||
<ReportTable
|
||||
data={data}
|
||||
|
||||
@@ -22,6 +22,7 @@ import { getYAxisWidth } from './chart-utils';
|
||||
import { useChartContext } from './ChartProvider';
|
||||
import { ReportChartTooltip } from './ReportChartTooltip';
|
||||
import { ReportTable } from './ReportTable';
|
||||
import { ResponsiveContainer } from './ResponsiveContainer';
|
||||
|
||||
interface ReportLineChartProps {
|
||||
data: IChartData;
|
||||
@@ -41,72 +42,61 @@ export function ReportLineChart({
|
||||
|
||||
return (
|
||||
<>
|
||||
<div
|
||||
className={cn(
|
||||
'max-sm:-mx-3 aspect-video w-full max-h-[300px] min-h-[200px]',
|
||||
editMode && 'border border-border bg-white rounded-md p-4'
|
||||
)}
|
||||
>
|
||||
<AutoSizer disableHeight>
|
||||
{({ width }) => (
|
||||
<LineChart
|
||||
width={width}
|
||||
height={Math.min(Math.max(width * 0.5625, 250), 300)}
|
||||
data={rechartData}
|
||||
>
|
||||
<CartesianGrid
|
||||
strokeDasharray="3 3"
|
||||
horizontal={true}
|
||||
vertical={false}
|
||||
/>
|
||||
<YAxis
|
||||
width={getYAxisWidth(data.metrics.max)}
|
||||
fontSize={12}
|
||||
axisLine={false}
|
||||
tickLine={false}
|
||||
allowDecimals={false}
|
||||
/>
|
||||
<Tooltip content={<ReportChartTooltip />} />
|
||||
<XAxis
|
||||
axisLine={false}
|
||||
fontSize={12}
|
||||
dataKey="date"
|
||||
tickFormatter={(m: string) => formatDate(m)}
|
||||
tickLine={false}
|
||||
allowDuplicatedCategory={false}
|
||||
/>
|
||||
{series.map((serie) => {
|
||||
return (
|
||||
<React.Fragment key={serie.name}>
|
||||
<ResponsiveContainer>
|
||||
{({ width, height }) => (
|
||||
<LineChart width={width} height={height} data={rechartData}>
|
||||
<CartesianGrid
|
||||
strokeDasharray="3 3"
|
||||
horizontal={true}
|
||||
vertical={false}
|
||||
/>
|
||||
<YAxis
|
||||
width={getYAxisWidth(data.metrics.max)}
|
||||
fontSize={12}
|
||||
axisLine={false}
|
||||
tickLine={false}
|
||||
allowDecimals={false}
|
||||
/>
|
||||
<Tooltip content={<ReportChartTooltip />} />
|
||||
<XAxis
|
||||
axisLine={false}
|
||||
fontSize={12}
|
||||
dataKey="date"
|
||||
tickFormatter={(m: string) => formatDate(m)}
|
||||
tickLine={false}
|
||||
allowDuplicatedCategory={false}
|
||||
/>
|
||||
{series.map((serie) => {
|
||||
return (
|
||||
<React.Fragment key={serie.name}>
|
||||
<Line
|
||||
type={lineType}
|
||||
key={serie.name}
|
||||
name={serie.name}
|
||||
isAnimationActive={true}
|
||||
strokeWidth={2}
|
||||
dataKey={`${serie.index}:count`}
|
||||
stroke={getChartColor(serie.index)}
|
||||
/>
|
||||
{previous && (
|
||||
<Line
|
||||
type={lineType}
|
||||
key={serie.name}
|
||||
name={serie.name}
|
||||
key={`${serie.name}:prev`}
|
||||
name={`${serie.name}:prev`}
|
||||
isAnimationActive={true}
|
||||
strokeWidth={2}
|
||||
dataKey={`${serie.index}:count`}
|
||||
strokeWidth={1}
|
||||
dot={false}
|
||||
strokeDasharray={'6 6'}
|
||||
dataKey={`${serie.index}:prev:count`}
|
||||
stroke={getChartColor(serie.index)}
|
||||
/>
|
||||
{previous && (
|
||||
<Line
|
||||
type={lineType}
|
||||
key={`${serie.name}:prev`}
|
||||
name={`${serie.name}:prev`}
|
||||
isAnimationActive={true}
|
||||
strokeWidth={1}
|
||||
dot={false}
|
||||
strokeDasharray={'6 6'}
|
||||
dataKey={`${serie.index}:prev:count`}
|
||||
stroke={getChartColor(serie.index)}
|
||||
/>
|
||||
)}
|
||||
</React.Fragment>
|
||||
);
|
||||
})}
|
||||
</LineChart>
|
||||
)}
|
||||
</AutoSizer>
|
||||
</div>
|
||||
)}
|
||||
</React.Fragment>
|
||||
);
|
||||
})}
|
||||
</LineChart>
|
||||
)}
|
||||
</ResponsiveContainer>
|
||||
{editMode && (
|
||||
<ReportTable
|
||||
data={data}
|
||||
|
||||
39
apps/web/src/components/report/chart/ResponsiveContainer.tsx
Normal file
39
apps/web/src/components/report/chart/ResponsiveContainer.tsx
Normal file
@@ -0,0 +1,39 @@
|
||||
import { cn } from '@/utils/cn';
|
||||
import AutoSizer from 'react-virtualized-auto-sizer';
|
||||
|
||||
import { useChartContext } from './ChartProvider';
|
||||
|
||||
interface ResponsiveContainerProps {
|
||||
children: (props: { width: number; height: number }) => React.ReactNode;
|
||||
}
|
||||
|
||||
export function ResponsiveContainer({ children }: ResponsiveContainerProps) {
|
||||
const { editMode } = useChartContext();
|
||||
const maxHeight = 300;
|
||||
const minHeight = 200;
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
maxHeight,
|
||||
minHeight,
|
||||
}}
|
||||
className={cn(
|
||||
'max-sm:-mx-3 aspect-video w-full',
|
||||
editMode && 'border border-border bg-white rounded-md p-4'
|
||||
)}
|
||||
>
|
||||
<AutoSizer disableHeight>
|
||||
{({ width }) =>
|
||||
children({
|
||||
width,
|
||||
height: Math.min(
|
||||
Math.max(width * 0.5625, minHeight),
|
||||
// we add p-4 (16px) padding in edit mode
|
||||
editMode ? maxHeight - 16 : maxHeight
|
||||
),
|
||||
})
|
||||
}
|
||||
</AutoSizer>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -60,9 +60,9 @@ export function SerieIcon({ name, ...props }: SerieIconProps) {
|
||||
)) as LucideIcon;
|
||||
}
|
||||
|
||||
return (
|
||||
return Icon ? (
|
||||
<div className="w-4 h-4 flex-shrink-0 relative [&_a]:!w-4 [&_a]:!h-4 [&_svg]:!rounded">
|
||||
{Icon ? <Icon size={16} {...props} /> : null}
|
||||
<Icon size={16} {...props} />
|
||||
</div>
|
||||
);
|
||||
) : null;
|
||||
}
|
||||
|
||||
@@ -20,80 +20,78 @@ export type ReportChartProps = IChartInput & {
|
||||
initialData?: RouterOutputs['chart']['chart'];
|
||||
};
|
||||
|
||||
export const Chart = memo(
|
||||
withChartProivder(function Chart({
|
||||
interval,
|
||||
events,
|
||||
breakdowns,
|
||||
chartType,
|
||||
name,
|
||||
range,
|
||||
lineType,
|
||||
previous,
|
||||
formula,
|
||||
unit,
|
||||
metric,
|
||||
projectId,
|
||||
}: ReportChartProps) {
|
||||
const [data] = api.chart.chart.useSuspenseQuery(
|
||||
{
|
||||
// dont send lineType since it does not need to be sent
|
||||
lineType: 'monotone',
|
||||
interval,
|
||||
chartType,
|
||||
events,
|
||||
breakdowns,
|
||||
name,
|
||||
range,
|
||||
startDate: null,
|
||||
endDate: null,
|
||||
projectId,
|
||||
previous,
|
||||
formula,
|
||||
unit,
|
||||
metric,
|
||||
},
|
||||
{
|
||||
keepPreviousData: true,
|
||||
}
|
||||
export const Chart = withChartProivder(function Chart({
|
||||
interval,
|
||||
events,
|
||||
breakdowns,
|
||||
chartType,
|
||||
name,
|
||||
range,
|
||||
lineType,
|
||||
previous,
|
||||
formula,
|
||||
unit,
|
||||
metric,
|
||||
projectId,
|
||||
}: ReportChartProps) {
|
||||
const [data] = api.chart.chart.useSuspenseQuery(
|
||||
{
|
||||
// dont send lineType since it does not need to be sent
|
||||
lineType: 'monotone',
|
||||
interval,
|
||||
chartType,
|
||||
events,
|
||||
breakdowns,
|
||||
name,
|
||||
range,
|
||||
startDate: null,
|
||||
endDate: null,
|
||||
projectId,
|
||||
previous,
|
||||
formula,
|
||||
unit,
|
||||
metric,
|
||||
},
|
||||
{
|
||||
keepPreviousData: true,
|
||||
}
|
||||
);
|
||||
|
||||
if (data.series.length === 0) {
|
||||
return <ChartEmpty />;
|
||||
}
|
||||
|
||||
if (chartType === 'map') {
|
||||
return <ReportMapChart data={data} />;
|
||||
}
|
||||
|
||||
if (chartType === 'histogram') {
|
||||
return <ReportHistogramChart interval={interval} data={data} />;
|
||||
}
|
||||
|
||||
if (chartType === 'bar') {
|
||||
return <ReportBarChart data={data} />;
|
||||
}
|
||||
|
||||
if (chartType === 'metric') {
|
||||
return <ReportMetricChart data={data} />;
|
||||
}
|
||||
|
||||
if (chartType === 'pie') {
|
||||
return <ReportPieChart data={data} />;
|
||||
}
|
||||
|
||||
if (chartType === 'linear') {
|
||||
return (
|
||||
<ReportLineChart lineType={lineType} interval={interval} data={data} />
|
||||
);
|
||||
}
|
||||
|
||||
if (data.series.length === 0) {
|
||||
return <ChartEmpty />;
|
||||
}
|
||||
if (chartType === 'area') {
|
||||
return (
|
||||
<ReportAreaChart lineType={lineType} interval={interval} data={data} />
|
||||
);
|
||||
}
|
||||
|
||||
if (chartType === 'map') {
|
||||
return <ReportMapChart data={data} />;
|
||||
}
|
||||
|
||||
if (chartType === 'histogram') {
|
||||
return <ReportHistogramChart interval={interval} data={data} />;
|
||||
}
|
||||
|
||||
if (chartType === 'bar') {
|
||||
return <ReportBarChart data={data} />;
|
||||
}
|
||||
|
||||
if (chartType === 'metric') {
|
||||
return <ReportMetricChart data={data} />;
|
||||
}
|
||||
|
||||
if (chartType === 'pie') {
|
||||
return <ReportPieChart data={data} />;
|
||||
}
|
||||
|
||||
if (chartType === 'linear') {
|
||||
return (
|
||||
<ReportLineChart lineType={lineType} interval={interval} data={data} />
|
||||
);
|
||||
}
|
||||
|
||||
if (chartType === 'area') {
|
||||
return (
|
||||
<ReportAreaChart lineType={lineType} interval={interval} data={data} />
|
||||
);
|
||||
}
|
||||
|
||||
return <p>Unknown chart type</p>;
|
||||
})
|
||||
);
|
||||
return <p>Unknown chart type</p>;
|
||||
});
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { api } from '@/app/_trpc/client';
|
||||
import { Combobox } from '@/components/ui/combobox';
|
||||
import { useAppParams } from '@/hooks/useAppParams';
|
||||
import { useDispatch } from '@/redux';
|
||||
import type { IChartEvent } from '@/types';
|
||||
import { cn } from '@/utils/cn';
|
||||
import { DatabaseIcon } from 'lucide-react';
|
||||
|
||||
import { useChartContext } from '../chart/ChartProvider';
|
||||
import { changeEvent } from '../reportSlice';
|
||||
|
||||
interface EventPropertiesComboboxProps {
|
||||
@@ -16,7 +16,7 @@ export function EventPropertiesCombobox({
|
||||
event,
|
||||
}: EventPropertiesComboboxProps) {
|
||||
const dispatch = useDispatch();
|
||||
const { projectId } = useChartContext();
|
||||
const { projectId } = useAppParams();
|
||||
|
||||
const query = api.chart.properties.useQuery(
|
||||
{
|
||||
|
||||
@@ -3,17 +3,17 @@
|
||||
import { api } from '@/app/_trpc/client';
|
||||
import { ColorSquare } from '@/components/ColorSquare';
|
||||
import { Combobox } from '@/components/ui/combobox';
|
||||
import { useAppParams } from '@/hooks/useAppParams';
|
||||
import { useDispatch, useSelector } from '@/redux';
|
||||
import type { IChartBreakdown } from '@/types';
|
||||
import { SplitIcon } from 'lucide-react';
|
||||
|
||||
import { useChartContext } from '../chart/ChartProvider';
|
||||
import { addBreakdown, changeBreakdown, removeBreakdown } from '../reportSlice';
|
||||
import { ReportBreakdownMore } from './ReportBreakdownMore';
|
||||
import type { ReportEventMoreProps } from './ReportEventMore';
|
||||
|
||||
export function ReportBreakdowns() {
|
||||
const { projectId } = useChartContext();
|
||||
const { projectId } = useAppParams();
|
||||
const selectedBreakdowns = useSelector((state) => state.report.breakdowns);
|
||||
const dispatch = useDispatch();
|
||||
const propertiesQuery = api.chart.properties.useQuery({
|
||||
|
||||
@@ -6,12 +6,12 @@ import { Dropdown } from '@/components/Dropdown';
|
||||
import { Checkbox } from '@/components/ui/checkbox';
|
||||
import { Combobox } from '@/components/ui/combobox';
|
||||
import { Input } from '@/components/ui/input';
|
||||
import { useAppParams } from '@/hooks/useAppParams';
|
||||
import { useDebounceFn } from '@/hooks/useDebounceFn';
|
||||
import { useDispatch, useSelector } from '@/redux';
|
||||
import type { IChartEvent } from '@/types';
|
||||
import { GanttChart, GanttChartIcon, Users } from 'lucide-react';
|
||||
|
||||
import { useChartContext } from '../chart/ChartProvider';
|
||||
import {
|
||||
addEvent,
|
||||
changeEvent,
|
||||
@@ -28,7 +28,8 @@ export function ReportEvents() {
|
||||
const previous = useSelector((state) => state.report.previous);
|
||||
const selectedEvents = useSelector((state) => state.report.events);
|
||||
const dispatch = useDispatch();
|
||||
const { projectId } = useChartContext();
|
||||
const { projectId } = useAppParams();
|
||||
|
||||
const eventsQuery = api.chart.events.useQuery({
|
||||
projectId,
|
||||
});
|
||||
|
||||
@@ -4,6 +4,7 @@ import { Dropdown } from '@/components/Dropdown';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { ComboboxAdvanced } from '@/components/ui/combobox-advanced';
|
||||
import { RenderDots } from '@/components/ui/RenderDots';
|
||||
import { useAppParams } from '@/hooks/useAppParams';
|
||||
import { useMappings } from '@/hooks/useMappings';
|
||||
import { useDispatch } from '@/redux';
|
||||
import type {
|
||||
@@ -14,7 +15,6 @@ import type {
|
||||
import { operators } from '@/utils/constants';
|
||||
import { SlidersHorizontal, Trash } from 'lucide-react';
|
||||
|
||||
import { useChartContext } from '../../chart/ChartProvider';
|
||||
import { changeEvent } from '../../reportSlice';
|
||||
|
||||
interface FilterProps {
|
||||
@@ -23,7 +23,7 @@ interface FilterProps {
|
||||
}
|
||||
|
||||
export function FilterItem({ filter, event }: FilterProps) {
|
||||
const { projectId } = useChartContext();
|
||||
const { projectId } = useAppParams();
|
||||
const getLabel = useMappings();
|
||||
const dispatch = useDispatch();
|
||||
const potentialValues = api.chart.values.useQuery({
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { api } from '@/app/_trpc/client';
|
||||
import { Combobox } from '@/components/ui/combobox';
|
||||
import { useAppParams } from '@/hooks/useAppParams';
|
||||
import { useDispatch } from '@/redux';
|
||||
import type { IChartEvent } from '@/types';
|
||||
import { FilterIcon } from 'lucide-react';
|
||||
|
||||
import { useChartContext } from '../../chart/ChartProvider';
|
||||
import { changeEvent } from '../../reportSlice';
|
||||
|
||||
interface FiltersComboboxProps {
|
||||
@@ -13,7 +13,7 @@ interface FiltersComboboxProps {
|
||||
|
||||
export function FiltersCombobox({ event }: FiltersComboboxProps) {
|
||||
const dispatch = useDispatch();
|
||||
const { projectId } = useChartContext();
|
||||
const { projectId } = useAppParams();
|
||||
|
||||
const query = api.chart.properties.useQuery(
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user