summaryrefslogtreecommitdiff
path: root/horizon
diff options
context:
space:
mode:
authorDiana Whitten <hurgleburgler@gmail.com>2015-10-08 12:22:08 -0700
committerDiana Whitten <hurgleburgler@gmail.com>2015-12-03 16:07:00 +0000
commit053b5f30d7b2c4b5ba6d885dc28723744e5b22db (patch)
tree627e08e9deae4f4ca183d508b34dbb6e1848f289 /horizon
parenteae45b143cb7be538c11b1b1b51aa7dd4be2e23d (diff)
downloadhorizon-053b5f30d7b2c4b5ba6d885dc28723744e5b22db.tar.gz
Horizon Dropdown now inherits from Bootstrap Theme
Horizon dropdowns now use proper Bootstrap markup to allow for theme inheritance. It was noticed during this effort that Horizon was using a mixture of <a> and <button> elements within dropdowns, and having to override CSS so that their styles were shared. This created unnecessary complexity in the CSS: http://getbootstrap.com/components/#dropdowns It was also noted that we were passing Bootstrap classes defined in the Python code to the templates through a static string that was concatenated within all the other needed attributes. This makes overriding the templates with custom classes difficult. New logic was added to allow classes to be separate. This more granular approach was added to the table drop down templates. Partially-Implements: blueprint horizon-theme-css-reorg Partially-Implements: blueprint bootstrap-html-standards Partial-bug: #1490207 Change-Id: Id82999e5db37035968d39361ba9be4ff87c26f66
Diffstat (limited to 'horizon')
-rw-r--r--horizon/tables/actions.py2
-rw-r--r--horizon/templates/horizon/common/_data_table_action.html42
-rw-r--r--horizon/templates/horizon/common/_data_table_row_action_dropdown.html5
-rw-r--r--horizon/templates/horizon/common/_data_table_row_actions_dropdown.html25
-rw-r--r--horizon/templates/horizon/common/_data_table_table_action.html11
-rw-r--r--horizon/templates/horizon/common/_data_table_table_actions.html16
-rw-r--r--horizon/templatetags/horizon.py37
-rw-r--r--horizon/utils/html.py15
8 files changed, 118 insertions, 35 deletions
diff --git a/horizon/tables/actions.py b/horizon/tables/actions.py
index 00e78ec5f..fda32de06 100644
--- a/horizon/tables/actions.py
+++ b/horizon/tables/actions.py
@@ -37,7 +37,7 @@ from horizon.utils import html
LOG = logging.getLogger(__name__)
# For Bootstrap integration; can be overridden in settings.
-ACTION_CSS_CLASSES = ("btn", "btn-default")
+ACTION_CSS_CLASSES = ()
STRING_SEPARATOR = "__"
diff --git a/horizon/templates/horizon/common/_data_table_action.html b/horizon/templates/horizon/common/_data_table_action.html
new file mode 100644
index 000000000..3fe51eb18
--- /dev/null
+++ b/horizon/templates/horizon/common/_data_table_action.html
@@ -0,0 +1,42 @@
+{% load horizon %}
+
+{% minifyspace %}
+ {% if action.method != "GET" %}
+ <button {{ action.attr_string_nc|safe }}
+ class="{% if is_single %}btn btn-default {% endif %}{% if is_small %}btn-sm {% endif %}{{ action.get_final_css|safe }}"
+ name="action"
+ {% if action.help_text %}
+ help_text="{{ action.help_text }}"
+ {% endif %}
+ type="submit"
+ {% if is_table_action %}
+ value="{{ action.get_param_name }}">
+ {% if action.icon != None %}
+ <span class="fa fa-{{ action.icon }}"></span>
+ {% endif %}
+ {% if action.handles_multiple %}
+ {{ action.verbose_name_plural }}
+ {% else %}
+ {{ action.verbose_name }}
+ {% endif %}
+ {% else %}
+ value="{{ action.table.name }}__{{ action.name }}__{{ row_id }}">
+ {{ action.verbose_name }}
+ {% endif %}
+ </button>
+ {% else %}
+ <a {{ action.attr_string_nc|safe }}
+ class="{% if is_single %}btn btn-default {% endif %}{% if is_small %}btn-sm {% endif %}{{ action.get_final_css|safe }}"
+ {% if is_table_action %}
+ href="{{ action.get_link_url }}"
+ title="{{ action.verbose_name }}">
+ {% if action.icon != None %}
+ <span class="fa fa-{{ action.icon }}"></span>
+ {% endif %}
+ {% else %}
+ href="{{ action.bound_url }}">
+ {% endif %}
+ {{ action.verbose_name }}
+ </a>
+ {% endif %}
+{% endminifyspace %}
diff --git a/horizon/templates/horizon/common/_data_table_row_action_dropdown.html b/horizon/templates/horizon/common/_data_table_row_action_dropdown.html
deleted file mode 100644
index aee336f6b..000000000
--- a/horizon/templates/horizon/common/_data_table_row_action_dropdown.html
+++ /dev/null
@@ -1,5 +0,0 @@
-{% if action.method != "GET" %}
- <button {{ action.attr_string|safe }} {% if action.help_text %}help_text="{{ action.help_text }}"{% endif %} name="action" value="{{ action.table.name }}__{{ action.name }}__{{ row_id }}" type="submit">{{ action.verbose_name }}</button>
-{% else %}
- <a href='{{ action.bound_url }}' {{ action.attr_string|safe }}>{{ action.verbose_name }}</a>
-{% endif %}
diff --git a/horizon/templates/horizon/common/_data_table_row_actions_dropdown.html b/horizon/templates/horizon/common/_data_table_row_actions_dropdown.html
index 37afa0ff0..9b62e9dd2 100644
--- a/horizon/templates/horizon/common/_data_table_row_actions_dropdown.html
+++ b/horizon/templates/horizon/common/_data_table_row_actions_dropdown.html
@@ -1,27 +1,28 @@
{% load horizon i18n %}
{% spaceless %} {# This makes sure whitespace doesn't affect positioning for dropdown. #}
-{% if row_actions|length > 1 %}
-<div class="btn-group {% if pull_right %}pull-right{% endif %}">
- {% for action in row_actions %}
+
+ {% if row_actions|length == 1 %}
+ {% include "horizon/common/_data_table_action.html" with action=row_actions.0 is_single=1 %}
+ {% elif row_actions|length > 1 %}
+ <div class="btn-group {% if pull_right %}pull-right{% endif %}">
+ {% for action in row_actions %}
{% if forloop.first %}
- {% include "horizon/common/_data_table_row_action_dropdown.html" %}
+ {% include "horizon/common/_data_table_action.html" with is_small=1 is_single=1 %}
<a class="btn btn-default btn-sm dropdown-toggle" data-toggle="dropdown" href="#">
<span class="fa fa-caret-down"></span>
</a>
- <ul class="dropdown-menu row_actions dropdown-menu-right">
+ <ul class="dropdown-menu dropdown-menu-right row_actions">
{% else %}
<li>
- {% include "horizon/common/_data_table_row_action_dropdown.html" %}
+ {% include "horizon/common/_data_table_action.html" %}
</li>
{% endif %}
{% if forloop.last %}
</ul>
{% endif %}
- {% endfor %}
-</div>
-{% endif %}
-{% if row_actions|length == 1 %}
- {% include "horizon/common/_data_table_row_action_dropdown.html" with action=row_actions.0 %}
-{% endif %}
+ {% endfor %}
+ </div>
+ {% endif %}
+
{% endspaceless %}
diff --git a/horizon/templates/horizon/common/_data_table_table_action.html b/horizon/templates/horizon/common/_data_table_table_action.html
deleted file mode 100644
index b0e819e2e..000000000
--- a/horizon/templates/horizon/common/_data_table_table_action.html
+++ /dev/null
@@ -1,11 +0,0 @@
-{% if action.method != "GET" %}
- <button {{ action.attr_string|safe }} name="action" value="{{ action.get_param_name }}" {% if action.help_text %}help_text="{{ action.help_text }}"{% endif %} type="submit">
- {% if action.icon != None %}<span class="fa fa-{{ action.icon }}"></span> {% endif %}
- {% if action.handles_multiple %}{{ action.verbose_name_plural }}{% else %}{{ action.verbose_name }}{% endif %}
- </button>
-{% else %}
- <a href='{{ action.get_link_url }}' title='{{ action.verbose_name }}' {{ action.attr_string|safe }}>
- {% if action.icon != None %}<span class="fa fa-{{ action.icon }}"></span> {% endif %}
- {{ action.verbose_name }}
- </a>
-{% endif %}
diff --git a/horizon/templates/horizon/common/_data_table_table_actions.html b/horizon/templates/horizon/common/_data_table_table_actions.html
index bd3f79d50..40cb31cdc 100644
--- a/horizon/templates/horizon/common/_data_table_table_actions.html
+++ b/horizon/templates/horizon/common/_data_table_table_actions.html
@@ -30,14 +30,23 @@
{% endfor %}
</select>
<input class="form-control" value="{{ filter.filter_string|default:'' }}" type="text" name="{{ filter.get_param_name }}" />
- <button type="submit" {{ filter.attr_string|safe }}>{% trans "Filter" %}</button>
+ <button type="submit" class="btn btn-default {{ filter.get_final_css|safe }}" {{ filter.attr_string_nc|safe }}>{% trans "Filter" %}</button>
</div>
{% endif %}
{% endblock table_filter %}
+
{% block table_actions %}
+
+ {% comment %}
+ For each single action in the Table Actions area
+ {% endcomment %}
{% for action in table_actions_buttons %}
- {% include "horizon/common/_data_table_table_action.html" %}
+ {% include "horizon/common/_data_table_action.html" with is_table_action=1 is_single=1 %}
{% endfor %}
+
+ {% comment %}
+ If additional actions are defined, scoop them into the actions dropdown menu
+ {% endcomment %}
{% if table_actions_menu|length > 0 %}
<div class="btn-group table_actions_menu">
<a class="btn btn-default dropdown-toggle" data-toggle="dropdown" href="#">
@@ -51,11 +60,12 @@
<ul class="dropdown-menu dropdown-menu-right">
{% for action in table_actions_menu %}
<li>
- {% include "horizon/common/_data_table_table_action.html" %}
+ {% include "horizon/common/_data_table_action.html" with is_table_action=1 %}
</li>
{% endfor %}
</ul>
</div>
{% endif %}
{% endblock table_actions %}
+
</div>
diff --git a/horizon/templatetags/horizon.py b/horizon/templatetags/horizon.py
index c8ef4f112..bca67bd45 100644
--- a/horizon/templatetags/horizon.py
+++ b/horizon/templatetags/horizon.py
@@ -19,6 +19,7 @@ from horizon.contrib import bootstrap_datepicker
from django.conf import settings
from django import template
+from django.template import Node
from django.utils.encoding import force_text
from django.utils import translation
from django.utils.translation import ugettext_lazy as _
@@ -26,10 +27,19 @@ from django.utils.translation import ugettext_lazy as _
from horizon.base import Horizon # noqa
from horizon import conf
-
register = template.Library()
+class MinifiedNode(Node):
+ def __init__(self, nodelist):
+ self.nodelist = nodelist
+
+ def render(self, context):
+ return ' '.join(
+ force_text(self.nodelist.render(context).strip()).split()
+ )
+
+
@register.filter
def has_permissions(user, component):
"""Checks if the given user meets the permissions requirements for
@@ -198,3 +208,28 @@ def datepicker_locale():
locale_mapping = getattr(settings, 'DATEPICKER_LOCALES',
bootstrap_datepicker.LOCALE_MAPPING)
return locale_mapping.get(translation.get_language(), 'en')
+
+
+@register.tag
+def minifyspace(parser, token):
+ """Removes whitespace including tab and newline characters. Do not use this
+ if you are using a <pre> tag
+
+ Example usage::
+
+ {% minifyspace %}
+ <p>
+ <a title="foo"
+ href="foo/">
+ Foo
+ </a>
+ </p>
+ {% endminifyspace %}
+
+ This example would return this HTML::
+
+ <p><a title="foo" href="foo/">Foo</a></p>
+ """
+ nodelist = parser.parse(('endminifyspace',))
+ parser.delete_first_token()
+ return MinifiedNode(nodelist)
diff --git a/horizon/utils/html.py b/horizon/utils/html.py
index fe5c3c60b..e936bb89c 100644
--- a/horizon/utils/html.py
+++ b/horizon/utils/html.py
@@ -33,13 +33,17 @@ class HTMLElement(object):
"""
return {}
- def get_final_attrs(self):
+ def get_final_attrs(self, classes=True):
"""Returns a dict containing the final attributes of this element
which will be rendered.
"""
final_attrs = copy.copy(self.get_default_attrs())
final_attrs.update(self.attrs)
- final_attrs['class'] = self.get_final_css()
+ if classes:
+ final_attrs['class'] = self.get_final_css()
+ else:
+ final_attrs.pop('class', None)
+
return final_attrs
def get_final_css(self):
@@ -59,6 +63,13 @@ class HTMLElement(object):
return flatatt(self.get_final_attrs())
@property
+ def attr_string_nc(self):
+ """Returns a flattened string of HTML attributes based on the
+ ``attrs`` dict provided to the class.
+ """
+ return flatatt(self.get_final_attrs(False))
+
+ @property
def class_string(self):
"""Returns a list of class name of HTML Element in string."""
classes_str = " ".join(self.classes)