import React from 'react'; import { Button, Checkbox, Confirm, Container, Divider, Form, Header, Loader, Placeholder, Table } from "semantic-ui-react"; import { getConfig, getDownloaders, getDownloads, killDownload, killDownloads, postDownload, saveConfig, startDownloads } from "../api"; import TimezoneSelect from 'react-timezone-select'; import {PageContainer, secondsToDate, secondsToFrequency, TabLinks, textEllipsis, WROLModeMessage} from "./Common"; import {Route} from "react-router-dom"; class Settings extends React.Component { constructor(props) { super(props); this.state = { disabled: false, ready: false, validTimezone: true, timezone: '', } this.mediaDirectory = React.createRef(); this.handleSubmit = this.handleSubmit.bind(this); } async componentDidMount() { let config = await getConfig(); this.setState({ ready: true, disabled: config.wrol_mode, timezone: config.timezone || '', }); this.mediaDirectory.current.value = config.media_directory; } async handleSubmit(e) { e.preventDefault(); let config = { media_directory: this.mediaDirectory.current.value, timezone: this.state.timezone.value, }; this.setState({validTimezone: true}); let response = await saveConfig(config); if (response.status !== 200) { let json = await response.json(); if (json.api_error === 'Invalid timezone') { this.setState({validTimezone: false}); } } } handleTimezoneChange = async (timezone) => { this.setState({timezone}); } render() { if (this.state.ready === false) { return } return (

The global settings for your server.

When saved, these will be written to your local.yaml file. Storing these settings in your local configuration file (rather than the database) allows your WROLPi to be rebuilt and save your settings.

This directory must already exist. The directory in which your media will be stored. Typically, this will be some external drive like /media/wrolpi.

) } } class WROLMode extends React.Component { constructor(props) { super(props); this.state = { WROLMode: false, } } async componentDidMount() { let config = await getConfig(); this.setState({ready: true, WROLMode: config.wrol_mode}); } toggleWROLMode = async () => { // Handle WROL Mode toggling by itself so that other settings are not modified. let config = { wrol_mode: !this.state.WROLMode, } await saveConfig(config); this.setState({disabled: !this.state.WROLMode, WROLMode: !this.state.WROLMode}); } render() { if (this.state.ready === false) { return } return (
WROL Mode

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.

Note: User settings and favorites can still be modified.

) } } class DownloadRow extends React.Component { render() { let {url, frequency, last_successful_download, status, next_download} = this.props; let positive = false; if (status === 'pending') { positive = true; } return ( {textEllipsis(url, 50)} {secondsToFrequency(frequency)} {last_successful_download ? secondsToDate(last_successful_download) : null} {secondsToDate(next_download)} {status} ); } } class StoppableRow extends React.Component { constructor(props) { super(props); this.state = { stopOpen: false, startOpen: false, }; } openStop = () => { this.setState({stopOpen: true}); } closeStop = () => { this.setState({stopOpen: false}); } openStart = () => { this.setState({startOpen: true}); } closeStart = () => { this.setState({startOpen: false}); } handleStop = async (e) => { e.preventDefault(); await killDownload(this.props.id); this.closeStop(); await this.props.fetchDownloads(); }; handleStart = async (e) => { e.preventDefault(); let downloader = this.props.downloader || null; await postDownload(`${this.props.url}`, downloader); this.closeStart(); await this.props.fetchDownloads(); }; render() { let {url, last_successful_download, status} = this.props; let {stopOpen, startOpen} = this.state; let buttonCell = ; let positive = false; let negative = false; let warning = false; if (status === 'pending' || status === 'new') { positive = status === 'pending'; buttonCell = ( ); } else if (status === 'failed' || status === 'deferred') { negative = status === 'failed'; warning = status === 'deferred'; buttonCell = ( ); } return ( {textEllipsis(url, 50)} {last_successful_download ? secondsToDate(last_successful_download) : null} {status} {buttonCell} ); } } class Downloads extends React.Component { constructor(props) { super(props); this.state = { once_downloads: null, recurring_downloads: null, pending_downloads: null, stopOpen: false, disabled: false, }; } async componentDidMount() { await this.fetchDownloads(); await this.fetchStatus(); } killDownloads = async () => { await killDownloads(); this.setState({stopOpen: false}, this.fetchStatus); } startDownloads = async () => { await startDownloads(); this.setState({stopOpen: false}, this.fetchStatus); } closeStop = () => { this.setState({stopOpen: false}); } openStop = () => { this.setState({stopOpen: true}); } fetchDownloads = async () => { let data = await getDownloads(); this.setState({ once_downloads: data.once_downloads, recurring_downloads: data.recurring_downloads, pending_downloads: data.pending_downloads, }); } fetchStatus = async () => { let data = await getDownloaders(); this.setState({disabled: data['manager_disabled']}); } render() { let tablePlaceholder = ( ); let stoppableHeader = ( URL Completed At Status Control ); let nonStoppableHeader = ( URL Download Frequency Last Successful Download Next Download Status ); let onceTable = tablePlaceholder; if (this.state.once_downloads !== null && this.state.once_downloads.length === 0) { onceTable =

No downloads are scheduled to be downloaded.

} else if (this.state.once_downloads !== null) { onceTable = ( {stoppableHeader} {this.state.once_downloads.map((i) => )}
); } let recurringTable = tablePlaceholder; if (this.state.recurring_downloads !== null && this.state.recurring_downloads.length === 0) { recurringTable =

No downloads are scheduled to be downloaded.

} else if (this.state.recurring_downloads !== null) { recurringTable = ( {nonStoppableHeader} {this.state.recurring_downloads.map((i) => )}
); } let {stopOpen} = this.state; let allButton = (<> ); if (this.state.disabled === true) { allButton = (<> ); } return (
{allButton}
Downloads
{onceTable}
Recurring Downloads
{recurringTable}
); } } export default function Admin(props) { const links = [ {text: 'Downloads', to: '/admin', exact: true, key: 'admin'}, {text: 'Settings', to: '/admin/settings', key: 'settings'}, {text: 'WROL Mode', to: '/admin/wrol', key: 'wrol'}, ]; return ( ) }