From 5f6b06b467f6b91c7b3fac40d547e9a40b6ff367 Mon Sep 17 00:00:00 2001
From: Retspen <anatoliy.guskov@gmail.com>
Date: Tue, 10 Mar 2015 16:46:52 +0200
Subject: [PATCH] Add sortable

---
 static/css/sortable-theme-bootstrap.css |  90 ++++++++++++++++
 static/js/sortable.min.js               |   2 +
 templates/instances.html                |   8 +-
 templates/secrets.html                  | 138 ++++++++++++------------
 templates/storage.html                  |  50 +++++----
 5 files changed, 197 insertions(+), 91 deletions(-)
 create mode 100755 static/css/sortable-theme-bootstrap.css
 create mode 100755 static/js/sortable.min.js

diff --git a/static/css/sortable-theme-bootstrap.css b/static/css/sortable-theme-bootstrap.css
new file mode 100755
index 0000000..7d81668
--- /dev/null
+++ b/static/css/sortable-theme-bootstrap.css
@@ -0,0 +1,90 @@
+/* line 2, ../sass/_sortable.sass */
+table[data-sortable] {
+  border-collapse: collapse;
+  border-spacing: 0;
+}
+/* line 6, ../sass/_sortable.sass */
+table[data-sortable] th {
+  vertical-align: bottom;
+  font-weight: bold;
+}
+/* line 10, ../sass/_sortable.sass */
+table[data-sortable] th, table[data-sortable] td {
+  text-align: left;
+  padding: 10px;
+}
+/* line 14, ../sass/_sortable.sass */
+table[data-sortable] th:not([data-sortable="false"]) {
+  -webkit-user-select: none;
+  -moz-user-select: none;
+  -ms-user-select: none;
+  -o-user-select: none;
+  user-select: none;
+  -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
+  -webkit-touch-callout: none;
+  cursor: pointer;
+}
+/* line 26, ../sass/_sortable.sass */
+table[data-sortable] th:after {
+  content: "";
+  visibility: hidden;
+  display: inline-block;
+  vertical-align: inherit;
+  height: 0;
+  width: 0;
+  border-width: 5px;
+  border-style: solid;
+  border-color: transparent;
+  margin-right: 1px;
+  margin-left: 10px;
+  float: right;
+}
+/* line 40, ../sass/_sortable.sass */
+table[data-sortable] th[data-sorted="true"]:after {
+  visibility: visible;
+}
+/* line 43, ../sass/_sortable.sass */
+table[data-sortable] th[data-sorted-direction="descending"]:after {
+  border-top-color: inherit;
+  margin-top: 8px;
+}
+/* line 47, ../sass/_sortable.sass */
+table[data-sortable] th[data-sorted-direction="ascending"]:after {
+  border-bottom-color: inherit;
+  margin-top: 3px;
+}
+
+/* line 5, ../sass/sortable-theme-bootstrap.sass */
+table[data-sortable].sortable-theme-bootstrap {
+  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
+  font-size: 14px;
+  line-height: 20px;
+  color: #333333;
+  background: white;
+}
+/* line 12, ../sass/sortable-theme-bootstrap.sass */
+table[data-sortable].sortable-theme-bootstrap thead th {
+  border-bottom: 2px solid #e0e0e0;
+}
+/* line 15, ../sass/sortable-theme-bootstrap.sass */
+table[data-sortable].sortable-theme-bootstrap tbody td {
+  border-top: 1px solid #e0e0e0;
+}
+/* line 18, ../sass/sortable-theme-bootstrap.sass */
+table[data-sortable].sortable-theme-bootstrap th[data-sorted="true"] {
+  color: #3a87ad;
+  background: #d9edf7;
+  border-bottom-color: #bce8f1;
+}
+/* line 23, ../sass/sortable-theme-bootstrap.sass */
+table[data-sortable].sortable-theme-bootstrap th[data-sorted="true"][data-sorted-direction="descending"]:after {
+  border-top-color: #3a87ad;
+}
+/* line 26, ../sass/sortable-theme-bootstrap.sass */
+table[data-sortable].sortable-theme-bootstrap th[data-sorted="true"][data-sorted-direction="ascending"]:after {
+  border-bottom-color: #3a87ad;
+}
+/* line 31, ../sass/sortable-theme-bootstrap.sass */
+table[data-sortable].sortable-theme-bootstrap.sortable-theme-bootstrap-striped tbody > tr:nth-child(odd) > td {
+  background-color: #f9f9f9;
+}
diff --git a/static/js/sortable.min.js b/static/js/sortable.min.js
new file mode 100755
index 0000000..242074c
--- /dev/null
+++ b/static/js/sortable.min.js
@@ -0,0 +1,2 @@
+/*! sortable.js 0.5.0 */
+(function(){var a,b,c,d,e,f;a="table[data-sortable]",c=/^-?[£$¤]?[\d,.]+%?$/,f=/^\s+|\s+$/g,e="ontouchstart"in document.documentElement,b=e?"touchstart":"click",d={init:function(){var b,c,e,f,g;for(c=document.querySelectorAll(a),g=[],e=0,f=c.length;f>e;e++)b=c[e],g.push(d.initTable(b));return g},initTable:function(a){var b,c,e,f,g;if(1===a.tHead.rows.length&&"true"!==a.getAttribute("data-sortable-initialized")){for(a.setAttribute("data-sortable-initialized","true"),e=a.querySelectorAll("th"),b=f=0,g=e.length;g>f;b=++f)c=e[b],"false"!==c.getAttribute("data-sortable")&&d.setupClickableTH(a,c,b);return a}},setupClickableTH:function(a,c,e){var f;return f=d.getColumnType(a,e),c.addEventListener(b,function(){var b,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u;for(j="true"===this.getAttribute("data-sorted"),k=this.getAttribute("data-sorted-direction"),b=j?"ascending"===k?"descending":"ascending":f.defaultSortDirection,m=this.parentNode.querySelectorAll("th"),n=0,q=m.length;q>n;n++)c=m[n],c.setAttribute("data-sorted","false"),c.removeAttribute("data-sorted-direction");for(this.setAttribute("data-sorted","true"),this.setAttribute("data-sorted-direction",b),l=a.tBodies[0],h=[],t=l.rows,o=0,r=t.length;r>o;o++)g=t[o],h.push([d.getNodeValue(g.cells[e]),g]);for(j?h.reverse():h.sort(f.compare),u=[],p=0,s=h.length;s>p;p++)i=h[p],u.push(l.appendChild(i[1]));return u})},getColumnType:function(a,b){var e,f,g,h,i;for(i=a.tBodies[0].rows,g=0,h=i.length;h>g;g++)if(e=i[g],f=d.getNodeValue(e.cells[b]),""!==f&&f.match(c))return d.types.numeric;return d.types.alpha},getNodeValue:function(a){return a?null!==a.getAttribute("data-value")?a.getAttribute("data-value"):"undefined"!=typeof a.innerText?a.innerText.replace(f,""):a.textContent.replace(f,""):""},types:{numeric:{defaultSortDirection:"descending",compare:function(a,b){var c,d;return c=parseFloat(a[0].replace(/[^0-9.-]/g,"")),d=parseFloat(b[0].replace(/[^0-9.-]/g,"")),isNaN(c)&&(c=0),isNaN(d)&&(d=0),d-c}},alpha:{defaultSortDirection:"ascending",compare:function(a,b){var c,d;return c=a[0].toLowerCase(),d=b[0].toLowerCase(),c===d?0:d>c?-1:1}}}},setTimeout(d.init,0),window.Sortable=d}).call(this);
\ No newline at end of file
diff --git a/templates/instances.html b/templates/instances.html
index 6157c6a..031b04c 100644
--- a/templates/instances.html
+++ b/templates/instances.html
@@ -1,6 +1,9 @@
 {% extends "base.html" %}
 {% load i18n %}
 {% block title %}{% trans "Instances" %}{% endblock %}
+{% block style %}
+    <link rel="stylesheet" href="{{ STATIC_URL }}/css/sortable-theme-bootstrap.css" />
+{% endblock %}
 {% block content %}
                 <!-- Page Heading -->
                 <div class="row">
@@ -17,7 +20,7 @@
                     <div class="col-lg-12">
                         <div class="table-responsive">
                             {% if request.user.is_superuser %}
-                                <table class="table table-hover table-striped">
+                                <table class="table table-hover table-striped sortable-theme-bootstrap" data-sortable>
                                     <thead>
                                         <tr>
                                             <th>Name</th>
@@ -25,7 +28,7 @@
                                             <th>Status</th>
                                             <th>VCPU</th>
                                             <th>Memory</th>
-                                            <th>Actions</th>
+                                            <th data-sortable="false" style="width: 165px;">Actions</th>
                                         </tr>
                                     </thead>
                                     <tbody>
@@ -190,6 +193,7 @@
                 </div>
 {% endblock %}
 {% block script %}
+<script src="{{ STATIC_URL }}/js/sortable.min.js"></script>
 <script>
     function open_console(uuid) {
         window.open("{% url 'console' %}?token=" + uuid, "", "width=850,height=485");
diff --git a/templates/secrets.html b/templates/secrets.html
index cb6a2b0..509ff92 100644
--- a/templates/secrets.html
+++ b/templates/secrets.html
@@ -1,6 +1,9 @@
 {% extends "base.html" %}
 {% load i18n %}
 {% block title %}{% trans "Secrets" %} - {{ compute.name }}{% endblock %}
+{% block style %}
+    <link rel="stylesheet" href="{{ STATIC_URL }}/css/sortable-theme-bootstrap.css" />
+{% endblock %}
 {% block content %}
            <!-- Page Heading -->
             <div class="row">
@@ -41,75 +44,78 @@
                 {% else %}
                     <div class="col-lg-12">
                         <div class="table-responsive">
-                        <table class="table table-hover">
-                        <thead>
-                        <tr class="active">
-                            <th>{% trans "UUID" %}</th>
-                            <th>{% trans "Type" %}</th>
-                            <th>{% trans "Usage" %}</th>
-                            <th style="width:90px;">{% trans "Action" %}</th>
-                        </tr>
-                        </thead>
-                        <tbody>
-                        {% for secret in secrets_all %}
-                            <tr>
-                                <td>{{ secret.uuid }}</td>
-                                <td>{% ifequal secret.usageType 0 %}
-                                    {% trans "volume" %}
-                                {% endifequal %}
-                                    {% ifequal secret.usageType 1 %}
-                                        {% trans "iscsi" %}
-                                    {% endifequal %}
-                                    {% ifequal secret.usageType 2 %}
-                                        {% trans "ceph" %}
-                                    {% endifequal %}
-                                </td>
-                                <td>{{ secret.usage }}</td>
-                                <td>
-                                    <form action="" method="post" role="form">{% csrf_token %}
-                                        <input type="hidden" name="uuid" value="{{ secret.uuid }}"/>
-                                        <a data-toggle="modal" href="#editSecret{{ secret.uuid }}" class="btn btn-sm btn-default" title="{% trans "Edit" %}">
-                                            <span class="glyphicon glyphicon-pencil"></span>
-                                        </a>
-                                        <button type="submit" class="btn btn-sm btn-default" name="delete" title="{% trans "Delete" %}" onclick="return confirm('{% trans "Are you sure?" %}')">
-                                            <span class="glyphicon glyphicon-trash"></span>
-                                        </button>
-                                    </form>
+                            <table class="table table-hover sortable-theme-bootstrap" data-sortable>
+                                <thead>
+                                <tr class="active">
+                                    <th>{% trans "UUID" %}</th>
+                                    <th>{% trans "Type" %}</th>
+                                    <th>{% trans "Usage" %}</th>
+                                    <th data-sortable="false" style="width:90px;">{% trans "Action" %}</th>
+                                </tr>
+                                </thead>
+                                <tbody>
+                                {% for secret in secrets_all %}
+                                    <tr>
+                                        <td>{{ secret.uuid }}</td>
+                                        <td>{% ifequal secret.usageType 0 %}
+                                            {% trans "volume" %}
+                                        {% endifequal %}
+                                            {% ifequal secret.usageType 1 %}
+                                                {% trans "iscsi" %}
+                                            {% endifequal %}
+                                            {% ifequal secret.usageType 2 %}
+                                                {% trans "ceph" %}
+                                            {% endifequal %}
+                                        </td>
+                                        <td>{{ secret.usage }}</td>
+                                        <td>
+                                            <form action="" method="post" role="form">{% csrf_token %}
+                                                <input type="hidden" name="uuid" value="{{ secret.uuid }}"/>
+                                                <a data-toggle="modal" href="#editSecret{{ secret.uuid }}" class="btn btn-sm btn-default" title="{% trans "Edit" %}">
+                                                    <span class="glyphicon glyphicon-pencil"></span>
+                                                </a>
+                                                <button type="submit" class="btn btn-sm btn-default" name="delete" title="{% trans "Delete" %}" onclick="return confirm('{% trans "Are you sure?" %}')">
+                                                    <span class="glyphicon glyphicon-trash"></span>
+                                                </button>
+                                            </form>
 
-                                    <!-- Modal -->
-                                    <div class="modal fade" id="editSecret{{ secret.uuid }}" tabindex="-1" role="dialog"
-                                         aria-labelledby="editSecret" aria-hidden="true">
-                                        <div class="modal-dialog">
-                                            <div class="modal-content">
-                                                <div class="modal-header">
-                                                    <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
-                                                    <h4 class="modal-title">{% trans "Set secret value" %}</h4>
-                                                </div>
-                                                <div class="tab-content">
-                                                    <form class="form-horizontal" method="post" role="form">{% csrf_token %}
-                                                        <div class="form-group">
-                                                            <label class="col-sm-3 control-label">{% trans "Value" %}</label>
-                                                            <div class="col-sm-6">
-                                                                <input type="hidden" name="uuid" value="{{ secret.uuid }}">
-                                                                <input type="text" name="value" class="form-control" value="{{ secret.value }}" maxlength="45" required pattern="[a-zA-Z0-9]$+">
-                                                            </div>
+                                            <!-- Modal -->
+                                            <div class="modal fade" id="editSecret{{ secret.uuid }}" tabindex="-1" role="dialog"
+                                                 aria-labelledby="editSecret" aria-hidden="true">
+                                                <div class="modal-dialog">
+                                                    <div class="modal-content">
+                                                        <div class="modal-header">
+                                                            <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
+                                                            <h4 class="modal-title">{% trans "Set secret value" %}</h4>
                                                         </div>
-                                                        <div class="modal-footer">
-                                                            <button type="button" class="btn btn-default" data-dismiss="modal">{% trans "Close" %}</button>
-                                                            <button type="submit" class="btn btn-primary" name="set_value">{% trans "Set" %}</button>
-                                                        </div>
-                                                    </form>
-                                                </div> <!-- /.modal-content -->
-                                            </div> <!-- /.tab-content -->
-                                        </div> <!-- /.modal-dialog -->
-                                    </div> <!-- /.modal -->
-                                </td>
-                            </tr>
-                        {% endfor %}
-                        </tbody>
-                    </table>
-                    </div>
+                                                        <div class="tab-content">
+                                                            <form class="form-horizontal" method="post" role="form">{% csrf_token %}
+                                                                <div class="form-group">
+                                                                    <label class="col-sm-3 control-label">{% trans "Value" %}</label>
+                                                                    <div class="col-sm-6">
+                                                                        <input type="hidden" name="uuid" value="{{ secret.uuid }}">
+                                                                        <input type="text" name="value" class="form-control" value="{{ secret.value }}" maxlength="45" required pattern="[a-zA-Z0-9]$+">
+                                                                    </div>
+                                                                </div>
+                                                                <div class="modal-footer">
+                                                                    <button type="button" class="btn btn-default" data-dismiss="modal">{% trans "Close" %}</button>
+                                                                    <button type="submit" class="btn btn-primary" name="set_value">{% trans "Set" %}</button>
+                                                                </div>
+                                                            </form>
+                                                        </div> <!-- /.modal-content -->
+                                                    </div> <!-- /.tab-content -->
+                                                </div> <!-- /.modal-dialog -->
+                                            </div> <!-- /.modal -->
+                                        </td>
+                                    </tr>
+                                {% endfor %}
+                                </tbody>
+                            </table>
+                        </div>
                     </div>
                 {% endif %}
             </div>
+{% endblock %}
+{% block script %}
+<script src="{{ STATIC_URL }}/js/sortable.min.js"></script>
 {% endblock %}
\ No newline at end of file
diff --git a/templates/storage.html b/templates/storage.html
index 88e9dcd..2d46842 100644
--- a/templates/storage.html
+++ b/templates/storage.html
@@ -1,6 +1,9 @@
 {% extends "base.html" %}
 {% load i18n %}
 {% block title %}{% trans "Storage" %} - {{ pool }}{% endblock %}
+{% block style %}
+    <link rel="stylesheet" href="{{ STATIC_URL }}/css/sortable-theme-bootstrap.css" />
+{% endblock %}
 {% block content %}
            <!-- Page Heading -->
             <div class="row">
@@ -77,14 +80,14 @@
                         <h3 class="page-header">{% trans "Volumes" %}</h3>
                         {% if volumes  %}
                         <div class="table-responsive">
-                            <table class="table table-striped table-bordered" id="sortTable">
+                            <table class="table table-striped table-bordered sortable-theme-bootstrap" data-sortable>
                                 <thead>
                                 <tr>
                                     <th style="width:35px;">#</th>
                                     <th>{% trans "Name" %}</th>
-                                    <th style="width:80px;">{% trans "Size" %}</th>
-                                    <th style="width:75px;">{% trans "Format" %}</th>
-                                    <th colspan="2">{% trans "Action" %}</th>
+                                    <th>{% trans "Size" %}</th>
+                                    <th>{% trans "Format" %}</th>
+                                    <th data-sortable="false" colspan="2">{% trans "Action" %}</th>
                                 </tr>
                                 </thead>
                                 <tbody>
@@ -177,25 +180,26 @@
             </div>
 {% endblock %}
 {% block script %}
-    <script>
-        $('.format-convert').hide();
-        $(document).on('change', '.volume-convert', function () {
-            if ($(this).prop('checked')) {
-                $('.format-convert').show();
-                if ($('.image-format').val() == 'qcow2') {
-                    $('.meta-prealloc').show();
-                }
-            } else {
-                $('.format-convert').hide();
-                $('.meta-prealloc').hide();
-            }
-        });
-        $(document).on('change', '.image-format', function () {
-            if ($(this).val() == "qcow2") {
+<script src="{{ STATIC_URL }}/js/sortable.min.js"></script>
+<script>
+    $('.format-convert').hide();
+    $(document).on('change', '.volume-convert', function () {
+        if ($(this).prop('checked')) {
+            $('.format-convert').show();
+            if ($('.image-format').val() == 'qcow2') {
                 $('.meta-prealloc').show();
-            } else {
-                $('.meta-prealloc').hide();
             }
-        });
-    </script>
+        } else {
+            $('.format-convert').hide();
+            $('.meta-prealloc').hide();
+        }
+    });
+    $(document).on('change', '.image-format', function () {
+        if ($(this).val() == "qcow2") {
+            $('.meta-prealloc').show();
+        } else {
+            $('.meta-prealloc').hide();
+        }
+    });
+</script>
 {% endblock %}