launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #24820
[Merge] ~ilasc/launchpad:add-person-livefs-index-view into launchpad:master
Ioana Lasc has proposed merging ~ilasc/launchpad:add-person-livefs-index-view into launchpad:master.
Commit message:
Add Person:+livefs index view
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
Related bugs:
Bug #1332479 in Launchpad itself: "Cannot view +livefs page"
https://bugs.launchpad.net/launchpad/+bug/1332479
For more details, see:
https://code.launchpad.net/~ilasc/launchpad/+git/launchpad/+merge/385042
Added livefs index view to provide the UI list of all the live filesystems owned by a given person.
--
Your team Launchpad code reviewers is requested to review the proposed merge of ~ilasc/launchpad:add-person-livefs-index-view into launchpad:master.
diff --git a/lib/lp/registry/browser/configure.zcml b/lib/lp/registry/browser/configure.zcml
index b8dc1bb..669d444 100644
--- a/lib/lp/registry/browser/configure.zcml
+++ b/lib/lp/registry/browser/configure.zcml
@@ -1231,6 +1231,13 @@
template="../templates/person-oauth-tokens.pt"
/>
<browser:page
+ name="+livefs"
+ for="lp.registry.interfaces.person.IPerson"
+ class="lp.registry.browser.person.PersonLiveFSView"
+ permission="launchpad.View"
+ template="../templates/livefs-index.pt"
+ />
+ <browser:page
name="+index"
for="lp.registry.interfaces.person.ITeam"
class="lp.registry.browser.team.TeamIndexView"
diff --git a/lib/lp/registry/browser/person.py b/lib/lp/registry/browser/person.py
index 8677ecd..3e3c92b 100644
--- a/lib/lp/registry/browser/person.py
+++ b/lib/lp/registry/browser/person.py
@@ -27,6 +27,7 @@ __all__ = [
'PersonIndexView',
'PersonKarmaView',
'PersonLanguagesView',
+ 'PersonLiveFSView',
'PersonNavigation',
'PersonOAuthTokensView',
'PersonOverviewMenu',
@@ -3620,6 +3621,32 @@ class PersonOAuthTokensView(LaunchpadView):
canonical_url(self.context, view_name='+oauth-tokens'))
+class PersonLiveFSView(LaunchpadView):
+ """Default view for the list of live filesystems owned by a person."""
+ page_title = 'LiveFS'
+
+ @property
+ def label(self):
+ return 'Live filesystems for %s' % self.context.name
+
+ @property
+ def title(self):
+ return self.context.name
+
+ @property
+ def livefs(self):
+ livefs = getUtility(ILiveFSSet).getByPerson(self.context)
+ return livefs.order_by('name')
+
+ @property
+ def livefs_navigator(self):
+ return BatchNavigator(self.livefs, self.request)
+
+ @cachedproperty
+ def count(self):
+ return self.livefs_navigator.batch.total()
+
+
class PersonTimeZoneForm(Interface):
time_zone = Choice(
diff --git a/lib/lp/registry/browser/tests/test_person.py b/lib/lp/registry/browser/tests/test_person.py
index 626cab4..9b5f7be 100644
--- a/lib/lp/registry/browser/tests/test_person.py
+++ b/lib/lp/registry/browser/tests/test_person.py
@@ -1,10 +1,14 @@
-# Copyright 2009-2017 Canonical Ltd. This software is licensed under the
+# -*- coding: utf-8 -*-
+# Copyright 2009-2020 Canonical Ltd. This software is licensed under the
# GNU Affero General Public License version 3 (see the file LICENSE).
+from __future__ import unicode_literals
+
__metaclass__ = type
import doctest
import email
+from operator import attrgetter
import re
from textwrap import dedent
@@ -43,6 +47,7 @@ from lp.registry.model.karma import KarmaCategory
from lp.registry.model.milestone import milestone_sort_key
from lp.scripts.garbo import PopulateLatestPersonSourcePackageReleaseCache
from lp.services.config import config
+from lp.services.features.testing import FeatureFixture
from lp.services.identity.interfaces.account import AccountStatus
from lp.services.identity.interfaces.emailaddress import IEmailAddressSet
from lp.services.log.logger import DevNullLogger
@@ -61,6 +66,7 @@ from lp.soyuz.enums import (
ArchiveStatus,
PackagePublishingStatus,
)
+from lp.soyuz.interfaces.livefs import LIVEFS_FEATURE_FLAG
from lp.soyuz.tests.test_publishing import SoyuzTestPublisher
from lp.testing import (
ANONYMOUS,
@@ -85,6 +91,7 @@ from lp.testing.layers import (
from lp.testing.matchers import HasQueryCount
from lp.testing.pages import (
extract_text,
+ find_main_content,
find_tag_by_id,
setupBrowserForUser,
)
@@ -1274,6 +1281,60 @@ class TestPersonRelatedProjectsView(TestCaseWithFactory):
self.assertThat(view(), next_match)
+class TestPersonLiveFSView(BrowserTestCase, TestCaseWithFactory):
+ layer = DatabaseFunctionalLayer
+
+ def setUp(self):
+ super(TestPersonLiveFSView, self).setUp()
+ self.useFixture(FeatureFixture({LIVEFS_FEATURE_FLAG: "on"}))
+ self.person = self.factory.makePerson(
+ name="test-person", displayname="Test Person")
+
+ def makeLiveFS(self, count=1):
+ with person_logged_in(self.person):
+ return [self.factory.makeLiveFS(
+ registrant=self.person, owner=self.person)
+ for _ in range(count)]
+
+ def test_displays_live_filesystem(self):
+ livefs = self.factory.makeLiveFS(
+ registrant=self.person, owner=self.person)
+ browser = self.getViewBrowser(self.person, "+livefs", user=self.person)
+ main_text = extract_text(find_main_content(browser.contents))
+
+ with person_logged_in(self.person):
+ self.assertIn(livefs.name, main_text)
+
+ def test_displays_no_livefs_system(self):
+ browser = self.getViewBrowser(self.person, "+livefs", user=self.person)
+ main_text = extract_text(find_main_content(browser.contents))
+ with person_logged_in(self.person):
+ self.assertIn(
+ "There are no live filesystems for %s"
+ % self.person.name,
+ main_text)
+
+ def test_paginates_live_filesystems(self):
+ batch_size = 5
+ self.pushConfig("launchpad", default_batch_size=batch_size)
+ livefs = self.makeLiveFS(10)
+ browser = self.getViewBrowser(self.person, "+livefs", user=self.person)
+ main_text = extract_text(find_main_content(browser.contents))
+ no_wrap_main_text = main_text.replace('\n', ' ')
+ with person_logged_in(self.person):
+ self.assertIn(
+ "There are 10 live filesystems registered for %s"
+ % self.person.name,
+ no_wrap_main_text)
+ self.assertIn("1 → 5 of 10 results", no_wrap_main_text)
+ self.assertIn("First • Previous • Next • Last", no_wrap_main_text)
+
+ # Assert we're listing the first set of live filesystems
+ items = sorted(livefs, key=attrgetter('name'))
+ for lfs in items[:batch_size]:
+ self.assertIn(lfs.name, main_text)
+
+
class TestPersonRelatedPackagesFailedBuild(TestCaseWithFactory):
"""The related packages views display links to failed builds."""
diff --git a/lib/lp/registry/templates/livefs-index.pt b/lib/lp/registry/templates/livefs-index.pt
new file mode 100644
index 0000000..345397f
--- /dev/null
+++ b/lib/lp/registry/templates/livefs-index.pt
@@ -0,0 +1,55 @@
+<html
+ xmlns="http://www.w3.org/1999/xhtml"
+ xmlns:tal="http://xml.zope.org/namespaces/tal"
+ xmlns:metal="http://xml.zope.org/namespaces/metal"
+ xmlns:i18n="http://xml.zope.org/namespaces/i18n"
+ metal:use-macro="view/macro:page/main_side"
+ i18n:domain="launchpad"
+>
+
+<body>
+ <metal:side fill-slot="side">
+ <div tal:replace="structure context/@@+global-actions"/>
+ </metal:side>
+
+ <div metal:fill-slot="main">
+ <div class="main-portlet">
+ <p tal:define="count view/count"
+ tal:condition="count">
+ <span tal:condition="python: count == 1">
+ There is <strong>1</strong> live filesystem</span>
+ <span tal:condition="python: count != 1">
+ There are <strong tal:content="count" /> live filesystems
+ </span>
+ registered for <tal:context replace="view/title" />.
+ </p>
+ <p tal:condition="not: view/count">
+ There are no live filesystems for <tal:context replace="view/title" />.
+ </p>
+ </div>
+
+ <table class="listing" id="mirrors_list" tal:condition="view/count">
+ <tbody>
+ <tr class="head">
+ <th>Name</th>
+ <th>Owner</th>
+ <th>Date created</th>
+ </tr>
+
+ <tr tal:repeat="filesystem view/livefs">
+ <td>
+ <a tal:content="filesystem/name"
+ tal:attributes="href filesystem/fmt:url" />
+ </td>
+ <td tal:content="structure filesystem/owner/fmt:link" />
+ <td tal:content="filesystem/date_created/fmt:displaydate" />
+ </tr>
+ </tbody>
+ </table>
+
+ <tal:navigation
+ replace="structure view/livefs_navigator/@@+navigation-links-lower" />
+ </div>
+
+</body>
+</html>