diff --git a/apps/devhub/templates/devhub/versions/list.html b/apps/devhub/templates/devhub/versions/list.html index 5985e9688d2..cba5143973d 100644 --- a/apps/devhub/templates/devhub/versions/list.html +++ b/apps/devhub/templates/devhub/versions/list.html @@ -50,6 +50,14 @@

{{ _('Current Status') }}

{% endif %}
+ {% if position %} + + {% trans pos=position['pos'], total=position['total'] %} + Queue Position: {{ pos }} of {{ total }} + {% endtrans %} + · + + {% endif %} {% if check_addon_ownership(request, addon, dev=True) %} {% set req = {amo.STATUS_PUBLIC: _('Request Full Review'), amo.STATUS_LITE: _('Request Preliminary Review')} %} diff --git a/apps/devhub/tests/test_views.py b/apps/devhub/tests/test_views.py index a5babd51796..e4a734f5b30 100644 --- a/apps/devhub/tests/test_views.py +++ b/apps/devhub/tests/test_views.py @@ -2702,6 +2702,50 @@ def setUp(self): assert self.client.login(username='del@icio.us', password='password') +class TestQueuePosition(UploadTest): + fixtures = ['base/apps', 'base/users', + 'base/addon_3615', 'base/platforms'] + + def setUp(self): + super(TestQueuePosition, self).setUp() + + self.url = reverse('devhub.versions.add_file', + args=[self.addon.slug, self.version.id]) + self.edit_url = reverse('devhub.versions.edit', + args=[self.addon.slug, self.version.id]) + files = self.version.files.all()[0] + files.platform_id = amo.PLATFORM_LINUX.id + files.save() + + def test_not_in_queue(self): + r = self.client.get(reverse('devhub.versions', args=[self.addon.slug])) + + eq_(self.addon.status, amo.STATUS_PUBLIC) + eq_(pq(r.content)('.version-status-actions .dark').length, 0) + + def test_in_queue(self): + statuses = [(amo.STATUS_NOMINATED, amo.STATUS_NOMINATED), + (amo.STATUS_PUBLIC, amo.STATUS_UNREVIEWED), + (amo.STATUS_LITE, amo.STATUS_UNREVIEWED)] + + for addon_status in statuses: + self.addon.status = addon_status[0] + self.addon.save() + + file = self.addon.latest_version.files.all()[0] + file.status = addon_status[1] + file.save() + + r = self.client.get(reverse('devhub.versions', + args=[self.addon.slug])) + doc = pq(r.content) + + span = doc('.version-status-actions .dark') + + eq_(span.length, 1) + assert "Queue Position: 1 of 1" in span.text() + + class TestVersionAddFile(UploadTest): fixtures = ['base/apps', 'base/users', 'base/addon_3615', 'base/platforms'] diff --git a/apps/devhub/views.py b/apps/devhub/views.py index 79a37331dcd..d548a0920a9 100644 --- a/apps/devhub/views.py +++ b/apps/devhub/views.py @@ -40,6 +40,7 @@ from addons.models import Addon, AddonUser from addons.views import BaseFilter from devhub.models import ActivityLog, BlogPost, RssKey, SubmitStep +from editors.helpers import get_position from files.models import File, FileUpload from files.utils import parse_addon from translations.models import delete_translation @@ -913,9 +914,11 @@ def version_list(request, addon_id, addon): qs = addon.versions.order_by('-created').transform(Version.transformer) versions = amo.utils.paginate(request, qs) new_file_form = forms.NewVersionForm(None, addon=addon) + data = {'addon': addon, 'versions': versions, 'new_file_form': new_file_form, + 'position': get_position(addon), 'timestamp': int(time.time())} return jingo.render(request, 'devhub/versions/list.html', data) diff --git a/apps/editors/helpers.py b/apps/editors/helpers.py index 2c06db23927..d2c73661df8 100644 --- a/apps/editors/helpers.py +++ b/apps/editors/helpers.py @@ -219,6 +219,26 @@ def send_mail(template, subject, emails, context): use_blacklist=False) +def get_position(addon): + version = addon.latest_version + + if not version: + return False + + q = version.current_queue + if not q: + return False + + mins_query = q.objects.filter(id=addon.id) + if mins_query.count() > 0: + mins = mins_query[0].waiting_time_min + pos = q.objects.having('waiting_time_min >=', mins).count() + total = q.objects.count() + return dict(mins=mins, pos=pos, total=total) + + return False + + class ReviewHelper: """ A class that builds enough to render the form back to the user and diff --git a/apps/editors/tests/test_views.py b/apps/editors/tests/test_views.py index 0b7755cf822..6554307c4cd 100644 --- a/apps/editors/tests/test_views.py +++ b/apps/editors/tests/test_views.py @@ -20,6 +20,7 @@ from applications.models import Application from devhub.models import ActivityLog from editors.models import EditorSubscription, EventLog +from editors.helpers import get_position from files.models import Platform, File import reviews from reviews.models import Review, ReviewFlag @@ -430,6 +431,11 @@ def addon_file(self, *args, **kw): a = create_addon_file(*args, **kw) self.versions[unicode(a['addon'].name)] = a['version'] + def get_queue(self, version_name): + addon_id = self.versions[version_name].addon.id + version = Addon.objects.get(pk=addon_id).latest_version + eq_(version.current_queue.objects.filter(id=addon_id).count(), 1) + class TestQueueBasics(QueueTest): @@ -688,6 +694,10 @@ def test_breadcrumbs(self): eq_(list_items.eq(0).find('a').text(), "Editor Tools") eq_(list_items.eq(1).text(), "Pending Updates") + def test_get_queue(self): + self.get_queue(u'Pending One') + self.get_queue(u'Pending Two') + class TestNominatedQueue(QueueTest): @@ -743,6 +753,10 @@ def test_queue_count(self): eq_(doc('.tabnav li a:eq(0)').attr('href'), reverse('editors.queue_nominated')) + def test_get_queue(self): + self.get_queue(u'Nominated One') + self.get_queue(u'Nominated Two') + class TestPreliminaryQueue(QueueTest): @@ -778,6 +792,10 @@ def test_breadcrumbs(self): eq_(list_items.eq(0).find('a').text(), "Editor Tools") eq_(list_items.eq(1).text(), "Preliminary Reviews") + def test_get_queue(self): + self.get_queue(u'Prelim One') + self.get_queue(u'Prelim Two') + class TestModeratedQueue(QueueTest): fixtures = ['base/users', 'base/apps', 'reviews/dev-reply.json'] diff --git a/apps/versions/models.py b/apps/versions/models.py index 8bc0bef070b..cf73a8e5708 100644 --- a/apps/versions/models.py +++ b/apps/versions/models.py @@ -151,6 +151,22 @@ def delete(self): amo.log(amo.LOG.DELETE_VERSION, self.addon, str(self.version)) super(Version, self).delete() + @property + def current_queue(self): + """Return the current queue, or None if not in a queue.""" + from editors.models import (ViewPendingQueue, ViewFullReviewQueue, + ViewPreliminaryQueue) + + if self.addon.status in [amo.STATUS_NOMINATED, + amo.STATUS_LITE_AND_NOMINATED]: + return ViewFullReviewQueue + elif self.addon.status == amo.STATUS_PUBLIC: + return ViewPendingQueue + elif self.addon.status in [amo.STATUS_LITE, amo.STATUS_UNREVIEWED]: + return ViewPreliminaryQueue + + return None + @amo.cached_property(writable=True) def all_activity(self): from devhub.models import VersionLog # yucky diff --git a/media/css/zamboni/developers.css b/media/css/zamboni/developers.css index 33f9b20f309..45e9ce5d380 100644 --- a/media/css/zamboni/developers.css +++ b/media/css/zamboni/developers.css @@ -705,6 +705,9 @@ form .char-count b { .item-actions a { color: #aaa; } +.item-actions .dark { + color: #444; +} #dashboard .item:hover .item-actions { color: #555; }