Skip to content

Commit

Permalink
Adds the Add Project modal for improved UX
Browse files Browse the repository at this point in the history
  • Loading branch information
NovaFox161 committed Sep 12, 2024
1 parent 4161243 commit 9051b1f
Show file tree
Hide file tree
Showing 5 changed files with 105 additions and 43 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,32 @@ class ComponentService(
return arrayOf(ActionRow.of(titleInput), ActionRow.of(descriptionInput))
}

suspend fun getAddProjectModalComponents(settings: GuildSettings): Array<LayoutComponent> {
val nameInput = TextInput.small(
"add-project.name",
localeService.getString(settings.locale, "modal.add-project.name.label"),
1,
100
).placeholder(localeService.getString(settings.locale, "modal.add-project.name.placeholder"))
.required()
val prefixInput = TextInput.small(
"add-project.prefix",
localeService.getString(settings.locale, "modal.add-project.prefix.label"),
1,
16
).placeholder(localeService.getString(settings.locale, "modal.add-project.prefix.placeholder"))
.required()
val infoInput = TextInput.paragraph(
"add-project.info",
localeService.getString(settings.locale, "modal.add-project.info.label"),
0,
4000
).placeholder(localeService.getString(settings.locale, "modal.add-project.info.placeholder").textInputPlaceholderSafe())
.required(false)

return arrayOf(ActionRow.of(nameInput), ActionRow.of(prefixInput), ActionRow.of(infoInput))
}

suspend fun getEditProjectModalComponents(settings: GuildSettings, project: Project): Array<LayoutComponent> {
val infoInput = TextInput.paragraph(
"edit-project.info",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ class ProjectCommand(

override suspend fun shouldDefer(event: ChatInputInteractionEvent): Boolean {
return when (event.options[0].name) {
"edit-info" -> false
"add", "edit-info" -> false
else -> super.shouldDefer(event)
}
}
Expand Down Expand Up @@ -61,36 +61,20 @@ class ProjectCommand(
}

private suspend fun add(event: ChatInputInteractionEvent, settings: GuildSettings) {
val name = event.options[0].getOption("name")
.flatMap(ApplicationCommandInteractionOption::getValue)
.map(ApplicationCommandInteractionOptionValue::asString)
.map { it.substring(0, 100.coerceAtMost(it.length)) }
.get()
val prefix = event.options[0].getOption("prefix")
.flatMap(ApplicationCommandInteractionOption::getValue)
.map(ApplicationCommandInteractionOptionValue::asString)
.map { it.replace(Regex("\\W"), "") } // Keep only alphanumeric chars
.map { it.substring(0, 16.coerceAtMost(it.length)) }
.get()

// Check if max amount of projects has been created
if (projectService.getAllProjects(settings.guildId).size >= 25) {
event.createFollowup(localeService.getString(settings.locale, "command.project.add.limit-reached"))
event.reply(localeService.getString(settings.locale, "command.project.add.limit-reached"))
.withEmbeds(embedService.getProjectListEmbed(settings))
.withEphemeral(ephemeral)
.map(Message::getId)
.flatMap { event.deleteFollowupDelayed(it, messageDeleteSeconds) }
.awaitSingleOrNull()
return
}

projectService.createProject(Project(guildId = settings.guildId, name = name, prefix = prefix))

event.createFollowup(localeService.getString(settings.locale, "command.project.add.success"))
.withEmbeds(embedService.getProjectListEmbed(settings))
.withEphemeral(ephemeral)
.map(Message::getId)
.flatMap { event.deleteFollowupDelayed(it, messageDeleteSeconds) }
// pop modal
event.presentModal()
.withCustomId("add-project-modal")
.withTitle(localeService.getString(settings.locale, "modal.add-project.title"))
.withComponents(*componentService.getAddProjectModalComponents(settings))
.awaitSingleOrNull()
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package org.dreamexposure.ticketbird.interaction

import discord4j.core.event.domain.interaction.ModalSubmitInteractionEvent
import discord4j.core.`object`.component.TextInput
import discord4j.core.`object`.entity.Message
import kotlinx.coroutines.reactor.awaitSingleOrNull
import org.dreamexposure.ticketbird.business.EmbedService
import org.dreamexposure.ticketbird.business.LocaleService
import org.dreamexposure.ticketbird.business.ProjectService
import org.dreamexposure.ticketbird.config.Config
import org.dreamexposure.ticketbird.extensions.asSeconds
import org.dreamexposure.ticketbird.extensions.discord4j.deleteFollowupDelayed
import org.dreamexposure.ticketbird.`object`.GuildSettings
import org.dreamexposure.ticketbird.`object`.Project
import org.springframework.stereotype.Component
import kotlin.jvm.optionals.getOrNull

@Component
class AddProjectModal(
private val projectService: ProjectService,
private val localeService: LocaleService,
private val embedService: EmbedService,
): InteractionHandler<ModalSubmitInteractionEvent> {
override val ids = arrayOf("add-project-modal")
override val ephemeral = true

private val messageDeleteSeconds = Config.TIMING_MESSAGE_DELETE_GENERIC_SECONDS.getLong().asSeconds()

override suspend fun handle(event: ModalSubmitInteractionEvent, settings: GuildSettings) {
val inputs = event.getComponents(TextInput::class.java)

val name = inputs.first { it.customId == "add-project.name" }.value.get()
val prefix = inputs.first { it.customId == "add-project.prefix" }.value.get()
val info = inputs.first { it.customId == "add-project.info" }.value.getOrNull()

// Double check if max amount of projects have been created
if (projectService.getAllProjects(settings.guildId).size >= 25) {
event.createFollowup(localeService.getString(settings.locale, "command.project.add.limit-reached"))
.withEmbeds(embedService.getProjectListEmbed(settings))
.withEphemeral(ephemeral)
.map(Message::getId)
.flatMap { event.deleteFollowupDelayed(it, messageDeleteSeconds) }
.awaitSingleOrNull()
return
}

val project = projectService.createProject(Project(
guildId = settings.guildId,
name = name,
prefix = prefix,
additionalInfo = info
))

event.createFollowup(localeService.getString(settings.locale, "command.project.add.success"))
.withEmbeds(embedService.getProjectViewEmbed(settings, project))
.withEphemeral(ephemeral)
.map(Message::getId)
.flatMap { event.deleteFollowupDelayed(it, messageDeleteSeconds) }
.awaitSingleOrNull()
}
}
20 changes: 1 addition & 19 deletions src/main/resources/commands/global/project.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,25 +7,7 @@
{
"type": 1,
"name": "add",
"description": "Adds a new project that users can select when opening tickets. Up to 25",
"options": [
{
"type": 3,
"name": "name",
"description": "The name of the new project.",
"required": true,
"max_length": 100,
"min_length": 1
},
{
"type": 3,
"name": "prefix",
"description": "A prefix to help identify tickets for this project. 16 characters max, alphanumeric allowed",
"required": true,
"max_length": 16,
"min_length": 1
}
]
"description": "Adds a new project that users can select when opening tickets. Up to 25 can be created"
},
{
"type": 1,
Expand Down
11 changes: 10 additions & 1 deletion src/main/resources/locale/values.properties
Original file line number Diff line number Diff line change
Expand Up @@ -161,9 +161,18 @@ modal.edit-support-message.description.label=Description
modal.edit-support-message.description.placeholder=Need help with something? \n\n Open a new ticket by clicking the button below or using the \
`/support` command.

modal.add-project.title=Add Project
modal.add-project.name.label=Name
modal.add-project.name.placeholder=The name of the project, what users will see when opening a ticket
modal.add-project.prefix.label=Prefix
modal.add-project.prefix.placeholder=Prefix added to a ticket channel's name to help identify it
modal.add-project.info.label=Additional Info
modal.add-project.info.placeholder=Any additional info you want to provide to users when a ticket has been opened


modal.edit-project.title=Edit Project
modal.edit-project.info.label=Additional Info
modal.edit-project.info.placeholder=Any additional info you want to provide to users when a ticket has been opened.
modal.edit-project.info.placeholder=Any additional info you want to provide to users when a ticket has been opened

# Auto complete
auto-complete.setup.actions.auto-close=Auto Close Ticket (Current: {0})
Expand Down

0 comments on commit 9051b1f

Please sign in to comment.