Commit a304c0e4 by Kálmán Viktor

dashboard: reworked template list

parent aea321fc
...@@ -1184,3 +1184,22 @@ class VmListSearchForm(forms.Form): ...@@ -1184,3 +1184,22 @@ class VmListSearchForm(forms.Form):
data = self.data.copy() data = self.data.copy()
data['stype'] = "all" data['stype'] = "all"
self.data = data self.data = data
class TemplateListSearchForm(forms.Form):
s = forms.CharField(widget=forms.TextInput(attrs={
'class': "form-control input-tags",
'placeholder': _("Search...")
}))
stype = forms.ChoiceField(vm_search_choices, widget=forms.Select(attrs={
'class': "btn btn-default input-tags",
}))
def __init__(self, *args, **kwargs):
super(TemplateListSearchForm, self).__init__(*args, **kwargs)
# set initial value, otherwise it would be overwritten by request.GET
if not self.data.get("stype"):
data = self.data.copy()
data['stype'] = "all"
self.data = data
...@@ -39,6 +39,7 @@ $(function() { ...@@ -39,6 +39,7 @@ $(function() {
$(".template-list-table thead th").css("cursor", "pointer"); $(".template-list-table thead th").css("cursor", "pointer");
$(".template-list-table th a").on("click", function(event) { $(".template-list-table th a").on("click", function(event) {
if(!$(this).closest("th").data("sort")) return true;
event.preventDefault(); event.preventDefault();
}); });
}); });
......
...@@ -146,13 +146,10 @@ class TemplateListTable(Table): ...@@ -146,13 +146,10 @@ class TemplateListTable(Table):
template_name="dashboard/template-list/column-template-name.html", template_name="dashboard/template-list/column-template-name.html",
attrs={'th': {'data-sort': "string"}} attrs={'th': {'data-sort': "string"}}
) )
num_cores = Column( resources = TemplateColumn(
verbose_name=_("Cores"), template_name="dashboard/template-list/column-template-resources.html",
attrs={'th': {'data-sort': "int"}}
)
ram_size = TemplateColumn(
"{{ record.ram_size }} MiB",
attrs={'th': {'data-sort': "int"}}, attrs={'th': {'data-sort': "int"}},
order_by=("ram_size"),
) )
lease = TemplateColumn( lease = TemplateColumn(
"{{ record.lease.name }}", "{{ record.lease.name }}",
...@@ -170,11 +167,14 @@ class TemplateListTable(Table): ...@@ -170,11 +167,14 @@ class TemplateListTable(Table):
verbose_name=_("Owner"), verbose_name=_("Owner"),
attrs={'th': {'data-sort': "string"}} attrs={'th': {'data-sort': "string"}}
) )
created = TemplateColumn(
template_name="dashboard/template-list/column-template-created.html",
verbose_name=_("Created at"),
)
running = TemplateColumn( running = TemplateColumn(
template_name="dashboard/template-list/column-template-running.html", template_name="dashboard/template-list/column-template-running.html",
verbose_name=_("Running"), verbose_name=_("Running"),
attrs={'th': {'data-sort': "int"}}, attrs={'th': {'data-sort': "int"}},
orderable=False,
) )
actions = TemplateColumn( actions = TemplateColumn(
verbose_name=_("Actions"), verbose_name=_("Actions"),
...@@ -187,8 +187,8 @@ class TemplateListTable(Table): ...@@ -187,8 +187,8 @@ class TemplateListTable(Table):
model = InstanceTemplate model = InstanceTemplate
attrs = {'class': ('table table-bordered table-striped table-hover' attrs = {'class': ('table table-bordered table-striped table-hover'
' template-list-table')} ' template-list-table')}
fields = ('name', 'num_cores', 'ram_size', 'system', fields = ('name', 'resources', 'system', 'access_method', 'lease',
'access_method', 'lease', 'owner', 'running', 'actions', ) 'owner', 'created', 'running', 'actions', )
prefix = "template-" prefix = "template-"
......
{% load i18n %} {% load i18n %}
{% if user and user.pk %} {% if user and user.pk %}
{% if user.get_full_name %} {% if user.get_full_name %}{{ user.get_full_name }}{% else %}{{ user.username }}{% endif %}{% if new_line %}<br />{% endif %}
{{ user.get_full_name }}
{% else %}
{{ user.username }}
{% endif %}
{% if show_org %} {% if show_org %}
{% if user.profile and user.profile.org_id %} {% if user.profile and user.profile.org_id %}
......
{{ record.created|date }}
<br />
{{ record.created|time }}
{% include "dashboard/_display-name.html" with user=record.owner show_org=True %} {% include "dashboard/_display-name.html" with user=record.owner show_org=True new_line=True %}
{% load i18n %}
{{ record.ram_size }}MiB RAM
<br />
{% blocktrans with num_cores=record.num_cores count count=record.num_cores %}
{{ num_cores }} CPU core
{% plural %}
{{ num_cores }} CPU cores
{% endblocktrans %}
...@@ -70,7 +70,8 @@ from .forms import ( ...@@ -70,7 +70,8 @@ from .forms import (
VmSaveForm, UserKeyForm, VmRenewForm, VmStateChangeForm, VmSaveForm, UserKeyForm, VmRenewForm, VmStateChangeForm,
CirclePasswordChangeForm, VmCreateDiskForm, VmDownloadDiskForm, CirclePasswordChangeForm, VmCreateDiskForm, VmDownloadDiskForm,
TraitsForm, RawDataForm, GroupPermissionForm, AclUserAddForm, TraitsForm, RawDataForm, GroupPermissionForm, AclUserAddForm,
VmResourcesForm, VmAddInterfaceForm, VmListSearchForm VmResourcesForm, VmAddInterfaceForm, VmListSearchForm,
TemplateListSearchForm,
) )
from .tables import ( from .tables import (
...@@ -169,6 +170,52 @@ class FilterMixin(object): ...@@ -169,6 +170,52 @@ class FilterMixin(object):
return super(FilterMixin, return super(FilterMixin,
self).get_queryset().filter(**self.get_queryset_filters()) self).get_queryset().filter(**self.get_queryset_filters())
def create_fake_get(self):
"""
Updates the request's GET dict to filter the vm list
For example: "name:xy node:1" updates the GET dict
to resemble this URL ?name=xy&node=1
"name:xy node:1".split(":") becomes ["name", "xy node", "1"]
we pop the the first element and use it as the first dict key
then we iterate over the rest of the list and split by the last
whitespace, the first part of this list will be the previous key's
value, then last part of the list will be the next key.
The final dict looks like this: {'name': xy, 'node':1}
"""
s = self.request.GET.get("s")
if s:
s = s.split(":")
if len(s) < 2: # if there is no ':' in the string, filter by name
got = {'name': s[0]}
else:
latest = s.pop(0)
got = {'%s' % latest: None}
for i in s[:-1]:
new = i.rsplit(" ", 1)
got[latest] = new[0]
latest = new[1] if len(new) > 1 else None
got[latest] = s[-1]
# generate a new GET request, that is kinda fake
fake = self.request.GET.copy()
for k, v in got.iteritems():
fake[k] = v
self.request.GET = fake
def create_acl_queryset(self, model):
cleaned_data = self.search_form.cleaned_data
stype = cleaned_data.get('stype', "all")
superuser = stype == "all"
shared = stype == "shared"
level = "owner" if stype == "owned" else "user"
queryset = model.get_objects_with_level(
level, self.request.user,
group_also=shared, disregard_superuser=not superuser,
)
return queryset
class IndexView(LoginRequiredMixin, TemplateView): class IndexView(LoginRequiredMixin, TemplateView):
template_name = "dashboard/index.html" template_name = "dashboard/index.html"
...@@ -1517,7 +1564,7 @@ class TemplateDetail(LoginRequiredMixin, SuccessMessageMixin, UpdateView): ...@@ -1517,7 +1564,7 @@ class TemplateDetail(LoginRequiredMixin, SuccessMessageMixin, UpdateView):
return kwargs return kwargs
class TemplateList(LoginRequiredMixin, SingleTableView): class TemplateList(LoginRequiredMixin, FilterMixin, SingleTableView):
template_name = "dashboard/template-list.html" template_name = "dashboard/template-list.html"
model = InstanceTemplate model = InstanceTemplate
table_class = TemplateListTable table_class = TemplateListTable
...@@ -1525,15 +1572,24 @@ class TemplateList(LoginRequiredMixin, SingleTableView): ...@@ -1525,15 +1572,24 @@ class TemplateList(LoginRequiredMixin, SingleTableView):
def get_context_data(self, *args, **kwargs): def get_context_data(self, *args, **kwargs):
context = super(TemplateList, self).get_context_data(*args, **kwargs) context = super(TemplateList, self).get_context_data(*args, **kwargs)
context['lease_table'] = LeaseListTable(Lease.objects.all(), context['lease_table'] = LeaseListTable(
request=self.request) Lease.get_objects_with_level("user", self.request.user),
request=self.request)
context['search_form'] = self.search_form
return context return context
def get(self, *args, **kwargs):
self.search_form = TemplateListSearchForm(self.request.GET)
self.search_form.full_clean()
return super(TemplateList, self).get(*args, **kwargs)
def get_queryset(self): def get_queryset(self):
logger.debug('TemplateList.get_queryset() called. User: %s', logger.debug('TemplateList.get_queryset() called. User: %s',
unicode(self.request.user)) unicode(self.request.user))
return InstanceTemplate.get_objects_with_level( queryset = self.create_acl_queryset(InstanceTemplate)
'user', self.request.user).all() return queryset.annotate(running=Count('instance_set'))
class TemplateDelete(LoginRequiredMixin, DeleteView): class TemplateDelete(LoginRequiredMixin, DeleteView):
...@@ -1611,7 +1667,7 @@ class VmList(LoginRequiredMixin, FilterMixin, ListView): ...@@ -1611,7 +1667,7 @@ class VmList(LoginRequiredMixin, FilterMixin, ListView):
def get_queryset(self): def get_queryset(self):
logger.debug('VmList.get_queryset() called. User: %s', logger.debug('VmList.get_queryset() called. User: %s',
unicode(self.request.user)) unicode(self.request.user))
queryset = self.create_default_queryset() queryset = self.create_acl_queryset(Instance).filter(destroyed_at=None)
self.create_fake_get() self.create_fake_get()
sort = self.request.GET.get("sort") sort = self.request.GET.get("sort")
...@@ -1626,52 +1682,6 @@ class VmList(LoginRequiredMixin, FilterMixin, ListView): ...@@ -1626,52 +1682,6 @@ class VmList(LoginRequiredMixin, FilterMixin, ListView):
**self.get_queryset_filters()).select_related('owner', 'node' **self.get_queryset_filters()).select_related('owner', 'node'
).distinct() ).distinct()
def create_default_queryset(self):
cleaned_data = self.search_form.cleaned_data
stype = cleaned_data.get('stype', "all")
superuser = stype == "all"
shared = stype == "shared"
level = "owner" if stype == "owned" else "user"
queryset = Instance.get_objects_with_level(
level, self.request.user,
group_also=shared, disregard_superuser=not superuser,
).filter(destroyed_at=None)
return queryset
def create_fake_get(self):
"""
Updates the request's GET dict to filter the vm list
For example: "name:xy node:1" updates the GET dict
to resemble this URL ?name=xy&node=1
"name:xy node:1".split(":") becomes ["name", "xy node", "1"]
we pop the the first element and use it as the first dict key
then we iterate over the rest of the list and split by the last
whitespace, the first part of this list will be the previous key's
value, then last part of the list will be the next key.
The final dict looks like this: {'name': xy, 'node':1}
"""
s = self.request.GET.get("s")
if s:
s = s.split(":")
if len(s) < 2: # if there is no ':' in the string, filter by name
got = {'name': s[0]}
else:
latest = s.pop(0)
got = {'%s' % latest: None}
for i in s[:-1]:
new = i.rsplit(" ", 1)
got[latest] = new[0]
latest = new[1] if len(new) > 1 else None
got[latest] = s[-1]
# generate a new GET request, that is kinda fake
fake = self.request.GET.copy()
for k, v in got.iteritems():
fake[k] = v
self.request.GET = fake
class NodeList(LoginRequiredMixin, SuperuserRequiredMixin, SingleTableView): class NodeList(LoginRequiredMixin, SuperuserRequiredMixin, SingleTableView):
template_name = "dashboard/node-list.html" template_name = "dashboard/node-list.html"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment