mirror of
https://github.com/Portabase/portabase.git
synced 2026-07-14 11:16:13 +02:00
working on statistics page.
This commit is contained in:
@@ -1,15 +0,0 @@
|
|||||||
import {PageParams} from "@/types/next";
|
|
||||||
|
|
||||||
export default async function RoutePage(props: PageParams<{}>) {
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="flex flex-1 flex-col gap-4 p-4">
|
|
||||||
<div className="grid auto-rows-min gap-4 md:grid-cols-3">
|
|
||||||
<div className="aspect-video rounded-xl bg-muted/50"/>
|
|
||||||
<div className="aspect-video rounded-xl bg-muted/50"/>
|
|
||||||
<div className="aspect-video rounded-xl bg-muted/50"/>
|
|
||||||
</div>
|
|
||||||
<div className="min-h-[100vh] flex-1 rounded-xl bg-muted/50 md:min-h-min"/>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,93 @@
|
|||||||
|
import {PageParams} from "@/types/next";
|
||||||
|
import {Page, PageContent, PageHeader, PageTitle} from "@/features/layout/page";
|
||||||
|
import {prisma} from "@/prisma";
|
||||||
|
import {Card, CardContent, CardHeader, CardTitle} from "@/components/ui/card";
|
||||||
|
import {EvolutionLineChart} from "@/components/wrappers/charts/evolution-line-chart";
|
||||||
|
import {PercentageLineChart} from "@/components/wrappers/charts/percentage-line-chart";
|
||||||
|
|
||||||
|
export default async function RoutePage(props: PageParams<{}>) {
|
||||||
|
|
||||||
|
const projectsCount = await prisma.project.count({
|
||||||
|
where: {
|
||||||
|
organization: {
|
||||||
|
slug: "default"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const backupsEvolution = await prisma.backup.findMany({
|
||||||
|
select: {
|
||||||
|
createdAt: true,
|
||||||
|
},
|
||||||
|
orderBy: {
|
||||||
|
createdAt: "asc",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const backupsRate = await prisma.backup.groupBy({
|
||||||
|
by: ['createdAt', 'status'],
|
||||||
|
where: {
|
||||||
|
status: {
|
||||||
|
in: ['success', 'failed'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
_count: {
|
||||||
|
id: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Page>
|
||||||
|
<PageHeader>
|
||||||
|
<PageTitle>
|
||||||
|
Statistics
|
||||||
|
</PageTitle>
|
||||||
|
</PageHeader>
|
||||||
|
<PageContent className="flex flex-col gap-y-4">
|
||||||
|
<div className="flex flex-col md:flex-row gap-4">
|
||||||
|
<Card className="w-full">
|
||||||
|
<CardHeader>
|
||||||
|
<CardTitle>Projects</CardTitle>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent>
|
||||||
|
{projectsCount}
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
<Card className="w-full">
|
||||||
|
<CardHeader>
|
||||||
|
<CardTitle>KPI 2</CardTitle>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
<Card className="w-full">
|
||||||
|
<CardHeader>
|
||||||
|
<CardTitle>KPI 3</CardTitle>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-col md:flex-row gap-4">
|
||||||
|
<Card className="w-full">
|
||||||
|
<CardHeader>
|
||||||
|
<CardTitle>Evolution of the number of backups</CardTitle>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent>
|
||||||
|
<EvolutionLineChart data={backupsEvolution}/>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
<Card className="w-full">
|
||||||
|
<CardHeader>
|
||||||
|
<CardTitle>Success rate of backups</CardTitle>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent>
|
||||||
|
<PercentageLineChart data={backupsRate}/>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
</PageContent>
|
||||||
|
</Page>
|
||||||
|
)
|
||||||
|
}
|
||||||
+2
-2
@@ -55,7 +55,7 @@
|
|||||||
"dockerode": "^4.0.2",
|
"dockerode": "^4.0.2",
|
||||||
"embla-carousel-react": "^8.3.1",
|
"embla-carousel-react": "^8.3.1",
|
||||||
"input-otp": "^1.4.0",
|
"input-otp": "^1.4.0",
|
||||||
"lucide-react": "^0.454.0",
|
"lucide-react": "^0.468.0",
|
||||||
"minio": "^8.0.2",
|
"minio": "^8.0.2",
|
||||||
"next": "15.0.3",
|
"next": "15.0.3",
|
||||||
"next-auth": "^5.0.0-beta.25",
|
"next-auth": "^5.0.0-beta.25",
|
||||||
@@ -70,7 +70,7 @@
|
|||||||
"react-hook-form": "^7.53.1",
|
"react-hook-form": "^7.53.1",
|
||||||
"react-resizable-panels": "^2.1.6",
|
"react-resizable-panels": "^2.1.6",
|
||||||
"react-twc": "^1.4.2",
|
"react-twc": "^1.4.2",
|
||||||
"recharts": "^2.13.3",
|
"recharts": "^2.15.0",
|
||||||
"socket.io": "^4.8.1",
|
"socket.io": "^4.8.1",
|
||||||
"socket.io-client": "^4.8.1",
|
"socket.io-client": "^4.8.1",
|
||||||
"sonner": "^1.6.1",
|
"sonner": "^1.6.1",
|
||||||
|
|||||||
@@ -2,11 +2,6 @@
|
|||||||
|
|
||||||
import * as React from "react"
|
import * as React from "react"
|
||||||
import * as RechartsPrimitive from "recharts"
|
import * as RechartsPrimitive from "recharts"
|
||||||
import {
|
|
||||||
NameType,
|
|
||||||
Payload,
|
|
||||||
ValueType,
|
|
||||||
} from "recharts/types/component/DefaultTooltipContent"
|
|
||||||
|
|
||||||
import { cn } from "@/lib/utils"
|
import { cn } from "@/lib/utils"
|
||||||
|
|
||||||
|
|||||||
@@ -32,8 +32,8 @@ export const SidebarMenuCustom = (props: SidebarMenuCustomProps) => {
|
|||||||
icon: ShieldHalf,
|
icon: ShieldHalf,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Statistic",
|
title: "Statistics",
|
||||||
url: "kpi",
|
url: "statistics",
|
||||||
icon: ChartArea,
|
icon: ChartArea,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -0,0 +1,144 @@
|
|||||||
|
// "use client"
|
||||||
|
//
|
||||||
|
// import {CartesianGrid, Line, LineChart, Tooltip, XAxis, YAxis} from "recharts"
|
||||||
|
// import {ChartConfig, ChartContainer, ChartTooltip, ChartTooltipContent,} from "@/components/ui/chart"
|
||||||
|
// import {humanReadableDate} from "@/utils/date-formatting";
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// export type lineChartProps = {
|
||||||
|
// data: any
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// export function EvolutionLineChart(props: lineChartProps) {
|
||||||
|
//
|
||||||
|
// const {data} = props
|
||||||
|
//
|
||||||
|
// // Process data to calculate cumulative count
|
||||||
|
// const cumulativeData = data.reduce((acc, backup) => {
|
||||||
|
// const date = backup.createdAt.toISOString().split("T")[0]; // Format as YYYY-MM-DD
|
||||||
|
//
|
||||||
|
// // Increment count for the current date or initialize it
|
||||||
|
// if (acc.length && acc[acc.length - 1].date === date) {
|
||||||
|
// acc[acc.length - 1].count += 1;
|
||||||
|
// } else {
|
||||||
|
// const lastCount = acc.length ? acc[acc.length - 1].count : 0;
|
||||||
|
// acc.push({date, count: lastCount + 1});
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// return acc;
|
||||||
|
// }, [] as { date: string; count: number }[]);
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// const chartConfig = {
|
||||||
|
// date: {
|
||||||
|
// label: "Date",
|
||||||
|
// color: "#2563eb",
|
||||||
|
// },
|
||||||
|
// count: {
|
||||||
|
// label: "Number of backups",
|
||||||
|
// color: "#60a5fa",
|
||||||
|
// },
|
||||||
|
// } satisfies ChartConfig
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// return (
|
||||||
|
// <ChartContainer config={chartConfig}>
|
||||||
|
// <LineChart
|
||||||
|
// accessibilityLayer
|
||||||
|
// data={data}
|
||||||
|
// margin={{
|
||||||
|
// left: 12,
|
||||||
|
// right: 12,
|
||||||
|
// }}
|
||||||
|
// >
|
||||||
|
// <CartesianGrid vertical={false}/>
|
||||||
|
// <XAxis
|
||||||
|
// dataKey="date"
|
||||||
|
// tickLine={false}
|
||||||
|
// axisLine={false}
|
||||||
|
// tickMargin={8}
|
||||||
|
// tickFormatter={(value) => humanReadableDate(Date(value)).split(' ')[0]}
|
||||||
|
// />
|
||||||
|
// <YAxis/>
|
||||||
|
// <ChartTooltip
|
||||||
|
// cursor={false}
|
||||||
|
// content={<ChartTooltipContent hideLabel/>}
|
||||||
|
// />
|
||||||
|
// <Line
|
||||||
|
// dataKey="count"
|
||||||
|
// type="linear"
|
||||||
|
// stroke="var(--color-desktop)"
|
||||||
|
// strokeWidth={2}
|
||||||
|
// dot={false}
|
||||||
|
// />
|
||||||
|
// </LineChart>
|
||||||
|
// </ChartContainer>
|
||||||
|
// )
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// export function PercentageLineChart(props: lineChartProps) {
|
||||||
|
//
|
||||||
|
// const {data} = props
|
||||||
|
//
|
||||||
|
// const chartConfig = {
|
||||||
|
// date: {
|
||||||
|
// label: "Date",
|
||||||
|
// color: "#2563eb",
|
||||||
|
// },
|
||||||
|
// successRate: {
|
||||||
|
// label: "Success Rate",
|
||||||
|
// color: "#60a5fa",
|
||||||
|
// },
|
||||||
|
// } satisfies ChartConfig
|
||||||
|
//
|
||||||
|
// const dailyStats = data.reduce((acc, backup) => {
|
||||||
|
// const date = backup.createdAt.toISOString().split("T")[0]; // Format YYYY-MM-DD
|
||||||
|
// const status = backup.status;
|
||||||
|
//
|
||||||
|
// if (!acc[date]) {
|
||||||
|
// acc[date] = {success: 0, failed: 0, total: 0};
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// acc[date][status === "success" ? "success" : "failed"] += backup._count.id;
|
||||||
|
// acc[date].total += backup._count.id;
|
||||||
|
//
|
||||||
|
// return acc;
|
||||||
|
// }, {} as Record<string, { success: number; failed: number; total: number }>);
|
||||||
|
//
|
||||||
|
// // Format data for the chart
|
||||||
|
// const formattedData = Object.entries(dailyStats).map(([date, stats]) => ({
|
||||||
|
// date,
|
||||||
|
// successRate: (stats.success / stats.total) * 100,
|
||||||
|
// }));
|
||||||
|
//
|
||||||
|
// return (
|
||||||
|
// <ChartContainer config={chartConfig}>
|
||||||
|
// <LineChart data={formattedData}>
|
||||||
|
// <CartesianGrid strokeDasharray="3 3"/>
|
||||||
|
// <XAxis dataKey="date"/>
|
||||||
|
// <YAxis domain={[0, 100]} tickFormatter={(tick) => `${tick}%`}/>
|
||||||
|
// {/*<Tooltip formatter={(value: number) => `${value.toFixed(2)}%`}/>*/}
|
||||||
|
// <ChartTooltip
|
||||||
|
// content={<ChartTooltipContent/>}
|
||||||
|
// cursor={false}
|
||||||
|
// defaultIndex={1}
|
||||||
|
// formatter={(value, name) => (
|
||||||
|
// <div className="flex min-w-[130px] items-center text-xs text-muted-foreground">
|
||||||
|
// {chartConfig[name as keyof typeof chartConfig]?.label ||
|
||||||
|
// name}
|
||||||
|
// <div className="ml-auto flex items-baseline gap-0.5 font-mono font-medium tabular-nums text-foreground">
|
||||||
|
// {value}
|
||||||
|
// <span className="font-normal text-muted-foreground">
|
||||||
|
// %
|
||||||
|
// </span>
|
||||||
|
// </div>
|
||||||
|
// </div>
|
||||||
|
// )}
|
||||||
|
// />
|
||||||
|
// <Line type="step" dataKey="successRate" stroke="#8884d8" strokeWidth={2}/>
|
||||||
|
// </LineChart>
|
||||||
|
// </ChartContainer>
|
||||||
|
// )
|
||||||
|
//
|
||||||
|
// }
|
||||||
|
//
|
||||||
@@ -0,0 +1,98 @@
|
|||||||
|
"use client"
|
||||||
|
|
||||||
|
import {ChartConfig, ChartContainer, ChartTooltip, ChartTooltipContent} from "@/components/ui/chart";
|
||||||
|
import {CartesianGrid, Line, LineChart, XAxis, YAxis} from "recharts";
|
||||||
|
import {humanReadableDate} from "@/utils/date-formatting";
|
||||||
|
|
||||||
|
const data = [
|
||||||
|
{date: "2024-12-01", count: 1},
|
||||||
|
{date: "2024-12-02", count: 2},
|
||||||
|
{date: "2024-12-03", count: 4},
|
||||||
|
{date: "2024-12-04", count: 8},
|
||||||
|
{date: "2024-12-05", count: 9},
|
||||||
|
{date: "2024-12-06", count: 9},
|
||||||
|
{date: "2024-12-07", count: 10},
|
||||||
|
{date: "2024-12-08", count: 13},
|
||||||
|
{date: "2024-12-09", count: 15},
|
||||||
|
{date: "2024-12-10", count: 18},
|
||||||
|
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
type Data = {
|
||||||
|
createdAt: Date;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export type evolutionLineChartProps = {
|
||||||
|
data: Data[]
|
||||||
|
}
|
||||||
|
|
||||||
|
export function EvolutionLineChart(props: evolutionLineChartProps) {
|
||||||
|
|
||||||
|
const {data} = props
|
||||||
|
console.log("aaa data", data)
|
||||||
|
|
||||||
|
|
||||||
|
// Process data to calculate cumulative count
|
||||||
|
const cumulativeData = data.reduce((acc, backup) => {
|
||||||
|
const date = backup.createdAt.toISOString().split("T")[0]; // Format as YYYY-MM-DD
|
||||||
|
|
||||||
|
// Increment count for the current date or initialize it
|
||||||
|
if (acc.length && acc[acc.length - 1].date === date) {
|
||||||
|
acc[acc.length - 1].count += 1;
|
||||||
|
} else {
|
||||||
|
const lastCount = acc.length ? acc[acc.length - 1].count : 0;
|
||||||
|
acc.push({date, count: lastCount + 1});
|
||||||
|
}
|
||||||
|
|
||||||
|
return acc;
|
||||||
|
}, [] as { date: string; count: number }[]);
|
||||||
|
|
||||||
|
|
||||||
|
const chartConfig = {
|
||||||
|
date: {
|
||||||
|
label: "Date",
|
||||||
|
color: "#2563eb",
|
||||||
|
},
|
||||||
|
count: {
|
||||||
|
label: "Number of backups",
|
||||||
|
color: "#60a5fa",
|
||||||
|
},
|
||||||
|
} satisfies ChartConfig
|
||||||
|
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ChartContainer config={chartConfig}>
|
||||||
|
<LineChart
|
||||||
|
accessibilityLayer
|
||||||
|
data={data}
|
||||||
|
margin={{
|
||||||
|
left: 12,
|
||||||
|
right: 12,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<CartesianGrid vertical={false}/>
|
||||||
|
<XAxis
|
||||||
|
dataKey="date"
|
||||||
|
tickLine={false}
|
||||||
|
axisLine={false}
|
||||||
|
tickMargin={8}
|
||||||
|
tickFormatter={(value) => humanReadableDate(Date(value)).split(' ')[0]}
|
||||||
|
/>
|
||||||
|
<YAxis/>
|
||||||
|
<ChartTooltip
|
||||||
|
cursor={false}
|
||||||
|
content={<ChartTooltipContent hideLabel/>}
|
||||||
|
/>
|
||||||
|
<Line
|
||||||
|
dataKey="count"
|
||||||
|
type="linear"
|
||||||
|
stroke="var(--color-desktop)"
|
||||||
|
strokeWidth={2}
|
||||||
|
dot={false}
|
||||||
|
/>
|
||||||
|
</LineChart>
|
||||||
|
</ChartContainer>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,85 @@
|
|||||||
|
"use client"
|
||||||
|
|
||||||
|
import {ChartConfig, ChartContainer, ChartTooltip, ChartTooltipContent} from "@/components/ui/chart";
|
||||||
|
import {CartesianGrid, Line, LineChart, XAxis, YAxis} from "recharts";
|
||||||
|
|
||||||
|
type Data = {
|
||||||
|
createdAt: Date;
|
||||||
|
status: "success" | "failed";
|
||||||
|
_count: { id: number };
|
||||||
|
}
|
||||||
|
|
||||||
|
export type percentageLineChartProps = {
|
||||||
|
data: Data[]
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export function PercentageLineChart(props: percentageLineChartProps) {
|
||||||
|
|
||||||
|
const {data} = props
|
||||||
|
|
||||||
|
const chartConfig = {
|
||||||
|
date: {
|
||||||
|
label: "Date",
|
||||||
|
color: "#2563eb",
|
||||||
|
},
|
||||||
|
successRate: {
|
||||||
|
label: "Success Rate",
|
||||||
|
color: "#60a5fa",
|
||||||
|
},
|
||||||
|
} satisfies ChartConfig
|
||||||
|
|
||||||
|
const dailyStats = data.reduce((acc, backup) => {
|
||||||
|
const date = backup.createdAt.toISOString().split("T")[0]; // Format YYYY-MM-DD
|
||||||
|
const status = backup.status;
|
||||||
|
|
||||||
|
if (!acc[date]) {
|
||||||
|
acc[date] = {success: 0, failed: 0, total: 0};
|
||||||
|
}
|
||||||
|
|
||||||
|
acc[date][status === "success" ? "success" : "failed"] += backup._count.id;
|
||||||
|
acc[date].total += backup._count.id;
|
||||||
|
|
||||||
|
return acc;
|
||||||
|
}, {} as Record<string, { success: number; failed: number; total: number }>);
|
||||||
|
|
||||||
|
// Format data for the chart
|
||||||
|
const formattedData = Object.entries(dailyStats).map(([date, stats]) => ({
|
||||||
|
date,
|
||||||
|
successRate: (stats.success / stats.total) * 100,
|
||||||
|
}));
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ChartContainer config={chartConfig}>
|
||||||
|
<LineChart
|
||||||
|
accessibilityLayer
|
||||||
|
data={formattedData}
|
||||||
|
>
|
||||||
|
<CartesianGrid strokeDasharray="3 3"/>
|
||||||
|
<XAxis dataKey="date"/>
|
||||||
|
<YAxis domain={[0, 100]} tickFormatter={(tick) => `${tick}%`}/>
|
||||||
|
<ChartTooltip
|
||||||
|
content={<ChartTooltipContent/>}
|
||||||
|
cursor={false}
|
||||||
|
defaultIndex={1}
|
||||||
|
formatter={(value, name) => (
|
||||||
|
<div className="flex min-w-[130px] items-center text-xs text-muted-foreground">
|
||||||
|
{chartConfig[name as keyof typeof chartConfig]?.label ||
|
||||||
|
name}
|
||||||
|
<div
|
||||||
|
className="ml-auto flex items-baseline gap-0.5 font-mono font-medium tabular-nums text-foreground">
|
||||||
|
{value}
|
||||||
|
<span className="font-normal text-muted-foreground">
|
||||||
|
%
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
<Line type="step" dataKey="successRate" stroke="#8884d8" strokeWidth={2}/>
|
||||||
|
</LineChart>
|
||||||
|
</ChartContainer>
|
||||||
|
)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@@ -10,12 +10,11 @@ import {
|
|||||||
DropdownMenuTrigger
|
DropdownMenuTrigger
|
||||||
} from "@/components/ui/dropdown-menu";
|
} from "@/components/ui/dropdown-menu";
|
||||||
import {Button} from "@/components/ui/button";
|
import {Button} from "@/components/ui/button";
|
||||||
import {Download, MoreHorizontal, Trash2} from "lucide-react";
|
import {MoreHorizontal} from "lucide-react";
|
||||||
import {ReloadIcon} from "@radix-ui/react-icons";
|
import {ReloadIcon} from "@radix-ui/react-icons";
|
||||||
import {Restoration} from "@prisma/client";
|
import {Restoration} from "@prisma/client";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export const restoreColumns: ColumnDef<Restoration>[] = [
|
export const restoreColumns: ColumnDef<Restoration>[] = [
|
||||||
{
|
{
|
||||||
accessorKey: "id",
|
accessorKey: "id",
|
||||||
|
|||||||
@@ -4046,10 +4046,10 @@ lru-cache@^5.1.1:
|
|||||||
dependencies:
|
dependencies:
|
||||||
yallist "^3.0.2"
|
yallist "^3.0.2"
|
||||||
|
|
||||||
lucide-react@^0.454.0:
|
lucide-react@^0.468.0:
|
||||||
version "0.454.0"
|
version "0.468.0"
|
||||||
resolved "https://registry.yarnpkg.com/lucide-react/-/lucide-react-0.454.0.tgz#a81b9c482018720f07ead0503ae502d94d528444"
|
resolved "https://registry.yarnpkg.com/lucide-react/-/lucide-react-0.468.0.tgz#830c1bfd905575ddd23b832baa420c87db166910"
|
||||||
integrity sha512-hw7zMDwykCLnEzgncEEjHeA6+45aeEzRYuKHuyRSOPkhko+J3ySGjGIzu+mmMfDFG1vazHepMaYFYHbTFAZAAQ==
|
integrity sha512-6koYRhnM2N0GGZIdXzSeiNwguv1gt/FAjZOiPl76roBi3xKEXa4WmfpxgQwTTL4KipXjefrnf3oV4IsYhi4JFA==
|
||||||
|
|
||||||
make-dir@^3.1.0:
|
make-dir@^3.1.0:
|
||||||
version "3.1.0"
|
version "3.1.0"
|
||||||
@@ -4862,10 +4862,10 @@ recharts-scale@^0.4.4:
|
|||||||
dependencies:
|
dependencies:
|
||||||
decimal.js-light "^2.4.1"
|
decimal.js-light "^2.4.1"
|
||||||
|
|
||||||
recharts@^2.13.3:
|
recharts@^2.15.0:
|
||||||
version "2.13.3"
|
version "2.15.0"
|
||||||
resolved "https://registry.yarnpkg.com/recharts/-/recharts-2.13.3.tgz#a5ce61e493dff921a14a14a8f42a9f2d2bbefd5a"
|
resolved "https://registry.yarnpkg.com/recharts/-/recharts-2.15.0.tgz#0b77bff57a43885df9769ae649a14cb1a7fe19aa"
|
||||||
integrity sha512-YDZ9dOfK9t3ycwxgKbrnDlRC4BHdjlY73fet3a0C1+qGMjXVZe6+VXmpOIIhzkje5MMEL8AN4hLIe4AMskBzlA==
|
integrity sha512-cIvMxDfpAmqAmVgc4yb7pgm/O1tmmkl/CjrvXuW+62/+7jj/iF9Ykm+hb/UJt42TREHMyd3gb+pkgoa2MxgDIw==
|
||||||
dependencies:
|
dependencies:
|
||||||
clsx "^2.0.0"
|
clsx "^2.0.0"
|
||||||
eventemitter3 "^4.0.1"
|
eventemitter3 "^4.0.1"
|
||||||
|
|||||||
Reference in New Issue
Block a user