diff --git a/application/Espo/Resources/i18n/en_US/EmailAddress.json b/application/Espo/Resources/i18n/en_US/EmailAddress.json new file mode 100644 index 0000000000..2f9d2aa22c --- /dev/null +++ b/application/Espo/Resources/i18n/en_US/EmailAddress.json @@ -0,0 +1,7 @@ +{ + "labels": { + "Primary": "Primary", + "Opted Out": "Opted Out", + "Invalid": "Invalid" + } +} diff --git a/application/Espo/Resources/metadata/fields/email.json b/application/Espo/Resources/metadata/fields/email.json index 3c26ae96b7..f17ea8f40b 100644 --- a/application/Espo/Resources/metadata/fields/email.json +++ b/application/Espo/Resources/metadata/fields/email.json @@ -4,10 +4,6 @@ "name":"required", "type":"bool", "default":false - }, - { - "name":"maxLength", - "type":"int" } ], "notCreatable": true, diff --git a/frontend/client/res/templates/fields/email/edit.tpl b/frontend/client/res/templates/fields/email/edit.tpl index 5493852128..f3dfe50f7e 100644 --- a/frontend/client/res/templates/fields/email/edit.tpl +++ b/frontend/client/res/templates/fields/email/edit.tpl @@ -1,4 +1,20 @@ - +{{#each emailAddressData}} +
+ + + + + + +
+{{/each}} + diff --git a/frontend/client/src/views/fields/email.js b/frontend/client/src/views/fields/email.js index dc87165482..3f5476208e 100644 --- a/frontend/client/src/views/fields/email.js +++ b/frontend/client/src/views/fields/email.js @@ -31,10 +31,10 @@ Espo.define('Views.Fields.Email', 'Views.Fields.Base', function (Dep) { listTemplate: 'fields.email.detail', - validations: ['required', 'email'], + validations: ['required', 'emailData'], validateEmail: function () { - if (this.model.get(this.name)) { + if (this.model.get(this.name)) { var re = /\S+@+\S+/; if (!re.test(this.model.get(this.name))) { var msg = this.translate('fieldShouldBeEmail', 'messages').replace('{field}', this.translate(this.name, 'fields', this.model.name)); @@ -44,10 +44,97 @@ Espo.define('Views.Fields.Email', 'Views.Fields.Base', function (Dep) { } }, + validateEmailData: function () { + var data = this.model.get(this.dataFieldName); + if (data && data.length) { + var re = /\S+@+\S+/; + var notValid = false; + data.forEach(function (row, i) { + var emailAddress = row.emailAddress; + if (!re.test(emailAddress)) { + var msg = this.translate('fieldShouldBeEmail', 'messages').replace('{field}', this.translate(this.name, 'fields', this.model.name)); + this.showValidationMessage(msg, 'div.email-address-block:nth-child(' + (i + 1).toString() + ') input'); + notValid = true; + } + }, this); + if (notValid) { + return true; + } + } + }, + + validateRequired: function () { + if (this.params.required || this.model.isRequired(this.name)) { + if (this.model.get(this.name) === '') { + var msg = this.translate('fieldIsRequired', 'messages').replace('{field}', this.translate(this.name, 'fields', this.model.name)); + this.showValidationMessage(msg, 'button[data-action="addEmailAddress"]'); + return true; + } + } + }, + + data: function () { + return _.extend({ + emailAddressData: this.model.get(this.name + 'Data') || [], + }, Dep.prototype.data.call(this)); + }, + events: { 'click [data-action="mailTo"]': function (e) { this.mailTo($(e.currentTarget).data('email-address')); }, + 'click [data-action="switchEmailProperty"]': function (e) { + var $target = $(e.currentTarget); + var property = $target.data('property-type'); + + if (property == 'primary') { + if (!$target.hasClass('active')) { + this.$el.find('button.email-property[data-property-type="primary"]').removeClass('active').children().addClass('text-muted'); + $target.addClass('active').children().removeClass('text-muted'); + } + + } else { + if ($target.hasClass('active')) { + $target.removeClass('active').children().addClass('text-muted'); + } else { + $target.addClass('active').children().removeClass('text-muted'); + } + } + this.fetchEmailAddressData(); + }, + 'change input.email-address': function (e) { + var $input = $(e.currentTarget); + if ($input.val() == '') { + var $block = $input.closest('div.email-address-block'); + + changePrimary = false; + if ($block.find('button[data-property-type="primary"]').hasClass('active')) { + changePrimary = true; + } + $block.remove(); + + if (changePrimary) { + this.$el.find('button[data-property-type="primary"]').first().addClass('active'); + } + } + + this.fetchEmailAddressData(); + }, + 'click [data-action="addEmailAddress"]': function () { + var data = this.model.get(this.dataFieldName) || []; + + o = { + emailAddress: '', + primary: data.length ? false : true, + optOut: false, + invalid: false + }; + + data.push(o); + + this.model.set(data, {silent: true}); + this.render(); + }, }, mailTo: function (emailAddress) { @@ -63,9 +150,60 @@ Espo.define('Views.Fields.Email', 'Views.Fields.Base', function (Dep) { }); }, + setup: function () { + this.dataFieldName = this.name + 'Data'; + }, + + afterRender: function () { + Dep.prototype.afterRender.call(this); + + if (this.mode == 'edit') { + + } + }, + + fetchEmailAddressData: function (dontUpdate) { + var data = []; + + var $list = this.$el.find('div.email-address-block'); + + if ($list.size()) { + $list.each(function (i, d) { + var row = {}; + var $d = $(d); + row.emailAddress = $d.find('input.email-address').val(); + if (row.emailAddress == '') { + return; + } + row.primary = $d.find('button[data-property-type="primary"]').hasClass('active'); + row.optOut = $d.find('button[data-property-type="optOut"]').hasClass('active'); + row.invalid = $d.find('button[data-property-type="invalid"]').hasClass('active'); + data.push(row); + }.bind(this)); + } + + var o = {}; + o[this.dataFieldName] = data; + + if (dontUpdate) { + this.model.set(o, {silent: true}); + } + + console.log(data); + + return data; + }, + fetch: function () { - var data = {}; - data[this.name] = this.$element.val() || null; + var data = {}; + + var adderssData = this.fetchEmailAddressData(true); + data[this.dataFieldName] = adderssData; + data[this.name] = null; + if (adderssData.length) { + data[this.name] = adderssData[0].emailAddress; + } + return data; },