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">×</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">×</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 %}