]> git.ozlabs.org Git - patchwork/commitdiff
Initial bundle reordering support
authorJeremy Kerr <jk@ozlabs.org>
Thu, 29 Jan 2009 06:38:46 +0000 (17:38 +1100)
committerJeremy Kerr <jk@ozlabs.org>
Thu, 29 Jan 2009 06:38:46 +0000 (17:38 +1100)
todo:
 * implement ajax reorder api
 * finish migration script
 * order patches in bundle view

Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
apps/patchwork/models.py
htdocs/js/bundle.js [new file with mode: 0644]
htdocs/js/jquery-1.2.6.js [new symlink]
htdocs/js/jquery.tablednd_0_5.js [new symlink]
lib/sql/migration/005-bundle-patch-ordering.sql [new file with mode: 0644]
templates/patchwork/bundle.html
templates/patchwork/patch-list.html

index 162fa21d68f2a6dcf4dc2bc054dc5ae429d46aa7..d0c2a6ed5d4c467fe289aa2ea1eddc64096c6786 100644 (file)
@@ -289,12 +289,20 @@ class Bundle(models.Model):
     owner = models.ForeignKey(User)
     project = models.ForeignKey(Project)
     name = models.CharField(max_length = 50, null = False, blank = False)
-    patches = models.ManyToManyField(Patch)
+    patches = models.ManyToManyField(Patch, through = 'BundlePatch')
     public = models.BooleanField(default = False)
 
     def n_patches(self):
         return self.patches.all().count()
 
+    def append_patch(self, patch):
+        # todo: use the aggregate queries in django 1.1
+        orders = BundlePatch.objects.filter(bundle = self).values('order')
+        max_order = max([ v for (k, v) in orders])
+
+        bp = BundlePatch.objects.create(bundle = self, patch = patch, order = max_order + 1)
+        bp.save()
+
     class Meta:
         unique_together = [('owner', 'name')]
 
@@ -313,6 +321,14 @@ class Bundle(models.Model):
         return '\n'.join([p.mbox().as_string(True) \
                         for p in self.patches.all()])
 
+class BundlePatch(models.Model):
+    patch = models.ForeignKey(Patch)
+    bundle = models.ForeignKey(Bundle)
+    order = models.IntegerField()
+
+    class Meta:
+        unique_together = [('bundle', 'patch'), ('bundle', 'order')]
+
 class UserPersonConfirmation(models.Model):
     user = models.ForeignKey(User)
     email = models.CharField(max_length = 200)
diff --git a/htdocs/js/bundle.js b/htdocs/js/bundle.js
new file mode 100644 (file)
index 0000000..dc4fb9c
--- /dev/null
@@ -0,0 +1,41 @@
+function parse_patch_id(id_str)
+{
+    var i;
+
+    i = id_str.indexOf(':');
+    if (i == -1)
+        return null;
+
+    return id_str.substring(i + 1);
+}
+
+function bundle_handle_drop(table, row)
+{
+    var relative, relation, current;
+    var relative_id, current_id;
+
+    current = $(row);
+    relative = $(current).prev();
+    relation = 'after';
+
+    /* if we have no previous row, position ourselves before the next
+     * row instead */
+    if (!relative.length) {
+        relative = current.next();
+        relation = 'before';
+
+        if (!relative)
+            return;
+    }
+
+    current_id = parse_patch_id(current.attr('id'));
+    relative_id = parse_patch_id(relative.attr('id'));
+
+    alert("put patch " + current_id + " " + relation + " " + relative_id);
+}
+
+$(document).ready(function() {
+    $("#patchlist").tableDnD({
+        onDrop: bundle_handle_drop
+    });
+});
diff --git a/htdocs/js/jquery-1.2.6.js b/htdocs/js/jquery-1.2.6.js
new file mode 120000 (symlink)
index 0000000..cb24de6
--- /dev/null
@@ -0,0 +1 @@
+../../lib/packages/jquery/jquery-1.2.6.js
\ No newline at end of file
diff --git a/htdocs/js/jquery.tablednd_0_5.js b/htdocs/js/jquery.tablednd_0_5.js
new file mode 120000 (symlink)
index 0000000..5918e24
--- /dev/null
@@ -0,0 +1 @@
+../../lib/packages/jquery/jquery.tablednd_0_5.js
\ No newline at end of file
diff --git a/lib/sql/migration/005-bundle-patch-ordering.sql b/lib/sql/migration/005-bundle-patch-ordering.sql
new file mode 100644 (file)
index 0000000..9f5bcf3
--- /dev/null
@@ -0,0 +1,9 @@
+BEGIN;
+ALTER TABLE patchwork_bundle_patches RENAME TO patchwork_bundlepatch;
+ALTER TABLE patchwork_bundlepatch ADD COLUMN "order" INTEGER NULL;
+UPDATE patchwork_bundlepatch SET "order" =
+    (SELECT COALESCE(max("order"), 0) + 1 FROM patchwork_bundlepatch AS p2
+        WHERE p2.bundle_id = patchwork_bundlepatch.bundle_id);
+ALTER TABLE patchwork_bundlepatch ALTER COLUMN "order" SET NOT NULL;
+ALTER TABLE patchwork_bundlepatch ADD UNIQUE("bundle_id", "order");
+COMMIT;
index 68bf5705bed7af347dcbbaabf024906984bf3379..d9a2785c52e67c7f52e75653289f7e589aadba2c 100644 (file)
@@ -2,6 +2,17 @@
 
 {% load person %}
 
+{% block headers %}
+  <script language="JavaScript" type="text/javascript"
+   src="/js/jquery-1.2.6.js">
+  </script>
+  <script language="JavaScript" type="text/javascript"
+   src="/js/jquery.tablednd_0_5.js">
+  </script>
+  <script language="JavaScript" type="text/javascript"
+   src="/js/bundle.js">
+  </script>
+{% endblock %}
 {% block title %}{{project.name}}{% endblock %}
 {% block heading %}bundle: {{bundle.name}}{% endblock %}
 
index 4c6b8a508f18a60fae3ac5ff1ff60d227b768489..5518805b036b52434637f0c02792003e8a6b0863 100644 (file)
 <form method="post">
 <input type="hidden" name="form" value="patchlistform"/>
 <input type="hidden" name="project" value="{{project.id}}"/>
-<table class="patchlist">
- <tr>
-  {% if user.is_authenticated %}
-  <th>
-   <input type="checkbox" onChange="select_all(this)"/>
-  </th>
-  {% endif %}
+<table class="patchlist" id="patchlist">
+ <thead>
+  <tr>
+   {% if user.is_authenticated %}
+   <th>
+    <input type="checkbox" onChange="select_all(this)"/>
+   </th>
+   {% endif %}
+
+   <th>
+    {% ifequal order.name "name" %}
+     <a class="colactive"
+      href="{% listurl order=order.reversed_name %}"><img
+      src="/images/16-arrow-{% if order.reversed %}up{% else %}down{%endif%}.png"
+      width="16" height="16"
+     ></a> <a class="colactive"
+      href="{% listurl order=order.reversed_name %}">Patch</a>
+    {% else %}
+     <a class="colinactive" href="{% listurl order="name" %}">Patch</a>
+    {% endifequal %}
+   </th>
+
+   <th>
+    {% ifequal order.name "date" %}
+     <a class="colactive"
+      href="{% listurl order=order.reversed_name %}"><img
+      src="/images/16-arrow-{% if order.reversed %}up{% else %}down{%endif%}.png"
+      width="16" height="16"
+     ></a> <a class="colactive"
+      href="{% listurl order=order.reversed_name %}">Date</a>
+    {% else %}
+     <a class="colinactive" href="{% listurl order="date" %}">Date</a>
+    {% endifequal %}
+   </th>
+
+   <th>
+    {% ifequal order.name "submitter" %}
+     <a class="colactive"
+      href="{% listurl order=order.reversed_name %}"><img
+      src="/images/16-arrow-{% if order.reversed %}up{% else %}down{%endif%}.png"
+      width="16" height="16"
+     ></a> <a class="colactive"
+      href="{% listurl order=order.reversed_name %}">Submitter</a>
+    {% else %}
+     <a class="colinactive" href="{% listurl order="submitter" %}">Submitter</a>
+    {% endifequal %}
+   </th>
+
+   <th>
+    {% ifequal order.name "delegate" %}
+     <a class="colactive"
+      href="{% listurl order=order.reversed_name %}"><img
+      src="/images/16-arrow-{% if order.reversed %}up{% else %}down{%endif%}.png"
+      width="16" height="16"
+     ></a> <a class="colactive"
+      href="{% listurl order=order.reversed_name %}">Delegate</a>
+    {% else %}
+     <a class="colinactive" href="{% listurl order="delegate" %}">Delegate</a>
+    {% endifequal %}
+   </th>
+
+   <th>
+    {% ifequal order.name "state" %}
+     <a class="colactive"
+      href="{% listurl order=order.reversed_name %}"><img
+      src="/images/16-arrow-{% if order.reversed %}up{% else %}down{%endif%}.png"
+      width="16" height="16"
+     ></a> <a class="colactive"
+      href="{% listurl order=order.reversed_name %}">State</a>
+    {% else %}
+     <a class="colinactive" href="{% listurl order="state" %}">State</a>
+    {% endifequal %}
+   </th>
 
-  <th>
-   {% ifequal order.name "name" %}
-    <a class="colactive"
-     href="{% listurl order=order.reversed_name %}"><img
-     src="/images/16-arrow-{% if order.reversed %}up{% else %}down{%endif%}.png"
-     width="16" height="16"
-    ></a> <a class="colactive"
-     href="{% listurl order=order.reversed_name %}">Patch</a>
-   {% else %}
-    <a class="colinactive" href="{% listurl order="name" %}">Patch</a>
-   {% endifequal %}
-  </th>
-
-  <th>
-   {% ifequal order.name "date" %}
-    <a class="colactive"
-     href="{% listurl order=order.reversed_name %}"><img
-     src="/images/16-arrow-{% if order.reversed %}up{% else %}down{%endif%}.png"
-     width="16" height="16"
-    ></a> <a class="colactive"
-     href="{% listurl order=order.reversed_name %}">Date</a>
-   {% else %}
-    <a class="colinactive" href="{% listurl order="date" %}">Date</a>
-   {% endifequal %}
-  </th>
-
-  <th>
-   {% ifequal order.name "submitter" %}
-    <a class="colactive"
-     href="{% listurl order=order.reversed_name %}"><img
-     src="/images/16-arrow-{% if order.reversed %}up{% else %}down{%endif%}.png"
-     width="16" height="16"
-    ></a> <a class="colactive"
-     href="{% listurl order=order.reversed_name %}">Submitter</a>
-   {% else %}
-    <a class="colinactive" href="{% listurl order="submitter" %}">Submitter</a>
-   {% endifequal %}
-  </th>
-
-  <th>
-   {% ifequal order.name "delegate" %}
-    <a class="colactive"
-     href="{% listurl order=order.reversed_name %}"><img
-     src="/images/16-arrow-{% if order.reversed %}up{% else %}down{%endif%}.png"
-     width="16" height="16"
-    ></a> <a class="colactive"
-     href="{% listurl order=order.reversed_name %}">Delegate</a>
-   {% else %}
-    <a class="colinactive" href="{% listurl order="delegate" %}">Delegate</a>
-   {% endifequal %}
-  </th>
-
-  <th>
-   {% ifequal order.name "state" %}
-    <a class="colactive"
-     href="{% listurl order=order.reversed_name %}"><img
-     src="/images/16-arrow-{% if order.reversed %}up{% else %}down{%endif%}.png"
-     width="16" height="16"
-    ></a> <a class="colactive"
-     href="{% listurl order=order.reversed_name %}">State</a>
-   {% else %}
-    <a class="colinactive" href="{% listurl order="state" %}">State</a>
-   {% endifequal %}
-  </th>
-
- </tr>
+  </tr>
+ </thead>
 
 {% if page %}
+ <tbody>
  {% for patch in page.object_list %}
-  <tr class="{% cycle 'odd' 'even' %}">
+  <tr id="patch_row:{{patch.id}}" class="{% cycle 'odd' 'even' %}">
     {% if user.is_authenticated %}
     <td>
     <input type="checkbox" name="patch_id:{{patch.id}}"/>
    <td>{{ patch.state }}</td>
   </tr>
  {% endfor %}
+ </tbody>
 </table>
 
 {% include "patchwork/pagination.html" %}