Universal Listings

This video features Sage Abdullah at Wagtail Space NL 2024 in Arnhem, Netherlands.

Universal Listings
0:25:20
Published June 27, 2024
128 views

Wagtail Space NL 2024 https://nl.wagtail.space

Summary

Sage Abdullah explains how Wagtail’s listing views evolved from simple, largely unchanged interfaces into a shared, more capable system for pages, snippets, reports, and other admin views. The work adds integrated search, custom filters, active-filter controls, Ajax updates, custom columns, exports, and a redesigned layout, while reusing generic views and Stimulus-based behavior. He argues that early integration, reusable code, and careful handling of interactions between front-end libraries are essential, and outlines plans to make breadcrumbs, header buttons, search, and filters configurable in Python without template overrides.

Key takeaways

  • Wagtail’s newer listing UI brings search and filtering into a consistent design across pages, snippets, and other admin views.
  • Generic index views and reusable Stimulus controllers let different listings share filtering and Ajax behavior without duplicating JavaScript.
  • Combining pop-ups, date pickers, tooltips, and partial updates creates difficult state, form, and positioning problems.
  • Integrating related pieces early helps reveal cross-component issues before the final stages of development.
  • Existing snippet configurations generally receive the new listing UI automatically, while custom page listings can use the page listing viewset.
  • Future work aims to let developers configure breadcrumbs, header buttons, search, and filters through Python rather than overriding templates.

Summarised automatically from the transcript.

Transcript

3,326 words · auto-generated Show

Automatically transcribed, so expect mistakes in names and technical terms.

0:07

Speaker 1: Welcome back to the last block of this event. Um the first presenter is already here. His name is Sage Abdullah. He's talking about he's talking to talk about customizable permissions.

0:20

Speaker 2: No, you depart all this things, but yeah I'll

0:22

Speaker 1: change of plans.

0:31

Speaker 2: Okay, um hello everyone. Thanks for being here. I'm so glad to be here as well, and thank you all for the um to the organizers for making this wonderful event happen. I'm Sage. I've been working on Whitetail itself for about two years now. And I've been a Wagtail core team member for the past a year and a half. Yeah, I originally wanted to talk about customizable permissions in Wagtail, but we had a change of plans uh in the details of the implementation, so I had to change my talk. Um but yeah I'm I'm happy to bring this talk. So yeah, I'm going to talk about universal listings and how we evolved White Tails listing views and beyond.

1:18

Speaker 2: So I'm going to start with a trip down memory lane. I'll start with uh going back to Wagtail 2. 0, even though uh so this was released and February 2018, before I even heard about Whitetail. It looked like this, which is vaguely familiar, but It looks quite different. It still has the light teal background in the header. And this is Marktel 2. 16, which was released in February 2022. And you'll notice that we made a few changes to the um to the colours, but not much has really changed since 2.

2:05

Speaker 2: 0 in terms of the UI. And then I'm going to do a recap of the editor , which I think Tom showed earlier today. This is how the editor looked like in 2. 16. And in 2022, we aim to do a complete redesign of the page editor to make it more accessible and easy to use. because uh the editor is the place where our users spend the most time in. And we have a three-month release. cycle so it was it was impossible to complete the implementation in one release. So we started um doing it. uh bits by b uh bits

2:50

Speaker 2: and the 3. 0 release we implemented the breadcrumbs, the collapsible breadcrumbs. So uh this is an iframe. I uh I ran a lot of um Docker containers to run multiple versions of WhiteTale. And um so we have E dis we have you designed the tabs and We added the status side panel to show you the information about the page. So previously it's shown right here, which kind of um obstructs the way uh to the content um and by moving it to the side panel the editor can see the content right away And in 4. 0 we finally completed

3:37

Speaker 2: the redesign of the um editor. We added the preview panel, which was one of the first things I worked on when I joined Torchbox. So um yeah we had the multiple devices for the preview as well. And in 4. 1 we made A few tweaks and we also added the minimap to help you navigate through the page more easily In 4. 2, we mo uh we mostly just made uh smaller changes to refine the experience. And in 5. 0, we added dark mode to the admin and not just the editor. So this is across the admin. But what

4:22

Speaker 2: about the other parts of the admin? Because uh the admin is not just the editor, we have lots of other views. This is the snippets listing view in Wagtail 2. 16, which is very simple. We have the search at the top and there's only a single column in the table for the uh and I guess the checkbox for the bulk actions but For the content itself it's only a single column for the string representation of the snippet. And for the page listings, it look like this. But yeah, I'm going to focus on the snippets listing, which you can see

5:07

Speaker 2: the iframe can sometimes break. But Anyway, um yeah, so I'm going to focus on the snippets listing because uh snippets are for non-page models and we have a lot of non-page models in the admin like the stuff that you see in the settings and also for listings like the report views. And then in 3. 0 we changed the header, but it mostly uh was still the same as the one in 2. 16. In 4. 0, we added the breadcrumbs and we moved the search to be in line with with the head with the heading. And we had additional default columns for the edited

5:54

Speaker 2: and uh we also added support for using revisions and drafts for snippets. That's why we have this status column. And that's actually The only reason why I why I added the breadcrumbs because in the editor for snippets I also added support for the preview panel which means you have to put this preview button at the top and without the breadcrumbs it would look strange so I had to copy the breadcrumbs over. And in 4. 1 not much really changed and in terms of the page listings. Yeah, we we also put the side panel here, but for the listing itself, there's not much

6:43

Speaker 2: uh that has changed. Uh there is not really any new functionality here. And if we jump to 5. 2, we added a few more things to snippets, which uh To name a few, the ability to have custom columns. And we have also moved the action buttons to be inside this three-dot drop-down because previously it was this uh visible on hover buttons which is not very accessible And we also added the ability to export the listing to a spreadsheet, and we also added the ability to have custom filters. But

7:28

Speaker 2: these um abilities to have uh the export and filtering it's it's not uh a new thing in WhiteL because it's actually um extracted from a similar feature in the report views. And so this is the report view for loft pages in Wagtel 5. 2. And if we go back to 2. 16 Nothing has really changed. So it's still pretty much the same, even though for the page editor we've made such leap to the implementation for the designs. So we had to do something about this. And Ben and Wright, our designer at Torchbox, who designs the UI and UX

8:15

Speaker 2: for the latest Wagtail features. He opened a discussion on GitHub to showcase the designs for the new listing views. The aim is to enhance the searching and filtering capabilities. of the page listings, but also to eventually roll out the same um patterns and functions to all listings in the CMS. So this is what you get with the latest um stable release of Wagtail 6. 1. Um this is an example of uh snippet listing with custom filters And uh this is not an iframe, by the way, it's it's just a screenshot. Um but yeah, I want you to take a good look at this screenshot.

9:01

Speaker 2: So we have the New ish breadcrumbs with the icons and the header buttons and the search and filtering are now at the top right And the filter is inside this component, the pop -up component. And we have a section that tells you the current active filters. And uh but yeah, um I'm going to talk about how we end up with this implementation because it's not straightforward. But um yeah, I'll I'll get to this in a bit. So for the search functionality, it has been around forever. Um

9:47

Speaker 2: You can see in this commit it's from 2014. It's before Wagtail 1. 0 was released, I think. Um But yeah, this is one of the one of my favorite things to do on my job to blame people. I use git blame and look for the commit that introduced the changes I wrote a bit about this on uh in a blog post on wagtail. org where I said, when you're working on a 10-year-old project like Wagtail. Looking at these old commits give you more context on how the code came to be. In some cases, the decisions made in the past might no longer be relevant today.

10:32

Speaker 2: But in other cases, you might find that our ancestors were way ahead of their time and you might want to build on top of what they've done. So the header search is an example of the first one, um, because it relies on inline scripts, uh which do not play well with the content security policy standard um something that wasn't as popular back then as it is now. And last year, one of our core team members, LB from Australia , refactor the header search to use Stimulus. Stimulus is a small JavaScript library that we have been adopting to replace jQuery and inline scripts within Wagetail.

11:20

Speaker 2: And LB has been the main driving force behind the initiative. So, refactoring It doesn't sound like a big deal and since it is always something that happens behind the scenes, it's it's not immediately visible to the user unless you end up breaking the feature somehow So I'm not going to go into details how the refactoring was done, but I promise this bit of refactoring will be important later. And like I said, filtering with Django filter was introduced for the report views in version 2. 10 to be precise. And this is an example of the other case where our ancestors were way ahead of their time

12:08

Speaker 2: because we end up reusing this code a lot. And I moved the generic uh sorry, I moved the filtering code from the report view to the generic index view so that it can be reused for snippets. In theory, I could have just copied the same code from the report views to the snippet views, or just extracted the view, uh, the code to the snippet view. But I thought this bit of code might be useful for other listing views in the admin, even though at the time it wasn't used other than for snippets. So in 5. 2 we started the work on implementing the uh designs that our designer made.

12:56

Speaker 2: Um We started by adding the search mechanism to the page listings. And like I said, with Wagtail we have a three-month release cycle, so we cannot do everything in one release. So we had to do it in smaller chunks. And for page listings, we've always had the ability to search for pages, but it's been a separate thing to the left sidebar. And it's not integrated into the page listings. So if you start to explore the tree structure, you won't be able to search. But if you search and you st continue exploring, you'll be taken to the page listings. So it it's not a nice experience. There's a f there's some friction in there.

13:44

Speaker 2: So yeah we we added the search field uh the search feature in 5. 2 but not filters And in 6. 0 we started adding filters to the page listings. This is done by refactoring the page listing view, which originally used its own class like it it's a entirely it's an entirely separate class. We refactored it to reuse the um base generic index view where it now contains the filtering code because I extracted it there. And this was how it looked like. We didn't have uh the new pop-up component just yet.

14:30

Speaker 2: Because um our main front end expert, Thibaut, was busy with other projects, so I had to suggest Matthew to use this dialog component that we already have to put the filters in in the meantime And then I had to do my share of some front-end work by implementing the new designs for the header, uh the breadcrumbs with the heading in incorporated into the breadcrumbs and the search and filters uh to be moved at the top right And after that, we wanted to add the

15:17

Speaker 2: active filters information and We separated the work in in two parts, the backend part, which Matthew worked on, and he implemented the feature to to list all the active filters. But so he was focusing on the back end and it was for the front end we just render a link that removes the filter and it will do a full page reload. It works, but it's not the final version that we want to merge into Wagtail, so this was marked as draft. And then I worked on top of his PR to implement the Ajax ever load and the designs for the little

16:02

Speaker 2: pills we call them for the active filters. And let me tell you for to implement the Ajax reload for the for clearing the active filters. I um so I'll I'll I'll show you uh the feature first. So if I clear it now as you can see there's this little spinner while it loads uh the results. And to to implement this, I didn't have to write a single line of JavaScript. Why? Well, because LB has done the work to ref uh when he refactored the header search to use stimulus. Um it allowed me to just reuse the code by adding these attributes to the HTML

16:49

Speaker 2: and it will use the same code as long as I provide the URL that Matthew provided, it will do its thing and refresh the page using Ajax. So that was nice And to implement the Ajax filtering for the filters pop-up, I had to move the input elements for the filters to be inside the same form as the search. And then I just change a few attributes to use the submit method of the form. And this also I I didn't have to write a single line of JavaScript. I just Reused what Alb has written, which is nice.

17:37

Speaker 2: And the final piece of the puzzle is to implement the pop-up component, which was done by Thibaut. So we thought, all right, that's done. Um we've got the Ajax reloads and the new pop-up component. Well, famous last words because uh we encountered a lot of issues after we started um integrating the new pop-up because um let me show you So this is the current version. And for example, if we have a date filter. The input needs to be rendered inside the same form, but the date picker also has a pop-up.

18:24

Speaker 2: So if we render the pop-up element inside the filters pop-up, it will be cut off by the pop-up. But if we put it outside, then uh you'll run into issues like So let me show you. If I click on this filters pop-up and I click anywhere else, it will close the pop-up. But the problem is to make it so that the date picker is not cut off by the pop-up, I had to put it outside of the pop-up. But if I click on this If I didn't fix it, it will immediately close the pop-up. So that's the example of

19:10

Speaker 2: a problem that I encountered. And this is because we are integrating different libraries on the front end to do this because like the date picker is one library and then the pop -up is another library on uh uh that we also um put some custom implementation to to allow you to have like this go back mechanism. So yeah, and also with uh the way that Tippee, our uh JS library that we use to render these tooltips and also the pop-up menu It by default unmounts the input elements. Uh well the contents of the pop-up

19:56

Speaker 2: when it's closed Which means if you have input any filters in here and you close it, it will be lost when you start searching because it gets removed from the HTML. So I had to work around that as well. And Yeah, uh not to mention like the surfers uh there is the synchronization for the state between the client and the server because the Searching and the filtering is it it only refreshes the results. It doesn't do a full page reload, which means if you have applied, let's say, a filter And in some cases, you have these, for example, download to export the

20:46

Speaker 2: listing as spreadsheets. And you would want the filters to be applied to the export as well. But since we are only refreshing the listing, we also need a way to refresh the links to these downloads as well. So that's just some examples of of these um problems that we encountered once we start integrating all of them together. So yeah. I also implemented some of the nice to have features like the ability to open the relevant filters. as you click on these active pills. But there was also the problem of when you're clicking on this, the pop-up

21:34

Speaker 2: things you're clicking away from the element, so it will close. So yet another example. But anyway. But I love how the spinner that shows up when you clear this. It I didn't implement that at all. It was done by the controller implemented by LP when he changed the header search. So if you look at the spinner in here, I don't know if you can see it, but Yeah, it uses the same code. I didn't have to write a single line of JavaScript to implement this spinner. So yeah, it was nice Anyway, the lessons that I learned um when doing a project like this.

22:20

Speaker 2: Um Do ple please integrate as early as you can if if it's possible. Don't wait until last minute because you'll encounter these problems that I just showed you And teamwork makes the dream work. So I loved how each of our team members used our expertise to build these feature feature. And yeah, it was a fun experience for me. And libraries come at the price. So while they may allow you to build uh fancy stuff quickly once you start integrating them um you'll start i seeing some weird bugs So also play the long game.

23:05

Speaker 2: Um if you write your code, you uh if whenever possible, think if how it can be reused in the future like LB did which was just so awesome. So thank you LB And how can you use this? Um You can do nothing because if you already set up search and filters for snippets, you'll automatically get the new UI and UX in most cases. And for snippets, that means you use index for the model or you set the search fields for the uh on the field set and you set the filters. And yeah, we didn't change the API for this since they were

23:52

Speaker 2: using the old design. So you'll automatically get the new design. And for Whiteo 6. 1, you can have custom page type listings with page listing viewset. And is that it? Well yeah, in the future, uh this I promise this is the last thing. Um I'm just uh showing you of my plans for the future. I want you to be able to customize the breadcrumbs and the buttons at the top, along with the search and filters, which were obvious, and like the buttons that show up here All without customizing the templates. So I'm hoping that you can do this by just changing some Python code

24:41

Speaker 2: with a few subclass. Because I know how painful it can be for overriding white tail templates, especially for third party packages But yeah, if you have any more ideas for such enhancements to the Wagtail UI and UX or just new features in general, tell us. And that's it. Thank you.

Questions this talk answers

What are Wagtail’s universal listings and what do they improve?

Universal listings are a unified approach to listing views across the Wagtail admin. They bring consistent searching, filtering, active-filter display, custom columns, exports, and updated navigation patterns beyond just page listings.

Discussed at 8:15

How did Wagtail add Ajax search and filtering without writing new JavaScript?

The implementation reused the Stimulus-based behavior already created for the header search. By adding the appropriate HTML attributes and putting the filter inputs in the same form as the search, Wagtail could refresh results and show loading states with Ajax without additional JavaScript.

Discussed at 16:02

What problems arise when combining Wagtail’s filter pop-up, date picker, and other front-end components?

Nested pop-ups can clip controls or close unexpectedly, and the pop-up library can remove filter inputs when it unmounts its contents. Ajax updates also require synchronizing client and server state so related links, such as spreadsheet exports, retain the active filters.

Discussed at 17:37

What are the main lessons from building Wagtail’s new listing views?

Integrate components early, make teamwork and reuse central to the implementation, recognize that third-party libraries can introduce integration bugs, and design code so it can support future features rather than only the immediate task.

Discussed at 22:20

How do I get the new Wagtail listing UI for snippets and custom page listings?

For snippets, existing search and filter configuration generally gets the new interface automatically, using the model index, search fields, and filters. In Wagtail 6.1, custom page-type listings can be created with `PageListingViewSet`, without changing the API used for the older design.

Discussed at 23:05

Presenters

Note: We understand that names change, people change, and bodies change. We respect each individual's journey and privacy. If you have any concerns about a video or need us to remove content, please don't hesitate to contact us. We will handle your request with care and promptly address any issues.

More videos by Sage Abdullah

More videos from Wagtail Space NL