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
=== modified file 'lib/lp/translations/browser/distroseries.py'
--- lib/lp/translations/browser/distroseries.py 2009-12-27 20:58:33 +0000
+++ lib/lp/translations/browser/distroseries.py 2010-02-16 13:30:44 +0000
@@ -28,9 +28,9 @@
2828
29from lp.registry.interfaces.distroseries import IDistroSeries29from lp.registry.interfaces.distroseries import IDistroSeries
30from lp.translations.browser.translations import TranslationsMixin30from lp.translations.browser.translations import TranslationsMixin
31from lp.translations.browser.potemplate import BaseSeriesTemplatesView
31from lp.translations.interfaces.distroserieslanguage import (32from lp.translations.interfaces.distroserieslanguage import (
32 IDistroSeriesLanguageSet)33 IDistroSeriesLanguageSet)
33from lp.translations.interfaces.potemplate import IPOTemplateSet
3434
3535
36class DistroSeriesTranslationsAdminView(LaunchpadEditFormView):36class DistroSeriesTranslationsAdminView(LaunchpadEditFormView):
@@ -157,17 +157,12 @@
157 [canonical_url(self.context), '+language-packs'])157 [canonical_url(self.context), '+language-packs'])
158158
159159
160class DistroSeriesTemplatesView(LaunchpadView):160class DistroSeriesTemplatesView(BaseSeriesTemplatesView):
161 """Show a list of all templates for the DistroSeries."""161 """Show a list of all templates for the DistroSeries."""
162162
163 is_distroseries = True163 def initialize(self):
164 label = "Translation templates"164 super(DistroSeriesTemplatesView, self).initialize(
165 page_title = "All templates"165 series=self.context, is_distroseries=True)
166
167 def iter_templates(self):
168 potemplateset = getUtility(IPOTemplateSet)
169 return potemplateset.getSubset(distroseries=self.context,
170 ordered_by_names=True)
171166
172167
173class DistroSeriesView(LaunchpadView, TranslationsMixin):168class DistroSeriesView(LaunchpadView, TranslationsMixin):
174169
=== modified file 'lib/lp/translations/browser/potemplate.py'
--- lib/lp/translations/browser/potemplate.py 2010-02-01 19:19:32 +0000
+++ lib/lp/translations/browser/potemplate.py 2010-02-16 13:30:44 +0000
@@ -21,6 +21,7 @@
21 'POTemplateUploadView',21 'POTemplateUploadView',
22 'POTemplateView',22 'POTemplateView',
23 'POTemplateViewPreferred',23 'POTemplateViewPreferred',
24 'BaseSeriesTemplatesView',
24 ]25 ]
2526
26import cgi27import cgi
@@ -174,21 +175,21 @@
174 @enabled_with_permission('launchpad.Edit')175 @enabled_with_permission('launchpad.Edit')
175 def upload(self):176 def upload(self):
176 text = 'Upload'177 text = 'Upload'
177 return Link('+upload', text)178 return Link('+upload', text, icon='add')
178179
179 def download(self):180 def download(self):
180 text = 'Download'181 text = 'Download'
181 return Link('+export', text)182 return Link('+export', text, icon='download')
182183
183 @enabled_with_permission('launchpad.Edit')184 @enabled_with_permission('launchpad.Edit')
184 def edit(self):185 def edit(self):
185 text = 'Settings'186 text = 'Edit'
186 return Link('+edit', text)187 return Link('+edit', text, icon='edit')
187188
188 @enabled_with_permission('launchpad.TranslationsAdmin')189 @enabled_with_permission('launchpad.TranslationsAdmin')
189 def administer(self):190 def administer(self):
190 text = 'Administer'191 text = 'Administer'
191 return Link('+admin', text)192 return Link('+admin', text, icon='edit')
192193
193194
194class POTemplateSubsetView:195class POTemplateSubsetView:
@@ -781,3 +782,40 @@
781 @property782 @property
782 def text(self):783 def text(self):
783 return smartquote('Template "%s"' % self.context.name)784 return smartquote('Template "%s"' % self.context.name)
785
786
787class BaseSeriesTemplatesView(LaunchpadView):
788 """Show a list of all templates for the Series."""
789
790 is_distroseries = True
791 distroseries = None
792 productseries = None
793 label = "Translation templates"
794 page_title = "All templates"
795
796 def initialize(self, series, is_distroseries=True):
797 self.is_distroseries = is_distroseries
798 if is_distroseries:
799 self.distroseries = series
800 else:
801 self.productseries = series
802
803 def iter_templates(self):
804 potemplateset = getUtility(IPOTemplateSet)
805 return potemplateset.getSubset(
806 productseries=self.productseries,
807 distroseries=self.distroseries,
808 ordered_by_names=True)
809
810 def rowCSSClass(self, template):
811 if template.iscurrent:
812 return "active-template"
813 else:
814 return "inactive-template"
815
816 def isVisible(self, template):
817 if (template.iscurrent or
818 check_permission('launchpad.Edit', template)):
819 return True
820 else:
821 return False
784822
=== modified file 'lib/lp/translations/browser/productseries.py'
--- lib/lp/translations/browser/productseries.py 2009-12-16 15:21:36 +0000
+++ lib/lp/translations/browser/productseries.py 2010-02-16 13:30:44 +0000
@@ -42,8 +42,8 @@
4242
43from lp.translations.browser.poexportrequest import BaseExportView43from lp.translations.browser.poexportrequest import BaseExportView
44from lp.translations.browser.translations import TranslationsMixin44from lp.translations.browser.translations import TranslationsMixin
45from lp.translations.browser.potemplate import BaseSeriesTemplatesView
45from lp.code.interfaces.branchjob import IRosettaUploadJobSource46from lp.code.interfaces.branchjob import IRosettaUploadJobSource
46from lp.translations.interfaces.potemplate import IPOTemplateSet
47from lp.translations.interfaces.productserieslanguage import (47from lp.translations.interfaces.productserieslanguage import (
48 IProductSeriesLanguageSet)48 IProductSeriesLanguageSet)
49from lp.translations.interfaces.translations import (49from lp.translations.interfaces.translations import (
@@ -479,18 +479,12 @@
479 _("The import has been requested."))479 _("The import has been requested."))
480480
481481
482class ProductSeriesTemplatesView(LaunchpadView):482class ProductSeriesTemplatesView(BaseSeriesTemplatesView):
483 """Show a list of all templates for the ProductSeries."""483 """Show a list of all templates for the ProductSeries."""
484484
485 is_distroseries = False485 def initialize(self):
486 label = "Translation templates"486 super(ProductSeriesTemplatesView, self).initialize(
487 page_title = "All templates"487 series=self.context, is_distroseries=False)
488
489 def iter_templates(self):
490 """Return an iterator of all `IPOTemplates` for the series."""
491 potemplateset = getUtility(IPOTemplateSet)
492 return potemplateset.getSubset(productseries=self.context,
493 ordered_by_names=True)
494488
495489
496class LinkTranslationsBranchView(LaunchpadEditFormView):490class LinkTranslationsBranchView(LaunchpadEditFormView):
497491
=== removed file 'lib/lp/translations/stories/productseries/xx-productseries-templates.txt'
--- lib/lp/translations/stories/productseries/xx-productseries-templates.txt 2009-12-28 22:58:18 +0000
+++ lib/lp/translations/stories/productseries/xx-productseries-templates.txt 1970-01-01 00:00:00 +0000
@@ -1,95 +0,0 @@
1Templates view for ProductSeries
2================================
3
4The +templates view for ProductSeries gives an overview of the translation
5templates in this series and provides easy access to the various subpages of
6each template.
7
8
9Preparation
10-----------
11
12To test the ordering of templates in the listing, we need another
13template that is new but must appear at the top of the list.
14
15 >>> login('foo.bar@canonical.com')
16 >>> from zope.component import getUtility
17 >>> from lp.registry.interfaces.product import IProductSet
18 >>> evolution = getUtility(IProductSet).getByName('evolution')
19 >>> evolution_trunk = evolution.getSeries('trunk')
20 >>> template = factory.makePOTemplate(productseries=evolution_trunk,
21 ... name='at-the-top')
22 >>> template = factory.makePOTemplate(productseries=evolution_trunk,
23 ... name='disabled')
24 >>> template.iscurrent = False
25 >>> logout()
26 >>> owner_browser = setupBrowser('Basic test@canonical.com:test')
27
28Getting there
29-------------
30
31To get to the listing of all templates, one needs to use the link
32from the product series translations page.
33
34 >>> user_browser.open(
35 ... 'http://translations.launchpad.dev/evolution/trunk')
36 >>> user_browser.getLink('full list of templates').click()
37 >>> print user_browser.url
38 http://translations.launchpad.dev/evolution/trunk/+templates
39
40
41The templates table
42-------------------
43
44The page shows a table of all templates and links to their subpages.
45Users will not see disabled templates.
46
47 >>> table = find_tag_by_id(user_browser.contents, 'templates_table')
48 >>> print extract_text(table)
49 Template name Last update Actions
50 at-the-top ... Download
51 evolution-2.2 2005-08-25 Download
52 evolution-2.2-test 2006-12-13 Download
53
54If an administrator views this page, links to the templates admin page are
55shown, too.
56
57 >>> admin_browser.open(
58 ... 'http://translations.launchpad.dev/evolution/trunk/+templates')
59 >>> table = find_tag_by_id(admin_browser.contents, 'templates_table')
60 >>> print extract_text(table)
61 Template name Last update Actions
62 at-the-top ... Edit Upload Download Administer
63 disabled (inactive) ... Edit Upload Download Administer
64 evolution-2.2 2005-08-25 Edit Upload Download Administer
65 evolution-2.2-test 2006-12-13 Edit Upload Download Administer
66
67
68Links to the templates
69----------------------
70
71Clicking on a template name will take the user to that template's overview
72page.
73
74 >>> admin_browser.getLink('evolution-2.2').click()
75 >>> print admin_browser.url
76 http://translations.launchpad.dev/evolution/trunk/+pots/evolution-2.2
77
78Clicking on 'Admin' will take the user to the page to administer the template.
79Likewise for the other links for each template.
80
81 >>> admin_browser.open(
82 ... 'http://translations.launchpad.dev/evolution/trunk/+templates')
83 >>> admin_browser.getLink('Admin', index=0).click()
84 >>> print admin_browser.url
85 http://translations.launchpad.dev/evolution/trunk/+pots/at-the-top/+admin
86
87Clicking on 'Edit' will take the user to the page to edit the template
88details, even if the translation of the templates are not active.
89
90 >>> owner_browser.open(
91 ... 'http://translations.launchpad.dev/evolution/trunk/+templates')
92 >>> owner_browser.getLink('Edit', index=1).click()
93 >>> print owner_browser.url
94 http://translations.launchpad.dev/evolution/trunk/+pots/disabled/+edit
95
960
=== renamed file 'lib/lp/translations/stories/distroseries/xx-distroseries-templates.txt' => 'lib/lp/translations/stories/standalone/xx-series-templates.txt'
--- lib/lp/translations/stories/distroseries/xx-distroseries-templates.txt 2009-12-10 12:46:11 +0000
+++ lib/lp/translations/stories/standalone/xx-series-templates.txt 2010-02-16 13:30:44 +0000
@@ -1,5 +1,9 @@
1Templates view for DistroSeries1Templates view for Series
2===============================2=========================
3
4
5Templates for DistroSeries
6--------------------------
37
4The +templates view for DistroSeries gives an overview of the translation8The +templates view for DistroSeries gives an overview of the translation
5templates in this series and provides easy access to the various subpages of9templates in this series and provides easy access to the various subpages of
@@ -19,8 +23,8 @@
19 http://translations.launchpad.dev/ubuntu/hoary/+templates23 http://translations.launchpad.dev/ubuntu/hoary/+templates
2024
2125
22The templates table26Templates view for DistroSeries
23-------------------27-------------------------------
2428
25Full template listing for a distribution series is reached by following29Full template listing for a distribution series is reached by following
26a link from the distribution series translations page.30a link from the distribution series translations page.
@@ -29,18 +33,14 @@
29 ... 'http://translations.launchpad.dev/ubuntu/hoary')33 ... 'http://translations.launchpad.dev/ubuntu/hoary')
30 >>> anon_browser.getLink('full list of templates').click()34 >>> anon_browser.getLink('full list of templates').click()
3135
32Full listing of templates shows source package name, template name and36Full listing of templates shows priority, source package name, template name
33the date of last update for this distribution series.37length, languages and the date of last update for this distribution series.
3438
35 >>> table = find_tag_by_id(anon_browser.contents, 'templates_table')39 >>> table = find_tag_by_id(anon_browser.contents, 'templates_table')
36 >>> print extract_text(table)40 >>> print extract_text(table)
37 Source package Template name Last update41 Priority Source package Template name Length Languages Updated
38 evolution evolution-2.2 2005-05-0642 100 evolution evolution-2.2 22 2 2005-05-06
39 evolution man 2006-08-1443 0 evolution man 1 1 2006-08-14 ...
40 mozilla pkgconf-mozilla 2005-05-06
41 pmount man 2006-08-14
42 pmount pmount 2005-05-06
43
4444
45Logged-in users see a link to all the active translation templates45Logged-in users see a link to all the active translation templates
46on a distribution series translation page.46on a distribution series translation page.
@@ -53,11 +53,9 @@
5353
54 >>> table = find_tag_by_id(user_browser.contents, 'templates_table')54 >>> table = find_tag_by_id(user_browser.contents, 'templates_table')
55 >>> print extract_text(table)55 >>> print extract_text(table)
56 Source package Template name Last update Actions56 Priority Source package Template name ... Updated Actions
57 evolution evolution-2.2 2005-05-06 Download57 100 evolution evolution-2.2 ... 2005-05-06 Download ...
58 ...58 0 mozilla pkgconf-mozilla ... 2005-05-06 Download ...
59 mozilla pkgconf-mozilla 2005-05-06 Download
60 ...
6159
62Administrator can see all editing options.60Administrator can see all editing options.
6361
@@ -69,35 +67,13 @@
6967
70 >>> table = find_tag_by_id(admin_browser.contents, 'templates_table')68 >>> table = find_tag_by_id(admin_browser.contents, 'templates_table')
71 >>> print extract_text(table)69 >>> print extract_text(table)
72 Source package Template name Last update Actions70 Priority Source package ... Updated Actions
73 evolution disabled-template (inactive) 2007-01-05 Edit Upload Download Administer71 0 evolution ... 2007-01-05 Edit Upload Download Administer
74 evolution evolution-2.2 2005-05-06 Edit Upload Download Administer72 100 ...
75 evolution man 2006-08-14 Edit Upload Download Administer73 0 pmount ... 2005-05-06 Edit Upload Download Administer
76 mozilla pkgconf-mozilla 2005-05-06 Edit Upload Download Administer74
77 pmount man 2006-08-14 Edit Upload Download Administer75Translation group owners can administer all templates for their distribution,
78 pmount pmount 2005-05-06 Edit Upload Download Administer76including those that are currently disabled.
79
80Ubuntu Translations Coordinator can administer all templates, including
81those that are currently disabled.
82
83New user is made an owner of an Ubuntu translation group, thus being
84considered a translations administrator for Ubuntu.
85
86 >>> from zope.component import getUtility
87 >>> from canonical.launchpad.ftests import login, logout
88 >>> from canonical.launchpad.interfaces import (
89 ... IDistributionSet, IPersonSet, ILaunchpadCelebrities)
90 >>> login('foo.bar@canonical.com')
91 >>> a_person = factory.makePerson(email='utc-member@example.com',
92 ... name='utc-member', password='test', displayname='Some Guy')
93 >>> utc_member = factory.makeTranslator('ro', person=a_person)
94 >>> utc_team = factory.makeTeam(owner=a_person)
95 >>> utg = factory.makeTranslationGroup(owner=utc_team,
96 ... name="Ubuntu Translation Group")
97 >>> ubuntu = getUtility(ILaunchpadCelebrities).ubuntu
98 >>> ubuntu.translationgroup = utg
99 >>> # Log out so we can go back to using test browsers.
100 >>> logout()
10177
102Visiting the Ubuntu Hoary templates page, translation administrators78Visiting the Ubuntu Hoary templates page, translation administrators
103will see "Edit" and "Administer" links for all templates.79will see "Edit" and "Administer" links for all templates.
@@ -105,7 +81,7 @@
105Trying to edit/administer enabled templates brings them to the81Trying to edit/administer enabled templates brings them to the
106appropriate page.82appropriate page.
10783
108 >>> utc_browser = setupBrowser(auth='Basic utc-member@example.com:test')84 >>> utc_browser = setupDTCBrowser()
109 >>> utc_browser.open(85 >>> utc_browser.open(
110 ... 'http://translations.launchpad.dev/ubuntu/hoary/+templates')86 ... 'http://translations.launchpad.dev/ubuntu/hoary/+templates')
111 >>> utc_browser.getLink(url='ubuntu/hoary/+source/evolution/+pots/evolution-2.2/+edit').click()87 >>> utc_browser.getLink(url='ubuntu/hoary/+source/evolution/+pots/evolution-2.2/+edit').click()
@@ -121,7 +97,6 @@
121Trying to edit/administer disabled templates brings them to the97Trying to edit/administer disabled templates brings them to the
122appropriate page.98appropriate page.
12399
124 >>> utc_browser = setupBrowser(auth='Basic utc-member@example.com:test')
125 >>> utc_browser.open(100 >>> utc_browser.open(
126 ... 'http://translations.launchpad.dev/ubuntu/hoary/+templates')101 ... 'http://translations.launchpad.dev/ubuntu/hoary/+templates')
127 >>> utc_browser.getLink(url='ubuntu/hoary/+source/evolution/+pots/disabled-template/+edit').click()102 >>> utc_browser.getLink(url='ubuntu/hoary/+source/evolution/+pots/disabled-template/+edit').click()
@@ -154,3 +129,84 @@
154 >>> print admin_browser.url129 >>> print admin_browser.url
155 http://translations.../evolution/+pots/disabled-template/+edit130 http://translations.../evolution/+pots/disabled-template/+edit
156131
132
133Templates view for ProductSeries
134--------------------------------
135
136The +templates view for ProductSeries gives an overview of the translation
137templates in this series and provides easy access to the various subpages of
138each template.
139
140
141Preparation
142-----------
143
144To test the ordering of templates in the listing, we need another
145template that is new but must appear at the top of the list.
146
147 >>> login('foo.bar@canonical.com')
148 >>> from zope.component import getUtility
149 >>> from lp.registry.interfaces.product import IProductSet
150 >>> evolution = getUtility(IProductSet).getByName('evolution')
151 >>> evolution_trunk = evolution.getSeries('trunk')
152 >>> template = factory.makePOTemplate(productseries=evolution_trunk,
153 ... name='at-the-top')
154 >>> logout()
155
156
157Getting there
158-------------
159
160To get to the listing of all templates, one needs to use the link
161from the product series translations page.
162
163 >>> user_browser.open(
164 ... 'http://translations.launchpad.dev/evolution/trunk')
165 >>> user_browser.getLink('full list of templates').click()
166 >>> print user_browser.url
167 http://translations.launchpad.dev/evolution/trunk/+templates
168
169
170The templates table
171-------------------
172
173The page shows a table of all templates and links to their subpages.
174
175 >>> table = find_tag_by_id(user_browser.contents, 'templates_table')
176 >>> print extract_text(table)
177 Priority Template name Length Languages Updated Actions
178 0 at-the-top 0 0 ... Download
179 0 evolution-2.2 22 1 2005-08-25 Download
180 0 evolutio... 8 1 2006-12-13 Download
181
182If an administrator views this page, links to the templates admin page are
183shown, too.
184
185 >>> admin_browser.open(
186 ... 'http://translations.launchpad.dev/evolution/trunk/+templates')
187 >>> table = find_tag_by_id(admin_browser.contents, 'templates_table')
188 >>> print extract_text(table)
189 Priority Template name ... Updated Actions
190 0 at-the-top ... ... Edit Upload Download Administer
191 0 evolution-2.2 ... 2005-08-25 Edit Upload Download Administer
192 0 evolutio... ... 2006-12-13 Edit Upload Download Administer
193
194
195Links to the templates
196----------------------
197
198Clicking on a template name will take the user to that template's overview
199page.
200
201 >>> admin_browser.getLink('evolution-2.2').click()
202 >>> print admin_browser.url
203 http://translations.launchpad.dev/evolution/trunk/+pots/evolution-2.2
204
205Clicking on 'Edit' will take the user to the page to edit the template
206details. Likewise for the other links for each template.
207
208 >>> admin_browser.open(
209 ... 'http://translations.launchpad.dev/evolution/trunk/+templates')
210 >>> admin_browser.getLink('Edit').click()
211 >>> print admin_browser.url
212 http://translations.launchpad.dev/evolution/trunk/+pots/at-the-top/+edit
157213
=== 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-16 13:30:44 +0000
@@ -7,8 +7,8 @@
7 <body>7 <body>
8 <div metal:fill-slot="head_epilogue">8 <div metal:fill-slot="head_epilogue">
9 <style type="text/css">9 <style type="text/css">
10 .inactive_links a img{10 .inactive_links a{
11 visibility: hidden;11 background: none;
12 }12 }
13 .inactive_links a{13 .inactive_links a{
14 color: lightgray;14 color: lightgray;
@@ -16,9 +16,11 @@
16 .template_links a{16 .template_links a{
17 padding-right: 1em;17 padding-right: 1em;
18 }18 }
19 td.template_column, th.template_column,
20 td.sourcepackage_column, th.sourcepackage_column {19 td.sourcepackage_column, th.sourcepackage_column {
21 width: 20em;20 width: 10em;
21 }
22 td.template_column, th.template_column {
23 width: 14em;
22 }24 }
23 td.actions_column, th.actions_column {25 td.actions_column, th.actions_column {
24 width: 27em;26 width: 27em;
@@ -26,14 +28,14 @@
26 </style>28 </style>
27 <style tal:condition="view/is_distroseries" type="text/css">29 <style tal:condition="view/is_distroseries" type="text/css">
28 #templates_table {30 #templates_table {
31 width: 81em;
32 }
33 </style>
34 <style tal:condition="not:view/is_distroseries" type="text/css">
35 #templates_table {
29 width: 79em;36 width: 79em;
30 }37 }
31 </style>38 </style>
32 <style tal:condition="not:view/is_distroseries" type="text/css">
33 #templates_table {
34 width: 58em;
35 }
36 </style>
37 <script language="JavaScript" type="text/javascript">39 <script language="JavaScript" type="text/javascript">
38 LPS.use('node-base', 'event-delegate', function(Y) {40 LPS.use('node-base', 'event-delegate', function(Y) {
39 Y.on('domready', function(e) {41 Y.on('domready', function(e) {
@@ -72,10 +74,13 @@
72 <table class="sortable listing" id="templates_table">74 <table class="sortable listing" id="templates_table">
73 <thead>75 <thead>
74 <tr>76 <tr>
77 <th class="priority_column">Priority</th>
75 <th tal:condition="view/is_distroseries"78 <th tal:condition="view/is_distroseries"
76 class="sourcepackage_column">Source package</th>79 class="sourcepackage_column">Source package</th>
77 <th class="template_column">Template name</th>80 <th class="template_column">Template name</th>
78 <th class="lastupdate_column">Last update</th>81 <th class="length_column">Length</th>
82 <th class="languages_column">Languages</th>
83 <th class="lastupdate_column">Updated</th>
79 <th class="actions_column"84 <th class="actions_column"
80 tal:condition="context/required:launchpad.AnyPerson">85 tal:condition="context/required:launchpad.AnyPerson">
81 Actions</th>86 Actions</th>
@@ -83,105 +88,63 @@
83 </thead>88 </thead>
84 <tbody>89 <tbody>
85 <tal:templates repeat="template view/iter_templates">90 <tal:templates repeat="template view/iter_templates">
86 <tal:not-current condition="not: template/iscurrent">91 <tr tal:define="
87 <tal:admin condition="template/required:launchpad.Edit">92 inactive_css_class python:view.rowCSSClass(template)"
88 <tr class="template_row inactive-template">93 tal:condition="python: view.isVisible(template)"
89 <td tal:condition="view/is_distroseries"94 tal:attributes="
90 tal:content="template/sourcepackagename/name"95 class string: template_row ${inactive_css_class}">
91 class="sourcepackage_column">Source package96 <td class="priority_column"
92 </td>97 tal:content="template/priority">7</td>
93 <td class="template_column">98 <td tal:condition="view/is_distroseries"
94 <a tal:attributes="href template/fmt:url">99 tal:content="template/sourcepackagename/name"
95 <span tal:content="template/name">Template name</span>100 class="sourcepackage_column">Source package
96 </a> (inactive)101 </td>
97 </td>102 <td class="template_column">
98 <td class="lastupdate_column">103 <a tal:attributes="href template/fmt:url">
99 <span class="sortkey"104 <span tal:content="template/name">Template name</span>
100 tal:condition="template/date_last_updated"105 </a>
101 tal:content="template/date_last_updated/fmt:datetime">106 <tal:inactive condition="not: template/iscurrent">
102 time sort key107 (inactive)
103 </span>108 </tal:inactive>
104 <span class="lastupdate_column"109 </td>
105 tal:condition="template/date_last_updated"110 <td class="length_column"
106 tal:attributes="111 tal:content="template/getPOTMsgSetsCount">1777</td>
107 title template/date_last_updated/fmt:datetime"112 <td class="languages_column"
108 tal:content="113 tal:content="template/language_count">777</td>
109 template/date_last_updated/fmt:approximatedate"114 <td class="lastupdate_column">
110 >115 <span class="sortkey"
111 2009-09-23116 tal:condition="template/date_last_updated"
112 </span>117 tal:content="template/date_last_updated/fmt:datetime">
113 </td>118 time sort key
114 <td class="actions_column"119 </span>
115 tal:condition="context/required:launchpad.AnyPerson">120 <span class="lastupdate_column"
116 <div class="template_links">121 tal:condition="template/date_last_updated"
117 <tal:maintainer condition="template/required:launchpad.Edit">122 tal:attributes="
118 <a tal:attributes="href string:${template/fmt:url}/+edit;123 title template/date_last_updated/fmt:datetime"
119 title string:Edit ${template/name}'s details">124 tal:content="
120 <img src="/@@/edit" />&nbsp;Edit</a>125 template/date_last_updated/fmt:approximatedate"
121 <a tal:attributes="href string:${template/fmt:url}/+upload;126 >
122 title string:Upload translations to ${template/name}">127 2009-09-23
123 <img src="/@@/add" />&nbsp;Upload</a>128 </span>
124 </tal:maintainer>129 </td>
125 <a tal:attributes="href string:${template/fmt:url}/+export;130 <td class="actions_column"
126 title string:Download translations from ${template/name}">131 tal:condition="context/required:launchpad.AnyPerson">
127 <img src="/@@/download" />&nbsp;Download</a>132 <div class="template_links">
128 <tal:admin condition="template/required:launchpad.TranslationsAdmin">133 <a tal:replace="
129 <a tal:attributes="href string:${template/fmt:url}/+admin;134 structure template/menu:translations/edit/fmt:link
130 title string:Administer ${template/name}">135 " />
131 <img src="/@@/edit" />&nbsp;Administer</a>136 <a tal:replace="
132 </tal:admin>137 structure template/menu:translations/upload/fmt:link
133 </div>138 " />
134 </td>139 <a tal:replace="
135 </tr>140 structure template/menu:translations/download/fmt:link
136 </tal:admin>141 " />
137 </tal:not-current>142 <a tal:replace="
138 <tal:current condition="template/iscurrent">143 structure template/menu:translations/administer/fmt:link
139 <tr class="template_row">144 " />
140 <td tal:condition="view/is_distroseries"145 </div>
141 tal:content="template/sourcepackagename/name"146 </td>
142 class="sourcepackage_column">Source package147 </tr>
143 </td>
144 <td class="template_column"><a tal:attributes="href template/fmt:url"
145 tal:content="template/name">Template name</a></td>
146 <td class="lastupdate_column">
147 <span class="sortkey"
148 tal:condition="template/date_last_updated"
149 tal:content="template/date_last_updated/fmt:datetime">
150 time sort key
151 </span>
152 <span class="lastupdate_column"
153 tal:condition="template/date_last_updated"
154 tal:attributes="
155 title template/date_last_updated/fmt:datetime"
156 tal:content="
157 template/date_last_updated/fmt:approximatedate"
158 >
159 2009-09-23
160 </span>
161 </td>
162 <td class="actions_column"
163 tal:condition="context/required:launchpad.AnyPerson">
164 <div class="template_links">
165 <tal:maintainer condition="template/required:launchpad.Edit">
166 <a tal:attributes="href string:${template/fmt:url}/+edit;
167 title string:Edit ${template/name}'s details">
168 <img src="/@@/edit" />&nbsp;Edit</a>
169 <a tal:attributes="href string:${template/fmt:url}/+upload;
170 title string:Upload translations to ${template/name}">
171 <img src="/@@/add" />&nbsp;Upload</a>
172 </tal:maintainer>
173 <a tal:attributes="href string:${template/fmt:url}/+export;
174 title string:Download translations from ${template/name}">
175 <img src="/@@/download" />&nbsp;Download</a>
176 <tal:admin condition="template/required:launchpad.TranslationsAdmin">
177 <a tal:attributes="href string:${template/fmt:url}/+admin;
178 title string:Administer ${template/name}">
179 <img src="/@@/edit" />&nbsp;Administer</a>
180 </tal:admin>
181 </div>
182 </td>
183 </tr>
184 </tal:current>
185 </tal:templates>148 </tal:templates>
186 </tbody>149 </tbody>
187 </table>150 </table>