diff --git a/web/favicon.ico b/web/favicon.ico
new file mode 100644
index 000000000..7a859e7ee
Binary files /dev/null and b/web/favicon.ico differ
diff --git a/web/package.json b/web/package.json
index bf39b247f..834ef4456 100644
--- a/web/package.json
+++ b/web/package.json
@@ -10,6 +10,7 @@
"dependencies": {
"@ant-design/icons": "^4.2.2",
"antd": "^4.6.6",
+ "classnames": "^2.2.6",
"d3-scale": "^3.2.3",
"d3-time-format": "^3.0.0",
"next": "9.5.3",
diff --git a/web/pages/_app.tsx b/web/pages/_app.tsx
index f1a4e0eb9..958b72559 100644
--- a/web/pages/_app.tsx
+++ b/web/pages/_app.tsx
@@ -1,15 +1,21 @@
-// import 'antd/dist/antd.css';
-// import '../styles/globals.scss'
-
import 'antd/dist/antd.dark.css';
import 'antd/dist/antd.compact.css';
-
import "../styles/globals.scss";
-import { AppProps } from 'next/app'
+import { AppProps } from 'next/app';
+import BroadcastStatusProvider from './utils/broadcast-status-context';
+import MainLayout from './components/main-layout';
+
function App({ Component, pageProps }: AppProps) {
- return
+ return (
+
+
+
+
+
+
+ )
}
-export default App
\ No newline at end of file
+export default App;
\ No newline at end of file
diff --git a/web/pages/broadcast-info.tsx b/web/pages/broadcast-info.tsx
new file mode 100644
index 000000000..465b48de5
--- /dev/null
+++ b/web/pages/broadcast-info.tsx
@@ -0,0 +1,18 @@
+import React, { useContext } from 'react';
+import { BroadcastStatusContext } from './utils/broadcast-status-context';
+
+
+export default function BroadcastInfo() {
+ const context = useContext(BroadcastStatusContext);
+ const { broadcaster } = context || {};
+ const { remoteAddr, time, streamDetails } = broadcaster || {};
+
+ return (
+
Connected Clients
diff --git a/web/pages/components/hardware-info.tsx b/web/pages/hardware-info.tsx
similarity index 93%
rename from web/pages/components/hardware-info.tsx
rename to web/pages/hardware-info.tsx
index 919489c2e..d92876499 100644
--- a/web/pages/components/hardware-info.tsx
+++ b/web/pages/hardware-info.tsx
@@ -1,5 +1,5 @@
import React, { useState, useEffect } from 'react';
-import { HARDWARE_STATS, fetchData, FETCH_INTERVAL } from '../utils/apis';
+import { HARDWARE_STATS, fetchData, FETCH_INTERVAL } from './utils/apis';
export default function HardwareInfo() {
const [hardwareStatus, setHardwareStatus] = useState({});
diff --git a/web/pages/home.tsx b/web/pages/home.tsx
deleted file mode 100644
index 1609d3893..000000000
--- a/web/pages/home.tsx
+++ /dev/null
@@ -1,12 +0,0 @@
-import React from 'react';
-
-import adminStyles from './components/styles.module.css';
-
-
-export default function HomeView(props) {
- return (
-
- < pick something
-
- );
-}
diff --git a/web/pages/index2.tsx b/web/pages/index2.tsx
index fdb9060ae..58dc825d7 100644
--- a/web/pages/index2.tsx
+++ b/web/pages/index2.tsx
@@ -1,43 +1,10 @@
-import React, { useState, useEffect } from 'react';
-import { BROADCASTER, fetchData, FETCH_INTERVAL } from './utils/apis';
-import MainLayout from './components/main-layout';
-import Home from './home';
+import React from 'react';
-export default function Admin() {
- const [broadcasterStatus, setBroadcasterStatus] = useState({});
- const [count, setCount] = useState(0);
-
- const getBroadcastStatus = async () => {
- try {
- const result = await fetchData(BROADCASTER);
- const broadcastActive = !!result.broadcaster;
-
- console.log("====",{count, result})
-
- setBroadcasterStatus({ ...result, broadcastActive });
- setCount(c => c + 1);
-
- } catch (error) {
- setBroadcasterStatus({ ...broadcasterStatus, message: error.message });
- }
- };
-
- useEffect(() => {
- let getStatusIntervalId = null;
-
- getBroadcastStatus();
- getStatusIntervalId = setInterval(getBroadcastStatus, FETCH_INTERVAL);
-
- // returned function will be called on component unmount
- return () => {
- clearInterval(getStatusIntervalId);
- }
- }, [])
-
-
+export default function AdminHome() {
return (
-
-
-
+
+ < pick something
+ Home view. pretty pictures. Rainbows. Kittens.
+
);
}
diff --git a/web/pages/update-server-config.tsx b/web/pages/update-server-config.tsx
new file mode 100644
index 000000000..7aa101dd0
--- /dev/null
+++ b/web/pages/update-server-config.tsx
@@ -0,0 +1,40 @@
+import React, { useState, useEffect } from 'react';
+import { SERVER_CONFIG, fetchData, FETCH_INTERVAL } from './utils/apis';
+
+export default function ServerConfig() {
+ const [clients, setClients] = useState({});
+
+ const getInfo = async () => {
+ try {
+ const result = await fetchData(SERVER_CONFIG);
+ console.log("viewers result", result)
+
+ setClients({ ...result });
+
+ } catch (error) {
+ setClients({ ...clients, message: error.message });
+ }
+ };
+
+ useEffect(() => {
+ let getStatusIntervalId = null;
+
+ getInfo();
+ getStatusIntervalId = setInterval(getInfo, FETCH_INTERVAL);
+
+ // returned function will be called on component unmount
+ return () => {
+ clearInterval(getStatusIntervalId);
+ }
+ }, []);
+
+ return (
+
+
Server Config
+
Display this data all pretty, most things will be editable in the future, not now.
+
+ {JSON.stringify(clients)}
+
+
+ );
+}
diff --git a/web/pages/utils/broadcast-status-context.tsx b/web/pages/utils/broadcast-status-context.tsx
new file mode 100644
index 000000000..86e595b24
--- /dev/null
+++ b/web/pages/utils/broadcast-status-context.tsx
@@ -0,0 +1,51 @@
+import React, { useState, useEffect } from 'react';
+import PropTypes from 'prop-types';
+
+import { BROADCASTER, fetchData, FETCH_INTERVAL } from './apis';
+
+const initialState = {
+ broadcastActive: false,
+ message: '',
+ broadcaster: null,
+};
+
+export const BroadcastStatusContext = React.createContext(initialState);
+
+const BroadcastStatusProvider = ({ children }) => {
+ const [broadcasterStatus, setBroadcasterStatus] = useState(initialState);
+
+ const getBroadcastStatus = async () => {
+ try {
+ const result = await fetchData(BROADCASTER);
+ const broadcastActive = !!result.broadcaster;
+ setBroadcasterStatus({ ...result, broadcastActive });
+
+ } catch (error) {
+ setBroadcasterStatus({ ...broadcasterStatus, message: error.message });
+ }
+ };
+
+ useEffect(() => {
+ let getStatusIntervalId = null;
+
+ getBroadcastStatus();
+ getStatusIntervalId = setInterval(getBroadcastStatus, FETCH_INTERVAL);
+
+ // returned function will be called on component unmount
+ return () => {
+ clearInterval(getStatusIntervalId);
+ }
+ }, [])
+
+ return (
+
+ {children}
+
+ );
+}
+
+BroadcastStatusProvider.propTypes = {
+ children: PropTypes.element.isRequired,
+};
+
+export default BroadcastStatusProvider;
\ No newline at end of file
diff --git a/web/pages/components/viewer-info.tsx b/web/pages/viewer-info.tsx
similarity index 96%
rename from web/pages/components/viewer-info.tsx
rename to web/pages/viewer-info.tsx
index 1446585fd..e63806a03 100644
--- a/web/pages/components/viewer-info.tsx
+++ b/web/pages/viewer-info.tsx
@@ -1,7 +1,8 @@
import React, { useState, useEffect } from 'react';
import {timeFormat} from 'd3-time-format';
import { LineChart, XAxis, YAxis, Line, Tooltip } from 'recharts';
-import { VIEWERS_OVER_TIME, fetchData } from '../utils/apis';
+
+import { VIEWERS_OVER_TIME, fetchData } from './utils/apis';
const FETCH_INTERVAL = 5 * 60 * 1000; // 5 mins
@@ -65,8 +66,6 @@ export default function ViewersOverTime() {
/>
-
-
);
}
diff --git a/web/styles/styles.module.css b/web/styles/styles.module.css
new file mode 100644
index 000000000..0b59be3fb
--- /dev/null
+++ b/web/styles/styles.module.css
@@ -0,0 +1,69 @@
+
+.logoSVG {
+ height: 2rem;
+ width: 2rem;
+}
+
+.owncastTitleContainer {
+ padding: 1rem;
+ display: flex;
+ flex-direction: row;
+ justify-content: center;
+ align-items: center;
+
+}
+.logoContainer {
+ background-color: #fff;
+ padding: .35rem;
+ border-radius: 9999px;
+}
+.owncastTitle {
+ display: inline-block;
+ margin-left: 1rem;
+ color: rgba(203,213,224, 1);
+ font-size: 1.15rem;
+ font-weight: 200;
+ text-transform: uppercase;
+ line-height: normal;
+ letter-spacing: .05em;
+}
+
+.contentMain {
+ padding: 3em;
+}
+
+.header {
+ display: flex;
+ flex-direction: row;
+ justify-content: flex-end;
+}
+
+.statusIndicatorContainer {
+ display: flex;
+ flex-direction: row;
+ justify-content: center;
+ align-items: center;
+
+}
+.statusIcon {
+ font-size: 1.5rem;
+}
+.statusIcon svg {
+ fill: #ccc;
+}
+.statusLabel {
+ color: #fff;
+ text-transform: uppercase;
+ font-size: .75rem;
+ display: inline-block;
+ margin-left: .5rem;
+ color: #ccc;
+}
+.online .statusIcon svg {
+ fill: #52c41a;
+}
+.online .statusLabel {
+ color: #52c41a;
+}
+
+/* //844-227-3943 */
\ No newline at end of file