dyno-bot/Dyno-web-premium-before-reset/react/dashboard/autoresponder/ResponseModal.jsx
2020-09-12 19:08:48 +01:00

350 lines
10 KiB
JavaScript

import React from 'react';
import axios from 'axios';
import '!style-loader!css-loader!emoji-mart/css/emoji-mart.css';
import { Picker } from 'emoji-mart';
import Emoji from 'emoji-mart/dist/components/emoji/emoji.js';
import RichCheckbox from '../common/RichCheckbox.jsx';
import RichMultiSelect from '../common/RichMultiSelect.jsx';
import RichSelect from '../common/RichSelect.jsx';
import Variables from '../common/Variables.jsx';
import Help from '../common/Help.jsx';
export default class ResponseModal extends React.Component {
state = {
channels: [],
formData: this.defaultFormData,
isPickerOpen: false,
contentChars: 0,
contentLimit: false,
nameChars: 0,
nameLimit: false,
}
get defaultFormData() {
return {
command: '',
response: '',
type: 'message',
allowedChannels: [],
ignoredChannels: [],
reactions: [],
wildcard: false,
};
}
async componentWillMount() {
this.setState({
channels: this.props.channels || [],
emojis: this.props.emojis || [],
formData: this.props.command ? this.props.command : this.defaultFormData,
});
}
async componentWillReceiveProps(props) {
this.setState({
channels: props.channels || [],
emojis: props.emojis || [],
formData: props.command ? props.command : this.defaultFormData,
});
}
setFormData(key, val) {
const formData = this.state.formData;
formData[key] = val;
return this.setState({
formData,
contentChars: formData.response.length,
nameChars: formData.command.length
});
}
handleInput(type, event) {
if (type == 'response') {
var input = event.target.value;
this.setState({
contentChars: input.length
});
if (input.length >= 2000) {
this.setState({
contentLimit: true
});
}
else {
this.setState({
contentLimit: false
})
}
}
this.setFormData(type, event.target.value);
}
handleCommandName = (event) => {
let value = event.target.value;
if (value.length > 72) {
return;
}
this.setState({
nameChars: value.length
});
if (value.length >= 72) {
this.setState({
nameChars: 72,
nameLimit: true
});
}
else {
this.setState({
nameLimit: false
})
}
this.setFormData('command', event.target.value);
}
handleMultiSelect(type, props, selectedOptions) {
this.setFormData(type, selectedOptions.map(o => ({ id: o.value, name: o.label })));
}
handleCheckbox(type, identifier, isEnabled) {
this.setFormData(type, isEnabled);
}
addReaction = (emoji) => {
if (emoji.custom) {
const customEmoji = this.state.emojis.find(e => e.name === emoji.name);
emoji._id = customEmoji.id;
}
const { formData } = this.state;
formData.reactions = formData.reactions || [];
formData.reactions.push(emoji);
this.setState({ formData, isPickerOpen: false });
}
deleteReaction(reaction) {
const { formData } = this.state;
const index = formData.reactions.findIndex(r => r.id === reaction.id);
formData.reactions.splice(index, 1);
this.setState({ formData });
}
addHandler = () => {
const command = this.state.formData;
const url = `/api/server/${this.props.match.params.id}/autoresponder/create`;
const data = { command };
// Max length
if (command.command.length > 72) return _showError('Command name cannot be over 72 characters.');
if (command.response.length > 2000) return _showError('Respones cannot be over 2,000 characters.');
const test = command.response.replace(/ *\{[^)]*\} */g, '');
if (test.length > 2000) return _showError('Response cannot be over 2,000 characters.');
axios.post(url, data).then((res) => {
if (res.status === 200) {
_showSuccess(`Added Response ${command.command}`);
try {
this.props.onClose(command);
} catch (err) {
return;
}
} else {
_showError('An error occurred.');
}
}).catch((err) => {
_showError('Something went wrong.');
});
}
saveHandler = () => {
const command = this.state.formData;
const url = `/api/server/${this.props.match.params.id}/autoresponder/edit`;
const data = { command };
if (command.response.length > 2000) return _showError('Respones cannot be over 2,000 characters.');
const test = command.response.replace(/ *\{[^)]*\} */g, '');
if (test.length > 2000) return _showError('Response cannot be over 2,000 characters.');
axios.post(url, data).then((res) => {
if (res.status === 200) {
_showSuccess(`Updated Response ${command.command}`);
this.props.onClose(command);
} else {
_showError('An error occurred.');
}
}).catch((err) => {
if (err) {
_showError('Something went wrong.');
}
});
}
togglePicker = () => {
this.setState({ isPickerOpen: !this.state.isPickerOpen });
}
render() {
const { formData } = this.state;
const disableName = !!this.props.command;
let channels = this.state.channels.filter(c => (c.type === 0 || c.type === 4));
const channelOptions = channels.map(c => ({ value: c.id, label: c.name }));
let allowedChannels = this.state.formData.allowedChannels || [];
let ignoredChannels = this.state.formData.ignoredChannels || [];
allowedChannels = channels.filter(c => allowedChannels.find(i => i.id === c.id));
ignoredChannels = channels.filter(c => ignoredChannels.find(i => i.id === c.id));
const customs = this.state.emojis.map(emoji => {
return {
name: emoji.name,
short_names: [emoji.name],
imageUrl: `https://cdn.discordapp.com/emojis/${emoji.id}.${emoji.animated ? 'gif' : 'png'}?v=1`,
};
});
// const { reactions } = formData;
// reactions = reactions.map(r => {
// // r.imageUrl = `https://cdn.discordapp.com/emojis/${emoji.id}.${emoji.animated ? 'gif' : 'png'}?v=1`,
// })
const canAddReactions = !formData.reactions || formData.reactions.length < 3;
const categories = [
'search',
'recent',
'custom',
'people',
'nature',
'foods',
'activity',
'places',
'objects',
'symbols',
'flags',
];
const contentClass = this.state.contentLimit ? "over2k" : "";
const nameClass = this.state.nameLimit ? "over2k" : "";
return (<div className='settings-content'>
<div className='cc-add'>
<h3 className='title is-5'>{this.props.command ? 'Edit' : 'Add'} Response</h3>
<label className='label'>Command - <span className={nameClass}>{this.state.nameChars}</span> Character{this.state.nameChars == 1 ? '' : 's'}</label>
<p className='cc-name control'>
<input className='input' type='text' value={formData.command} disabled={disableName} onChange={this.handleCommandName} />
</p>
<p className='control'>
<input id='messageType' className='radio'
type='radio'
name='type'
value='message'
onChange={this.handleInput.bind(this, 'type')}
checked={formData.type === 'message'} />
<label htmlFor='messageType'>
Message Response
</label>
<Help text='Auto responds with a message.' />
<input id='reactionType' className='radio'
type='radio'
name='type'
value='reaction'
onChange={this.handleInput.bind(this, 'type')}
checked={formData.type === 'reaction'} />
<label htmlFor='reactionType'>
Reaction Response
</label>
<Help text='Auto responds by adding a reaction to the message. Note: Dyno requires the "Add Reactions" permission to be able to do this.' />
</p>
{formData.type === 'message' && (
<p className='control'>
<label className='label'>Response - <span className={contentClass}>{this.state.contentChars}</span> Character{this.state.contentChars == 1 ? '' : 's'}</label> {/*- */}
<textarea className='input cc-response' name="response" value={formData.response} onChange={this.handleInput.bind(this, 'response')}></textarea>
</p>
)}
{formData.type === 'reaction' && (
<div className='reaction-picker'>
{formData.reactions && formData.reactions.map(reaction => (
<div key={reaction.id} className='reaction'>
{reaction.custom ?
<span className='custom' style={{
background: `url(${reaction.imageUrl}) no-repeat center`,
backgroundSize: `20px`,
}}></span> :
<Emoji set='twitter' sheetSize={64} emoji={reaction.colons} />
}
<a className='icon delete-reaction' onClick={this.deleteReaction.bind(this, reaction)}>
<i className='fa fa-times'></i>
</a>
</div>
))}
{canAddReactions && (
<div className='reaction'>
<a className='is-info' onClick={this.togglePicker}>+</a>
</div>
)}
{this.state.isPickerOpen && (
<Picker
set='twitter'
title='Pick an emoji'
custom={customs}
include={categories}
showPreview={false}
// emojiTooltip={true}
onClick={this.addReaction} />
)}
</div>
)}
<RichMultiSelect
module={module}
setting='allowedChannels'
friendlyName='Allowed Channel'
label='Allowed Channels'
placeholder='Allowed Channels'
defaultValue={allowedChannels}
options={channelOptions}
helpText='Dyno will only respond in these channels.'
onChange={this.handleMultiSelect.bind(this, 'allowedChannels')} />
<RichMultiSelect
module={module}
setting='ignoredChannels'
friendlyName='Ignored Channel'
label='Ignored Channels'
placeholder='Ignored Channels'
defaultValue={ignoredChannels}
options={channelOptions}
helpText='Dyno will not respond in these channels.'
onChange={this.handleMultiSelect.bind(this, 'ignoredChannels')} />
<RichCheckbox
text='Wildcard'
onChange={this.handleCheckbox.bind(this, 'wildcard')}
helpText='Auto responder will search for the command anywhere in the message.'
defaultValue={formData.wildcard} />
<div className='control'>
<Variables />
</div>
{this.props.command ? (
<div className='cc-buttons'>
<span className='control'>
<a className='button edit-command is-info' onClick={this.saveHandler}>Save Response</a>
</span>
</div>
) : (
<div className='cc-buttons'>
<span className='control'>
<a className='button add-command is-info' onClick={this.addHandler}>Add Response</a>
</span>
</div>
)}
</div>
</div>);
}
}