Jump to content

First Steps to Making New Admin Tabs?


Recommended Posts

As an early foray into PW, I've been porting over a WP site I built not too long ago.

Needless to say it's been pretty amazing so far and I'm excited to keep going. The way the selectors work is a dream compared to WP, even if PW is in its infancy when it comes to the admin interface.

Now, there are probably more bad WordPress developers out there than good ones, and I know this having spent the past five years working in WP and making the transition, but one thing WP does have down right is the clear separation of content types in the Dashboard: Content types like Pages/Posts/Custom Post Types with taxonomies are organized differently than Menus or Sidebars & Widgets, and so on. By this I mean, visually, of course: that is, I go to a different part of the admin to administrate different types of data, and my experience with clients I've built installations for is that this visual separation of content makes sense to them, often without my having to explain anything when I release a build. This is of course as compared to say, the way Drupal organizes its content in the admin, which only ever gives clients headaches.

Anyway, I want to experiment with the Ergo admin theme and see what complexities are involved in adding new tabs to the main menu, potentially to create the illusion that specific pages and/or trees of pages are stored in separate parts of the PW admin. Has there been any talk in the forums about this?

If anyone can point me to discussions you've come across, that'd be great.

Link to comment
Share on other sites

Welcome! That's a really good & interesting question. One thing I'd suggest is to read this article and Ryan's comments below it: http://gadgetopia.com/post/7242

He talks about "bucket" CMS software, which is really part of what you're talking about, if I'm reading you right. So read what he says about how he prefers to arrange data and see what you think. It could be that you end up writing a really neat system on top of ProcessWire, and I've actually spoken about other CMS developers on that subject, but I think it's a good idea to understand ProcessWire's aims & successes first.

I'll hold off on admin tab advice because it's been a while since I've done that and my knowledge may be outdated. :-)

  • Like 2
Link to comment
Share on other sites

Having looked at several PW Admin themes, I can safely say creating a PW admin is quite "easy". It is just a page after all. I have been toying with some admin theme ideas lately (too many ideas, so little time!) but haven't finished (er, haven't started) on any of them. Down the pipeline (very long pipeline) I will do a tut on how to port different admin themes to PW. It is just a matter of outputting the content you want in the "section" you want...

I'm too lazy to search atm  but yeah, this topic has been discussed before. I think PW aims to remain simple to use. And because it is simple to use and build things with, stuff like admin themes can easily be built/customised by the user rather than provided in the core. Just my 2 pence :) 

Link to comment
Share on other sites

Sweet, I'll check that out tomorrow.

RE: the article; I appreciate the article's discussion of a "master geography" or single kernel of truth, suggested by the system, as the basis for all relationships between content types. I also agree with Ryan's comment in the article about how we need a master tree so that content doesn't get disconnected from the URL maps that the Web/Google depends on. 

I guess when I say I'd like to bucket out content in the admin, I don't mean to actually separate the content from the "home" tree. That is, it looks like all pages, no matter what templates they use, live off the "home" tree in PW and are connected to it, whether they generate real URLs or not. What I'd like to try and do is make separate tabs/admin pages for content like sidebars, widgets/blocks, and menus since they don't have URLs in the front end, and definitely do behave differently than regular pages in the system (since, for example, there are things like custom menus, global sidebars, and global widgets/blocks and so on).

I think this might be as easy as having a page called "Sidebars" in the hierarchy that's hidden from the "home" tree (excuse my lack of familiarity with the PW terminology here), but made visible, with all its children (presumably the individual sidebars that can be assigned to pages throughout the site, and their child widgets), if you visit a tab like "Sidebars" in the main admin navigation. Same for menus.

So really, for me, it'd just be a matter of making a new admin page that can be linked to from the main navigation, and then listing out a particular subtree of the home tree. As far as philosophy's concerned, my driver's really the client; my experience is that they have less success searching for stuff that behaves like an attachment to the real content in a tree than in its own cordoned-off little area.

  • Like 1
Link to comment
Share on other sites

I think I see what you mean. I don't want to give the idea that I'm against it, either--having created pages like that both in and outside of the admin area. But I had a few experiences where I made really weird decisions until I understood how Ryan's experience added up to a big picture where you get a system that seems to scale really well when it comes time to tweak the original tweaks. :-)

Link to comment
Share on other sites

Okay, so here's what I came up with:


Make a branch of pages in the Home tree completely hidden from a "client" role, say of Menus or Sidebars, but that is visible from a tab in the admin's primary menu so that the client is just dealing with pages in the "Home" tree. The end result being just "Pages," "Menus," and "Sidebars" in the primary admin menu.


1) I make a template called "node" for any parent page that starts a branch of pages that shouldn't be viewable in the Home tree to the client role. This isn't necessary but I feel like it's helpful because now these pages don't resemble the regular page template if the user somehow stumbles upon them.

2) I make a page called "Menus" and assign it the "node" template in the Home tree. All my custom menus are children of this page.

3) I make a page called "Menus" as a child of the hidden Admin page in the Home tree. This causes PW to make a tab with the message about not having a process assigned to it.

4) I make a module that assigns a process to the new template: (http://processwire.com/talk/topic/1272-new-page-nav-in-admin/):

class UtilityMenuList extends Process {

	public static function getModuleInfo() {
		return array(
			'title' => 'Custom Menu List',
			'summary' => 'List all custom menus.',
			'version' => 100,
			'permission' => 'page-edit'

	public function execute(){
		$pl = $this->modules->get("ProcessPageList");
		$pl->set('id',1057); // or any other parent page
		return $pl->execute();

Here we set the ID to the "Menus" page from step 2. This is the branch of pages we want to appear on the Menus tab.

5) We go back to the Menus admin page from step 4 and choose UtilityMenuList from the Process field. This makes PW show a Home tree that only includes the Menus branch.

6) Now we want to exclude the Menus branch from being visible on the Home tree, since that should only show "regular" Pages. I followed Soma's tutorial here for extracting branches from the JSON, since it's not apparent how to hook into ProcessPageList according to this thread: http://processwire.com/talk/topic/1272-new-page-nav-in-admin/. We create another module:

 * Utility Hide Nodes
 * Hides pages with a node template from display in the admin.
 * ProcessWire 2.x
 * Copyright © 2010 by Ryan Cramer
 * Licensed under GNU/GPL v2, see LICENSE.TXT
 * http://www.processwire.com
 * http://www.ryancramer.com
class UtilityHideNodes extends WireData implements Module {
    public static function getModuleInfo() {
        return array(
            'title' => 'Hide Node Pages',
            'version' => 100,
            'summary' => 'Example module to hide page in the admin per user per page.
                          Add a page field "pagelist_hidden" with a PageListSelectMultiple input type
                          to the user template. Select or add pages you want to hide in the admin.',
            'href' => '',
            'singular' => true,
            'autoload' => true
    public function init() {
        // only add hook only if the render parameter is set
        // (as used by ProcessPageList)
        if(!isset($_GET['render'])) return;
        $user = $this->user;
        $roles = $user->roles;
        // loop thru each role
        foreach($roles as $role) {
            if (!$role->pagelist_hidden) return;

        $this->addHookAfter('ProcessPageList::execute', $this, 'pageListHiddenPages');
    public function pageListHiddenPages(HookEvent $event){

        $user = $this->user;
        $roles = $user->roles;
        foreach($roles as $role) {
            foreach($role->pagelist_hidden as $hidden_page) {
                $hidden[] = $hidden_page->id;

        // make sure it's an ajax request
            // manipulate the json returned and remove any pages found from array
            $json = json_decode($event->return, true);
            foreach($json['children'] as $key => $child){
                if(in_array($child['id'],$hidden)) unset($json['children'][$key]);
            $json['children'] = array_values($json['children']);
            $event->return = json_encode($json);

7) I altered Soma's code to make it work with roles. We go to the Role template instead of User and add a new field called "pagelist_hidden" of the type Pages, with the following settings: Details = Multiple Pages (PageArray) and InputFieldType = PageListSelectMultiple. This will let us choose specific pages to make hidden from the Home tree on a role-by-role basis.

8) In my case I have a "client" role, so I assign this field to the Role template and then pick my Menus branch on the "client" role.

9) If I log in as the client role, the Menus branch doesn't appear at all in the Home tree, but I can still see it in the branch that gets outputted under my new Menu tab.

So as a result we can add as many tabs as we need (potentially to create the illusion of more content types beyond pages) and hide as many branches thru the admin interface by simply adding them to the client's user role.

The Menus parent page still appears on this tab, which is unfortunate but not so bad. If this were a Blog section, it would still make sense visually. I just set the parent to be uneditable, that way the client can't mess with it, but the children are still editable.

Next step would be... can we somehow paginate a branch?  Anyhoo it's pretty neat so far. 


Altered Soma's code to work with roles & not individual users.

  • Like 6
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Recently Browsing   0 members

    • No registered users viewing this page.
  • Similar Content

    • By Robin S
      This module lets you add some custom menu items to the main admin menu, and you can set the dropdown links dynamically in a hook if needed.
      Sidenote: the module config uses some repeatable/sortable rows for the child link settings, similar to the ProFields Table interface. The data gets saved as JSON in a hidden textarea field. Might be interesting to other module developers?
      Custom Admin Menus
      Adds up to three custom menu items with optional dropdowns to the main admin menu.
      The menu items can link to admin pages, front-end pages, or pages on external websites.
      The links can be set to open in a new browser tab, and child links in the dropdown can be given an icon.
      Requires ProcessWire v3.0.178 or newer.
      Example of menu items

      Module config for the menus

      Link list shown when parent menu item is not given a URL

      Setting child menu items dynamically
      If needed you can set the child menu items dynamically using a hook.
      $wire->addHookAfter('CustomAdminMenus::getMenuChildren', function(HookEvent $event) { // The menu number is the first argument $menu_number = $event->arguments(0); if($menu_number === 1) { $colours = $event->wire()->pages->findRaw('template=colour', ['title', 'url', 'page_icon']); $children = []; foreach($colours as $colour) { // Each child item should be an array with the following keys $children[] = [ 'icon' => $colour['page_icon'], 'label' => $colour['title'], 'url' => $colour['url'], 'newtab' => false, ]; } $event->return = $children; } }); Create multiple levels of flyout menus
      It's also possible to create multiple levels of flyout submenus using a hook.

      For each level a submenu can be defined in a "children" item. Example:
      $wire->addHookAfter('CustomAdminMenus::getMenuChildren', function(HookEvent $event) { // The menu number is the first argument $menu_number = $event->arguments(0); if($menu_number === 1) { $children = [ [ 'icon' => 'adjust', 'label' => 'One', 'url' => '/one/', 'newtab' => false, ], [ 'icon' => 'anchor', 'label' => 'Two', 'url' => '/two/', 'newtab' => false, 'children' => [ [ 'icon' => 'child', 'label' => 'Red', 'url' => '/red/', 'newtab' => false, ], [ 'icon' => 'bullhorn', 'label' => 'Green', 'url' => '/green/', 'newtab' => false, 'children' => [ [ 'icon' => 'wifi', 'label' => 'Small', 'url' => '/small/', 'newtab' => true, ], [ 'icon' => 'codepen', 'label' => 'Medium', 'url' => '/medium/', 'newtab' => false, ], [ 'icon' => 'cogs', 'label' => 'Large', 'url' => '/large/', 'newtab' => false, ], ] ], [ 'icon' => 'futbol-o', 'label' => 'Blue', 'url' => '/blue/', 'newtab' => true, ], ] ], [ 'icon' => 'hand-o-left', 'label' => 'Three', 'url' => '/three/', 'newtab' => false, ], ]; $event->return = $children; } }); Showing/hiding menus according to user role
      You can determine which menu items can be seen by a role by checking the user's role in the hook.
      For example, if a user has or lacks a role you could include different child menu items in the hook return value. Or if you want to conditionally hide a custom menu altogether you can set the return value to false. Example:
      $wire->addHookAfter('CustomAdminMenus::getMenuChildren', function(HookEvent $event) { // The menu number is the first argument $menu_number = $event->arguments(0); $user = $event->wire()->user; // For custom menu number 1... if($menu_number === 1) { // ...if user does not have some particular role... if(!$user->hasRole('foo')) { // ...do not show the menu $event->return = false; } } });  
    • By prestoav
      Hi all,
      I've noticed that, when creating new users for clients, the chosen admin theme is not saved. For example, I create a new user select Reno or UIKit as the theme at point of creation and save. When logging in that user for the first time the admin theme is back to default. Changing it again and saving corrects this.

      Anyone else noticed this or is it a known bug at the moment?

      CMS V 3.0.156.

    • By sambadave
      Hi there
      Short version of question
      Let's say I have a page in the admin that contains a field... Is it possible to output the content from that field on another page in the admin? Almost like a reference.
      Longer version of question (with example)
      A house builder with multiple (60+) developments. They want to be able to create notices/messages that can be added to one or many developments. Handy for things like regional covid lockdowns or temporary office closures due to bad weather.
      My approach for the admin editing options:
      Add each message to each development
      Pros: You edit the message on the development page in context
      Cons: Very time consuming and repetitive if the same message needs to be applied to 60+ developments
        Control all the messages from one admin page and say which development each message should be applied to
      Pros: Easier to add/remove messages to more than one development at a time. Control all messages from one place.
      Cons: Content is not added on development page, which is where typical admin users may expect to find it I went for option 2 due to flexibility, and created a page within the admin for global development notices. This contains a repeater with:
      Field for message to display Checkbox list of all developments. The user can select which ones to apply each message to It's working really well but the only thing is that if the user goes to a specific development in the admin, the relevant messages aren't displayed in context (as they aren't edited on that page and instead on the global development notices page)... which may cause confusion when a new staff member / content admin tries to edit the text but there is no field when they go to the development admin page where they expect to see it...
      I don't require the message(s) to also be editable on the development page, but I wondered if there was a nice way to show it/them somehow. I feel like I am missing something really simple as I'm sure ProcessWire will have a nice way of achieving this, or maybe there are field settings that allow this kind of thing to happen?
      Any ideas on approaches or similar experiences would be much appreciated, even if it is just a much simpler example with the content from one field being shown on another admin page to get the ball rolling.
      Thanks in advance for any advice :)
    • By schwarzdesign
      We're currently working on a few sites that have some users with very limited access; most importantly, some users can only edit their own profile and nothing else in the backend. We're using AdminThemeUiKit, so the CMS navbar only contains the site logo and the username for those users. The problem is that the crucial "View site" link that gets you back to the frontend is hidden in the dropdown behind the username. This isn't immediately obvious (and TBH it does feel out of place there, even when you know it's there).
      I'm looking for ways to make the "back to site" link more visible – and I also think this is worth a discussion for AdminThemeUiKit in general. Here's what I have considered:
      Ideally, clicking the logo would take you back to the frontend (currently, you just get a blank page with nothing but an 'edit profile' button). I checked the settings, but the Uikit theme only has options to open the site tree or open a side navigation. Maybe a new option to go back to the frontend could be added? Or maybe the method that gets the logo link should be made hookable, so I could retain the default behaviour for editors, but change the link for users with limited access. An additional link in the menu would also work. But the only way I can think of to add this would be a Process module that just redirects to the homepage. But that's a bit overcomplicated, and I would like to do this without the additional redirect. Of course, copying the theme and modifying it manually or inserting a prominent link with JavaScript would work, but both options are sort of hacky and require some upkeep. Is there a better way? Have you come across this problem yet, and how did you solve it? I'm looking forward to suggestions!
    • By humanafterall
      I would like to set an admin template to 'https only' as recommended in the Processwire security docs.
      However if I do this it forces this setting locally too, resulting in https://localhost requests which result in an error page.
      Is there a simple way round this? Setting https for templates in the config?
  • Create New...