Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
CIRCLE
/
cloud
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
94
Merge Requests
10
Pipelines
Wiki
Snippets
Members
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit
fdb2cc34
authored
May 05, 2014
by
Kálmán Viktor
Browse files
Options
Browse Files
Download
Plain Diff
Merge remote-tracking branch 'origin/master' into feature-template-wizard
parents
da26baa2
08566087
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
268 additions
and
29 deletions
+268
-29
circle/dashboard/static/dashboard/dashboard.css
+9
-1
circle/dashboard/static/dashboard/js/stupidtable.min.js
+119
-0
circle/dashboard/static/dashboard/template-list.js
+21
-0
circle/dashboard/static/dashboard/vm-list.js
+52
-12
circle/dashboard/tables.py
+24
-6
circle/dashboard/templates/dashboard/template-list.html
+2
-1
circle/dashboard/templates/dashboard/vm-list.html
+30
-8
circle/dashboard/templates/dashboard/vm-list/header-link.html
+1
-0
circle/dashboard/views.py
+10
-1
No files found.
circle/dashboard/static/dashboard/dashboard.css
View file @
fdb2cc34
...
...
@@ -321,7 +321,7 @@ a.hover-black {
}
.template-list-table-thin
{
width
:
95
px
;
width
:
100
px
;
}
...
...
@@ -540,3 +540,11 @@ footer a, footer a:hover, footer a:visited {
bottom
:
10px
;
right
:
20px
;
}
.vm-list-table
th
i
{
margin-top
:
3px
;
}
.table-sorting
{
display
:
none
;
}
circle/dashboard/static/dashboard/js/stupidtable.min.js
0 → 100644
View file @
fdb2cc34
// Stupid jQuery table plugin.
/*
* Source: https://github.com/joequery/Stupid-Table-Plugin
* The Stupid jQuery Plugin is licensed under the MIT license.
* Copyright (c) 2012 Joseph McCullough
*/
// Call on a table
// sortFns: Sort functions for your datatypes.
(
function
(
$
)
{
$
.
fn
.
stupidtable
=
function
(
sortFns
)
{
return
this
.
each
(
function
()
{
var
$table
=
$
(
this
);
sortFns
=
sortFns
||
{};
// Merge sort functions with some default sort functions.
sortFns
=
$
.
extend
({},
$
.
fn
.
stupidtable
.
default_sort_fns
,
sortFns
);
// ==================================================== //
// Begin execution! //
// ==================================================== //
// Do sorting when THs are clicked
$table
.
on
(
"click.stupidtable"
,
"th"
,
function
()
{
var
$this
=
$
(
this
);
var
th_index
=
0
;
var
dir
=
$
.
fn
.
stupidtable
.
dir
;
$table
.
find
(
"th"
).
slice
(
0
,
$this
.
index
()).
each
(
function
()
{
var
cols
=
$
(
this
).
attr
(
"colspan"
)
||
1
;
th_index
+=
parseInt
(
cols
,
10
);
});
// Determine (and/or reverse) sorting direction, default `asc`
var
sort_dir
=
$this
.
data
(
"sort-default"
)
||
dir
.
ASC
;
if
(
$this
.
data
(
"sort-dir"
))
sort_dir
=
$this
.
data
(
"sort-dir"
)
===
dir
.
ASC
?
dir
.
DESC
:
dir
.
ASC
;
// Choose appropriate sorting function.
var
type
=
$this
.
data
(
"sort"
)
||
null
;
// Prevent sorting if no type defined
if
(
type
===
null
)
{
return
;
}
// Trigger `beforetablesort` event that calling scripts can hook into;
// pass parameters for sorted column index and sorting direction
$table
.
trigger
(
"beforetablesort"
,
{
column
:
th_index
,
direction
:
sort_dir
});
// More reliable method of forcing a redraw
$table
.
css
(
"display"
);
// Run sorting asynchronously on a timout to force browser redraw after
// `beforetablesort` callback. Also avoids locking up the browser too much.
setTimeout
(
function
()
{
// Gather the elements for this column
var
column
=
[];
var
sortMethod
=
sortFns
[
type
];
var
trs
=
$table
.
children
(
"tbody"
).
children
(
"tr"
);
// Extract the data for the column that needs to be sorted and pair it up
// with the TR itself into a tuple
trs
.
each
(
function
(
index
,
tr
)
{
var
$e
=
$
(
tr
).
children
().
eq
(
th_index
);
var
sort_val
=
$e
.
data
(
"sort-value"
);
var
order_by
=
typeof
(
sort_val
)
!==
"undefined"
?
sort_val
:
$e
.
text
();
column
.
push
([
order_by
,
tr
]);
});
// Sort by the data-order-by value
column
.
sort
(
function
(
a
,
b
)
{
return
sortMethod
(
a
[
0
],
b
[
0
]);
});
if
(
sort_dir
!=
dir
.
ASC
)
column
.
reverse
();
// Replace the content of tbody with the sorted rows. Strangely (and
// conveniently!) enough, .append accomplishes this for us.
trs
=
$
.
map
(
column
,
function
(
kv
)
{
return
kv
[
1
];
});
$table
.
children
(
"tbody"
).
append
(
trs
);
// Reset siblings
$table
.
find
(
"th"
).
data
(
"sort-dir"
,
null
).
removeClass
(
"sorting-desc sorting-asc"
);
$this
.
data
(
"sort-dir"
,
sort_dir
).
addClass
(
"sorting-"
+
sort_dir
);
// Trigger `aftertablesort` event. Similar to `beforetablesort`
$table
.
trigger
(
"aftertablesort"
,
{
column
:
th_index
,
direction
:
sort_dir
});
// More reliable method of forcing a redraw
$table
.
css
(
"display"
);
},
10
);
});
});
};
// Enum containing sorting directions
$
.
fn
.
stupidtable
.
dir
=
{
ASC
:
"asc"
,
DESC
:
"desc"
};
$
.
fn
.
stupidtable
.
default_sort_fns
=
{
"int"
:
function
(
a
,
b
)
{
return
parseInt
(
a
,
10
)
-
parseInt
(
b
,
10
);
},
"float"
:
function
(
a
,
b
)
{
return
parseFloat
(
a
)
-
parseFloat
(
b
);
},
"string"
:
function
(
a
,
b
)
{
if
(
a
<
b
)
return
-
1
;
if
(
a
>
b
)
return
+
1
;
return
0
;
},
"string-ins"
:
function
(
a
,
b
)
{
a
=
a
.
toLowerCase
();
b
=
b
.
toLowerCase
();
if
(
a
<
b
)
return
-
1
;
if
(
a
>
b
)
return
+
1
;
return
0
;
}
};
})(
jQuery
);
circle/dashboard/static/dashboard/template-list.js
View file @
fdb2cc34
...
...
@@ -20,6 +20,27 @@ $(function() {
});
return
false
;
});
/* template table sort */
var
ttable
=
$
(
".template-list-table"
).
stupidtable
();
ttable
.
on
(
"beforetablesort"
,
function
(
event
,
data
)
{
// pass
});
ttable
.
on
(
"aftertablesort"
,
function
(
event
,
data
)
{
$
(
".template-list-table thead th i"
).
remove
();
var
icon_html
=
'<i class="icon-sort-'
+
(
data
.
direction
==
"desc"
?
"up"
:
"down"
)
+
' pull-right" style="position: absolute;"></i>'
;
$
(
".template-list-table thead th"
).
eq
(
data
.
column
).
append
(
icon_html
);
});
// only if js is enabled
$
(
".template-list-table thead th"
).
css
(
"cursor"
,
"pointer"
);
$
(
".template-list-table th a"
).
on
(
"click"
,
function
(
event
)
{
event
.
preventDefault
();
});
});
...
...
circle/dashboard/static/dashboard/vm-list.js
View file @
fdb2cc34
...
...
@@ -17,14 +17,14 @@ $(function() {
if
(
ctrlDown
)
{
setRowColor
(
$
(
this
));
if
(
!
$
(
this
).
hasClass
(
'vm-list-selected'
))
{
selected
.
splice
(
selected
.
indexOf
(
$
(
this
).
index
()),
1
);
selected
.
splice
(
getSelectedIndex
(
$
(
this
).
index
()),
1
);
}
else
{
selected
.
push
(
$
(
this
).
index
()
);
selected
.
push
(
{
'index'
:
$
(
this
).
index
(),
'vm'
:
$
(
this
).
data
(
"vm-pk"
)}
);
}
retval
=
false
;
}
else
if
(
shiftDown
)
{
if
(
selected
.
length
>
0
)
{
start
=
selected
[
selected
.
length
-
1
]
+
1
;
start
=
selected
[
selected
.
length
-
1
]
[
'index'
]
+
1
;
end
=
$
(
this
).
index
();
if
(
start
>
end
)
{
...
...
@@ -32,8 +32,9 @@ $(function() {
}
for
(
var
i
=
start
;
i
<=
end
;
i
++
)
{
if
(
selected
.
indexOf
(
i
)
<
0
)
{
selected
.
push
(
i
);
var
vm
=
$
(
".vm-list-table tbody tr"
).
eq
(
i
).
data
(
"vm-pk"
);
if
(
!
isAlreadySelected
(
vm
))
{
selected
.
push
({
'index'
:
i
,
'vm'
:
vm
});
setRowColor
(
$
(
'.vm-list-table tbody tr'
).
eq
(
i
));
}
}
...
...
@@ -42,13 +43,13 @@ $(function() {
}
else
{
$
(
'.vm-list-selected'
).
removeClass
(
'vm-list-selected'
);
$
(
this
).
addClass
(
'vm-list-selected'
);
selected
=
[
$
(
this
).
index
()
];
selected
=
[
{
'index'
:
$
(
this
).
index
(),
'vm'
:
$
(
this
).
data
(
"vm-pk"
)}
];
}
// reset btn disables
$
(
'.vm-list-table tbody tr .btn'
).
attr
(
'disabled'
,
false
);
// show/hide group controls
if
(
selected
.
length
>
1
)
{
if
(
selected
.
length
>
0
)
{
$
(
'.vm-list-group-control a'
).
attr
(
'disabled'
,
false
);
for
(
var
i
=
0
;
i
<
selected
.
length
;
i
++
)
{
$
(
'.vm-list-table tbody tr'
).
eq
(
selected
[
i
]).
find
(
'.btn'
).
attr
(
'disabled'
,
true
);
...
...
@@ -61,7 +62,7 @@ $(function() {
$
(
'#vm-list-group-migrate'
).
click
(
function
()
{
console
.
log
(
collectIds
(
selected
));
// pass?
});
$
(
'.vm-list-details'
).
popover
({
...
...
@@ -131,8 +132,9 @@ $(function() {
$
(
'#vm-list-group-select-all'
).
click
(
function
()
{
$
(
'.vm-list-table tbody tr'
).
each
(
function
()
{
var
index
=
$
(
this
).
index
();
if
(
selected
.
indexOf
(
index
)
<
0
)
{
selected
.
push
(
index
);
var
vm
=
$
(
this
).
data
(
"vm-pk"
);
if
(
!
isAlreadySelected
(
vm
))
{
selected
.
push
({
'index'
:
index
,
'vm'
:
vm
});
$
(
this
).
addClass
(
'vm-list-selected'
);
}
});
...
...
@@ -154,13 +156,51 @@ $(function() {
);
return
false
;
});
/* table sort */
var
table
=
$
(
".vm-list-table"
).
stupidtable
();
table
.
on
(
"beforetablesort"
,
function
(
event
,
data
)
{
$
(
".table-sorting"
).
show
();
});
table
.
on
(
"aftertablesort"
,
function
(
event
,
data
)
{
// this didn't work ;;
// var th = $("this").find("th");
$
(
".table-sorting"
).
hide
();
$
(
".vm-list-table thead th i"
).
remove
();
var
icon_html
=
'<i class="icon-sort-'
+
(
data
.
direction
==
"desc"
?
"up"
:
"down"
)
+
' pull-right"></i>'
;
$
(
".vm-list-table thead th"
).
eq
(
data
.
column
).
append
(
icon_html
);
});
// only if js is enabled
$
(
".vm-list-table thead th"
).
css
(
"cursor"
,
"pointer"
);
$
(
".vm-list-table th a"
).
on
(
"click"
,
function
(
event
)
{
event
.
preventDefault
();
});
});
function
isAlreadySelected
(
vm
)
{
for
(
var
i
=
0
;
i
<
selected
.
length
;
i
++
)
if
(
selected
[
i
].
vm
==
vm
)
return
true
;
return
false
;
}
function
getSelectedIndex
(
index
)
{
for
(
var
i
=
0
;
i
<
selected
.
length
;
i
++
)
if
(
selected
[
i
].
index
==
index
)
return
i
;
return
-
1
;
}
function
collectIds
(
rows
)
{
var
ids
=
[];
for
(
var
i
=
0
;
i
<
rows
.
length
;
i
++
)
{
var
div
=
$
(
'td:first-child div'
,
$
(
'.vm-list-table tbody tr'
).
eq
(
rows
[
i
]));
ids
.
push
(
div
.
prop
(
'id'
).
replace
(
'vm-'
,
''
));
ids
.
push
(
rows
[
i
].
vm
);
}
return
ids
;
}
...
...
circle/dashboard/tables.py
View file @
fdb2cc34
...
...
@@ -220,21 +220,35 @@ class TemplateListTable(Table):
name
=
LinkColumn
(
'dashboard.views.template-detail'
,
args
=
[
A
(
'pk'
)],
attrs
=
{
'th'
:
{
'data-sort'
:
"string"
}}
)
num_cores
=
Column
(
verbose_name
=
_
(
"Cores"
),
attrs
=
{
'th'
:
{
'data-sort'
:
"int"
}}
)
ram_size
=
TemplateColumn
(
"{{ record.ram_size }} Mb"
,
attrs
=
{
'th'
:
{
'data-sort'
:
"string"
}}
)
lease
=
TemplateColumn
(
"{{ record.lease.name }}"
,
verbose_name
=
_
(
"Lease"
),
attrs
=
{
'th'
:
{
'data-sort'
:
"string"
}}
)
arch
=
Column
(
attrs
=
{
'th'
:
{
'data-sort'
:
"string"
}}
)
system
=
Column
(
attrs
=
{
'th'
:
{
'data-sort'
:
"string"
}}
)
access_method
=
Column
(
attrs
=
{
'th'
:
{
'data-sort'
:
"string"
}}
)
actions
=
TemplateColumn
(
verbose_name
=
_
(
"Actions"
),
template_name
=
"dashboard/template-list/column-template-actions.html"
,
attrs
=
{
'th'
:
{
'class'
:
'template-list-table-thin'
}},
orderable
=
False
,
)
class
Meta
:
...
...
@@ -242,8 +256,9 @@ class TemplateListTable(Table):
attrs
=
{
'class'
:
(
'table table-bordered table-striped table-hover'
' template-list-table'
)}
fields
=
(
'name'
,
'num_cores'
,
'ram_size'
,
'arch'
,
'system'
,
'access_method'
,
'lease'
,
'state'
,
'actions'
,
)
'system'
,
'access_method'
,
'lease'
,
'actions'
,
)
prefix
=
"template-"
class
LeaseListTable
(
Table
):
...
...
@@ -252,21 +267,24 @@ class LeaseListTable(Table):
args
=
[
A
(
'pk'
)],
)
suspend_in
=
TemplateColumn
(
suspend_in
terval_seconds
=
TemplateColumn
(
"{{ record.get_readable_suspend_time }}"
)
delete_in
=
TemplateColumn
(
delete_in
terval_seconds
=
TemplateColumn
(
"{{ record.get_readable_delete_time }}"
)
actions
=
TemplateColumn
(
verbose_name
=
_
(
"Actions"
),
template_name
=
"dashboard/template-list/column-lease-actions.html"
template_name
=
"dashboard/template-list/column-lease-actions.html"
,
orderable
=
False
,
)
class
Meta
:
model
=
Lease
attrs
=
{
'class'
:
(
'table table-bordered table-striped table-hover'
' lease-list-table'
)}
fields
=
(
'name'
,
'suspend_in'
,
'delete_in'
,
)
fields
=
(
'name'
,
'suspend_interval_seconds'
,
'delete_interval_seconds'
,
)
prefix
=
"lease-"
circle/dashboard/templates/dashboard/template-list.html
View file @
fdb2cc34
...
...
@@ -55,5 +55,6 @@
{% endblock %}
{% block extra_js %}
<script
src=
"{{ STATIC_URL}}dashboard/template-list.js"
></script>
<script
src=
"{{ STATIC_URL}}dashboard/template-list.js"
></script>
<script
src=
"{{ STATIC_URL}}dashboard/js/stupidtable.min.js"
></script>
{% endblock %}
circle/dashboard/templates/dashboard/vm-list.html
View file @
fdb2cc34
...
...
@@ -9,6 +9,10 @@
<div
class=
"col-md-12"
>
<div
class=
"panel panel-default"
>
<div
class=
"panel-heading"
>
<div
class=
"pull-right table-sorting"
>
{% trans "Sorting ... " %}
<!--<i class="icon-refresh icon-spin icon-2x"></i>-->
</div>
<h3
class=
"no-margin"
><i
class=
"icon-desktop"
></i>
{% trans "Virtual machines" %}
</h3>
</div>
<div
class=
"pull-right"
style=
"max-width: 250px; margin-top: 15px; margin-right: 15px;"
>
...
...
@@ -32,22 +36,39 @@
<div
class=
"panel-body"
>
<table
class=
"table table-bordered table-striped table-hover vm-list-table"
>
<thead><tr>
<th
class=
"orderable pk sortable vm-list-table-thin"
><a
href=
"?sort=pk"
>
{% trans "ID" %}
</a></th>
<th
class=
"name orderable sortable"
><a
href=
"?sort=name"
>
{% trans "Name" %}
</a></th>
<th>
{% trans "State" %}
</th>
<th
class=
"orderable sortable"
><a
href=
"?sort=owner"
>
{% trans "Owner" %}
</a></th>
{% if user.is_superuser %}
<th
class=
"orderable sortable"
><a
href=
"?sort=node"
>
{% trans "Node" %}
</a></th>
{% endif %}
<th
data-sort=
"int"
class=
"orderable pk sortable vm-list-table-thin"
style=
"min-width: 50px;"
>
{% trans "ID" as t %}
{% include "dashboard/vm-list/header-link.html" with name=t sort="pk" %}
</th>
<th
data-sort=
"string"
class=
"name orderable sortable"
>
{% trans "Name" as t %}
{% include "dashboard/vm-list/header-link.html" with name=t sort="name" %}
</th>
<th
data-sort=
"string"
>
{% trans "State" as t %}
{% include "dashboard/vm-list/header-link.html" with name=t sort="status" %}
</th>
<th
data-sort=
"string"
class=
"orderable sortable"
>
{% trans "Owner" as t %}
{% include "dashboard/vm-list/header-link.html" with name=t sort="owner" %}
</th>
{% if user.is_superuser %}
<th
data-sort=
"string"
class=
"orderable sortable"
>
{% trans "Node" as t %}
{% include "dashboard/vm-list/header-link.html" with name=t sort="node" %}
</th>
{% endif %}
</tr></thead><tbody>
{% for i in object_list %}
<tr
class=
"{% cycle 'odd' 'even' %}"
>
<tr
class=
"{% cycle 'odd' 'even' %}"
data-vm-pk=
"{{ i.pk }}"
>
<td
class=
"pk"
><div
id=
"vm-{{i.pk}}"
>
{{i.pk}}
</div>
</td>
<td
class=
"name"
><a
class=
"real-link"
href=
"{% url "
dashboard
.
views
.
detail
"
i
.
pk
%}"
>
{{ i.name }}
</a>
</td>
<td
class=
"state"
>
{{ i.get_status_display }}
</td>
<td>
{{ i.owner }}
</td>
{% if user.is_superuser %}
<td>
{{ i.node.name|default:"-" }}
</td>
{% endif %}
{% if user.is_superuser %}
<td
data-sort-value=
"{{ i.node.normalized_name }}"
>
{{ i.node.name|default:"-" }}
</td>
{% endif %}
</tr>
{% empty %}
<tr><td
colspan=
"
4"
>
{% trans "You have no virtual machines." %}
</td></tr>
<tr><td
colspan=
"
5"
><strong>
{% trans "You have no virtual machines." %}
</strong>
</td></tr>
{% endfor %}
</tbody>
</table>
...
...
@@ -92,4 +113,5 @@
{% block extra_js %}
<script
src=
"{{ STATIC_URL}}dashboard/vm-list.js"
></script>
<script
src=
"{{ STATIC_URL}}dashboard/vm-common.js"
></script>
<script
src=
"{{ STATIC_URL}}dashboard/js/stupidtable.min.js"
></script>
{% endblock %}
circle/dashboard/templates/dashboard/vm-list/header-link.html
0 → 100644
View file @
fdb2cc34
<a
href=
"?sort={% if request.GET.sort == sort %}-{% endif %}{{ sort }}"
>
{{ name }}
</a>
circle/dashboard/views.py
View file @
fdb2cc34
...
...
@@ -1053,7 +1053,8 @@ class TemplateList(LoginRequiredMixin, SingleTableView):
def
get_context_data
(
self
,
*
args
,
**
kwargs
):
context
=
super
(
TemplateList
,
self
)
.
get_context_data
(
*
args
,
**
kwargs
)
context
[
'lease_table'
]
=
LeaseListTable
(
Lease
.
objects
.
all
())
context
[
'lease_table'
]
=
LeaseListTable
(
Lease
.
objects
.
all
(),
request
=
self
.
request
)
return
context
def
get_queryset
(
self
):
...
...
@@ -1126,6 +1127,14 @@ class VmList(LoginRequiredMixin, ListView):
s
=
self
.
request
.
GET
.
get
(
"s"
)
if
s
:
queryset
=
queryset
.
filter
(
name__icontains
=
s
)
sort
=
self
.
request
.
GET
.
get
(
"sort"
)
# remove "-" that means descending order
# also check if the column name is valid
if
(
sort
and
(
sort
[
1
:]
if
sort
[
0
]
==
"-"
else
sort
)
in
[
i
.
name
for
i
in
Instance
.
_meta
.
fields
]
+
[
"pk"
]):
queryset
=
queryset
.
order_by
(
sort
)
return
queryset
.
select_related
(
'owner'
,
'node'
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment