Diff for "VersionThreeDotO/UI/Conversion"

Not logged in - Log In / Register

Differences between revisions 15 and 16
Revision 15 as of 2009-08-07 12:45:09
Size: 13445
Editor: sinzui
Comment:
Revision 16 as of 2009-08-07 12:54:53
Size: 13538
Editor: sinzui
Comment:
Deletions are marked like this. Additions are marked like this.
Line 50: Line 50:
Line 149: Line 150:
    * Ensure the CSS works because the classes are right, the css that works     * Ensure the CSS works because the classes are right, the CSS that works
Line 158: Line 159:
      to insert the page title into the HTML. (Note: AFAICS, it's using context.title
     
with no fallback, so currently I'm explicitly setting the heading slot - noodles 20090806)
      to insert the page title into the HTML.
      *
(Note: AFAICS, it's using context.title with no fallback, so currently
       
I'm explicitly setting the heading slot - noodles 20090806)
        Wrong. The heading slot in the main page, not the HTML <title>.
        Look around line 28.
      * pagetitles.py is deprecated. Do not add to it. Do no one use
        CONTEXTS/fmt:pagetitle
Line 193: Line 199:
    yui-g: A grid column
    yui-u: A unit of content
    yui-g: A row
    yui-u: A column
Line 197: Line 203:
    first: The first item in the yui-g (fixes issues in css 2.x browsers)
           (See the note above about problems with this class)
    first: The first column

UI 3.0 implementation

A primer about the 3.0 UI and how we go about doing it.

There are some bugs that must be fixed before layouts changes can start:

We want to minimise the number of developers writing HTML and CSS until there are more HTML examples and CSS rules in place.

Layouts

  • locationless: A page without tabs, search, or side portlets
    • This is used by non-app pages like errors. Most (maybe all) pages that use this layout have been converted.
  • searchless: A page without global search or side portlets
    • This is for pages that implement their own search in the main area. The Launchpad front page uses this layout. Other pages may want to switch to this layout.
  • main_only: A page without side portlets
    • This will be the most common layout because modification pages and some listing pages do not have items that qualify for side portlets.
  • main_side: A page with everything
    • This page is for artefacts that have actions that create notifications, have subscribers, or have notifications that can be placed in the side. Other portlets should not be placed in the sidebar.

Estimate conversion table

    Old layout                        New layout
  5 default(2.0)                      main_side
 30 applicationhome                   main_only
 10 pillarindex                       main_side
  1 search                            searchless
256 context/@@main_template/master    main_??
158 onecolumn                         main_??

See the Conversion report for a summary of our progress.

Converting a template to a layout

* Choose the layout
    ? The page does not belong to an application, can be shown anywhere
      ! use locationless.
    ? Does the page implement search in the main area, and does it contradict
      with global search
      ! use searchless
    ? Does the page have actions that create objects or notifications, does
      it have a subscriber's list, does it have notification (events) to 
      show recent activity?
      ! use main_side
    ? All other cases (simple artefacts or modification pages)
      ! use main_only

* Mechanical changes
    * Switch the layout:
      * Update the macro
        -  xml:lang="en"
        -  lang="en"
        -  dir="ltr"
        -  metal:use-macro="context/@@main_template/master"
        +  metal:use-macro="view/macro:page/main_only"
      * Update the heading?
        * If this is the index of an object move <h1> to the heading slot.
          The page layout is probably main_side. The rule could also be
          stated as the context.title above the bread crumbs should not
          also be repeated in maincontent.

    * Remove 0.0 and 1.0-isms
      * Delete all portlet slots
      * Delete the help
        * You may want to extract the help to a separate file and link to it

    * YUI-ify
      * If there is more than on block on the page:
        * First block is class="top-portlet"
        * All following blocks are class="portlet"

    * Launchpadify
      * Convert crafted links into fmt:link or fmt:link-icon
        * We may want to extend the formatter to handle alternate link text.
        * We probably need to add links the menus.
      * Create valid css-ids using fmt:css-id
        * It takes an optional prefix fmt:css-id/prefix-

* Design changes
    * Menus and links
        * Dismantle the context, app, and navigation menus.
          * Move the links inline.
            Are the links really needed in the page?
          * Many pages will require a "related <nouns>" portlet at the bottom
            of the page that has a list of links to other pages. Edit pages might
            link to other edit pages for example.
            * Create a navigation menu if the links are shared between views.
              Use the related pages adapter to render the view's menu.
              <tal:menu replace="structure view/@@+related-pages" />
              The disabled links and the current page are removed the from list.
        * Define the global Modification/Set links
          * Some links cannot be moved into the page because they act on the
            entire object or on some unseen object. eg.
            Change password and Change Details. The menu should be very small.

    * Side portlets
        * Build the side portlets that convey activity
          * Are there subscribers that need to be shown?
          * Are there items to download?
          * Are there events or notification to display?

    * Main portlets
        * The 'first' problem:
          The YUI CSS requires that the div that contains 'first' also contain the
          'yui-u' class. The portlet template can define its div and set the 'portlet'
          class. The calling template will set the yui classes. Something like this:
            <div class="first yui-u"
              tal:content="structure context/@@+portlet-top-contributors" />
        * If there is a lot of content, divide the main area into columns
          * Create a parent column <div class="yui-g">
          * Create first portlet <div class="yui-u first portlet">
          * Add all other portlets <div class="yui-u portlet">
          * Note the 'first' problem above, if you separate the portlet to another file,
            keep the YUI classes in the calling template: <div class="yui-u first">
         * Use the <div class="portlet"> structure to create the correct
          margins and borders around the chunk of content.
          * Note that the new CSS makes better use of content. The portlet
            presentation changes based on its location on the page.

    * Common structures
        * Replace 0.0-2.0 html structures with 3.0 so that the layout is
          consistent for all pages
          * Horizontal lines of links are now <ul class="horizontal">
            to normalise spacing
          * Table and CSS that created content that was left-aligned to heading
            are removed. The subordinate information appears below the heading
            now. They are may be replaced with <dl> that may have
            many <dd> per <dt>

    * Ensure the CSS works because the classes are right, the CSS that works
      on ids is being removed.


* Implementation changes
    * Many pages are creating links that should be codified in a menu for the
      app (ApplicationMenu), context (ContextMenu), or view (NavigationMenu)

    * base-layout will use view/page_title before falling back pagetitles
      to insert the page title into the HTML.
      * (Note: AFAICS, it's using context.title with no fallback, so currently
        I'm explicitly setting the heading slot - noodles 20090806)
        Wrong. The heading slot in the main page, not the HTML <title>.
        Look around line 28.  
      * pagetitles.py is deprecated. Do not add to it. Do no one use
        CONTEXTS/fmt:pagetitle
      * If the view is used by one template, the moving the title rule from
        pagetitles to view/page_title is simple.
      * If several templates use the view you may be able to write a more
        complex rule create the title
      * You can choose to not convert the page title, let the template
        fall back to page titles.

* Test changes.
    * Lots of pagetests/stories will break.
      * Does the test verifying page titles, heading, and links work between
        pages?
        * Fix them.
      * Does the test check forms, or verify the primary content of the page?
        * Throw out the test, create a unittest or browser/doctest that
          verifies the view's contracts and purpose.
      * Does the page verify the that an object's state was changed.
        * Throw out the test, create unittest or browser/doctest that
          verifies the state.
      * Does the test verify an external script?
        * Throw out the test and create unittest or doctest that verifies
          the script ran and states changed.

3.0 CSS

Launchpad is using classes for styling, ids are used for testing and scripts.
YUI is doing layout, Launchpad is decorating the layout, so many divs will
have a yui and a launchpad class.

YUI (layout)
    yui-g: A row
    yui-u: A column
           Probably always paired with portlet, though the two classes may be
           in separate divs. Probably should have an id for testing and scripts
    first: The first column

Launchpad (decoration)
    portlet: A chunk on content distinguished by margins, padding, and borders
           Probably always paired with yui-u
    top-portlet: The first portlet in the page, probably a description.

There are may css classes we have not written yet because we have not
discovered all the kinds of html structures we need to make the layout
consistent.

Example layout

A common layout will be an intro on top of two columns of content. You can
see examples of the four layouts in lib/lp/app/browser/tests/testfiles/

<html
  ...
  metal:use-macro="view/macro:page/main_side">
  <body>
  <tal:heading metal:fill-slot="heading">
    <h1>Zaphod Beeblebrox</h1>
  </tal:heading>

  <tal:main metal:fill-slot="main">
    <div class="top-portlet">
      Description
    </div>

    <div class="yui-g">
      <div class="first yui-u"
        tal:content="structure context/@@+portlet-top-contributors" />

      <div class="yui-u"
        tal:content="structure context/@@+portlet-packages" />
    </div>
  </tal:main>

  <tal:side metal:fill-slot="side">
    <div id="actions" class="first portlet">
      content
    </div>
    <div id="attachments" class="portlet">
      more content
    </div>
    <div class="portlet"
       tal:content="structure context/@@+latest-announcements" />
  </tal:side>
  </body>
</html>

Adding a NavigationMenu

Launchpad uses NavigationMenus to associate outbound links to a view. The menu and view are bound together by a marker interface. Links that are used in more than one menu should be defined in a mixin class to ensure that there is a single canonical definition of them.

The menu can be rendered as an action menu in the side portlets or as a list of related pages in the main content.

Working with two menus

There are a few cases where a page may need two menus. One for actions that change an object that are not possible to move into the main content, the other for pages related to the content of the page. NavigationMenus can be created for content objects and views.

A browser module example

   1 from zope.interface import implements, Interface
   2 
   3 from canonical.launchpad.webapp.menu import NavigationMenu
   4 from canonical.launchpad.webapp.publisher import LaunchpadView
   5 
   6 from lp.myapp.interfaces.myobject import IObject
   7 
   8 
   9 class ObjectLinksMixin:
  10     """A mixin class that provides links used by more than on menu."""
  11 
  12 
  13 # Classes to create menus on more than one view
  14 class IObjectEditMenu(Interface):
  15     """A marker interface for the edit navigation menu."""
  16 
  17 
  18 class ObjectEditMenu(NavigationMenu, ObjectLinksMixin):
  19     """A menu for different aspects of editing a oject."""
  20 
  21     usedfor = IObjectEditMenu
  22     facet = 'overview'
  23     title = 'Change object'
  24     links = ('edit', 'images', 'reassign', 'review', 'administer')
  25 
  26 
  27 class ObjectEditView(LauncpadView):
  28     """A view to set branding."""
  29     implements(IObjectEditMenu)
  30 
  31 
  32 class ObjectImagesView(LauncpadView):
  33     """A view to set images."""
  34     implements(IObjectEditMenu)
  35 
  36 
  37 # Class to create a menu for the object, irrespective of the view.
  38 class ObjectActionMenu(NavigationMenu, ObjectLinksMixin):
  39     """An action menu to modify the object."""
  40 
  41     usedfor = IObject
  42     facet = 'overview'
  43     title = 'Action object'
  44     links = ('review', 'administer')
  45 
  46 
  47 # Menus are normally registered using the menu ZCML directive. They can
  48 # be registered in Python. To register the 
  49 provideAdapter(
  50     ObjectEditMenu, [IObjectEditMenu], INavigationMenu, name="overview")
  51 provideAdapter(
  52     ObjectActionMenu, [IObject], INavigationMenu, name="overview")

A ZCML example to register a menu

    <browser:menus
        classes="
            ObjectEditMenu
            ObjectActionMenu"
        module="lp.myapp.browser.myobject"/>

Rendering a NavigationMenu

To render an action menu use this TALES view:

  • <tal:menu replace="structure context/@@+global-actions" />

To render a related pages:

  • <tal:menu replace="structure view/@@+related-pages" />

Note that view and context can be interchanged in the examples since context objects and their views may both have NavigationMenus.

Infrastructure improvements

The MenuAPI now caches menus per request. They are faster and there is no danger of a link changing during rendering.

VersionThreeDotO/UI/Conversion (last edited 2009-09-18 07:58:54 by michael.nelson)