Adding Segment around Status elements.

This commit is contained in:
Roland 2022-12-02 11:23:05 -07:00
parent 9137537a3b
commit 964e5325f9
No known key found for this signature in database
GPG key ID: 9D6DBD3ACF11AB93
4 changed files with 333 additions and 314 deletions

View file

@ -256,173 +256,175 @@ function ChannelPage({create, header}) {
<Button>Videos</Button>
</Link>}
<Header as="h1">{header}</Header>
<WROLModeMessage content='Channel page is disabled while WROL Mode is enabled.'/>
<Form
id="editChannel"
onSubmit={handleSubmit}
error={error}
success={success}
autoComplete="off"
>
<FormGroup>
<FormField width={8}>
<FormInput required
label="Channel Name"
name="name"
type="text"
placeholder="Short Channel Name"
disabled={disabled}
error={errors.name}
value={channel.name}
onChange={(e, {value}) => changeValue('name', value)}
/>
</FormField>
<FormField width={8}>
<label>
Directory <RequiredAsterisk/>
</label>
<DirectoryInput required
disabled={create === undefined}
value={channel.directory}
setInput={value => changeValue('directory', value)}
placeholder='videos/channel directory'
/>
</FormField>
</FormGroup>
{
create !== undefined &&
<Segment>
<Header as="h1">{header}</Header>
<WROLModeMessage content='Channel page is disabled while WROL Mode is enabled.'/>
<Form
id="editChannel"
onSubmit={handleSubmit}
error={error}
success={success}
autoComplete="off"
>
<FormGroup>
<FormField width={8}/>{/* Empty field*/}
<FormField width={8}>
<FormField>
<Toggle
toggle
label="Create this directory, if it doesn't exist."
name="mkdir"
disabled={disabled}
error={errors.mkdir}
checked={channel.mkdir}
onChange={i => {
handleCheckbox(null, {name: 'mkdir', checked: i})
}}
/>
</FormField>
<FormInput required
label="Channel Name"
name="name"
type="text"
placeholder="Short Channel Name"
disabled={disabled}
error={errors.name}
value={channel.name}
onChange={(e, {value}) => changeValue('name', value)}
/>
</FormField>
<FormField width={8}>
<label>
Directory <RequiredAsterisk/>
</label>
<DirectoryInput required
disabled={create === undefined}
value={channel.directory}
setInput={value => changeValue('directory', value)}
placeholder='videos/channel directory'
/>
</FormField>
</FormGroup>
}
<FormGroup>
<FormField width={16}>
<FormInput
label="URL"
name="url"
type="url"
disabled={disabled}
placeholder='https://example.com/channel/videos'
error={errors.url}
value={channel.url}
onChange={handleInputChange}
/>
</FormField>
</FormGroup>
<FormGroup>
<FormField>
<label>Download Frequency</label>
<Dropdown selection
name='download_frequency'
placeholder='Frequency'
error={errors.download_frequency}
value={channel.download_frequency}
disabled={disabled || !channel.url}
options={frequencyOptions}
onChange={handleInputChange}
/>
</FormField>
</FormGroup>
<Accordion style={{marginBottom: '1em'}}>
<AccordionTitle
onClick={handleAdvancedClick}
index={0}
active={activeIndex === 0}
>
<Icon name='dropdown'/>
Advanced Settings
</AccordionTitle>
<AccordionContent active={activeIndex === 0}>
<Segment secondary>
<Header as="h4">
The following settings are encouraged by default, modify them at your own risk.
</Header>
<FormField>
<FormInput
label="Title Match Regex"
name="match_regex"
type="text"
disabled={disabled}
error={!validRegex}
placeholder='.*([Nn]ame Matching).*'
value={channel.match_regex}
onChange={checkRegex}
/>
</FormField>
</Segment>
</AccordionContent>
</Accordion>
<Message error
header={messageHeader}
content={messageContent}
/>
<Message success
header={messageHeader}
content={messageContent}
/>
<Grid stackable columns={2}>
<Grid.Row>
<Grid.Column>
{!create &&
<>
<Button color='red' onClick={handleDeleteButton} size='small'>
Delete
</Button>
<Confirm
open={deleteOpen}
content='Are you sure you want to delete this channel? No video files will be deleted.'
confirmButton='Delete'
onCancel={() => setDeleteOpen(false)}
onConfirm={handleDeleteConfirm}
{
create !== undefined &&
<FormGroup>
<FormField width={8}/>{/* Empty field*/}
<FormField width={8}>
<FormField>
<Toggle
toggle
label="Create this directory, if it doesn't exist."
name="mkdir"
disabled={disabled}
error={errors.mkdir}
checked={channel.mkdir}
onChange={i => {
handleCheckbox(null, {name: 'mkdir', checked: i})
}}
/>
<Button
color='violet'
size='small'
onClick={handleDownloadChannel}
disabled={!channel.url || !channel.download_frequency}
>
Download
</Button>
<Button color='blue' size='small' onClick={handleRefreshChannel}>
Refresh
</Button>
</>
}
</Grid.Column>
<Grid.Column>
<Button
color="green"
size='big'
type="submit"
floated='right'
>
{disabled ? <Loader active inline/> : 'Save'}
</Button>
</Grid.Column>
</Grid.Row>
</Grid>
</FormField>
</FormField>
</FormGroup>
}
<FormGroup>
<FormField width={16}>
<FormInput
label="URL"
name="url"
type="url"
disabled={disabled}
placeholder='https://example.com/channel/videos'
error={errors.url}
value={channel.url}
onChange={handleInputChange}
/>
</FormField>
</FormGroup>
</Form>
<FormGroup>
<FormField>
<label>Download Frequency</label>
<Dropdown selection
name='download_frequency'
placeholder='Frequency'
error={errors.download_frequency}
value={channel.download_frequency}
disabled={disabled || !channel.url}
options={frequencyOptions}
onChange={handleInputChange}
/>
</FormField>
</FormGroup>
<Accordion style={{marginBottom: '1em'}}>
<AccordionTitle
onClick={handleAdvancedClick}
index={0}
active={activeIndex === 0}
>
<Icon name='dropdown'/>
Advanced Settings
</AccordionTitle>
<AccordionContent active={activeIndex === 0}>
<Segment secondary>
<Header as="h4">
The following settings are encouraged by default, modify them at your own risk.
</Header>
<FormField>
<FormInput
label="Title Match Regex"
name="match_regex"
type="text"
disabled={disabled}
error={!validRegex}
placeholder='.*([Nn]ame Matching).*'
value={channel.match_regex}
onChange={checkRegex}
/>
</FormField>
</Segment>
</AccordionContent>
</Accordion>
<Message error
header={messageHeader}
content={messageContent}
/>
<Message success
header={messageHeader}
content={messageContent}
/>
<Grid stackable columns={2}>
<Grid.Row>
<Grid.Column>
{!create &&
<>
<Button color='red' onClick={handleDeleteButton} size='small'>
Delete
</Button>
<Confirm
open={deleteOpen}
content='Are you sure you want to delete this channel? No video files will be deleted.'
confirmButton='Delete'
onCancel={() => setDeleteOpen(false)}
onConfirm={handleDeleteConfirm}
/>
<Button
color='violet'
size='small'
onClick={handleDownloadChannel}
disabled={!channel.url || !channel.download_frequency}
>
Download
</Button>
<Button color='blue' size='small' onClick={handleRefreshChannel}>
Refresh
</Button>
</>
}
</Grid.Column>
<Grid.Column>
<Button
color="green"
size='big'
type="submit"
floated='right'
>
{disabled ? <Loader active inline/> : 'Save'}
</Button>
</Grid.Column>
</Grid.Row>
</Grid>
</Form>
</Segment>
<div style={{marginTop: '2em'}}>
{channel.statistics && <ChannelStatistics statistics={channel.statistics}/>}

View file

@ -1,10 +1,10 @@
import React from 'react';
import {Container} from "semantic-ui-react";
import {getStatus, saveSettings} from "../../api";
import {PageContainer, TabLinks, Toggle, useTitle} from "../Common";
import {PageContainer, TabLinks, Toggle} from "../Common";
import {Route, Routes} from "react-router-dom";
import {ThemeContext} from "../../contexts/contexts";
import {Header, Loader} from "../Theme";
import {Header, Loader, Segment} from "../Theme";
import {Downloads} from "./Downloads";
import {Settings} from "./Settings";
import {Status} from "./Status";
@ -44,19 +44,21 @@ class WROLMode extends React.Component {
return <ThemeContext.Consumer>
{({t}) => <Container fluid>
<Header as="h1">WROL Mode</Header>
<Header as='h4'>
Enable read-only mode. No content can be deleted or modified. Enable this when the SHTF and you
want to prevent any potential loss of data.
</Header>
<p {...t}>
Note: User settings and favorites can still be modified.
</p>
<Toggle
checked={this.state.WROLMode}
onChange={this.toggleWROLMode}
label={this.state.WROLMode ? 'WROL Mode Enabled' : 'WROL Mode Disabled'}
/>
<Segment>
<Header as="h1">WROL Mode</Header>
<Header as='h4'>
Enable read-only mode. No content can be deleted or modified. Enable this when the SHTF and you
want to prevent any potential loss of data.
</Header>
<p {...t}>
Note: User settings and favorites can still be modified.
</p>
<Toggle
checked={this.state.WROLMode}
onChange={this.toggleWROLMode}
label={this.state.WROLMode ? 'WROL Mode Enabled' : 'WROL Mode Disabled'}
/>
</Segment>
</Container>}
</ThemeContext.Consumer>

View file

@ -1,7 +1,7 @@
import React from "react";
import {getSettings, saveSettings} from "../../api";
import {Button, Form, FormField, FormGroup, FormInput, Header, Loader} from "../Theme";
import {Container, Dimmer, Divider, Icon, Modal} from "semantic-ui-react";
import {Button, Form, FormField, FormGroup, FormInput, Header, Loader, Segment} from "../Theme";
import {Container, Dimmer, Icon, Modal} from "semantic-ui-react";
import {ThemeContext} from "../../contexts/contexts";
import {HelpPopup, HotspotToggle, ThrottleToggle, Toggle, WROLModeMessage} from "../Common";
import QRCode from "react-qr-code";
@ -127,112 +127,115 @@ export class Settings extends React.Component {
{({i, t}) => <Container fluid>
<WROLModeMessage content='Settings are disabled because WROL Mode is enabled.'/>
<HotspotToggle/>
<ThrottleToggle/>
<Divider/>
<Segment>
<HotspotToggle/>
<ThrottleToggle/>
</Segment>
<Header as='h3'>
The settings for your WROLPi.
</Header>
<p {...t}>
Any changes will be written to <i>config/wrolpi.yaml</i>.
</p>
<Segment>
<Header as='h2'>
Settings
</Header>
<p {...t}>
Any changes will be written to <i>config/wrolpi.yaml</i>.
</p>
<Form id="settings" onSubmit={this.handleSubmit}>
<div style={{margin: '0.5em'}}>
<Toggle
label='Download on Startup'
disabled={disabled || download_on_startup === null}
checked={download_on_startup === true}
onChange={checked => this.handleInputChange(null, 'download_on_startup', checked)}
/>
</div>
<Form id="settings" onSubmit={this.handleSubmit}>
<div style={{margin: '0.5em'}}>
<Toggle
label='Download on Startup'
disabled={disabled || download_on_startup === null}
checked={download_on_startup === true}
onChange={checked => this.handleInputChange(null, 'download_on_startup', checked)}
/>
</div>
<div style={{margin: '0.5em'}}>
<Toggle
label='WiFi Hotspot on Startup'
disabled={disabled || hotspot_on_startup === null}
checked={hotspot_on_startup === true}
onChange={checked => this.handleInputChange(null, 'hotspot_on_startup', checked)}
/>
</div>
<div style={{margin: '0.5em'}}>
<Toggle
label='WiFi Hotspot on Startup'
disabled={disabled || hotspot_on_startup === null}
checked={hotspot_on_startup === true}
onChange={checked => this.handleInputChange(null, 'hotspot_on_startup', checked)}
/>
</div>
<div style={{margin: '0.5em'}}>
<Toggle
label='CPU Power-save on Startup'
disabled={disabled || throttle_on_startup === null}
checked={throttle_on_startup === true}
onChange={checked => this.handleInputChange(null, 'throttle_on_startup', checked)}
/>
</div>
<div style={{margin: '0.5em'}}>
<Toggle
label='CPU Power-save on Startup'
disabled={disabled || throttle_on_startup === null}
checked={throttle_on_startup === true}
onChange={checked => this.handleInputChange(null, 'throttle_on_startup', checked)}
/>
</div>
<FormGroup inline>
<FormInput
label={<>
<b {...t}>Download Timeout</b>
<HelpPopup content='Downloads will be stopped after this many seconds have elapsed.
<FormGroup inline>
<FormInput
label={<>
<b {...t}>Download Timeout</b>
<HelpPopup content='Downloads will be stopped after this many seconds have elapsed.
Downloads will never timeout if this is empty.'/>
</>}
value={download_timeout}
disabled={disabled || download_timeout === null}
onChange={(e, d) => this.handleTimeoutChange(e, 'download_timeout', d.value)}
/>
</FormGroup>
</>}
value={download_timeout}
disabled={disabled || download_timeout === null}
onChange={(e, d) => this.handleTimeoutChange(e, 'download_timeout', d.value)}
/>
</FormGroup>
<FormGroup inline>
<FormInput
label='Hotspot SSID'
value={hotspot_ssid}
disabled={disabled || hotspot_ssid === null}
onChange={(e, d) =>
this.setState({hotspot_ssid: d.value}, this.handleHotspotChange)}
/>
<FormInput
label='Hotspot Password'
disabled={disabled || hotspot_password === null}
value={hotspot_password}
onChange={(e, d) =>
this.setState({hotspot_password: d.value}, this.handleHotspotChange)}
/>
<FormInput
label='Hotspot Device'
disabled={disabled || hotspot_password === null}
value={hotspot_device}
onChange={(e, d) => this.handleInputChange(e, 'hotspot_device', d.value)}
/>
</FormGroup>
<FormGroup inline>
<FormInput
label='Hotspot SSID'
value={hotspot_ssid}
disabled={disabled || hotspot_ssid === null}
onChange={(e, d) =>
this.setState({hotspot_ssid: d.value}, this.handleHotspotChange)}
/>
<FormInput
label='Hotspot Password'
disabled={disabled || hotspot_password === null}
value={hotspot_password}
onChange={(e, d) =>
this.setState({hotspot_password: d.value}, this.handleHotspotChange)}
/>
<FormInput
label='Hotspot Device'
disabled={disabled || hotspot_password === null}
value={hotspot_device}
onChange={(e, d) => this.handleInputChange(e, 'hotspot_device', d.value)}
/>
</FormGroup>
<Modal closeIcon
onClose={() => this.setState({qrOpen: false})}
onOpen={this.handleQrOpen}
open={this.state.qrOpen}
trigger={qrButton}
>
<Modal.Header>
Scan this code to join the hotspot
</Modal.Header>
<Modal.Content>
<QRCode value={qrCodeValue} size={300}/>
</Modal.Content>
</Modal>
<Modal closeIcon
onClose={() => this.setState({qrOpen: false})}
onOpen={this.handleQrOpen}
open={this.state.qrOpen}
trigger={qrButton}
>
<Modal.Header>
Scan this code to join the hotspot
</Modal.Header>
<Modal.Content>
<QRCode value={qrCodeValue} size={300}/>
</Modal.Content>
</Modal>
<FormField>
<label>Timezone</label>
<TimezoneSelect
value={timezone}
onChange={i => this.handleInputChange(null, 'timezone', i)}
/>
</FormField>
<FormField>
<label>Timezone</label>
<TimezoneSelect
value={timezone}
onChange={i => this.handleInputChange(null, 'timezone', i)}
/>
</FormField>
<Button color="blue" type="submit" disabled={disabled}>
Save
</Button>
<Button color="blue" type="submit" disabled={disabled}>
Save
</Button>
<Dimmer active={pending}>
<Loader active={pending} size='large'/>
</Dimmer>
<Dimmer active={pending}>
<Loader active={pending} size='large'/>
</Dimmer>
</Form>
</Form>
</Segment>
</Container>
}
</ThemeContext.Consumer>

View file

@ -1,7 +1,7 @@
import {Header, Progress, Segment, Statistic, StatisticGroup} from "../Theme";
import React, {useContext} from "react";
import {humanBandwidth, humanFileSize, LoadStatistic, useTitle} from "../Common";
import {Divider, Responsive} from "semantic-ui-react";
import {Responsive} from "semantic-ui-react";
import {ProgressPlaceholder} from "../Placeholder";
import Grid from "semantic-ui-react/dist/commonjs/collections/Grid";
import {StatusContext} from "../../contexts/contexts";
@ -182,56 +182,68 @@ export function Status() {
}
return <>
<CPUUsageProgress value={percent} label='CPU Usage'/>
<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>
<Segment>
<CPUUsageProgress value={percent} label='CPU Usage'/>
<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>
</Segment>
<Header as='h1'>Network Bandwidth</Header>
{bandwidth ?
bandwidth.map(i => <BandwidthProgressGroup key={i['name']} bandwidth={i}/>) :
<ProgressPlaceholder/>}
<Segment>
<Header as='h1'>Network Bandwidth</Header>
{bandwidth ? bandwidth.map(i => <BandwidthProgressGroup key={i['name']} bandwidth={i}/>) :
<ProgressPlaceholder/>}
</Segment>
<Divider/>
<Segment>
<Header as='h1'>Drive Usage</Header>
{drives.map((drive) => <DriveInfo key={drive['mount']} {...drive}/>)}
</Segment>
<Header as='h1'>Drive Usage</Header>
{drives.map((drive) => <DriveInfo key={drive['mount']} {...drive}/>)}
<Header as='h1'>Drive Bandwidth</Header>
{disk_bandwidth.map((disk) => <DiskBandwidth key={disk['name']} {...disk}/>)}
<Segment>
<Header as='h1'>Drive Bandwidth</Header>
{disk_bandwidth.map((disk) => <DiskBandwidth key={disk['name']} {...disk}/>)}
</Segment>
</Responsive>
<Responsive maxWidth={769}>
<StatisticGroup size='mini'>
<CPUTemperatureStatistic
value={temperature}
high_temperature={high_temperature}
critical_temperature={critical_temperature}
style={{marginRight: 0}}
/>
<LoadStatistic label='1 Min. Load' value={minute_1} cores={cores}/>
<LoadStatistic label='5 Min.' value={minute_5} cores={cores}/>
<LoadStatistic label='15 Min.' value={minute_15} cores={cores}/>
</StatisticGroup>
<Segment>
<CPUUsageProgress value={percent} label='CPU Usage'/>
<StatisticGroup size='mini'>
<CPUTemperatureStatistic
value={temperature}
high_temperature={high_temperature}
critical_temperature={critical_temperature}
style={{marginRight: 0}}
/>
<LoadStatistic label='1 Min. Load' value={minute_1} cores={cores}/>
<LoadStatistic label='5 Min.' value={minute_5} cores={cores}/>
<LoadStatistic label='15 Min.' value={minute_15} cores={cores}/>
</StatisticGroup>
</Segment>
<Header as='h2'>Network Bandwidth</Header>
{bandwidth ?
bandwidth.map(i => <BandwidthProgressGroup key={i['name']} bandwidth={i}/>) :
<ProgressPlaceholder/>}
<Segment>
<Header as='h2'>Network Bandwidth</Header>
{bandwidth ? bandwidth.map(i => <BandwidthProgressGroup key={i['name']} bandwidth={i}/>) :
<ProgressPlaceholder/>}
</Segment>
<Header as='h2'>Drive Usage</Header>
{drives.map((drive) => <DriveInfo key={drive['mount']} {...drive}/>)}
<Segment>
<Header as='h2'>Drive Usage</Header>
{drives.map((drive) => <DriveInfo key={drive['mount']} {...drive}/>)}
</Segment>
<Header as='h2'>Drive Bandwidth</Header>
{disk_bandwidth.map((disk) => <DiskBandwidth key={disk['name']} {...disk}/>)}
<Segment>
<Header as='h2'>Drive Bandwidth</Header>
{disk_bandwidth.map((disk) => <DiskBandwidth key={disk['name']} {...disk}/>)}
</Segment>
</Responsive>
</>
}