← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] lp:~sinzui/launchpad/launchpad-header-0 into lp:launchpad/devel

 

You have been requested to review the proposed merge of lp:~sinzui/launchpad/launchpad-header-0 into lp:launchpad/devel.

This is my branch to fix the launchpad header so for the title edit widget.
This branch fixes a number of visual issues in the header, but in doing so,
it call attention to the registered slot. Michael and I decided that the
registration slot is out of scope for this branch and the probable solution
is to move it, which requires a reexamination of all its uses.

    lp:~sinzui/launchpad/owner-driver-supervisor
    Diff size: 643
    Launchpad bug: https://bugs.launchpad.net/bugs/538028
    Test command: ./bin/test -vv -t test_base_layout -t base-layout
    Pre-implementation: noodles
    Target release: 10.08


Fix the launchpad header so for the title edit widget
-----------------------------------------------------

The floated left and right instructions in the launchpad header break
the layout of the title edit widget; The widget disassembles itself trying
to avoid the floated content.


Rules
-----

    * Consider using inline-block CSS and relative positioning to fix the
      issue.

    Michael suggested:
    * ADDENDUM: Fix the leading white space before the watermark.
    * ADDENDUM: Align the apps with the bottom of the icon so that there is
      no extra white space between the context, apps, heading and bead crumbs.

    Curtis:
    * Michael's suggestions are very good. They make other problems in the
      header more obvious. The registration slot is taking advantage of the
      unwanted white space. It will be obvious that it was an after thought
      when it creates an extra line. If it is clear that the apps are the
      second part of the header, it may be clear to some users they appear
      in the wrong place in the bread crumbs.

    * ADDENDUM: Move the check for bread crumbs to the list element so that
      no part of the block is rendered when there is no bread crumbs.


QA
--

    * Visit https://edge.launchpad.net/launchpad
    * Choose the edit the title
    * Verify the widget stays together and remains adjacent to the logo.
    * Visit https://bugs.edge.launchpad.net/launchpad-web/+bug/538028
    * Verify the context, apps, title, and bread crumbs are together...
      the reported by line does not interrupt.
    * Visit https://bugs.edge.launchpad.net/launchpad-web
    * Verify the context, apps, title, and bread crumbs are together


Lint
----

Linting changed files:
  lib/canonical/launchpad/icing/style-3-0.css.in
  lib/lp/app/browser/tests/base-layout.txt
  lib/lp/app/browser/tests/test_base_layout.py
  lib/lp/app/templates/base-layout-macros.pt
  lib/lp/app/templates/base-layout.pt
  lib/lp/app/templates/launchpad-hierarchy.pt


Test
----

    * lib/lp/app/browser/tests/base-layout.txt
      * Removed big chunks of a very brittle test that broke from the minor
        markup changes. The diff shows the tests for common parts were
        different, but they where/should be the same. I decided to move
        the testing to a unittest. Note that the diff /before/ my decision to
        to replace the tests was long and hard to read.
    * lib/lp/app/browser/tests/test_base_layout.py
      * Moved the tests for the parts that base-layout provides to unittests.
        I should now be obvious when parts each layout provides.


Implementation
--------------

    * lib/canonical/launchpad/icing/style-3-0.css.in
      * Added .flowed-block which allows us to layout horizontal chunks
        of block content like we image it in our heads.
      * Replaced #locationbar with.login-logout which accidentally solved
        Michaels concern about the leading space :)
      * Updated watermark-apps-portlet rules to not wrap and clear any floated
        content so that the title edit widget does not need to avoid other
        parts of the header.
      * Removed the excess whitespace from .registering and #logincontrol
    * lib/lp/app/templates/base-layout-macros.pt
      * Added an id to make the content easy to test.
    * lib/lp/app/templates/base-layout.pt
      * Wrapped the problem code in flowed-block divs.
      * Moved the registration slot below the logo so that there was no
        floated content near the heading that the title edit widget wraps.
      * Added ids to make content testable.
    * lib/lp/app/templates/launchpad-hierarchy.pt
      * Moved the bread crumb test condition to the block element...the page
        was always rendering space for the bread crumbs.

-- 
https://code.launchpad.net/~sinzui/launchpad/launchpad-header-0/+merge/30570
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~sinzui/launchpad/launchpad-header-0 into lp:launchpad/devel.
=== modified file 'lib/canonical/launchpad/icing/style-3-0.css.in'
--- lib/canonical/launchpad/icing/style-3-0.css.in	2010-07-22 16:27:12 +0000
+++ lib/canonical/launchpad/icing/style-3-0.css.in	2010-07-23 15:26:51 +0000
@@ -709,6 +709,13 @@
 .batch-navigation-links .next {
     margin-right: 0.25em;
     }
+.flowed-block {
+    display: table-cell;
+    display: inline-table;
+    display: inline-block;
+    text-align: left;
+    vertical-align: top;
+    }
 
 
 /* =========================
@@ -1111,18 +1118,22 @@
 .demo {
     background-color: #fee;
     }
-#locationbar {
-    /* The following style works around the fact that the locationbar, which
-    is only used of the Login/Register links in 3.0 UI, is accessible on
-    "locationless" pages. It adds extra space at the top of every page in
-    Launchpad but that does actually look quite good ... ;-).*/
-    height: 1em;
+.login-logout {
+    position: absolute;
+    top: .5em;
+    right: 1.5em;
     }
 div.watermark-apps-portlet {
-    padding-bottom:1em;
+    clear: both;
+    margin-bottom: .5em;
+    white-space: no-wrap;
+    }
+div.watermark-apps-portlet .wide {
+    width: 75%;
+    vertical-align: bottom;
+    margin-bottom: 0.3em;
     }
 div.watermark-apps-portlet img {
-    float: left;
     margin: 0 1.5em 0 0;
     }
 div.watermark-apps-portlet h1, div.watermark-apps-portlet h2 {
@@ -1176,19 +1187,20 @@
     width: 100%;
     white-space: nowrap;
     }
+.context-publication {
+    margin-bottom: 1em;
+    }
 .registering {
     /* Registered slot */
-    float: right;
-    font-size: 85%;
+    margin: 0 0 0.2em 0;
+    font-style: italic;
+    font-size: 77%;
     color: #666;
-    position: relative;
-    top: 2em;
     }
 .breadcrumbs {
     margin-left: 0;
     list-style-type: none;
     clear: both;
-    margin-bottom: 2em;
     font-size: 77%;
     }
 .breadcrumbs li {
@@ -1217,6 +1229,9 @@
     /* align the image with the text */
     margin-bottom: -2px;
     }
+#logincontrol form {
+    margin: 0;
+    }
 #logincontrol input[type='submit'] {
     /* The button lacks the right margin that buttons usually have: */
     font-size: 77%;

=== modified file 'lib/lp/app/browser/tests/base-layout.txt'
--- lib/lp/app/browser/tests/base-layout.txt	2010-07-08 15:26:09 +0000
+++ lib/lp/app/browser/tests/base-layout.txt	2010-07-23 15:26:51 +0000
@@ -35,101 +35,12 @@
 main and side content are positioned using the "yui-t4", "yui-main",
 "yui-b", and "yui-b side" classes.
 
-Header.
+    >>> from canonical.launchpad.testing.pages import find_tag_by_id
 
     >>> view = MainSideView(user, request)
     >>> html = view.render()
     >>> print html
     <!DOCTYPE html ...
-    <html xmlns="http://www.w3.org/1999/xhtml"; xml:lang="en"
-          lang="en" dir="ltr">
-      <head>
-        <title>Test base-layout: main_side</title>
-        <link rel="shortcut icon" href="/@@/launchpad.png" />
-    ...
-
-Standard Javascript functions.
-
-    >>> print html
-    <!DOCTYPE html ...
-    ...
-            sortables_init();
-            initInlineHelp();
-            Y.lp.activate_collapsibles();
-            activateFoldables();
-            activateConstrainBugExpiration();
-    ...
-
-Body preamble.
-
-    >>> from canonical.launchpad.testing.pages import find_tag_by_id
-
-    >>> body_tag = find_tag_by_id(html, 'document')
-    >>> body = str(body_tag)
-    >>> print body
-    <body id="document"
-            class="tab-overview
-          main_side
-          public
-          yui-skin-sam">
-        <div class="yui-d0">
-    <BLANKLINE>
-          <div id="locationbar">
-    ...
-
-Watermark and breadcrumbs.
-
-    >>> print body
-    <body ...
-    ...
-          <div class="watermark-apps-portlet top-portlet">
-            <img alt="" width="64" height="64" src="/@@/person-logo" />
-            <h2>Waffles</h2>
-    ...
-      <!-- Application Menu -->
-      <ul class="facetmenu">
-    <BLANKLINE>
-          <li class="overview active"
-              title="General information about Waffles"><a
-        href="http://launchpad.dev/~waffles";>Overview</a></li>
-    ...
-              <div class="yui-b" dir="ltr">
-                <div>
-                  <h2>Heading</h2>
-                  <ol class="breadcrumbs">
-    ...
-
-Top portlet.
-
-    >>> print body
-    <body ...
-          <div class="top-portlet">
-            <p class="registered">
-              Registered on 2005-09-16
-              by <a class="sprite team" href="#">Illuminati team</a>
-            </p>
-            <p>
-              Main content of the page.
-            </p>
-          </div>
-    ...
-
-Help pane.
-
-    >>> print str(find_tag_by_id(body_tag, 'help-pane'))
-    <div id="help-pane" class="invisible">
-          <div id="help-body">
-            <iframe id="help-pane-content" class="invisible" ...
-            </div>
-          <div id="help-footer">
-            <span id="help-close"></span>
-          </div>
-        </div>
-
-Footer.
-
-    >>> print html
-    <!DOCTYPE html ...
       <!--
         Facet name: overview
         Page type: main_side
@@ -151,72 +62,6 @@
 
     >>> view = MainOnlyView(user, request)
     >>> html = view.render()
-
-Heading.
-
-    >>> print html
-    <!DOCTYPE html ...
-    <html xmlns="http://www.w3.org/1999/xhtml"; xml:lang="en"
-          lang="en" dir="ltr">
-      <head>
-        <title>Test base-layout: main_only</title>
-        <link rel="shortcut icon" href="/@@/launchpad.png" />
-    ...
-
-Watermark.
-
-    >>> body_tag = find_tag_by_id(html, 'document')
-    >>> body = str(body_tag)
-    >>> print body
-    <body ...
-          <div class="watermark-apps-portlet top-portlet">
-            <img alt="" width="64" height="64" src="/@@/person-logo" />
-            <h2>Waffles</h2>
-    ...
-
-Main content.
-
-    >>> print str(find_tag_by_id(body_tag, 'maincontent'))
-    <div id="maincontent" class="yui-main">
-              <div class="yui-b" dir="ltr">
-                <div>
-    <BLANKLINE>
-                  <ol class="breadcrumbs">
-    <BLANKLINE>
-    </ol>
-    <BLANKLINE>
-                </div>
-    <BLANKLINE>
-    <BLANKLINE>
-    <BLANKLINE>
-          <div class="top-portlet">
-            <h1>Heading</h1>
-            <p class="registered">
-              Registered on 2005-09-16
-              by <a class="sprite team" href="#">Illuminati team</a>
-            </p>
-            <p>
-              Main content of the page.
-            </p>
-          </div>
-        </div><!-- yui-b -->
-    </div>
-
-Global search.
-
-    >>> print body
-    <body ...
-      <form id="globalsearch" method="get"
-            accept-charset="UTF-8"
-            action="http://launchpad.dev/+search";>
-        <input type="search" id="search-text" name="field.text" />
-        <input type="submit" value="" class="icon-only sprite search-icon" />
-      </form>
-    </div>
-    ...
-
-Footer.
-
     >>> print html
     <!DOCTYPE html ...
     ...
@@ -240,83 +85,6 @@
 
     >>> view = SearchlessView(user, request)
     >>> html = view.render()
-
-Heading.
-
-    >>> print html
-    <!DOCTYPE html ...
-    <html xmlns="http://www.w3.org/1999/xhtml"; xml:lang="en"
-          lang="en" dir="ltr">
-      <head>
-        <title>Test base-layout: searchless</title>
-        <link rel="shortcut icon" href="/@@/launchpad.png" />
-    ...
-
-Body class.
-
-    >>> body_tag = find_tag_by_id(html, 'document')
-    >>> body = str(body_tag)
-    >>> print body
-    <body id="document"
-            class="tab-overview
-          searchless
-          public
-          yui-skin-sam">
-        <div class="yui-d0">
-    ...
-
-Watermarks.
-
-    >>> print body
-    <body ...
-          <div class="watermark-apps-portlet top-portlet">
-            <img alt="" width="64" height="64" src="/@@/person-logo" />
-            <h2>Waffles</h2>
-            <div id="registration" class="registering">
-            </div>
-    <BLANKLINE>
-      <!-- Application Menu -->
-      <ul class="facetmenu">
-    <BLANKLINE>
-          <li class="overview active"
-              title="General information about Waffles"><a
-        href="http://launchpad.dev/~waffles";>Overview</a></li>
-    ...
-
-Main content.
-
-    >>> print str(find_tag_by_id(body_tag, 'maincontent'))
-    <div id="maincontent" class="yui-main">
-              <div class="yui-b" dir="ltr">
-                <div>
-    <BLANKLINE>
-                  <ol class="breadcrumbs">
-    <BLANKLINE>
-    </ol>
-    ...
-
-Top portlet.
-
-    >>> print body
-    <body ...
-          <div class="top-portlet">
-            <h1>Heading</h1>
-            <p class="registered">
-              Registered on 2005-09-16
-              by <a class="sprite team" href="#">Illuminati team</a>
-            </p>
-            <p>
-              Main content of the page.
-            </p>
-          </div>
-          </div><!-- yui-b -->
-          </div><!-- yui-main -->
-          <!-- yui-b side -->
-          <!-- yui-t4 -->
-    ...
-
-Footer.
-
     >>> print html
     <!DOCTYPE html ...
     ...
@@ -342,51 +110,6 @@
 
     >>> view = LocationlessView(user, request)
     >>> html = view.render()
-
-Heading.
-
-    >>> print html
-    <!DOCTYPE html ...
-    <html xmlns="http://www.w3.org/1999/xhtml"; xml:lang="en"
-          lang="en" dir="ltr">
-      <head>
-        <title>Test base-layout: locationless</title>
-        <link rel="shortcut icon" href="/@@/launchpad.png" />
-    ...
-
-Body.
-
-    >>> body_tag = find_tag_by_id(html, 'document')
-    >>> body = str(body_tag)
-    >>> print body
-    <body id="document"
-            class="tab-overview
-          locationless
-          public
-          yui-skin-sam">
-        <div class="yui-d0">
-    ...
-
-Main content.
-
-    >>> print str(find_tag_by_id(body_tag, 'maincontent'))
-    <div id="maincontent" class="yui-main">
-        <div class="yui-b" dir="ltr">
-          <div class="top-portlet">
-            <h1>Heading</h1>
-            <p class="registered">
-              Registered on 2005-09-16
-              by <a class="sprite team" href="#">Illuminati team</a>
-            </p>
-            <p>
-              Main content of the page.
-            </p>
-          </div>
-        </div><!-- yui-b -->
-    </div>
-
-Footer.
-
     >>> print html
     <!DOCTYPE html ...
     ...
@@ -517,8 +240,6 @@
     >>> body_tag = find_tag_by_id(view.render(), 'maincontent')
     >>> print str(body_tag)
     <div id="maincontent" ...
-      <ol class="breadcrumbs">
-      </ol>
       ...
       <div class="informational message">I cannot do that Dave.</div>
       <div class="top-portlet">

=== added file 'lib/lp/app/browser/tests/test_base_layout.py'
--- lib/lp/app/browser/tests/test_base_layout.py	1970-01-01 00:00:00 +0000
+++ lib/lp/app/browser/tests/test_base_layout.py	2010-07-23 15:26:51 +0000
@@ -0,0 +1,163 @@
+# Copyright 2010 Canonical Ltd.  This software is licensed under the
+# GNU Affero General Public License version 3 (see the file LICENSE).
+
+"""Tests for base-layout.pt and its macros.
+
+The base-layout master template defines macros that control the layout
+of the page. Any page can use these layout options by including
+
+    metal:use-macro='view/macro:page/<layout>"
+
+in the root element. The template provides common layout to Launchpad.
+"""
+
+__metaclass__ = type
+
+from BeautifulSoup import BeautifulSoup
+
+from z3c.ptcompat import ViewPageTemplateFile
+
+from canonical.launchpad.webapp.publisher import LaunchpadView
+from canonical.launchpad.webapp.servers import LaunchpadTestRequest
+from canonical.testing.layers import DatabaseFunctionalLayer
+from canonical.launchpad.testing.pages import find_tag_by_id
+
+from lp.testing import TestCaseWithFactory
+
+
+class TestBaseLayout(TestCaseWithFactory):
+    """Test for the ILaunchpadRoot permission"""
+    layer = DatabaseFunctionalLayer
+
+    def setUp(self):
+        super(TestBaseLayout, self).setUp()
+        self.user = self.factory.makePerson(name='waffles')
+        self.request = LaunchpadTestRequest(
+            SERVER_URL='http://launchpad.dev',
+            PATH_INFO='/~waffles/+layout')
+        self.request.setPrincipal(self.user)
+
+    def makeTemplateView(self, layout):
+        """Return a view that uses the specified layout."""
+
+        class TemplateView(LaunchpadView):
+            """A simple view to test base-layout."""
+            __launchpad_facetname__ = 'overview'
+            template = ViewPageTemplateFile(
+                'testfiles/%s.pt' % layout.replace('_', '-'))
+            page_title = 'Test base-layout: %s' % layout
+
+        return TemplateView(self.user, self.request)
+
+    def test_base_layout_doctype(self):
+        # Verify that the document is a html DOCTYPE.
+        view = self.makeTemplateView('main_side')
+        markup = view()
+        self.assertTrue(markup.startswith('<!DOCTYPE html'))
+
+    def verify_base_layout_html_element(self, content):
+        # The html element states the namespace and language information.
+        self.assertEqual(
+            'http://www.w3.org/1999/xhtml', content.html['xmlns'])
+        html_tag = content.html
+        self.assertEqual('en', html_tag['xml:lang'])
+        self.assertEqual('en', html_tag['lang'])
+        self.assertEqual('ltr', html_tag['dir'])
+
+    def verify_base_layout_head_parts(self, view, content):
+        # Verify the common head parts of every layout.
+        head = content.head
+        # The page's title starts with the view's page_title.
+        self.assertTrue(head.title.string.startswith(view.page_title))
+        # The shortcut icon for the browser chrome is provided.
+        link_tag = head.link
+        self.assertEqual('shortcut icon', link_tag['rel'])
+        self.assertEqual('/@@/launchpad.png', link_tag['href'])
+        # The template loads the common scripts.
+        load_script = find_tag_by_id(head, 'base-layout-load-scripts').name
+        self.assertEqual('script', load_script)
+
+    def verify_base_layout_body_parts(self, document):
+        # Verify the common body parts of every layout.
+        self.assertEqual('body', document.name)
+        yui_layout = document.find('div', 'yui-d0')
+        self.assertTrue(yui_layout is not None)
+        self.assertEqual(
+            'login-logout', yui_layout.find(True, id='locationbar')['class'])
+        self.assertEqual(
+            'yui-main', yui_layout.find(True, id='maincontent')['class'])
+        self.assertEqual(
+            'invisible', document.find(True, id='help-pane')['class'])
+        self.assertEqual(
+            'footer', yui_layout.find(True, id='footer')['class'])
+
+    def verify_watermark(self, document):
+        # Verify the parts of a watermark.
+        yui_layout = document.find('div', 'yui-d0')
+        watermark = yui_layout.find(True, id='watermark')
+        self.assertEqual('watermark-apps-portlet', watermark['class'])
+        self.assertEqual('/@@/person-logo', watermark.img['src'])
+        self.assertEqual('Waffles', watermark.h2.string)
+        self.assertEqual('facetmenu', watermark.ul['class'])
+
+    def test_main_side(self):
+        # The main_side layout has everything.
+        view = self.makeTemplateView('main_side')
+        content = BeautifulSoup(view())
+        self.verify_base_layout_html_element(content)
+        self.verify_base_layout_head_parts(view, content)
+        document = find_tag_by_id(content, 'document')
+        self.verify_base_layout_body_parts(document)
+        classes = 'tab-overview main_side public yui-skin-sam'.split()
+        self.assertEqual(classes, document['class'].split())
+        self.verify_watermark(document)
+        self.assertEqual(
+            'yui-b side', document.find(True, id='side-portlets')['class'])
+        self.assertEqual('form', document.find(True, id='globalsearch').name)
+
+    def test_main_only(self):
+        # The main_only layout has everything except side portlets.
+        view = self.makeTemplateView('main_only')
+        content = BeautifulSoup(view())
+        self.verify_base_layout_html_element(content)
+        self.verify_base_layout_head_parts(view, content)
+        document = find_tag_by_id(content, 'document')
+        self.verify_base_layout_body_parts(document)
+        classes = 'tab-overview main_only public yui-skin-sam'.split()
+        self.assertEqual(classes, document['class'].split())
+        self.verify_watermark(document)
+        self.assertEqual(
+            'registering', document.find(True, id='registration')['class'])
+        self.assertEqual(None, document.find(True, id='side-portlets'))
+        self.assertEqual('form', document.find(True, id='globalsearch').name)
+
+    def test_searchless(self):
+        # The searchless layout is missing side portlets and search.
+        view = self.makeTemplateView('searchless')
+        content = BeautifulSoup(view())
+        self.verify_base_layout_html_element(content)
+        self.verify_base_layout_head_parts(view, content)
+        document = find_tag_by_id(content, 'document')
+        self.verify_base_layout_body_parts(document)
+        self.verify_watermark(document)
+        classes = 'tab-overview searchless public yui-skin-sam'.split()
+        self.assertEqual(classes, document['class'].split())
+        self.assertEqual(
+            'registering', document.find(True, id='registration')['class'])
+        self.assertEqual(None, document.find(True, id='side-portlets'))
+        self.assertEqual(None, document.find(True, id='globalsearch'))
+
+    def test_locationless(self):
+        # The locationless layout has no optional content.
+        view = self.makeTemplateView('locationless')
+        content = BeautifulSoup(view())
+        self.verify_base_layout_html_element(content)
+        self.verify_base_layout_head_parts(view, content)
+        document = find_tag_by_id(content, 'document')
+        self.verify_base_layout_body_parts(document)
+        classes = 'tab-overview locationless public yui-skin-sam'.split()
+        self.assertEqual(classes, document['class'].split())
+        self.assertEqual(None, document.find(True, id='registration'))
+        self.assertEqual(None, document.find(True, id='watermark'))
+        self.assertEqual(None, document.find(True, id='side-portlets'))
+        self.assertEqual(None, document.find(True, id='globalsearch'))

=== modified file 'lib/lp/app/templates/base-layout-macros.pt'
--- lib/lp/app/templates/base-layout-macros.pt	2010-07-14 14:38:07 +0000
+++ lib/lp/app/templates/base-layout-macros.pt	2010-07-23 15:26:51 +0000
@@ -288,7 +288,7 @@
 
   <metal:load-lavascript use-macro="context/@@+base-layout-macros/load-javascript" />
 
-  <script type="text/javascript">
+  <script id="base-layout-load-scripts" type="text/javascript">
     LPS.use('node', 'lp', function(Y) {
         Y.on('load', function(e) {
             sortables_init();

=== modified file 'lib/lp/app/templates/base-layout.pt'
--- lib/lp/app/templates/base-layout.pt	2010-07-02 18:35:03 +0000
+++ lib/lp/app/templates/base-layout.pt	2010-07-23 15:26:51 +0000
@@ -83,21 +83,22 @@
           })();
         </script>
     <div class="yui-d0">
-      <div id="locationbar">
+      <div id="locationbar" class="login-logout">
         <tal:login replace="structure context/@@login_status" />
       </div><!--id="locationbar"-->
 
-      <div class="watermark-apps-portlet top-portlet"
+      <div id="watermark" class="watermark-apps-portlet"
            tal:condition="view/macro:pagehas/applicationtabs">
-        <span tal:replace="structure view/watermark:logo"></span>
-        <h2 tal:replace="structure view/watermark:heading">
-          Celso Providelo
-        </h2>
-        <div id="registration" class="registering">
-          <metal:registering define-slot="registering" />
-        </div>
-        <metal:heading_nav
-          use-macro="context/@@+base-layout-macros/application-buttons"/>
+        <div class="flowed-block">
+          <span tal:replace="structure view/watermark:logo"></span>
+        </div>
+        <div class="flowed-block wide">
+          <h2 tal:replace="structure view/watermark:heading">
+            Celso Providelo
+          </h2>
+          <metal:heading_nav
+            use-macro="context/@@+base-layout-macros/application-buttons"/>
+        </div>
       </div>
 
       <div class="yui-t4"
@@ -108,13 +109,17 @@
               lang view/lang|default_language|default;
               xml:lang view/lang|default_language|default;
               dir view/dir|string:ltr">
-            <div tal:condition="view/macro:pagehas/applicationtabs">
+            <div class="context-publication"
+              tal:condition="view/macro:pagehas/applicationtabs">
               <h1
                 tal:condition="view/label|nothing"
                 tal:content="view/label"
                 metal:define-slot="heading"
                 >Page Label
               </h1>
+              <div id="registration" class="registering">
+                <metal:registering define-slot="registering" />
+              </div>
               <tal:breadcrumbs replace="structure context/@@+hierarchy">
                 ProjectName > Branches > Merge Proposals > fix-for-navigation
               </tal:breadcrumbs>
@@ -132,7 +137,7 @@
           </div><!-- yui-b -->
         </div><!-- yui-main -->
 
-        <div class="yui-b side"
+        <div id="side-portlets" class="yui-b side"
           tal:condition="view/macro:pagehas/portlets">
           <metal:portlets define-slot="side" />
         </div><!-- yui-b side -->

=== modified file 'lib/lp/app/templates/launchpad-hierarchy.pt'
--- lib/lp/app/templates/launchpad-hierarchy.pt	2010-01-22 17:28:32 +0000
+++ lib/lp/app/templates/launchpad-hierarchy.pt	2010-07-23 15:26:51 +0000
@@ -3,13 +3,13 @@
   xmlns:tal="http://xml.zope.org/namespaces/tal";
   xmlns:metal="http://xml.zope.org/namespaces/metal";
   xmlns:i18n="http://xml.zope.org/namespaces/i18n";
-  i18n:domain="launchpad">
+  i18n:domain="launchpad"
+  tal:condition="view/display_breadcrumbs">
 
-<tal:breadcrumbs repeat="breadcrumb view/items"
-                 condition="view/display_breadcrumbs">
+<tal:breadcrumbs repeat="breadcrumb view/items">
   <li>
     <a tal:attributes="href breadcrumb/url"
-      tal:omit-tag="repeat/breadcrumb/end"><tal:text 
+      tal:omit-tag="repeat/breadcrumb/end"><tal:text
         condition="not: repeat/breadcrumb/end"
         replace="breadcrumb/text">
           Bugs on redfish</tal:text><tal:text

=== modified file 'lib/lp/bugs/stories/bugs/xx-bug-heat-on-bug-page.txt'
--- lib/lp/bugs/stories/bugs/xx-bug-heat-on-bug-page.txt	2010-03-15 13:22:02 +0000
+++ lib/lp/bugs/stories/bugs/xx-bug-heat-on-bug-page.txt	2010-07-23 15:26:51 +0000
@@ -3,8 +3,8 @@
 The bug heat appears on the bug index page as four flames.
 
     >>> anon_browser.open('http://bugs.launchpad.dev/firefox/+bug/1')
-    >>> print find_tag_by_id(
-    ...     anon_browser.contents, 'registration').fetch('img')[0]
+    >>> print find_main_content(
+    ...     anon_browser.contents).find('img', src='/@@/bug-heat-0.png')
     <img src="/@@/bug-heat-0.png" alt="0 out of 4 heat flames" title="Heat: 0" />
 
 Packages use their distribution as context when generating flame icons
@@ -30,6 +30,6 @@
     >>> logout()
 
     >>> anon_browser.open(canonical_url(dsp_bug))
-    >>> print find_tag_by_id(
-    ...     anon_browser.contents, 'registration').fetch('img')[0]
+    >>> print find_main_content(
+    ...     anon_browser.contents).find('img', src='/@@/bug-heat-0.png')
     <img src="/@@/bug-heat-0.png" alt="0 out of 4 heat flames" title="Heat: 1250" />

=== modified file 'lib/lp/bugs/templates/bugtask-index.pt'
--- lib/lp/bugs/templates/bugtask-index.pt	2010-07-16 16:14:39 +0000
+++ lib/lp/bugs/templates/bugtask-index.pt	2010-07-23 15:26:51 +0000
@@ -43,12 +43,11 @@
     </metal:side>
 
     <tal:registering metal:fill-slot="registering">
-      Bug #<tal:block content="context/bug/id"/> reported by
+      Reported by
       <tal:reporter replace="structure context/bug/owner/fmt:link" />
       <span
         tal:attributes="title context/bug/datecreated/fmt:datetime"
         tal:content="context/bug/datecreated/fmt:displaydate" />
-      <tal:heat replace="structure view/bug_heat_html" />
     </tal:registering>
 
     <metal:heading fill-slot="heading" tal:define="context_menu context/menu:context">
@@ -92,6 +91,10 @@
         </tal:XXX>
       </p>
 
+      <div style="float: right;">
+        <tal:heat replace="structure view/bug_heat_html" />
+      </div>
+
       <div tal:replace="structure context/bug/@@+bugtasks-and-nominations-table" />
 
       <div id="maincontentsub">


References