UI: Execution & task screens - state info tooltip

* Added tooltip to view "state info" on error states
* Extended Horizon base to support such behaviour (SmartCell)
* Implementation derived following a discussion with Horizon developers
* I was asked by Horizon devs to push an architectural solution
  so we may won't need that "workarround" in the future

Screenshots:
 http://pasteboard.co/lvX8FX2.png
 http://pasteboard.co/lAnTDBq.png

Partially implements blueprint: mistral-dashboard-executions-screen
Partially implements blueprint: tasks-screen-improvments

Change-Id: I9781e61b5385f96bcc73c4c8dbb93671ea179e73
This commit is contained in:
Gal Margalit 2015-12-27 13:30:32 +00:00
parent f01a2ed0c6
commit 3a1e52ed63
3 changed files with 100 additions and 1 deletions

View File

@ -0,0 +1,81 @@
# -*- coding: utf-8 -*-
#
# Copyright © 2015 - Alcatel-Lucent
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""File Overrides OpenStack Horizon Cell method to return the whole
row data using cell_attributes_getter"""
from django import forms
from django import template
from horizon.tables.base import Cell
import six
def get_data(self, datum, column, row):
"""Fetches the data to be displayed in this cell."""
table = row.table
if column.auto == "multi_select":
data = ""
if row.can_be_selected(datum):
widget = forms.CheckboxInput(check_test=lambda value: False)
# Convert value to string to avoid accidental type conversion
data = widget.render('object_ids',
six.text_type(table.get_object_id(datum)),
{'class': 'table-row-multi-select'})
table._data_cache[column][table.get_object_id(datum)] = data
elif column.auto == "form_field":
widget = column.form_field
if issubclass(widget.__class__, forms.Field):
widget = widget.widget
widget_name = "%s__%s" % \
(column.name,
six.text_type(table.get_object_id(datum)))
# Create local copy of attributes, so it don't change column
# class form_field_attributes
form_field_attributes = {}
form_field_attributes.update(column.form_field_attributes)
# Adding id of the input so it pairs with label correctly
form_field_attributes['id'] = widget_name
if (template.defaultfilters.urlize in column.filters or
template.defaultfilters.yesno in column.filters):
data = widget.render(widget_name,
column.get_raw_data(datum),
form_field_attributes)
else:
data = widget.render(widget_name,
column.get_data(datum),
form_field_attributes)
table._data_cache[column][table.get_object_id(datum)] = data
elif column.auto == "actions":
data = table.render_row_actions(datum, pull_right=False)
table._data_cache[column][table.get_object_id(datum)] = data
else:
data = column.get_data(datum)
if column.cell_attributes_getter:
# Following line is the change: cell_attributes_getter called with
# "datum" instead of "data"
cell_attributes = column.cell_attributes_getter(datum) or {}
self.attrs.update(cell_attributes)
return data
def init():
Cell.get_data = get_data

View File

@ -21,9 +21,12 @@ from horizon import exceptions
from horizon import tables from horizon import tables
from mistraldashboard import api from mistraldashboard import api
import mistraldashboard.default.SmartCell as SmartCell
from mistraldashboard.default.utils import humantime from mistraldashboard.default.utils import humantime
from mistraldashboard.default.utils import label from mistraldashboard.default.utils import label
SmartCell.init()
class DeleteExecution(tables.DeleteAction): class DeleteExecution(tables.DeleteAction):
@staticmethod @staticmethod
@ -155,6 +158,11 @@ class UpdateRow(tables.Row):
class ExecutionsTable(tables.DataTable): class ExecutionsTable(tables.DataTable):
def getHoverHelp(data):
if hasattr(data, 'state_info') and data.state_info:
return {'title': data.state_info}
STATE_STATUS_CHOICES = ( STATE_STATUS_CHOICES = (
("success", True), ("success", True),
("error", False), ("error", False),
@ -214,6 +222,7 @@ class ExecutionsTable(tables.DataTable):
filters=[label], filters=[label],
status=True, status=True,
status_choices=STATE_STATUS_CHOICES, status_choices=STATE_STATUS_CHOICES,
cell_attributes_getter=getHoverHelp
) )
class Meta(object): class Meta(object):

View File

@ -20,9 +20,12 @@ from horizon import exceptions
from horizon import tables from horizon import tables
from mistraldashboard import api from mistraldashboard import api
import mistraldashboard.default.SmartCell as SmartCell
from mistraldashboard.default.utils import humantime from mistraldashboard.default.utils import humantime
from mistraldashboard.default.utils import label from mistraldashboard.default.utils import label
SmartCell.init()
class UpdateRow(tables.Row): class UpdateRow(tables.Row):
ajax = True ajax = True
@ -41,6 +44,11 @@ class UpdateRow(tables.Row):
class TaskTable(tables.DataTable): class TaskTable(tables.DataTable):
def getHoverHelp(data):
if hasattr(data, 'state_info') and data.state_info:
return {'title': data.state_info}
STATE_STATUS_CHOICES = ( STATE_STATUS_CHOICES = (
("success", True), ("success", True),
("error", False), ("error", False),
@ -92,7 +100,8 @@ class TaskTable(tables.DataTable):
status=True, status=True,
status_choices=STATE_STATUS_CHOICES, status_choices=STATE_STATUS_CHOICES,
verbose_name=_("State"), verbose_name=_("State"),
filters=[label] filters=[label],
cell_attributes_getter=getHoverHelp
) )
class Meta(object): class Meta(object):