[extensions-web] Add new UI so that extension authors can see and manipulate their versions



commit 4588378633ccc7f187c1c01ced69c7c3fd35827a
Author: Jasper St. Pierre <jstpierre mecheye net>
Date:   Thu Nov 24 01:36:15 2011 -0500

    Add new UI so that extension authors can see and manipulate their versions
    
    With the new multiversion feature, "what version is the user getting?"
    doesn't have a straightforward answer. Add a new UI to the bottom of extension
    details panes that gives extension authors the ability to see which version
    of an extension the user is getting based on their shell version, and the
    ability to activate or deactivate extension versions.

 sweettooth/extensions/models.py                    |   10 ++++
 .../extensions/templates/extensions/detail.html    |    1 +
 .../templates/extensions/detail_edit.html          |   48 +++++++++++++++++++-
 sweettooth/extensions/urls.py                      |    7 +++-
 sweettooth/extensions/views.py                     |   19 +++++++-
 sweettooth/static/css/sweettooth.css               |   12 +++++
 sweettooth/static/js/extensions.js                 |   24 ++++++++++
 sweettooth/static/js/main.js                       |   23 +++++++++
 8 files changed, 140 insertions(+), 4 deletions(-)
---
diff --git a/sweettooth/extensions/models.py b/sweettooth/extensions/models.py
index 67069f5..3f44363 100644
--- a/sweettooth/extensions/models.py
+++ b/sweettooth/extensions/models.py
@@ -28,6 +28,7 @@ STATUSES = {
 }
 
 VISIBLE_STATUSES = (STATUS_ACTIVE,)
+LIVE_STATUSES = (STATUS_ACTIVE, STATUS_INACTIVE)
 REJECTED_STATUSES = (STATUS_REJECTED,)
 REVIEWED_STATUSES = (STATUS_REJECTED, STATUS_INACTIVE, STATUS_ACTIVE)
 
@@ -322,6 +323,15 @@ class ExtensionVersion(models.Model):
     def get_status_class(self):
         return STATUSES[self.status].lower()
 
+    def is_live(self):
+        return self.status in LIVE_STATUSES
+
+    def is_active(self):
+        return self.status == STATUS_ACTIVE
+
+    def is_inactive(self):
+        return self.status == STATUS_INACTIVE
+
 submitted_for_review = Signal(providing_args=["request", "version"])
 reviewed = Signal(providing_args=["request", "version", "review"])
 status_changed = Signal(providing_args=["version", "log"])
diff --git a/sweettooth/extensions/templates/extensions/detail.html b/sweettooth/extensions/templates/extensions/detail.html
index 2a6bb0f..9c62c93 100644
--- a/sweettooth/extensions/templates/extensions/detail.html
+++ b/sweettooth/extensions/templates/extensions/detail.html
@@ -24,6 +24,7 @@
 
     <div class="extension"
          data-uuid="{{ extension.uuid }}"
+         data-ver-url-base="{% url extensions-version-detail ext_pk=extension.pk slug=extension.slug pk='' %}"
          data-svm="{{ shell_version_map }}">
       <div class="switch{% if is_rejected %} insensitive{% endif %}"></div>
 
diff --git a/sweettooth/extensions/templates/extensions/detail_edit.html b/sweettooth/extensions/templates/extensions/detail_edit.html
index b6ee5f8..d201749 100644
--- a/sweettooth/extensions/templates/extensions/detail_edit.html
+++ b/sweettooth/extensions/templates/extensions/detail_edit.html
@@ -42,8 +42,52 @@
   </div>
   {% endif %}
 
-  {% if not is_preview %}
-    <a href="{% url extensions-upload-file pk=extension.pk %}">Upload a new version</a>
+  {% if not is_preview and is_multiversion %}
+    <h2 class="expandy_header expanded"> Admin </h2>
+    <ul>
+      <li>
+        <a href="{% url extensions-upload-file pk=extension.pk %}">Upload a new version</a>
+      </li>
+    </ul>
+
+    <h2 class="expandy_header expanded"> Versions </h2>
+    <table>
+      <thead> <tr>
+        <th> Version </th> <th> Status </th> <th> Shell Versions </th> <th> Actions </th>
+      </tr> </thead>
+      <tbody>
+      {% for version in all_versions %}
+      <tr data-pk="{{ version.pk }}">
+        <td> <a href="{% url extensions-version-detail ext_pk=extension.pk slug=extension.slug pk=version.pk %}"> {{ version.version }} </a> </td>
+        <td>
+          <span class="{{ version.get_status_class }}">{{ version.get_status_display }}</span>
+        </td>
+        <td>
+          {% for shell_version in version.shell_versions.all %}
+          <code class="extension_shell_versions">{{ shell_version.version_string }}</code>
+          {% endfor %}
+        </td>
+        {% if version.is_live %}
+        <td class="extension_status_toggle{% if version.is_active %} visible{% endif %}">
+          <a href="{% url extensions-ajax-set-status-inactive %}">Inactivate</a>
+        </td>
+        <td class="extension_status_toggle{% if not version.is_active %} visible{% endif %}">
+          <a href="{% url extensions-ajax-set-status-active %}">Activate</a>
+        </td>
+        {% endif %}
+
+      </tr>
+      {% endfor %}
+      </tbody>
+    </table>
+
+    <h2 class="expandy_header expanded"> Shell Versions </h2>
+    <p> Shell versions mapped to their associated extension versions </p>
+    <table id="extension_shell_versions_info">
+      <thead> <th> Shell Version </th> <th> Extension Version </th> </thead>
+      <tbody>
+      </tbody>
+    </table>
   {% endif %}
 {% endblock %}
 
diff --git a/sweettooth/extensions/urls.py b/sweettooth/extensions/urls.py
index 0a7624a..c0bba63 100644
--- a/sweettooth/extensions/urls.py
+++ b/sweettooth/extensions/urls.py
@@ -16,6 +16,11 @@ ajax_patterns = patterns('',
     url(r'^upload/screenshot/(?P<pk>\d+)', views.ajax_upload_screenshot_view, name='extensions-ajax-screenshot'),
     url(r'^upload/icon/(?P<pk>\d+)', views.ajax_upload_icon_view, name='extensions-ajax-icon'),
     url(r'^detail/', views.ajax_details_view, name='extensions-ajax-details'),
+
+    url(r'^set-status/active/', views.ajax_set_status_view,
+        dict(newstatus=models.STATUS_ACTIVE), name='extensions-ajax-set-status-active'),
+    url(r'^set-status/inactive/', views.ajax_set_status_view,
+        dict(newstatus=models.STATUS_INACTIVE), name='extensions-ajax-set-status-inactive'),
 )
 
 shell_patterns = patterns('',
@@ -37,7 +42,7 @@ urlpatterns = patterns('',
         name='extensions-index'),
 
     # we ignore PK of extension, and get extension from version PK
-    url(r'^extension/(?P<ext_pk>\d+)/(?P<slug>.+)/version/(?P<pk>\d+)/$',
+    url(r'^extension/(?P<ext_pk>\d+)/(?P<slug>.+)/version/(?P<pk>.*)/$',
         views.extension_version_view, name='extensions-version-detail'),
 
     url(r'^extension/(?P<pk>\d+)/(?P<slug>.+)/$',
diff --git a/sweettooth/extensions/views.py b/sweettooth/extensions/views.py
index ea38ddb..755abd5 100644
--- a/sweettooth/extensions/views.py
+++ b/sweettooth/extensions/views.py
@@ -113,7 +113,9 @@ def extension_view(request, obj, **kwargs):
 
     context = dict(shell_version_map = json.dumps(shell_version_map),
                    extension = extension,
-                   is_visible = True)
+                   all_versions = extension.versions.order_by('-version'),
+                   is_visible = True,
+                   is_multiversion = True)
     return render(request, template_name, context)
 
 @model_view(models.ExtensionVersion)
@@ -267,6 +269,21 @@ def ajax_query_view(request):
     extensions = models.Extension.objects.filter(**query_params)
     return [ajax_details(e) for e in extensions]
 
+ ajax_view
+def ajax_set_status_view(request, newstatus):
+    pk = request.GET['pk']
+
+    version = get_object_or_404(models.ExtensionVersion, pk=pk)
+    extension = version.extension
+
+    if not extension.user_can_edit(request.user):
+        return HttpResponseForbidden()
+
+    version.status = newstatus
+    version.save()
+
+    return build_shell_version_map(extension.visible_versions)
+
 @login_required
 def upload_file(request, pk):
     if pk is None:
diff --git a/sweettooth/static/css/sweettooth.css b/sweettooth/static/css/sweettooth.css
index 59795c3..9d43ea7 100644
--- a/sweettooth/static/css/sweettooth.css
+++ b/sweettooth/static/css/sweettooth.css
@@ -361,6 +361,18 @@ li.extension:last-child {
     padding-left: 16px;
 }
 
+.extension table {
+    width: 100%;
+}
+
+.extension_status_toggle {
+    display: none;
+}
+
+.extension_status_toggle.visible {
+    display: table-cell;
+}
+
 #error_report input[name=can_contact] {
     margin-left: 1em;
 }
diff --git a/sweettooth/static/js/extensions.js b/sweettooth/static/js/extensions.js
index 6fd1700..4842aba 100644
--- a/sweettooth/static/js/extensions.js
+++ b/sweettooth/static/js/extensions.js
@@ -6,6 +6,30 @@ function($, messages, dbusProxy, extensionUtils) {
 
     var ExtensionState = extensionUtils.ExtensionState;
 
+    $.fn.buildShellVersionsInfo = function () {
+        return this.each(function() {
+            var $table = $(this);
+            var $tbody = $table.find('tbody');
+            var $extension = $table.parents('.extension');
+            var urlBase = $extension.data('ver-url-base');
+
+            $tbody.children().remove();
+
+            var svm = $extension.data('svm');
+            for (var version in svm) {
+                if (!svm.hasOwnProperty(version))
+                    continue;
+
+                var vpk = extensionUtils.grabProperExtensionVersion(svm, version);
+
+                var $tr = $('<tr>').appendTo($tbody);
+
+                $('<td>').append($('<code>').text(version)).appendTo($tr);
+                $('<td>').append($('<a>', {'href': urlBase + vpk.pk}).text(vpk.version)).appendTo($tr);
+            }
+        });
+    };
+
     // While technically we shouldn't have mismatched API versions,
     // the plugin doesn't check whether the Shell matches, so if someone
     // is running with an old Shell version but a newer plugin, error out.
diff --git a/sweettooth/static/js/main.js b/sweettooth/static/js/main.js
index d6ce266..9cb0c15 100644
--- a/sweettooth/static/js/main.js
+++ b/sweettooth/static/js/main.js
@@ -101,6 +101,29 @@ require(['jquery', 'messages', 'extensions',
             $(this).toggleClass('expanded').next().slideToggle();
         }).not('.expanded').next().hide();
 
+        $('#extension_shell_versions_info').buildShellVersionsInfo();
+
+        $('.extension_status_toggle a').click(function() {
+            var href = $(this).attr('href');
+            var pk = $(this).parents('tr').data('pk');
+            var $ext = $(this).parents('.extension');
+
+            var req = $.ajax({
+                type: 'GET',
+                dataType: 'json',
+                data: { pk: pk },
+                url: href
+            });
+
+            req.done(function(newShellVersionMap) {
+                $ext.data('svm', newShellVersionMap);
+                $('#extension_shell_versions_info').buildShellVersionsInfo();
+                $('.extension_status_toggle').toggleClass('visible');
+            });
+
+            return false;
+        });
+
         if (window._SW)
             try {
                 window._SW();



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]