Showing error modal when clicking hotspot toggle on Docker.

This commit is contained in:
Roland 2022-10-22 14:27:18 -06:00
parent 1230a3056d
commit d28797326b
No known key found for this signature in database
GPG key ID: 9D6DBD3ACF11AB93
6 changed files with 178 additions and 56 deletions

View file

@ -3,7 +3,7 @@
<head>
<meta charset="utf-8"/>
<link rel="icon" href="%PUBLIC_URL%/favicon.ico"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"/>
<meta name="theme-color" content="#000000"/>
<meta
name="description"

View file

@ -8,6 +8,7 @@ import {Header, Segment, Statistic, StatisticGroup} from "./components/Theme";
import {Link} from "react-router-dom";
import {BandwidthProgressCombined, CPUUsageProgress} from "./components/admin/Status";
import {ProgressPlaceholder} from "./components/Placeholder";
import {Divider} from "semantic-ui-react";
export function Dashboard() {
useTitle('Dashboard');
@ -34,16 +35,16 @@ export function Dashboard() {
}
return (<PageContainer>
<SearchInput clearable
searchStr={searchStr}
onSubmit={setSearchStr}
size='large'
placeholder='Search Everywhere...'
actionIcon='search'
style={{marginBottom: '2em'}}
/>
{body}
</PageContainer>)
<SearchInput clearable
searchStr={searchStr}
onSubmit={setSearchStr}
size='large'
placeholder='Search Everywhere...'
actionIcon='search'
style={{marginBottom: '2em'}}
/>
{body}
</PageContainer>)
}
function DashboardStatus() {
@ -64,24 +65,28 @@ function DashboardStatus() {
pending_downloads = downloads['disabled'] ? 'x' : downloads['pending'];
}
let bandwidths = <ProgressPlaceholder/>;
if (status && status['bandwidth']) {
bandwidths = status['bandwidth'].map(i => <BandwidthProgressCombined key={i['name']} bandwidth={i}/>);
}
return <Segment>
<Link to='/admin/status'>
<Header as='h2'>Status</Header>
<CPUUsageProgress value={percent} label='CPU Usage'/>
<Header as='h3'>Load</Header>
<StatisticGroup size='mini'>
<LoadStatistic label='1 Minute' value={load['minute_1']} cores={cores}/>
<LoadStatistic label='5 Minute' value={load['minute_5']} cores={cores}/>
<LoadStatistic label='15 Minute' value={load['minute_15']} cores={cores}/>
<LoadStatistic label='1 Min. Load' value={load['minute_1']} cores={cores}/>
<LoadStatistic label='5 Min. Load' value={load['minute_5']} cores={cores}/>
<LoadStatistic label='15 Min. Load' value={load['minute_15']} cores={cores}/>
</StatisticGroup>
<Header as='h3'>Bandwidth</Header>
{status && status['bandwidth'] ? status['bandwidth'].map(i => <BandwidthProgressCombined key={i['name']}
bandwidth={i}/>) :
<ProgressPlaceholder/>}
{bandwidths}
</Link>
<Divider/>
<Link to='/admin'>
<StatisticGroup size='mini'>
<Statistic label='Downloading' value={pending_downloads}/>

View file

@ -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 = <Modal basic closeIcon
onOpen={onOpen}
onClose={onClose}
open={open}
>
<Header>
<Icon name={icon || 'exclamation triangle'}/>
{header || 'Unsupported'}
</Header>
<Modal.Content>
<Modal.Description>
{message}
</Modal.Description>
</Modal.Content>
<Modal.Actions>
<Button basic inverted onClick={onClose}>Ok</Button>
</Modal.Actions>
</Modal>;
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 <a href='#' onClick={toggleHotspot}>
<IconGroup size='large'>
<Icon name='wifi' disabled={on !== true}/>
{on === false && <Icon corner name='x'/>}
{on === null && <Icon corner name='question'/>}
</IconGroup>
</a>
return <>
<a href='#' onClick={toggleHotspot}>
<IconGroup size='large'>
<Icon name='wifi' disabled={on !== true}/>
{on === false && <Icon corner name='x'/>}
{on === null && <Icon corner name='question'/>}
</IconGroup>
</a>
{modal}
</>
}
export function useTitle(title) {

View file

@ -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 {
<pre style={{overflowX: 'scroll'}}>{error}</pre>
</Modal.Content>
<Modal.Actions>
<Button onClick={() => this.setState({errorModalOpen: false})}>Close</Button>
<SemanticButton onClick={() => this.setState({errorModalOpen: false})}>Close</SemanticButton>
</Modal.Actions>
</Modal>;

View file

@ -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 <Progress percent={percent} label={label} color={color} key={label}/>;
}
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 = <DiskBandwidthProgress
bytes_ps={bytes_read_ps}
total={total}
label={`${name} read`}
/>;
const write = <DiskBandwidthProgress
bytes_ps={bytes_write_ps}
total={total}
label={`${name} write`}
/>;
return <Grid columns={2}>
<Grid.Row>
<Grid.Column>{read}</Grid.Column>
<Grid.Column>{write}</Grid.Column>
</Grid.Row>
</Grid>
}
function CPUTemperatureStatistic({value, high_temperature, critical_temperature}) {
if (!value) {
return <Statistic label='Temp C°' value='?'/>
}
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 <Grid columns={2} stackable>
return <Grid columns={2}>
<Grid.Row>
<Grid.Column>
{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 <Progress percent={value} progress color={color} label={label}/>
}
@ -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 <>
<CPUUsageProgress value={percent} label='CPU Usage'/>
<CPUTemperatureStatistic
value={temperature}
high_temperature={high_temperature}
critical_temperature={critical_temperature}
/>
<Statistic label='Cores' value={cores || '?'}/>
<Responsive minWidth={770}>
<StatisticGroup>
<CPUTemperatureStatistic
value={temperature}
high_temperature={high_temperature}
critical_temperature={critical_temperature}
/>
<LoadStatistic label='1 Minute Load' value={minute_1} cores={cores}/>
<LoadStatistic label='5 Minute Load' value={minute_5} cores={cores}/>
<LoadStatistic label='15 Minute Load' value={minute_15} cores={cores}/>
</StatisticGroup>
<Divider/>
<Divider/>
<StatisticGroup>
<LoadStatistic label='1 Minute Load' value={minute_1} cores={cores}/>
<LoadStatistic label='5 Minute Load' value={minute_5} cores={cores}/>
<LoadStatistic label='15 Minute Load' value={minute_15} cores={cores}/>
</StatisticGroup>
<Header as='h1'>Network Bandwidth</Header>
{bandwidth ?
bandwidth.map(i => <BandwidthProgressGroup key={i['name']} bandwidth={i}/>) :
<ProgressPlaceholder/>}
<Divider/>
<Divider/>
<Header as='h1'>Bandwidth</Header>
{bandwidth ?
bandwidth.map(i => <BandwidthProgressGroup key={i['name']} bandwidth={i}/>) :
<ProgressPlaceholder/>}
<Header as='h1'>Drive Usage</Header>
{drives.map((drive) => <DriveInfo key={drive['mount']} {...drive}/>)}
<Divider/>
<Header as='h1'>Drive Bandwidth</Header>
{disk_bandwidth.map((disk) => <DiskBandwidth key={disk['name']} {...disk}/>)}
</Responsive>
<Responsive maxWidth={769}>
<StatisticGroup size='mini'>
<CPUTemperatureStatistic
value={temperature}
high_temperature={high_temperature}
critical_temperature={critical_temperature}
/>
<LoadStatistic label='1 Min. Load' value={minute_1} cores={cores}/>
<LoadStatistic label='5 Min. Load' value={minute_5} cores={cores}/>
<LoadStatistic label='15 Min. Load' value={minute_15} cores={cores}/>
</StatisticGroup>
<Header as='h1'>Drive Usage</Header>
{drives.map((drive) => <DriveInfo key={drive['mount']} {...drive}/>)}
<Header as='h2'>Network Bandwidth</Header>
{bandwidth ?
bandwidth.map(i => <BandwidthProgressGroup key={i['name']} bandwidth={i}/>) :
<ProgressPlaceholder/>}
<Header as='h2'>Drive Usage</Header>
{drives.map((drive) => <DriveInfo key={drive['mount']} {...drive}/>)}
<Header as='h2'>Drive Bandwidth</Header>
{disk_bandwidth.map((disk) => <DiskBandwidth key={disk['name']} {...disk}/>)}
</Responsive>
</>
}

View file

@ -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 = () => {