Skip to content

Commit

Permalink
graph improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
wardviaene committed Aug 25, 2024
1 parent 1ede636 commit 3b7b4d2
Show file tree
Hide file tree
Showing 8 changed files with 155 additions and 38 deletions.
2 changes: 1 addition & 1 deletion latest
Original file line number Diff line number Diff line change
@@ -1 +1 @@
v1.1.1beta1
v1.1.1
42 changes: 38 additions & 4 deletions pkg/rest/stats.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"fmt"
"net/http"
"path"
"sort"
"strconv"
"strings"
"time"
Expand All @@ -15,6 +16,13 @@ import (
)

func (c *Context) userStatsHandler(w http.ResponseWriter, r *http.Request) {
// get all users
users := c.UserStore.ListUsers()
userMap := make(map[string]string)
for _, user := range users {
userMap[user.ID] = user.Login
}
// calculate stats
var userStatsResponse UserStatsResponse
statsFile := c.Storage.Client.ConfigPath(path.Join(wireguard.VPN_STATS_DIR, "user-"+time.Now().Format("2006-01-02")) + ".log")
if !c.Storage.Client.FileExists(statsFile) { // file does not exist so just return empty response
Expand Down Expand Up @@ -85,22 +93,48 @@ func (c *Context) userStatsHandler(w http.ResponseWriter, r *http.Request) {
Datasets: []UserStatsDataset{},
}
for userID, data := range receiveBytesData {
login, ok := userMap[userID]
if !ok {
login = "unknown"
}
userStatsResponse.ReceiveBytes.Datasets = append(userStatsResponse.ReceiveBytes.Datasets, UserStatsDataset{
Label: userID,
Data: data,
BorderColor: getColor(len(userStatsResponse.ReceiveBytes.Datasets)),
Label: login,
Data: data,
Tension: 0.1,
})
}
for userID, data := range transmitBytesData {
login, ok := userMap[userID]
if !ok {
login = "unknown"
}
userStatsResponse.TransmitBytes.Datasets = append(userStatsResponse.TransmitBytes.Datasets, UserStatsDataset{
Label: userID,
Data: data,
BorderColor: getColor(len(userStatsResponse.TransmitBytes.Datasets)),
Label: login,
Data: data,
Tension: 0.1,
})
}

sort.Sort(userStatsResponse.ReceiveBytes.Datasets)
sort.Sort(userStatsResponse.TransmitBytes.Datasets)

out, err := json.Marshal(userStatsResponse)
if err != nil {
c.returnError(w, fmt.Errorf("user stats response marshal error: %s", err), http.StatusBadRequest)
return
}
c.write(w, out)
}

func getColor(i int) string {
colors := []string{
"#DEEFB7",
"#98DFAF",
"#5FB49C",
"#414288",
"#682D63",
}
return colors[i%len(colors)]
}
3 changes: 2 additions & 1 deletion pkg/rest/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -180,8 +180,9 @@ type UserStatsResponse struct {
TransmitBytes UserStatsData `json:"transmitBytes"`
}
type UserStatsData struct {
Datasets []UserStatsDataset `json:"datasets"`
Datasets UserStatsDatasets `json:"datasets"`
}
type UserStatsDatasets []UserStatsDataset
type UserStatsDataset struct {
Label string `json:"label"`
Data []UserStatsDataPoint `json:"data"`
Expand Down
13 changes: 13 additions & 0 deletions pkg/rest/types_sort.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package rest

func (u UserStatsDatasets) Len() int {
return len(u)
}

func (u UserStatsDatasets) Swap(i, j int) {
u[i], u[j] = u[j], u[i]
}

func (u UserStatsDatasets) Less(i, j int) bool {
return u[i].Label < u[j].Label
}
47 changes: 37 additions & 10 deletions webapp/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions webapp/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
},
"dependencies": {
"@mantine/core": "^7.9.2",
"@mantine/dates": "^7.12.1",
"@mantine/form": "^7.10.0",
"@mantine/hooks": "^7.9.2",
"@tabler/icons-react": "^3.4.0",
Expand Down
51 changes: 40 additions & 11 deletions webapp/src/Routes/Home/UserStats.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import { Card } from "@mantine/core";
import { Card, Center, Text } from "@mantine/core";
//import { DatePicker } from '@mantine/dates';
import { useQuery } from "@tanstack/react-query";
import { useAuthContext } from "../../Auth/Auth";
import { AppSettings } from '../../Constants/Constants';
import { Chart } from 'react-chartjs-2';
import 'chartjs-adapter-date-fns';
import { Chart as ChartJS, LineController, LineElement, PointElement, LinearScale, Title, CategoryScale, TimeScale } from 'chart.js';
import { Chart as ChartJS, LineController, LineElement, PointElement, LinearScale, Title, CategoryScale, TimeScale, ChartOptions, Legend } from 'chart.js';

export function UserStats() {
ChartJS.register(LineController, LineElement, PointElement, LinearScale, Title, CategoryScale, TimeScale);
ChartJS.register(LineController, LineElement, PointElement, LinearScale, Title, CategoryScale, TimeScale, Legend);

const {authInfo} = useAuthContext()
const { isPending, error, data } = useQuery({
Expand All @@ -25,30 +26,58 @@ export function UserStats() {
),
enabled: authInfo.role === "admin",
})
const options = {

const options:ChartOptions<"line"> = {
responsive: true,
plugins: {
legend: {
position: 'top' as const,
},
title: {
position: 'right' as const,
display: true,
text: 'VPN Received (in bytes)',
},
},
scales: {
x: {
type: 'time',
min: '00:00:00',
/*time: {
displayFormats: {
quarter: 'HHHH MM'
}
}*/
},
y: {
min: 0
}
}
}

if (isPending) return ''
if (error) return 'cannot retrieve licensed users'


if(data.receivedBytes.datasets === null) {
data.receivedBytes.datasets = [{ data: [0], label: "no data"}]
}
if(data.transmitBytes.datasets === null) {
data.transmitBytes.datasets = [{ data: [0], label: "no data"}]
}

return (
<Card withBorder radius="md" padding="xl" bg="var(--mantine-color-body)" mt={20}>
<Chart type="line" data={data.receivedBytes} options={options} />
<>
<Card withBorder radius="md" bg="var(--mantine-color-body)" mt={20}>
<Center>
<Text fw={500} size="lg">VPN Data Received (bytes)</Text>
<Text>
</Text>

</Center>
<Chart type="line" data={data.receivedBytes} options={options} />
</Card>
<Card withBorder radius="md" bg="var(--mantine-color-body)" mt={20}>
<Center>
<Text fw={500} size="lg">VPN Data Sent (bytes)</Text>
</Center>
<Chart type="line" data={data.transmitBytes} options={options} />
</Card>
</>
)
}
34 changes: 23 additions & 11 deletions webapp/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -348,10 +348,10 @@
resolved "https://registry.npmjs.org/@kurkle/color/-/color-0.3.2.tgz"
integrity sha512-fuscdXJ9G1qb7W8VdHi+IwRqij3lBkosAm4ydQtEmbY58OzHXqQhvlxqEkoz0yssNVn38bcpRWgA9PP+OGoisw==

"@mantine/core@^7.9.2":
version "7.10.1"
resolved "https://registry.npmjs.org/@mantine/core/-/core-7.10.1.tgz"
integrity sha512-l9ypojKN3PjwO1CSLIsqxi7mA25+7w+xc71Q+JuCCREI0tuGwkZsKbIOpuTATIJOjPh8ycLiW7QxX1LYsRTq6w==
"@mantine/core@^7.9.2", "@mantine/[email protected]":
version "7.12.1"
resolved "https://registry.npmjs.org/@mantine/core/-/core-7.12.1.tgz"
integrity sha512-PXKIDaT1fpNB77dPQIcdFGM2NRnfmsJSVx3uuBccngBQWMIWI0wPyiO1Y26DK4LQrbrypeb+TS+Zxpgx6RoiCA==
dependencies:
"@floating-ui/react" "^0.26.9"
clsx "^2.1.1"
Expand All @@ -360,6 +360,13 @@
react-textarea-autosize "8.5.3"
type-fest "^4.12.0"

"@mantine/dates@^7.12.1":
version "7.12.1"
resolved "https://registry.npmjs.org/@mantine/dates/-/dates-7.12.1.tgz"
integrity sha512-+Dg5ZGoYPWYRWPY7HagLeW36ayVjKQIkTpdNvgGDwh5YpaFy5cHd6LK6USKUshTsRPuzM3oUKwXIBK8hsigMyA==
dependencies:
clsx "^2.1.1"

"@mantine/form@^7.10.0":
version "7.10.1"
resolved "https://registry.npmjs.org/@mantine/form/-/form-7.10.1.tgz"
Expand All @@ -368,10 +375,10 @@
fast-deep-equal "^3.1.3"
klona "^2.0.6"

"@mantine/hooks@^7.9.2", "@mantine/hooks@7.10.1":
version "7.10.1"
resolved "https://registry.npmjs.org/@mantine/hooks/-/hooks-7.10.1.tgz"
integrity sha512-0EH9WBWUdtQLGU3Ak+csQ77EtUxI6pPNfwZdRJQWcaA3f8SFOLo9h9CGxiikFExerhvuCeUlaTf3s+TB9Op/rw==
"@mantine/hooks@^7.9.2", "@mantine/hooks@7.12.1":
version "7.12.1"
resolved "https://registry.npmjs.org/@mantine/hooks/-/hooks-7.12.1.tgz"
integrity sha512-YPA3qiMHJkWID5+YzakBaLvjHtX3Fg3PdPY49iIb/CaWM9+lrJ+77TOVS7bsY7ZTBHXUfzft1/6Woqt3xSuweA==

"@nodelib/[email protected]":
version "2.1.5"
Expand Down Expand Up @@ -899,6 +906,11 @@ date-fns@^3.6.0, date-fns@>=2.0.0:
resolved "https://registry.npmjs.org/date-fns/-/date-fns-3.6.0.tgz"
integrity sha512-fRHTG8g/Gif+kSh50gaGEdToemgfj74aRX3swtiouboip5JDLAyDE9F11nHMIcvOaXeOC6D7SpNhi7uFyB7Uww==

dayjs@>=1.0.0:
version "1.11.13"
resolved "https://registry.npmjs.org/dayjs/-/dayjs-1.11.13.tgz"
integrity sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==

debug@^4.1.0, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4, debug@^4.3.5:
version "4.3.5"
resolved "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz"
Expand Down Expand Up @@ -1479,9 +1491,9 @@ merge2@^1.3.0, merge2@^1.4.1:
integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==

micromatch@^4.0.4:
version "4.0.7"
resolved "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz"
integrity sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==
version "4.0.8"
resolved "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz"
integrity sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==
dependencies:
braces "^3.0.3"
picomatch "^2.3.1"
Expand Down

0 comments on commit 3b7b4d2

Please sign in to comment.