From 713d2ac9256122256b36bbcbcd10f5e165a85140 Mon Sep 17 00:00:00 2001 From: Oliver Date: Mon, 10 Jun 2024 08:24:38 +1000 Subject: [PATCH] Mantine charts (#7419) * Install @mantine/charts * Import charts styles * Refactor * Refactor internal price panel * Refactor variant price panel * BOM bar chart * BOM donut * Refactor supplier pricing panel * More refaactoring * Cleanup unused imports * Fix typo * playwright test updates --- src/frontend/package.json | 1 + src/frontend/src/components/charts/colors.tsx | 20 ++-- .../components/charts/tooltipFormatter.tsx | 9 +- src/frontend/src/main.tsx | 1 + .../pages/part/pricing/BomPricingPanel.tsx | 110 ++++++------------ .../pages/part/pricing/PriceBreakPanel.tsx | 42 ++----- .../part/pricing/PricingOverviewPanel.tsx | 50 ++------ .../part/pricing/PurchaseHistoryPanel.tsx | 45 ++----- .../pages/part/pricing/SaleHistoryPanel.tsx | 40 ++----- .../part/pricing/SupplierPricingPanel.tsx | 49 +++----- .../part/pricing/VariantPricingPanel.tsx | 52 +++------ src/frontend/src/tables/InvenTreeTable.tsx | 6 +- src/frontend/tests/pages/pui_part.spec.ts | 16 +-- src/frontend/yarn.lock | 5 + 14 files changed, 136 insertions(+), 310 deletions(-) diff --git a/src/frontend/package.json b/src/frontend/package.json index 285078580fa7..af2378e32bc3 100644 --- a/src/frontend/package.json +++ b/src/frontend/package.json @@ -27,6 +27,7 @@ "@lingui/core": "^4.10.0", "@lingui/react": "^4.10.0", "@mantine/carousel": "^7.8.0", + "@mantine/charts": "^7.10.1", "@mantine/core": "^7.10.0", "@mantine/dates": "^7.8.0", "@mantine/dropzone": "^7.8.0", diff --git a/src/frontend/src/components/charts/colors.tsx b/src/frontend/src/components/charts/colors.tsx index 6be93493bdf9..fc19be342740 100644 --- a/src/frontend/src/components/charts/colors.tsx +++ b/src/frontend/src/components/charts/colors.tsx @@ -1,12 +1,12 @@ export const CHART_COLORS: string[] = [ - '#ffa8a8', - '#8ce99a', - '#74c0fc', - '#ffe066', - '#63e6be', - '#ffc078', - '#d8f5a2', - '#66d9e8', - '#e599f7', - '#dee2e6' + 'blue', + 'teal', + 'lime', + 'yellow', + 'grape', + 'red', + 'orange', + 'green', + 'indigo', + 'pink' ]; diff --git a/src/frontend/src/components/charts/tooltipFormatter.tsx b/src/frontend/src/components/charts/tooltipFormatter.tsx index 73b3b9770379..2e7eadc13e5b 100644 --- a/src/frontend/src/components/charts/tooltipFormatter.tsx +++ b/src/frontend/src/components/charts/tooltipFormatter.tsx @@ -1,9 +1,12 @@ import { formatCurrency } from '../../defaults/formatters'; -export function tooltipFormatter(label: any, currency: string) { +/* + * Render a chart label for a currency graph + */ +export function tooltipFormatter(value: any, currency?: string) { return ( - formatCurrency(label, { + formatCurrency(value, { currency: currency - })?.toString() ?? '' + })?.toString() ?? value.toString() ); } diff --git a/src/frontend/src/main.tsx b/src/frontend/src/main.tsx index 01ea516254c7..b4d48e77e5f1 100644 --- a/src/frontend/src/main.tsx +++ b/src/frontend/src/main.tsx @@ -1,4 +1,5 @@ import '@mantine/carousel/styles.css'; +import '@mantine/charts/styles.css'; import '@mantine/core/styles.css'; import '@mantine/notifications/styles.css'; import '@mantine/spotlight/styles.css'; diff --git a/src/frontend/src/pages/part/pricing/BomPricingPanel.tsx b/src/frontend/src/pages/part/pricing/BomPricingPanel.tsx index b0c9f6039290..9ee05a7bf954 100644 --- a/src/frontend/src/pages/part/pricing/BomPricingPanel.tsx +++ b/src/frontend/src/pages/part/pricing/BomPricingPanel.tsx @@ -1,5 +1,7 @@ import { t } from '@lingui/macro'; +import { BarChart, DonutChart } from '@mantine/charts'; import { + Center, Group, SegmentedControl, SimpleGrid, @@ -7,18 +9,6 @@ import { Text } from '@mantine/core'; import { ReactNode, useMemo, useState } from 'react'; -import { - Bar, - BarChart, - Cell, - Legend, - Pie, - PieChart, - ResponsiveContainer, - Tooltip, - XAxis, - YAxis -} from 'recharts'; import { CHART_COLORS } from '../../../components/charts/colors'; import { tooltipFormatter } from '../../../components/charts/tooltipFormatter'; @@ -44,42 +34,30 @@ function BomPieChart({ readonly data: any[]; readonly currency: string; }) { + // Construct donut data + const maxPricing = useMemo(() => { + return data.map((entry, index) => { + return { + name: entry.name, + value: entry.total_price_max, + color: CHART_COLORS[index % CHART_COLORS.length] + '.5' + }; + }); + }, [data]); + return ( - - - - {data.map((_entry, index) => ( - - ))} - - - {data.map((_entry, index) => ( - - ))} - - tooltipFormatter(label, currency)} - /> - - +
+ tooltipFormatter(value, currency)} + /> +
); } @@ -92,32 +70,18 @@ function BomBarChart({ readonly currency: string; }) { return ( - - - - - formatCurrency(value, { - currency: currency - })?.toString() ?? '' - } - /> - tooltipFormatter(label, currency)} - /> - - - - - + tooltipFormatter(value, currency)} + /> ); } diff --git a/src/frontend/src/pages/part/pricing/PriceBreakPanel.tsx b/src/frontend/src/pages/part/pricing/PriceBreakPanel.tsx index 8a8f87d5d012..fa1da3fe07c6 100644 --- a/src/frontend/src/pages/part/pricing/PriceBreakPanel.tsx +++ b/src/frontend/src/pages/part/pricing/PriceBreakPanel.tsx @@ -1,18 +1,9 @@ import { t } from '@lingui/macro'; +import { BarChart } from '@mantine/charts'; import { SimpleGrid } from '@mantine/core'; import { useCallback, useMemo, useState } from 'react'; -import { - Bar, - BarChart, - Legend, - ResponsiveContainer, - Tooltip, - XAxis, - YAxis -} from 'recharts'; import { AddItemButton } from '../../../components/buttons/AddItemButton'; -import { CHART_COLORS } from '../../../components/charts/colors'; import { tooltipFormatter } from '../../../components/charts/tooltipFormatter'; import { ApiFormFieldSet } from '../../../components/forms/fields/ApiFormField'; import { formatCurrency } from '../../../defaults/formatters'; @@ -169,29 +160,14 @@ export default function PriceBreakPanel({ }} /> {table.records.length > 0 ? ( - - - - - formatCurrency(value, { - currency: currency - })?.toString() ?? '' - } - /> - - tooltipFormatter(label, currency) - } - /> - - - - + tooltipFormatter(value, currency)} + /> ) : ( )} diff --git a/src/frontend/src/pages/part/pricing/PricingOverviewPanel.tsx b/src/frontend/src/pages/part/pricing/PricingOverviewPanel.tsx index 4aa67f844b27..3d3c5b571b41 100644 --- a/src/frontend/src/pages/part/pricing/PricingOverviewPanel.tsx +++ b/src/frontend/src/pages/part/pricing/PricingOverviewPanel.tsx @@ -1,4 +1,5 @@ import { t } from '@lingui/macro'; +import { BarChart } from '@mantine/charts'; import { Alert, Anchor, @@ -19,17 +20,7 @@ import { } from '@tabler/icons-react'; import { DataTable } from 'mantine-datatable'; import { ReactNode, useMemo } from 'react'; -import { - Bar, - BarChart, - Legend, - ResponsiveContainer, - Tooltip, - XAxis, - YAxis -} from 'recharts'; -import { CHART_COLORS } from '../../../components/charts/colors'; import { tooltipFormatter } from '../../../components/charts/tooltipFormatter'; import { formatCurrency, renderDate } from '../../../defaults/formatters'; import { panelOptions } from '../PartPricingPanel'; @@ -192,34 +183,17 @@ export default function PricingOverviewPanel({ columns={columns} /> - - - - - formatCurrency(value, { - currency: pricing?.currency - })?.toString() ?? '' - } - /> - - tooltipFormatter(label, pricing?.currency) - } - /> - - - - - + tooltipFormatter(value, pricing?.currency)} + /> ); diff --git a/src/frontend/src/pages/part/pricing/PurchaseHistoryPanel.tsx b/src/frontend/src/pages/part/pricing/PurchaseHistoryPanel.tsx index b13495497e4e..8f1550b34030 100644 --- a/src/frontend/src/pages/part/pricing/PurchaseHistoryPanel.tsx +++ b/src/frontend/src/pages/part/pricing/PurchaseHistoryPanel.tsx @@ -1,18 +1,8 @@ import { t } from '@lingui/macro'; +import { BarChart } from '@mantine/charts'; import { Group, SimpleGrid, Text } from '@mantine/core'; import { ReactNode, useCallback, useMemo } from 'react'; -import { - Bar, - BarChart, - Legend, - ResponsiveContainer, - Tooltip, - XAxis, - YAxis -} from 'recharts'; -import { CHART_COLORS } from '../../../components/charts/colors'; -import { tooltipFormatter } from '../../../components/charts/tooltipFormatter'; import { formatCurrency, renderDate } from '../../../defaults/formatters'; import { ApiEndpoints } from '../../../enums/ApiEndpoints'; import { useTable } from '../../../hooks/UseTable'; @@ -131,32 +121,13 @@ export default function PurchaseHistoryPanel({ }} /> {purchaseHistoryData.length > 0 ? ( - - - - - formatCurrency(value, { - currency: currency - })?.toString() ?? '' - } - /> - tooltipFormatter(label, currency)} - /> - - - - - + ) : ( )} diff --git a/src/frontend/src/pages/part/pricing/SaleHistoryPanel.tsx b/src/frontend/src/pages/part/pricing/SaleHistoryPanel.tsx index 032777fec5cf..a71427c24de6 100644 --- a/src/frontend/src/pages/part/pricing/SaleHistoryPanel.tsx +++ b/src/frontend/src/pages/part/pricing/SaleHistoryPanel.tsx @@ -1,18 +1,8 @@ import { t } from '@lingui/macro'; +import { BarChart } from '@mantine/charts'; import { SimpleGrid } from '@mantine/core'; import { ReactNode, useMemo } from 'react'; -import { - Bar, - BarChart, - Legend, - ResponsiveContainer, - Tooltip, - XAxis, - YAxis -} from 'recharts'; -import { CHART_COLORS } from '../../../components/charts/colors'; -import { tooltipFormatter } from '../../../components/charts/tooltipFormatter'; import { formatCurrency } from '../../../defaults/formatters'; import { ApiEndpoints } from '../../../enums/ApiEndpoints'; import { useTable } from '../../../hooks/UseTable'; @@ -95,27 +85,13 @@ export default function SaleHistoryPanel({ part }: { part: any }): ReactNode { }} /> {saleHistoryData.length > 0 ? ( - - - - - formatCurrency(value, { - currency: currency - })?.toString() ?? '' - } - /> - tooltipFormatter(label, currency)} - /> - - - - + ) : ( )} diff --git a/src/frontend/src/pages/part/pricing/SupplierPricingPanel.tsx b/src/frontend/src/pages/part/pricing/SupplierPricingPanel.tsx index 0cae3cb15690..e69a498d38cf 100644 --- a/src/frontend/src/pages/part/pricing/SupplierPricingPanel.tsx +++ b/src/frontend/src/pages/part/pricing/SupplierPricingPanel.tsx @@ -1,18 +1,9 @@ import { t } from '@lingui/macro'; +import { BarChart } from '@mantine/charts'; import { SimpleGrid } from '@mantine/core'; import { useMemo } from 'react'; -import { - Bar, - BarChart, - ResponsiveContainer, - Tooltip, - XAxis, - YAxis -} from 'recharts'; -import { CHART_COLORS } from '../../../components/charts/colors'; import { tooltipFormatter } from '../../../components/charts/tooltipFormatter'; -import { formatCurrency } from '../../../defaults/formatters'; import { ApiEndpoints } from '../../../enums/ApiEndpoints'; import { useTable } from '../../../hooks/UseTable'; import { apiUrl } from '../../../states/ApiState'; @@ -64,31 +55,19 @@ export default function SupplierPricingPanel({ part }: { part: any }) { }} /> {supplierPricingData.length > 0 ? ( - - - - - formatCurrency(value, { - currency: currency - })?.toString() ?? '' - } - /> - tooltipFormatter(label, currency)} - /> - - - - + tooltipFormatter(value, currency)} + /> ) : ( )} diff --git a/src/frontend/src/pages/part/pricing/VariantPricingPanel.tsx b/src/frontend/src/pages/part/pricing/VariantPricingPanel.tsx index 12f21ccd3368..38c918b32c94 100644 --- a/src/frontend/src/pages/part/pricing/VariantPricingPanel.tsx +++ b/src/frontend/src/pages/part/pricing/VariantPricingPanel.tsx @@ -1,17 +1,8 @@ import { t } from '@lingui/macro'; +import { BarChart } from '@mantine/charts'; import { SimpleGrid, Stack } from '@mantine/core'; import { ReactNode, useMemo } from 'react'; -import { - Bar, - BarChart, - Legend, - ResponsiveContainer, - Tooltip, - XAxis, - YAxis -} from 'recharts'; -import { CHART_COLORS } from '../../../components/charts/colors'; import { tooltipFormatter } from '../../../components/charts/tooltipFormatter'; import { formatCurrency } from '../../../defaults/formatters'; import { ApiEndpoints } from '../../../enums/ApiEndpoints'; @@ -97,34 +88,19 @@ export default function VariantPricingPanel({ }} /> {variantPricingData.length > 0 ? ( - - - - - formatCurrency(value, { - currency: pricing?.currency - })?.toString() ?? '' - } - /> - - tooltipFormatter(label, pricing?.currency) - } - /> - - - - - + + tooltipFormatter(value, pricing?.currency) + } + /> ) : ( )} diff --git a/src/frontend/src/tables/InvenTreeTable.tsx b/src/frontend/src/tables/InvenTreeTable.tsx index 47d26be023a0..c372153d40ae 100644 --- a/src/frontend/src/tables/InvenTreeTable.tsx +++ b/src/frontend/src/tables/InvenTreeTable.tsx @@ -580,8 +580,8 @@ export function InvenTreeTable({ )} - - + + {tableProps.enableDownload && ( ({ ))} - + {tableProps.enableSearch && ( diff --git a/src/frontend/tests/pages/pui_part.spec.ts b/src/frontend/tests/pages/pui_part.spec.ts index e9aee7ddaa5e..d411738184fb 100644 --- a/src/frontend/tests/pages/pui_part.spec.ts +++ b/src/frontend/tests/pages/pui_part.spec.ts @@ -29,25 +29,25 @@ test('PUI - Pages - Part - Pricing (Nothing, BOM)', async ({ page }) => { await page.getByRole('button', { name: 'BOM Pricing' }).isEnabled(); // Overview Graph - let graph = page.locator('#pricing-overview-chart'); + let graph = page.getByLabel('pricing-overview-chart'); await graph.waitFor(); await graph.getByText('$60').waitFor(); - await graph.getByText('BOM Pricing').waitFor(); - await graph.getByText('Overall Pricing').waitFor(); - await graph.locator('path').nth(1).hover(); - await page.getByText('min_value : $50').waitFor(); + await graph.locator('tspan').filter({ hasText: 'BOM Pricing' }).waitFor(); + await graph.locator('tspan').filter({ hasText: 'Overall Pricing' }).waitFor(); // BOM Pricing await page.getByRole('button', { name: 'BOM Pricing' }).click(); await page.getByText('Bar Chart').click(); - await page.getByText('total_price_min').waitFor(); await page.getByText('Pie Chart').click(); await page.getByRole('button', { name: 'Quantity Not sorted' }).waitFor(); await page.getByRole('button', { name: 'Unit Price Not sorted' }).waitFor(); // BOM Pricing - linkjumping - await page.getByText('Wood Screw').waitFor(); - await page.getByText('Wood Screw').click(); + await page + .getByLabel('BOM Pricing') + .getByRole('table') + .getByText('Wood Screw') + .click(); await page.waitForURL('**/part/98/pricing'); }); diff --git a/src/frontend/yarn.lock b/src/frontend/yarn.lock index 4cf923c8ff20..4188cdbfce40 100644 --- a/src/frontend/yarn.lock +++ b/src/frontend/yarn.lock @@ -1809,6 +1809,11 @@ resolved "https://registry.yarnpkg.com/@mantine/carousel/-/carousel-7.10.0.tgz#ee750504814ec4eff7523e17a0052dc86bec45c8" integrity sha512-+fP/hyHpXoK5nHR5mgEjPhPqjiurwMDP+aLseaE/mvmoBZEFF3vOPAqYOekNDrdyaqvtHkM82T9mnR4M3BAK0w== +"@mantine/charts@^7.10.1": + version "7.10.1" + resolved "https://registry.yarnpkg.com/@mantine/charts/-/charts-7.10.1.tgz#c1b92ccac16d05b87cc103adcd79f0e0c2f87c62" + integrity sha512-fMy2EmgegdHVkrtnRO8ync8kqOJoXqixxc1JDmhn9tks4lSvKAKB9ui8OyaTUOWzls/Cs0VfyW51sB/HKe5faw== + "@mantine/core@^7.10.0": version "7.10.0" resolved "https://registry.yarnpkg.com/@mantine/core/-/core-7.10.0.tgz#bfaafc92cf2346e5a6cbb49289f577ce3f7c05f7"