diff --git a/web/pages/components/chart.tsx b/web/components/chart.tsx similarity index 100% rename from web/pages/components/chart.tsx rename to web/components/chart.tsx diff --git a/web/pages/components/config/README.md b/web/components/config/README.md similarity index 100% rename from web/pages/components/config/README.md rename to web/components/config/README.md diff --git a/web/pages/components/config/cpu-usage.tsx b/web/components/config/cpu-usage.tsx similarity index 94% rename from web/pages/components/config/cpu-usage.tsx rename to web/components/config/cpu-usage.tsx index 139ea85e7..f7d82a194 100644 --- a/web/pages/components/config/cpu-usage.tsx +++ b/web/components/config/cpu-usage.tsx @@ -1,6 +1,6 @@ import React, { useContext, useState, useEffect } from 'react'; import { Typography, Slider } from 'antd'; -import { ServerStatusContext } from '../../../utils/server-status-context'; +import { ServerStatusContext } from '../../utils/server-status-context'; const { Title } = Typography; diff --git a/web/pages/components/config/edit-directory.tsx b/web/components/config/edit-directory.tsx similarity index 92% rename from web/pages/components/config/edit-directory.tsx rename to web/components/config/edit-directory.tsx index fa8e81382..3a56cdd5f 100644 --- a/web/pages/components/config/edit-directory.tsx +++ b/web/components/config/edit-directory.tsx @@ -4,8 +4,8 @@ import { Typography } from 'antd'; import ToggleSwitch from './form-toggleswitch-with-submit'; -import { ServerStatusContext } from '../../../utils/server-status-context'; -import { FIELD_PROPS_NSFW, FIELD_PROPS_YP } from './constants'; +import { ServerStatusContext } from '../../utils/server-status-context'; +import { FIELD_PROPS_NSFW, FIELD_PROPS_YP } from '../../utils/config-constants'; const { Title } = Typography; diff --git a/web/pages/components/config/edit-instance-details.tsx b/web/components/config/edit-instance-details.tsx similarity index 93% rename from web/pages/components/config/edit-instance-details.tsx rename to web/components/config/edit-instance-details.tsx index 7c5d32708..7ef694f25 100644 --- a/web/pages/components/config/edit-instance-details.tsx +++ b/web/components/config/edit-instance-details.tsx @@ -4,7 +4,7 @@ import TextFieldWithSubmit, { TEXTFIELD_TYPE_URL, } from './form-textfield-with-submit'; -import { ServerStatusContext } from '../../../utils/server-status-context'; +import { ServerStatusContext } from '../../utils/server-status-context'; import { postConfigUpdateToAPI, TEXTFIELD_PROPS_INSTANCE_URL, @@ -12,9 +12,9 @@ import { TEXTFIELD_PROPS_SERVER_SUMMARY, TEXTFIELD_PROPS_LOGO, API_YP_SWITCH, -} from './constants'; +} from '../../utils/config-constants'; -import { UpdateArgs } from '../../../types/config-section'; +import { UpdateArgs } from '../../types/config-section'; export default function EditInstanceDetails() { const [formDataValues, setFormDataValues] = useState(null); diff --git a/web/pages/components/config/edit-server-details.tsx b/web/components/config/edit-server-details.tsx similarity index 90% rename from web/pages/components/config/edit-server-details.tsx rename to web/components/config/edit-server-details.tsx index 77551557f..afe2223ee 100644 --- a/web/pages/components/config/edit-server-details.tsx +++ b/web/components/config/edit-server-details.tsx @@ -5,17 +5,17 @@ import { CopyOutlined, RedoOutlined } from '@ant-design/icons'; import { TEXTFIELD_TYPE_NUMBER, TEXTFIELD_TYPE_PASSWORD } from './form-textfield'; import TextFieldWithSubmit from './form-textfield-with-submit'; -import { ServerStatusContext } from '../../../utils/server-status-context'; -import { AlertMessageContext } from '../../../utils/alert-message-context'; +import { ServerStatusContext } from '../../utils/server-status-context'; +import { AlertMessageContext } from '../../utils/alert-message-context'; import { TEXTFIELD_PROPS_FFMPEG, TEXTFIELD_PROPS_RTMP_PORT, TEXTFIELD_PROPS_STREAM_KEY, TEXTFIELD_PROPS_WEB_PORT, -} from './constants'; +} from '../../utils/config-constants'; -import { UpdateArgs } from '../../../types/config-section'; +import { UpdateArgs } from '../../types/config-section'; export default function EditInstanceDetails() { const [formDataValues, setFormDataValues] = useState(null); @@ -55,7 +55,9 @@ export default function EditInstanceDetails() { }; const showStreamKeyChangeMessage = () => { - setMessage('Changing your stream key will log you out of the admin and block you from streaming until you change the key in your broadcasting software.'); + setMessage( + 'Changing your stream key will log you out of the admin and block you from streaming until you change the key in your broadcasting software.', + ); }; const showFfmpegChangeMessage = () => { diff --git a/web/pages/components/config/edit-social-links.tsx b/web/components/config/edit-social-links.tsx similarity index 95% rename from web/pages/components/config/edit-social-links.tsx rename to web/components/config/edit-social-links.tsx index af9096f4d..2396f1121 100644 --- a/web/pages/components/config/edit-social-links.tsx +++ b/web/components/config/edit-social-links.tsx @@ -3,19 +3,19 @@ import { Typography, Table, Button, Modal, Input } from 'antd'; import { ColumnsType } from 'antd/lib/table'; import { DeleteOutlined } from '@ant-design/icons'; import SocialDropdown from './social-icons-dropdown'; -import { fetchData, NEXT_PUBLIC_API_HOST, SOCIAL_PLATFORMS_LIST } from '../../../utils/apis'; -import { ServerStatusContext } from '../../../utils/server-status-context'; +import { fetchData, NEXT_PUBLIC_API_HOST, SOCIAL_PLATFORMS_LIST } from '../../utils/apis'; +import { ServerStatusContext } from '../../utils/server-status-context'; import { API_SOCIAL_HANDLES, postConfigUpdateToAPI, RESET_TIMEOUT, DEFAULT_SOCIAL_HANDLE, OTHER_SOCIAL_HANDLE_OPTION, -} from './constants'; -import { SocialHandle, UpdateArgs } from '../../../types/config-section'; -import { isValidUrl } from '../../../utils/urls'; +} from '../../utils/config-constants'; +import { SocialHandle, UpdateArgs } from '../../types/config-section'; +import { isValidUrl } from '../../utils/urls'; import TextField from './form-textfield'; -import { createInputStatus, STATUS_ERROR, STATUS_SUCCESS } from '../../../utils/input-statuses'; +import { createInputStatus, STATUS_ERROR, STATUS_SUCCESS } from '../../utils/input-statuses'; import FormStatusIndicator from './form-status-indicator'; const { Title } = Typography; @@ -43,9 +43,9 @@ export default function EditSocialLinks() { let resetTimer = null; const PLACEHOLDERS = { - 'mastodon': 'https://mastodon.social/@username', - 'twitter': 'https://twitter.com/username' - } + mastodon: 'https://mastodon.social/@username', + twitter: 'https://twitter.com/username', + }; const getAvailableIcons = async () => { try { diff --git a/web/pages/components/config/edit-storage.tsx b/web/components/config/edit-storage.tsx similarity index 95% rename from web/pages/components/config/edit-storage.tsx rename to web/components/config/edit-storage.tsx index ae9efba22..129b31811 100644 --- a/web/pages/components/config/edit-storage.tsx +++ b/web/components/config/edit-storage.tsx @@ -1,26 +1,26 @@ import { Switch, Button, Collapse } from 'antd'; import classNames from 'classnames'; import React, { useContext, useState, useEffect } from 'react'; -import { UpdateArgs } from '../../../types/config-section'; -import { ServerStatusContext } from '../../../utils/server-status-context'; -import { AlertMessageContext } from '../../../utils/alert-message-context'; +import { UpdateArgs } from '../../types/config-section'; +import { ServerStatusContext } from '../../utils/server-status-context'; +import { AlertMessageContext } from '../../utils/alert-message-context'; import { postConfigUpdateToAPI, API_S3_INFO, RESET_TIMEOUT, S3_TEXT_FIELDS_INFO, -} from './constants'; +} from '../../utils/config-constants'; import { createInputStatus, StatusState, STATUS_ERROR, STATUS_PROCESSING, STATUS_SUCCESS, -} from '../../../utils/input-statuses'; +} from '../../utils/input-statuses'; import TextField from './form-textfield'; import FormStatusIndicator from './form-status-indicator'; -import { isValidUrl } from '../../../utils/urls'; +import { isValidUrl } from '../../utils/urls'; const { Panel } = Collapse; diff --git a/web/pages/components/config/edit-tags.tsx b/web/components/config/edit-tags.tsx similarity index 92% rename from web/pages/components/config/edit-tags.tsx rename to web/components/config/edit-tags.tsx index e92278974..c989b89a1 100644 --- a/web/pages/components/config/edit-tags.tsx +++ b/web/components/config/edit-tags.tsx @@ -2,10 +2,14 @@ import React, { useContext, useState, useEffect } from 'react'; import { Typography, Tag } from 'antd'; -import { ServerStatusContext } from '../../../utils/server-status-context'; -import { FIELD_PROPS_TAGS, RESET_TIMEOUT, postConfigUpdateToAPI } from './constants'; +import { ServerStatusContext } from '../../utils/server-status-context'; +import { + FIELD_PROPS_TAGS, + RESET_TIMEOUT, + postConfigUpdateToAPI, +} from '../../utils/config-constants'; import TextField from './form-textfield'; -import { UpdateArgs } from '../../../types/config-section'; +import { UpdateArgs } from '../../types/config-section'; import { createInputStatus, StatusState, @@ -13,7 +17,7 @@ import { STATUS_PROCESSING, STATUS_SUCCESS, STATUS_WARNING, -} from '../../../utils/input-statuses'; +} from '../../utils/input-statuses'; const { Title } = Typography; diff --git a/web/pages/components/config/form-status-indicator.tsx b/web/components/config/form-status-indicator.tsx similarity index 90% rename from web/pages/components/config/form-status-indicator.tsx rename to web/components/config/form-status-indicator.tsx index 28c61771e..a80fd75c6 100644 --- a/web/pages/components/config/form-status-indicator.tsx +++ b/web/components/config/form-status-indicator.tsx @@ -1,7 +1,7 @@ import React from 'react'; import classNames from 'classnames'; -import { StatusState } from '../../../utils/input-statuses'; +import { StatusState } from '../../utils/input-statuses'; interface FormStatusIndicatorProps { status: StatusState; diff --git a/web/pages/components/config/form-textfield-with-submit.tsx b/web/components/config/form-textfield-with-submit.tsx similarity index 94% rename from web/pages/components/config/form-textfield-with-submit.tsx rename to web/components/config/form-textfield-with-submit.tsx index 5505aeb7c..3804df7fa 100644 --- a/web/pages/components/config/form-textfield-with-submit.tsx +++ b/web/components/config/form-textfield-with-submit.tsx @@ -1,9 +1,9 @@ import React, { useEffect, useState, useContext } from 'react'; import { Button } from 'antd'; import classNames from 'classnames'; -import { RESET_TIMEOUT, postConfigUpdateToAPI } from './constants'; +import { RESET_TIMEOUT, postConfigUpdateToAPI } from '../../utils/config-constants'; -import { ServerStatusContext } from '../../../utils/server-status-context'; +import { ServerStatusContext } from '../../utils/server-status-context'; import TextField, { TextFieldProps } from './form-textfield'; import { createInputStatus, @@ -11,8 +11,8 @@ import { STATUS_ERROR, STATUS_PROCESSING, STATUS_SUCCESS, -} from '../../../utils/input-statuses'; -import { UpdateArgs } from '../../../types/config-section'; +} from '../../utils/input-statuses'; +import { UpdateArgs } from '../../types/config-section'; import FormStatusIndicator from './form-status-indicator'; export const TEXTFIELD_TYPE_TEXT = 'default'; diff --git a/web/pages/components/config/form-textfield.tsx b/web/components/config/form-textfield.tsx similarity index 92% rename from web/pages/components/config/form-textfield.tsx rename to web/components/config/form-textfield.tsx index 825530588..8b0862be7 100644 --- a/web/pages/components/config/form-textfield.tsx +++ b/web/components/config/form-textfield.tsx @@ -1,9 +1,9 @@ import React from 'react'; import classNames from 'classnames'; import { Input, InputNumber } from 'antd'; -import { FieldUpdaterFunc } from '../../../types/config-section'; +import { FieldUpdaterFunc } from '../../types/config-section'; // import InfoTip from '../info-tip'; -import { StatusState } from '../../../utils/input-statuses'; +import { StatusState } from '../../utils/input-statuses'; import FormStatusIndicator from './form-status-indicator'; export const TEXTFIELD_TYPE_TEXT = 'default'; @@ -96,10 +96,6 @@ export default function TextField(props: TextFieldProps) { type: 'number', min: 1, max: 10 ** maxLength - 1, - onKeyDown: (e: React.KeyboardEvent) => { - if (e.target.value.length > maxLength - 1) e.preventDefault(); - return false; - }, }; } else if (type === TEXTFIELD_TYPE_URL) { fieldProps = { @@ -140,7 +136,7 @@ export default function TextField(props: TextFieldProps) { onBlur={handleBlur} onPressEnter={handlePressEnter} disabled={disabled} - value={value} + value={value as number | (readonly string[] & number)} /> @@ -159,7 +155,7 @@ TextField.defaultProps = { disabled: false, // initialValue: '', label: '', - maxLength: null, + maxLength: 255, placeholder: '', required: false, diff --git a/web/pages/components/config/form-toggleswitch-with-submit.tsx b/web/components/config/form-toggleswitch-with-submit.tsx similarity index 92% rename from web/pages/components/config/form-toggleswitch-with-submit.tsx rename to web/components/config/form-toggleswitch-with-submit.tsx index 4676625f2..942da041c 100644 --- a/web/pages/components/config/form-toggleswitch-with-submit.tsx +++ b/web/components/config/form-toggleswitch-with-submit.tsx @@ -6,12 +6,12 @@ import { STATUS_ERROR, STATUS_PROCESSING, STATUS_SUCCESS, -} from '../../../utils/input-statuses'; +} from '../../utils/input-statuses'; import FormStatusIndicator from './form-status-indicator'; -import { RESET_TIMEOUT, postConfigUpdateToAPI } from './constants'; +import { RESET_TIMEOUT, postConfigUpdateToAPI } from '../../utils/config-constants'; -import { ServerStatusContext } from '../../../utils/server-status-context'; +import { ServerStatusContext } from '../../utils/server-status-context'; import InfoTip from '../info-tip'; interface ToggleSwitchProps { diff --git a/web/pages/components/config/social-icons-dropdown.tsx b/web/components/config/social-icons-dropdown.tsx similarity index 90% rename from web/pages/components/config/social-icons-dropdown.tsx rename to web/components/config/social-icons-dropdown.tsx index 767c8ea88..cb3a621d8 100644 --- a/web/pages/components/config/social-icons-dropdown.tsx +++ b/web/components/config/social-icons-dropdown.tsx @@ -1,8 +1,8 @@ import React from 'react'; import { Select } from 'antd'; -import { SocialHandleDropdownItem } from '../../../types/config-section'; -import { NEXT_PUBLIC_API_HOST } from '../../../utils/apis'; -import { OTHER_SOCIAL_HANDLE_OPTION } from './constants'; +import { SocialHandleDropdownItem } from '../../types/config-section'; +import { NEXT_PUBLIC_API_HOST } from '../../utils/apis'; +import { OTHER_SOCIAL_HANDLE_OPTION } from '../../utils/config-constants'; interface DropdownProps { iconList: SocialHandleDropdownItem[]; diff --git a/web/pages/components/config/video-latency.tsx b/web/components/config/video-latency.tsx similarity index 80% rename from web/pages/components/config/video-latency.tsx rename to web/components/config/video-latency.tsx index 455a19b9c..c213e0f6d 100644 --- a/web/pages/components/config/video-latency.tsx +++ b/web/components/config/video-latency.tsx @@ -1,15 +1,19 @@ import React, { useContext, useState, useEffect } from 'react'; import { Typography, Slider } from 'antd'; -import { ServerStatusContext } from '../../../utils/server-status-context'; -import { AlertMessageContext } from '../../../utils/alert-message-context'; -import { API_VIDEO_SEGMENTS, RESET_TIMEOUT, postConfigUpdateToAPI } from './constants'; +import { ServerStatusContext } from '../../utils/server-status-context'; +import { AlertMessageContext } from '../../utils/alert-message-context'; +import { + API_VIDEO_SEGMENTS, + RESET_TIMEOUT, + postConfigUpdateToAPI, +} from '../../utils/config-constants'; import { createInputStatus, StatusState, STATUS_ERROR, STATUS_PROCESSING, STATUS_SUCCESS, -} from '../../../utils/input-statuses'; +} from '../../utils/input-statuses'; import FormStatusIndicator from './form-status-indicator'; const { Title } = Typography; @@ -88,7 +92,9 @@ export default function VideoLatency() { // setSubmitStatusMessage('Variants updated.'); resetTimer = setTimeout(resetStates, RESET_TIMEOUT); if (serverStatusData.online) { - setMessage('Your latency buffer setting will take effect the next time you begin a live stream.') + setMessage( + 'Your latency buffer setting will take effect the next time you begin a live stream.', + ); } }, onError: (message: string) => { @@ -109,11 +115,13 @@ export default function VideoLatency() {
Latency Buffer

- While it's natural to want to keep your latency as low as possible, you may experience reduced error tolerance and stability in some environments the lower you go. -

- For interactive live streams you may want to experiment with a lower latency, for non-interactive broadcasts you may want to increase it. Read to learn more. -

+ While it's natural to want to keep your latency as low as possible, you may experience + reduced error tolerance and stability in some environments the lower you go.

+ For interactive live streams you may want to experiment with a lower latency, for + non-interactive broadcasts you may want to increase it.{' '} + Read to learn more. +

} diff --git a/web/pages/components/config/video-variant-form.tsx b/web/components/config/video-variant-form.tsx similarity index 97% rename from web/pages/components/config/video-variant-form.tsx rename to web/components/config/video-variant-form.tsx index c5e7b5e83..1d85253a4 100644 --- a/web/pages/components/config/video-variant-form.tsx +++ b/web/components/config/video-variant-form.tsx @@ -1,8 +1,8 @@ // This content populates the video variant modal, which is spawned from the variants table. import React from 'react'; import { Slider, Switch, Collapse } from 'antd'; -import { FieldUpdaterFunc, VideoVariant } from '../../../types/config-section'; -import { DEFAULT_VARIANT_STATE } from './constants'; +import { FieldUpdaterFunc, VideoVariant } from '../../types/config-section'; +import { DEFAULT_VARIANT_STATE } from '../../utils/config-constants'; import InfoTip from '../info-tip'; import CPUUsageSelector from './cpu-usage'; diff --git a/web/pages/components/config/video-variants-table.tsx b/web/components/config/video-variants-table.tsx similarity index 95% rename from web/pages/components/config/video-variants-table.tsx rename to web/components/config/video-variants-table.tsx index 39b337afa..c22e62118 100644 --- a/web/pages/components/config/video-variants-table.tsx +++ b/web/components/config/video-variants-table.tsx @@ -4,9 +4,9 @@ import React, { useContext, useState } from 'react'; import { Typography, Table, Modal, Button } from 'antd'; import { ColumnsType } from 'antd/lib/table'; import { DeleteOutlined } from '@ant-design/icons'; -import { ServerStatusContext } from '../../../utils/server-status-context'; -import { AlertMessageContext } from '../../../utils/alert-message-context'; -import { UpdateArgs, VideoVariant } from '../../../types/config-section'; +import { ServerStatusContext } from '../../utils/server-status-context'; +import { AlertMessageContext } from '../../utils/alert-message-context'; +import { UpdateArgs, VideoVariant } from '../../types/config-section'; import VideoVariantForm from './video-variant-form'; import { @@ -15,7 +15,7 @@ import { SUCCESS_STATES, RESET_TIMEOUT, postConfigUpdateToAPI, -} from './constants'; +} from '../../utils/config-constants'; const { Title } = Typography; diff --git a/web/pages/components/info-tip.tsx b/web/components/info-tip.tsx similarity index 100% rename from web/pages/components/info-tip.tsx rename to web/components/info-tip.tsx diff --git a/web/pages/components/key-value-table.tsx b/web/components/key-value-table.tsx similarity index 100% rename from web/pages/components/key-value-table.tsx rename to web/components/key-value-table.tsx diff --git a/web/pages/components/log-table.tsx b/web/components/log-table.tsx similarity index 100% rename from web/pages/components/log-table.tsx rename to web/components/log-table.tsx diff --git a/web/pages/components/logo.tsx b/web/components/logo.tsx similarity index 100% rename from web/pages/components/logo.tsx rename to web/components/logo.tsx diff --git a/web/pages/components/main-layout.tsx b/web/components/main-layout.tsx similarity index 94% rename from web/pages/components/main-layout.tsx rename to web/components/main-layout.tsx index 095622b9e..486b7cdbf 100644 --- a/web/pages/components/main-layout.tsx +++ b/web/components/main-layout.tsx @@ -18,17 +18,17 @@ import { 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'; -import { AlertMessageContext } from '../../utils/alert-message-context'; +import { ServerStatusContext } from '../utils/server-status-context'; +import { AlertMessageContext } from '../utils/alert-message-context'; import TextFieldWithSubmit from './config/form-textfield-with-submit'; -import { TEXTFIELD_PROPS_STREAM_TITLE } from './config/constants'; +import { TEXTFIELD_PROPS_STREAM_TITLE } from '../utils/config-constants'; -import { UpdateArgs } from '../../types/config-section'; +import { UpdateArgs } from '../types/config-section'; let performedUpgradeCheck = false; diff --git a/web/pages/components/message-visiblity-toggle.tsx b/web/components/message-visiblity-toggle.tsx similarity index 91% rename from web/pages/components/message-visiblity-toggle.tsx rename to web/components/message-visiblity-toggle.tsx index bd4fdf64c..0e428e812 100644 --- a/web/pages/components/message-visiblity-toggle.tsx +++ b/web/components/message-visiblity-toggle.tsx @@ -7,10 +7,10 @@ import { CheckCircleFilled, ExclamationCircleFilled, } from '@ant-design/icons'; -import { fetchData, UPDATE_CHAT_MESSGAE_VIZ } from '../../utils/apis'; -import { MessageType } from '../../types/chat'; -import { OUTCOME_TIMEOUT } from '../chat'; -import { isEmptyObject } from '../../utils/format'; +import { fetchData, UPDATE_CHAT_MESSGAE_VIZ } from '../utils/apis'; +import { MessageType } from '../types/chat'; +import { OUTCOME_TIMEOUT } from '../pages/chat'; +import { isEmptyObject } from '../utils/format'; interface MessageToggleProps { isVisible: boolean; diff --git a/web/pages/components/statistic.tsx b/web/components/statistic.tsx similarity index 100% rename from web/pages/components/statistic.tsx rename to web/components/statistic.tsx diff --git a/web/pages/_app.tsx b/web/pages/_app.tsx index 49327044c..31fced645 100644 --- a/web/pages/_app.tsx +++ b/web/pages/_app.tsx @@ -23,7 +23,7 @@ import { AppProps } from 'next/app'; import ServerStatusProvider from '../utils/server-status-context'; import AlertMessageProvider from '../utils/alert-message-context'; -import MainLayout from './components/main-layout'; +import MainLayout from '../components/main-layout'; function App({ Component, pageProps }: AppProps) { return ( diff --git a/web/pages/chat.tsx b/web/pages/chat.tsx index 8deef3750..915b948d4 100644 --- a/web/pages/chat.tsx +++ b/web/pages/chat.tsx @@ -1,14 +1,14 @@ -import React, { useState, useEffect } from "react"; -import { Table, Typography, Tooltip, Button } from "antd"; -import { CheckCircleFilled, ExclamationCircleFilled } from "@ant-design/icons"; +import React, { useState, useEffect } from 'react'; +import { Table, Typography, Tooltip, Button } from 'antd'; +import { CheckCircleFilled, ExclamationCircleFilled } from '@ant-design/icons'; import classNames from 'classnames'; import { ColumnsType } from 'antd/es/table'; -import format from 'date-fns/format' +import format from 'date-fns/format'; -import { CHAT_HISTORY, fetchData, FETCH_INTERVAL, UPDATE_CHAT_MESSGAE_VIZ } from "../utils/apis"; +import { CHAT_HISTORY, fetchData, FETCH_INTERVAL, UPDATE_CHAT_MESSGAE_VIZ } from '../utils/apis'; import { MessageType } from '../types/chat'; -import { isEmptyObject } from "../utils/format"; -import MessageVisiblityToggle from "./components/message-visiblity-toggle"; +import { isEmptyObject } from '../utils/format'; +import MessageVisiblityToggle from '../components/message-visiblity-toggle'; const { Title } = Typography; @@ -55,7 +55,7 @@ export default function Chat() { setMessages(result); } } catch (error) { - console.log("==== error", error); + console.log('==== error', error); } }; @@ -73,7 +73,7 @@ export default function Chat() { }, []); const nameFilters = createUserNameFilters(messages); - + const rowSelection = { selectedRowKeys, onChange: (selectedKeys: string[]) => { @@ -81,10 +81,10 @@ export default function Chat() { }, }; - const updateMessage = message => { - const messageIndex = messages.findIndex(m => m.id === message.id); - messages.splice(messageIndex, 1, message) - setMessages([...messages]); + const updateMessage = message => { + const messageIndex = messages.findIndex(m => m.id === message.id); + messages.splice(messageIndex, 1, message); + setMessages([...messages]); }; const resetBulkOutcome = () => { @@ -93,7 +93,7 @@ export default function Chat() { setBulkAction(''); }, OUTCOME_TIMEOUT); }; - const handleSubmitBulk = async (bulkVisibility) => { + const handleSubmitBulk = async bulkVisibility => { setBulkProcessing(true); const result = await fetchData(UPDATE_CHAT_MESSGAE_VIZ, { auth: true, @@ -104,7 +104,7 @@ export default function Chat() { }, }); - if (result.success && result.message === "changed") { + if (result.success && result.message === 'changed') { setBulkOutcome(); resetBulkOutcome(); @@ -112,7 +112,7 @@ export default function Chat() { const updatedList = [...messages]; selectedRowKeys.map(key => { const messageIndex = updatedList.findIndex(m => m.id === key); - const newMessage = {...messages[messageIndex], visible: bulkVisibility }; + const newMessage = { ...messages[messageIndex], visible: bulkVisibility }; updatedList.splice(messageIndex, 1, newMessage); return null; }); @@ -123,15 +123,15 @@ export default function Chat() { resetBulkOutcome(); } setBulkProcessing(false); - } + }; const handleSubmitBulkShow = () => { setBulkAction('show'); handleSubmitBulk(true); - } + }; const handleSubmitBulkHide = () => { setBulkAction('hide'); handleSubmitBulk(false); - } + }; const chatColumns: ColumnsType = [ { @@ -140,7 +140,7 @@ export default function Chat() { key: 'timestamp', className: 'timestamp-col', defaultSortOrder: 'descend', - render: (timestamp) => { + render: timestamp => { const dateObject = new Date(timestamp); return format(dateObject, 'PP pp'); }, @@ -155,7 +155,7 @@ export default function Chat() { filters: nameFilters, onFilter: (value, record) => record.author === value, sorter: (a, b) => a.author.localeCompare(b.author), - sortDirections: ['ascend', 'descend'], + sortDirections: ['ascend', 'descend'], ellipsis: true, render: author => ( @@ -176,21 +176,20 @@ export default function Chat() { // eslint-disable-next-line react/no-danger dangerouslySetInnerHTML={{ __html: body }} /> - ) + ), }, { title: '', dataIndex: 'visible', key: 'visible', className: 'toggle-col', - filters: [{ text: 'Visible messages', value: true }, { text: 'Hidden messages', value: false }], + filters: [ + { text: 'Visible messages', value: true }, + { text: 'Hidden messages', value: false }, + ], onFilter: (value, record) => record.visible === value, render: (visible, record) => ( - + ), width: 30, }, @@ -200,7 +199,7 @@ export default function Chat() { 'bulk-editor': true, active: selectedRowKeys.length, }); - + return (
Chat Messages @@ -236,14 +235,14 @@ export default function Chat() { !record.visible ? 'hidden' : ''} + rowClassName={record => (!record.visible ? 'hidden' : '')} dataSource={messages} columns={chatColumns} - rowKey={(row) => row.id} + rowKey={row => row.id} rowSelection={rowSelection} /> - ) + + ); } - diff --git a/web/pages/config-page-content.tsx b/web/pages/config-page-content.tsx index 4bd1b4fd8..672308d84 100644 --- a/web/pages/config-page-content.tsx +++ b/web/pages/config-page-content.tsx @@ -8,7 +8,7 @@ import { postConfigUpdateToAPI, RESET_TIMEOUT, API_CUSTOM_CONTENT, -} from './components/config/constants'; +} from '../utils/config-constants'; import { createInputStatus, StatusState, @@ -17,7 +17,7 @@ import { STATUS_SUCCESS, } from '../utils/input-statuses'; import 'react-markdown-editor-lite/lib/index.css'; -import FormStatusIndicator from './components/config/form-status-indicator'; +import FormStatusIndicator from '../components/config/form-status-indicator'; const { Title } = Typography; @@ -87,7 +87,8 @@ export default function PageContentEditor() { Page Content

- Edit the content of your page by using simple Markdown syntax. + Edit the content of your page by using simple{' '} + Markdown syntax.

- +
{hasChanged ? ( ) : null} -
); diff --git a/web/pages/config-public-details.tsx b/web/pages/config-public-details.tsx index bfc5352ff..821e68026 100644 --- a/web/pages/config-public-details.tsx +++ b/web/pages/config-public-details.tsx @@ -2,9 +2,9 @@ import React from 'react'; import { Typography } from 'antd'; import Link from 'next/link'; -import EditInstanceDetails from './components/config/edit-instance-details'; -import EditDirectoryDetails from './components/config/edit-directory'; -import EditInstanceTags from './components/config/edit-tags'; +import EditInstanceDetails from '../components/config/edit-instance-details'; +import EditDirectoryDetails from '../components/config/edit-directory'; +import EditInstanceTags from '../components/config/edit-tags'; const { Title } = Typography; @@ -13,7 +13,8 @@ export default function PublicFacingDetails() { <> General Settings

- The following are displayed on your site to describe your stream and its content. Learn more. + The following are displayed on your site to describe your stream and its content.{' '} + Learn more.

diff --git a/web/pages/config-server-details.tsx b/web/pages/config-server-details.tsx index 3d04afff7..40ee36149 100644 --- a/web/pages/config-server-details.tsx +++ b/web/pages/config-server-details.tsx @@ -1,6 +1,6 @@ import React from 'react'; import { Typography } from 'antd'; -import EditServerDetails from './components/config/edit-server-details'; +import EditServerDetails from '../components/config/edit-server-details'; const { Title } = Typography; @@ -9,7 +9,8 @@ export default function ConfigServerDetails() {
Server Settings

- You should change your stream key from the default and keep it safe. For most people it's likely the other settings will not need to be changed. + You should change your stream key from the default and keep it safe. For most people it's + likely the other settings will not need to be changed.

diff --git a/web/pages/config-social-items.tsx b/web/pages/config-social-items.tsx index fafe0c169..c7ae8f9c8 100644 --- a/web/pages/config-social-items.tsx +++ b/web/pages/config-social-items.tsx @@ -1,6 +1,6 @@ import React from 'react'; import { Typography } from 'antd'; -import EditSocialLinks from './components/config/edit-social-links'; +import EditSocialLinks from '../components/config/edit-social-links'; const { Title } = Typography; diff --git a/web/pages/config-storage.tsx b/web/pages/config-storage.tsx index 1b8e636fa..7df326eec 100644 --- a/web/pages/config-storage.tsx +++ b/web/pages/config-storage.tsx @@ -1,6 +1,6 @@ import { Typography } from 'antd'; import React from 'react'; -import EditStorage from './components/config/edit-storage'; +import EditStorage from '../components/config/edit-storage'; const { Title } = Typography; @@ -9,10 +9,14 @@ export default function ConfigStorageInfo() { <> Storage

- Owncast supports optionally using external storage providers to distribute your video. Learn more about this by visiting our Storage Documentation. + Owncast supports optionally using external storage providers to distribute your video. Learn + more about this by visiting our{' '} + Storage Documentation.

- Configuring this incorrectly will likely cause your video to be unplayable. Double check the documentation for your storage provider on how to configure the bucket you created for Owncast. + Configuring this incorrectly will likely cause your video to be unplayable. Double check the + documentation for your storage provider on how to configure the bucket you created for + Owncast.

diff --git a/web/pages/config-video.tsx b/web/pages/config-video.tsx index a654e3e8d..92a99adb8 100644 --- a/web/pages/config-video.tsx +++ b/web/pages/config-video.tsx @@ -1,8 +1,8 @@ import React from 'react'; import { Typography } from 'antd'; -import VideoVariantsTable from './components/config/video-variants-table'; -import VideoLatency from './components/config/video-latency'; +import VideoVariantsTable from '../components/config/video-variants-table'; +import VideoLatency from '../components/config/video-latency'; const { Title } = Typography; @@ -11,18 +11,20 @@ export default function ConfigVideoSettings() {
Video configuration

- Before changing your video configuration visit the video documentation{' '} - to learn how it impacts your stream performance. + Before changing your video configuration{' '} + visit the video documentation to learn + how it impacts your stream performance.

-

- -

-


-

- -

- +

+ +

+
+
+
+

+ +

); } diff --git a/web/pages/hardware-info.tsx b/web/pages/hardware-info.tsx index 2cd3f84f1..e8d446342 100644 --- a/web/pages/hardware-info.tsx +++ b/web/pages/hardware-info.tsx @@ -1,13 +1,13 @@ -import { BulbOutlined, LaptopOutlined, SaveOutlined } from "@ant-design/icons"; -import { Row } from "antd"; +import { BulbOutlined, LaptopOutlined, SaveOutlined } from '@ant-design/icons'; +import { Row } from 'antd'; import React, { useEffect, useState } from 'react'; import { fetchData, FETCH_INTERVAL, HARDWARE_STATS } from '../utils/apis'; -import Chart from './components/chart'; -import StatisticItem from "./components/statistic"; +import Chart from '../components/chart'; +import StatisticItem from '../components/statistic'; interface TimedValue { - time: Date, - value: Number + time: Date; + value: Number; } export default function HardwareInfo() { @@ -15,92 +15,88 @@ export default function HardwareInfo() { cpu: Array(), memory: Array(), disk: Array(), - message: "", + message: '', }); const getHardwareStatus = async () => { try { const result = await fetchData(HARDWARE_STATS); setHardwareStatus({ ...result }); - } catch (error) { setHardwareStatus({ ...hardwareStatus, message: error.message }); } }; - + useEffect(() => { let getStatusIntervalId = null; getHardwareStatus(); getStatusIntervalId = setInterval(getHardwareStatus, FETCH_INTERVAL); // runs every 1 min. - - // returned function will be called on component unmount + + // returned function will be called on component unmount return () => { clearInterval(getStatusIntervalId); - } + }; }, []); - if (!hardwareStatus.cpu) { return null; } const currentCPUUsage = hardwareStatus.cpu[hardwareStatus.cpu.length - 1]?.value; - const currentRamUsage = - hardwareStatus.memory[hardwareStatus.memory.length - 1]?.value; - const currentDiskUsage = - hardwareStatus.disk[hardwareStatus.disk.length - 1]?.value; - -const series = [ - { - name: "CPU", - color: "#B63FFF", - data: hardwareStatus.cpu, - }, - { - name: "Memory", - color: "#2087E2", - data: hardwareStatus.memory, - }, - { - name: "Disk", - color: "#FF7700", - data: hardwareStatus.disk, - }, -]; - - return ( -
-
- - } - color={series[0].color} - progress - centered - /> - } - color={series[1].color} - progress - centered - /> - } - color={series[2].color} - progress - centered - /> - + const currentRamUsage = hardwareStatus.memory[hardwareStatus.memory.length - 1]?.value; + const currentDiskUsage = hardwareStatus.disk[hardwareStatus.disk.length - 1]?.value; - -
+ const series = [ + { + name: 'CPU', + color: '#B63FFF', + data: hardwareStatus.cpu, + }, + { + name: 'Memory', + color: '#2087E2', + data: hardwareStatus.memory, + }, + { + name: 'Disk', + color: '#FF7700', + data: hardwareStatus.disk, + }, + ]; + + return ( +
+
+ + } + color={series[0].color} + progress + centered + /> + } + color={series[1].color} + progress + centered + /> + } + color={series[2].color} + progress + centered + /> + + +
- ); -} \ No newline at end of file +
+ ); +} diff --git a/web/pages/index.tsx b/web/pages/index.tsx index 2060acd31..0eeda64d3 100644 --- a/web/pages/index.tsx +++ b/web/pages/index.tsx @@ -7,29 +7,29 @@ Will display an overview with the following datasources: TODO: Link each overview value to the sub-page that focuses on it. */ -import React, { useState, useEffect, useContext } from "react"; -import { Skeleton, Card, Statistic } from "antd"; -import { UserOutlined, ClockCircleOutlined } from "@ant-design/icons"; -import { formatDistanceToNow, formatRelative } from "date-fns"; -import { ServerStatusContext } from "../utils/server-status-context"; -import StatisticItem from "./components/statistic" -import LogTable from "./components/log-table"; +import React, { useState, useEffect, useContext } from 'react'; +import { Skeleton, Card, Statistic } from 'antd'; +import { UserOutlined, ClockCircleOutlined } from '@ant-design/icons'; +import { formatDistanceToNow, formatRelative } from 'date-fns'; +import { ServerStatusContext } from '../utils/server-status-context'; +import StatisticItem from '../components/statistic'; +import LogTable from '../components/log-table'; import Offline from './offline-notice'; -import { - LOGS_WARN, - fetchData, - FETCH_INTERVAL, -} from "../utils/apis"; -import { formatIPAddress, isEmptyObject } from "../utils/format"; -import { UpdateArgs } from "../types/config-section"; +import { LOGS_WARN, fetchData, FETCH_INTERVAL } from '../utils/apis'; +import { formatIPAddress, isEmptyObject } from '../utils/format'; +import { UpdateArgs } from '../types/config-section'; function streamDetailsFormatter(streamDetails) { return (
    -
  • {streamDetails.videoCodec || 'Unknown'} @ {streamDetails.videoBitrate || 'Unknown'} kbps
  • +
  • + {streamDetails.videoCodec || 'Unknown'} @ {streamDetails.videoBitrate || 'Unknown'} kbps +
  • {streamDetails.framerate || 'Unknown'} fps
  • -
  • {streamDetails.width} x {streamDetails.height}
  • +
  • + {streamDetails.width} x {streamDetails.height} +
); } @@ -39,7 +39,7 @@ export default function Home() { const { broadcaster, serverConfig: configData } = serverStatusData || {}; const { remoteAddr, streamDetails } = broadcaster || {}; - const encoder = streamDetails?.encoder || "Unknown encoder"; + const encoder = streamDetails?.encoder || 'Unknown encoder'; const [logsData, setLogs] = useState([]); const getLogs = async () => { @@ -47,22 +47,22 @@ export default function Home() { const result = await fetchData(LOGS_WARN); setLogs(result); } catch (error) { - console.log("==== error", error); + console.log('==== error', error); } }; const getMoreStats = () => { getLogs(); - } + }; useEffect(() => { getMoreStats(); let intervalId = null; intervalId = setInterval(getMoreStats, FETCH_INTERVAL); - + return () => { clearInterval(intervalId); - } + }; }, []); if (isEmptyObject(configData) || isEmptyObject(serverStatusData)) { @@ -80,40 +80,38 @@ export default function Home() { } // map out settings - const videoQualitySettings = serverStatusData?.currentBroadcast?.outputSettings?.map((setting, index) => { - const { audioPassthrough, videoPassthrough, audioBitrate, videoBitrate, framerate } = setting; + const videoQualitySettings = serverStatusData?.currentBroadcast?.outputSettings?.map( + (setting, index) => { + const { audioPassthrough, videoPassthrough, audioBitrate, videoBitrate, framerate } = setting; - const audioSetting = audioPassthrough - ? `${streamDetails.audioCodec || 'Unknown'}, ${streamDetails.audioBitrate} kbps` - : `${audioBitrate || 'Unknown'} kbps`; + const audioSetting = audioPassthrough + ? `${streamDetails.audioCodec || 'Unknown'}, ${streamDetails.audioBitrate} kbps` + : `${audioBitrate || 'Unknown'} kbps`; - const videoSetting = videoPassthrough - ? `${streamDetails.videoBitrate || 'Unknown'} kbps, ${streamDetails.framerate} fps ${streamDetails.width} x ${streamDetails.height}` - : `${videoBitrate || 'Unknown'} kbps, ${framerate} fps`; + const videoSetting = videoPassthrough + ? `${streamDetails.videoBitrate || 'Unknown'} kbps, ${streamDetails.framerate} fps ${ + streamDetails.width + } x ${streamDetails.height}` + : `${videoBitrate || 'Unknown'} kbps, ${framerate} fps`; - let settingTitle = 'Outbound Stream Details'; - settingTitle = (videoQualitySettings?.length > 1) ? - `${settingTitle} ${index + 1}` : settingTitle; - return ( - - - - - ); - }); + let settingTitle = 'Outbound Stream Details'; + settingTitle = + videoQualitySettings?.length > 1 ? `${settingTitle} ${index + 1}` : settingTitle; + return ( + + + + + ); + }, + ); // inbound const { viewerCount, sessionPeakViewerCount } = serverStatusData; - const streamAudioDetailString = `${streamDetails.audioCodec}, ${streamDetails.audioBitrate || 'Unknown'} kbps`; + const streamAudioDetailString = `${streamDetails.audioCodec}, ${ + streamDetails.audioBitrate || 'Unknown' + } kbps`; const broadcastDate = new Date(broadcaster.time); @@ -123,18 +121,11 @@ export default function Home() {
} /> - } - /> + } />
- -
- {videoQualitySettings} -
+
{videoQualitySettings}
diff --git a/web/pages/logs.tsx b/web/pages/logs.tsx index 94957d45a..ce15c6bee 100644 --- a/web/pages/logs.tsx +++ b/web/pages/logs.tsx @@ -1,10 +1,7 @@ -import React, { useState, useEffect } from "react"; -import LogTable from "./components/log-table"; +import React, { useState, useEffect } from 'react'; +import LogTable from '../components/log-table'; -import { - LOGS_ALL, - fetchData, -} from "../utils/apis"; +import { LOGS_ALL, fetchData } from '../utils/apis'; const FETCH_INTERVAL = 5 * 1000; // 5 sec @@ -16,7 +13,7 @@ export default function Logs() { const result = await fetchData(LOGS_ALL); setLogs(result); } catch (error) { - console.log("==== error", error); + console.log('==== error', error); } }; @@ -33,6 +30,5 @@ export default function Logs() { }; }, []); - return ; + return ; } - diff --git a/web/pages/offline-notice.tsx b/web/pages/offline-notice.tsx index 1a87c6b66..a5bb16ab8 100644 --- a/web/pages/offline-notice.tsx +++ b/web/pages/offline-notice.tsx @@ -6,8 +6,8 @@ import { BookTwoTone, PlaySquareTwoTone, } from '@ant-design/icons'; -import OwncastLogo from './components/logo'; -import LogTable from './components/log-table'; +import OwncastLogo from '../components/logo'; +import LogTable from '../components/log-table'; const { Meta } = Card; diff --git a/web/pages/viewer-info.tsx b/web/pages/viewer-info.tsx index 6790a956e..5a3ece0e5 100644 --- a/web/pages/viewer-info.tsx +++ b/web/pages/viewer-info.tsx @@ -3,8 +3,8 @@ import { Table, Row } from 'antd'; import { formatDistanceToNow } from 'date-fns'; import { UserOutlined } from '@ant-design/icons'; import { SortOrder } from 'antd/lib/table/interface'; -import Chart from './components/chart'; -import StatisticItem from './components/statistic'; +import Chart from '../components/chart'; +import StatisticItem from '../components/statistic'; import { ServerStatusContext } from '../utils/server-status-context'; diff --git a/web/utils/alert-message-context.tsx b/web/utils/alert-message-context.tsx index 3cf81fc71..114699017 100644 --- a/web/utils/alert-message-context.tsx +++ b/web/utils/alert-message-context.tsx @@ -3,9 +3,8 @@ import PropTypes from 'prop-types'; export const AlertMessageContext = React.createContext({ message: null, - setMessage: (text?: string) => { - return text; - }, + // eslint-disable-next-line @typescript-eslint/no-unused-vars + setMessage: (text?: string) => null, }); const AlertMessageProvider = ({ children }) => { diff --git a/web/pages/components/config/constants.tsx b/web/utils/config-constants.tsx similarity index 97% rename from web/pages/components/config/constants.tsx rename to web/utils/config-constants.tsx index a065b5977..88223e727 100644 --- a/web/pages/components/config/constants.tsx +++ b/web/utils/config-constants.tsx @@ -1,8 +1,8 @@ // DEFAULT VALUES import React from 'react'; import { CheckCircleFilled, ExclamationCircleFilled } from '@ant-design/icons'; -import { fetchData, SERVER_CONFIG_UPDATE_URL } from '../../../utils/apis'; -import { ApiPostArgs, VideoVariant, SocialHandle } from '../../../types/config-section'; +import { fetchData, SERVER_CONFIG_UPDATE_URL } from './apis'; +import { ApiPostArgs, VideoVariant, SocialHandle } from '../types/config-section'; export const TEXT_MAXLENGTH = 255; diff --git a/web/utils/input-statuses.tsx b/web/utils/input-statuses.tsx index 9dc62f626..11c077473 100644 --- a/web/utils/input-statuses.tsx +++ b/web/utils/input-statuses.tsx @@ -15,13 +15,16 @@ export const STATUS_WARNING = 'warning'; export type InputStatusTypes = 'error' | 'invalid' | 'proessing' | 'success' | 'warning'; -export type StatusState = { +export interface StatusState { type: InputStatusTypes; icon: any; // Element type of sorts? message: string; -}; +} +interface InputStates { + [key: string]: StatusState; +} -export const INPUT_STATES = { +export const INPUT_STATES: InputStates = { [STATUS_SUCCESS]: { type: STATUS_SUCCESS, icon: , diff --git a/web/utils/server-status-context.tsx b/web/utils/server-status-context.tsx index e60c2a481..689934525 100644 --- a/web/utils/server-status-context.tsx +++ b/web/utils/server-status-context.tsx @@ -5,7 +5,7 @@ import PropTypes from 'prop-types'; import { STATUS, fetchData, FETCH_INTERVAL, SERVER_CONFIG } from './apis'; import { ConfigDetails, UpdateArgs } from '../types/config-section'; -import { DEFAULT_VARIANT_STATE } from '../pages/components/config/constants'; +import { DEFAULT_VARIANT_STATE } from './config-constants'; export const initialServerConfigState: ConfigDetails = { streamKey: '', @@ -47,6 +47,7 @@ export const initialServerConfigState: ConfigDetails = { const initialServerStatusState = { broadcastActive: false, broadcaster: null, + currentBroadcast: null, online: false, viewerCount: 0, sessionMaxViewerCount: 0, @@ -60,9 +61,8 @@ export const ServerStatusContext = React.createContext({ ...initialServerStatusState, serverConfig: initialServerConfigState, - setFieldInConfigState: (args: UpdateArgs) => { - return args; - }, + // eslint-disable-next-line @typescript-eslint/no-unused-vars + setFieldInConfigState: (args: UpdateArgs) => null, }); const ServerStatusProvider = ({ children }) => {