RemovingTheActionsMenu

Not logged in - Log In / Register

Removing the Actions menu

Part of the Launchpad 2.0 design is putting each action link in the most appropriate spot on the page, rather than grouping them all into an Actions menu. Here's how to convert a page with an Actions menu into the new design.

Accessing the context menu

The context menu is being instantiated, and the code for all menu items is being run, whenever it is accessed using its adapter. For that reason, it is a good idea to bind it to a variable once, in the top of the template, and accessing that variable when trying getting action links.

For example:

  <body tal:define="context_menu context/menu:context">
  ...
  </body>

For each of the items in the Actions menu, decide: is it relevant to this page? If so, decide where it should go on the page, and what it should look like. Then insert it into the page template.

For context menu items, you can insert a menu item with code like this:

<div class="actions"
  tal:define="link context_menu/nameofitem"
  tal:condition="link/enabled"
  tal:content="structure link/render"
/>

For application menu items, it's the same, but using the name of the application, e.g. "code" or "translations":

<div class="actions"
  tal:define="link context/menu:bugs/nameofitem"
  tal:condition="link/enabled"
  tal:content="structure link/render"
/>

Using class="actions" ensures (once mpt/launchpad/2008-06-actions lands) consistent vertical and horizontal spacing around action links (and end-of-form buttons, too). It's not essential to use <div>, though: you could use <p>, or <td>, or whatever element is appropriate.

If presenting a link within a sentence or similar structure, the class="actions" isn't relevant, so you could use no HTML element at all:

If the item you&rsquo;re looking for isn&rsquo;t here, you may want to 
<tal:add
  define="link context_menu/add"
  condition="link/enabled"
  replace="structure link/render"
/>.

If you need to customize the link presentation (to make it an icon-only Edit button, for example), do the rendering yourself instead of using link/render:

<a
  tal:define="link context/menu:bugs/nameofitem"
  tal:condition="link/enabled"
  tal:attributes="href link/url"
><img tal:attributes="alt link/text; title link/text" src="/@@/edit" /></a>

The link/enabled property also lets you insert explanatory text if someone might be expecting to do something, but can't:

<div tal:condition="not:link/enabled">
  You need to be signed in as a project maintainer to change this.
</div>

For bonus points, where a link leads to a form that contains only one or two controls, usually that form should be embedded into the main page instead. This is more work, but will save a page load for everyone who uses the form.

Using tabs navigation

Some menu links are not really action items, but more navigation links. Those should be moved to NavigationMenu for the context. These menu are defined like a regular ApplicationMenu.

It's also possible to tie the navigation menu to a set of views instead to a global context. To do that, define a marker interface that will be provided by the views that are related to the NavigationMenu. In the menu definition, simply use that marker interface in the usedfor attribute. This will usually result in two levels of tab navigation. So that proper highlighting is maitained, you'll want to add a menu attribute to the links of the first-level NavigationMenu. The value of that attribute should be the class of the second-level navigation menu.

Here is an that sets up a top-level navigation menu for 'Silverware'; both 'Forks' and 'Spoons'. It then adds a sub-menu for looking at different types of forks.

class IForkMenu(Interface):
    """A marker interface implemented by all the views for forks."""


class ISpoonMenu(Interface):
    """A marker interface implemented by all the views for spoons."""


class SilverwareNavigationMenu(NavigationMenu):

    usedfor = IFancySilverware
    facet = 'overview'
    links = ['forks', 'spoons']

    def forks(self):
        target='+forks'
        text='Forks'
        return Link(target, text, menu=AllForksMenu)

    def spoons(self):
        target='+spoons'
        text='Spoons'
        return Link(target, text, menu=AllSpoonsMenu)


class AllForksMenu(NavigationMenu):

    usedfor = IForkMenu
    facet = 'overview'
    links = ['dinner_fork', 'salad_fork', ...]

    def dinner_fork(self):
        ...
        return Link(target, text)

    def salad_fork(self):
        ...


class DinnerForkView(LaunchpadView):

    implements(IForkMenu)

    ... normal view stuff goes here ...


class SaladForkView(LaunchpadView):

    implements(IForkMenu)

    ... normal view stuff goes here ...

Don't forget to register the new menus in the appropriate ZCML file - it will be in the same stanza as the old actions menu:

  <browser:menus
    module="canonical.launchpad.browser.silverware"
    classes="SilverwareActionsMenu SilverwareOverview
             SilverwareNavigationMenu AllForksMenu"
    />

Hiding the Actions menu

Once you've embedded all the menu items that should be included, it's time to hide the Actions menu.

If the page has other portlets:

Change from this

to this

metal:use-macro="context/@@main_template/master"

metal:use-macro="view/macro:page/default2.0"

metal:use-macro="view/macro:page/default"

metal:use-macro="view/macro:page/default2.0"

The above will hide the actions menu in the tests and in development mode (launchpad.dev), but it will remain visible on production (lpnet and edge).

If the page has no other portlets, you can switch to a single-column layout:

Change from this

to this

metal:use-macro="context/@@main_template/master"

metal:use-macro="view/macro:page/onecolumn"

metal:use-macro="view/macro:page/default"

metal:use-macro="view/macro:page/onecolumn"

(Once the Actions menu has been removed from all/most pages, these layout variations will be consolidated, and the "onecolumn" and "defaultnomenu" names will no longer be used.)

RemovingTheActionsMenu (last edited 2009-01-12 21:42:28 by beuno)