diff --git a/web/.env.production b/web/.env.production index d307f0c91..1fad60181 100644 --- a/web/.env.production +++ b/web/.env.production @@ -1,3 +1 @@ -NEXT_PUBLIC_ADMIN_USERNAME=admin -NEXT_PUBLIC_ADMIN_STREAMKEY=abc123 NEXT_PUBLIC_API_HOST=/ \ No newline at end of file diff --git a/web/next.config.js b/web/next.config.js index 5213ae8de..a94cfa43a 100644 --- a/web/next.config.js +++ b/web/next.config.js @@ -1,3 +1,4 @@ module.exports = { basePath: "/admin", + trailingSlash: true, }; diff --git a/web/pages/components/chart.tsx b/web/pages/components/chart.tsx index 080e722a4..5a6968f36 100644 --- a/web/pages/components/chart.tsx +++ b/web/pages/components/chart.tsx @@ -5,7 +5,7 @@ import styles from '../../styles/styles.module.css'; interface ToolTipProps { active?: boolean, - payload?: object, + payload?: {name: string, payload: {value: string, time: Date}}[], unit?: string } @@ -22,6 +22,7 @@ interface TimedValue { interface ChartProps { data?: TimedValue[], + title?: string, color: string, unit: string, dataCollections?: any[], @@ -31,19 +32,24 @@ function CustomizedTooltip(props: ToolTipProps) { const { active, payload, unit } = props; if (active && payload && payload[0]) { const time = payload[0].payload ? timeFormat("%I:%M")(new Date(payload[0].payload.time)) : ""; + + const tooltipDetails = payload.map(data => { + return
+ {data.payload.value}{unit} {data.name} +
+ }); return ( -
-

- {time} {payload[0].payload.value} {unit} -

-
+ + {time} + {tooltipDetails} + ); } return null; } CustomizedTooltip.defaultProps = defaultProps; -export default function Chart({ data, color, unit, dataCollections }: ChartProps) { +export default function Chart({ data, title, color, unit, dataCollections }: ChartProps) { if (!data && !dataCollections) { return null; } @@ -67,6 +73,18 @@ export default function Chart({ data, color, unit, dataCollections }: ChartProps }); } + const line = data ? ( + + ) : null; + return (
@@ -87,23 +105,18 @@ export default function Chart({ data, color, unit, dataCollections }: ChartProps /> } /> - + {line} {dataCollections?.map((s) => ( ))} diff --git a/web/pages/components/log-table.tsx b/web/pages/components/log-table.tsx index 6d0c01cb0..b4f385832 100644 --- a/web/pages/components/log-table.tsx +++ b/web/pages/components/log-table.tsx @@ -77,7 +77,6 @@ export default function LogTable({ logs, pageSize }: Props) { rowKey={(row) => row.time} pagination={{ pageSize: pageSize || 20 }} /> - ;
); } diff --git a/web/pages/components/main-layout.tsx b/web/pages/components/main-layout.tsx index 1b7ff11cb..64070873e 100644 --- a/web/pages/components/main-layout.tsx +++ b/web/pages/components/main-layout.tsx @@ -3,7 +3,7 @@ import PropTypes from 'prop-types'; import Link from 'next/link'; import { differenceInSeconds } from "date-fns"; import { useRouter } from 'next/router'; -import { Layout, Menu } from 'antd'; +import { Layout, Menu, Popover } from 'antd'; import { SettingOutlined, @@ -38,6 +38,11 @@ export default function MainLayout(props) { const streamDurationString = online ? parseSecondsToDurationString(differenceInSeconds(new Date(), new Date(broadcaster.time))) : ""; + const content = ( +
+ +
+ ); const statusIcon = online ? : ; const statusMessage = online ? `Online ${streamDurationString}` : "Offline"; @@ -145,10 +150,12 @@ export default function MainLayout(props) {
+
{statusMessage} {statusIcon}
+
{children} diff --git a/web/pages/components/statistic.tsx b/web/pages/components/statistic.tsx index abe51849b..64910e443 100644 --- a/web/pages/components/statistic.tsx +++ b/web/pages/components/statistic.tsx @@ -1,25 +1,57 @@ -import { Statistic, Card, Col} from "antd"; +import { Typography, Statistic, Card, Col, Progress} from "antd"; +const { Text } = Typography; interface ItemProps { title: string, value: string, prefix: JSX.Element, + color: string, + progress?: boolean, + centered: boolean, }; export default function StatisticItem(props: ItemProps) { const { title, value, prefix } = props; - const valueStyle = { color: "#334", fontSize: "1.8rem" }; + const View = props.progress ? ProgressView : StatisticView; + const style = props.centered ? {display: 'flex', alignItems: 'center', justifyContent: 'center'} : {}; return ( - +
+ +
); +} + +function ProgressView({title, value, prefix, color}) { + const endColor = value > 90 ? 'red' : color; + const content = ( +
+ {prefix} +
{title}
+
{value}%
+
+ ) + return ( + content} /> + ) +} + +function StatisticView({title, value, prefix, color}) { + const valueStyle = { fontSize: "1.8rem" }; + + return ( + + ) } \ No newline at end of file diff --git a/web/pages/hardware-info.tsx b/web/pages/hardware-info.tsx index 9688421ea..8ae70a5df 100644 --- a/web/pages/hardware-info.tsx +++ b/web/pages/hardware-info.tsx @@ -1,8 +1,8 @@ /* eslint-disable no-array-constructor */ -import React, { useState, useEffect } from 'react'; +import { BulbOutlined, LaptopOutlined, SaveOutlined } from "@ant-design/icons"; import { Row } from "antd"; -import {LaptopOutlined, BulbOutlined, SaveOutlined} from "@ant-design/icons" -import { HARDWARE_STATS, fetchData, FETCH_INTERVAL } from '../utils/apis'; +import React, { useEffect, useState } from 'react'; +import { fetchData, FETCH_INTERVAL, HARDWARE_STATS } from '../utils/apis'; import Chart from './components/chart'; import StatisticItem from "./components/statistic"; @@ -55,17 +55,17 @@ export default function HardwareInfo() { const series = [ { name: "CPU", - color: "#FF7700", + color: "#B63FFF", data: hardwareStatus.cpu, }, { name: "Memory", - color: "#004777", + color: "#2087E2", data: hardwareStatus.memory, }, { name: "Disk", - color: "#A9E190", + color: "#FF7700", data: hardwareStatus.disk, }, ]; @@ -76,19 +76,28 @@ const series = [

Hardware Info

} + title={series[0].name} + value={`${currentCPUUsage}`} + prefix={} + color={series[0].color} + progress + centered /> } + title={series[1].name} + value={`${currentRamUsage}`} + prefix={} + color={series[1].color} + progress + centered /> } + title={series[2].name} + value={`${currentDiskUsage}`} + prefix={} + color={series[2].color} + progress + centered /> @@ -96,18 +105,6 @@ const series = [ -

cpu:[], disk: [], memory: []; value = %age.

-

the times should be the same for each, though milliseconds differ

-
- {JSON.stringify(hardwareStatus)} -
); } \ No newline at end of file diff --git a/web/pages/index.tsx b/web/pages/index.tsx index 3da98746d..166e1a637 100644 --- a/web/pages/index.tsx +++ b/web/pages/index.tsx @@ -8,7 +8,11 @@ TODO: Link each overview value to the sub-page that focuses on it. */ import React, { useState, useEffect, useContext } from "react"; +<<<<<<< HEAD import { Row, Skeleton, Typography } from "antd"; +======= +import { Row, Col, Skeleton, Result, List, Typography, Card } from "antd"; +>>>>>>> 4cdf5b73baa0584a0e6b2f586c27ca53923c65c7 import { UserOutlined, ClockCircleOutlined } from "@ant-design/icons"; import { formatDistanceToNow, formatRelative } from "date-fns"; import { ServerStatusContext } from "../utils/server-status-context"; @@ -27,6 +31,10 @@ import { formatIPAddress, isEmptyObject } from "../utils/format"; const { Title } = Typography; +<<<<<<< HEAD +======= + +>>>>>>> 4cdf5b73baa0584a0e6b2f586c27ca53923c65c7 <<<<<<< HEAD export default function Home() { @@ -105,6 +113,9 @@ export default function Stats() { ); } + const logTable = logs.length > 0 ? : null + console.log(logs) + if (!broadcaster) { return ; } @@ -122,17 +133,18 @@ export default function Stats() { title="Outbound Video Stream" value={`${setting.videoBitrate} kbps ${setting.framerate} fps`} prefix={null} + color="#334" /> ); }); - const logTable = logs.length > 0 ? : null const { viewerCount, sessionMaxViewerCount } = stats; const streamVideoDetailString = `${streamDetails.videoCodec} ${streamDetails.videoBitrate} kbps ${streamDetails.width}x${streamDetails.height}`; const streamAudioDetailString = `${streamDetails.audioCodec} ${streamDetails.audioBitrate} kpbs`; @@ -148,16 +160,19 @@ export default function Stats() { )}`} value={formatDistanceToNow(new Date(broadcaster.time))} prefix={} + color="#334" /> } + color="#334" /> } + color="#334" /> @@ -166,16 +181,19 @@ export default function Stats() { title="Input" value={formatIPAddress(remoteAddr)} prefix={null} + color="#334" /> @@ -186,15 +204,81 @@ export default function Stats() { title="Stream key" value={config.streamKey} prefix={null} + color="#334" /> {logTable} ); + + function Offline() { + const data = [ + { + title: "Send some test content", + content: ( +
+ Test your server with any video you have around. Pass it to the test script and start streaming it. +
+ ./test/ocTestStream.sh yourVideo.mp4 +
+
+ ), + }, + { + title: "Use your broadcasting software", + content: ( + + ) + }, + { + title: "Chat is disabled", + content: "Chat will continue to be disabled until you begin a live stream." + }, + { + title: "Embed your video onto other sites", + content: ( + + ) + } + ]; + return ( +
+ } + title="No stream is active." + subTitle="You should start one." + /> + + ( + + {item.content} + + )} + /> + {logTable} +
+ ); + } } diff --git a/web/pages/offline-notice.tsx b/web/pages/offline-notice.tsx index f2175561c..85bb10f5e 100644 --- a/web/pages/offline-notice.tsx +++ b/web/pages/offline-notice.tsx @@ -7,7 +7,7 @@ export default function Offline() { title: "Send some test content", content: (
- With any video you have around you can pass it to the test script and start streaming it. + Test your server with any video you have around. Pass it to the test script and start streaming it.
./test/ocTestStream.sh yourVideo.mp4
@@ -23,8 +23,17 @@ export default function Offline() { ) }, { - title: "Something else", + title: "Chat is disabled", + content: "Chat will continue to be disabled until you begin a live stream." }, + { + title: "Embed your video onto other sites", + content: ( + + ) + } ]; return (
@@ -39,9 +48,9 @@ export default function Offline() { gutter: 16, xs: 1, sm: 2, - md: 4, - lg: 4, - xl: 6, + md: 2, + lg: 6, + xl: 3, xxl: 3, }} dataSource={data} @@ -51,6 +60,7 @@ export default function Offline() { )} /> + {logTable}
); } diff --git a/web/pages/storage.tsx b/web/pages/storage.tsx index fc9a9810f..88862a0af 100644 --- a/web/pages/storage.tsx +++ b/web/pages/storage.tsx @@ -12,7 +12,7 @@ function Storage({ config }) { return (

Local storage is being used. Enable external S3 storage if you want - to use it. + to use it. TODO: Make this message somewhat more informative. Point to documentation or something.

); } @@ -74,20 +74,7 @@ export default function ServerConfig() { return (
-

Server Config

-

- Display this data all pretty, most things will be editable in the - future, not now. -

-
-
); } diff --git a/web/pages/update-server-config.tsx b/web/pages/update-server-config.tsx index 901fd1704..4527efda2 100644 --- a/web/pages/update-server-config.tsx +++ b/web/pages/update-server-config.tsx @@ -149,24 +149,9 @@ export default function ServerConfig() { return (
-

Server Config

-

- Display this data all pretty, most things will be editable in the - future, not now. -

-
- - {JSON.stringify(config)} -
); } diff --git a/web/pages/upgrade.tsx b/web/pages/upgrade.tsx index e8cdb8d0a..b90444e7c 100644 --- a/web/pages/upgrade.tsx +++ b/web/pages/upgrade.tsx @@ -38,7 +38,7 @@ export default function Logs() { {release.name} {new Date(release.created_at).toDateString()} - {release.body};

Downloads

+ {release.body}

Downloads

); @@ -68,6 +68,6 @@ function AssetTable(assets) { }, ]; - return ; + return
} diff --git a/web/pages/video-config.tsx b/web/pages/video-config.tsx index faef9a149..b8d58dfea 100644 --- a/web/pages/video-config.tsx +++ b/web/pages/video-config.tsx @@ -109,20 +109,7 @@ export default function VideoConfig() { return (
-

Server Config

-

- Display this data all pretty, most things will be editable in the - future, not now. -

-
-
); } diff --git a/web/pages/viewer-info.tsx b/web/pages/viewer-info.tsx index 04977adf3..de1099178 100644 --- a/web/pages/viewer-info.tsx +++ b/web/pages/viewer-info.tsx @@ -109,22 +109,25 @@ export default function ViewersOverTime() { title="Current viewers" value={viewerCount.toString()} prefix={} + color="#334" /> } + color="#334" /> } + color="#334" />
- +
-
; +
); } diff --git a/web/utils/apis.ts b/web/utils/apis.ts index 4085631ba..d9dc1009b 100644 --- a/web/utils/apis.ts +++ b/web/utils/apis.ts @@ -37,16 +37,19 @@ export const LOGS_WARN = `${API_LOCATION}logs/warnings`; const GITHUB_RELEASE_URL = "https://api.github.com/repos/owncast/owncast/releases/latest"; export async function fetchData(url) { - const encoded = btoa(`${ADMIN_USERNAME}:${ADMIN_STREAMKEY}`); + let options: RequestInit = {}; + + if (ADMIN_USERNAME && ADMIN_STREAMKEY) { + const encoded = btoa(`${ADMIN_USERNAME}:${ADMIN_STREAMKEY}`); + options.headers = { + 'Authorization': `Basic ${encoded}` + } + options.mode = 'cors'; + options.credentials = 'include' + } try { - const response = await fetch(url, { - headers: { - 'Authorization': `Basic ${encoded}`, - }, - mode: 'cors', - credentials: 'include', - }); + const response = await fetch(url, options); if (!response.ok) { const message = `An error has occured: ${response.status}`; throw new Error(message);