Object Upload validated on client side

Perform a js validation of the Object Upload name. If the name is
not entered, the submit button will appears disabled.

Fixes bug #1125232
Change-Id: Id33f3999e9267f5fc58eb55406fc5b763597839b
Co-Authored-By: Cristian A Sanchez <cristian.a.sanchez@intel.com>
This commit is contained in:
Maxime Vidori 2013-12-05 18:04:57 +01:00
parent 859f8cfe7e
commit b37b9d5fc4
7 changed files with 91 additions and 45 deletions

View File

@ -0,0 +1,7 @@
/*globals horizonApp*/
(function () {
'use strict';
horizonApp.
controller('DummyCtrl', function () {
});
}());

View File

@ -0,0 +1,22 @@
/*globals horizonApp*/
(function () {
'use strict';
horizonApp.
directive('notBlank', function () {
return {
require: 'ngModel',
link: function (scope, elm, attrs, ctrl) {
ctrl.$parsers.unshift(function (viewValue) {
if (viewValue.length) {
// it is valid
ctrl.$setValidity('notBlank', true);
return viewValue;
}
// it is invalid, return undefined (no model update)
ctrl.$setValidity('notBlank', false);
return undefined;
});
}
};
});
}());

View File

@ -1,50 +1,52 @@
horizon.addInitFunction(function () {
module('Coding Style (jsHint)');
module('Coding Style (jsHint)');
test('jsHint', function () {
expect(0);
test('jsHint', function () {
expect(0);
config = {
// Warnings reported by JSHint. Suppressing for now...
'-W080': true, // it's not necessary to initialize to 'undefined'
config = {
// Warnings reported by JSHint. Suppressing for now...
'-W080': true, // it's not necessary to initialize to 'undefined'
// Proposed set of rules
//'camelcase' : true,
//'indent': 2,
//'undef': true,
//'quotmark': 'single',
//'maxlen': 80,
//'trailing': true,
//'curly': true
};
// Proposed set of rules
//'camelcase' : true,
//'indent': 2,
//'undef': true,
//'quotmark': 'single',
//'maxlen': 80,
//'trailing': true,
//'curly': true
};
jsHintTest('horizon.communication.js', '/static/horizon/js/horizon.communication.js', config);
jsHintTest('horizon.conf.js', '/static/horizon/js/horizon.conf.js', config);
jsHintTest('horizon.cookies.js', '/static/horizon/js/horizon.cookies.js', config);
jsHintTest('horizon.d3linechart.js', '/static/horizon/js/horizon.d3linechart.js', config);
jsHintTest('horizon.d3piechart.js', '/static/horizon/js/horizon.d3piechart.js', config);
jsHintTest('horizon.firewalls.js', '/static/horizon/js/horizon.firewalls.js', config);
jsHintTest('horizon.forms.js', '/static/horizon/js/horizon.forms.js', config);
jsHintTest('horizon.formset_table.js', '/static/horizon/js/horizon.formset_table.js', config);
jsHintTest('horizon.heattop.js', '/static/horizon/js/horizon.heattop.js', config);
jsHintTest('horizon.instances.js', '/static/horizon/js/horizon.instances.js', config);
jsHintTest('horizon.js', '/static/horizon/js/horizon.js', config);
jsHintTest('horizon.membership.js', '/static/horizon/js/horizon.membership.js', config);
jsHintTest('horizon.messages.js', '/static/horizon/js/horizon.messages.js', config);
jsHintTest('horizon.modals.js', '/static/horizon/js/horizon.modals.js', config);
jsHintTest('horizon.networktopology.js', '/static/horizon/js/horizon.networktopology.js', config);
jsHintTest('horizon.quota.js', '/static/horizon/js/horizon.quota.js', config);
jsHintTest('horizon.tables.js', '/static/horizon/js/horizon.tables.js', config);
jsHintTest('horizon.tabs.js', '/static/horizon/js/horizon.tabs.js', config);
jsHintTest('horizon.templates.js', '/static/horizon/js/horizon.templates.js', config);
jsHintTest('horizon.users.js', '/static/horizon/js/horizon.users.js', config);
jsHintTest('horizon.utils.js', '/static/horizon/js/horizon.utils.js', config);
jsHintTest('horizon.communication.js', '/static/horizon/js/horizon.communication.js', config);
jsHintTest('horizon.conf.js', '/static/horizon/js/horizon.conf.js', config);
jsHintTest('horizon.cookies.js', '/static/horizon/js/horizon.cookies.js', config);
jsHintTest('horizon.d3linechart.js', '/static/horizon/js/horizon.d3linechart.js', config);
jsHintTest('horizon.d3piechart.js', '/static/horizon/js/horizon.d3piechart.js', config);
jsHintTest('horizon.firewalls.js', '/static/horizon/js/horizon.firewalls.js', config);
jsHintTest('horizon.forms.js', '/static/horizon/js/horizon.forms.js', config);
jsHintTest('horizon.heattop.js', '/static/horizon/js/horizon.heattop.js', config);
jsHintTest('horizon.instances.js', '/static/horizon/js/horizon.instances.js', config);
jsHintTest('horizon.js', '/static/horizon/js/horizon.js', config);
jsHintTest('horizon.membership.js', '/static/horizon/js/horizon.membership.js', config);
jsHintTest('horizon.messages.js', '/static/horizon/js/horizon.messages.js', config);
jsHintTest('horizon.modals.js', '/static/horizon/js/horizon.modals.js', config);
jsHintTest('horizon.networktopology.js', '/static/horizon/js/horizon.networktopology.js', config);
jsHintTest('horizon.quota.js', '/static/horizon/js/horizon.quota.js', config);
jsHintTest('horizon.tables.js', '/static/horizon/js/horizon.tables.js', config);
jsHintTest('horizon.tabs.js', '/static/horizon/js/horizon.tabs.js', config);
jsHintTest('horizon.templates.js', '/static/horizon/js/horizon.templates.js', config);
jsHintTest('horizon.users.js', '/static/horizon/js/horizon.users.js', config);
jsHintTest('horizon.utils.js', '/static/horizon/js/horizon.utils.js', config);
jsHintTest('tests/jshint.js', '/static/horizon/tests/jshint.js', config);
jsHintTest('tests/messages.js', '/static/horizon/tests/messages.js', config);
jsHintTest('tests/modals.js', '/static/horizon/tests/modals.js', config);
jsHintTest('tests/tables.js', '/static/horizon/tests/tables.js', config);
jsHintTest('tests/templates.js', '/static/horizon/tests/templates.js', config);
jsHintTest('tests/jshint.js', '/static/horizon/tests/jshint.js', config);
jsHintTest('tests/messages.js', '/static/horizon/tests/messages.js', config);
jsHintTest('tests/modals.js', '/static/horizon/tests/modals.js', config);
jsHintTest('tests/tables.js', '/static/horizon/tests/tables.js', config);
jsHintTest('tests/templates.js', '/static/horizon/tests/templates.js', config);
});
jsHintTest('angular/horizon.js', '/static/horizon/js/angular/horizon.js', config);
jsHintTest('angular/directives/forms.js', '/static/horizon/js/angular/directives/forms.js', config);
jsHintTest('angular/controllers/dummy.js', '/static/horizon/js/angular/controllers/dummy.js', config);
});
});

View File

@ -10,6 +10,8 @@
<script src="{{ STATIC_URL }}horizon/lib/angular.js" type="text/javascript" charset="utf-8"></script>
<script src='{{ STATIC_URL }}horizon/js/angular/horizon.js' type='text/javascript' charset='utf-8'></script>
<script src='{{ STATIC_URL }}horizon/js/angular/controllers/dummy.js' type='text/javascript' charset='utf-8'></script>
<script src='{{ STATIC_URL }}horizon/js/angular/directives/forms.js' type='text/javascript' charset='utf-8'></script>
<script src='{{ STATIC_URL }}horizon/lib/jquery/jquery.cookie.js' type='text/javascript' charset="utf-8"></script>
<script src='{{ STATIC_URL }}horizon/lib/jquery/jquery.quicksearch.js' type='text/javascript' charset="utf-8"></script>

View File

@ -9,7 +9,14 @@
</div>
<hr />
{% endif %}
<form id="{% block form_id %}{% endblock %}" autocomplete="{% block autocomplete %}{% endblock %}" class="{% block form_class %}{% endblock %}" action="{% block form_action %}{% endblock %}" method="{% block form-method %}POST{% endblock %}" {% if add_to_field %}data-add-to-field="{{ add_to_field }}"{% endif %} {% block form_attrs %}{% endblock %}>{% csrf_token %}
<form id="{% block form_id %}{% endblock %}"
ng-controller="{% block ng_controller %}DummyCtrl{% endblock %}"
name="{% block form_name %}{% endblock %}"
autocomplete="{% block autocomplete %}{% endblock %}"
class="{% block form_class %}{% endblock %}"
action="{% block form_action %}{% endblock %}"
method="{% block form-method %}POST{% endblock %}"
{% if add_to_field %}data-add-to-field="{{ add_to_field }}"{% endif %} {% block form_attrs %}{% endblock %}>{% csrf_token %}
<div class="modal-body clearfix">
{% block modal-body %}
<fieldset>

View File

@ -82,11 +82,16 @@ class UploadObject(forms.SelfHandlingForm):
path = forms.CharField(max_length=255,
required=False,
widget=forms.HiddenInput)
name = forms.CharField(max_length=255,
label=_("Object Name"),
help_text=_("Slashes are allowed, and are treated "
"as pseudo-folders by the Object "
"Store."))
"Store."),
widget=forms.TextInput(
attrs={"ng-model": "name",
"not-blank": ""}
))
object_file = forms.FileField(label=_("File"), allow_empty_file=True)
container_name = forms.CharField(widget=forms.HiddenInput())

View File

@ -3,6 +3,7 @@
{% load url from future %}
{% block form_id %}upload_object_form{% endblock %}
{% block form_name %}uploadForm{% endblock %}
{% block form_action %}{% url 'horizon:project:containers:object_upload' container_name %}{% endblock %}
{% block form_attrs %}enctype="multipart/form-data"{% endblock %}
@ -22,6 +23,6 @@
{% endblock %}
{% block modal-footer %}
<input class="btn btn-primary pull-right" type="submit" value="{% trans "Upload Object" %}" />
<input class="btn btn-primary pull-right" type="submit" ng-disabled="uploadForm.$invalid || uploadForm.$pristine" value="{% trans "Upload Object" %}" />
<a href="{% url 'horizon:project:containers:index' container_name|add:'/' %}" class="btn secondary cancel close">{% trans "Cancel" %}</a>
{% endblock %}