diff --git a/web/pages/components/config/constants.tsx b/web/pages/components/config/constants.tsx index 503b3e882..e3748a33d 100644 --- a/web/pages/components/config/constants.tsx +++ b/web/pages/components/config/constants.tsx @@ -187,23 +187,29 @@ export const TEXTFIELD_DEFAULTS = { }, videoSettings: { + // number slider numberOfPlaylistItems: { apiPath: '/webserverport', // tbd defaultValue: 4, - maxLength: 6, + maxLength: 3, placeholder: '4', label: 'Segment Length', tip: '', required: true, + minValue: 1, + maxValue: 10, }, + // number slider segmentLengthSeconds: { apiPath: '/webserverport', // tbd defaultValue: 5, - maxLength: 6, + maxLength: 3, placeholder: '5', label: 'Number of segments', tip: '', required: true, + minValue: 1, + maxValue: 10, }, } } diff --git a/web/pages/components/config/edit-directory.tsx b/web/pages/components/config/edit-directory.tsx index 797253114..3be998b34 100644 --- a/web/pages/components/config/edit-directory.tsx +++ b/web/pages/components/config/edit-directory.tsx @@ -35,7 +35,6 @@ export default function EditYPDetails() { disabled: !hasInstanceUrl, }; - // TODO: DISABLE THIS SECTION UNTIL instanceURL is populated return (
Owncast Directory Settings diff --git a/web/pages/components/config/form-textfield.tsx b/web/pages/components/config/form-textfield.tsx index b14e3d0d1..7219cf16d 100644 --- a/web/pages/components/config/form-textfield.tsx +++ b/web/pages/components/config/form-textfield.tsx @@ -31,7 +31,7 @@ export default function TextField(props: TextFieldProps) { configPath = '', disabled = false, fieldName, - handleResetValue, + handleResetValue = () => {}, initialValues = {}, onSubmit, onBlur, @@ -67,7 +67,7 @@ export default function TextField(props: TextFieldProps) { const val = type === TEXTFIELD_TYPE_NUMBER ? e : e.target.value; // https://developer.mozilla.org/en-US/docs/Web/API/ValidityState - const hasValidity = type !== TEXTFIELD_TYPE_NUMBER && e.target.validity.valid; + const hasValidity = (type !== TEXTFIELD_TYPE_NUMBER && e.target.validity.valid) || type === TEXTFIELD_TYPE_NUMBER ; if ((required && (val === '' || val === null)) || val === initialValue || !hasValidity) { setHasChanged(false); @@ -139,7 +139,7 @@ export default function TextField(props: TextFieldProps) { Field = InputNumber; fieldProps = { type: 'number', - min: 0, + min: 1, max: (10**maxLength) - 1, onKeyDown: (e: React.KeyboardEvent) => { if (e.target.value.length > maxLength - 1 ) @@ -154,7 +154,7 @@ export default function TextField(props: TextFieldProps) { } return ( -
+
+ !bitrate ? "Same as source" : `${bitrate} kbps`, + }, + { + title: "Framerate", + dataIndex: "framerate", + key: "framerate", + render: (framerate: number) => + !framerate ? "Same as source" : `${framerate} fps`, + }, + { + title: "Encoder preset", + dataIndex: "encoderPreset", + key: "encoderPreset", + render: (preset: string) => + !preset ? "n/a" : preset, + }, + { + title: "Audio bitrate", + dataIndex: "audioBitrate", + key: "audioBitrate", + render: (bitrate: number) => + !bitrate ? "Same as source" : `${bitrate} kbps`, + }, + { + title: '', + dataIndex: '', + key: 'edit', + render: () => "edit.. populate modal", + }, + ]; + + + const videoQualityVariantData = videoQualityVariants.map((variant, index) => ({ key: index, ...variant })); + + return ( + <> + Current Variants + + + + + ); +} \ No newline at end of file diff --git a/web/pages/config-page-content.tsx b/web/pages/config-page-content.tsx index 4e6466307..4a5ad491d 100644 --- a/web/pages/config-page-content.tsx +++ b/web/pages/config-page-content.tsx @@ -95,7 +95,7 @@ export default function PageContentEditor() { }} />
- { hasChanged ? : null } + { hasChanged ? : null }
{newStatusIcon} {newStatusMessage} {submitStatusMessage}
diff --git a/web/pages/config-public-details.tsx b/web/pages/config-public-details.tsx index 2531dba5b..28f257608 100644 --- a/web/pages/config-public-details.tsx +++ b/web/pages/config-public-details.tsx @@ -1,5 +1,6 @@ import React, { useContext, useEffect } from 'react'; import { Typography, Form } from 'antd'; +import Link from 'next/link'; import TextField, { TEXTFIELD_TYPE_TEXTAREA, TEXTFIELD_TYPE_URL } from './components/config/form-textfield'; @@ -18,27 +19,21 @@ export default function PublicFacingDetails() { const { serverConfig } = serverStatusData || {}; const { instanceDetails, yp } = serverConfig; - const { instanceDetails: instanceDetailsDefaults, yp: ypDefaults } = TEXTFIELD_DEFAULTS; const initialValues = { ...instanceDetails, ...yp, }; - const defaultFields = { - ...instanceDetailsDefaults, - ...ypDefaults, - }; - useEffect(() => { form.setFieldsValue(initialValues); }, [instanceDetails]); - const handleResetValue = (fieldName: string) => { - const defaultValue = defaultFields[fieldName] && defaultFields[fieldName].defaultValue || ''; + // const handleResetValue = (fieldName: string) => { + // const defaultValue = defaultFields[fieldName] && defaultFields[fieldName].defaultValue || ''; - form.setFieldsValue({ [fieldName]: initialValues[fieldName] || defaultValue }); - } + // form.setFieldsValue({ [fieldName]: initialValues[fieldName] || defaultValue }); + // } // if instanceUrl is empty, we should also turn OFF the `enabled` field of directory. const handleSubmitInstanceUrl = () => { @@ -54,7 +49,7 @@ export default function PublicFacingDetails() { } const extraProps = { - handleResetValue, + // handleResetValue, initialValues, configPath: 'instanceDetails', }; @@ -83,6 +78,9 @@ export default function PublicFacingDetails() { + + this page! +
{/* add social handles comp diff --git a/web/pages/config-server-details.tsx b/web/pages/config-server-details.tsx index 5196983bc..5ed3e1ef6 100644 --- a/web/pages/config-server-details.tsx +++ b/web/pages/config-server-details.tsx @@ -31,7 +31,7 @@ export default function ConfigServerDetails() { const defaultValue = TEXTFIELD_DEFAULTS[fieldName] && TEXTFIELD_DEFAULTS[fieldName].defaultValue || ''; form.setFieldsValue({ [fieldName]: initialValues[fieldName] || defaultValue }); - } + }; const extraProps = { handleResetValue, diff --git a/web/pages/config-video.tsx b/web/pages/config-video.tsx index 100951982..539b83675 100644 --- a/web/pages/config-video.tsx +++ b/web/pages/config-video.tsx @@ -1,113 +1,62 @@ -import React, { useContext } from 'react'; -import { Table, Typography } from 'antd'; +import React, { useContext, useEffect } from 'react'; +import { Typography, Form, Slider } from 'antd'; import { ServerStatusContext } from '../utils/server-status-context'; +import VideoVariantsTable from './components/config/video-variants-table'; +import TextField, { TEXTFIELD_TYPE_NUMBER } from './components/config/form-textfield'; +import { TEXTFIELD_DEFAULTS } from './components/config/constants'; + const { Title } = Typography; - -function VideoVariants({ config }) { - if (!config || !config.videoSettings) { - return null; - } - console.log(config.videoSettings) - - const videoQualityColumns = [ - { - title: "#", - dataIndex: "key", - key: "key" - }, - { - title: "Video bitrate", - dataIndex: "videoBitrate", - key: "videoBitrate", - render: (bitrate) => - !bitrate ? "Same as source" : `${bitrate} kbps`, - }, - { - title: "Framerate", - dataIndex: "framerate", - key: "framerate", - render: (framerate) => - !framerate ? "Same as source" : `${framerate} fps`, - }, - { - title: "Encoder preset", - dataIndex: "encoderPreset", - key: "framerate", - render: (preset) => - !preset ? "n/a" : preset, - }, - { - title: "Audio bitrate", - dataIndex: "audioBitrate", - key: "audioBitrate", - render: (bitrate) => - !bitrate ? "Same as source" : `${bitrate} kbps`, - }, - ]; - - const miscVideoSettingsColumns = [ - { - title: "Name", - dataIndex: "name", - key: "name", - }, - { - title: "Value", - dataIndex: "value", - key: "value", - }, - ]; - - const miscVideoSettings = [ - { - name: "Segment length", - value: config.videoSettings.segmentLengthSeconds, - key: "segmentLength" - }, - { - name: "Number of segments", - value: config.videoSettings.numberOfPlaylistItems, - key: "numberOfSegments" - }, - ]; - - const videoQualityVariantData = config.videoSettings.videoQualityVariants.map(function(variant, index) { - return { - key: index, - ...variant - } - }); - - return ( -
- Video configuration -
- -
row.name} - /> -
- Learn more about configuring Owncast <a href="https://owncast.online/docs/configuration">by visiting the documentation.</a> - - ); -} - -export default function VideoConfig() { +export default function VideoConfig() { + const [form] = Form.useForm(); const serverStatusData = useContext(ServerStatusContext); - const { serverConfig: config } = serverStatusData || {}; + // const { serverConfig } = serverStatusData || {}; + // const { videoSettings } = serverConfig || {}; + // const { numberOfPlaylistItems, segmentLengthSeconds } = videoSettings || {}; + + const videoSettings = serverStatusData?.serverConfig?.videoSettings; + const { numberOfPlaylistItems, segmentLengthSeconds } = videoSettings || {}; + const initialValues = { + numberOfPlaylistItems, + segmentLengthSeconds, + }; + + useEffect(() => { + form.setFieldsValue(initialValues); + }, [serverStatusData]); + + const handleResetValue = (fieldName: string) => { + const defaultValue = TEXTFIELD_DEFAULTS.videoSettings[fieldName] && TEXTFIELD_DEFAULTS.videoSettings[fieldName].defaultValue || ''; + + form.setFieldsValue({ [fieldName]: initialValues[fieldName] || defaultValue }); + } + + const extraProps = { + handleResetValue, + initialValues: videoSettings, + configPath: 'videoSettings', + }; return ( -
- +
+ Video configuration + Learn more about configuring Owncast <a href="https://owncast.online/docs/configuration">by visiting the documentation.</a> + +
+ + + + +
+ + + +
+
); } diff --git a/web/styles/colors.scss b/web/styles/colors.scss index 5c93e506d..575542372 100644 --- a/web/styles/colors.scss +++ b/web/styles/colors.scss @@ -4,6 +4,8 @@ --online-color: #73dd3f; + --owncast-dark1: #1f1f21; + --ant-error: #ff4d4f; --ant-success: #52c41a; diff --git a/web/styles/config.scss b/web/styles/config.scss index 2361c8e8a..40c6005ce 100644 --- a/web/styles/config.scss +++ b/web/styles/config.scss @@ -13,7 +13,7 @@ .tag-editor-container, .config-directory-details-form { border-radius: 1em; - background-color: rgba(128,0,255,.15); + background-color: rgba(128,99,255,.1); padding: 1.5em; margin-bottom: 1em; } @@ -41,6 +41,15 @@ justify-content: flex-end; position: relative; width: 314px; + + // &.type-numeric { + // .ant-form-item-control { + // flex-direction: row; + // .ant-form-item-control-input { + // margin-right: .75rem; + // } + // } + // } } .textfield { display: flex; @@ -77,6 +86,17 @@ right: 0; bottom: .5em; } +// .ant-form-horizontal { +// .textfield-container.type-numeric { +// width: auto; + +// .submit-button { +// bottom: unset; +// top: 0; +// right: unset; +// } +// } +// } // form-toggleswitch @@ -156,3 +176,14 @@ } } } + +.config-video-variants { + .config-video-misc { + margin: 2rem 0; + // .ant-form { + // display: flex; + // flex-direction: row; + // align-items: flex-start; + // } + } +} diff --git a/web/styles/globals.scss b/web/styles/globals.scss index cd1d7cdcf..3820090a6 100644 --- a/web/styles/globals.scss +++ b/web/styles/globals.scss @@ -1,3 +1,5 @@ +@import "~antd/dist/antd.dark"; + $owncast-purple: rgba(90,103,216,1); html, @@ -7,6 +9,8 @@ body { font-family: system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji"; font-size: 16px; + + // background-color: #1f1f21; } a { @@ -25,6 +29,11 @@ pre { margin: .5rem 0; background-color: #eee; } +// pre { +// background-color: rgb(44, 44, 44); +// color:lightgrey; +// } + code { color: var(--owncast-purple); } @@ -34,14 +43,7 @@ code { } - -@media (prefers-color-scheme: dark) { - @import "~antd/dist/antd.dark"; - pre { - background-color: rgb(44, 44, 44); - color:lightgrey; - } -} + // GENERAL ANT FORM OVERRIDES @@ -50,24 +52,22 @@ code { } .ant-input-affix-wrapper { border-radius: 5px; - background-color: rgba(0,0,0,.1); - @media (prefers-color-scheme: dark) { - border-radius: 5px; - background-color: rgba(255,255,255,.1); - } + background-color: rgba(255,255,255,.1); + textarea { border-radius: 5px; } + input { + background-color: transparent; + } } .ant-btn-primary:hover, .ant-btn-primary:focus { background-color: white; color: #40a9ff; } .ant-btn.ant-btn-primary:focus { - border: 1px solid var(--owncast-purple); - @media (prefers-color-scheme: dark) { - border-color: white; - } + border-color: white; + } .ant-input-affix-wrapper, .ant-btn { @@ -76,41 +76,40 @@ code { } // markdown editor overrides -@media (prefers-color-scheme: dark) { - .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: $owncast-purple; - } - h1 { - font-size: 2em; - } - } +.rc-md-editor { + // Set the background color of the preview container + .editor-container { + background-color: #E2E8F0; + color: rgba(45,55,72,1); + } - // Custom CSS class used to format the text of the editor - .markdown-editor-pane { - color: white !important; - background-color: black; - font-family: monospace; + // Custom CSS for formatting the preview text + .markdown-editor-preview-pane { + // color:lightgrey; + a { + color: $owncast-purple; } + h1 { + font-size: 2em; + } + } - // Set the background color of the editor text input - textarea { - background-color: rgb(44,44,44) !important; - color:lightgrey !important; - } + // Custom CSS class used to format the text of the editor + .markdown-editor-pane { + color: white !important; + background-color: black; + font-family: monospace; + } - // 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; - } - } -} + // Set the background color of the editor text input + textarea { + background-color: rgb(44,44,44) !important; + color:lightgrey !important; + } + + // 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; + } +} \ No newline at end of file