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;