diff --git a/app/public/index.html b/app/public/index.html index 1faaf9b3..2c352473 100644 --- a/app/public/index.html +++ b/app/public/index.html @@ -3,7 +3,7 @@ - + - - {body} - ) + + {body} + ) } function DashboardStatus() { @@ -64,24 +65,28 @@ function DashboardStatus() { pending_downloads = downloads['disabled'] ? 'x' : downloads['pending']; } + let bandwidths = ; + if (status && status['bandwidth']) { + bandwidths = status['bandwidth'].map(i => ); + } + return
Status
-
Load
- - - + + +
Bandwidth
- {status && status['bandwidth'] ? status['bandwidth'].map(i => ) : - } + {bandwidths} + + diff --git a/app/src/components/Common.js b/app/src/components/Common.js index 4b009aa8..65c670a9 100644 --- a/app/src/components/Common.js +++ b/app/src/components/Common.js @@ -1,5 +1,16 @@ import React, {useContext, useEffect, useState} from "react"; -import {Card, Container, IconGroup, Image, Input, Pagination, Responsive, TableCell, TableRow} from 'semantic-ui-react'; +import { + Card, + Container, + IconGroup, + Image, + Input, + Modal, + Pagination, + Responsive, + TableCell, + TableRow +} from 'semantic-ui-react'; import {Link, NavLink} from "react-router-dom"; import Message from "semantic-ui-react/dist/commonjs/collections/Message"; import {useDownloaders, useHotspot, useThrottle} from "../hooks/customHooks"; @@ -734,22 +745,61 @@ export function DarkModeToggle() { } + +export function UnsupportedModal(header, message, icon) { + const [open, setOpen] = useState(false); + const onOpen = () => setOpen(true); + const onClose = () => setOpen(false); + + const modal = +
+ + {header || 'Unsupported'} +
+ + + {message} + + + + + +
; + + return {modal, doClose: onClose, doOpen: onOpen}; +} + export function HotspotStatusIcon() { - const {on, setHotspot} = useHotspot(); + const {on, setHotspot, dockerized} = useHotspot(); + const {modal, doOpen} = UnsupportedModal( + 'Unsupported on Docker', + 'You cannot toggle the hotspot on Docker.' + ); + const toggleHotspot = (e) => { e.preventDefault(); + if (dockerized) { + doOpen(); + } if (on != null) { setHotspot(!on); } } - return - - - {on === false && } - {on === null && } - - + return <> + + + + {on === false && } + {on === null && } + + + {modal} + } export function useTitle(title) { diff --git a/app/src/components/admin/Downloads.js b/app/src/components/admin/Downloads.js index d3c85a1f..cb5de503 100644 --- a/app/src/components/admin/Downloads.js +++ b/app/src/components/admin/Downloads.js @@ -1,4 +1,4 @@ -import React, {useContext} from "react"; +import React, {useContext, useState} from "react"; import {clearCompletedDownloads, clearFailedDownloads, killDownload, postDownload} from "../../api"; import {Link} from "react-router-dom"; import { @@ -9,6 +9,7 @@ import { WROLModeMessage } from "../Common"; import { + Button as SemanticButton, Confirm, Modal, PlaceholderLine, @@ -18,7 +19,7 @@ import { TableHeaderCell, TableRow } from "semantic-ui-react"; -import {Button, Header, Placeholder, Table} from "../Theme"; +import {Button, Header, Icon, Placeholder, Table} from "../Theme"; import {ThemeContext} from "../../contexts/contexts"; import {useDownloads} from "../../hooks/customHooks"; @@ -113,7 +114,7 @@ class DownloadRow extends React.Component {
{error}
- + this.setState({errorModalOpen: false})}>Close ; diff --git a/app/src/components/admin/Status.js b/app/src/components/admin/Status.js index 7ce2c4af..0cb896fe 100644 --- a/app/src/components/admin/Status.js +++ b/app/src/components/admin/Status.js @@ -1,7 +1,7 @@ import {Header, Progress, Statistic, StatisticGroup} from "../Theme"; import React, {useContext} from "react"; import {humanBandwidth, humanFileSize, LoadStatistic} from "../Common"; -import {Divider} from "semantic-ui-react"; +import {Divider, Responsive} from "semantic-ui-react"; import {ProgressPlaceholder} from "../Placeholder"; import Grid from "semantic-ui-react/dist/commonjs/collections/Grid"; import {StatusContext} from "../../contexts/contexts"; @@ -21,10 +21,51 @@ function DriveInfo({used, size, percent, mount}) { /> } +function DiskBandwidthProgress({bytes_ps, total, label}) { + let percent = bytes_ps / total; + percent = percent || 0; + let color = null; + if (percent >= 90) { + color = 'red'; + } else if (percent >= 80) { + color = 'orange'; + } else if (percent >= 50) { + color = 'yellow'; + } + label = `${label} ${humanBandwidth(bytes_ps)}`; + return ; +} + +function DiskBandwidth({name, bytes_read_ps, bytes_write_ps}) { + const total = 10_000_000; // Arbitrary size. What is the real speed of the disk? + + const read = ; + const write = ; + + return + + {read} + {write} + + +} + function CPUTemperatureStatistic({value, high_temperature, critical_temperature}) { if (!value) { return } + if (critical_temperature && critical_temperature === high_temperature) { + // Critical and high are equal, manually change it so high changes color before critical. + high_temperature = critical_temperature - 25; + } const props = {}; if ((critical_temperature && value >= critical_temperature) || (!critical_temperature && value >= 75)) { props['color'] = 'red'; @@ -66,7 +107,7 @@ export function BandwidthProgressGroup({bandwidth, ...props}) { {...props} />; - return + return {recv} @@ -96,8 +137,6 @@ export function CPUUsageProgress({value, label}) { color = 'brown'; } else if (value >= 50) { color = 'orange'; - } else if (value >= 30) { - color = 'green'; } return } @@ -115,6 +154,7 @@ export function Status() { let minute_15; let bandwidth; let drives = []; + let disk_bandwidth = []; if (status && status['cpu_info']) { const {cpu_info, load} = status; @@ -130,36 +170,61 @@ export function Status() { drives = status['drives']; bandwidth = status['bandwidth']; + disk_bandwidth = status['disk_bandwidth']; } return <> - - + + + + + + + - + - - - - - +
Network Bandwidth
+ {bandwidth ? + bandwidth.map(i => ) : + } - + -
Bandwidth
- {bandwidth ? - bandwidth.map(i => ) : - } +
Drive Usage
+ {drives.map((drive) => )} - +
Drive Bandwidth
+ {disk_bandwidth.map((disk) => )} +
+ + + + + + + -
Drive Usage
- {drives.map((drive) => )} +
Network Bandwidth
+ {bandwidth ? + bandwidth.map(i => ) : + } + +
Drive Usage
+ {drives.map((drive) => )} + +
Drive Bandwidth
+ {disk_bandwidth.map((disk) => )} +
} diff --git a/app/src/hooks/customHooks.js b/app/src/hooks/customHooks.js index 6ff24c54..7f92941b 100644 --- a/app/src/hooks/customHooks.js +++ b/app/src/hooks/customHooks.js @@ -10,7 +10,6 @@ import { getDownloaders, getDownloads, getFiles, - getHotspotStatus, getInventory, getSettings, getStatistics, @@ -462,6 +461,8 @@ export const useBrowseFiles = () => { export const useHotspot = () => { const [on, setOn] = useState(null); const {status} = useContext(StatusContext); + // Hotspot is unsupported on Docker. + const {dockerized} = status; useEffect(() => { if (status && status['hotspot_status']) { @@ -481,7 +482,7 @@ export const useHotspot = () => { await setHotspot(on); } - return {on, setOn, setHotspot: localSetHotspot}; + return {on, setOn, setHotspot: localSetHotspot, dockerized}; } export const useDownloads = () => {