Is your feature request related to a problem? Please describe.
I'm currently using NAFF for a company contract that involves needing to survey user data at a large scale and give us administrative control over what text inputs are used. We do this by checking a database for given text inputs and select menus, and sending it on an interaction create event.
Doing this, however, brings pros and cons:
The good
We can easily control which text inputs are sent and how. 👍🏼
Using a database lets us build commands to write to it in order to change text inputs instead of hardcoding the logic. 👍🏼
The bad
The modals are limited to a database which can be inefficient for storage of a modal. 👎🏼
It's arguably easier if we have a way to flexibly control how a modal is built in the code instead of relying on formatting of database fields. 👎🏼
Describe the solution you'd like
The modal class in NAFF strictly follows the API object schema for its resource. Instead of directly modifying the contents of the Python object, I'd like if there was a way we could pre-emptively build a modal without being too specific. This is where I pitch my idea: a modal builder.
Take the following example of what you currently do in NAFF:
This works good if you're not needing to change anything, and/or you're keeping the modal's design hardcoded inside the source code. However, doing modal.components[0] and etc. is an inefficient; and non-ergonomic manner to changing the modal's contents. We now have to remember which indices of the modal's components we want to change, or iterate through it. Yucky and not nice!
Instead, if we used something like dataclasses, we could establish a key-value pair of the attribute to the object. Take the following proposal where we use typing.TypedDict to our advantage for required and non-required values.
from naff import * # forgive me polls
import typing
# We can either adopt the name of the modal through the class or as a positional argument of the decorator.
@naff.modal_builder(name="Modal title")
class MyNewModal(typing.TypedDict):
# In the class, modal text inputs and their respective object are type annotated instead.
# We still adopt the kwargs approach to writing contents.
short_text_input: typing.Required[ShortText(label="Short input text")]
# Instead of declaring a text input component's optionality in the object, we can refer from
# the optional value in the class.
long_text: typing.NotRequired[ParagraphText(label="Paragraph text input")] = None # equals expression is unnecessary
# The same may apply for select menus within where we want to automatically represent an
# default choice.
# We technically make it "required" since it's not an undefined value, but it'll still default to that select option.
selection: typing.Required[Select] = SelectOption(label="foo", value="bar")
With a key-value pair set with the attribute name and the type, we could also establish an object return from the decorator's application onto the class. In this case we'll just call it ModalBuild. This object essentially acts as a manager of the newly built modal and will now allow us to modify it in whatever situation. This theoretically lets us do this:
global new_modal
new_modal = typing.Mapping[MyNewModal, ModalBuild]
# We can now directly affect the contents of it easily without needing to iterate through
# components and checking the custom ID, and offers more versatility.
new_modal.short_text_input.required = False
# Subsequently we could do this. Not nice, but if we were working with a database, it'd be simpler.
new_modal.long_text = ParagraphText(label="Paragraph text input")
Describe alternatives you've considered
We've originally considered just writing our own modal builder class that used special magic methods for changing attribute data based off of the database and apply them during runtime, but we found this didn't work nicely for what we wanted.
Additional Information
With this solution, it should still be possible to send a ModalBuild the same as a regular Modal object from NAFF in an interaction response.
Is your feature request related to a problem? Please describe.
I'm currently using NAFF for a company contract that involves needing to survey user data at a large scale and give us administrative control over what text inputs are used. We do this by checking a database for given text inputs and select menus, and sending it on an interaction create event.
Doing this, however, brings pros and cons:
The good
The bad
Describe the solution you'd like
The modal class in NAFF strictly follows the API object schema for its resource. Instead of directly modifying the contents of the Python object, I'd like if there was a way we could pre-emptively build a modal without being too specific. This is where I pitch my idea: a modal builder.
Take the following example of what you currently do in NAFF:
This works good if you're not needing to change anything, and/or you're keeping the modal's design hardcoded inside the source code. However, doing
modal.components[0]
and etc. is an inefficient; and non-ergonomic manner to changing the modal's contents. We now have to remember which indices of the modal's components we want to change, or iterate through it. Yucky and not nice!Instead, if we used something like dataclasses, we could establish a key-value pair of the attribute to the object. Take the following proposal where we use
typing.TypedDict
to our advantage for required and non-required values.With a key-value pair set with the attribute name and the type, we could also establish an object return from the decorator's application onto the class. In this case we'll just call it
ModalBuild
. This object essentially acts as a manager of the newly built modal and will now allow us to modify it in whatever situation. This theoretically lets us do this:Describe alternatives you've considered
We've originally considered just writing our own modal builder class that used special magic methods for changing attribute data based off of the database and apply them during runtime, but we found this didn't work nicely for what we wanted.
Additional Information
With this solution, it should still be possible to send a
ModalBuild
the same as a regularModal
object from NAFF in an interaction response.