Implement required field indicator
Change Horizon's use of forms to set 'required' css class for required fields. Change template _form_fields.html to include Django field classes in order to honor above setting. Also changed horizon workflow to set "required" class on tabs of steps that contain required fields. Horizon CSS appends an asterisk after the field label and tab text based on "required" classname. The current indicator is based on review with horizon UX people and can be customized easily. Change-Id: I03261328d70abcefd13f609088ccb4d58ef30067 Implements: blueprint required-fields
This commit is contained in:
parent
8411e406e6
commit
dbe4a6792b
@ -36,6 +36,8 @@ class SelfHandlingForm(SelfHandlingMixin, forms.Form):
|
||||
A base :class:`Form <django:django.forms.Form>` class which includes
|
||||
processing logic in its subclasses.
|
||||
"""
|
||||
required_css_class = 'required'
|
||||
|
||||
def api_error(self, message):
|
||||
"""
|
||||
Adds an error to the form's error dictionary after validation
|
||||
|
@ -7,7 +7,7 @@
|
||||
</div>
|
||||
{% endif %}
|
||||
{% for field in form.visible_fields %}
|
||||
<div class="control-group form-field clearfix{% if field.errors %} error{% endif %}">
|
||||
<div class="control-group form-field clearfix{% if field.errors %} error{% endif %} {{ field.css_classes }}">
|
||||
{{ field.label_tag }}
|
||||
{% if field.errors %}
|
||||
{% for error in field.errors %}
|
||||
|
@ -13,7 +13,7 @@
|
||||
{% block modal-body %}
|
||||
<ul class="nav nav-tabs">
|
||||
{% for step in workflow.steps %}
|
||||
<li class="{% if entry_point == step.slug %}active{% endif %}{% if step.has_errors %} error{% endif %}">
|
||||
<li class="{% if entry_point == step.slug %}active{% endif %}{% if step.has_errors %} error{% endif %}{% if step.has_required_fields %} required{% endif %}">
|
||||
<a href="#{{ step.get_id }}" data-toggle="tab" data-target="#{{ step.get_id }}">{{ step }}</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
|
@ -139,6 +139,7 @@ class Action(forms.Form):
|
||||
% self.__class__.__name__)
|
||||
self.request = request
|
||||
self._populate_choices(request, context)
|
||||
self.required_css_class = 'required'
|
||||
|
||||
def __unicode__(self):
|
||||
return force_unicode(self.name)
|
||||
@ -445,6 +446,16 @@ class Step(object):
|
||||
"""
|
||||
self.action.add_error(message)
|
||||
|
||||
def has_required_fields(self):
|
||||
"""
|
||||
Returns True if action contains any required fields
|
||||
"""
|
||||
for key in self.contributes:
|
||||
field = self.action.fields.get(key, None)
|
||||
if (field and field.required):
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
class WorkflowMetaclass(type):
|
||||
def __new__(mcs, name, bases, attrs):
|
||||
|
@ -36,8 +36,6 @@ LOG = logging.getLogger(__name__)
|
||||
class CreateNetworkInfoAction(workflows.Action):
|
||||
net_name = forms.CharField(max_length=255,
|
||||
label=_("Network Name"),
|
||||
help_text=_("Network Name. This field is "
|
||||
"optional."),
|
||||
required=False)
|
||||
admin_state = forms.BooleanField(label=_("Admin State"),
|
||||
initial=True, required=False)
|
||||
@ -59,8 +57,6 @@ class CreateSubnetInfoAction(workflows.Action):
|
||||
initial=True, required=False)
|
||||
subnet_name = forms.CharField(max_length=255,
|
||||
label=_("Subnet Name"),
|
||||
help_text=_("Subnet Name. This field is "
|
||||
"optional."),
|
||||
required=False)
|
||||
cidr = fields.IPField(label=_("Network Address"),
|
||||
required=False,
|
||||
@ -72,7 +68,7 @@ class CreateSubnetInfoAction(workflows.Action):
|
||||
ip_version = forms.ChoiceField(choices=[(4, 'IPv4'), (6, 'IPv6')],
|
||||
label=_("IP Version"))
|
||||
gateway_ip = fields.IPField(
|
||||
label=_("Gateway IP (optional)"),
|
||||
label=_("Gateway IP"),
|
||||
required=False,
|
||||
initial="",
|
||||
help_text=_("IP address of Gateway (e.g. 192.168.0.254) "
|
||||
|
@ -1144,6 +1144,15 @@ form div.clearfix.error {
|
||||
content: "*";
|
||||
}
|
||||
|
||||
.nav-tabs li.required a:after,
|
||||
form .form-field.required > label:after {
|
||||
content: "*";
|
||||
font-weight: bold;
|
||||
line-height: 0;
|
||||
padding-left: 4px;
|
||||
color: #3290c0;
|
||||
}
|
||||
|
||||
/* Region selector in header */
|
||||
|
||||
#region_selector {
|
||||
|
Loading…
x
Reference in New Issue
Block a user