11 changed files with 175 additions and 175 deletions
@ -0,0 +1,43 @@ |
|||||||
|
/* eslint-disable react/no-array-index-key */ |
||||||
|
import React, { useContext, useEffect } from 'react'; |
||||||
|
import { Typography, Button, Tooltip } from 'antd'; |
||||||
|
import { CloseCircleOutlined } from '@ant-design/icons'; |
||||||
|
import { ServerStatusContext } from '../../../utils/server-status-context'; |
||||||
|
|
||||||
|
const { Title } = Typography; |
||||||
|
|
||||||
|
function Tag({ label }) { |
||||||
|
return ( |
||||||
|
<Button className="tag" type="text" shape="round"> |
||||||
|
{label} |
||||||
|
<Tooltip title="Delete this tag."> |
||||||
|
<Button type="link" size="small" className="tag-delete"> |
||||||
|
<CloseCircleOutlined /> |
||||||
|
</Button> |
||||||
|
</Tooltip> |
||||||
|
|
||||||
|
</Button> |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
export default function EditInstanceTags() { |
||||||
|
const serverStatusData = useContext(ServerStatusContext); |
||||||
|
const { serverConfig } = serverStatusData || {}; |
||||||
|
|
||||||
|
const { instanceDetails } = serverConfig; |
||||||
|
const { tags = [] } = instanceDetails; |
||||||
|
console.log(tags) |
||||||
|
|
||||||
|
return ( |
||||||
|
<div className="tag-editor-container"> |
||||||
|
|
||||||
|
<Title level={3}>Add Tags</Title> |
||||||
|
<p>This is a great way to categorize your Owncast server on the Directory!</p> |
||||||
|
|
||||||
|
<div className="tag-current-tags"> |
||||||
|
{tags.map((tag, index) => <Tag label={tag} key={`tag-${tag}-${index}`} />)} |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
@ -0,0 +1,55 @@ |
|||||||
|
import React, { useContext, useEffect } from 'react'; |
||||||
|
import { Typography, Form } from 'antd'; |
||||||
|
|
||||||
|
import TextField, { TEXTFIELD_TYPE_NUMBER, TEXTFIELD_TYPE_PASSWORD, TEXTFIELD_TYPE_TEXTAREA } from './components/config/form-textfield'; |
||||||
|
|
||||||
|
import { ServerStatusContext } from '../utils/server-status-context'; |
||||||
|
|
||||||
|
const { Title } = Typography; |
||||||
|
|
||||||
|
export default function ConfigServerDetails() { |
||||||
|
const [form] = Form.useForm(); |
||||||
|
|
||||||
|
const serverStatusData = useContext(ServerStatusContext); |
||||||
|
const { serverConfig } = serverStatusData || {}; |
||||||
|
|
||||||
|
const { ffmpegPath, streamKey, webServerPort } = serverConfig; |
||||||
|
|
||||||
|
const streamDetails = { |
||||||
|
ffmpegPath, streamKey, webServerPort |
||||||
|
}; |
||||||
|
|
||||||
|
useEffect(() => { |
||||||
|
form.setFieldsValue({...streamDetails}); |
||||||
|
}, [serverStatusData]); |
||||||
|
|
||||||
|
|
||||||
|
const handleResetValue = (fieldName: string) => { |
||||||
|
form.setFieldsValue({ [fieldName]: streamDetails[fieldName]}); |
||||||
|
} |
||||||
|
|
||||||
|
const extraProps = { |
||||||
|
handleResetValue, |
||||||
|
initialValues: streamDetails, |
||||||
|
}; |
||||||
|
|
||||||
|
console.log(streamDetails) |
||||||
|
return ( |
||||||
|
<> |
||||||
|
<Title level={2}>Edit your Server's details</Title> |
||||||
|
|
||||||
|
<div className="config-public-details-container"> |
||||||
|
<Form |
||||||
|
form={form} |
||||||
|
layout="vertical" |
||||||
|
> |
||||||
|
<TextField fieldName="streamKey" type={TEXTFIELD_TYPE_PASSWORD} {...extraProps} /> |
||||||
|
<TextField fieldName="ffmpegPath" type={TEXTFIELD_TYPE_TEXTAREA} {...extraProps} /> |
||||||
|
<TextField fieldName="webServerPort" type={TEXTFIELD_TYPE_NUMBER} {...extraProps} /> |
||||||
|
</Form> |
||||||
|
</div> |
||||||
|
</> |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
@ -1,147 +0,0 @@ |
|||||||
import React, { useContext } from 'react'; |
|
||||||
import { Table, Typography, Input } from 'antd'; |
|
||||||
import { isEmptyObject } from '../utils/format'; |
|
||||||
import KeyValueTable from "./components/key-value-table"; |
|
||||||
import { ServerStatusContext } from '../utils/server-status-context'; |
|
||||||
|
|
||||||
import PublicFacingDetails from './components/config/public-facing-details'; |
|
||||||
|
|
||||||
import adminStyles from '../styles/styles.module.scss'; |
|
||||||
|
|
||||||
const { Title } = Typography; |
|
||||||
const { TextArea } = Input; |
|
||||||
|
|
||||||
|
|
||||||
function SocialHandles({ config }) { |
|
||||||
if (!config) { |
|
||||||
return null; |
|
||||||
} |
|
||||||
|
|
||||||
const columns = [ |
|
||||||
{ |
|
||||||
title: "Platform", |
|
||||||
dataIndex: "platform", |
|
||||||
key: "platform", |
|
||||||
}, |
|
||||||
{ |
|
||||||
title: "URL", |
|
||||||
dataIndex: "url", |
|
||||||
key: "url", |
|
||||||
render: (url) => <a href={url}>{url}</a> |
|
||||||
}, |
|
||||||
]; |
|
||||||
|
|
||||||
if (!config.instanceDetails?.socialHandles) { |
|
||||||
return null; |
|
||||||
} |
|
||||||
|
|
||||||
return ( |
|
||||||
<div className={adminStyles.configSection}> |
|
||||||
<Title level={2}>Social Handles</Title> |
|
||||||
<Table |
|
||||||
pagination={false} |
|
||||||
columns={columns} |
|
||||||
dataSource={config.instanceDetails.socialHandles} |
|
||||||
rowKey="platform" |
|
||||||
/> |
|
||||||
</div> |
|
||||||
); |
|
||||||
} |
|
||||||
|
|
||||||
function InstanceDetails({ config }) { |
|
||||||
if (!config || isEmptyObject(config)) { |
|
||||||
return null; |
|
||||||
} |
|
||||||
|
|
||||||
const { instanceDetails = {}, yp, streamKey, ffmpegPath, webServerPort } = config; |
|
||||||
|
|
||||||
const data = [ |
|
||||||
{ |
|
||||||
name: "Server name", |
|
||||||
value: instanceDetails.name, |
|
||||||
}, |
|
||||||
{ |
|
||||||
name: "Title", |
|
||||||
value: instanceDetails.title, |
|
||||||
}, |
|
||||||
{ |
|
||||||
name: "Summary", |
|
||||||
value: instanceDetails.summary, |
|
||||||
}, |
|
||||||
{ |
|
||||||
name: "Logo", |
|
||||||
value: instanceDetails.logo, |
|
||||||
}, |
|
||||||
{ |
|
||||||
name: "Tags", |
|
||||||
value: instanceDetails.tags?.join(", "), |
|
||||||
}, |
|
||||||
{ |
|
||||||
name: "NSFW", |
|
||||||
value: instanceDetails.nsfw?.toString(), |
|
||||||
}, |
|
||||||
{ |
|
||||||
name: "Shows in Owncast directory", |
|
||||||
value: yp.enabled.toString(), |
|
||||||
}, |
|
||||||
]; |
|
||||||
|
|
||||||
const configData = [ |
|
||||||
{ |
|
||||||
name: "Stream key", |
|
||||||
value: streamKey, |
|
||||||
}, |
|
||||||
{ |
|
||||||
name: "ffmpeg path", |
|
||||||
value: ffmpegPath, |
|
||||||
}, |
|
||||||
{ |
|
||||||
name: "Web server port", |
|
||||||
value: webServerPort, |
|
||||||
}, |
|
||||||
]; |
|
||||||
|
|
||||||
return ( |
|
||||||
<> |
|
||||||
<div className={adminStyles.configSection}> |
|
||||||
<KeyValueTable title="Server details" data={data} /> |
|
||||||
</div> |
|
||||||
<div className={adminStyles.configSection}> |
|
||||||
<KeyValueTable title="Server configuration" data={configData} /> |
|
||||||
</div> |
|
||||||
</> |
|
||||||
); |
|
||||||
} |
|
||||||
|
|
||||||
function PageContent({ config }) { |
|
||||||
if (!config?.instanceDetails?.extraPageContent) { |
|
||||||
return null; |
|
||||||
} |
|
||||||
return ( |
|
||||||
<div className={adminStyles.configSection}> |
|
||||||
<Title level={2}>Page content</Title> |
|
||||||
<TextArea |
|
||||||
disabled rows={4} |
|
||||||
value={config.instanceDetails.extraPageContent} |
|
||||||
/> |
|
||||||
</div> |
|
||||||
); |
|
||||||
} |
|
||||||
|
|
||||||
export default function ServerConfig() { |
|
||||||
const serverStatusData = useContext(ServerStatusContext); |
|
||||||
const { serverConfig: config } = serverStatusData || {}; |
|
||||||
|
|
||||||
return ( |
|
||||||
<> |
|
||||||
<PublicFacingDetails /> |
|
||||||
|
|
||||||
<InstanceDetails config={config} /> |
|
||||||
<SocialHandles config={config} /> |
|
||||||
<PageContent config={config} /> |
|
||||||
|
|
||||||
<Title level={5}>Learn more about configuring Owncast <a href="https://owncast.online/docs/configuration">by visiting the documentation.</a></Title> |
|
||||||
</> |
|
||||||
); |
|
||||||
} |
|
||||||
|
|
||||||
Loading…
Reference in new issue