diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 6c9b7e0d..2f7336fc 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -78,7 +78,7 @@ "closable": true, "title": "Defguard", "width": 992, - "minWidth": 360, + "minWidth": 650, "minHeight": 450 } ] diff --git a/src/pages/client/components/LocationUsageChart/LocationUsageChart.tsx b/src/pages/client/components/LocationUsageChart/LocationUsageChart.tsx index e23f907c..06da393e 100644 --- a/src/pages/client/components/LocationUsageChart/LocationUsageChart.tsx +++ b/src/pages/client/components/LocationUsageChart/LocationUsageChart.tsx @@ -1,7 +1,10 @@ +import './style.scss'; + import dayjs from 'dayjs'; import { sortBy } from 'lodash-es'; import { useMemo } from 'react'; -import { Bar, BarChart, ResponsiveContainer, XAxis, YAxis } from 'recharts'; +import AutoSizer from 'react-virtualized-auto-sizer'; +import { Bar, BarChart, XAxis, YAxis } from 'recharts'; import { NetworkSpeed } from '../../../../shared/defguard-ui/components/Layout/NetworkSpeed/NetworkSpeed'; import { NetworkDirection } from '../../../../shared/defguard-ui/components/Layout/NetworkSpeed/types'; @@ -10,8 +13,6 @@ import { LocationStats } from '../../types'; interface LocationUsageProps { data: LocationStats[]; - width?: number; - height?: number; hideX?: boolean; barSize?: number; barGap?: number; @@ -39,8 +40,6 @@ const totalUploadDownload = (data: LocationStats[]): number[] => { export const LocationUsageChart = ({ data, - height = 300, - width = 900, hideX = false, barSize = 5, barGap = 2, @@ -49,6 +48,9 @@ export const LocationUsageChart = ({ const [totalUpload, totalDownload] = useMemo(() => totalUploadDownload(data), [data]); const getFormattedData = useMemo(() => parseStatsForCharts(data), [data]); const { colors } = useTheme(); + + if (!data.length) return null; + return (
@@ -60,37 +62,41 @@ export const LocationUsageChart = ({
- - - - - - - - + + {(size) => ( + + + + + + + )} +
); }; diff --git a/src/pages/client/components/LocationUsageChart/style.scss b/src/pages/client/components/LocationUsageChart/style.scss index e69de29b..bf4afd9b 100644 --- a/src/pages/client/components/LocationUsageChart/style.scss +++ b/src/pages/client/components/LocationUsageChart/style.scss @@ -0,0 +1,21 @@ +@use '@scssutils' as *; + +.location-usage { + display: grid; + grid-template-rows: auto auto; + grid-template-columns: 1fr; + width: 100%; + row-gap: 8px; + + & > .summary { + grid-row: 1; + grid-column: 1; + width: 100%; + } + + & > .chart-wrapper { + grid-row: 2; + grid-column: 1; + width: 100%; + } +} diff --git a/src/pages/client/components/LocationsList/components/LocationsDetailView/LocationsDetailView.tsx b/src/pages/client/components/LocationsList/components/LocationsDetailView/LocationsDetailView.tsx index 4fd0b722..704bd048 100644 --- a/src/pages/client/components/LocationsList/components/LocationsDetailView/LocationsDetailView.tsx +++ b/src/pages/client/components/LocationsList/components/LocationsDetailView/LocationsDetailView.tsx @@ -3,7 +3,9 @@ import './style.scss'; import { useQuery } from '@tanstack/react-query'; import { useMemo, useState } from 'react'; import { error } from 'tauri-plugin-log-api'; +import { useBreakpoint } from 'use-breakpoint'; +import { deviceBreakpoints } from '../../../../../../shared/constants'; import { Card } from '../../../../../../shared/defguard-ui/components/Layout/Card/Card'; import { CardTabs } from '../../../../../../shared/defguard-ui/components/Layout/CardTabs/CardTabs'; import { CardTabsData } from '../../../../../../shared/defguard-ui/components/Layout/CardTabs/types'; @@ -31,6 +33,7 @@ const findLocationById = ( const { getLocationStats, getLastConnection, getConnectionHistory } = clientApi; export const LocationsDetailView = ({ locations }: Props) => { + const { breakpoint } = useBreakpoint(deviceBreakpoints); const [activeLocationId, setActiveLocationId] = useState(locations[0].id); const statsFilter = useClientStore((state) => state.statsFilter); @@ -81,18 +84,28 @@ export const LocationsDetailView = ({ locations }: Props) => {
- + {breakpoint === 'desktop' && ( + + )}
- {locationStats ? ( - + {breakpoint !== 'desktop' && ( +
+ +
+ )} + {locationStats && locationStats.length ? ( + ) : null} - {connectionHistory ? ( + {connectionHistory && connectionHistory.length ? ( ) : null}
diff --git a/src/pages/client/components/LocationsList/components/LocationsDetailView/style.scss b/src/pages/client/components/LocationsList/components/LocationsDetailView/style.scss index f1492785..68c3b786 100644 --- a/src/pages/client/components/LocationsList/components/LocationsDetailView/style.scss +++ b/src/pages/client/components/LocationsList/components/LocationsDetailView/style.scss @@ -2,7 +2,9 @@ @mixin list-layout { display: inline-grid; - grid-template-columns: minmax(180px, 25%) repeat(3, 1fr) auto; // Adjust for larger screens. + grid-template-columns: minmax(180px, 25%) repeat(3, 1fr) auto; + + // Adjust for larger screens. & > * { grid-row: 1; @@ -11,18 +13,35 @@ #locations-detail-view { & > .card { - & > h2 { - @include typography(app-welcome-1); - color: var(--text-body-primary); + display: flex; + flex-flow: column; + row-gap: 20px; + padding: 20px; + min-height: 50vh; + border-top-left-radius: 0; + + @include media-breakpoint-up(lg) { + min-height: 600px; } - padding: 2rem 2rem; + & > .header { display: flex; + flex-flow: row nowrap; + align-items: center; justify-content: space-between; + width: 100%; + row-gap: 20px; } - border-top-left-radius: 0; - height: 800px; - width: 90%; + + & > .info { + display: flex; + flex-flow: row wrap; + column-gap: 10px; + row-gap: 20px; + align-items: center; + justify-content: space-between; + } + & > .location-usage { display: flex; flex-direction: column;