edit tags section

This commit is contained in:
gingervitis
2021-01-01 18:23:23 -08:00
committed by Gabe Kangas
parent 624ab72eb3
commit c93aefa05d
4 changed files with 191 additions and 35 deletions

View File

@@ -1,4 +1,6 @@
// DEFAULT VALUES
import React from 'react';
import { CheckCircleFilled, ExclamationCircleFilled } from '@ant-design/icons';
export const DEFAULT_NAME = 'Owncast User';
export const DEFAULT_TITLE = 'Owncast Server';
@@ -6,8 +8,22 @@ export const DEFAULT_SUMMARY = '';
export const TEXT_MAXLENGTH = 255;
export const RESET_TIMEOUT = 3000;
export const SUCCESS_STATES = {
success: {
icon: <CheckCircleFilled style={{ color: 'green' }} />,
message: 'Success!',
},
error: {
icon: <ExclamationCircleFilled style={{ color: 'red' }} />,
message: 'An error occurred.',
},
};
// Creating this so that it'll be easier to change values in one place, rather than looking for places to change it in a sea of JSX.
// key is the input's `fieldName`
export const TEXTFIELD_DEFAULTS = {
@@ -95,5 +111,16 @@ export const TEXTFIELD_DEFAULTS = {
label: 'Server port',
tip: 'What port are you serving Owncast from? Default is :8080',
},
//
tags: {
apiPath: '/tags',
defaultValue: '',
maxLength: 24,
placeholder: 'Add a new tag',
configPath: 'instanceDetails',
label: '',
tip: '',
}
}

View File

@@ -22,7 +22,7 @@ import { FormItemProps } from 'antd/es/form';
import { InfoCircleOutlined } from '@ant-design/icons';
import { TEXTFIELD_DEFAULTS, TEXT_MAXLENGTH } from './defaults';
import { TEXTFIELD_DEFAULTS, TEXT_MAXLENGTH, RESET_TIMEOUT } from './constants';
import { TextFieldProps } from '../../../types/config-section';
import { fetchData, SERVER_CONFIG_UPDATE_URL } from '../../../utils/apis';
@@ -84,7 +84,7 @@ export default function TextField(props: TextFieldProps) {
setSubmitStatus('error');
setSubmitStatusMessage(`There was an error: ${result.message}`);
}
resetTimer = setTimeout(resetStates, 3000);
resetTimer = setTimeout(resetStates, RESET_TIMEOUT);
};
const handleChange = e => {
@@ -139,7 +139,7 @@ export default function TextField(props: TextFieldProps) {
<Form.Item
label={label}
name={fieldName}
// hasFeedback
hasFeedback
validateStatus={submitStatus}
help={submitStatusMessage}
>

View File

@@ -1,33 +1,105 @@
/* 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 React, { useContext, useState, useEffect } from 'react';
import { Typography, Tag, Input } from 'antd';
import { ServerStatusContext } from '../../../utils/server-status-context';
import { fetchData, SERVER_CONFIG_UPDATE_URL } from '../../../utils/apis';
import { TEXTFIELD_DEFAULTS, RESET_TIMEOUT, SUCCESS_STATES } from './constants';
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 [newTagInput, setNewTagInput] = useState('');
const [submitStatus, setSubmitStatus] = useState(null);
const [submitDetails, setSubmitDetails] = useState('');
const serverStatusData = useContext(ServerStatusContext);
const { serverConfig } = serverStatusData || {};
const { serverConfig, setConfigField } = serverStatusData || {};
const { instanceDetails } = serverConfig;
const { tags = [] } = instanceDetails;
console.log(tags)
const {
apiPath,
maxLength,
placeholder,
configPath,
} = TEXTFIELD_DEFAULTS.tags || {};
let resetTimer = null;
useEffect(() => {
return () => {
clearTimeout(resetTimer);
}
}, []);
const resetStates = () => {
setSubmitStatus(null);
setSubmitDetails('');
resetTimer = null;
clearTimeout(resetTimer);
}
// posts all the tags at once as an array obj
const postUpdateToAPI = async (postValue: any) => {
// const result = await fetchData(`${SERVER_CONFIG_UPDATE_URL}${apiPath}`, {
// data: { value: postValue },
// method: 'POST',
// auth: true,
// });
const result = {
success: true,
message: 'success yay'
}
if (result.success) {
setConfigField({ fieldName: 'tags', value: postValue, path: configPath });
setSubmitStatus('success');
setSubmitDetails('Tags updated.');
setNewTagInput('');
} else {
setSubmitStatus('error');
setSubmitDetails(result.message);
}
resetTimer = setTimeout(resetStates, RESET_TIMEOUT);
};
const handleInputChange = e => {
if (submitDetails !== '') {
setSubmitDetails('');
}
setNewTagInput(e.target.value);
};
// send to api and do stuff
const handleSubmitNewTag = () => {
resetStates();
const newTag = newTagInput.trim();
if (newTag === '') {
setSubmitDetails('Please enter a tag');
return;
}
if (tags.some(tag => tag.toLowerCase() === newTag.toLowerCase())) {
setSubmitDetails('This tag is already used!');
return;
}
const updatedTags = [...tags, newTag];
postUpdateToAPI(updatedTags);
};
const handleDeleteTag = index => {
resetStates();
const updatedTags = [...tags];
updatedTags.splice(index, 1);
postUpdateToAPI(updatedTags);
}
const {
icon: newStatusIcon = null,
message: newStatusMessage = '',
} = SUCCESS_STATES[submitStatus] || {};
return (
<div className="tag-editor-container">
@@ -35,9 +107,31 @@ export default function EditInstanceTags() {
<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}`} />)}
{tags.map((tag, index) => {
const handleClose = () => {
handleDeleteTag(index);
};
return (
<Tag closable onClose={handleClose} key={`tag-${tag}-${index}`}>{tag}</Tag>
);
})}
</div>
<div className={`add-new-status ${submitStatus || ''}`}>
{newStatusIcon} {newStatusMessage} {submitDetails}
</div>
<div className="add-new-tag-section">
<Input
type="text"
className="new-tag-input"
value={newTagInput}
onChange={handleInputChange}
onPressEnter={handleSubmitNewTag}
maxLength={maxLength}
placeholder={placeholder}
allowClear
/>
</div>
</div>
);
}