0

apply config form flow to edit content page

This commit is contained in:
gingervitis 2021-01-03 23:32:47 -08:00 committed by Gabe Kangas
parent 2772a8e5ec
commit e7e89556e7
9 changed files with 139 additions and 61 deletions

View File

@ -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) => {

View File

@ -150,6 +150,9 @@ export default function MainLayout(props) {
<Menu.Item key="config-storage">
<Link href="/config-storage">Storage</Link>
</Menu.Item>
<Menu.Item key="config-page-content">
<Link href="/config-page-content">Custom page content</Link>
</Menu.Item>
</SubMenu>
<SubMenu

View File

@ -0,0 +1,105 @@
import React, { useState, useEffect, useContext } from 'react';
import { Typography, Button } from "antd";
import { FormItemProps } from 'antd/lib/form';
import dynamic from 'next/dynamic';
import MarkdownIt from 'markdown-it';
import { ServerStatusContext } from '../utils/server-status-context';
import { TEXTFIELD_DEFAULTS, postConfigUpdateToAPI, RESET_TIMEOUT, SUCCESS_STATES} from './components/config/constants';
import 'react-markdown-editor-lite/lib/index.css';
const { Title } = Typography;
const mdParser = new MarkdownIt(/* Markdown-it options */);
const MdEditor = dynamic(() => import('react-markdown-editor-lite'), {
ssr: false,
});
export default function PageContentEditor() {
const [content, setContent] = useState('');
const [submitStatus, setSubmitStatus] = useState<FormItemProps['validateStatus']>('');
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 (
<div className="config-page-content-form">
<Title level={2}>Edit custom content</Title>
<p>Add some content about your site with the Markdown editor below. This content shows up at the bottom half of your Owncast page.</p>
<MdEditor
style={{ height: "30em" }}
value={content}
renderHTML={(c: string) => mdParser.render(c)}
onChange={handleEditorChange}
config={{
htmlClass: 'markdown-editor-preview-pane',
markdownClass: 'markdown-editor-pane',
}}
/>
<div className="page-content-actions">
{ hasChanged ? <Button type="primary" size="small" onClick={handleSave}>Save</Button> : null }
<div className={`status-message ${submitStatus || ''}`}>
{newStatusIcon} {newStatusMessage} {submitStatusMessage}
</div>
</div>
</div>
);
}

View File

@ -39,7 +39,7 @@ export default function ConfigServerDetails() {
configPath: '',
};
return (
<>
<div className="config-server-details-form">
<Title level={2}>Edit your Server&apos;s details</Title>
<div className="config-public-details-container">
@ -53,7 +53,7 @@ export default function ConfigServerDetails() {
<TextField fieldName="rtmpServerPort" type={TEXTFIELD_TYPE_NUMBER} {...extraProps} />
</Form>
</div>
</>
</div>
);
}

View File

@ -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 (
<div>
<MdEditor
style={{ height: "500px" }}
value={content}
renderHTML={(content) => mdParser.render(content)}
onChange={handleEditorChange}
config={{ htmlClass: 'markdown-editor-preview-pane', markdownClass: 'markdown-editor-pane' }}
/>
<Button onClick={handleSave}>Save</Button>
</div>
);
}

View File

@ -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;
}
}
}

View File

@ -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.

View File

@ -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;

View File

@ -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,