From 360a7b7a86586e26ef06dfc3c65baa735ba18b22 Mon Sep 17 00:00:00 2001 From: Xinni Ge Date: Thu, 21 Jun 2018 19:08:50 +0900 Subject: [PATCH] Add support of event list pagination Add pagination support to event list api and show event list by page in stack detail page. Change-Id: Ie1699b267a4ca4c33669ea2fccfd170618fc2560 Story: #1343684 Task: #18885 --- heat_dashboard/api/heat.py | 36 ++++++++++++++++++++-- heat_dashboard/content/stacks/tables.py | 1 + heat_dashboard/content/stacks/tabs.py | 41 ++++++++++++++++++++----- 3 files changed, 69 insertions(+), 9 deletions(-) diff --git a/heat_dashboard/api/heat.py b/heat_dashboard/api/heat.py index 04ac1757..ca61523e 100644 --- a/heat_dashboard/api/heat.py +++ b/heat_dashboard/api/heat.py @@ -206,8 +206,40 @@ def snapshot_delete(request, stack_id, snapshot_id): @profiler.trace -def events_list(request, stack_name): - return heatclient(request).events.list(stack_name) +def events_list(request, stack_name, marker=None, sort_dir='desc', + sort_key='event_time', paginate=False, filters=None): + limit = getattr(settings, 'API_RESULT_LIMIT', 1000) + page_size = utils.get_page_size(request) + + if paginate: + request_size = page_size + 1 + else: + request_size = limit + kwargs = {'sort_dir': sort_dir, 'sort_key': sort_key} + if marker: + kwargs['marker'] = marker + + if filters: + kwargs.update(filters) + + events_iter = heatclient(request).events.list(stack_name, + limit=request_size, + **kwargs) + + has_prev_data = False + has_more_data = False + events = list(events_iter) + if paginate: + if len(events) > page_size: + events.pop() + has_more_data = True + if marker is not None: + has_prev_data = True + elif sort_dir == 'asc' and marker is not None: + has_more_data = True + elif marker is not None: + has_prev_data = True + return events, has_more_data, has_prev_data @profiler.trace diff --git a/heat_dashboard/content/stacks/tables.py b/heat_dashboard/content/stacks/tables.py index 4660a84d..3fcc01a5 100644 --- a/heat_dashboard/content/stacks/tables.py +++ b/heat_dashboard/content/stacks/tables.py @@ -333,6 +333,7 @@ class EventsTable(tables.DataTable): class Meta(object): name = "events" verbose_name = _("Stack Events") + pagination_param = 'event_marker' class ResourcesUpdateRow(tables.Row): diff --git a/heat_dashboard/content/stacks/tabs.py b/heat_dashboard/content/stacks/tabs.py index 11e91c28..91bb3297 100644 --- a/heat_dashboard/content/stacks/tabs.py +++ b/heat_dashboard/content/stacks/tabs.py @@ -11,6 +11,7 @@ # under the License. import logging +from operator import attrgetter from django.utils.translation import ugettext_lazy as _ @@ -81,9 +82,10 @@ class ResourceOverviewTab(tabs.Tab): "metadata": self.tab_group.kwargs['metadata']} -class StackEventsTab(tabs.Tab): +class StackEventsTab(tabs.TableTab): name = _("Events") slug = "events" + table_classes = (project_tables.EventsTable, ) template_name = "project/stacks/_detail_events.html" preload = False @@ -95,21 +97,46 @@ class StackEventsTab(tabs.Tab): ("orchestration", "events:index"),), request) - def get_context_data(self, request): + def get_events_data(self): stack = self.tab_group.kwargs['stack'] + stack_identifier = '%s/%s' % (stack.stack_name, stack.id) + prev_marker = self.request.GET.get( + project_tables.EventsTable._meta.prev_pagination_param) + if prev_marker is not None: + sort_dir = 'asc' + marker = prev_marker + else: + sort_dir = 'desc' + marker = self.request.GET.get( + project_tables.EventsTable._meta.pagination_param, None) + try: - stack_identifier = '%s/%s' % (stack.stack_name, stack.id) - events = api.heat.events_list(self.request, stack_identifier) + events, self._more, self._prev = api.heat.events_list( + self.request, + stack_identifier, + marker=marker, + paginate=True, + sort_dir=sort_dir) + if prev_marker is not None: + events = sorted(events, key=attrgetter('event_time'), + reverse=True) LOG.debug('got events %s', events) # The stack id is needed to generate the resource URL. for event in events: event.stack_id = stack.id except Exception: events = [] - messages.error(request, _( + self._prev = False + self._more = False + messages.error(self.request, _( 'Unable to get events for stack "%s".') % stack.stack_name) - return {"stack": stack, - "table": project_tables.EventsTable(request, data=events), } + return events + + def has_prev_data(self, table): + return self._prev + + def has_more_data(self, table): + return self._more class StackResourcesTab(tabs.Tab):