← marzneshin
/
dashboard/src/modules/users/components/widgets/user-nodes-usage-widget/index.tsx
/
blame
https://dev.kronoz.win/r/marzneshin.git
| 1 | e6e6467 | Dawsh | 2y ago | import { FC } from 'react'; |
| 2 | e6e6467 | Dawsh | 2y ago | import { useTranslation } from 'react-i18next'; |
| 3 | e6e6467 | Dawsh | 2y ago | import { |
| 4 | e6e6467 | Dawsh | 2y ago | SectionWidget, |
| 5 | e6e6467 | Dawsh | 2y ago | ChartLegendContent, |
| 6 | e6e6467 | Dawsh | 2y ago | ChartContainer, |
| 7 | e6e6467 | Dawsh | 2y ago | Awaiting, |
| 8 | e6e6467 | Dawsh | 2y ago | ChartLegend, |
| 9 | e6e6467 | Dawsh | 2y ago | ChartTooltip, |
| 10 | e6e6467 | Dawsh | 2y ago | ChartTooltipContent, |
| 11 | e6e6467 | Dawsh | 2y ago | } from "@marzneshin/components"; |
| 12 | e6e6467 | Dawsh | 2y ago | import { Area, AreaChart, CartesianGrid, YAxis, XAxis } from "recharts" |
| 13 | e6e6467 | Dawsh | 2y ago | import { useState } from "react"; |
| 14 | 6a4fee1 | Dawsh | 2y ago | import { UserNodesUsageWidgetProps } from "./types"; |
| 15 | 6a4fee1 | Dawsh | 2y ago | import { dateXAxisTicks, useFromNowInterval, SelectDateView, ChartDateInterval } from "@marzneshin/common/stats-charts"; |
| 16 | 6a4fee1 | Dawsh | 2y ago | import { useChartConfig, useTransformData } from "./hooks"; |
| 17 | e6e6467 | Dawsh | 2y ago | import { format as formatByte } from '@chbphone55/pretty-bytes'; |
| 18 | e6e6467 | Dawsh | 2y ago | import { useUserNodeUsagesQuery } from "@marzneshin/modules/users"; |
| 19 | e6e6467 | Dawsh | 2y ago | import { UsageGraphSkeleton } from "./skeleton" |
| 20 | e6e6467 | Dawsh | 2y ago | |
| 21 | e6e6467 | Dawsh | 2y ago | export const UserNodesUsageWidget: FC<UserNodesUsageWidgetProps> = ({ |
| 22 | e6e6467 | Dawsh | 2y ago | user, |
| 23 | e6e6467 | Dawsh | 2y ago | }) => { |
| 24 | e6e6467 | Dawsh | 2y ago | const { t } = useTranslation(); |
| 25 | e6e6467 | Dawsh | 2y ago | const [timeRange, setTimeRange] = useState("1d") |
| 26 | e6e6467 | Dawsh | 2y ago | const { start, end } = useFromNowInterval(timeRange as ChartDateInterval); |
| 27 | e6e6467 | Dawsh | 2y ago | const { data, isPending } = useUserNodeUsagesQuery({ username: user.username, start, end }) |
| 28 | e6e6467 | Dawsh | 2y ago | const chartData = useTransformData(data); |
| 29 | e6e6467 | Dawsh | 2y ago | const config = useChartConfig(data); |
| 30 | b15de9e | Erfan | 2y ago | const [totalAmount, totalMetric] = formatByte(data.total); |
| 31 | e6e6467 | Dawsh | 2y ago | |
| 32 | e6e6467 | Dawsh | 2y ago | return ( |
| 33 | e6e6467 | Dawsh | 2y ago | <Awaiting |
| 34 | e6e6467 | Dawsh | 2y ago | Component={ |
| 35 | e6e6467 | Dawsh | 2y ago | <SectionWidget |
| 36 | b15de9e | Erfan | 2y ago | title={<div className="hstack justify-between w-full">{t("page.users.settings.nodes-usage.title")}</div>} |
| 37 | e6e6467 | Dawsh | 2y ago | description={t("page.users.settings.nodes-usage.desc")} |
| 38 | b15de9e | Erfan | 2y ago | options={ |
| 39 | b15de9e | Erfan | 2y ago | <div className="vstack justify-end w-full"> |
| 40 | b15de9e | Erfan | 2y ago | <span className="text-lg leading-none sm:text-2xl w-full"> |
| 41 | b15de9e | Erfan | 2y ago | {totalAmount} {totalMetric} |
| 42 | b15de9e | Erfan | 2y ago | </span> |
| 43 | b15de9e | Erfan | 2y ago | <span className="text-sm flex justify-end text-muted-foreground w-full"> |
| 44 | b15de9e | Erfan | 2y ago | Total |
| 45 | b15de9e | Erfan | 2y ago | </span> |
| 46 | b15de9e | Erfan | 2y ago | </div> |
| 47 | b15de9e | Erfan | 2y ago | } |
| 48 | b15de9e | Erfan | 2y ago | footer={ |
| 49 | b15de9e | Erfan | 2y ago | <SelectDateView timeRange={timeRange} setTimeRange={setTimeRange} /> |
| 50 | b15de9e | Erfan | 2y ago | } |
| 51 | e6e6467 | Dawsh | 2y ago | > |
| 52 | e6e6467 | Dawsh | 2y ago | <ChartContainer |
| 53 | e6e6467 | Dawsh | 2y ago | className="aspect-auto h-[320px] w-full" |
| 54 | e6e6467 | Dawsh | 2y ago | config={config}> |
| 55 | e6e6467 | Dawsh | 2y ago | <AreaChart |
| 56 | e6e6467 | Dawsh | 2y ago | accessibilityLayer |
| 57 | e6e6467 | Dawsh | 2y ago | data={chartData} |
| 58 | e6e6467 | Dawsh | 2y ago | margin={{ |
| 59 | e6e6467 | Dawsh | 2y ago | left: 13, |
| 60 | e6e6467 | Dawsh | 2y ago | top: 13, |
| 61 | e6e6467 | Dawsh | 2y ago | right: 12, |
| 62 | e6e6467 | Dawsh | 2y ago | }} |
| 63 | e6e6467 | Dawsh | 2y ago | > |
| 64 | e6e6467 | Dawsh | 2y ago | <CartesianGrid vertical={false} /> |
| 65 | e6e6467 | Dawsh | 2y ago | <YAxis |
| 66 | e6e6467 | Dawsh | 2y ago | tickLine={false} |
| 67 | e6e6467 | Dawsh | 2y ago | axisLine={false} |
| 68 | e6e6467 | Dawsh | 2y ago | tickMargin={8} |
| 69 | e6e6467 | Dawsh | 2y ago | tickFormatter={(value) => { |
| 70 | e6e6467 | Dawsh | 2y ago | const [amount, metric] = formatByte(value) |
| 71 | e6e6467 | Dawsh | 2y ago | return `${amount} ${metric}` |
| 72 | e6e6467 | Dawsh | 2y ago | }} |
| 73 | e6e6467 | Dawsh | 2y ago | /> |
| 74 | e6e6467 | Dawsh | 2y ago | <XAxis |
| 75 | e6e6467 | Dawsh | 2y ago | dataKey="datetime" |
| 76 | e6e6467 | Dawsh | 2y ago | tickLine={false} |
| 77 | e6e6467 | Dawsh | 2y ago | axisLine={false} |
| 78 | e6e6467 | Dawsh | 2y ago | tickMargin={8} |
| 79 | 6a4fee1 | Dawsh | 2y ago | tickFormatter={(value) => dateXAxisTicks(value, timeRange as ChartDateInterval)} |
| 80 | e6e6467 | Dawsh | 2y ago | /> |
| 81 | e6e6467 | Dawsh | 2y ago | <ChartTooltip |
| 82 | e6e6467 | Dawsh | 2y ago | cursor={false} |
| 83 | e6e6467 | Dawsh | 2y ago | content={ |
| 84 | e6e6467 | Dawsh | 2y ago | <ChartTooltipContent |
| 85 | e6e6467 | Dawsh | 2y ago | indicator='line' |
| 86 | e6e6467 | Dawsh | 2y ago | labelFormatter={(value) => { |
| 87 | e6e6467 | Dawsh | 2y ago | return new Date(value).toLocaleDateString("en-US", { |
| 88 | e6e6467 | Dawsh | 2y ago | month: "short", |
| 89 | e6e6467 | Dawsh | 2y ago | day: "numeric", |
| 90 | e6e6467 | Dawsh | 2y ago | year: "numeric", |
| 91 | e6e6467 | Dawsh | 2y ago | hour: "numeric" |
| 92 | e6e6467 | Dawsh | 2y ago | }) |
| 93 | e6e6467 | Dawsh | 2y ago | }} |
| 94 | e6e6467 | Dawsh | 2y ago | valueFormatter={(value) => { |
| 95 | e6e6467 | Dawsh | 2y ago | const [amount, metric] = formatByte(value as number) |
| 96 | e6e6467 | Dawsh | 2y ago | return `${amount} ${metric}` |
| 97 | e6e6467 | Dawsh | 2y ago | }} |
| 98 | e6e6467 | Dawsh | 2y ago | /> |
| 99 | e6e6467 | Dawsh | 2y ago | } |
| 100 | e6e6467 | Dawsh | 2y ago | /> |
| 101 | e6e6467 | Dawsh | 2y ago | <defs> |
| 102 | e6e6467 | Dawsh | 2y ago | {data.node_usages.map(node => |
| 103 | e6e6467 | Dawsh | 2y ago | <linearGradient key={node.node_name} id={node.node_name} x1="0" y1="0" x2="0" y2="1"> |
| 104 | e6e6467 | Dawsh | 2y ago | <stop |
| 105 | e6e6467 | Dawsh | 2y ago | offset="5%" |
| 106 | e6e6467 | Dawsh | 2y ago | stopColor={config[node.node_name].color} |
| 107 | e6e6467 | Dawsh | 2y ago | stopOpacity={0.1} |
| 108 | e6e6467 | Dawsh | 2y ago | /> |
| 109 | e6e6467 | Dawsh | 2y ago | <stop |
| 110 | e6e6467 | Dawsh | 2y ago | offset="95%" |
| 111 | e6e6467 | Dawsh | 2y ago | stopColor={config[node.node_name].color} |
| 112 | e6e6467 | Dawsh | 2y ago | stopOpacity={0.8} |
| 113 | e6e6467 | Dawsh | 2y ago | /> |
| 114 | e6e6467 | Dawsh | 2y ago | </linearGradient> |
| 115 | e6e6467 | Dawsh | 2y ago | )} |
| 116 | e6e6467 | Dawsh | 2y ago | </defs> |
| 117 | e6e6467 | Dawsh | 2y ago | {data.node_usages.map(node => |
| 118 | e6e6467 | Dawsh | 2y ago | <Area |
| 119 | e6e6467 | Dawsh | 2y ago | dataKey={node.node_name} |
| 120 | e6e6467 | Dawsh | 2y ago | key={node.node_name} |
| 121 | e6e6467 | Dawsh | 2y ago | type="natural" |
| 122 | e6e6467 | Dawsh | 2y ago | fill={config[node.node_name].color} |
| 123 | e6e6467 | Dawsh | 2y ago | fillOpacity={0.4} |
| 124 | e6e6467 | Dawsh | 2y ago | stackId={node.node_id} |
| 125 | e6e6467 | Dawsh | 2y ago | stroke={config[node.node_name].color} |
| 126 | e6e6467 | Dawsh | 2y ago | /> |
| 127 | e6e6467 | Dawsh | 2y ago | )} |
| 128 | e6e6467 | Dawsh | 2y ago | <ChartLegend content={<ChartLegendContent />} /> |
| 129 | e6e6467 | Dawsh | 2y ago | </AreaChart> |
| 130 | e6e6467 | Dawsh | 2y ago | </ChartContainer> |
| 131 | e6e6467 | Dawsh | 2y ago | </SectionWidget> |
| 132 | e6e6467 | Dawsh | 2y ago | } |
| 133 | e6e6467 | Dawsh | 2y ago | Skeleton={<UsageGraphSkeleton />} |
| 134 | e6e6467 | Dawsh | 2y ago | isFetching={isPending} |
| 135 | e6e6467 | Dawsh | 2y ago | /> |
| 136 | e6e6467 | Dawsh | 2y ago | ); |
| 137 | e6e6467 | Dawsh | 2y ago | }; |