Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 29 additions & 2 deletions cloudkittydashboard/dashboards/admin/summary/tables.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,14 @@
# License for the specific language governing permissions and limitations
# under the License.

from django.conf import settings
from django.urls import reverse
from django.utils.translation import gettext_lazy as _

from horizon import tables

from cloudkittydashboard.utils import formatTitle


def get_details_link(datum):
if datum.tenant_id:
Expand All @@ -37,12 +40,36 @@ class Meta(object):


class TenantSummaryTable(tables.DataTable):
res_type = tables.Column('type', verbose_name=_("Resource Type"))
groupby_list = getattr(settings,
'OPENSTACK_CLOUDKITTY_GROUPBY_LIST',
['type'])

# Dynamically create columns based on groupby_list
for field in groupby_list:
locals()[field] = tables.Column(
field, verbose_name=_(formatTitle(field)))

rate = tables.Column('rate', verbose_name=_("Rate"))

def __init__(self, request, data=None, needs_form_wrapper=None, **kwargs):
super().__init__(request, data, needs_form_wrapper, **kwargs)

# Hide columns based on checkbox selection
for field in self.groupby_list:
if request.GET.get(field) != 'true':
self.columns[field].classes = ['hidden']

class Meta(object):
name = "tenant_summary"
verbose_name = _("Project Summary")

def get_object_id(self, datum):
return datum.get('type')
# Prevents the table from displaying the same ID for different rows
id_parts = []
for field in self.groupby_list:
if field in datum and datum[field]:
id_parts.append(str(datum[field]))

if id_parts:
return '_'.join(id_parts)
return _('No IDs found')
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@

{% trans "Project ID:" %} {{ project_id }}

{{ groupby_list|json_script:"groupby_list_config" }}
{% include "project/rating/groupby.html" %}
{{ table.render }}

{{ modules }}
Expand Down
41 changes: 29 additions & 12 deletions cloudkittydashboard/dashboards/admin/summary/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
from cloudkittydashboard.dashboards.admin.summary import tables as sum_tables
from cloudkittydashboard import utils

from cloudkittydashboard import forms

rate_prefix = getattr(settings,
'OPENSTACK_CLOUDKITTY_RATE_PREFIX', None)
rate_postfix = getattr(settings,
Expand All @@ -35,8 +37,7 @@ class IndexView(tables.DataTableView):
def get_data(self):
summary = api.cloudkittyclient(
self.request, version='2').summary.get_summary(
groupby=['project_id'],
response_format='object')
groupby=['project_id'], response_format='object')

tenants, unused = api_keystone.tenant_list(self.request)
tenants = {tenant.id: tenant.name for tenant in tenants}
Expand All @@ -47,6 +48,7 @@ def get_data(self):
'project_id': 'ALL',
'rate': total,
})

data = api.identify(data, key='project_id')
for tenant in data:
tenant['tenant_id'] = tenant.get('project_id')
Expand All @@ -60,27 +62,42 @@ def get_data(self):
class TenantDetailsView(tables.DataTableView):
template_name = 'admin/rating_summary/details.html'
table_class = sum_tables.TenantSummaryTable
page_title = _("Script details: {{ table.project_id }}")

def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['groupby_list'] = getattr(settings,
'OPENSTACK_CLOUDKITTY_GROUPBY_LIST',
['type'])
return context

def get_data(self):
tenant_id = self.kwargs['project_id']
form = forms.CheckBoxForm(self.request.GET)
groupby = form.get_selected_fields()

if tenant_id == 'ALL':
summary = api.cloudkittyclient(
self.request, version='2').summary.get_summary(
groupby=['type'], response_format='object')
self.request, version='2'
).summary.get_summary(groupby=groupby, response_format='object')
else:
summary = api.cloudkittyclient(
self.request, version='2').summary.get_summary(
filters={'project_id': tenant_id},
groupby=['type'], response_format='object')
self.request, version='2'
).summary.get_summary(
filters={'project_id': tenant_id},
groupby=groupby,
response_format='object',
)

data = summary.get('results')
total = sum([r.get('rate') for r in data])
data.append({'type': 'TOTAL', 'rate': total})

for item in data:
item['rate'] = utils.formatRate(item['rate'],
rate_prefix, rate_postfix)
if not groupby:
data = [{'type': 'TOTAL', 'rate': total}]

else:
data.append({'type': 'TOTAL', 'rate': total})
for item in data:
item['rate'] = utils.formatRate(
item['rate'], rate_prefix, rate_postfix)

return data
31 changes: 29 additions & 2 deletions cloudkittydashboard/dashboards/project/rating/tables.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,47 @@
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from django.conf import settings
from django.utils.translation import gettext_lazy as _

from horizon import tables

from cloudkittydashboard.utils import formatTitle


class SummaryTable(tables.DataTable):
"""This table formats a summary for the given tenant."""

res_type = tables.Column('type', verbose_name=_('Metric Type'))
groupby_list = getattr(settings,
'OPENSTACK_CLOUDKITTY_GROUPBY_LIST',
['type'])

# Dynamically create columns based on groupby_list
for field in groupby_list:
locals()[field] = tables.Column(
field, verbose_name=_(formatTitle(field)))

rate = tables.Column('rate', verbose_name=_('Rate'))

def __init__(self, request, data=None, needs_form_wrapper=None, **kwargs):
super().__init__(request, data, needs_form_wrapper, **kwargs)

# Hide columns based on checkbox selection
for field in self.groupby_list:
if request.GET.get(field) != 'true':
self.columns[field].classes = ['hidden']

class Meta(object):
name = "summary"
verbose_name = _("Summary")

def get_object_id(self, datum):
return datum.get('type')
# prevents the table from displaying the same ID for different rows
id_parts = []
for field in self.groupby_list:
if field in datum and datum[field]:
id_parts.append(str(datum[field]))

if id_parts:
return '_'.join(id_parts)
return _('No IDs found')
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{% load i18n %}
{% load static %}

{{ groupby_list|json_script:"groupby_list_config" }}

<!-- For select/unselect button translations -->
<script id="groupby_translations" type="application/json">
{
"select_all": "{% trans 'Select All' %}",
"unselect_all": "{% trans 'Unselect All' %}"
}
</script>
<link rel="stylesheet" href="{% static 'cloudkitty/css/grouping.css' %}">
<script src="{% static 'cloudkitty/js/grouping.js' %}" type="text/javascript" charset="utf-8"></script>

<form method="GET" action="?" id="groupby_checkbox" class="groupby-form">
<h4>{% trans "Group by:" %}</h4>
<div id="checkboxes"></div>
<button class="btn btn-primary" id="toggleAll" type="button">
{% trans "Select All" %}
</button>
<button class="btn btn-primary" type="submit">{% trans "Submit" %}</button>
</form>
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@
{% block title %}{% trans "Rating Summary" %}{% endblock %}

{% block page_header %}
{% include "horizon/common/_page_header.html" with title=_("Rating Summary") %}
{% include "horizon/common/_page_header.html" with title=_("Rating Summary") %}
{% endblock page_header %}

{% block main %}

{{ groupby_list|json_script:"groupby_list_config" }}
{% include "project/rating/groupby.html" %}
{{ table.render }}

{{ modules }}
Expand Down
28 changes: 21 additions & 7 deletions cloudkittydashboard/dashboards/project/rating/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
from horizon import exceptions
from horizon import tables

from cloudkittydashboard import forms

from cloudkittydashboard.api import cloudkitty as api
from cloudkittydashboard.dashboards.project.rating \
import tables as rating_tables
Expand All @@ -34,19 +36,31 @@ class IndexView(tables.DataTableView):
table_class = rating_tables.SummaryTable
template_name = 'project/rating/index.html'

def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['groupby_list'] = getattr(settings,
'OPENSTACK_CLOUDKITTY_GROUPBY_LIST',
['type'])
return context

def get_data(self):
form = forms.CheckBoxForm(self.request.GET)
groupby = form.get_selected_fields()
summary = api.cloudkittyclient(
self.request, version='2').summary.get_summary(
tenant_id=self.request.user.tenant_id,
groupby=['type'], response_format='object')
groupby=groupby, response_format='object')
data = summary.get("results")
total = sum([r.get("rate") for r in data])

data = summary.get('results')
total = sum([r.get('rate') for r in data])
if not groupby: # No checkboxes are selected, display total rate only
data = [{"type": "TOTAL", "rate": total}]

data.append({'type': 'TOTAL', 'rate': total})
for item in data:
item['rate'] = utils.formatRate(item['rate'],
rate_prefix, rate_postfix)
else: # Some checkboxes are selected - use groupby
data.append({'type': 'TOTAL', 'rate': total})
for item in data:
item['rate'] = utils.formatRate(item['rate'],
rate_prefix, rate_postfix)
return data


Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{% load i18n %}

{% block trimmed %}
<div class="input-group date">
{{ datepicker_input }}
<label class="sr-only">{{ datepicker_label }}</label>
<span class="input-group-addon datepicker-addon">
<span class="fa fa-calendar"></span>
</span>
</div>
<script>
$(function () {
$('.datepicker input').datepicker({
todayBtn: "linked", // Enables the today button which quickly links back to today
endDate: '0d', // Prevents the user from picking a date in the future
});
});
</script>
{% endblock %}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
{% load i18n %}
{%load static %}

<link rel="stylesheet" href="{% static 'cloudkitty/css/datepicker.css' %}">
<script src="{% static 'cloudkitty/js/datepicker.js' %}" type="text/javascript" charset="utf-8"></script>

<form action="?" method="get" id="{{ datepicker_id }}" class="form-inline">
<h4>{% trans "Select a period of time to view data in:" %}
<span class="small help-block">{% trans "The date should be in YYYY-MM-DD format." %}</span>
</h4>
<div class="datepicker form-group">
{% with datepicker_input=form.start datepicker_label="From" %}
{% include 'project/reporting/_datepicker_reporting.html' %}
{% endwith %}
</div>
<span class="datepicker-delimiter">
<span class="datepicker-delimiter-text">{% trans 'to' %}</span>
</span>
<div class="datepicker form-group">
{% with datepicker_input=form.end datepicker_label="To" %}
{% include 'project/reporting/_datepicker_reporting.html' %}
{% endwith %}
</div>
<button class="btn btn-primary" type="submit">{% trans "Submit" %}</button>
</form>

<div class="controls-container">
<div class="dropdown default-ranges">
<button class="dropbtn">{% trans "Period Range" %}</button>
<div class="dropdown-content">
<button data-period="day" data-view="current">{% trans "Day View" %}</button>
<button data-period="week" data-view="current">{% trans "Week View" %}</button>
<button data-period="month" data-view="current">{% trans "Month View" %}</button>
<button data-period="year" data-view="current">{% trans "Year View" %}</button>
</div>
</div>
<div class="dropdown preset-ranges">
<button class="dropbtn">{% trans "Preset Ranges" %}</button>
<div class="dropdown-content">
<button data-period="day" data-view="yesterday">{% trans "Yesterday" %}</button>
<button data-period="week" data-view="last">{% trans "Last Week" %}</button>
<button data-period="month" data-view="last">{% trans "Last Month" %}</button>
<button data-period="month" data-view="last" data-amount="3">{% trans "Last 3 Months" %}</button>
<button data-period="month" data-view="last" data-amount="6">{% trans "Last 6 Months" %}</button>
<button data-period="year" data-view="last">{% trans "Last Year" %}</button>
</div>
</div>
<button class="arrow-btn" data-direction="prev">&laquo;</button>
<button class="arrow-btn" data-direction="next">&raquo;</button>
</div>


<script>
$(function () {
initDatepicker({
formId: '{{ datepicker_id }}',
startFieldName: '{{ form.start.name }}',
endFieldName: '{{ form.end.name }}'
});
});
</script>
Loading
Loading