Record creation / update screen simplification
This change moves the record create and update screen so that users only need to provide the leftmost label of the record they would like to use. Change-Id: I033c7c6bf327f667397f0aca5ed3eb17259c9543 Closes-bug: #1461213
This commit is contained in:
@@ -18,6 +18,7 @@ import re
|
||||
from designateclient import exceptions as designate_exceptions
|
||||
from django.core.exceptions import ValidationError # noqa
|
||||
from django.core import validators
|
||||
from django.template.loader import render_to_string
|
||||
from django.utils.translation import ugettext_lazy as _ # noqa
|
||||
|
||||
from horizon import forms
|
||||
@@ -38,6 +39,8 @@ WILDCARD_DOMAIN_NAME_REGEX = r'^(?!.{255,})(?:(^\*|(?!\-)[A-Za-z0-9_\-]{1,63})(?
|
||||
SRV_NAME_REGEX = r'^(?:_[A-Za-z0-9_\-]{1,62}\.){2}'
|
||||
SRV_DATA_REGEX = r'^(?:(?:6553[0-5]|655[0-2][0-9]|65[0-4][0-9]{2}|6[0-4][0-9]{3}|[1-5][0-9]{4}|[1-9][0-9]{1,3}|[0-9])\s){2}(?!.{255,})((?!\-)[A-Za-z0-9_\-]{1,63}(?<!\-)\.)+$' # noqa
|
||||
SSHFP_DATA_REGEX = r'^[1-3]\s[1-2]\s\b([0-9a-fA-F]{5,40}|[0-9a-fA-F]{64})\b$'
|
||||
# The max length for a dns label
|
||||
NAME_MAX_LENGTH = 63
|
||||
|
||||
|
||||
def handle_exc(func):
|
||||
@@ -189,6 +192,16 @@ class DomainUpdate(DomainForm):
|
||||
return domain
|
||||
|
||||
|
||||
class PrefixWidget(forms.TextInput):
|
||||
|
||||
def render(self, name, value, attrs=None):
|
||||
template_name = 'project/dns_domains/prefix_html_widget.html'
|
||||
result = super(PrefixWidget, self).render(name, value, attrs)
|
||||
view_data = {'input': result,
|
||||
'suffix': getattr(self, "suffix", '')}
|
||||
return render_to_string(template_name, view_data)
|
||||
|
||||
|
||||
class RecordForm(forms.SelfHandlingForm):
|
||||
|
||||
'''Base class for RecordCreate and RecordUpdate forms.
|
||||
@@ -224,9 +237,8 @@ class RecordForm(forms.SelfHandlingForm):
|
||||
)
|
||||
|
||||
name = forms.CharField(
|
||||
max_length=256,
|
||||
required=False,
|
||||
widget=forms.TextInput(attrs={
|
||||
widget=PrefixWidget(attrs={
|
||||
'class': 'switched',
|
||||
'data-switch-on': 'record_type',
|
||||
'data-record_type-a': _('Name'),
|
||||
@@ -324,6 +336,10 @@ class RecordForm(forms.SelfHandlingForm):
|
||||
def __init__(self, request, *args, **kwargs):
|
||||
super(RecordForm, self).__init__(request, *args, **kwargs)
|
||||
initial = kwargs.get('initial', {})
|
||||
domain_suffix = "." + initial['domain_name']
|
||||
self.fields['name'].widget.suffix = domain_suffix
|
||||
self.fields['name'].max_length = min(NAME_MAX_LENGTH,
|
||||
255 - len(domain_suffix))
|
||||
if limit_records_to_fips():
|
||||
del self.fields['data'].widget.attrs['data-record_type-a']
|
||||
del self.fields['data'].widget.attrs['data-record_type-aaaa']
|
||||
@@ -390,16 +406,14 @@ class RecordForm(forms.SelfHandlingForm):
|
||||
else:
|
||||
cleaned_data['name'] += domain_name
|
||||
else:
|
||||
cleaned_data['name'] += "." + domain_name
|
||||
if not re.match(WILDCARD_DOMAIN_NAME_REGEX,
|
||||
cleaned_data['name']):
|
||||
self._add_field_error('name', _('Enter a valid hostname.'
|
||||
' The hostname should end'
|
||||
' with a period.'))
|
||||
elif not cleaned_data['name'].endswith(domain_name):
|
||||
self._add_field_error(
|
||||
'name',
|
||||
_('Name must be in the current domain'))
|
||||
|
||||
self._add_field_error('name',
|
||||
_('Enter a valid hostname. The '
|
||||
'hostname should contain letters '
|
||||
'and numbers, and be no more than '
|
||||
'63 characters.'))
|
||||
# Data field
|
||||
if self._is_field_blank(cleaned_data, 'data'):
|
||||
if record_type in ['A', 'AAAA', 'CNAME', 'MX', 'SRV']:
|
||||
|
||||
@@ -7,13 +7,16 @@
|
||||
{% block modal_id %}create_record_modal{% endblock %}
|
||||
{% block modal-header %}{% trans "Create Record for" %} {{ domain.name }}{% endblock %}
|
||||
|
||||
{% block modal-body-right %}
|
||||
<h3>{% trans "Description:" %}</h3>
|
||||
{% block modal-body %}
|
||||
|
||||
<div id="scoped-content">
|
||||
{% include 'project/dns_domains/prefix_field_style.html' %}
|
||||
<fieldset>
|
||||
{% include "horizon/common/_form_fields.html" %}
|
||||
</fieldset>
|
||||
</div>
|
||||
|
||||
{% blocktrans %}
|
||||
<p>
|
||||
<strong>Please note:</strong>
|
||||
For record types, the name <strong>must</strong> end with a period.
|
||||
</p>
|
||||
<p>
|
||||
<strong>TTL</strong>
|
||||
The TTL is the time-to-live for the record, in seconds.
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
<style type = "text/css" scoped>
|
||||
.form_field_suffix { float: right; padding-top:10px; }
|
||||
.form_field_prefix { display: block; overflow: hidden; }
|
||||
</style>
|
||||
@@ -0,0 +1,2 @@
|
||||
<label class="form_field_suffix">{{ suffix }}</label>
|
||||
<span class="form_field_prefix">{{ input }}</span>
|
||||
@@ -223,7 +223,7 @@ class UpdateRecordView(BaseRecordFormView):
|
||||
|
||||
initial.update({
|
||||
'id': self.record.id,
|
||||
'name': self.record.name,
|
||||
'name': self.record.name.replace("." + initial['domain_name'], ''),
|
||||
'data': self.record.data,
|
||||
'txt': self.record.data,
|
||||
'priority': self.record.priority,
|
||||
|
||||
@@ -86,13 +86,14 @@ DOMAIN_ID = '123'
|
||||
class BaseRecordFormCleanTests(test.TestCase):
|
||||
|
||||
DOMAIN_NAME = 'foo.com.'
|
||||
HOSTNAME = 'www.foo.com.'
|
||||
HOSTNAME = 'www'
|
||||
|
||||
MSG_FIELD_REQUIRED = 'This field is required'
|
||||
MSG_INVALID_HOSTNAME = 'Enter a valid hostname. The hostname should end '\
|
||||
'with a period.'
|
||||
MSG_INVALID_HOSTNAME = 'Enter a valid hostname. The '\
|
||||
'hostname should contain letters '\
|
||||
'and numbers, and be no more than '\
|
||||
'63 characters.'
|
||||
MSG_INVALID_HOSTNAME_SHORT = 'Enter a valid hostname'
|
||||
MSG_OUTSIDE_DOMAIN = 'Name must be in the current domain'
|
||||
|
||||
def setUp(self):
|
||||
super(BaseRecordFormCleanTests, self).setUp()
|
||||
@@ -101,7 +102,9 @@ class BaseRecordFormCleanTests(test.TestCase):
|
||||
self.request = self.factory.get('', {})
|
||||
|
||||
# Set-up form instance
|
||||
self.form = forms.RecordCreate(self.request)
|
||||
kwargs = {}
|
||||
kwargs['initial'] = {'domain_name': self.DOMAIN_NAME}
|
||||
self.form = forms.RecordCreate(self.request, **kwargs)
|
||||
self.form._errors = {}
|
||||
self.form.cleaned_data = {
|
||||
'domain_name': self.DOMAIN_NAME,
|
||||
@@ -139,7 +142,7 @@ class ARecordFormTests(BaseRecordFormCleanTests):
|
||||
self.assert_no_errors()
|
||||
|
||||
def test_valid_name_field_wild_card(self):
|
||||
self.form.cleaned_data['name'] = '*.' + self.DOMAIN_NAME
|
||||
self.form.cleaned_data['name'] = '*'
|
||||
self.form.clean()
|
||||
self.assert_no_errors()
|
||||
|
||||
@@ -154,17 +157,17 @@ class ARecordFormTests(BaseRecordFormCleanTests):
|
||||
self.assert_required_error('data')
|
||||
|
||||
def test_invalid_name_field(self):
|
||||
self.form.cleaned_data['name'] = 'foo'
|
||||
self.form.cleaned_data['name'] = '$#%foo!!'
|
||||
self.form.clean()
|
||||
self.assert_error('name', self.MSG_INVALID_HOSTNAME)
|
||||
|
||||
def test_invalid_name_field_starting_dash(self):
|
||||
self.form.cleaned_data['name'] = '-ww.foo.com'
|
||||
self.form.cleaned_data['name'] = '-ww'
|
||||
self.form.clean()
|
||||
self.assert_error('name', self.MSG_INVALID_HOSTNAME)
|
||||
|
||||
def test_invalid_name_field_trailing_dash(self):
|
||||
self.form.cleaned_data['name'] = 'www.foo.co-'
|
||||
self.form.cleaned_data['name'] = 'co-'
|
||||
self.form.clean()
|
||||
self.assert_error('name', self.MSG_INVALID_HOSTNAME)
|
||||
|
||||
@@ -176,7 +179,7 @@ class ARecordFormTests(BaseRecordFormCleanTests):
|
||||
def test_outside_of_domain_name_field(self):
|
||||
self.form.cleaned_data['name'] = 'www.bar.com.'
|
||||
self.form.clean()
|
||||
self.assert_error('name', self.MSG_OUTSIDE_DOMAIN)
|
||||
self.assert_error('name', self.MSG_INVALID_HOSTNAME)
|
||||
|
||||
def test_invalid_data_field(self):
|
||||
self.form.cleaned_data['data'] = 'foo'
|
||||
@@ -201,7 +204,7 @@ class AAAARecordFormTests(BaseRecordFormCleanTests):
|
||||
self.assert_no_errors()
|
||||
|
||||
def test_valid_name_field_wild_card(self):
|
||||
self.form.cleaned_data['name'] = '*.' + self.DOMAIN_NAME
|
||||
self.form.cleaned_data['name'] = '*'
|
||||
self.form.clean()
|
||||
self.assert_no_errors()
|
||||
|
||||
@@ -216,7 +219,7 @@ class AAAARecordFormTests(BaseRecordFormCleanTests):
|
||||
self.assert_required_error('data')
|
||||
|
||||
def test_invalid_name_field(self):
|
||||
self.form.cleaned_data['name'] = 'foo'
|
||||
self.form.cleaned_data['name'] = '#@$foo!!'
|
||||
self.form.clean()
|
||||
self.assert_error('name', self.MSG_INVALID_HOSTNAME)
|
||||
|
||||
@@ -238,7 +241,7 @@ class AAAARecordFormTests(BaseRecordFormCleanTests):
|
||||
def test_outside_of_domain_name_field(self):
|
||||
self.form.cleaned_data['name'] = 'www.bar.com.'
|
||||
self.form.clean()
|
||||
self.assert_error('name', self.MSG_OUTSIDE_DOMAIN)
|
||||
self.assert_error('name', self.MSG_INVALID_HOSTNAME)
|
||||
|
||||
def test_invalid_data_field(self):
|
||||
self.form.cleaned_data['data'] = 'foo'
|
||||
@@ -261,7 +264,7 @@ class CNAMERecordFormTests(BaseRecordFormCleanTests):
|
||||
self.assert_no_errors()
|
||||
|
||||
def test_valid_name_field_wild_card(self):
|
||||
self.form.cleaned_data['name'] = '*.' + self.DOMAIN_NAME
|
||||
self.form.cleaned_data['name'] = '*'
|
||||
self.form.clean()
|
||||
self.assert_no_errors()
|
||||
|
||||
@@ -276,7 +279,7 @@ class CNAMERecordFormTests(BaseRecordFormCleanTests):
|
||||
self.assert_required_error('data')
|
||||
|
||||
def test_invalid_name_field(self):
|
||||
self.form.cleaned_data['name'] = 'foo'
|
||||
self.form.cleaned_data['name'] = '$#%#$foo!!!'
|
||||
self.form.clean()
|
||||
self.assert_error('name', self.MSG_INVALID_HOSTNAME)
|
||||
|
||||
@@ -298,7 +301,7 @@ class CNAMERecordFormTests(BaseRecordFormCleanTests):
|
||||
def test_outside_of_domain_name_field(self):
|
||||
self.form.cleaned_data['name'] = 'www.bar.com.'
|
||||
self.form.clean()
|
||||
self.assert_error('name', self.MSG_OUTSIDE_DOMAIN)
|
||||
self.assert_error('name', self.MSG_INVALID_HOSTNAME)
|
||||
|
||||
def test_invalid_data_field(self):
|
||||
self.form.cleaned_data['data'] = 'foo'
|
||||
@@ -356,7 +359,7 @@ class TXTRecordFormTests(BaseRecordFormCleanTests):
|
||||
self.assert_no_errors()
|
||||
|
||||
def test_valid_name_field_wild_card(self):
|
||||
self.form.cleaned_data['name'] = '*.' + self.DOMAIN_NAME
|
||||
self.form.cleaned_data['name'] = '*'
|
||||
self.form.clean()
|
||||
self.assert_no_errors()
|
||||
|
||||
@@ -371,7 +374,7 @@ class TXTRecordFormTests(BaseRecordFormCleanTests):
|
||||
self.assert_required_error('txt')
|
||||
|
||||
def test_invalid_name_field(self):
|
||||
self.form.cleaned_data['name'] = 'foo'
|
||||
self.form.cleaned_data['name'] = 'foo-'
|
||||
self.form.clean()
|
||||
self.assert_error('name', self.MSG_INVALID_HOSTNAME)
|
||||
|
||||
@@ -386,14 +389,14 @@ class TXTRecordFormTests(BaseRecordFormCleanTests):
|
||||
self.assert_error('name', self.MSG_INVALID_HOSTNAME)
|
||||
|
||||
def test_invalid_name_field_bad_wild_card(self):
|
||||
self.form.cleaned_data['name'] = 'derp.*.' + self.DOMAIN_NAME
|
||||
self.form.cleaned_data['name'] = 'derp.*'
|
||||
self.form.clean()
|
||||
self.assert_error('name', self.MSG_INVALID_HOSTNAME)
|
||||
|
||||
def test_outside_of_domain_name_field(self):
|
||||
self.form.cleaned_data['name'] = 'www.bar.com.'
|
||||
self.form.clean()
|
||||
self.assert_error('name', self.MSG_OUTSIDE_DOMAIN)
|
||||
self.assert_error('name', self.MSG_INVALID_HOSTNAME)
|
||||
|
||||
def test_default_assignment_data_field(self):
|
||||
self.form.clean()
|
||||
|
||||
Reference in New Issue
Block a user