Merge lp:~sinzui/launchpad/remove-main-template into lp:launchpad
- remove-main-template
- Merge into devel
Proposed by
Curtis Hovey
Status: | Merged |
---|---|
Approved by: | Aaron Bentley |
Approved revision: | not available |
Merged at revision: | not available |
Proposed branch: | lp:~sinzui/launchpad/remove-main-template |
Merge into: | lp:launchpad |
Diff against target: |
939 lines (+49/-535) 21 files modified
lib/canonical/launchpad/doc/tales-macro.txt (+3/-32) lib/canonical/launchpad/doc/zcmldirectives.txt (+2/-2) lib/canonical/launchpad/icing/style.css (+0/-1) lib/canonical/launchpad/pagetitles.py (+0/-9) lib/canonical/launchpad/templates/launchpad-forgottenpassword.pt (+1/-2) lib/canonical/launchpad/templates/main-template-macros.pt (+0/-33) lib/canonical/launchpad/templates/main-template.pt (+0/-308) lib/canonical/launchpad/webapp/login.py (+1/-0) lib/canonical/launchpad/webapp/tales.py (+5/-99) lib/canonical/launchpad/zcml/launchpad.zcml (+0/-18) lib/canonical/widgets/location.py (+1/-1) lib/lp/app/browser/configure.zcml (+6/-0) lib/lp/app/templates/base-layout-macros.pt (+1/-2) lib/lp/registry/browser/productrelease.py (+1/-1) lib/lp/registry/browser/team.py (+1/-1) lib/lp/registry/templates/object-timeline-graph.pt (+3/-3) lib/lp/services/openid/browser/configure.zcml (+1/-0) lib/lp/services/openid/browser/openidrpconfig.py (+18/-0) lib/lp/services/openid/templates/openidrpconfig-add.pt (+2/-10) lib/lp/services/openid/templates/openidrpconfig-edit.pt (+2/-10) lib/lp/services/openid/templates/openidrpconfigset-index.pt (+1/-3) |
To merge this branch: | bzr merge lp:~sinzui/launchpad/remove-main-template |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Aaron Bentley (community) | Approve | ||
Review via email: mp+15165@code.launchpad.net |
Commit message
Description of the change
To post a comment you must log in.
Revision history for this message
Curtis Hovey (sinzui) wrote : | # |
Revision history for this message
Aaron Bentley (abentley) wrote : | # |
Looks good, thanks!
review:
Approve
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'lib/canonical/launchpad/doc/tales-macro.txt' |
2 | --- lib/canonical/launchpad/doc/tales-macro.txt 2009-10-21 18:42:52 +0000 |
3 | +++ lib/canonical/launchpad/doc/tales-macro.txt 2009-11-23 17:20:28 +0000 |
4 | @@ -12,20 +12,20 @@ |
5 | layout it's using. The following METAL fragment illustrates the way it's |
6 | usually done: |
7 | |
8 | - <html metal:use-macro="view/macro:page/default" /> |
9 | + <html metal:use-macro="view/macro:page/main_side" /> |
10 | |
11 | |
12 | >>> from canonical.launchpad.ftests import test_tales |
13 | >>> view = FakeView() |
14 | |
15 | # Return value is the compiled macro expression. |
16 | - >>> test_tales('view/macro:page/default', view=view) |
17 | + >>> test_tales('view/macro:page/main_side', view=view) |
18 | [('version', ...] |
19 | |
20 | The pagetype is registered in the __pagetype__ attribute. |
21 | |
22 | >>> view.__pagetype__ |
23 | - 'default' |
24 | + 'main_side' |
25 | |
26 | If the pagetype isn't defined, a LocationError is raised. |
27 | |
28 | @@ -43,35 +43,6 @@ |
29 | >>> test_tales('view/macro:pagehas/portlets', view=view) |
30 | True |
31 | |
32 | - >>> test_tales('view/macro:pagehas/actionsmenu', view=view) |
33 | - True |
34 | - |
35 | - >>> test_tales('view/macro:pagehas/heading', view=view) |
36 | - False |
37 | - |
38 | - |
39 | -The actions menu is deprecated. Some of the links are moved inline, |
40 | -others are shown as navigation tabs. The navigationtabs page feature |
41 | -controls that aspect. Two layouts show these, default2.0 and onecolumn. |
42 | - |
43 | - >>> from canonical.launchpad.webapp.tales import PageMacroDispatcher |
44 | - >>> for layout in sorted(PageMacroDispatcher._pagetypes): |
45 | - ... view = FakeView() |
46 | - ... macro = test_tales('view/macro:page/%s' % layout, view=view) |
47 | - ... if test_tales('view/macro:pagehas/navigationtabs', view=view): |
48 | - ... print layout |
49 | - default2.0 |
50 | - onecolumn |
51 | - |
52 | -These two layouts have the actionsmenu turned off. |
53 | - |
54 | - >>> macro = test_tales('view/macro:page/default2.0', view=view) |
55 | - >>> test_tales('view/macro:pagehas/actionsmenu', view=view) |
56 | - False |
57 | - |
58 | - >>> macro = test_tales('view/macro:page/onecolumn', view=view) |
59 | - >>> test_tales('view/macro:pagehas/actionsmenu', view=view) |
60 | - False |
61 | |
62 | The 'macro:isbetauser' can be used to safely try to determine if the |
63 | current user is a beta user. It works for views that provide |
64 | |
65 | === modified file 'lib/canonical/launchpad/doc/zcmldirectives.txt' |
66 | --- lib/canonical/launchpad/doc/zcmldirectives.txt 2009-10-21 19:35:40 +0000 |
67 | +++ lib/canonical/launchpad/doc/zcmldirectives.txt 2009-11-23 17:20:28 +0000 |
68 | @@ -151,7 +151,7 @@ |
69 | ... for="canonical.launchpad.ftests.IFoo" |
70 | ... name="+mandrill" |
71 | ... permission="zope.Public" |
72 | - ... template="templates/main-template.pt" |
73 | + ... template="../../lp/app/templates/base-layout.pt" |
74 | ... facet="another-mister-lizard" |
75 | ... layer="canonical.launchpad.ftests.IFooLayer" |
76 | ... /> |
77 | @@ -169,7 +169,7 @@ |
78 | ... (fooobject, request), name='+mandrill') |
79 | |
80 | >>> print mandrill_view.__class__.__name__ |
81 | - SimpleViewClass from ...main-template.pt |
82 | + SimpleViewClass from ...base-layout.pt |
83 | >>> print mandrill_view.__launchpad_facetname__ |
84 | another-mister-lizard |
85 | |
86 | |
87 | === modified file 'lib/canonical/launchpad/icing/style.css' |
88 | --- lib/canonical/launchpad/icing/style.css 2009-11-15 23:14:57 +0000 |
89 | +++ lib/canonical/launchpad/icing/style.css 2009-11-23 17:20:28 +0000 |
90 | @@ -607,7 +607,6 @@ |
91 | float: left; |
92 | width: 16.16%; /* = (100% / 6) - 0.5% left over */ |
93 | margin: 0 0.25%; /* = the leftover 0.5%, half each on the left and right */ |
94 | - /* This is overridden in main-template.pt for Internet Explorer */ |
95 | padding: 0; |
96 | text-align: center; |
97 | color: #333; |
98 | |
99 | === modified file 'lib/canonical/launchpad/pagetitles.py' |
100 | --- lib/canonical/launchpad/pagetitles.py 2009-11-18 11:52:25 +0000 |
101 | +++ lib/canonical/launchpad/pagetitles.py 2009-11-23 17:20:28 +0000 |
102 | @@ -394,8 +394,6 @@ |
103 | |
104 | launchpad_forbidden = 'Forbidden' |
105 | |
106 | -launchpad_forgottenpassword = 'Need a new Launchpad password?' |
107 | - |
108 | # launchpad_css is a css file |
109 | |
110 | # launchpad_js is standard javascript |
111 | @@ -516,13 +514,6 @@ |
112 | """Return the page title to the invalid identity page.""" |
113 | return 'Invalid OpenID identity %s' % view.openid_request.identity |
114 | |
115 | -openidrpconfig_add = 'Add an OpenID Relying Party Configuration' |
116 | - |
117 | -openidrpconfig_edit = ContextDisplayName( |
118 | - 'Edit Relying Party Configuration for %s') |
119 | - |
120 | -openidrpconfigset_index = 'OpenID Relying Party Configurations' |
121 | - |
122 | def package_bugs(context, view): |
123 | """Return the page title bug in a package.""" |
124 | return 'Bugs in %s' % context.name |
125 | |
126 | === modified file 'lib/canonical/launchpad/templates/launchpad-forgottenpassword.pt' |
127 | --- lib/canonical/launchpad/templates/launchpad-forgottenpassword.pt 2009-10-20 11:29:26 +0000 |
128 | +++ lib/canonical/launchpad/templates/launchpad-forgottenpassword.pt 2009-11-23 17:20:28 +0000 |
129 | @@ -5,8 +5,7 @@ |
130 | omit-tag=""> |
131 | <tal:do-this-first tal:content="view/process_form" /> |
132 | <html |
133 | - metal:use-macro="context/@@main_template/master" |
134 | -> |
135 | + metal:use-macro="view/macro:page/main_only"> |
136 | <head metal:fill-slot="head_epilogue"> |
137 | <meta name="robots" content="noindex" /> |
138 | </head> |
139 | |
140 | === removed file 'lib/canonical/launchpad/templates/main-template-macros.pt' |
141 | --- lib/canonical/launchpad/templates/main-template-macros.pt 2009-07-17 17:59:07 +0000 |
142 | +++ lib/canonical/launchpad/templates/main-template-macros.pt 1970-01-01 00:00:00 +0000 |
143 | @@ -1,33 +0,0 @@ |
144 | -<macros |
145 | - xmlns="http://www.w3.org/1999/xhtml" |
146 | - xmlns:tal="http://xml.zope.org/namespaces/tal" |
147 | - xmlns:metal="http://xml.zope.org/namespaces/metal" |
148 | - xmlns:i18n="http://xml.zope.org/namespaces/i18n" |
149 | - i18n:domain="launchpad" |
150 | - tal:omit-tag="" |
151 | -> |
152 | - <metal:notifications define-macro="notifications"> |
153 | - <metal:base-notifications |
154 | - use-macro="context/@@+base-layout-macros/notifications" /> |
155 | - </metal:notifications> |
156 | - |
157 | - <metal:load-javascript define-macro="load-javascript"> |
158 | - <metal:base-load-javascript |
159 | - use-macro="context/@@+base-layout-macros/load-javascript" /> |
160 | - </metal:load-javascript> |
161 | - |
162 | - <metal:page-javascript define-macro="page-javascript"> |
163 | - <metal:base-page-javascript |
164 | - use-macro="context/@@+base-layout-macros/page-javascript" /> |
165 | - </metal:page-javascript> |
166 | - |
167 | - <metal:launchpad-stylesheet define-macro="launchpad-stylesheet"> |
168 | - <metal:base-launchpad-stylesheet |
169 | - use-macro="context/@@+base-layout-macros/launchpad-stylesheet" /> |
170 | - </metal:launchpad-stylesheet> |
171 | - |
172 | - <metal:lp-client-cache define-macro="lp-client-cache"> |
173 | - <metal:base-lp-client-cache |
174 | - use-macro="context/@@+base-layout-macros/lp-client-cache" /> |
175 | - </metal:lp-client-cache> |
176 | -</macros> |
177 | |
178 | === removed file 'lib/canonical/launchpad/templates/main-template.pt' |
179 | --- lib/canonical/launchpad/templates/main-template.pt 2009-09-15 17:30:59 +0000 |
180 | +++ lib/canonical/launchpad/templates/main-template.pt 1970-01-01 00:00:00 +0000 |
181 | @@ -1,308 +0,0 @@ |
182 | -<metal:page |
183 | - xmlns:metal="http://xml.zope.org/namespaces/metal" |
184 | - xmlns:tal="http://xml.zope.org/namespaces/tal" |
185 | - define-macro="master" |
186 | - tal:define=" |
187 | - revno modules/canonical.launchpad.versioninfo/revno | string:unknown; |
188 | - version string:Launchpad 2.2.6 (r${revno}); |
189 | - " |
190 | -><metal:doctype define-slot="doctype"><tal:doctype tal:replace="structure string:<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">" /></metal:doctype> |
191 | -<metal:block define-slot="top_slot" /> |
192 | -<html |
193 | - xmlns="http://www.w3.org/1999/xhtml" |
194 | - xmlns:tal="http://xml.zope.org/namespaces/tal" |
195 | - xmlns:metal="http://xml.zope.org/namespaces/metal" |
196 | - xmlns:i18n="http://xml.zope.org/namespaces/i18n" |
197 | - xml:lang="en" |
198 | - lang="en" |
199 | - dir="ltr" |
200 | - tal:attributes="lang view/lang|default_language|default; |
201 | - xml:lang view/lang|default_language|default; |
202 | - dir view/dir|string:ltr" |
203 | - tal:define=" |
204 | - rooturl modules/canonical.launchpad.webapp.vhosts/allvhosts/configs/mainsite/rooturl; |
205 | - icingroot string:${rooturl}+icing/rev${revno}; |
206 | - icingroot_contrib string:${rooturl}+icing-contrib/rev${revno}; |
207 | - devmode modules/canonical.config/config/devmode; |
208 | - is_demo modules/canonical.config/config/launchpad/is_demo; |
209 | - is_edge modules/canonical.config/config/launchpad/is_edge; |
210 | - is_lpnet modules/canonical.config/config/launchpad/is_lpnet; |
211 | - site_message modules/canonical.config/config/launchpad/site_message; |
212 | - CONTEXTS python:{'template':template, 'context': context, 'view':view}; |
213 | - " |
214 | -> |
215 | - <head tal:define="yui string:${icingroot}/yui/3.0.0pr2/build; |
216 | - lazr_js string:${icingroot}/lazr/build; |
217 | - lp_js string:${icingroot}/build" |
218 | - > |
219 | - <title tal:content="CONTEXTS/fmt:pagetitle" i18n:translate="">Launchpad</title> |
220 | - <tal:atomfeeds condition="view/feed_links | nothing"> |
221 | - <tal:loop repeat="link view/feed_links"> |
222 | - <link rel="alternate" type="application/atom+xml" href="" title="" |
223 | - tal:attributes="title link/title; |
224 | - href link/href"/> |
225 | - </tal:loop> |
226 | - </tal:atomfeeds> |
227 | - |
228 | - <!-- Launchpad style sheet --> |
229 | - <metal:launchpad-stylesheet |
230 | - use-macro="context/@@+main-template-macros/launchpad-stylesheet" /> |
231 | - |
232 | - <style tal:condition="is_demo" type="text/css" |
233 | - >html, body {background-image: url(/@@/demo) !important;}</style> |
234 | - <tal:comment condition="nothing"> |
235 | - Internet Explorer apparently doubles the horizontal margins of the |
236 | - application tabs, which causes the 'Answers' tab to wrap onto a second |
237 | - row. To work around this, we give IE some speshul CSS: |
238 | - </tal:comment> |
239 | - <!--[if lte IE 7]> |
240 | - <style type="text/css">#lp-apps span {margin: 0 0.125%;}</style> |
241 | - <![endif]--> |
242 | - <tal:comment condition="nothing"> |
243 | - This CSS collapses the contents of collapsible fieldsets, |
244 | - without the flashing that would result from doing it in JavaScript. |
245 | - activateCollapsibles() removes the class="collapsed" from fieldsets, to |
246 | - re-show their divs, once the children themselves have been collapsed. |
247 | - </tal:comment> |
248 | - <style type="text/css"> |
249 | - fieldset.collapsed div, fieldset div.collapsed {display: none;} |
250 | - </style> |
251 | - <noscript> |
252 | - <style type="text/css"> |
253 | - fieldset.collapsible div, fieldset div.collapsed {display: block;} |
254 | - </style> |
255 | - </noscript> |
256 | - |
257 | - <metal:page-javascript |
258 | - use-macro="context/@@+main-template-macros/page-javascript" /> |
259 | - |
260 | - <link rel="shortcut icon" href="/@@/launchpad.png" /> |
261 | - <metal:block define-slot="head_epilogue"></metal:block> |
262 | - </head> |
263 | - <body |
264 | - id="document" |
265 | - tal:attributes="class string:tab-${view/menu:selectedfacetname} ${view/macro:pagetype} yui-skin-sam" |
266 | - > |
267 | - <div id="locationbar"> |
268 | - <tal:login replace="structure context/@@login_status" /> |
269 | - <form |
270 | - tal:condition="view/macro:pagehas/globalsearch" |
271 | - id="globalsearch" |
272 | - action="" |
273 | - xml:lang="en" lang="en" dir="ltr" |
274 | - method="get" |
275 | - accept-charset="UTF-8" |
276 | - tal:attributes="action string:${rooturl}+search" |
277 | - class="sprite search-icon" |
278 | - > |
279 | - <input type="search" id="search-text" name="field.text" /> |
280 | - </form> |
281 | - <tal:hierarchy replace="structure context/@@+hierarchy" /> |
282 | - <div |
283 | - tal:condition="view/macro:pagehas/applicationtabs" |
284 | - tal:define="facetmenu view/menu:facet" |
285 | - id="lp-apps" |
286 | - class="clearfix" |
287 | - > |
288 | - <tal:XXX replace="nothing"> |
289 | - # XXX mpt 2008-07-02 bug=229931: The HTML comment works. |
290 | - </tal:XXX> |
291 | - <!-- :-) --><tal:facet repeat="link facetmenu"> |
292 | - <span |
293 | - tal:condition="python: link.enabled and link.selected" |
294 | - tal:attributes="title link/summary; class string:${link/name} active" |
295 | - ><strong |
296 | - tal:condition="not:link/linked" |
297 | - tal:content="structure link/escapedtext" |
298 | - /><a |
299 | - tal:condition="link/linked" |
300 | - tal:attributes="href link/url" |
301 | - tal:content="structure link/escapedtext" |
302 | - /></span><span |
303 | - tal:condition="python: link.enabled and not link.selected" |
304 | - tal:attributes="title link/summary; class link/name" |
305 | - ><a |
306 | - tal:condition="link/enabled" |
307 | - tal:attributes="href link/url" |
308 | - tal:content="structure link/escapedtext" |
309 | - /></span><span |
310 | - tal:condition="not:link/enabled" |
311 | - tal:attributes="class string:${link/name} disabled-tab" |
312 | - ><strong |
313 | - tal:content="structure link/escapedtext" |
314 | - /></span><small tal:condition="not:repeat/link/end" |
315 | - > / </small></tal:facet> |
316 | - </div> |
317 | - |
318 | - </div><!--id="locationbar"--> |
319 | - |
320 | - <tal:maintenance replace="structure context/@@+maintenancemessage" /> |
321 | - <h1 metal:define-slot="heading" |
322 | - tal:condition="view/macro:pagehas/applicationbuttons" /> |
323 | - <div tal:condition="view/macro:pagehas/applicationborder" id="mainarea"> |
324 | - <div id="container"> |
325 | - <!--[if IE 7]> <![endif]--> |
326 | - <tal:XXX condition="nothing"> |
327 | - # XXX mpt 2008-07-16 bug=249032: This conditional comment should |
328 | - # not be necessary. |
329 | - </tal:XXX> |
330 | - |
331 | - <tal:noportlets |
332 | - condition="not: view/macro:pagehas/portlets" |
333 | - > |
334 | - <tal:notifications |
335 | - define="notifications request/notifications" |
336 | - condition="notifications" |
337 | - > |
338 | - <metal:notifications |
339 | - use-macro= |
340 | - "context/@@+main-template-macros/notifications" |
341 | - /> |
342 | - </tal:notifications> |
343 | - </tal:noportlets> |
344 | - <metal:block define-slot="before_nav_menu"/> |
345 | - <div id="navigation-tabs" |
346 | - tal:condition="view/macro:pagehas/navigationtabs"> |
347 | - <div id="context-navigation-tabs" |
348 | - tal:condition="context/menu:navigation"> |
349 | - <tal:menu |
350 | - replace="structure context/@@+navigationmenutabs" |
351 | - /> |
352 | - </div> |
353 | - <div id="view-navigation-tabs" |
354 | - tal:condition="view/menu:navigation"> |
355 | - <tal:menu |
356 | - replace="structure view/@@+navigationmenutabs" |
357 | - /> |
358 | - </div> |
359 | - </div> |
360 | - <tal:noportlets condition="not: view/macro:pagehas/portlets"> |
361 | - <metal:block define-slot="main" /> |
362 | - </tal:noportlets> |
363 | - <div |
364 | - id="maincontent" |
365 | - tal:condition="view/macro:pagehas/portlets" |
366 | - > |
367 | - <div id="nonportlets"> |
368 | - |
369 | - <div class="pageheading" |
370 | - tal:condition="view/macro:pagehas/pageheading"> |
371 | - <metal:block define-slot="pageheading"> |
372 | - <tal:XXX condition="nothing"> |
373 | - # XXX Mark Shuttleworth 2007-04-30: Obsolete |
374 | - </tal:XXX> |
375 | - </metal:block> |
376 | - </div> |
377 | - <tal:notifications |
378 | - define="notifications request/notifications" |
379 | - condition="notifications" |
380 | - ><metal:notifications |
381 | - use-macro="context/@@+main-template-macros/notifications" /> |
382 | - </tal:notifications> |
383 | - <metal:block define-slot="main" /> |
384 | - |
385 | - </div> |
386 | - </div> |
387 | - <div |
388 | - id="portlets" xml:lang="en" lang="en" dir="ltr" |
389 | - tal:condition="view/macro:pagehas/portlets" |
390 | - > |
391 | - <tal:menu condition="view/macro:pagehas/actionsmenu" |
392 | - replace="structure view/@@+menubox" /> |
393 | - <metal:portlets define-slot="portlets" /> |
394 | - <metal:portlets define-slot="portlets_two" /> |
395 | - <metal:portlets define-slot="portlets_one" /> |
396 | - </div> |
397 | - <div class="clear"></div> |
398 | - |
399 | - </div><!--id="container"--> |
400 | - </div><!--id="mainarea"--> |
401 | - <tal:noborder condition="not:view/macro:pagehas/applicationborder"> |
402 | - <tal:notifications |
403 | - define="notifications request/notifications" |
404 | - condition="notifications" |
405 | - ><metal:notifications |
406 | - use-macro="context/@@+main-template-macros/notifications" /> |
407 | - </tal:notifications> |
408 | - <metal:block define-slot="main" /> |
409 | - </tal:noborder> |
410 | - <div id="globalfooter" class="clearfix" xml:lang="en" lang="en" dir="ltr"> |
411 | - <div id="colophon"> |
412 | - <a tal:condition="not:request/lp:person" href="/+tour" |
413 | - >What is Launchpad?</a> |
414 | - <a tal:condition="request/lp:person" href="/feedback" |
415 | - >Contact us</a> | <a href="https://help.launchpad.net/">Get help with Launchpad</a> |
416 | - </div> |
417 | - |
418 | - <metal:site-message |
419 | - use-macro="context/@@+base-layout-macros/site-message"/> |
420 | - |
421 | - <div id="lp-arcana"> |
422 | - © 2004-2009 <a |
423 | - href="http://canonical.com/">Canonical Ltd.</a> |
424 | - | |
425 | - <a href="/legal">Terms of use</a> |
426 | - <span tal:condition="not:is_lpnet" id="lp-version"> |
427 | - | |
428 | - <a |
429 | - href="https://help.launchpad.net/LaunchpadReleases" |
430 | - tal:content="version" |
431 | - /> |
432 | - <tal:devmode condition="devmode">devmode</tal:devmode> |
433 | - <tal:demo condition="is_demo">demo site</tal:demo> |
434 | - <tal:edge condition="is_edge">beta site</tal:edge> |
435 | - </span> |
436 | - </div> |
437 | - <ul style="clear: both; margin-top:20px;" tal:condition="nothing"> |
438 | - <li>Facet name: |
439 | - <tal:block tal:replace="view/menu:selectedfacetname" /> |
440 | - </li> |
441 | - <li>Page type: |
442 | - <tal:pagetype replace="view/macro:pagetype" /> |
443 | - </li> |
444 | - <li>Has portlet column: |
445 | - <span tal:replace="view/macro:pagehas/portlets" /> |
446 | - </li> |
447 | - <li>Has application tabs: |
448 | - <span tal:replace="view/macro:pagehas/applicationtabs" /> |
449 | - </li> |
450 | - <li>Has application border: |
451 | - <span tal:replace="view/macro:pagehas/applicationborder" /> |
452 | - </li> |
453 | - <li>Has application buttons: |
454 | - <span tal:replace="view/macro:pagehas/applicationbuttons" /> |
455 | - </li> |
456 | - <li>Has heading: |
457 | - <span tal:replace="view/macro:pagehas/heading" /> |
458 | - </li> |
459 | - </ul> |
460 | - </div><!--id="globalfooter"--> |
461 | - |
462 | - <div id="help-pane" class="invisible"> |
463 | - <div id="help-body"> |
464 | - <tal:XXX condition="nothing"> |
465 | - # XXX mars 2008-11-07 bug=295254: |
466 | - # We use this ugly src="" hack to get rid of an IE6 security |
467 | - # warning. See bug #295234. |
468 | - </tal:XXX> |
469 | - <iframe |
470 | - id="help-pane-content" |
471 | - class="invisible" |
472 | - src="javascript:void(0);"></iframe> |
473 | - </div> |
474 | - <div id="help-footer"> |
475 | - <span id="help-close"></span> |
476 | - </div> |
477 | - </div> |
478 | - |
479 | - <metal:lp-client-cache |
480 | - use-macro="context/@@+main-template-macros/lp-client-cache" /> |
481 | - |
482 | - </body> |
483 | -</html> |
484 | -<tal:requestlog |
485 | - define="log modules/canonical.launchpad.webapp.adapter/summarize_requests" |
486 | - replace="structure string:<!-- at least ${log} -->" /> |
487 | -<tal:version replace="structure string:<!-- ${version} -->" /> |
488 | -</metal:page> |
489 | -<!-- 1-0 inprogress portlets wrong in IE/Mac --> |
490 | |
491 | === modified file 'lib/canonical/launchpad/webapp/login.py' |
492 | --- lib/canonical/launchpad/webapp/login.py 2009-10-29 18:38:51 +0000 |
493 | +++ lib/canonical/launchpad/webapp/login.py 2009-11-23 17:20:28 +0000 |
494 | @@ -550,6 +550,7 @@ |
495 | submitted = False |
496 | captcha_submission = 'captcha_submission' |
497 | captcha_hash = 'captcha_hash' |
498 | + page_title = 'Need a new Launchpad password?' |
499 | |
500 | def process_form(self): |
501 | request = self.request |
502 | |
503 | === modified file 'lib/canonical/launchpad/webapp/tales.py' |
504 | --- lib/canonical/launchpad/webapp/tales.py 2009-11-14 22:44:07 +0000 |
505 | +++ lib/canonical/launchpad/webapp/tales.py 2009-11-23 17:20:28 +0000 |
506 | @@ -2998,17 +2998,13 @@ |
507 | """Selects a macro, while storing information about page layout. |
508 | |
509 | view/macro:page |
510 | - view/macro:page/onecolumn |
511 | - view/macro:page/applicationhome |
512 | - view/macro:page/pillarindex |
513 | - view/macro:page/freeform |
514 | + view/macro:page/main_side |
515 | + view/macro:page/main_only |
516 | + view/macro:page/searchless |
517 | + view/macro:page/locationless |
518 | |
519 | view/macro:pagehas/applicationtabs |
520 | - view/macro:pagehas/applicationborder |
521 | - view/macro:pagehas/applicationbuttons |
522 | view/macro:pagehas/globalsearch |
523 | - view/macro:pagehas/heading |
524 | - view/macro:pagehas/pageheading |
525 | view/macro:pagehas/portlets |
526 | |
527 | view/macro:pagetype |
528 | @@ -3017,7 +3013,6 @@ |
529 | |
530 | implements(ITraversable) |
531 | |
532 | - master = ViewPageTemplateFile('../templates/main-template.pt') |
533 | base = ViewPageTemplateFile('../../../lp/app/templates/base-layout.pt') |
534 | |
535 | def __init__(self, context): |
536 | @@ -3054,7 +3049,7 @@ |
537 | if pagetype not in self._pagetypes: |
538 | raise TraversalError('unknown pagetype: %s' % pagetype) |
539 | self.context.__pagetype__ = pagetype |
540 | - return self._template.macros['master'] |
541 | + return self.base.macros['master'] |
542 | |
543 | def haspage(self, layoutelement): |
544 | pagetype = getattr(self.context, '__pagetype__', None) |
545 | @@ -3069,15 +3064,9 @@ |
546 | |
547 | def __init__(self, |
548 | applicationtabs=False, |
549 | - applicationborder=False, |
550 | - applicationbuttons=False, |
551 | globalsearch=False, |
552 | - heading=False, |
553 | - pageheading=True, |
554 | portlets=False, |
555 | pagetypewasset=True, |
556 | - actionsmenu=True, |
557 | - navigationtabs=False |
558 | ): |
559 | self.elements = vars() |
560 | |
561 | @@ -3085,108 +3074,25 @@ |
562 | return self.elements[name] |
563 | |
564 | _pagetypes = { |
565 | - 'unset': |
566 | - LayoutElements( |
567 | - applicationborder=True, |
568 | - applicationtabs=True, |
569 | - globalsearch=True, |
570 | - portlets=True, |
571 | - pagetypewasset=False), |
572 | - 'default': |
573 | - LayoutElements( |
574 | - applicationborder=True, |
575 | - applicationtabs=True, |
576 | - globalsearch=True, |
577 | - portlets=True), |
578 | - 'default2.0': |
579 | - LayoutElements( |
580 | - actionsmenu=False, |
581 | - applicationborder=True, |
582 | - applicationtabs=True, |
583 | - globalsearch=True, |
584 | - portlets=True, |
585 | - navigationtabs=True), |
586 | - 'onecolumn': |
587 | - LayoutElements( |
588 | - actionsmenu=False, |
589 | - applicationborder=True, |
590 | - applicationtabs=True, |
591 | - globalsearch=True, |
592 | - navigationtabs=True, |
593 | - portlets=False), |
594 | - 'applicationhome': |
595 | - LayoutElements( |
596 | - applicationborder=True, |
597 | - applicationbuttons=True, |
598 | - applicationtabs=True, |
599 | - globalsearch=True, |
600 | - pageheading=False, |
601 | - heading=True), |
602 | - 'pillarindex': |
603 | - LayoutElements( |
604 | - applicationborder=True, |
605 | - applicationbuttons=True, |
606 | - globalsearch=True, |
607 | - heading=True, |
608 | - pageheading=False, |
609 | - portlets=True), |
610 | - 'search': |
611 | - LayoutElements( |
612 | - actionsmenu=False, |
613 | - applicationborder=True, |
614 | - applicationtabs=True, |
615 | - globalsearch=False, |
616 | - heading=False, |
617 | - pageheading=False, |
618 | - portlets=False), |
619 | - 'freeform': |
620 | - LayoutElements(), |
621 | 'main_side': |
622 | LayoutElements( |
623 | - actionsmenu=False, |
624 | - applicationborder=False, |
625 | applicationtabs=True, |
626 | globalsearch=True, |
627 | - heading=False, |
628 | - pageheading=False, |
629 | portlets=True), |
630 | 'main_only': |
631 | LayoutElements( |
632 | - actionsmenu=False, |
633 | - applicationborder=False, |
634 | applicationtabs=True, |
635 | globalsearch=True, |
636 | - heading=False, |
637 | - pageheading=False, |
638 | portlets=False), |
639 | 'searchless': |
640 | LayoutElements( |
641 | - actionsmenu=False, |
642 | - applicationborder=False, |
643 | applicationtabs=True, |
644 | globalsearch=False, |
645 | - heading=False, |
646 | - pageheading=False, |
647 | portlets=False), |
648 | 'locationless': |
649 | LayoutElements(), |
650 | } |
651 | |
652 | - _3_0_pagetypes = [ |
653 | - 'main_side', |
654 | - 'main_only', |
655 | - 'searchless', |
656 | - 'locationless', |
657 | - ] |
658 | - |
659 | - @property |
660 | - def _template(self): |
661 | - """Return the ViewPageTemplateFile used by layout.""" |
662 | - if self.context.__pagetype__ in self._3_0_pagetypes: |
663 | - return self.base |
664 | - else: |
665 | - return self.master |
666 | - |
667 | |
668 | class TranslationGroupFormatterAPI(ObjectFormatterAPI): |
669 | """Adapter for `ITranslationGroup` objects to a formatted string.""" |
670 | |
671 | === modified file 'lib/canonical/launchpad/zcml/launchpad.zcml' |
672 | --- lib/canonical/launchpad/zcml/launchpad.zcml 2009-09-18 13:24:29 +0000 |
673 | +++ lib/canonical/launchpad/zcml/launchpad.zcml 2009-11-23 17:20:28 +0000 |
674 | @@ -9,17 +9,6 @@ |
675 | xmlns:xmlrpc="http://namespaces.zope.org/xmlrpc" |
676 | i18n_domain="canonical.launchpad"> |
677 | |
678 | - <!-- XXX: Steve Alexander 2004-11-24: |
679 | - yuck... registering a main template as a view for everything. |
680 | - This should be a non-published resource. |
681 | - --> |
682 | - <browser:page |
683 | - name="main_template" |
684 | - for="*" |
685 | - permission="zope.Public" |
686 | - template="../templates/main-template.pt" |
687 | - /> |
688 | - |
689 | <!-- Error pages --> |
690 | <!-- System Errors --> |
691 | <browser:page |
692 | @@ -168,13 +157,6 @@ |
693 | permission="zope.Public" |
694 | /> |
695 | |
696 | - <browser:page |
697 | - for="*" |
698 | - name="+main-template-macros" |
699 | - template="../templates/main-template-macros.pt" |
700 | - permission="zope.Public" |
701 | - /> |
702 | - |
703 | <!-- Macros for the forbidden pages; used by launchpad-forbidden.pt and |
704 | shipit-forbidden.pt, initially. --> |
705 | <browser:page |
706 | |
707 | === modified file 'lib/canonical/widgets/location.py' |
708 | --- lib/canonical/widgets/location.py 2009-06-25 05:30:52 +0000 |
709 | +++ lib/canonical/widgets/location.py 2009-11-23 17:20:28 +0000 |
710 | @@ -57,7 +57,7 @@ |
711 | def __init__(self, context, request): |
712 | # This widget makes use of javascript for googlemaps and |
713 | # json-handling, so we flag that in the request so that our |
714 | - # main-template includes the necessary javascript files. |
715 | + # base-layout includes the necessary javascript files. |
716 | request.needs_json = True |
717 | request.needs_gmap2 = True |
718 | super(LocationWidget, self).__init__(context, request) |
719 | |
720 | === modified file 'lib/lp/app/browser/configure.zcml' |
721 | --- lib/lp/app/browser/configure.zcml 2009-09-08 22:42:42 +0000 |
722 | +++ lib/lp/app/browser/configure.zcml 2009-11-23 17:20:28 +0000 |
723 | @@ -16,6 +16,12 @@ |
724 | /> |
725 | <browser:page |
726 | for="*" |
727 | + name="+main-template-macros" |
728 | + template="../templates/base-layout-macros.pt" |
729 | + permission="zope.Public" |
730 | + /> |
731 | + <browser:page |
732 | + for="*" |
733 | name="+related-pages" |
734 | class="canonical.launchpad.browser.launchpad.NavigationMenuTabs" |
735 | template="../templates/navigationmenu-related-pages.pt" |
736 | |
737 | === modified file 'lib/lp/app/templates/base-layout-macros.pt' |
738 | --- lib/lp/app/templates/base-layout-macros.pt 2009-11-10 21:49:38 +0000 |
739 | +++ lib/lp/app/templates/base-layout-macros.pt 2009-11-23 17:20:28 +0000 |
740 | @@ -271,8 +271,7 @@ |
741 | devmode modules/canonical.config/config/devmode"> |
742 | <tal:comment replace="nothing"> |
743 | This macro loads the old stylesheet, then the YUI CSS, and finally |
744 | - the new stylesheet. When no pages use main-template, this can be |
745 | - refactored. |
746 | + the new stylesheet. |
747 | </tal:comment> |
748 | <metal:old-style-sheet use-macro="context/@@+base-layout-macros/launchpad-stylesheet" /> |
749 | <link rel="stylesheet" type="text/css" |
750 | |
751 | === modified file 'lib/lp/registry/browser/productrelease.py' |
752 | --- lib/lp/registry/browser/productrelease.py 2009-09-11 16:11:43 +0000 |
753 | +++ lib/lp/registry/browser/productrelease.py 2009-11-23 17:20:28 +0000 |
754 | @@ -185,7 +185,7 @@ |
755 | |
756 | def initialize(self): |
757 | # The dynamically loaded milestone form needs this javascript |
758 | - # enabled in the main-template.pt. |
759 | + # enabled in the base-layout. |
760 | self.request.needs_datepicker_iframe = True |
761 | super(ProductReleaseFromSeriesAddView, self).initialize() |
762 | |
763 | |
764 | === modified file 'lib/lp/registry/browser/team.py' |
765 | --- lib/lp/registry/browser/team.py 2009-10-22 18:37:29 +0000 |
766 | +++ lib/lp/registry/browser/team.py 2009-11-23 17:20:28 +0000 |
767 | @@ -1013,7 +1013,7 @@ |
768 | limit = None |
769 | |
770 | def initialize(self): |
771 | - # Tell our main-template to include Google's gmap2 javascript so that |
772 | + # Tell our base-layout to include Google's gmap2 javascript so that |
773 | # we can render the map. |
774 | if self.mapped_participants_count > 0: |
775 | self.request.needs_gmap2 = True |
776 | |
777 | === modified file 'lib/lp/registry/templates/object-timeline-graph.pt' |
778 | --- lib/lp/registry/templates/object-timeline-graph.pt 2009-09-28 20:48:08 +0000 |
779 | +++ lib/lp/registry/templates/object-timeline-graph.pt 2009-11-23 17:20:28 +0000 |
780 | @@ -10,11 +10,11 @@ |
781 | > |
782 | <head> |
783 | <metal:launchpad-stylesheet |
784 | - use-macro="context/@@+main-template-macros/launchpad-stylesheet" /> |
785 | + use-macro="context/@@+base-layout-macros/launchpad-stylesheet" /> |
786 | <metal:load-javascript |
787 | - use-macro="context/@@+main-template-macros/load-javascript" /> |
788 | + use-macro="context/@@+base-layout-macros/load-javascript" /> |
789 | <metal:lp-client-cache |
790 | - use-macro="context/@@+main-template-macros/lp-client-cache" /> |
791 | + use-macro="context/@@+base-layout-macros/lp-client-cache" /> |
792 | </head> |
793 | |
794 | <body style="margin: 0; padding: 0"> |
795 | |
796 | === modified file 'lib/lp/services/openid/browser/configure.zcml' |
797 | --- lib/lp/services/openid/browser/configure.zcml 2009-07-17 02:25:09 +0000 |
798 | +++ lib/lp/services/openid/browser/configure.zcml 2009-11-23 17:20:28 +0000 |
799 | @@ -48,6 +48,7 @@ |
800 | <browser:page |
801 | for="..interfaces.openidrpconfig.IOpenIDRPConfigSet" |
802 | name="+index" |
803 | + class=".openidrpconfig.OpenIDRPConfigSetView" |
804 | permission="launchpad.Admin" |
805 | template="../templates/openidrpconfigset-index.pt" |
806 | /> |
807 | |
808 | === modified file 'lib/lp/services/openid/browser/openidrpconfig.py' |
809 | --- lib/lp/services/openid/browser/openidrpconfig.py 2009-07-17 02:25:09 +0000 |
810 | +++ lib/lp/services/openid/browser/openidrpconfig.py 2009-11-23 17:20:28 +0000 |
811 | @@ -19,6 +19,7 @@ |
812 | from canonical.launchpad.webapp import ( |
813 | LaunchpadEditFormView, LaunchpadFormView, Navigation, action, |
814 | canonical_url, custom_widget) |
815 | +from canonical.launchpad.webapp.publisher import LaunchpadView |
816 | from canonical.widgets import LabeledMultiCheckBoxWidget |
817 | from canonical.widgets.image import ImageChangeWidget |
818 | from lp.registry.interfaces.person import PersonCreationRationale |
819 | @@ -38,6 +39,11 @@ |
820 | return getUtility(IOpenIDRPConfigSet).get(config_id) |
821 | |
822 | |
823 | +class OpenIDRPConfigSetView(LaunchpadView): |
824 | + page_title = 'OpenID Relying Party Configurations' |
825 | + label = page_title |
826 | + |
827 | + |
828 | class OpenIDRPConfigAddView(LaunchpadFormView): |
829 | """View class for adding new RP configurations.""" |
830 | |
831 | @@ -47,6 +53,8 @@ |
832 | 'auto_authorize'] |
833 | custom_widget('logo', ImageChangeWidget, ImageChangeWidget.ADD_STYLE) |
834 | custom_widget('allowed_sreg', LabeledMultiCheckBoxWidget) |
835 | + label = 'Add an OpenID Relying Party Configuration' |
836 | + page_title = label |
837 | |
838 | initial_values = { |
839 | 'creation_rationale': |
840 | @@ -73,10 +81,18 @@ |
841 | def next_url(self): |
842 | return canonical_url(getUtility(IOpenIDRPConfigSet)) |
843 | |
844 | + cancel_url = next_url |
845 | + |
846 | |
847 | class OpenIDRPConfigEditView(LaunchpadEditFormView): |
848 | """View class for editing or removing RP configurations.""" |
849 | |
850 | + @property |
851 | + def label(self): |
852 | + return 'Edit Relying Party Configuration for %s' % ( |
853 | + self.context.displayname) |
854 | + page_title = label |
855 | + |
856 | schema = IOpenIDRPConfig |
857 | field_names = ['trust_root', 'displayname', 'description', 'logo', |
858 | 'allowed_sreg', 'creation_rationale', 'can_query_any_team', |
859 | @@ -104,3 +120,5 @@ |
860 | @property |
861 | def next_url(self): |
862 | return canonical_url(getUtility(IOpenIDRPConfigSet)) |
863 | + |
864 | + cancel_url = next_url |
865 | |
866 | === modified file 'lib/lp/services/openid/templates/openidrpconfig-add.pt' |
867 | --- lib/lp/services/openid/templates/openidrpconfig-add.pt 2009-07-17 17:59:07 +0000 |
868 | +++ lib/lp/services/openid/templates/openidrpconfig-add.pt 2009-11-23 17:20:28 +0000 |
869 | @@ -3,21 +3,13 @@ |
870 | xmlns:tal="http://xml.zope.org/namespaces/tal" |
871 | xmlns:metal="http://xml.zope.org/namespaces/metal" |
872 | xmlns:i18n="http://xml.zope.org/namespaces/i18n" |
873 | - xml:lang="en" |
874 | - lang="en" |
875 | - metal:use-macro="context/@@main_template/master" |
876 | + metal:use-macro="view/macro:page/main_only" |
877 | i18n:domain="launchpad"> |
878 | |
879 | <body> |
880 | |
881 | <div metal:fill-slot="main"> |
882 | - |
883 | - <div metal:use-macro="context/@@launchpad_form/form"> |
884 | - |
885 | - <h1 metal:fill-slot="heading">Add an OpenID Relying Party Configuration</h1> |
886 | - |
887 | - </div> |
888 | - |
889 | + <div metal:use-macro="context/@@launchpad_form/form" /> |
890 | </div> |
891 | |
892 | </body> |
893 | |
894 | === modified file 'lib/lp/services/openid/templates/openidrpconfig-edit.pt' |
895 | --- lib/lp/services/openid/templates/openidrpconfig-edit.pt 2009-07-17 17:59:07 +0000 |
896 | +++ lib/lp/services/openid/templates/openidrpconfig-edit.pt 2009-11-23 17:20:28 +0000 |
897 | @@ -3,21 +3,13 @@ |
898 | xmlns:tal="http://xml.zope.org/namespaces/tal" |
899 | xmlns:metal="http://xml.zope.org/namespaces/metal" |
900 | xmlns:i18n="http://xml.zope.org/namespaces/i18n" |
901 | - xml:lang="en" |
902 | - lang="en" |
903 | - metal:use-macro="context/@@main_template/master" |
904 | + metal:use-macro="view/macro:page/main_only" |
905 | i18n:domain="launchpad"> |
906 | |
907 | <body> |
908 | |
909 | <div metal:fill-slot="main"> |
910 | - |
911 | - <div metal:use-macro="context/@@launchpad_form/form"> |
912 | - |
913 | - <h1 metal:fill-slot="heading">Edit OpenID Relying Party Configuration</h1> |
914 | - |
915 | - </div> |
916 | - |
917 | + <div metal:use-macro="context/@@launchpad_form/form" /> |
918 | </div> |
919 | |
920 | </body> |
921 | |
922 | === modified file 'lib/lp/services/openid/templates/openidrpconfigset-index.pt' |
923 | --- lib/lp/services/openid/templates/openidrpconfigset-index.pt 2009-07-17 17:59:07 +0000 |
924 | +++ lib/lp/services/openid/templates/openidrpconfigset-index.pt 2009-11-23 17:20:28 +0000 |
925 | @@ -3,13 +3,11 @@ |
926 | xmlns:tal="http://xml.zope.org/namespaces/tal" |
927 | xmlns:metal="http://xml.zope.org/namespaces/metal" |
928 | xmlns:i18n="http://xml.zope.org/namespaces/i18n" |
929 | - metal:use-macro="context/@@main_template/master" |
930 | + metal:use-macro="view/macro:page/main_only" |
931 | i18n:domain="launchpad"> |
932 | |
933 | <body> |
934 | <div metal:fill-slot="main"> |
935 | - <h1>OpenID Relying Party Configurations</h1> |
936 | - |
937 | <table class="listing" tal:condition="context/getAll"> |
938 | <thead> |
939 | <tr> |
This is my branch to remove main-template and main-template- macros.
lp:~sinzui/launchpad/remove-main-template /bugs.launchpad .net/bugs/ 69726 macro|zcmldirec tives"
then test the whole suite. (/me did) implementation: no one
Diff size: 940 (450 lines are removed files)
Launchpad bug: https:/
Test command: ./bin/test -vvt "tales-
Pre-
Target release: 3.1.11
= Remove main-template and main-template- macros =
main-template and main-template- macros are obsolete and launchpad still
has code and tests to support them. They should be removed.
== Rules ==
* Remove main-template and main-template- macros from zcml and templates
* Update page macros, remove obsolete behaviour
ADDENDUM
ec2 test discovered pages that were still on 2.0 UI.
* Shipit and signon both use @@+main- template- macros/ notifications macros will continue support macros, update it to 3.0
Registering that name on base-template-
* OpenIDRPConfig is still using main-template, updated them to 3.0
* forgottenpassword is still using main-template, update it to 3.0
* The timeline is still using main-template-
== QA ==
* Visit a project
* Verify that the timeline displays
* Visit +rpconfig
* Verify the page displays
* Verify the add and edit pages have cancel buttons
* Visit forgottenpassword, verify the page displays.
== Lint ==
Linting changed files: /launchpad/ pagetitles. py /launchpad/ doc/tales- macro.txt /launchpad/ doc/zcmldirecti ves.txt /launchpad/ icing/style. css /launchpad/ templates/ launchpad- forgottenpasswo rd.pt /launchpad/ webapp/ login.py /launchpad/ webapp/ tales.py /launchpad/ zcml/launchpad. zcml /widgets/ location. py app/browser/ configure. zcml app/templates/ base-layout- macros. pt registry/ browser/ productrelease. py registry/ browser/ team.py registry/ templates/ object- timeline- graph.pt services/ openid/ browser/ configure. zcml services/ openid/ browser/ openidrpconfig. py services/ openid/ templates/ openidrpconfig- add.pt services/ openid/ templates/ openidrpconfig- edit.pt services/ openid/ templates/ openidrpconfigs et-index. pt
lib/canonical
lib/canonical
lib/canonical
lib/canonical
lib/canonical
lib/canonical
lib/canonical
lib/canonical
lib/canonical
lib/lp/
lib/lp/
lib/lp/
lib/lp/
lib/lp/
lib/lp/
lib/lp/
lib/lp/
lib/lp/
lib/lp/
== Test ==
* lib/canonical/ launchpad/ doc/tales- macro.txt launchpad/ doc/zcmldirecti ves.txt
* Removed unsupported features.
* Updated test to use a real page layout.
* lib/canonical/
* Updated test to use a modern example.
== Implementation ==
* lib/canonical/ launchpad/ pagetitles. py launchpad/ icing/style. css launchpad/ templates/ launchpad- forgottenpasswo rd.pt launchpad/ webapp/ login.py launchpad/ webapp/ tales.py
* Removed the unused page title.
* lib/canonical/
* Removed the comment about main template.
* lib/canonical/
* Updated page to 3.0
* lib/canonical/
* Moved the page title tot he view.
* lib/canonical/
* Updated the documentation examples for page layouts.
* Removed master (main-template) and the code that switched between
main and base.
* Removed the old layout co...