diff --git a/web/pages/_app.tsx b/web/pages/_app.tsx
index cb2c8864e2..49327044c2 100644
--- a/web/pages/_app.tsx
+++ b/web/pages/_app.tsx
@@ -1,7 +1,11 @@
+// order matters!
import 'antd/dist/antd.css';
import '../styles/colors.scss';
import '../styles/globals.scss';
import '../styles/ant-overrides.scss';
+import '../styles/markdown-editor.scss';
+
+import '../styles/main-layout.scss';
import '../styles/form-textfields.scss';
import '../styles/form-toggleswitch.scss';
@@ -11,7 +15,6 @@ import '../styles/config-storage.scss';
import '../styles/config-tags.scss';
import '../styles/config-video-variants.scss';
-
import '../styles/home.scss';
import '../styles/chat.scss';
import '../styles/config.scss';
diff --git a/web/pages/components/chart.tsx b/web/pages/components/chart.tsx
index 57445d35aa..0ee2ec304a 100644
--- a/web/pages/components/chart.tsx
+++ b/web/pages/components/chart.tsx
@@ -9,11 +9,11 @@ interface TimedValue {
}
interface ChartProps {
- data?: TimedValue[],
- title?: string,
- color: string,
- unit: string,
- dataCollections?: any[],
+ data?: TimedValue[];
+ title?: string;
+ color: string;
+ unit: string;
+ dataCollections?: any[];
}
function createGraphDataset(dataArray) {
@@ -33,18 +33,20 @@ export default function Chart({ data, title, color, unit, dataCollections }: Cha
renderData.push({
name: title,
color,
- data: createGraphDataset(data)
+ data: createGraphDataset(data),
});
}
dataCollections.forEach(collection => {
- renderData.push(
- {name: collection.name, data: createGraphDataset(collection.data), color: collection.color}
- )
+ renderData.push({
+ name: collection.name,
+ data: createGraphDataset(collection.data),
+ color: collection.color,
+ });
});
return (
-
+
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {' '}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
);
-}
\ No newline at end of file
+}
diff --git a/web/pages/components/main-layout.tsx b/web/pages/components/main-layout.tsx
index d8e948c7ef..095622b9e3 100644
--- a/web/pages/components/main-layout.tsx
+++ b/web/pages/components/main-layout.tsx
@@ -1,8 +1,8 @@
import React, { useContext, useEffect, useState } from 'react';
import PropTypes from 'prop-types';
import Link from 'next/link';
-import Head from 'next/head'
-import { differenceInSeconds } from "date-fns";
+import Head from 'next/head';
+import { differenceInSeconds } from 'date-fns';
import { useRouter } from 'next/router';
import { Layout, Menu, Popover, Alert } from 'antd';
@@ -16,11 +16,10 @@ import {
QuestionCircleOutlined,
MessageOutlined,
ExperimentOutlined,
-
} from '@ant-design/icons';
import classNames from 'classnames';
-import { upgradeVersionAvailable } from "../../utils/apis";
-import { parseSecondsToDurationString } from '../../utils/format'
+import { upgradeVersionAvailable } from '../../utils/apis';
+import { parseSecondsToDurationString } from '../../utils/format';
import OwncastLogo from './logo';
import { ServerStatusContext } from '../../utils/server-status-context';
@@ -29,7 +28,7 @@ import { AlertMessageContext } from '../../utils/alert-message-context';
import TextFieldWithSubmit from './config/form-textfield-with-submit';
import { TEXTFIELD_PROPS_STREAM_TITLE } from './config/constants';
-import adminStyles from '../../styles/styles.module.scss';
+import { UpdateArgs } from '../../types/config-section';
let performedUpgradeCheck = false;
@@ -37,72 +36,47 @@ export default function MainLayout(props) {
const { children } = props;
const context = useContext(ServerStatusContext);
- const { serverConfig, online, broadcaster, versionNumber, streamTitle } = context || {};
+ const { serverConfig, online, broadcaster, versionNumber } = context || {};
const { instanceDetails } = serverConfig;
- const [currentStreamTitle, setCurrentStreamTitle] = useState(streamTitle);
+ const [currentStreamTitle, setCurrentStreamTitle] = useState('');
const alertMessage = useContext(AlertMessageContext);
-
+
const router = useRouter();
const { route } = router || {};
const { Header, Footer, Content, Sider } = Layout;
const { SubMenu } = Menu;
- // status indicator items
- const streamDurationString = broadcaster ? parseSecondsToDurationString(differenceInSeconds(new Date(), new Date(broadcaster.time))) : "";
- const currentThumbnail = online ? (
-
- ) : null;
- const statusIcon = online ? : ;
- const statusMessage = online ? `Online ${streamDurationString}` : "Offline";
- const statusIndicator = (
-
- {statusMessage}
- {statusIcon}
-
- );
- const statusIndicatorWithThumb = online ? (
-
- {statusIndicator}
-
- ) : statusIndicator;
- // ///////////////
-
const [upgradeVersion, setUpgradeVersion] = useState(null);
const checkForUpgrade = async () => {
try {
const result = await upgradeVersionAvailable(versionNumber);
setUpgradeVersion(result);
} catch (error) {
- console.log("==== error", error);
+ console.log('==== error', error);
}
};
useEffect(() => {
if (!performedUpgradeCheck) {
checkForUpgrade();
- performedUpgradeCheck = true
+ performedUpgradeCheck = true;
}
});
useEffect(() => {
- setCurrentStreamTitle(streamTitle);
- }, [streamTitle]);
+ setCurrentStreamTitle(instanceDetails.streamTitle);
+ }, [instanceDetails]);
const handleStreamTitleChanged = ({ value }: UpdateArgs) => {
setCurrentStreamTitle(value);
- }
-
+ };
const appClass = classNames({
- "owncast-layout": true,
- [adminStyles.online]: online,
+ 'app-container': true,
+ online,
});
const upgradeMenuItemStyle = upgradeVersion ? 'block' : 'none';
@@ -110,15 +84,36 @@ export default function MainLayout(props) {
const clearAlertMessage = () => {
alertMessage.setMessage(null);
- }
+ };
+
+ const headerAlertMessage = alertMessage.message ? (
+
+ ) : null;
+
+ // status indicator items
+ const streamDurationString = broadcaster
+ ? parseSecondsToDurationString(differenceInSeconds(new Date(), new Date(broadcaster.time)))
+ : '';
+ const currentThumbnail = online ? (
+
+ ) : null;
+ const statusIcon = online ? : ;
+ const statusMessage = online ? `Online ${streamDurationString}` : 'Offline';
+
+ const statusIndicator = (
+
+ {statusMessage}
+ {statusIcon}
+
+ );
+ const statusIndicatorWithThumb = online ? (
+
+ {statusIndicator}
+
+ ) : (
+ statusIndicator
+ );
- const headerAlertMessage = alertMessage.message ? ( ): null;
-
return (
@@ -126,47 +121,32 @@ export default function MainLayout(props) {
-
+
-
-
+
+
- Owncast Admin
+ Owncast Admin
}>
Home
- }
- title="Current stream"
- >
+ } title="Current stream">
Viewers
- }
- title="Chat utilities"
- >
+ } title="Chat utilities">
Chat
- }
- >
+ }>
General
@@ -189,11 +169,7 @@ export default function MainLayout(props) {
- }
- title="Utilities"
- >
+ } title="Utilities">
Hardware
@@ -206,11 +182,7 @@ export default function MainLayout(props) {
- }
- title="Integrations"
- >
+ } title="Integrations">
Webhooks
@@ -218,38 +190,33 @@ export default function MainLayout(props) {
Access Tokens
- }
- title="Help"
- >
+ } title="Help">
Help
-
-
- {
- data.map(item => (
-
-
-
- ))
- }
+ {data.map(item => (
+
+
+
+ ))}
-
>
diff --git a/web/styles/globals.scss b/web/styles/globals.scss
index 6c0317df44..308933e183 100644
--- a/web/styles/globals.scss
+++ b/web/styles/globals.scss
@@ -36,48 +36,13 @@ code {
}
-// markdown editor overrides
-
-.rc-virtual-list-scrollbar {
- display: block !important;
-}
-.rc-md-editor {
- // Set the background color of the preview container
- .editor-container {
- background-color: #E2E8F0;
- color: rgba(45,55,72,1);
- }
-
- // Custom CSS for formatting the preview text
- .markdown-editor-preview-pane {
- // color:lightgrey;
- a {
- color: var(--owncast-purple);;
- }
- h1 {
- font-size: 2em;
- }
- }
-
- // Custom CSS class used to format the text of the editor
- .markdown-editor-pane {
- color: white !important;
- background-color: black;
- font-family: monospace;
- }
-
- // Set the background color of the editor text input
- textarea {
- background-color: rgb(44,44,44) !important;
- color:lightgrey !important;
- }
-.ant-btn {
- transition-duration: .15s;
- transition-delay: 0s;
+.logo-svg {
+ height: 2rem;
+ width: 2rem;
}
- // Hide extra toolbar buttons.
- .button-type-undo, .button-type-redo, .button-type-clear, .button-type-image, .button-type-wrap, .button-type-quote, .button-type-strikethrough, .button-type-code-inline, .button-type-code-block {
- display: none !important;
- }
+p.page-description {
+ margin: 1em 0;
+ color: #ccc;
+ width: 80%;
}
diff --git a/web/styles/main-layout.scss b/web/styles/main-layout.scss
new file mode 100644
index 0000000000..8cde3017d9
--- /dev/null
+++ b/web/styles/main-layout.scss
@@ -0,0 +1,138 @@
+.app-container {
+
+ .side-nav {
+ position: fixed;
+ height: 100vh;
+ overflow: auto;
+ z-index: 10;
+ }
+
+ h1.owncast-title {
+ padding: 1rem;
+ display: flex;
+ flex-direction: row;
+ justify-content: center;
+ align-items: center;
+
+ .logo-container {
+ background-color: #fff;
+ padding: .35rem;
+ border-radius: 9999px;
+ }
+
+ .title-label {
+ 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;
+ }
+ }
+
+ .layout-main {
+ margin-left: 240px; // width of Ant Sider
+ }
+ .layout-header {
+ display: flex;
+ flex-direction: row;
+ justify-content: flex-end;
+ padding-right: 1rem;
+ }
+
+
+ .main-content-container {
+ padding: 3em;
+ }
+
+ .footer-container {
+ text-align: center;
+ }
+
+
+
+ .online-status-indicator {
+ display: flex;
+ flex-direction: row;
+ justify-content: center;
+ align-items: center;
+
+ .online-thumbnail {
+ width: 12.5rem;
+ }
+
+ .status-label {
+ color: #fff;
+ text-transform: uppercase;
+ font-size: .75rem;
+ display: inline-block;
+ margin-right: .5rem;
+ color: #999;
+ }
+ .status-icon {
+ font-size: 1.5rem;
+ svg {
+ fill: #999;
+ }
+ }
+ }
+ .online {
+ .online-status-indicator {
+ .status-icon {
+ svg {
+ fill: var(--online-color);
+ }
+ }
+ .status-label {
+ color: var(--online-color);
+ }
+ }
+ }
+}
+
+
+// stream title form field in header
+.global-stream-title-container {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ width: 100%;
+ .textfield-with-submit-container {
+ flex-direction: row;
+ justify-content: center;
+ align-items: center;
+ margin-bottom: 0;
+
+ .input-side {
+ width: 400px;
+ }
+
+ .label-side {
+ display: none;
+ }
+ .lower-container {
+ width: auto;
+ .lower-content {
+ flex-direction: column-reverse;
+ position: relative;
+ }
+ .label-spacer,
+ .field-tip {
+ display: none;
+ }
+ .status-container {
+ line-height: 1;
+ position: absolute;
+ bottom: -2em;
+ }
+ .update-button-container {
+ margin: 0;
+ margin-left: .5em;
+ line-height: 1;
+ }
+ }
+ }
+}
+
diff --git a/web/styles/markdown-editor.scss b/web/styles/markdown-editor.scss
new file mode 100644
index 0000000000..74186233cb
--- /dev/null
+++ b/web/styles/markdown-editor.scss
@@ -0,0 +1,46 @@
+
+// markdown editor overrides
+
+.rc-virtual-list-scrollbar {
+ display: block !important;
+}
+.rc-md-editor {
+ // Set the background color of the preview container
+ .editor-container {
+ background-color: #E2E8F0;
+ color: rgba(45,55,72,1);
+ }
+
+ // Custom CSS for formatting the preview text
+ .markdown-editor-preview-pane {
+ // color:lightgrey;
+ a {
+ color: var(--owncast-purple);;
+ }
+ h1 {
+ font-size: 2em;
+ }
+ }
+
+ // Custom CSS class used to format the text of the editor
+ .markdown-editor-pane {
+ color: white !important;
+ background-color: black;
+ font-family: monospace;
+ }
+
+ // Set the background color of the editor text input
+ textarea {
+ background-color: rgb(44,44,44) !important;
+ color:lightgrey !important;
+ }
+.ant-btn {
+ transition-duration: .15s;
+ transition-delay: 0s;
+}
+
+ // Hide extra toolbar buttons.
+ .button-type-undo, .button-type-redo, .button-type-clear, .button-type-image, .button-type-wrap, .button-type-quote, .button-type-strikethrough, .button-type-code-inline, .button-type-code-block {
+ display: none !important;
+ }
+}
diff --git a/web/styles/styles.module.scss b/web/styles/styles.module.scss
index 4d2af6e143..2e4b99bfbf 100644
--- a/web/styles/styles.module.scss
+++ b/web/styles/styles.module.scss
@@ -1,9 +1,4 @@
-.logoSVG {
- height: 2rem;
- width: 2rem;
-}
-
.owncastTitleContainer {
padding: 1rem;
display: flex;