Skip to content

Commit

Permalink
Merge pull request #22971 from dimagi/jls/domain-select2-v4
Browse files Browse the repository at this point in the history
Upgrade select2 on domain app pages that use requirejs
  • Loading branch information
orangejenny committed Jan 16, 2019
2 parents b339baf + c31c40d commit a121c7c
Show file tree
Hide file tree
Showing 30 changed files with 325 additions and 73 deletions.
36 changes: 18 additions & 18 deletions corehq/apps/accounting/forms.py
Expand Up @@ -91,6 +91,7 @@ class BillingAccountBasicForm(forms.Form):

email_list = forms.CharField(
label=ugettext_lazy('Client Contact Emails'),
widget=forms.SelectMultiple(choices=[]),
)
is_active = forms.BooleanField(
label=ugettext_lazy("Account is Active"),
Expand Down Expand Up @@ -150,10 +151,10 @@ def __init__(self, account, *args, **kwargs):
'name': account.name,
'salesforce_account_id': account.salesforce_account_id,
'currency': account.currency.code,
'email_list': ','.join(contact_info.email_list),
'email_list': contact_info.email_list,
'is_active': account.is_active,
'is_customer_billing_account': account.is_customer_billing_account,
'enterprise_admin_emails': ','.join(account.enterprise_admin_emails),
'enterprise_admin_emails': account.enterprise_admin_emails,
'enterprise_restricted_signup_domains': ','.join(account.enterprise_restricted_signup_domains),
'invoicing_plan': account.invoicing_plan,
'dimagi_contact': account.dimagi_contact,
Expand Down Expand Up @@ -200,9 +201,11 @@ def __init__(self, account, *args, **kwargs):
'invoicing_plan',
crispy.Field(
'enterprise_admin_emails',
css_class='input-xxlarge accounting-email-select2'
css_class='input-xxlarge accounting-email-select2',
data_initial=json.dumps(self.initial.get('enterprise_admin_emails')),
),
data_bind='visible: is_customer_billing_account'
data_bind='visible: is_customer_billing_account',
data_initial=json.dumps(self.initial.get('enterprise_admin_emails')),
)
)
additional_fields.append(
Expand All @@ -227,13 +230,14 @@ def __init__(self, account, *args, **kwargs):
crispy.Fieldset(
'Basic Information',
'name',
crispy.Field('email_list', css_class='input-xxlarge accounting-email-select2'),
crispy.Field('email_list', css_class='input-xxlarge accounting-email-select2',
data_initial=json.dumps(self.initial.get('email_list'))),
crispy.Div(
crispy.Div(
css_class='col-sm-3 col-md-2'
),
crispy.Div(
crispy.HTML(self.initial['email_list']),
crispy.HTML(", ".join(self.initial.get('email_list'))),
css_class='col-sm-9 col-md-8 col-lg-6'
),
css_id='emails-text',
Expand Down Expand Up @@ -285,14 +289,10 @@ def clean_name(self):
return name

def clean_email_list(self):
return self.cleaned_data['email_list'].split(',')
return self.data.getlist('email_list')

def clean_enterprise_admin_emails(self):
# Do not return a list with an empty string
if self.cleaned_data['enterprise_admin_emails']:
return [e.strip() for e in self.cleaned_data['enterprise_admin_emails'].split(r',')]
else:
return []
return self.data.getlist('enterprise_admin_emails')

def clean_enterprise_restricted_signup_domains(self):
if self.cleaned_data['enterprise_restricted_signup_domains']:
Expand Down Expand Up @@ -405,6 +405,7 @@ class Meta(object):
'postal_code',
'country',
]
widgets = {'country': forms.Select(choices=[])}

def __init__(self, account, *args, **kwargs):
contact_info, _ = BillingContactInfo.objects.get_or_create(
Expand All @@ -416,6 +417,7 @@ def __init__(self, account, *args, **kwargs):
self.helper.form_class = "form-horizontal"
self.helper.label_class = 'col-sm-3 col-md-2'
self.helper.field_class = 'col-sm-9 col-md-8 col-lg-6'
country_code = args[0].get('country') if len(args) > 0 else account.billingcontactinfo.country
self.helper.layout = crispy.Layout(
crispy.Fieldset(
'Contact Information',
Expand All @@ -431,11 +433,8 @@ def __init__(self, account, *args, **kwargs):
crispy.Field(
'country',
css_class="input-xlarge accounting-country-select2",
data_countryname=COUNTRIES.get(
args[0].get('country') if len(args) > 0
else account.billingcontactinfo.country,
''
)
data_country_code=country_code or '',
data_country_name=COUNTRIES.get(country_code, ''),
),
),
hqcrispy.FormActions(
Expand Down Expand Up @@ -2055,7 +2054,8 @@ def __init__(self, *args, **kwargs):
self.helper.layout = crispy.Layout(
crispy.Fieldset(
'Trigger Bookkeeper Email Details',
crispy.Field('emails', css_class='input-xxlarge accounting-email-select2'),
crispy.Field('emails', css_class='input-xxlarge accounting-email-select2',
data_initial=json.dumps(self.initial.get('emails'))),
crispy.Field('month', css_class="input-large"),
crispy.Field('year', css_class="input-large"),
),
Expand Down
@@ -1,7 +1,7 @@
hqDefine('accounting/js/base_subscriptions_main', [
'jquery',
'knockout',
'accounting/js/widgets',
'accounting/js/widgets_v3',
'accounting/js/credits_tab',
'jquery-ui/ui/datepicker',
], function (
Expand Down
Expand Up @@ -3,7 +3,7 @@ hqDefine('accounting/js/billing_account_form', [
'knockout',
'hqwebapp/js/initial_page_data',
'accounting/js/credits_tab',
'accounting/js/widgets',
'accounting/js/widgets_v4',
], function (
$,
ko,
Expand Down
@@ -1,5 +1,5 @@
hqDefine("accounting/js/invoice_main", [
'accounting/js/widgets',
'accounting/js/widgets_v3',
], function () {
// This page doesn't have any page-specific logic, it just depends on the modules above
});
@@ -1,7 +1,7 @@
hqDefine('accounting/js/subscriptions_main', [
'jquery',
'hqwebapp/js/initial_page_data',
'accounting/js/widgets',
'accounting/js/widgets_v3',
'accounting/js/base_subscriptions_main',
], function (
$,
Expand Down
@@ -1,4 +1,4 @@
hqDefine('accounting/js/widgets', [
hqDefine('accounting/js/widgets_v3', [
'jquery',
'knockout',
'underscore',
Expand Down
172 changes: 172 additions & 0 deletions corehq/apps/accounting/static/accounting/js/widgets_v4.js
@@ -0,0 +1,172 @@
hqDefine('accounting/js/widgets_v4', [
'jquery',
'knockout',
'underscore',
'select2/dist/js/select2.full.min',
], function (
$,
ko,
_
) {
var asyncSelect2Handler = function (field, multiple) {
'use strict';
var self = {};

self.fieldName = field;
self.multiple = !! multiple;

self.init = function (initial) {
var $field = $('form [name="' + self.fieldName + '"]');
if ($field.attr('type') !== 'hidden') {
if (initial) {
if (!_.isArray(initial)) {
initial = [{id: initial, text: initial}];
}

// Add a DOM option for each value, which select2 will pick up on change
_.each(initial, function (result) {
$field.append(new Option(result.text, result.id));
});

// Set the actual value; using an array works for both single and multiple selects
$field.val(_.pluck(initial, 'id'));
}
$field.select2({
minimumInputLength: 0,
placeholder: '', // required for allowClear to work
allowClear: true,
ajax: {
quietMillis: 150,
url: '',
dataType: 'json',
type: 'post',
data: function (params) {
return {
handler: 'select2_billing',
action: self.fieldName,
searchString: params.term,
existing: $('form [name="' + self.fieldName + '"]').val(),
additionalData: self.getAdditionalData(),
};
},
},
multiple: self.multiple,
});
}
};

self.getAdditionalData = function () {
return null;
};

return self;
};

var emailSelect2Handler = function (field) {
'use strict';
var self = {};

self.fieldName = field;
self.validEmailText = gettext("Please enter a valid email.");

self.init = function (initial) {
var $field = $('form [name="' + self.fieldName + '"]');
if (initial) {
if (!_.isArray(initial)) {
initial = [{id: initial, text: initial}];
}

// Add a DOM option for each value, which select2 will pick up on change
_.each(initial, function (result) {
$field.append(new Option(result.text, result.id));
});

// Set the actual value; using an array works for both single and multiple selects
$field.val(_.pluck(initial, 'id'));
}
$field.select2({
tags: true,
createTag: function (params) {
var term = params.term,
data = this.$element.select2("data");

// Prevent duplicates
var matchedData = $(data).filter(function () {
return this.text.localeCompare(term) === 0;
});

if (matchedData.length === 0 && self.utils.validateEmail(term)) {
return { id: term, text: term };
}
},
multiple: true,
data: [],
language: {
noResults: function () {
return self.validEmailText;
},
},
});
};

self.utils = {
validateEmail: function (email) {
// from http://stackoverflow.com/questions/46155/validate-email-address-in-javascript
var re = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; // eslint-disable-line no-useless-escape
return re.test(email);
},
};

return self;
};

var adjustBalanceFormModel = function () {
var self = {};
self.adjustmentType = ko.observable("current");
self.showCustomAmount = ko.computed(function () {
return self.adjustmentType() === 'credit';
}, self);

return self;
};

$(function () {
_.each($(".accounting-email-select2"), function (input) {
var handler = emailSelect2Handler($(input).attr("name"));
handler.init(_.map($(input).data("initial"), function (e) {
return {
id: e,
text: e,
};
}));
});
$(".accounting-email-select2").removeAttr('required');

_.each($(".accounting-async-select2"), function (input) {
var handler = asyncSelect2Handler($(input).attr("name"));
handler.init();
});

_.each($(".accounting-country-select2"), function (el) {
var country = asyncSelect2Handler('country'),
data = $(el).data(),
initial = [];
if (data.countryCode) {
initial = [{
id: data.countryCode,
text: data.countryName,
}];
}
country.init(initial);
});

_.each($('.ko-adjust-balance-form'), function (form) {
$(form).koApplyBindings(adjustBalanceFormModel());
});
});

return {
asyncSelect2Handler: asyncSelect2Handler,
emailSelect2Handler: emailSelect2Handler,
};
});
Expand Up @@ -3,7 +3,7 @@
{% load hq_shared_tags %}
{% load i18n %}

{% requirejs_main 'accounting/js/widgets' %}
{% requirejs_main 'accounting/js/widgets_v3' %}

{% block page_content %}
{% crispy basic_form %}
Expand Down
Expand Up @@ -2,7 +2,7 @@
{% load hq_shared_tags %}

{% block js %}{{ block.super }}
<script src="{% static 'accounting/js/widgets.js' %}"></script>
<script src="{% static 'accounting/js/widgets_v3.js' %}"></script>
{% endblock %}

{% block page_content %}
Expand Down
Expand Up @@ -2,7 +2,7 @@
{% load crispy_forms_tags %}
{% load hq_shared_tags %}

{% requirejs_main "accounting/js/widgets" %}
{% requirejs_main "accounting/js/widgets_v3" %}

{% block page_content %}
{% crispy trigger_email_form %}
Expand Down
Expand Up @@ -2,8 +2,8 @@
{% load crispy_forms_tags %}
{% load hq_shared_tags %}

{% requirejs_main "accounting/js/widgets" %}
{% requirejs_main "accounting/js/widgets_v3" %}

{% block page_content %}
{% crispy trigger_customer_form %}
{% endblock %}
{% endblock %}
Expand Up @@ -2,7 +2,7 @@
{% load crispy_forms_tags %}
{% load hq_shared_tags %}

{% requirejs_main "accounting/js/widgets" %}
{% requirejs_main "accounting/js/widgets_v3" %}

{% block page_content %}
{% crispy trigger_form %}
Expand Down

0 comments on commit a121c7c

Please sign in to comment.