mirror of
https://github.com/Hessenuk/DiscordTickets.git
synced 2024-12-22 15:53:08 +02:00
Make edit button work
This commit is contained in:
parent
44ee84d8f7
commit
34a4e071b5
@ -10,6 +10,7 @@ const env = {
|
||||
HTTP_BIND: 8080,
|
||||
HTTP_EXTERNAL: 'http://localhost:8080',
|
||||
PORTAL: '',
|
||||
PUBLIC: false,
|
||||
SUPER: '319467558166069248',
|
||||
};
|
||||
|
||||
|
@ -1,4 +1,13 @@
|
||||
const { Button } = require('@eartharoid/dbf');
|
||||
const {
|
||||
ActionRowBuilder,
|
||||
ModalBuilder,
|
||||
SelectMenuBuilder,
|
||||
SelectMenuOptionBuilder,
|
||||
TextInputBuilder,
|
||||
TextInputStyle,
|
||||
} = require('discord.js');
|
||||
const emoji = require('node-emoji');
|
||||
|
||||
module.exports = class EditButton extends Button {
|
||||
constructor(client, options) {
|
||||
@ -8,5 +17,93 @@ module.exports = class EditButton extends Button {
|
||||
});
|
||||
}
|
||||
|
||||
async run(id, interaction) { }
|
||||
async run(id, interaction) {
|
||||
/** @type {import("client")} */
|
||||
const client = this.client;
|
||||
|
||||
const ticket = await client.prisma.ticket.findUnique({
|
||||
select: {
|
||||
category: { select: { name: true } },
|
||||
guild: { select: { locale: true } },
|
||||
questionAnswers: { include: { question: true } },
|
||||
topic: true,
|
||||
},
|
||||
where: { id: interaction.channel.id },
|
||||
});
|
||||
|
||||
const getMessage = client.i18n.getLocale(ticket.guild.locale);
|
||||
|
||||
if (ticket.questionAnswers.length === 0) {
|
||||
await interaction.showModal(
|
||||
new ModalBuilder()
|
||||
.setCustomId(JSON.stringify({
|
||||
action: 'topic',
|
||||
edit: true,
|
||||
}))
|
||||
.setTitle(ticket.category.name)
|
||||
.setComponents(
|
||||
new ActionRowBuilder()
|
||||
.setComponents(
|
||||
new TextInputBuilder()
|
||||
.setCustomId('topic')
|
||||
.setLabel(getMessage('modals.topic.label'))
|
||||
.setStyle(TextInputStyle.Paragraph)
|
||||
.setMaxLength(1000)
|
||||
.setMinLength(5)
|
||||
.setPlaceholder(getMessage('modals.topic.placeholder'))
|
||||
.setRequired(true)
|
||||
.setValue(ticket.topic || ''),
|
||||
),
|
||||
),
|
||||
);
|
||||
} else {
|
||||
await interaction.showModal(
|
||||
new ModalBuilder()
|
||||
.setCustomId(JSON.stringify({
|
||||
action: 'questions',
|
||||
edit: true,
|
||||
}))
|
||||
.setTitle(ticket.category.name)
|
||||
.setComponents(
|
||||
ticket.questionAnswers
|
||||
.filter(a => a.question.type === 'TEXT') // TODO: remove this when modals support select menus
|
||||
.map(a => {
|
||||
if (a.question.type === 'TEXT') {
|
||||
return new ActionRowBuilder()
|
||||
.setComponents(
|
||||
new TextInputBuilder()
|
||||
.setCustomId(String(a.id))
|
||||
.setLabel(a.question.label)
|
||||
.setStyle(a.question.style)
|
||||
.setMaxLength(Math.min(a.question.maxLength, 1000))
|
||||
.setMinLength(a.question.minLength)
|
||||
.setPlaceholder(a.question.placeholder)
|
||||
.setRequired(a.question.required)
|
||||
.setValue(a.value || a.question.value),
|
||||
);
|
||||
} else if (a.question.type === 'MENU') {
|
||||
return new ActionRowBuilder()
|
||||
.setComponents(
|
||||
new SelectMenuBuilder()
|
||||
.setCustomId(a.question.id)
|
||||
.setPlaceholder(a.question.placeholder || a.question.label)
|
||||
.setMaxValues(a.question.maxLength)
|
||||
.setMinValues(a.question.minLength)
|
||||
.setOptions(
|
||||
a.question.options.map((o, i) => {
|
||||
const builder = new SelectMenuOptionBuilder()
|
||||
.setValue(String(i))
|
||||
.setLabel(o.label);
|
||||
if (o.description) builder.setDescription(o.description);
|
||||
if (o.emoji) builder.setEmoji(emoji.hasEmoji(o.emoji) ? emoji.get(o.emoji) : { id: o.emoji });
|
||||
return builder;
|
||||
}),
|
||||
),
|
||||
);
|
||||
}
|
||||
}),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
@ -169,6 +169,7 @@ log:
|
||||
claim: claimed
|
||||
close: closed
|
||||
unclaim: released
|
||||
update: updated
|
||||
menus:
|
||||
category:
|
||||
placeholder: Select a ticket category
|
||||
@ -224,6 +225,9 @@ ticket:
|
||||
title: ✅ Ticket created
|
||||
answers:
|
||||
no_value: '*No response*'
|
||||
edited:
|
||||
description: Your changes have been saved.
|
||||
title: ✅ Ticket updated
|
||||
opening_message:
|
||||
content: |
|
||||
{staff}
|
||||
|
@ -129,7 +129,7 @@ async function logAdminEvent(client, {
|
||||
* @param {string} details.action
|
||||
*/
|
||||
async function logTicketEvent(client, {
|
||||
userId, action, target,
|
||||
userId, action, target, diff,
|
||||
}) {
|
||||
const ticket = await client.prisma.ticket.findUnique({
|
||||
include: { guild: true },
|
||||
@ -143,9 +143,10 @@ async function logTicketEvent(client, {
|
||||
if (!ticket.guild.logChannel) return;
|
||||
const colour = action === 'create'
|
||||
? 'Aqua' : action === 'close'
|
||||
? 'DarkAqua' : action === 'claim'
|
||||
? 'LuminousVividPink' : action === 'unclaim'
|
||||
? 'DarkVividPink' : 'Default';
|
||||
? 'DarkAqua' : action === 'update'
|
||||
? 'Purple' : action === 'claim'
|
||||
? 'LuminousVividPink' : action === 'unclaim'
|
||||
? 'DarkVividPink' : 'Default';
|
||||
const getMessage = client.i18n.getLocale(ticket.guild.locale);
|
||||
const i18nOptions = {
|
||||
user: `<@${member.user.id}>`,
|
||||
@ -160,14 +161,8 @@ async function logTicketEvent(client, {
|
||||
iconURL: member.displayAvatarURL(),
|
||||
name: member.displayName,
|
||||
})
|
||||
.setTitle(getMessage('log.ticket.title', {
|
||||
...i18nOptions,
|
||||
verb: getMessage(`log.ticket.verb.${action}`),
|
||||
}))
|
||||
.setDescription(getMessage('log.ticket.description', {
|
||||
...i18nOptions,
|
||||
verb: getMessage(`log.ticket.verb.${action}`),
|
||||
}))
|
||||
.setTitle(getMessage('log.ticket.title', i18nOptions))
|
||||
.setDescription(getMessage('log.ticket.description', i18nOptions))
|
||||
.addFields([
|
||||
{
|
||||
name: getMessage('log.ticket.ticket'),
|
||||
@ -176,6 +171,15 @@ async function logTicketEvent(client, {
|
||||
]),
|
||||
];
|
||||
|
||||
if (diff && diff.original) {
|
||||
embeds.push(
|
||||
new EmbedBuilder()
|
||||
.setColor(colour)
|
||||
.setTitle(getMessage('log.admin.changes'))
|
||||
.setFields(makeDiff(diff)),
|
||||
);
|
||||
}
|
||||
|
||||
return await channel.send({ embeds });
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,7 @@
|
||||
const { Modal } = require('@eartharoid/dbf');
|
||||
const { EmbedBuilder } = require('discord.js');
|
||||
const ExtendedEmbedBuilder = require('../lib/embed');
|
||||
const { logTicketEvent } = require('../lib/logging');
|
||||
|
||||
module.exports = class QuestionsModal extends Modal {
|
||||
constructor(client, options) {
|
||||
@ -14,9 +17,103 @@ module.exports = class QuestionsModal extends Modal {
|
||||
* @param {import("discord.js").ModalSubmitInteraction} interaction
|
||||
*/
|
||||
async run(id, interaction) {
|
||||
await this.client.tickets.postQuestions({
|
||||
...id,
|
||||
interaction,
|
||||
});
|
||||
/** @type {import("client")} */
|
||||
const client = this.client;
|
||||
|
||||
if (id.edit) {
|
||||
await interaction.deferReply({ ephemeral: true });
|
||||
const { category } = await client.prisma.ticket.findUnique({
|
||||
select: { category: { select: { customTopic: true } } },
|
||||
where: { id: interaction.channel.id },
|
||||
});
|
||||
let topic;
|
||||
if (category.customTopic) topic = interaction.fields.getTextInputValue(category.customTopic);
|
||||
const select = {
|
||||
createdById: true,
|
||||
guild: {
|
||||
select: {
|
||||
footer: true,
|
||||
locale: true,
|
||||
successColour: true,
|
||||
},
|
||||
},
|
||||
id: true,
|
||||
openingMessageId: true,
|
||||
questionAnswers: { include: { question: true } },
|
||||
};
|
||||
const original = await client.prisma.ticket.findUnique({
|
||||
select,
|
||||
where: { id: interaction.channel.id },
|
||||
});
|
||||
const ticket = await client.prisma.ticket.update({
|
||||
data: {
|
||||
questionAnswers: {
|
||||
update: interaction.fields.fields.map(f => ({
|
||||
data: { value: f.value },
|
||||
where: { id: Number(f.customId) },
|
||||
})),
|
||||
},
|
||||
topic,
|
||||
},
|
||||
select,
|
||||
where: { id: interaction.channel.id },
|
||||
});
|
||||
const getMessage = client.i18n.getLocale(ticket.guild.locale);
|
||||
|
||||
if (topic) await interaction.channel.setTopic(`<@${ticket.createdById}> | ${topic}`);
|
||||
|
||||
const opening = await interaction.channel.messages.fetch(ticket.openingMessageId);
|
||||
if (opening && opening.embeds.length >= 2) {
|
||||
const embeds = [...opening.embeds];
|
||||
embeds[1] = new EmbedBuilder(embeds[1].data)
|
||||
.setFields(
|
||||
ticket.questionAnswers
|
||||
.map(a => ({
|
||||
name: a.question.label,
|
||||
value: a.value || getMessage('ticket.answers.no_value'),
|
||||
})),
|
||||
);
|
||||
await opening.edit({ embeds });
|
||||
}
|
||||
|
||||
await interaction.editReply({
|
||||
embeds: [
|
||||
new ExtendedEmbedBuilder({
|
||||
iconURL: interaction.guild.iconURL(),
|
||||
text: ticket.guild.footer,
|
||||
})
|
||||
.setColor(ticket.guild.successColour)
|
||||
.setTitle(getMessage('ticket.edited.title'))
|
||||
.setDescription(getMessage('ticket.edited.description')),
|
||||
],
|
||||
});
|
||||
|
||||
/** @param {ticket} ticket */
|
||||
const makeDiff = ticket => {
|
||||
const diff = {};
|
||||
ticket.questionAnswers.forEach(a => {
|
||||
diff[a.question.label] = a.value || getMessage('ticket.answers.no_value');
|
||||
});
|
||||
return diff;
|
||||
};
|
||||
|
||||
logTicketEvent(this.client, {
|
||||
action: 'update',
|
||||
diff: {
|
||||
original: makeDiff(original),
|
||||
updated: makeDiff(ticket),
|
||||
},
|
||||
target: {
|
||||
id: ticket.id,
|
||||
name: `<#${ticket.id}>`,
|
||||
},
|
||||
userId: interaction.user.id,
|
||||
});
|
||||
} else {
|
||||
await this.client.tickets.postQuestions({
|
||||
...id,
|
||||
interaction,
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
@ -1,4 +1,7 @@
|
||||
const { Modal } = require('@eartharoid/dbf');
|
||||
const { EmbedBuilder } = require('discord.js');
|
||||
const ExtendedEmbedBuilder = require('../lib/embed');
|
||||
const { logTicketEvent } = require('../lib/logging');
|
||||
|
||||
module.exports = class TopicModal extends Modal {
|
||||
constructor(client, options) {
|
||||
@ -9,9 +12,84 @@ module.exports = class TopicModal extends Modal {
|
||||
}
|
||||
|
||||
async run(id, interaction) {
|
||||
await this.client.tickets.postQuestions({
|
||||
...id,
|
||||
interaction,
|
||||
});
|
||||
/** @type {import("client")} */
|
||||
const client = this.client;
|
||||
|
||||
if (id.edit) {
|
||||
await interaction.deferReply({ ephemeral: true });
|
||||
const topic = interaction.fields.getTextInputValue('topic');
|
||||
const select = {
|
||||
createdById: true,
|
||||
guild: {
|
||||
select: {
|
||||
footer: true,
|
||||
locale: true,
|
||||
successColour: true,
|
||||
},
|
||||
},
|
||||
id: true,
|
||||
openingMessageId: true,
|
||||
};
|
||||
const original = await client.prisma.ticket.findUnique({
|
||||
select,
|
||||
where: { id: interaction.channel.id },
|
||||
});
|
||||
const ticket = await client.prisma.ticket.update({
|
||||
data: { topic },
|
||||
select,
|
||||
where: { id: interaction.channel.id },
|
||||
});
|
||||
const getMessage = client.i18n.getLocale(ticket.guild.locale);
|
||||
|
||||
if (topic) await interaction.channel.setTopic(`<@${ticket.createdById}> | ${topic}`);
|
||||
|
||||
const opening = await interaction.channel.messages.fetch(ticket.openingMessageId);
|
||||
if (opening && opening.embeds.length >= 2) {
|
||||
const embeds = [...opening.embeds];
|
||||
embeds[1] = new EmbedBuilder(embeds[1].data)
|
||||
.setFields({
|
||||
name: getMessage('ticket.opening_message.fields.topic'),
|
||||
value: topic,
|
||||
});
|
||||
await opening.edit({ embeds });
|
||||
}
|
||||
|
||||
await interaction.editReply({
|
||||
embeds: [
|
||||
new ExtendedEmbedBuilder({
|
||||
iconURL: interaction.guild.iconURL(),
|
||||
text: ticket.guild.footer,
|
||||
})
|
||||
.setColor(ticket.guild.successColour)
|
||||
.setTitle(getMessage('ticket.edited.title'))
|
||||
.setDescription(getMessage('ticket.edited.description')),
|
||||
],
|
||||
});
|
||||
|
||||
/** @param {ticket} ticket */
|
||||
const makeDiff = ticket => {
|
||||
const diff = {};
|
||||
diff[getMessage('ticket.opening_message.fields.topic')] = ticket.topic;
|
||||
return diff;
|
||||
};
|
||||
|
||||
logTicketEvent(this.client, {
|
||||
action: 'update',
|
||||
diff: {
|
||||
original: makeDiff(original),
|
||||
updated: makeDiff(ticket),
|
||||
},
|
||||
target: {
|
||||
id: ticket.id,
|
||||
name: `<#${ticket.id}>`,
|
||||
},
|
||||
userId: interaction.user.id,
|
||||
});
|
||||
} else {
|
||||
await this.client.tickets.postQuestions({
|
||||
...id,
|
||||
interaction,
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
@ -21,9 +21,10 @@ module.exports.get = () => ({
|
||||
discriminator: client.user.discriminator,
|
||||
id: client.user.id,
|
||||
portal: process.env.PORTAL || null,
|
||||
public: !!process.env.PUBLIC,
|
||||
stats: {
|
||||
activatedUsers: users.length,
|
||||
archivedMessages: users.reduce((total, user) => total + user.messageCount, 0), // don't count archivedMessage table rows, they get deleted
|
||||
archivedMessages: users.reduce((total, user) => total + user.messageCount, 0), // don't count archivedMessage table rows, they can be deleted
|
||||
avgResolutionTime: ms(closedTickets.reduce((total, ticket) => total + (ticket.closedAt - ticket.createdAt), 0) ?? 1 / closedTickets.length),
|
||||
avgResponseTime: ms(closedTickets.reduce((total, ticket) => total + (ticket.firstResponseAt - ticket.createdAt), 0) ?? 1 / closedTickets.length),
|
||||
categories: await client.prisma.category.count(),
|
||||
|
Loading…
Reference in New Issue
Block a user