fixes for various admin issues (#181)

* up max char count for variant name to fix https://github.com/owncast/owncast/issues/1037

* max widthing the line chart canvas size so it scales with the page.
fixes
- https://github.com/owncast/owncast/issues/842
- https://github.com/owncast/owncast/issues/1024

* A fix to make Storage Endpoint URL validation have better feedback.

- give the field a type of "url"
- give the field a pattern to check
- have native browser handle the validation
- if the field is invalid, use :invalid selector to turn the text red on blur.

fixes: https://github.com/owncast/owncast/issues/1000

* a fix for https://github.com/owncast/owncast/issues/874

* - fixes for https://github.com/owncast/owncast/issues/972
Add optional prop to text field to trim() whitespaces from field. Apply logic to mostly url fields.

- move textfield blur if invalid turn red to globaal

* - a fix for bug:  https://github.com/owncast/owncast/issues/998
don't return null if platform name not found because its custom.

- clean up react key problem on socialhandles table

* fix react key issue on Actions table

* fix for https://github.com/owncast/owncast/issues/1008 to display 'other' field when editing an item not in predefined social list

* clean up other potential react key warnings

* Prettified Code!

Co-authored-by: gingervitis <gingervitis@users.noreply.github.com>
This commit is contained in:
gingervitis
2021-05-22 23:27:51 -07:00
committed by GitHub
parent 8d7f11b4ef
commit d0eb1446f3
15 changed files with 132 additions and 43 deletions

View File

@@ -4,7 +4,7 @@ import React, { useState, useEffect, useContext } from 'react';
import { Table, Space, Button, Modal, Checkbox, Input, Typography } from 'antd';
import { ServerStatusContext } from '../utils/server-status-context';
import { DeleteOutlined } from '@ant-design/icons';
import isValidUrl from '../utils/urls';
import isValidUrl, { DEFAULT_TEXTFIELD_URL_PATTERN } from '../utils/urls';
import FormStatusIndicator from '../components/config/form-status-indicator';
import {
createInputStatus,
@@ -41,12 +41,12 @@ function NewActionModal(props: Props) {
function save() {
onOk(actionUrl, actionTitle, actionDescription, actionIcon, actionColor, openExternally);
setActionUrl('')
setActionTitle('')
setActionDescription('')
setActionIcon('')
setActionColor('')
setOpenExternally(false)
setActionUrl('');
setActionTitle('');
setActionDescription('');
setActionIcon('');
setActionColor('');
setOpenExternally(false);
}
function canSave(): Boolean {
@@ -91,7 +91,9 @@ function NewActionModal(props: Props) {
value={actionUrl}
required
placeholder="https://myserver.com/action (required)"
onChange={input => setActionUrl(input.currentTarget.value)}
onChange={input => setActionUrl(input.currentTarget.value.trim())}
type="url"
pattern={DEFAULT_TEXTFIELD_URL_PATTERN}
/>
</p>
<p>
@@ -184,7 +186,7 @@ export default function Actions() {
dataIndex: 'icon',
key: 'icon',
render: (url: string) => {
return url ? <img style={{width: '2vw'}} src={url} /> : null;
return url ? <img style={{ width: '2vw' }} src={url} /> : null;
},
},
{
@@ -289,11 +291,22 @@ export default function Actions() {
</Paragraph>
<Paragraph>
Read more about how to use actions, with examples, at{' '}
<a href="https://owncast.online/thirdparty/?source=admin" target="_blank"
rel="noopener noreferrer">our documentation</a>.
<a
href="https://owncast.online/thirdparty/?source=admin"
target="_blank"
rel="noopener noreferrer"
>
our documentation
</a>
.
</Paragraph>
<Table rowKey="id" columns={columns} dataSource={actions} pagination={false} />
<Table
rowKey={record => `${record.title}-${record.url}`}
columns={columns}
dataSource={actions}
pagination={false}
/>
<br />
<Button type="primary" onClick={showCreateModal}>
Create New Action

View File

@@ -37,7 +37,7 @@ export default function ConfigVideoSettings() {
<VideoLatency />
</div>
<Collapse className="advanced-settings">
<Collapse className="advanced-settings codec-module">
<Panel header="Advanced Settings" key="1">
<div className="form-module variants-table-module">
<VideoCodecSelector />

View File

@@ -75,7 +75,7 @@ export default function HardwareInfo() {
<Col>
<StatisticItem
title={series[0].name}
value={`${currentCPUUsage}`}
value={`${currentCPUUsage || 0}`}
prefix={<LaptopOutlined style={{ color: series[0].color }} />}
color={series[0].color}
progress
@@ -85,7 +85,7 @@ export default function HardwareInfo() {
<Col>
<StatisticItem
title={series[1].name}
value={`${currentRamUsage}`}
value={`${currentRamUsage || 0}`}
prefix={<BulbOutlined style={{ color: series[1].color }} />}
color={series[1].color}
progress
@@ -95,7 +95,7 @@ export default function HardwareInfo() {
<Col>
<StatisticItem
title={series[2].name}
value={`${currentDiskUsage}`}
value={`${currentDiskUsage || 0}`}
prefix={<SaveOutlined style={{ color: series[2].color }} />}
color={series[2].color}
progress

View File

@@ -205,8 +205,8 @@ export default function Help() {
<Title level={2}>Common tasks</Title>
<Row gutter={[16, 16]}>
{questions.map(question => (
<Col xs={24} lg={12}>
<Card key={question.title}>
<Col xs={24} lg={12} key={question.title}>
<Card>
<Meta avatar={question.icon} title={question.title} description={question.content} />
</Card>
</Col>
@@ -216,8 +216,8 @@ export default function Help() {
<Title level={2}>Other</Title>
<Row gutter={[16, 16]}>
{otherResources.map(question => (
<Col xs={24} lg={12}>
<Card key={question.title}>
<Col xs={24} lg={12} key={question.title}>
<Card>
<Meta avatar={question.icon} title={question.title} description={question.content} />
</Card>
</Col>

View File

@@ -23,7 +23,15 @@ function AssetTable(assets) {
},
];
return <Table dataSource={data} columns={columns} rowKey="id" size="large" pagination={false} />;
return (
<Table
dataSource={data}
columns={columns}
rowKey={record => record.id}
size="large"
pagination={false}
/>
);
}
export default function Logs() {

View File

@@ -13,7 +13,7 @@ import {
Col,
} from 'antd';
import { DeleteOutlined } from '@ant-design/icons';
import isValidUrl from '../utils/urls';
import isValidUrl, { DEFAULT_TEXTFIELD_URL_PATTERN } from '../utils/urls';
import { fetchData, DELETE_WEBHOOK, CREATE_WEBHOOK, WEBHOOKS } from '../utils/apis';
@@ -86,7 +86,11 @@ function NewWebhookModal(props: Props) {
};
const checkboxes = events.map(function (singleEvent) {
return (<Col span={8} key={singleEvent.value}><Checkbox value={singleEvent.value}>{singleEvent.label}</Checkbox></Col>)
return (
<Col span={8} key={singleEvent.value}>
<Checkbox value={singleEvent.value}>{singleEvent.label}</Checkbox>
</Col>
);
});
return (
@@ -101,15 +105,15 @@ function NewWebhookModal(props: Props) {
<Input
value={webhookUrl}
placeholder="https://myserver.com/webhook"
onChange={input => setWebhookUrl(input.currentTarget.value)}
onChange={input => setWebhookUrl(input.currentTarget.value.trim())}
type="url"
pattern={DEFAULT_TEXTFIELD_URL_PATTERN}
/>
</div>
<p>Select the events that will be sent to this webhook.</p>
<Checkbox.Group style={{ width: '100%' }} value={selectedEvents} onChange={onChange}>
<Row>
{checkboxes}
</Row>
<Row>{checkboxes}</Row>
</Checkbox.Group>
<p>
<Button type="primary" onClick={selectAll}>
@@ -225,7 +229,12 @@ export default function Webhooks() {
.
</Paragraph>
<Table rowKey="id" columns={columns} dataSource={webhooks} pagination={false} />
<Table
rowKey={record => record.id}
columns={columns}
dataSource={webhooks}
pagination={false}
/>
<br />
<Button type="primary" onClick={showCreateModal}>
Create Webhook