From e7e89556e79bb6e4e4d18b1ad40c770972b540bd Mon Sep 17 00:00:00 2001 From: gingervitis Date: Sun, 3 Jan 2021 23:32:47 -0800 Subject: [PATCH] apply config form flow to edit content page --- .../components/config/form-textfield.tsx | 2 +- web/pages/components/main-layout.tsx | 3 + web/pages/config-page-content.tsx | 105 ++++++++++++++++++ web/pages/config-server-details.tsx | 4 +- web/pages/edit-page-content.tsx | 51 --------- web/styles/config.scss | 13 +++ web/styles/globals.scss | 11 +- web/types/config-section.ts | 4 +- web/utils/server-status-context.tsx | 7 +- 9 files changed, 139 insertions(+), 61 deletions(-) create mode 100644 web/pages/config-page-content.tsx delete mode 100644 web/pages/edit-page-content.tsx diff --git a/web/pages/components/config/form-textfield.tsx b/web/pages/components/config/form-textfield.tsx index 096ac370a..b14e3d0d1 100644 --- a/web/pages/components/config/form-textfield.tsx +++ b/web/pages/components/config/form-textfield.tsx @@ -60,7 +60,7 @@ export default function TextField(props: TextFieldProps) { setHasChanged(false); clearTimeout(resetTimer); resetTimer = null; - } + }; // if field is required but value is empty, or equals initial value, then don't show submit/update button. otherwise clear out any result messaging and display button. const handleChange = (e: any) => { diff --git a/web/pages/components/main-layout.tsx b/web/pages/components/main-layout.tsx index 28ec1d1a2..f9fa310bb 100644 --- a/web/pages/components/main-layout.tsx +++ b/web/pages/components/main-layout.tsx @@ -150,6 +150,9 @@ export default function MainLayout(props) { Storage + + Custom page content + import('react-markdown-editor-lite'), { + ssr: false, +}); + +export default function PageContentEditor() { + const [content, setContent] = useState(''); + const [submitStatus, setSubmitStatus] = useState(''); + const [submitStatusMessage, setSubmitStatusMessage] = useState(''); + const [hasChanged, setHasChanged] = useState(false); + + const serverStatusData = useContext(ServerStatusContext); + const { serverConfig, setFieldInConfigState } = serverStatusData || {}; + + const { instanceDetails } = serverConfig; + const { extraPageContent: initialContent } = instanceDetails; + + const { apiPath } = TEXTFIELD_DEFAULTS.instanceDetails.extraPageContent; + + let resetTimer = null; + + function handleEditorChange({ text }) { + setContent(text); + if (text !== initialContent && !hasChanged) { + setHasChanged(true); + } else if (text === initialContent && hasChanged) { + setHasChanged(false); + } + } + + // Clear out any validation states and messaging + const resetStates = () => { + setSubmitStatus(''); + setHasChanged(false); + clearTimeout(resetTimer); + resetTimer = null; + }; + + // posts all the tags at once as an array obj + async function handleSave() { + setSubmitStatus('validating'); + await postConfigUpdateToAPI({ + apiPath, + data: { value: content }, + onSuccess: () => { + setFieldInConfigState({ fieldName: 'extraPageContent', value: content, path: apiPath }); + setSubmitStatus('success'); + }, + onError: (message: string) => { + setSubmitStatus('error'); + setSubmitStatusMessage(`There was an error: ${message}`); + }, + }); + resetTimer = setTimeout(resetStates, RESET_TIMEOUT); + } + + useEffect(() => { + setContent(initialContent); + }, [instanceDetails]); + + const { + icon: newStatusIcon = null, + message: newStatusMessage = '', + } = SUCCESS_STATES[submitStatus] || {}; + + + return ( +
+ Edit custom content + +

Add some content about your site with the Markdown editor below. This content shows up at the bottom half of your Owncast page.

+ + mdParser.render(c)} + onChange={handleEditorChange} + config={{ + htmlClass: 'markdown-editor-preview-pane', + markdownClass: 'markdown-editor-pane', + }} + /> +
+ { hasChanged ? : null } +
+ {newStatusIcon} {newStatusMessage} {submitStatusMessage} +
+
+
+ ); +} diff --git a/web/pages/config-server-details.tsx b/web/pages/config-server-details.tsx index 39f284f46..5196983bc 100644 --- a/web/pages/config-server-details.tsx +++ b/web/pages/config-server-details.tsx @@ -39,7 +39,7 @@ export default function ConfigServerDetails() { configPath: '', }; return ( - <> +
Edit your Server's details
@@ -53,7 +53,7 @@ export default function ConfigServerDetails() {
- +
); } diff --git a/web/pages/edit-page-content.tsx b/web/pages/edit-page-content.tsx deleted file mode 100644 index 55e6ac349..000000000 --- a/web/pages/edit-page-content.tsx +++ /dev/null @@ -1,51 +0,0 @@ -import React, { useEffect } from 'react'; - -import MarkdownIt from 'markdown-it'; -const mdParser = new MarkdownIt(/* Markdown-it options */); - -import dynamic from 'next/dynamic'; -import 'react-markdown-editor-lite/lib/index.css'; - -import { SERVER_CONFIG, fetchData, FETCH_INTERVAL, UPDATE_CHAT_MESSGAE_VIZ } from "../utils/apis"; - -import { Table, Typography, Tooltip, Button } from "antd"; - -const MdEditor = dynamic(() => import('react-markdown-editor-lite'), { - ssr: false -}); - -export default function PageContentEditor() { - const [content, setContent] = React.useState(""); - - function handleEditorChange({ html, text }) { - setContent(text); - } - - function handleSave() { - console.log(content); - alert("Make API call to save here." + content) - } - - async function setInitialContent() { - const serverConfig = await fetchData(SERVER_CONFIG); - const initialContent = serverConfig.instanceDetails.extraPageContent; - setContent(initialContent); - } - - useEffect(() => { - setInitialContent(); - }, []); - - return ( -
- mdParser.render(content)} - onChange={handleEditorChange} - config={{ htmlClass: 'markdown-editor-preview-pane', markdownClass: 'markdown-editor-pane' }} - /> - -
- ); -} diff --git a/web/styles/config.scss b/web/styles/config.scss index af413041f..2361c8e8a 100644 --- a/web/styles/config.scss +++ b/web/styles/config.scss @@ -143,3 +143,16 @@ } } +.config-page-content-form { + .page-content-actions { + margin-top: 1em; + display: flex; + flex-direction: row; + justify-content: flex-start; + align-items: center; + + .status-message { + margin-left: 1em; + } + } +} diff --git a/web/styles/globals.scss b/web/styles/globals.scss index 5499ba26c..cd1d7cdcf 100644 --- a/web/styles/globals.scss +++ b/web/styles/globals.scss @@ -80,16 +80,16 @@ code { .rc-md-editor { // Set the background color of the preview container .editor-container { - background-color: black; + background-color: #E2E8F0; + color: rgba(45,55,72,1); } // Custom CSS for formatting the preview text .markdown-editor-preview-pane { - color:lightgrey; + // color:lightgrey; a { color: $owncast-purple; } - h1 { font-size: 2em; } @@ -97,12 +97,15 @@ code { // Custom CSS class used to format the text of the editor .markdown-editor-pane { - color:lightgrey !important; + 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; } // Hide extra toolbar buttons. diff --git a/web/types/config-section.ts b/web/types/config-section.ts index 4e60b3eb4..e04c411da 100644 --- a/web/types/config-section.ts +++ b/web/types/config-section.ts @@ -9,6 +9,8 @@ export interface TextFieldProps { required?: boolean; disabled?: boolean; onSubmit?: () => void; + onBlur?: () => void; + onChange?: () => void; } export interface ToggleSwitchProps { @@ -49,7 +51,7 @@ export interface ConfigInstanceDetailsFields { export interface VideoVariant { audioBitrate: number; - audioPassthrough: number; + audioPassthrough: false | number; encoderPreset: 'ultrafast' | 'superfast' | 'veryfast' | 'faster' | 'fast'; framerate: number; videoBitrate: number; diff --git a/web/utils/server-status-context.tsx b/web/utils/server-status-context.tsx index 8d9449961..e39e65e77 100644 --- a/web/utils/server-status-context.tsx +++ b/web/utils/server-status-context.tsx @@ -25,6 +25,8 @@ export const initialServerConfigState: ConfigDetails = { instanceUrl: '', }, videoSettings: { + numberOfPlaylistItems: 5, + segmentLengthSeconds: 4, videoQualityVariants: [ { audioPassthrough: false, @@ -32,6 +34,7 @@ export const initialServerConfigState: ConfigDetails = { videoBitrate: 0, audioBitrate: 0, framerate: 0, + encoderPreset: 'veryfast', }, ], } @@ -93,7 +96,7 @@ const ServerStatusProvider = ({ children }) => { }; setConfig(updatedConfig); - } + }; useEffect(() => { @@ -108,7 +111,7 @@ const ServerStatusProvider = ({ children }) => { return () => { clearInterval(getStatusIntervalId); } - }, []) + }, []); const providerValue = { ...status,