mirror of
https://github.com/owncast/owncast.git
synced 2024-11-29 11:39:08 +03:00
Merge pull request #16 from nebunez/gw/20201226-admin-formfields
Add random streamkey generation and copy key
This commit is contained in:
commit
362c421d05
2 changed files with 58 additions and 10 deletions
|
@ -1,4 +1,7 @@
|
||||||
import React, { useState, useContext, useEffect } from 'react';
|
import React, { useState, useContext, useEffect } from 'react';
|
||||||
|
import { Button, Input, Tooltip } from 'antd';
|
||||||
|
import { CopyOutlined, RedoOutlined } from '@ant-design/icons';
|
||||||
|
|
||||||
import TextField, { TEXTFIELD_TYPE_NUMBER, TEXTFIELD_TYPE_PASSWORD } from './form-textfield';
|
import TextField, { TEXTFIELD_TYPE_NUMBER, TEXTFIELD_TYPE_PASSWORD } from './form-textfield';
|
||||||
|
|
||||||
import { ServerStatusContext } from '../../../utils/server-status-context';
|
import { ServerStatusContext } from '../../../utils/server-status-context';
|
||||||
|
@ -14,6 +17,10 @@ export default function EditInstanceDetails() {
|
||||||
|
|
||||||
const { streamKey, ffmpegPath, rtmpServerPort, webServerPort } = serverConfig;
|
const { streamKey, ffmpegPath, rtmpServerPort, webServerPort } = serverConfig;
|
||||||
|
|
||||||
|
const [copyIsVisible, setCopyVisible] = useState(false);
|
||||||
|
|
||||||
|
const COPY_TOOLTIP_TIMEOUT = 3000;
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setFormDataValues({
|
setFormDataValues({
|
||||||
streamKey, ffmpegPath, rtmpServerPort, webServerPort
|
streamKey, ffmpegPath, rtmpServerPort, webServerPort
|
||||||
|
@ -31,6 +38,23 @@ export default function EditInstanceDetails() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function generateStreamKey () {
|
||||||
|
let key = '';
|
||||||
|
for (let i = 0; i < 3; i+=1) {
|
||||||
|
key += Math.random().toString(36).substring(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
handleFieldChange({ fieldName: 'streamKey', value: key });
|
||||||
|
}
|
||||||
|
|
||||||
|
function copyStreamKey () {
|
||||||
|
navigator.clipboard.writeText(formDataValues.streamKey)
|
||||||
|
.then(() => {
|
||||||
|
setCopyVisible(true);
|
||||||
|
setTimeout(() => setCopyVisible(false), COPY_TOOLTIP_TIMEOUT);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={configStyles.publicDetailsContainer}>
|
<div className={configStyles.publicDetailsContainer}>
|
||||||
<div className={configStyles.textFieldsSection}>
|
<div className={configStyles.textFieldsSection}>
|
||||||
|
@ -42,6 +66,27 @@ export default function EditInstanceDetails() {
|
||||||
type={TEXTFIELD_TYPE_PASSWORD}
|
type={TEXTFIELD_TYPE_PASSWORD}
|
||||||
onChange={handleFieldChange}
|
onChange={handleFieldChange}
|
||||||
/>
|
/>
|
||||||
|
<div>
|
||||||
|
<span style={{fontSize: '0.75em', color: '#ff7777', marginRight: '0.5em'}}>
|
||||||
|
Save this key somewhere safe,
|
||||||
|
you will need it to stream or login to the admin dashboard!
|
||||||
|
</span>
|
||||||
|
<Tooltip className="copy-tooltip"
|
||||||
|
title="Copied!"
|
||||||
|
trigger=""
|
||||||
|
visible={copyIsVisible}>
|
||||||
|
<Button type="primary"
|
||||||
|
icon={<CopyOutlined />}
|
||||||
|
size="small"
|
||||||
|
onClick={copyStreamKey}
|
||||||
|
/>
|
||||||
|
</Tooltip>
|
||||||
|
<Button type="primary"
|
||||||
|
icon={<RedoOutlined />}
|
||||||
|
size="small"
|
||||||
|
onClick={generateStreamKey}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
<TextField
|
<TextField
|
||||||
fieldName="ffmpegPath"
|
fieldName="ffmpegPath"
|
||||||
{...TEXTFIELD_PROPS_FFMPEG}
|
{...TEXTFIELD_PROPS_FFMPEG}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import React, { useState, useContext } from 'react';
|
import React, { useEffect, useState, useContext } from 'react';
|
||||||
import { Button, Input, InputNumber } from 'antd';
|
import { Button, Input, InputNumber } from 'antd';
|
||||||
import { FormItemProps } from 'antd/es/form';
|
import { FormItemProps } from 'antd/es/form';
|
||||||
|
|
||||||
|
@ -38,7 +38,7 @@ export default function TextField(props: TextFieldProps) {
|
||||||
const [submitStatus, setSubmitStatus] = useState<FormItemProps['validateStatus']>('');
|
const [submitStatus, setSubmitStatus] = useState<FormItemProps['validateStatus']>('');
|
||||||
const [submitStatusMessage, setSubmitStatusMessage] = useState('');
|
const [submitStatusMessage, setSubmitStatusMessage] = useState('');
|
||||||
const [hasChanged, setHasChanged] = useState(false);
|
const [hasChanged, setHasChanged] = useState(false);
|
||||||
const [fieldValueForSubmit, setFieldValueForSubmit] = useState('');
|
const [fieldValueForSubmit, setFieldValueForSubmit] = useState<string | number>('');
|
||||||
|
|
||||||
const serverStatusData = useContext(ServerStatusContext);
|
const serverStatusData = useContext(ServerStatusContext);
|
||||||
const { setFieldInConfigState } = serverStatusData || {};
|
const { setFieldInConfigState } = serverStatusData || {};
|
||||||
|
@ -71,21 +71,24 @@ export default function TextField(props: TextFieldProps) {
|
||||||
resetTimer = null;
|
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.
|
useEffect(() => {
|
||||||
const handleChange = (e: any) => {
|
// TODO: Add native validity checks here, somehow
|
||||||
const val = type === TEXTFIELD_TYPE_NUMBER ? e : e.target.value;
|
|
||||||
|
|
||||||
// https://developer.mozilla.org/en-US/docs/Web/API/ValidityState
|
// https://developer.mozilla.org/en-US/docs/Web/API/ValidityState
|
||||||
const hasValidity = (type !== TEXTFIELD_TYPE_NUMBER && e.target.validity.valid) || type === TEXTFIELD_TYPE_NUMBER ;
|
// const hasValidity = (type !== TEXTFIELD_TYPE_NUMBER && e.target.validity.valid) || type === TEXTFIELD_TYPE_NUMBER ;
|
||||||
|
if ((required && (value === '' || value === null)) || value === initialValue) {
|
||||||
if ((required && (val === '' || val === null)) || val === initialValue || !hasValidity) {
|
|
||||||
setHasChanged(false);
|
setHasChanged(false);
|
||||||
} else {
|
} else {
|
||||||
// show submit button
|
// show submit button
|
||||||
resetStates();
|
resetStates();
|
||||||
setHasChanged(true);
|
setHasChanged(true);
|
||||||
setFieldValueForSubmit(val);
|
setFieldValueForSubmit(value);
|
||||||
}
|
}
|
||||||
|
}, [value]);
|
||||||
|
|
||||||
|
// 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) => {
|
||||||
|
const val = type === TEXTFIELD_TYPE_NUMBER ? e : e.target.value;
|
||||||
|
|
||||||
// if an extra onChange handler was sent in as a prop, let's run that too.
|
// if an extra onChange handler was sent in as a prop, let's run that too.
|
||||||
if (onChange) {
|
if (onChange) {
|
||||||
onChange({ fieldName, value: val });
|
onChange({ fieldName, value: val });
|
||||||
|
|
Loading…
Reference in a new issue