From 68ceafa4d3133639bdd2409894609e93ea4ebf8c Mon Sep 17 00:00:00 2001 From: James Ritchie Date: Thu, 30 Nov 2023 16:24:31 +0000 Subject: [PATCH] Added new concurrency chart to the usage page --- .../billing/ConcurrentRunsChart.tsx | 114 ++++++++++ .../stories/UsageCharts.stories.tsx | 107 +--------- .../route.tsx | 199 ++++++++++-------- 3 files changed, 232 insertions(+), 188 deletions(-) create mode 100644 apps/webapp/app/components/billing/ConcurrentRunsChart.tsx diff --git a/apps/webapp/app/components/billing/ConcurrentRunsChart.tsx b/apps/webapp/app/components/billing/ConcurrentRunsChart.tsx new file mode 100644 index 000000000..8cceba3a0 --- /dev/null +++ b/apps/webapp/app/components/billing/ConcurrentRunsChart.tsx @@ -0,0 +1,114 @@ +import { + Label, + Line, + LineChart, + ReferenceLine, + ResponsiveContainer, + Tooltip, + XAxis, + YAxis, +} from "recharts"; +import { Header3 } from "../primitives/Headers"; + +const tooltipStyle = { + display: "flex", + alignItems: "center", + gap: "0.5rem", + borderRadius: "0.25rem", + border: "1px solid #1A2434", + backgroundColor: "#0B1018", + padding: "0.3rem 0.5rem", + fontSize: "0.75rem", + color: "#E2E8F0", +}; + +export function ConcurrentRunsChart({ + concurrentRunsLimit: planLimit, +}: { + concurrentRunsLimit: number; +}) { + return ( + <> + Monthly concurrent Runs + + + + + + + + + + + + ); +} + +export const ConcurrentRunsData = [ + { + name: "Nov 23", + "Concurrent Runs": 2, + }, + { + name: "Dec 23", + "Concurrent Runs": 4, + }, + { + name: "Jan 24", + "Concurrent Runs": 3, + }, + { + name: "Feb 24", + "Concurrent Runs": 5, + }, + { + name: "Mar 24", + "Concurrent Runs": 25, + }, + { + name: "Apr 24", + "Concurrent Runs": 2, + }, + { + name: "May 24", + "Concurrent Runs": 10, + }, + { + name: "Jun 24", + "Concurrent Runs": 8, + }, + { + name: "Jul 24", + "Concurrent Runs": null, + }, + { + name: "Aug 24", + "Concurrent Runs": null, + }, + { + name: "Sep 24", + "Concurrent Runs": null, + }, + { + name: "Oct 24", + "Concurrent Runs": null, + }, +]; diff --git a/apps/webapp/app/components/stories/UsageCharts.stories.tsx b/apps/webapp/app/components/stories/UsageCharts.stories.tsx index 337f4a153..ff92596ac 100644 --- a/apps/webapp/app/components/stories/UsageCharts.stories.tsx +++ b/apps/webapp/app/components/stories/UsageCharts.stories.tsx @@ -1,18 +1,6 @@ import type { Meta, StoryObj } from "@storybook/react"; -import { - Bar, - BarChart, - CartesianGrid, - Legend, - Line, - LineChart, - ReferenceLine, - ResponsiveContainer, - Tooltip, - TooltipProps, - XAxis, - YAxis, -} from "recharts"; +import { TooltipProps } from "recharts"; +import { ConcurrentRunsChart } from "../billing/ConcurrentRunsChart"; const meta: Meta = { title: "Billing/UsageCharts", @@ -31,86 +19,10 @@ export const RunQueue: Story = { render: () => , }; -const data = [ - { - name: "Nov 23", - "Concurrent Runs": 2, - }, - { - name: "Dec 23", - "Concurrent Runs": 4, - }, - { - name: "Jan 24", - "Concurrent Runs": 3, - }, - { - name: "Feb 24", - "Concurrent Runs": 5, - }, - { - name: "Mar 24", - "Concurrent Runs": 25, - }, - { - name: "Apr 24", - "Concurrent Runs": 10, - }, - { - name: "May 24", - "Concurrent Runs": null, - }, - { - name: "Jun 24", - "Concurrent Runs": null, - }, - { - name: "Jul 24", - "Concurrent Runs": null, - }, - { - name: "Aug 24", - "Concurrent Runs": null, - }, - { - name: "Sep 24", - "Concurrent Runs": null, - }, - { - name: "Oct 24", - "Concurrent Runs": null, - }, -]; - function UsageCharts() { return (
- - - - - - - - - +
); } @@ -118,16 +30,3 @@ function UsageCharts() { function RunQueueChart() { return
Run Queue chart
; } - -const CustomTooltip = ({ active, payload, label }: TooltipProps) => { - if (active && payload) { - return ( -
-

{label}:

-

{payload[0].value}

-
- ); - } - - return null; -}; diff --git a/apps/webapp/app/routes/_app.orgs.$organizationSlug.billing._index/route.tsx b/apps/webapp/app/routes/_app.orgs.$organizationSlug.billing._index/route.tsx index bfdc3864e..f7d46cb10 100644 --- a/apps/webapp/app/routes/_app.orgs.$organizationSlug.billing._index/route.tsx +++ b/apps/webapp/app/routes/_app.orgs.$organizationSlug.billing._index/route.tsx @@ -1,18 +1,16 @@ import { ArrowRightIcon } from "@heroicons/react/20/solid"; import { ArrowUpCircleIcon } from "@heroicons/react/24/outline"; -import { - ForwardIcon, - SquaresPlusIcon, - UsersIcon, - WrenchScrewdriverIcon, -} from "@heroicons/react/24/solid"; +import { SquaresPlusIcon, UsersIcon, WrenchScrewdriverIcon } from "@heroicons/react/24/solid"; import { Link } from "@remix-run/react/dist/components"; import { LoaderFunctionArgs } from "@remix-run/server-runtime"; import { Bar, BarChart, ResponsiveContainer, Tooltip, TooltipProps, XAxis, YAxis } from "recharts"; import { typedjson, useTypedLoaderData } from "remix-typedjson"; +import { ConcurrentRunsChart } from "~/components/billing/ConcurrentRunsChart"; +import { UsageBar } from "~/components/billing/UsageBar"; import { LinkButton } from "~/components/primitives/Buttons"; import { Callout } from "~/components/primitives/Callout"; -import { Header2 } from "~/components/primitives/Headers"; +import { Header2, Header3 } from "~/components/primitives/Headers"; +import { NamedIcon } from "~/components/primitives/NamedIcon"; import { Paragraph } from "~/components/primitives/Paragraph"; import { TextLink } from "~/components/primitives/TextLink"; import { useOrganization } from "~/hooks/useOrganizations"; @@ -43,9 +41,9 @@ export async function loader({ params, request }: LoaderFunctionArgs) { const CustomTooltip = ({ active, payload, label }: TooltipProps) => { if (active && payload) { return ( -
-

{label}:

-

{payload[0].value}

+
+

{label}:

+

{payload[0].value}

); } @@ -58,43 +56,101 @@ export default function Page() { const loaderData = useTypedLoaderData(); return ( - <> - +
+ Concurrent Runs +
+ + Increase concurrent Runs + + } > - Increase concurrency - - } - className="mb-4" - > - Some of your Runs are being queued because your Run concurrency is limited to 50. - -
+ Some of your Runs are being queued because the number of concurrent Runs is limited to + 50. + + +
+
+ +
+ Runs +
+
+
+
+ Month-to-date +

$0.00

+
+ +
+ Projected +

$25.00

+
+
+ +
+
+ Monthly Runs + + + + `${value}`} + /> + } /> + + + +
+
+
+
- Total Runs this month - + Total Runs this month +
-

{loaderData.runsCount.toLocaleString()}

+

{loaderData.runsCount.toLocaleString()}

- {loaderData.runsCountLastMonth} runs last month + {loaderData.runsCountLastMonth} Runs last month
- Total Jobs - + Total Jobs +
-

{loaderData.totalJobs.toLocaleString()}

+

{loaderData.totalJobs.toLocaleString()}

{loaderData.totalJobs === loaderData.totalJobsLastMonth ? ( <>No change since last month @@ -108,11 +164,11 @@ export default function Page() {
- Total Integrations - + Total Integrations +
-

{loaderData.totalIntegrations.toLocaleString()}

+

{loaderData.totalIntegrations.toLocaleString()}

{loaderData.totalIntegrations === loaderData.totalIntegrationsLastMonth ? ( <>No change since last month @@ -132,11 +188,11 @@ export default function Page() {
- Team members - + Team members +
-

{loaderData.totalMembers.toLocaleString()}

+

{loaderData.totalMembers.toLocaleString()}

-
-
- Job Runs per month - - - - `${value}`} - /> - } /> - - - +
+
+ Jobs + Runs
-
-
- Jobs - Runs -
-
- {loaderData.jobs.map((job) => ( - -
-

{job.slug}

-

Project: {job.project.name}

-
-
{job._count.runs.toLocaleString()}
- - ))} -
+
+ {loaderData.jobs.map((job) => ( + +
+

{job.slug}

+

Project: {job.project.name}

+
+
{job._count.runs.toLocaleString()}
+ + ))}
- +
); }