Merge lp:~adiroiban/launchpad/bug-340664 into lp:launchpad

Proposed by Adi Roiban
Status: Merged
Approved by: Graham Binns
Approved revision: not available
Merged at revision: not available
Proposed branch: lp:~adiroiban/launchpad/bug-340664
Merge into: lp:launchpad
Diff against target: 691 lines (+230/-279)
6 files modified
lib/lp/translations/browser/distroseries.py (+5/-10)
lib/lp/translations/browser/potemplate.py (+43/-5)
lib/lp/translations/browser/productseries.py (+5/-11)
lib/lp/translations/stories/productseries/xx-productseries-templates.txt (+0/-95)
lib/lp/translations/stories/standalone/xx-series-templates.txt (+105/-49)
lib/lp/translations/templates/object-templates.pt (+72/-109)
To merge this branch: bzr merge lp:~adiroiban/launchpad/bug-340664
Reviewer Review Type Date Requested Status
Graham Binns (community) Approve
Curtis Hovey (community) ui Approve
Review via email: mp+18452@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Adi Roiban (adiroiban) wrote :

= Bug 340664 =
As discussed during Translations 3.0 UI sprint, we've decided to add administration page listing all templates for a single series. This would be mostly used by maintainers, and initially should have following columns:

  * template
  * length (number of messages)
  * languages (that have at least some translations)
  * last update
  * editing button

Showing priority might not be a bad idea either.

== Proposed fix ==

Add priority, length and languages to the +templates pages.

== Pre-implementation notes ==
Last update and editing buttons were added in previous branches.

I talked with Danilo and he said the screenshots are OK and this is the intended way for fixing the bug.

== Implementation details ==
distroseries-templates and productseries-templates stories were merged into a single series-templates file.

Since both product and distribution series are using the same template for displaying templates list, I have create a base class for those views.

object-template.pt logic was moved from the template to the view and the new template should be easier to read.

== Tests ==
lp-test -t series-templates

== Demo and Q/A ==
Log in as admin and go to a product +templates page
https://translations.launchpad.dev/evolution/trunk/+templates

The table should look like in this screenshot:
http://launchpadlibrarian.net/37268665/productseries.png

Log in as admin and go to a distribution +templates page
The table should look like in this screenshot:
http://launchpadlibrarian.net/37268672/distroseries.png

When logged in as a normal user you should not see the edit, upload and admin links.

= Launchpad lint =

Checking for conflicts. and issues in doctests and templates.
Running jslint, xmllint, pyflakes, and pylint.
Using normal rules.

Linting changed files:
  lib/lp/translations/browser/distroseries.py
  lib/lp/translations/browser/productseries.py

Revision history for this message
Michael Nelson (michael.nelson) wrote :

Hi Adi, I'm requesting a UI review from Curtis first (he's been starved of them), as it's always worth doing that before the code review.

Revision history for this message
Curtis Hovey (sinzui) wrote :
Download full text (3.3 KiB)

Hi Adi.

This is a good start. I was please to see a presentation that deemphasised
the action to improve the readability of the page.

The behaviour of these actions is disconcerting. When I edit a a template,
the next_url is the template, but I expected to return to the all templates
view. I know that this behaviour has not changed in this branch. I do not
see any bugs that pertain to this surprise--maybe I do not know what to
search on. Here is an example of how to negotiate multiple origins:

    @property
    def next_url(self):
        referrer = self.request.getHeader('referer')
        if (referrer is not None
            and referrer.startswith(self.request.getApplicationURL())):
            return referrer
        else:
            return canonical_url(self.context)

We should discuss if this is in scope. If not this should be a bug reported
against translations.

See below for some 3.0 style concerns.

=== modified file 'lib/lp/translations/templates/object-templates.pt'
--- lib/lp/translations/templates/object-templates.pt 2009-12-28 22:58:18 +0000
+++ lib/lp/translations/templates/object-templates.pt 2010-02-10 13:48:35 +0000
...

+ <td class="actions_column"
+ tal:condition="context/required:launchpad.AnyPerson">
+ <div class="template_links">
+ <tal:maintainer condition="template/required:launchpad.Edit">
+ <a tal:attributes="href string:${template/fmt:url}/+edit;
+ title string:Edit ${template/name}'s details">
+ <img src="/@@/edit" />&nbsp;Edit</a>
+ <a tal:attributes="href string:${template/fmt:url}/+upload;
+ title string:Upload translations to ${template/name}">
+ <img src="/@@/add" />&nbsp;Upload</a>
+ </tal:maintainer>
+ <a tal:attributes="href string:${template/fmt:url}/+export;
+ title string:Download translations from ${template/name}">
+ <img src="/@@/download" />&nbsp;Download</a>
+ <tal:admin condition="template/required:launchpad.TranslationsAdmin">
+ <a tal:attributes="href string:${template/fmt:url}/+admin;
+ title string:Administer ${template/name}">
+ <img src="/@@/edit" />&nbsp;Administer</a>
+ </tal:admin>

I an uncomfortable with these hand crafted links. We usually need extra tests
to verify that the permission and URL that is in the same as the canonical
definitions used by menus, and render the correct markup.

This rendered markup is not 3.0 style. This should use a sprite, which will
fix the strange underlining issues I see under the icon eg:

  class="sprint edit"

All these links appear to be defined in POTemplateMenu, so I think you can
avoid writing lots of tests by removing this exceptional markup with:

    <a tal:replace="structure template/menu:translations/edit/fmt:link" />

The URL is guaranteed by menu:translations. The markup is guaranteed by
fmt:link. This does permission checking for you too. This will be consistent
with other links....

Read more...

review: Needs Fixing (ui)
Revision history for this message
Adi Roiban (adiroiban) wrote :

Hi Curtis and thanks for taking the time to do this review.

I agree that the forms next url is buggy. I think it is best to open a new bug report as this diff could become to big. If you consider this is issues is valid for a new bug,I can take care of reporting and solving that bug.

I agree that it is best to use the URL formatter, rather than constructing the URL in the template.

I think we can rename „Settings” to „Edit”.

Should we keep the javascript that hides the icons and only shows them on mouseover?

Revision history for this message
Curtis Hovey (sinzui) wrote :

I like the hover presentation. I want to see it on edge to get feedback from users. Please file a bug about the next URL problem.

review: Approve (ui)
Revision history for this message
Adi Roiban (adiroiban) wrote :
Download full text (3.7 KiB)

I filled bug 522188.

The hover presentation is already on edge. ie: https://translations.edge.launchpad.net/openobject-addons/trunk/+templates

I tried to look into doc/tales.txt but I am not sure if the are covering all permissions testing or if I should move the permission testing for templates actions in a different test. Any advice is much appreciated. Thanks!

Bellow is the diff with the latest changes:
=== modified file 'lib/lp/translations/browser/potemplate.py'
--- lib/lp/translations/browser/potemplate.py 2010-02-02 11:17:00 +0000
+++ lib/lp/translations/browser/potemplate.py 2010-02-15 14:55:25 +0000
@@ -175,21 +175,21 @@
     @enabled_with_permission('launchpad.Edit')
     def upload(self):
         text = 'Upload'
- return Link('+upload', text)
+ return Link('+upload', text, icon='add')

     def download(self):
         text = 'Download'
- return Link('+export', text)
+ return Link('+export', text, icon='download')

     @enabled_with_permission('launchpad.Edit')
     def edit(self):
- text = 'Settings'
- return Link('+edit', text)
+ text = 'Edit'
+ return Link('+edit', text, icon='edit')

     @enabled_with_permission('launchpad.TranslationsAdmin')
     def administer(self):
         text = 'Administer'
- return Link('+admin', text)
+ return Link('+admin', text, icon='edit')

 class POTemplateSubsetView:

=== modified file 'lib/lp/translations/templates/object-templates.pt'
--- lib/lp/translations/templates/object-templates.pt 2010-02-02 11:17:00 +0000
+++ lib/lp/translations/templates/object-templates.pt 2010-02-15 15:25:55 +0000
@@ -7,8 +7,8 @@
   <body>
     <div metal:fill-slot="head_epilogue">
       <style type="text/css">
- .inactive_links a img{
- visibility: hidden;
+ .inactive_links a{
+ background: none;
         }
         .inactive_links a{
           color: lightgray;
@@ -130,22 +130,18 @@
               <td class="actions_column"
                   tal:condition="context/required:launchpad.AnyPerson">
               <div class="template_links">
- <tal:maintainer condition="template/required:launchpad.Edit">
- <a tal:attributes="href string:${template/fmt:url}/+edit;
- title string:Edit ${template/name}'s details">
- <img src="/@@/edit" />&nbsp;Edit</a>
- <a tal:attributes="href string:${template/fmt:url}/+upload;
- title string:Upload translations to ${template/name}">
- <img src="/@@/add" />&nbsp;Upload</a>
- </tal:maintainer>
- <a tal:attributes="href string:${template/fmt:url}/+export;
- title string:Download translations from ${template/name}">
- <img src="/@@/download" />&nbsp;Download</a>
- <tal:admin condition="template/required:launchpad.TranslationsAdmin">
- <a tal:attributes="href string:${template/fmt:url}/+admin;
- title string:Administer ${template/name}">
- <img src="/@@/edit" />&nbsp;Administer...

Read more...

Revision history for this message
Curtis Hovey (sinzui) wrote :

Thanks for these changes. These links finally meet launchpad 2.0 rules after 18 months.

We do not need explict tests for most links because the decorator and formatter rules are well tested.

Revision history for this message
Graham Binns (gmb) wrote :

Hi Adi,

You've got a typo in xx-series-templates.txt (line 288 of the diff):
s/lenght/length/. Other than that this is a nice branch and I'm happy for it to land. I'll run it through ec2 for you.

review: Approve
Revision history for this message
Graham Binns (gmb) wrote :

(Approved revision: 10102).

Revision history for this message
Adi Roiban (adiroiban) wrote :

Many thanks for the review!

I have pushed the typo fix.
When you have time, please run it through ec2. There is no hurry.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'lib/lp/translations/browser/distroseries.py'
2--- lib/lp/translations/browser/distroseries.py 2009-12-27 20:58:33 +0000
3+++ lib/lp/translations/browser/distroseries.py 2010-02-16 13:30:44 +0000
4@@ -28,9 +28,9 @@
5
6 from lp.registry.interfaces.distroseries import IDistroSeries
7 from lp.translations.browser.translations import TranslationsMixin
8+from lp.translations.browser.potemplate import BaseSeriesTemplatesView
9 from lp.translations.interfaces.distroserieslanguage import (
10 IDistroSeriesLanguageSet)
11-from lp.translations.interfaces.potemplate import IPOTemplateSet
12
13
14 class DistroSeriesTranslationsAdminView(LaunchpadEditFormView):
15@@ -157,17 +157,12 @@
16 [canonical_url(self.context), '+language-packs'])
17
18
19-class DistroSeriesTemplatesView(LaunchpadView):
20+class DistroSeriesTemplatesView(BaseSeriesTemplatesView):
21 """Show a list of all templates for the DistroSeries."""
22
23- is_distroseries = True
24- label = "Translation templates"
25- page_title = "All templates"
26-
27- def iter_templates(self):
28- potemplateset = getUtility(IPOTemplateSet)
29- return potemplateset.getSubset(distroseries=self.context,
30- ordered_by_names=True)
31+ def initialize(self):
32+ super(DistroSeriesTemplatesView, self).initialize(
33+ series=self.context, is_distroseries=True)
34
35
36 class DistroSeriesView(LaunchpadView, TranslationsMixin):
37
38=== modified file 'lib/lp/translations/browser/potemplate.py'
39--- lib/lp/translations/browser/potemplate.py 2010-02-01 19:19:32 +0000
40+++ lib/lp/translations/browser/potemplate.py 2010-02-16 13:30:44 +0000
41@@ -21,6 +21,7 @@
42 'POTemplateUploadView',
43 'POTemplateView',
44 'POTemplateViewPreferred',
45+ 'BaseSeriesTemplatesView',
46 ]
47
48 import cgi
49@@ -174,21 +175,21 @@
50 @enabled_with_permission('launchpad.Edit')
51 def upload(self):
52 text = 'Upload'
53- return Link('+upload', text)
54+ return Link('+upload', text, icon='add')
55
56 def download(self):
57 text = 'Download'
58- return Link('+export', text)
59+ return Link('+export', text, icon='download')
60
61 @enabled_with_permission('launchpad.Edit')
62 def edit(self):
63- text = 'Settings'
64- return Link('+edit', text)
65+ text = 'Edit'
66+ return Link('+edit', text, icon='edit')
67
68 @enabled_with_permission('launchpad.TranslationsAdmin')
69 def administer(self):
70 text = 'Administer'
71- return Link('+admin', text)
72+ return Link('+admin', text, icon='edit')
73
74
75 class POTemplateSubsetView:
76@@ -781,3 +782,40 @@
77 @property
78 def text(self):
79 return smartquote('Template "%s"' % self.context.name)
80+
81+
82+class BaseSeriesTemplatesView(LaunchpadView):
83+ """Show a list of all templates for the Series."""
84+
85+ is_distroseries = True
86+ distroseries = None
87+ productseries = None
88+ label = "Translation templates"
89+ page_title = "All templates"
90+
91+ def initialize(self, series, is_distroseries=True):
92+ self.is_distroseries = is_distroseries
93+ if is_distroseries:
94+ self.distroseries = series
95+ else:
96+ self.productseries = series
97+
98+ def iter_templates(self):
99+ potemplateset = getUtility(IPOTemplateSet)
100+ return potemplateset.getSubset(
101+ productseries=self.productseries,
102+ distroseries=self.distroseries,
103+ ordered_by_names=True)
104+
105+ def rowCSSClass(self, template):
106+ if template.iscurrent:
107+ return "active-template"
108+ else:
109+ return "inactive-template"
110+
111+ def isVisible(self, template):
112+ if (template.iscurrent or
113+ check_permission('launchpad.Edit', template)):
114+ return True
115+ else:
116+ return False
117
118=== modified file 'lib/lp/translations/browser/productseries.py'
119--- lib/lp/translations/browser/productseries.py 2009-12-16 15:21:36 +0000
120+++ lib/lp/translations/browser/productseries.py 2010-02-16 13:30:44 +0000
121@@ -42,8 +42,8 @@
122
123 from lp.translations.browser.poexportrequest import BaseExportView
124 from lp.translations.browser.translations import TranslationsMixin
125+from lp.translations.browser.potemplate import BaseSeriesTemplatesView
126 from lp.code.interfaces.branchjob import IRosettaUploadJobSource
127-from lp.translations.interfaces.potemplate import IPOTemplateSet
128 from lp.translations.interfaces.productserieslanguage import (
129 IProductSeriesLanguageSet)
130 from lp.translations.interfaces.translations import (
131@@ -479,18 +479,12 @@
132 _("The import has been requested."))
133
134
135-class ProductSeriesTemplatesView(LaunchpadView):
136+class ProductSeriesTemplatesView(BaseSeriesTemplatesView):
137 """Show a list of all templates for the ProductSeries."""
138
139- is_distroseries = False
140- label = "Translation templates"
141- page_title = "All templates"
142-
143- def iter_templates(self):
144- """Return an iterator of all `IPOTemplates` for the series."""
145- potemplateset = getUtility(IPOTemplateSet)
146- return potemplateset.getSubset(productseries=self.context,
147- ordered_by_names=True)
148+ def initialize(self):
149+ super(ProductSeriesTemplatesView, self).initialize(
150+ series=self.context, is_distroseries=False)
151
152
153 class LinkTranslationsBranchView(LaunchpadEditFormView):
154
155=== removed file 'lib/lp/translations/stories/productseries/xx-productseries-templates.txt'
156--- lib/lp/translations/stories/productseries/xx-productseries-templates.txt 2009-12-28 22:58:18 +0000
157+++ lib/lp/translations/stories/productseries/xx-productseries-templates.txt 1970-01-01 00:00:00 +0000
158@@ -1,95 +0,0 @@
159-Templates view for ProductSeries
160-================================
161-
162-The +templates view for ProductSeries gives an overview of the translation
163-templates in this series and provides easy access to the various subpages of
164-each template.
165-
166-
167-Preparation
168------------
169-
170-To test the ordering of templates in the listing, we need another
171-template that is new but must appear at the top of the list.
172-
173- >>> login('foo.bar@canonical.com')
174- >>> from zope.component import getUtility
175- >>> from lp.registry.interfaces.product import IProductSet
176- >>> evolution = getUtility(IProductSet).getByName('evolution')
177- >>> evolution_trunk = evolution.getSeries('trunk')
178- >>> template = factory.makePOTemplate(productseries=evolution_trunk,
179- ... name='at-the-top')
180- >>> template = factory.makePOTemplate(productseries=evolution_trunk,
181- ... name='disabled')
182- >>> template.iscurrent = False
183- >>> logout()
184- >>> owner_browser = setupBrowser('Basic test@canonical.com:test')
185-
186-Getting there
187--------------
188-
189-To get to the listing of all templates, one needs to use the link
190-from the product series translations page.
191-
192- >>> user_browser.open(
193- ... 'http://translations.launchpad.dev/evolution/trunk')
194- >>> user_browser.getLink('full list of templates').click()
195- >>> print user_browser.url
196- http://translations.launchpad.dev/evolution/trunk/+templates
197-
198-
199-The templates table
200--------------------
201-
202-The page shows a table of all templates and links to their subpages.
203-Users will not see disabled templates.
204-
205- >>> table = find_tag_by_id(user_browser.contents, 'templates_table')
206- >>> print extract_text(table)
207- Template name Last update Actions
208- at-the-top ... Download
209- evolution-2.2 2005-08-25 Download
210- evolution-2.2-test 2006-12-13 Download
211-
212-If an administrator views this page, links to the templates admin page are
213-shown, too.
214-
215- >>> admin_browser.open(
216- ... 'http://translations.launchpad.dev/evolution/trunk/+templates')
217- >>> table = find_tag_by_id(admin_browser.contents, 'templates_table')
218- >>> print extract_text(table)
219- Template name Last update Actions
220- at-the-top ... Edit Upload Download Administer
221- disabled (inactive) ... Edit Upload Download Administer
222- evolution-2.2 2005-08-25 Edit Upload Download Administer
223- evolution-2.2-test 2006-12-13 Edit Upload Download Administer
224-
225-
226-Links to the templates
227-----------------------
228-
229-Clicking on a template name will take the user to that template's overview
230-page.
231-
232- >>> admin_browser.getLink('evolution-2.2').click()
233- >>> print admin_browser.url
234- http://translations.launchpad.dev/evolution/trunk/+pots/evolution-2.2
235-
236-Clicking on 'Admin' will take the user to the page to administer the template.
237-Likewise for the other links for each template.
238-
239- >>> admin_browser.open(
240- ... 'http://translations.launchpad.dev/evolution/trunk/+templates')
241- >>> admin_browser.getLink('Admin', index=0).click()
242- >>> print admin_browser.url
243- http://translations.launchpad.dev/evolution/trunk/+pots/at-the-top/+admin
244-
245-Clicking on 'Edit' will take the user to the page to edit the template
246-details, even if the translation of the templates are not active.
247-
248- >>> owner_browser.open(
249- ... 'http://translations.launchpad.dev/evolution/trunk/+templates')
250- >>> owner_browser.getLink('Edit', index=1).click()
251- >>> print owner_browser.url
252- http://translations.launchpad.dev/evolution/trunk/+pots/disabled/+edit
253-
254
255=== renamed file 'lib/lp/translations/stories/distroseries/xx-distroseries-templates.txt' => 'lib/lp/translations/stories/standalone/xx-series-templates.txt'
256--- lib/lp/translations/stories/distroseries/xx-distroseries-templates.txt 2009-12-10 12:46:11 +0000
257+++ lib/lp/translations/stories/standalone/xx-series-templates.txt 2010-02-16 13:30:44 +0000
258@@ -1,5 +1,9 @@
259-Templates view for DistroSeries
260-===============================
261+Templates view for Series
262+=========================
263+
264+
265+Templates for DistroSeries
266+--------------------------
267
268 The +templates view for DistroSeries gives an overview of the translation
269 templates in this series and provides easy access to the various subpages of
270@@ -19,8 +23,8 @@
271 http://translations.launchpad.dev/ubuntu/hoary/+templates
272
273
274-The templates table
275--------------------
276+Templates view for DistroSeries
277+-------------------------------
278
279 Full template listing for a distribution series is reached by following
280 a link from the distribution series translations page.
281@@ -29,18 +33,14 @@
282 ... 'http://translations.launchpad.dev/ubuntu/hoary')
283 >>> anon_browser.getLink('full list of templates').click()
284
285-Full listing of templates shows source package name, template name and
286-the date of last update for this distribution series.
287+Full listing of templates shows priority, source package name, template name
288+length, languages and the date of last update for this distribution series.
289
290 >>> table = find_tag_by_id(anon_browser.contents, 'templates_table')
291 >>> print extract_text(table)
292- Source package Template name Last update
293- evolution evolution-2.2 2005-05-06
294- evolution man 2006-08-14
295- mozilla pkgconf-mozilla 2005-05-06
296- pmount man 2006-08-14
297- pmount pmount 2005-05-06
298-
299+ Priority Source package Template name Length Languages Updated
300+ 100 evolution evolution-2.2 22 2 2005-05-06
301+ 0 evolution man 1 1 2006-08-14 ...
302
303 Logged-in users see a link to all the active translation templates
304 on a distribution series translation page.
305@@ -53,11 +53,9 @@
306
307 >>> table = find_tag_by_id(user_browser.contents, 'templates_table')
308 >>> print extract_text(table)
309- Source package Template name Last update Actions
310- evolution evolution-2.2 2005-05-06 Download
311- ...
312- mozilla pkgconf-mozilla 2005-05-06 Download
313- ...
314+ Priority Source package Template name ... Updated Actions
315+ 100 evolution evolution-2.2 ... 2005-05-06 Download ...
316+ 0 mozilla pkgconf-mozilla ... 2005-05-06 Download ...
317
318 Administrator can see all editing options.
319
320@@ -69,35 +67,13 @@
321
322 >>> table = find_tag_by_id(admin_browser.contents, 'templates_table')
323 >>> print extract_text(table)
324- Source package Template name Last update Actions
325- evolution disabled-template (inactive) 2007-01-05 Edit Upload Download Administer
326- evolution evolution-2.2 2005-05-06 Edit Upload Download Administer
327- evolution man 2006-08-14 Edit Upload Download Administer
328- mozilla pkgconf-mozilla 2005-05-06 Edit Upload Download Administer
329- pmount man 2006-08-14 Edit Upload Download Administer
330- pmount pmount 2005-05-06 Edit Upload Download Administer
331-
332-Ubuntu Translations Coordinator can administer all templates, including
333-those that are currently disabled.
334-
335-New user is made an owner of an Ubuntu translation group, thus being
336-considered a translations administrator for Ubuntu.
337-
338- >>> from zope.component import getUtility
339- >>> from canonical.launchpad.ftests import login, logout
340- >>> from canonical.launchpad.interfaces import (
341- ... IDistributionSet, IPersonSet, ILaunchpadCelebrities)
342- >>> login('foo.bar@canonical.com')
343- >>> a_person = factory.makePerson(email='utc-member@example.com',
344- ... name='utc-member', password='test', displayname='Some Guy')
345- >>> utc_member = factory.makeTranslator('ro', person=a_person)
346- >>> utc_team = factory.makeTeam(owner=a_person)
347- >>> utg = factory.makeTranslationGroup(owner=utc_team,
348- ... name="Ubuntu Translation Group")
349- >>> ubuntu = getUtility(ILaunchpadCelebrities).ubuntu
350- >>> ubuntu.translationgroup = utg
351- >>> # Log out so we can go back to using test browsers.
352- >>> logout()
353+ Priority Source package ... Updated Actions
354+ 0 evolution ... 2007-01-05 Edit Upload Download Administer
355+ 100 ...
356+ 0 pmount ... 2005-05-06 Edit Upload Download Administer
357+
358+Translation group owners can administer all templates for their distribution,
359+including those that are currently disabled.
360
361 Visiting the Ubuntu Hoary templates page, translation administrators
362 will see "Edit" and "Administer" links for all templates.
363@@ -105,7 +81,7 @@
364 Trying to edit/administer enabled templates brings them to the
365 appropriate page.
366
367- >>> utc_browser = setupBrowser(auth='Basic utc-member@example.com:test')
368+ >>> utc_browser = setupDTCBrowser()
369 >>> utc_browser.open(
370 ... 'http://translations.launchpad.dev/ubuntu/hoary/+templates')
371 >>> utc_browser.getLink(url='ubuntu/hoary/+source/evolution/+pots/evolution-2.2/+edit').click()
372@@ -121,7 +97,6 @@
373 Trying to edit/administer disabled templates brings them to the
374 appropriate page.
375
376- >>> utc_browser = setupBrowser(auth='Basic utc-member@example.com:test')
377 >>> utc_browser.open(
378 ... 'http://translations.launchpad.dev/ubuntu/hoary/+templates')
379 >>> utc_browser.getLink(url='ubuntu/hoary/+source/evolution/+pots/disabled-template/+edit').click()
380@@ -154,3 +129,84 @@
381 >>> print admin_browser.url
382 http://translations.../evolution/+pots/disabled-template/+edit
383
384+
385+Templates view for ProductSeries
386+--------------------------------
387+
388+The +templates view for ProductSeries gives an overview of the translation
389+templates in this series and provides easy access to the various subpages of
390+each template.
391+
392+
393+Preparation
394+-----------
395+
396+To test the ordering of templates in the listing, we need another
397+template that is new but must appear at the top of the list.
398+
399+ >>> login('foo.bar@canonical.com')
400+ >>> from zope.component import getUtility
401+ >>> from lp.registry.interfaces.product import IProductSet
402+ >>> evolution = getUtility(IProductSet).getByName('evolution')
403+ >>> evolution_trunk = evolution.getSeries('trunk')
404+ >>> template = factory.makePOTemplate(productseries=evolution_trunk,
405+ ... name='at-the-top')
406+ >>> logout()
407+
408+
409+Getting there
410+-------------
411+
412+To get to the listing of all templates, one needs to use the link
413+from the product series translations page.
414+
415+ >>> user_browser.open(
416+ ... 'http://translations.launchpad.dev/evolution/trunk')
417+ >>> user_browser.getLink('full list of templates').click()
418+ >>> print user_browser.url
419+ http://translations.launchpad.dev/evolution/trunk/+templates
420+
421+
422+The templates table
423+-------------------
424+
425+The page shows a table of all templates and links to their subpages.
426+
427+ >>> table = find_tag_by_id(user_browser.contents, 'templates_table')
428+ >>> print extract_text(table)
429+ Priority Template name Length Languages Updated Actions
430+ 0 at-the-top 0 0 ... Download
431+ 0 evolution-2.2 22 1 2005-08-25 Download
432+ 0 evolutio... 8 1 2006-12-13 Download
433+
434+If an administrator views this page, links to the templates admin page are
435+shown, too.
436+
437+ >>> admin_browser.open(
438+ ... 'http://translations.launchpad.dev/evolution/trunk/+templates')
439+ >>> table = find_tag_by_id(admin_browser.contents, 'templates_table')
440+ >>> print extract_text(table)
441+ Priority Template name ... Updated Actions
442+ 0 at-the-top ... ... Edit Upload Download Administer
443+ 0 evolution-2.2 ... 2005-08-25 Edit Upload Download Administer
444+ 0 evolutio... ... 2006-12-13 Edit Upload Download Administer
445+
446+
447+Links to the templates
448+----------------------
449+
450+Clicking on a template name will take the user to that template's overview
451+page.
452+
453+ >>> admin_browser.getLink('evolution-2.2').click()
454+ >>> print admin_browser.url
455+ http://translations.launchpad.dev/evolution/trunk/+pots/evolution-2.2
456+
457+Clicking on 'Edit' will take the user to the page to edit the template
458+details. Likewise for the other links for each template.
459+
460+ >>> admin_browser.open(
461+ ... 'http://translations.launchpad.dev/evolution/trunk/+templates')
462+ >>> admin_browser.getLink('Edit').click()
463+ >>> print admin_browser.url
464+ http://translations.launchpad.dev/evolution/trunk/+pots/at-the-top/+edit
465
466=== modified file 'lib/lp/translations/templates/object-templates.pt'
467--- lib/lp/translations/templates/object-templates.pt 2009-12-28 22:58:18 +0000
468+++ lib/lp/translations/templates/object-templates.pt 2010-02-16 13:30:44 +0000
469@@ -7,8 +7,8 @@
470 <body>
471 <div metal:fill-slot="head_epilogue">
472 <style type="text/css">
473- .inactive_links a img{
474- visibility: hidden;
475+ .inactive_links a{
476+ background: none;
477 }
478 .inactive_links a{
479 color: lightgray;
480@@ -16,9 +16,11 @@
481 .template_links a{
482 padding-right: 1em;
483 }
484- td.template_column, th.template_column,
485 td.sourcepackage_column, th.sourcepackage_column {
486- width: 20em;
487+ width: 10em;
488+ }
489+ td.template_column, th.template_column {
490+ width: 14em;
491 }
492 td.actions_column, th.actions_column {
493 width: 27em;
494@@ -26,14 +28,14 @@
495 </style>
496 <style tal:condition="view/is_distroseries" type="text/css">
497 #templates_table {
498+ width: 81em;
499+ }
500+ </style>
501+ <style tal:condition="not:view/is_distroseries" type="text/css">
502+ #templates_table {
503 width: 79em;
504 }
505 </style>
506- <style tal:condition="not:view/is_distroseries" type="text/css">
507- #templates_table {
508- width: 58em;
509- }
510- </style>
511 <script language="JavaScript" type="text/javascript">
512 LPS.use('node-base', 'event-delegate', function(Y) {
513 Y.on('domready', function(e) {
514@@ -72,10 +74,13 @@
515 <table class="sortable listing" id="templates_table">
516 <thead>
517 <tr>
518+ <th class="priority_column">Priority</th>
519 <th tal:condition="view/is_distroseries"
520 class="sourcepackage_column">Source package</th>
521 <th class="template_column">Template name</th>
522- <th class="lastupdate_column">Last update</th>
523+ <th class="length_column">Length</th>
524+ <th class="languages_column">Languages</th>
525+ <th class="lastupdate_column">Updated</th>
526 <th class="actions_column"
527 tal:condition="context/required:launchpad.AnyPerson">
528 Actions</th>
529@@ -83,105 +88,63 @@
530 </thead>
531 <tbody>
532 <tal:templates repeat="template view/iter_templates">
533- <tal:not-current condition="not: template/iscurrent">
534- <tal:admin condition="template/required:launchpad.Edit">
535- <tr class="template_row inactive-template">
536- <td tal:condition="view/is_distroseries"
537- tal:content="template/sourcepackagename/name"
538- class="sourcepackage_column">Source package
539- </td>
540- <td class="template_column">
541- <a tal:attributes="href template/fmt:url">
542- <span tal:content="template/name">Template name</span>
543- </a> (inactive)
544- </td>
545- <td class="lastupdate_column">
546- <span class="sortkey"
547- tal:condition="template/date_last_updated"
548- tal:content="template/date_last_updated/fmt:datetime">
549- time sort key
550- </span>
551- <span class="lastupdate_column"
552- tal:condition="template/date_last_updated"
553- tal:attributes="
554- title template/date_last_updated/fmt:datetime"
555- tal:content="
556- template/date_last_updated/fmt:approximatedate"
557- >
558- 2009-09-23
559- </span>
560- </td>
561- <td class="actions_column"
562- tal:condition="context/required:launchpad.AnyPerson">
563- <div class="template_links">
564- <tal:maintainer condition="template/required:launchpad.Edit">
565- <a tal:attributes="href string:${template/fmt:url}/+edit;
566- title string:Edit ${template/name}'s details">
567- <img src="/@@/edit" />&nbsp;Edit</a>
568- <a tal:attributes="href string:${template/fmt:url}/+upload;
569- title string:Upload translations to ${template/name}">
570- <img src="/@@/add" />&nbsp;Upload</a>
571- </tal:maintainer>
572- <a tal:attributes="href string:${template/fmt:url}/+export;
573- title string:Download translations from ${template/name}">
574- <img src="/@@/download" />&nbsp;Download</a>
575- <tal:admin condition="template/required:launchpad.TranslationsAdmin">
576- <a tal:attributes="href string:${template/fmt:url}/+admin;
577- title string:Administer ${template/name}">
578- <img src="/@@/edit" />&nbsp;Administer</a>
579- </tal:admin>
580- </div>
581- </td>
582- </tr>
583- </tal:admin>
584- </tal:not-current>
585- <tal:current condition="template/iscurrent">
586- <tr class="template_row">
587- <td tal:condition="view/is_distroseries"
588- tal:content="template/sourcepackagename/name"
589- class="sourcepackage_column">Source package
590- </td>
591- <td class="template_column"><a tal:attributes="href template/fmt:url"
592- tal:content="template/name">Template name</a></td>
593- <td class="lastupdate_column">
594- <span class="sortkey"
595- tal:condition="template/date_last_updated"
596- tal:content="template/date_last_updated/fmt:datetime">
597- time sort key
598- </span>
599- <span class="lastupdate_column"
600- tal:condition="template/date_last_updated"
601- tal:attributes="
602- title template/date_last_updated/fmt:datetime"
603- tal:content="
604- template/date_last_updated/fmt:approximatedate"
605- >
606- 2009-09-23
607- </span>
608- </td>
609- <td class="actions_column"
610- tal:condition="context/required:launchpad.AnyPerson">
611- <div class="template_links">
612- <tal:maintainer condition="template/required:launchpad.Edit">
613- <a tal:attributes="href string:${template/fmt:url}/+edit;
614- title string:Edit ${template/name}'s details">
615- <img src="/@@/edit" />&nbsp;Edit</a>
616- <a tal:attributes="href string:${template/fmt:url}/+upload;
617- title string:Upload translations to ${template/name}">
618- <img src="/@@/add" />&nbsp;Upload</a>
619- </tal:maintainer>
620- <a tal:attributes="href string:${template/fmt:url}/+export;
621- title string:Download translations from ${template/name}">
622- <img src="/@@/download" />&nbsp;Download</a>
623- <tal:admin condition="template/required:launchpad.TranslationsAdmin">
624- <a tal:attributes="href string:${template/fmt:url}/+admin;
625- title string:Administer ${template/name}">
626- <img src="/@@/edit" />&nbsp;Administer</a>
627- </tal:admin>
628- </div>
629- </td>
630- </tr>
631- </tal:current>
632+ <tr tal:define="
633+ inactive_css_class python:view.rowCSSClass(template)"
634+ tal:condition="python: view.isVisible(template)"
635+ tal:attributes="
636+ class string: template_row ${inactive_css_class}">
637+ <td class="priority_column"
638+ tal:content="template/priority">7</td>
639+ <td tal:condition="view/is_distroseries"
640+ tal:content="template/sourcepackagename/name"
641+ class="sourcepackage_column">Source package
642+ </td>
643+ <td class="template_column">
644+ <a tal:attributes="href template/fmt:url">
645+ <span tal:content="template/name">Template name</span>
646+ </a>
647+ <tal:inactive condition="not: template/iscurrent">
648+ (inactive)
649+ </tal:inactive>
650+ </td>
651+ <td class="length_column"
652+ tal:content="template/getPOTMsgSetsCount">1777</td>
653+ <td class="languages_column"
654+ tal:content="template/language_count">777</td>
655+ <td class="lastupdate_column">
656+ <span class="sortkey"
657+ tal:condition="template/date_last_updated"
658+ tal:content="template/date_last_updated/fmt:datetime">
659+ time sort key
660+ </span>
661+ <span class="lastupdate_column"
662+ tal:condition="template/date_last_updated"
663+ tal:attributes="
664+ title template/date_last_updated/fmt:datetime"
665+ tal:content="
666+ template/date_last_updated/fmt:approximatedate"
667+ >
668+ 2009-09-23
669+ </span>
670+ </td>
671+ <td class="actions_column"
672+ tal:condition="context/required:launchpad.AnyPerson">
673+ <div class="template_links">
674+ <a tal:replace="
675+ structure template/menu:translations/edit/fmt:link
676+ " />
677+ <a tal:replace="
678+ structure template/menu:translations/upload/fmt:link
679+ " />
680+ <a tal:replace="
681+ structure template/menu:translations/download/fmt:link
682+ " />
683+ <a tal:replace="
684+ structure template/menu:translations/administer/fmt:link
685+ " />
686+ </div>
687+ </td>
688+ </tr>
689 </tal:templates>
690 </tbody>
691 </table>