Using grey color by default for some Semantic elements when no color is provided.

This commit is contained in:
Roland 2022-09-29 14:58:16 -06:00
parent 335ad7ceb0
commit d82b7c12fb
No known key found for this signature in database
GPG key ID: 9D6DBD3ACF11AB93
6 changed files with 143 additions and 138 deletions

View file

@ -1,103 +1,22 @@
import React, {useContext, useState} from 'react';
import React, {useContext} from 'react';
import './App.css';
import {NavBar} from "./components/Nav";
import {Link, Route, Routes} from "react-router-dom";
import {Route, Routes} from "react-router-dom";
import {VideosRoute, VideoWrapper} from "./components/Videos";
import Admin from "./components/admin/Admin";
import {Container, Divider} from "semantic-ui-react";
import {Container} from "semantic-ui-react";
import 'semantic-ui-offline/semantic.min.css';
import {SemanticToastContainer} from 'react-semantic-toasts';
import 'react-semantic-toasts/styles/react-semantic-alert.css';
import {AppsRoute} from "./components/Apps";
import {InventoryRoute} from "./components/Inventory";
import {ArchiveRoute} from "./components/Archive";
import {DownloadMenu} from "./components/Upload";
import {LoadStatistic, PageContainer, SearchInput, useTitle} from "./components/Common";
import {FilesRoute, FilesSearchView} from "./components/Files";
import {useSearchFiles, useSettingsInterval, useStatus} from "./hooks/customHooks";
import {FilesRoute} from "./components/Files";
import {useSettingsInterval} from "./hooks/customHooks";
import {MapRoute} from "./components/Map";
import {SettingsContext, ThemeContext} from "./contexts/contexts";
import {Header, Segment, Statistic, StatisticGroup, ThemeWrapper} from "./components/Theme";
import {CPUUsageProgress} from "./components/admin/Status";
function Dashboard() {
useTitle('Dashboard');
const {searchStr, setSearchStr} = useSearchFiles();
const [downloadOpen, setDownloadOpen] = useState(false);
const onDownloadOpen = (name) => setDownloadOpen(!!name);
const {wrol_mode} = useContext(SettingsContext);
const downloads = <DownloadMenu onOpen={onDownloadOpen}/>;
// Only show dashboard parts if not searching.
let body;
if (searchStr) {
body = <FilesSearchView showLimit={true} showSelect={true} showSelectButton={true}/>;
} else {
body = <>
{!wrol_mode && downloads}
{/* Hide Status when user is starting a download */}
{!downloadOpen && <DashboardStatus/>}
</>;
}
return (
<PageContainer>
<SearchInput clearable
searchStr={searchStr}
onSubmit={setSearchStr}
size='large'
placeholder='Search Everywhere...'
actionIcon='search'
style={{marginBottom: '2em'}}
/>
{body}
</PageContainer>
)
}
function DashboardStatus() {
const {status} = useStatus();
let percent = 0;
let load = {};
let cores = 0;
let pending_downloads = '?';
if (status && status['cpu_info']) {
percent = status['cpu_info']['percent'];
load = status['load'];
cores = status['cpu_info']['cores'];
pending_downloads = status['downloads']['pending_downloads'];
}
const {download_manager_disabled, download_manager_stopped} = useContext(SettingsContext);
if (pending_downloads === 0 && (download_manager_disabled || download_manager_stopped)) {
pending_downloads = 'x';
}
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}/>
</StatisticGroup>
</Link>
<Divider/>
<Link to='/admin'>
<StatisticGroup size='mini'>
<Statistic label='Downloads' value={pending_downloads}/>
</StatisticGroup>
</Link>
</Segment>;
}
import {ThemeWrapper} from "./components/Theme";
import {Dashboard} from "./Dashboard";
function PageNotFound() {
return (

89
app/src/Dashboard.js Normal file
View file

@ -0,0 +1,89 @@
import {LoadStatistic, PageContainer, SearchInput, useTitle} from "./components/Common";
import {useSearchFiles, useStatus} from "./hooks/customHooks";
import React, {useContext, useState} from "react";
import {SettingsContext} from "./contexts/contexts";
import {DownloadMenu} from "./components/Upload";
import {FilesSearchView} from "./components/Files";
import {Header, Segment, Statistic, StatisticGroup} from "./components/Theme";
import {Link} from "react-router-dom";
import {CPUUsageProgress} from "./components/admin/Status";
import {Divider} from "semantic-ui-react";
export function Dashboard() {
useTitle('Dashboard');
const {searchStr, setSearchStr} = useSearchFiles();
const [downloadOpen, setDownloadOpen] = useState(false);
const onDownloadOpen = (name) => setDownloadOpen(!!name);
const {wrol_mode} = useContext(SettingsContext);
const downloads = <DownloadMenu onOpen={onDownloadOpen}/>;
// Only show dashboard parts if not searching.
let body;
if (searchStr) {
body = <FilesSearchView showLimit={true} showSelect={true} showSelectButton={true}/>;
} else {
body = <>
{!wrol_mode && downloads}
{/* Hide Status when user is starting a download */}
{!downloadOpen && <DashboardStatus/>}
</>;
}
return (
<PageContainer>
<SearchInput clearable
searchStr={searchStr}
onSubmit={setSearchStr}
size='large'
placeholder='Search Everywhere...'
actionIcon='search'
style={{marginBottom: '2em'}}
/>
{body}
</PageContainer>
)
}
function DashboardStatus() {
const {status} = useStatus();
let percent = 0;
let load = {};
let cores = 0;
let pending_downloads = '?';
if (status && status['cpu_info']) {
percent = status['cpu_info']['percent'];
load = status['load'];
cores = status['cpu_info']['cores'];
pending_downloads = status['downloads']['pending_downloads'];
}
const {download_manager_disabled, download_manager_stopped} = useContext(SettingsContext);
if (pending_downloads === 0 && (download_manager_disabled || download_manager_stopped)) {
pending_downloads = 'x';
}
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}/>
</StatisticGroup>
</Link>
<Divider/>
<Link to='/admin'>
<StatisticGroup size='mini'>
<Statistic label='Downloading' value={pending_downloads}/>
</StatisticGroup>
</Link>
</Segment>;
}

View file

@ -1,11 +1,11 @@
import React, {useContext, useEffect, useState} from "react";
import {Card, Container, Image, Input, Pagination, Popup, Responsive, TableCell, TableRow} from 'semantic-ui-react';
import {Card, Container, Image, Input, 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";
import {getSettings} from "../api";
import {darkTheme, SettingsContext, ThemeContext} from "../contexts/contexts";
import {Button, CardIcon, Form, Header, Icon, Menu, Statistic} from "./Theme";
import {Button, CardIcon, Form, Header, Icon, Menu, Popup, Statistic} from "./Theme";
export const API_URI = `http://${window.location.host}/api`;
export const VIDEOS_API = `${API_URI}/videos`;
@ -835,17 +835,15 @@ export function FileIcon({file, disabled = true, size = 'huge', ...props}) {
}
export function LoadStatistic({label, value, cores, ...props}) {
let color;
const quarter = cores / 4;
if (cores && value >= (quarter * 3)) {
color = 'red';
props['color'] = 'red';
} else if (cores && value >= (quarter * 2)) {
color = 'orange';
props['color'] = 'orange';
}
return <Statistic
label={label}
value={value ? parseFloat(value).toFixed(1) : '?'}
color={color}
{...props}/>;
}

View file

@ -105,21 +105,29 @@ const invertedNull = (props) => {
return props;
}
const defaultGrey = (props, inverted) => {
// Some elements look softer when grey, use grey only if another color is not provided.
if (inverted) {
return {color: 'grey', ...props};
}
return props;
}
export function Button(props) {
const {i} = useContext(ThemeContext);
props = {...i, ...props};
const {i, inverted} = useContext(ThemeContext);
props = defaultGrey({...i, ...props}, inverted);
return <BUTTON {...props}/>
}
export function Accordion(props) {
const {i} = useContext(ThemeContext);
props = {...i, ...props};
const {i, inverted} = useContext(ThemeContext);
props = defaultGrey({...i, ...props}, inverted);
return <ACCORDION {...props}/>
}
export function Header(props) {
const {i} = useContext(ThemeContext);
props = {...i, ...props};
const {i, inverted} = useContext(ThemeContext);
props = defaultGrey({...i, ...props}, inverted);
return <HEADER {...props}/>
}
@ -191,8 +199,8 @@ export function Segment(props) {
}
export function Statistic(props) {
const {i} = useContext(ThemeContext);
props = {...i, ...props};
const {i, inverted} = useContext(ThemeContext);
props = defaultGrey({...i, ...props}, inverted);
return <STATISTIC {...props}/>
}

View file

@ -5,7 +5,7 @@ import Icon from "semantic-ui-react/dist/commonjs/elements/Icon";
import Message from "semantic-ui-react/dist/commonjs/collections/Message";
import {ThemeContext} from "../contexts/contexts";
import {Button, Form, FormInput, Header, Loader, TextArea} from "./Theme";
import {FormDropdown} from "semantic-ui-react";
import {ButtonGroup, FormDropdown} from "semantic-ui-react";
const validUrl = /^(http|https):\/\/[^ "]+$/;
@ -13,10 +13,7 @@ class Downloader extends React.Component {
constructor(props) {
super(props);
this.state = {
urls: '',
valid: true,
pending: false,
downloader: props.downloader,
urls: '', valid: true, pending: false, downloader: props.downloader,
};
}
@ -58,20 +55,18 @@ class Downloader extends React.Component {
const {header} = this.props;
return <ThemeContext.Consumer>
{({i}) => (
<Form onSubmit={this.submitDownload}>
<WROLModeMessage content='Downloading is disabled while WROL Mode is enabled'/>
<Header as='h3'>{header}</Header>
<TextArea required
placeholder={'Enter one URL per line'}
name='urls'
onChange={this.handleInputChange}
value={this.state.urls}
/>
<Button content='Cancel' onClick={this.props.clearSelected}/>
<Button primary style={{marginTop: '1em'}} disabled={disabled}>Download</Button>
</Form>
)}
{({i}) => (<Form onSubmit={this.submitDownload}>
<WROLModeMessage content='Downloading is disabled while WROL Mode is enabled'/>
<Header as='h3'>{header}</Header>
<TextArea required
placeholder={'Enter one URL per line'}
name='urls'
onChange={this.handleInputChange}
value={this.state.urls}
/>
<Button content='Cancel' onClick={this.props.clearSelected}/>
<Button primary style={{marginTop: '1em'}} disabled={disabled}>Download</Button>
</Form>)}
</ThemeContext.Consumer>
}
}
@ -80,18 +75,9 @@ class ChannelDownload extends React.Component {
constructor(props) {
super(props);
this.state = {
url: '',
frequency: 604800,
pending: false,
disabled: false,
ready: false,
error: null,
success: null,
url: '', frequency: 604800, pending: false, disabled: false, ready: false, error: null, success: null,
};
this.freqOptions = [
{key: 'once', text: 'Once', value: 0},
...frequencyOptions,
];
this.freqOptions = [{key: 'once', text: 'Once', value: 0}, ...frequencyOptions,];
this.handleUrlChange = this.handleUrlChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
this.handleFrequencyChange = this.handleFrequencyChange.bind(this);
@ -289,13 +275,13 @@ export function DownloadMenu({onOpen}) {
onOpen(name)
}
let body = (<>
<Button content='Videos' onClick={() => localOnOpen('video')} style={{marginBottom: '1em'}}/>
<Button content='Archive' onClick={() => localOnOpen('archive')} style={{marginBottom: '1em'}}/>
<Button content='Channel/Playlist' onClick={() => localOnOpen('video_channel')}
let body = (<ButtonGroup>
<Button color='blue' content='Videos' onClick={() => localOnOpen('video')} style={{marginBottom: '1em'}}/>
<Button color='green' content='Archive' onClick={() => localOnOpen('archive')} style={{marginBottom: '1em'}}/>
<Button color='blue' content='Channel/Playlist' onClick={() => localOnOpen('video_channel')}
style={{marginBottom: '1em'}}/>
<Button content='RSS Feed' onClick={() => localOnOpen('rss')} style={{marginBottom: '1em'}}/>
</>);
</ButtonGroup>);
function clearSelected() {
localOnOpen(null);

View file

@ -97,6 +97,11 @@ export class Settings extends React.Component {
this.setState({[name]: value});
}
handleQrOpen = async (e) => {
e.preventDefault();
this.setState({qrOpen: true});
}
render() {
if (this.state.ready === false) {
return <Loader active inline='centered'/>
@ -199,7 +204,7 @@ export class Settings extends React.Component {
<Modal closeIcon
onClose={() => this.setState({qrOpen: false})}
onOpen={() => this.setState({qrOpen: true})}
onOpen={this.handleQrOpen}
open={this.state.qrOpen}
trigger={qrButton}
>