Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Form input field macros #15989

Draft
wants to merge 9 commits into
base: main
Choose a base branch
from

Conversation

AshtonWooster
Copy link
Contributor

@AshtonWooster AshtonWooster commented May 21, 2024

This is associated with the issue: #6393

Added macros for "input_field_label", "input_field_errors", and "input_field". These should make managing the codebase easier and reduces the verbosity of the html code.

I only made edits to a couple of the places where these could be used. Let me know if this looks alright, or if there is anything to add/ change to make it more accessible or readable. Once it's finished, I'll go through and update other places where these could be used.

Additionally, thanks to @kx-chen for getting the backbone of this done!

Copy link
Member

@miketheman miketheman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@AshtonWooster Thanks for kicking this off!

I wanted to verify the changes in the rendered HTML, so I created some snapshots for before/after comparisons.

  • Running main branch
  • Running this branch's changes

I used httpie and difftastic - but this should be easy enough to recreate in any HTTP requester (curl) and diff tool.

Commands like:

http http://localhost/account/register/ --out=register-before.html
# shut down services, switch branch, run `make serve`
http http://localhost/account/register/ --out=register-after.html

(same with /login/)

Running difft register-before.html register-after.html --display=inline produces this diff:

register-after.html --- 1/5 --- HTML
15
16        <title>Create an account · Warehouse</title>
17        <meta name="description" content="The Python Package Index (PyPI) is a repository of software for the Python programming language.">
18
19        <link rel="stylesheet" href="/static/css/warehouse-ltr.78716823.css">
20        <link rel="stylesheet" href="/static/css/fontawesome.697f100e.css">
   22     <link rel="stylesheet" href="/static/css/warehouse-ltr.e691b0dd.css">
   23     <link rel="stylesheet" href="/static/css/fontawesome.327443c3.css">
   24     <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Source+Sans+3:400,400italic,600,600italic,700,700italic%7CSource+Code+Pro:500">
   25     <noscript>
   26       <link rel="stylesheet" href="/static/css/noscript.be55ea0c.css">
   27     </noscript>

register-after.html --- 2/5 --- HTML
155        <div class="site-container">
156          <h1 class="page-title">Create an account on PyPI</h1>
157
158          <form method="POST" action="/account/register/" data-controller="password password-match password-strength-gauge password-breach">
159            <input name="csrf_token" type="hidden" value="ORlsYrGqldgOvAXqD9MeAG94Jzz-UG8UZV8DW_WYkzM">
165              <input aria-describedby="name-errors" autocapitalize="off" autocomplete="name" class="form-group__field" id="full_name" maxlength="100" name="full_name" placeholder="Your name" spellcheck="false" type="text" value="">
172    Email address            <span class="form-group__required">(required)</span>
174              <input aria-describedby="email-errors" autocomplete="email" class="form-group__field" id="email" maxlength="254" name="email" placeholder="Your email address" required="required" spellcheck="false" type="email" value="">
   162         <input name="csrf_token" type="hidden" value="Pimbov5uTKqNzG38kPhVpl5JQttcJeYWWPSm072PpUw">
   169   <input aria-describedby="name-errors" autocapitalize="off" autocomplete="name" class="form-group__field" data-action="" data-target="" id="full_name" maxlength="100" name="full_name" placeholder="Your name" required spellcheck="false" type="text" value="">
   178 Email  <span class="form-group__required">(required)</span>
   181   <input aria-describedby="email-errors" autocapitalize="off" autocomplete="email" class="form-group__field" data-action="" data-target="" id="email" maxlength="254" name="email" placeholder="Your email address" required spellcheck="false" type="email" value="">
   182   <div id="email-errors">
   183 </div>
   184
   185

register-after.html --- 3/5 --- HTML
184            <div class="form-group">
185              <label for="username" class="form-group__label">
186    Username            <span class="form-group__required">(required)</span>
187              </label>
188              <input aria-describedby="username-errors" autocapitalize="off" autocomplete="username" class="form-group__field" id="username" maxlength="50" name="username" placeholder="Select a username" required="required" spellcheck="false" type="text" value="">
   198   <input aria-describedby="username-errors" autocapitalize="off" autocomplete="username" class="form-group__field" data-action="" data-target="" id="username" maxlength="50" name="username" placeholder="Select a username" required spellcheck="false" type="text" value="">
   199   <div id="username-errors">
   200 </div>
   201
   202

register-after.html --- 4/5 --- HTML
220              <div class="form-group">
221                <label for="password_confirm" class="form-group__label">
222    Confirm password              <span class="form-group__required">(required)</span>
223                </label>
224                <input aria-describedby="password-confirm-errors" autocomplete="new-password" class="form-group__field" data-action="input-&gt;password-match#checkPasswordsMatch" data-password-match-target="passwordMatch" data-password-target="password" id="password_confirm" maxlength="4096" name="password_confirm" placeholder="Confirm password" required="required" spellcheck="false" type="password" value="">
225                <div id="password-confirm-errors">
   239   <input aria-describedby="confirm-password-errors" autocapitalize="off" autocomplete="new-password" class="form-group__field" data-action="input-&gt;password-match#checkPasswordsMatch" data-target="password.password password-match.passwordMatch" id="password_confirm" maxlength="4096" name="password_confirm" placeholder="Confirm password" required spellcheck="false" type="password" value="">
   240   <div id="confirm-password-errors">
   241 </div>
   242
   243
   244           </div>

register-after.html --- 5/5 --- HTML
517
518    <div id="pDebug">
519        <div  id="pDebugToolbarHandle">
520            <a title="Show Toolbar" id="pShowToolBarButton"
521               href="http://localhost/_debug_toolbar/323831343733373638343634353238" target="pDebugToolbar">&#171;</a>
   538            href="http://localhost/_debug_toolbar/323831343733363036353130343830" target="pDebugToolbar">&#171;</a>
   539     </div>
   540 </div>
   541 </body>
   542

Ignoring the diffs for the compiled css files and debug toolbar session, there's some diffs that look fine, and others that should be more closely evaluated.

  • required="required" to required is fine - the attribute doesn't require a value. However, it looks like the requirement was added to the full_name input - was that originally missing from the HTML template? I don't think it's required.
  • The base template sets autocapitalize="off" by default for all form_instance()` - should it set that for everyone, or should it be selectively applied?
  • data_action="", data_target="" are now added to some inputs that didn't have them previously. Is that dangerous? Worht looking into!
  • password-confirm-errors has become confirm-password-errors - unclear if that's computed or generate, but either way, it might not matter if it's consistent, unless it's being used by the javascript controller.
  • data-password-match-target="passwordMatch" data-password-target="password" changed to data-target="password.password password-match.passwordMatch" - I think the name of the data-*-target is meaningful - that's how Stimulus finds the right elements. Refs: https://stimulus.hotwired.dev/reference/targets

Hopefully this isn't too much to consider, and please let me know if anything isn't clear.

</ul>
{% endif %}
</div>
{{ input_field(name="username", user_friendly_name="Username", form_instance=form.username, placeholder="Your username", autocomplete="username") }}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's add some newlines to help readability here. For example:

Suggested change
{{ input_field(name="username", user_friendly_name="Username", form_instance=form.username, placeholder="Your username", autocomplete="username") }}
{{ input_field(
name="username",
user_friendly_name="Username",
form_instance=form.username,
placeholder="Your username",
autocomplete="username",
) }}

While this doesn't give us as compact a line count, it makes up for it in readability.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the detailed feedback, I'll go back and do some fixing!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Having trouble trying to figure out how to not pass "data_action" and "data_target" to "form_instance()" when they are not passed to the macro. Is there a simple way to not pass it if not set, or would I need to use an if statement in the macro?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have been busy recently, but will begin working on this again soon!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @AshtonWooster ! Any chance you've found some time to work on this again?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@miketheman I should have some time this weekend to work on it, I'll let you know what I get done.

Copy link
Contributor Author

@AshtonWooster AshtonWooster Aug 24, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@miketheman I was unsure how to regenerate the messages.pot file, or add the "data-*-target" and "data-*-action" for the macros. Are there any resources I can read through that explain how to do this? Thanks for the help!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Certainly! For the translations, the dev docs discuss briefly: https://warehouse.pypa.io/development/submitting-patches.html#translations

This often has to be done when rebasing a branch, since the main branch gets updated with other strings, so if a PR falls behind, it has to be done before merging.

For creating data-*-target style attributes conditionally, I'm wondering if constructing those conditionally as a dictionary and passing them to the field would "just work", something like:

set extra_attributes = {}
if foo:
    extra_attributes["data-foo-action"] = "something"
...

input_field(
    ...,
	**extra_attributes,
)

or something like that? I'm not totally certain if that works, but worth a try!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the help, I'll try to implement this when I get a chance.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants