252 lines
9.8 KiB
Cheetah
252 lines
9.8 KiB
Cheetah
{{define "content"}}
|
|
<div class="content">
|
|
<div class="container-fluid">
|
|
<div class="row">
|
|
<div class="col-md-12">
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h4 class="card-title">Reaction Panels</h4>
|
|
</div>
|
|
<div class="card-body">
|
|
<p class="white">Your panel quota: <b><span id="panel-count"></span> / <span id="panel-quota"></span></b></p>
|
|
<p class="white" id="premium-ad">Note: You can create unlimited panels with premium</p>
|
|
|
|
<table class="table table-hover table-striped">
|
|
<thead>
|
|
<tr>
|
|
<th>Channel</th>
|
|
<th>Panel Title</th>
|
|
<th>Panel Content</th>
|
|
<th>Ticket Channel Category</th>
|
|
<th>Delete</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody id="panel-container">
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h4 class="card-title">Create A Panel</h4>
|
|
</div>
|
|
<div class="card-body">
|
|
<form onsubmit="createPanel(); return false;">
|
|
<div class="row">
|
|
<div class="col-md-4 pr-1">
|
|
<div class="form-group">
|
|
<label class="black">Panel Title</label>
|
|
<input name="title" type="text" class="form-control" placeholder="Open a ticket!" id="title">
|
|
</div>
|
|
</div>
|
|
<div class="col-md-8 pr-1">
|
|
<div class="form-group">
|
|
<label class="black">Panel Content</label>
|
|
<textarea name="content" type="text" class="form-control"
|
|
placeholder="By reacting to this ticket, a ticket will be opened for you." id="content"></textarea>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="row">
|
|
<div class="col-md-3 pr-1">
|
|
<label class="black">Panel Colour</label>
|
|
<div class="input-group mb-3">
|
|
<input name="colour" type="color" class="form-control input-fill" value="#2ECC71" id="colour">
|
|
</div>
|
|
</div>
|
|
|
|
<div class="col-md-3 pr-1">
|
|
<label class="black">Panel Channel</label>
|
|
<div class="input-group mb-3">
|
|
<div class="input-group-prepend">
|
|
<div class="input-group-text">#</div>
|
|
</div>
|
|
<select class="form-control" name="channel" id="channel-container">
|
|
</select>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="col-md-3 pr-1">
|
|
<label class="black">Ticket Channel Category</label>
|
|
<div class="input-group mb-3">
|
|
<div class="input-group-prepend">
|
|
<div class="input-group-text">#</div>
|
|
</div>
|
|
<select class="form-control" name="categories" id="category-container">
|
|
</select>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="col-md-3 pr-1">
|
|
<div class="form-group">
|
|
<label class="black">Reaction Emote</label>
|
|
<input name="reaction" type="text" class="form-control" placeholder="envelope_with_arrow" id="reaction">
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row">
|
|
<div class="col-md-2 pr-1 offset-md-5">
|
|
<div class="form-group">
|
|
<button type="submit" class="btn btn-primary btn-fill"><i class="fas fa-paper-plane"></i> Submit</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div aria-live="polite" aria-atomic="true" style="position: relative; min-height: 200px;">
|
|
<div style="position: absolute; right: 10px" id="toast-container">
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
async function getChannels() {
|
|
const res = await axios.get('/api/{{.guildId}}/channels');
|
|
return res.data;
|
|
}
|
|
|
|
function getChannelName(channels, channelId) {
|
|
const ch = channels.find(ch => ch.id === channelId);
|
|
if (ch === undefined) {
|
|
return "Unknown";
|
|
} else {
|
|
return ch.name;
|
|
}
|
|
}
|
|
|
|
async function deletePanel(messageId) {
|
|
const res = await axios.delete('/api/{{.guildId}}/panels/' + messageId);
|
|
|
|
if (res.status === 200 && res.data.success) {
|
|
showToast('Success', 'Panel deleted successfully');
|
|
|
|
const el = document.getElementById(messageId);
|
|
el.parentNode.removeChild(el);
|
|
} else {
|
|
showToast('Error', res.data.error);
|
|
}
|
|
}
|
|
|
|
async function createPanel() {
|
|
const data = {
|
|
title: document.getElementById('title').value,
|
|
content: document.getElementById('content').value,
|
|
emote: document.getElementById('reaction').value.replace(':', ''),
|
|
colour: parseInt(`0x${document.getElementById('colour').value.slice(1)}`),
|
|
channel_id: document.getElementById('channel-container').options[document.getElementById('channel-container').selectedIndex].value,
|
|
category_id: document.getElementById('category-container').options[document.getElementById('category-container').selectedIndex].value,
|
|
};
|
|
|
|
// fill defaults
|
|
if (data.title === '') {
|
|
data.title = 'Open a ticket!';
|
|
}
|
|
if (data.content === '') {
|
|
data.content = 'By reacting to this ticket, a ticket will be opened for you.';
|
|
}
|
|
if (data.emote === '') {
|
|
data.emote = 'envelope_with_arrow';
|
|
}
|
|
|
|
const res = await axios.put('/api/{{.guildId}}/panels', data);
|
|
if (res.status === 200 && res.data.success) {
|
|
appendPanel(data, await getChannels());
|
|
showToast('Success', 'Panel created successfully')
|
|
} else {
|
|
showToast('Error', res.data.error);
|
|
}
|
|
}
|
|
|
|
async function fillChannels(channels) {
|
|
const container = document.getElementById('channel-container');
|
|
|
|
channels.filter(ch => ch.type === 0).forEach(ch => {
|
|
const el = document.createElement('option');
|
|
el.value = ch.id;
|
|
el.appendChild(document.createTextNode(ch.name));
|
|
container.appendChild(el);
|
|
});
|
|
}
|
|
|
|
async function fillCategories(channels) {
|
|
const container = document.getElementById('category-container');
|
|
|
|
channels.filter(ch => ch.type === 4).forEach(ch => {
|
|
const el = document.createElement('option');
|
|
el.value = ch.id;
|
|
el.appendChild(document.createTextNode(ch.name));
|
|
container.appendChild(el);
|
|
});
|
|
}
|
|
|
|
// TODO: Update on append / delete
|
|
async function fillPanelQuota(panelCount) {
|
|
const res = await axios.get('/api/{{.guildId}}/premium');
|
|
|
|
const el = document.getElementById('panel-quota');
|
|
if (res.data.premium) {
|
|
el.appendChild(document.createTextNode('∞'));
|
|
} else {
|
|
el.appendChild(document.createTextNode('1'));
|
|
document.getElementById('premium-ad').style.display = 'block';
|
|
}
|
|
|
|
document.getElementById('panel-count').appendChild(document.createTextNode(panelCount));
|
|
}
|
|
|
|
function appendPanel(panel, channels) {
|
|
const container = document.getElementById('panel-container');
|
|
|
|
const tr = document.createElement('tr');
|
|
tr.id = panel.message_id; // TODO: When we call this after creating a panel, we don't know the message ID yet
|
|
|
|
appendTd(tr, `#${getChannelName(channels, panel.channel_id)}`);
|
|
appendTd(tr, panel.title);
|
|
appendTd(tr, panel.content);
|
|
appendTd(tr, getChannelName(channels, panel.category_id));
|
|
|
|
// build remove button
|
|
const deleteTd = document.createElement('td');
|
|
const deleteButton = document.createElement('button');
|
|
deleteButton.type = 'submit';
|
|
deleteButton.classList.add('btn', 'btn-primary', 'btn-fill', 'mx-auto');
|
|
deleteButton.appendChild(document.createTextNode('Delete'));
|
|
deleteButton.onclick = () => {deletePanel(panel.message_id)};
|
|
deleteTd.appendChild(deleteButton);
|
|
tr.appendChild(deleteTd);
|
|
|
|
container.appendChild(tr);
|
|
}
|
|
|
|
async function fillPanels(channels) {
|
|
const res = await axios.get('/api/{{.guildId}}/panels');
|
|
if (res.status !== 200) {
|
|
showToast("Error", res.data);
|
|
return 0;
|
|
}
|
|
|
|
for (const panel of res.data) {
|
|
appendPanel(panel, channels);
|
|
}
|
|
|
|
return res.data.length;
|
|
}
|
|
|
|
async function loadData() {
|
|
const channels = await getChannels();
|
|
|
|
const panelCount = await fillPanels(channels);
|
|
await fillPanelQuota(panelCount);
|
|
await fillChannels(channels);
|
|
await fillCategories(channels);
|
|
}
|
|
|
|
loadData();
|
|
</script>
|
|
</div>
|
|
{{end}} |