diff --git a/application/Espo/Core/defaults/config.php b/application/Espo/Core/defaults/config.php index 4d8e0353c2..cf302e1177 100644 --- a/application/Espo/Core/defaults/config.php +++ b/application/Espo/Core/defaults/config.php @@ -87,7 +87,7 @@ return array ( 'Lead', 'Opportunity', ), - "tabList" => array("Account", "Contact", "Lead", "Opportunity", "Calendar", "Meeting", "Call", "Task", "Case", "Email", "Campaign"), + "tabList" => array("Account", "Contact", "Lead", "Opportunity", "Calendar", "Meeting", "Call", "Task", "Case", "Email", "Document", "Campaign"), "quickCreateList" => array("Account", "Contact", "Lead", "Opportunity", "Meeting", "Call", "Task", "Case"), 'calendarDefaultEntity' => 'Meeting', 'disableExport' => false, diff --git a/application/Espo/Modules/Crm/Resources/metadata/entityDefs/Call.json b/application/Espo/Modules/Crm/Resources/metadata/entityDefs/Call.json index 179634ac1a..0a265e749e 100644 --- a/application/Espo/Modules/Crm/Resources/metadata/entityDefs/Call.json +++ b/application/Espo/Modules/Crm/Resources/metadata/entityDefs/Call.json @@ -140,8 +140,7 @@ "len": "36", "default": "None" } - }, - "layoutRelationshipsDisabled": true + } }, "contacts": { "type": "hasMany", @@ -153,8 +152,7 @@ "len": "36", "default": "None" } - }, - "layoutRelationshipsDisabled": true + } }, "leads": { "type": "hasMany", @@ -166,8 +164,7 @@ "len": "36", "default": "None" } - }, - "layoutRelationshipsDisabled": true + } }, "parent": { "type": "belongsToParent", diff --git a/application/Espo/Modules/Crm/Resources/metadata/entityDefs/Meeting.json b/application/Espo/Modules/Crm/Resources/metadata/entityDefs/Meeting.json index b2d4ad19aa..02c68c1132 100644 --- a/application/Espo/Modules/Crm/Resources/metadata/entityDefs/Meeting.json +++ b/application/Espo/Modules/Crm/Resources/metadata/entityDefs/Meeting.json @@ -135,8 +135,7 @@ "len": "36", "default": "None" } - }, - "layoutRelationshipsDisabled": true + } }, "contacts": { "type": "hasMany", @@ -148,8 +147,7 @@ "len": "36", "default": "None" } - }, - "layoutRelationshipsDisabled": true + } }, "leads": { "type": "hasMany", @@ -161,8 +159,7 @@ "len": "36", "default": "None" } - }, - "layoutRelationshipsDisabled": true + } }, "parent": { "type": "belongsToParent", diff --git a/application/Espo/Services/Email.php b/application/Espo/Services/Email.php index 229abe6172..e78a3069f6 100644 --- a/application/Espo/Services/Email.php +++ b/application/Espo/Services/Email.php @@ -26,6 +26,7 @@ use \Espo\ORM\Entity; use \Espo\Entities; use \Espo\Core\Exceptions\Error; +use \Espo\Core\Exceptions\Forbidden; class Email extends Record { @@ -133,7 +134,22 @@ class Email extends Record public function getEntity($id = null) { - $entity = parent::getEntity($id); + + $entity = $this->getRepository()->get($id); + if (!empty($entity) && !empty($id)) { + $this->loadAdditionalFields($entity); + + if (!$this->getAcl()->check($entity, 'read')) { + $userIdList = $entity->get('usersIds'); + if (!is_array($userIdList) || !in_array($this->getUser()->id, $userIdList)) { + throw new Forbidden(); + } + } + } + if (!empty($entity)) { + $this->prepareEntityForOutput($entity); + } + if (!empty($entity) && !empty($id)) { if ($entity->get('fromEmailAddressName')) { diff --git a/application/Espo/Services/User.php b/application/Espo/Services/User.php index 9bd404662f..d3d5d97ad1 100644 --- a/application/Espo/Services/User.php +++ b/application/Espo/Services/User.php @@ -271,7 +271,7 @@ class User extends Record $body = $this->getLanguage()->translate('passwordChangeLinkEmailBody', 'messages', 'User'); $link = $this->getConfig()->get('siteUrl') . '?entryPoint=changePassword&id=' . $requestId; - + $body = str_replace('{link}', $link, $body); $email->set(array( @@ -289,6 +289,9 @@ class User extends Record if ($id == 'system') { throw new Forbidden(); } + if ($id == $this->getUser()->id) { + throw new Forbidden(); + } return parent::deleteEntity($id); } } diff --git a/frontend/client/modules/crm/src/views/call/list.js b/frontend/client/modules/crm/src/views/call/list.js index 9d2c039feb..c26346a578 100644 --- a/frontend/client/modules/crm/src/views/call/list.js +++ b/frontend/client/modules/crm/src/views/call/list.js @@ -17,56 +17,55 @@ * * You should have received a copy of the GNU General Public License * along with EspoCRM. If not, see http://www.gnu.org/licenses/. - ************************************************************************/ - + ************************************************************************/ + Espo.define('Crm:Views.Call.List', 'Views.List', function (Dep) { return Dep.extend({ - + actionSetHeld: function (data) { var id = data.id; if (!id) { return; - } + } var model = this.collection.get(id); if (!model) { return; } - + model.set('status', 'Held'); - + this.listenToOnce(model, 'sync', function () { this.notify(false); this.collection.fetch(); }, this); - + this.notify('Saving...'); - model.save(); - + model.save(); + }, - + actionSetNotHeld: function (data) { var id = data.id; if (!id) { return; - } + } var model = this.collection.get(id); if (!model) { return; } - + model.set('status', 'Not Held'); - + this.listenToOnce(model, 'sync', function () { this.notify(false); this.collection.fetch(); }, this); - + this.notify('Saving...'); - model.save(); - + model.save(); }, - + }); - + }); diff --git a/frontend/client/res/templates/stream/notes/email-received.tpl b/frontend/client/res/templates/stream/notes/email-received.tpl index 535ee3e902..a89c55f4bf 100644 --- a/frontend/client/res/templates/stream/notes/email-received.tpl +++ b/frontend/client/res/templates/stream/notes/email-received.tpl @@ -13,7 +13,7 @@ {{{avatar}}}
- + {{{message}}}
diff --git a/frontend/client/src/views/email/record/detail.js b/frontend/client/src/views/email/record/detail.js index d98f4552c0..f2e5110f29 100644 --- a/frontend/client/src/views/email/record/detail.js +++ b/frontend/client/src/views/email/record/detail.js @@ -47,9 +47,6 @@ Espo.define('Views.Email.Record.Detail', 'Views.Record.Detail', function (Dep) { setup: function () { Dep.prototype.setup.call(this); - this.listenTo(this.model, 'change:attachmentsIds', function () { - this.handleAttachmentField(); - }, this); }, handleAttachmentField: function () { @@ -64,8 +61,9 @@ Espo.define('Views.Email.Record.Detail', 'Views.Record.Detail', function (Dep) { Dep.prototype.afterRender.call(this); this.handleAttachmentField(); - - + this.listenTo(this.model, 'change:attachmentsIds', function () { + this.handleAttachmentField(); + }, this); }, }); diff --git a/frontend/client/src/views/record/list.js b/frontend/client/src/views/record/list.js index a1c2a84e47..f69bfdf96d 100644 --- a/frontend/client/src/views/record/list.js +++ b/frontend/client/src/views/record/list.js @@ -132,18 +132,15 @@ Espo.define('Views.Record.List', 'View', function (Dep) { this.$el.find('.list > table tbody tr').removeClass('active'); } }, - 'click [data-action="quickEdit"]': function (e) { - var $target = $(e.currentTarget); - var id = $target.data('id'); - var data = $target.data(); - this.quickEdit(id, data); - - }, - 'click [data-action="quickRemove"]': function (e) { - var $target = $(e.currentTarget); - var id = $target.data('id'); - var data = $target.data(); - this.quickRemove(id, data); + 'click .action': function (e) { + $el = $(e.currentTarget); + var action = $el.data('action'); + var method = 'action' + Espo.Utils.upperCaseFirst(action); + if (typeof this[method] == 'function') { + var data = $el.data(); + this[method](data); + e.stopPropagation(); + } }, 'click .checkbox-dropdown [data-action="selectAllResult"]': function (e) { this.selectAllResult(); @@ -785,8 +782,11 @@ Espo.define('Views.Record.List', 'View', function (Dep) { }); }, - quickEdit: function (id, d) { + actionQuickEdit: function (d) { d = d || {} + var id = d.id; + if (!id) return; + if (this.allowQuickEdit) { this.notify('Loading...'); this.createView('quickEdit', 'Modals.Edit', { @@ -811,7 +811,11 @@ Espo.define('Views.Record.List', 'View', function (Dep) { return 'tr[data-id="' + id + '"]'; }, - quickRemove: function (id) { + actionQuickRemove: function (data) { + data = data || {} + var id = data.id; + if (!id) return; + var model = this.collection.get(id); if (!this.getAcl().checkModel(model, 'delete')) { this.notify('Access denied', 'error'); diff --git a/frontend/client/src/views/record/panels/bottom.js b/frontend/client/src/views/record/panels/bottom.js index 1d41fff38a..5d6b37ed9f 100644 --- a/frontend/client/src/views/record/panels/bottom.js +++ b/frontend/client/src/views/record/panels/bottom.js @@ -33,7 +33,9 @@ Espo.define('Views.Record.Panels.Bottom', 'View', function (Dep) { var action = $el.data('action'); var method = 'action' + Espo.Utils.upperCaseFirst(action); if (typeof this[method] == 'function') { - this[method]($el.data('id')); + var data = $el.data(); + this[method](data); + e.stopPropagation(); } } }, @@ -58,6 +60,22 @@ Espo.define('Views.Record.Panels.Bottom', 'View', function (Dep) { return []; }, + actionViewRecord: function (data) { + var id = data.id; + var scope = data.scope; + + this.notify('Loading...'); + this.createView('quickDetail', 'Modals.Detail', { + scope: scope, + id: id + }, function (view) { + view.once('after:render', function () { + Espo.Ui.notify(false); + }); + view.render(); + }.bind(this)); + } + }); }); diff --git a/frontend/client/src/views/record/panels/default-side.js b/frontend/client/src/views/record/panels/default-side.js index c795e47f1f..fb97c69f24 100644 --- a/frontend/client/src/views/record/panels/default-side.js +++ b/frontend/client/src/views/record/panels/default-side.js @@ -17,7 +17,7 @@ * * You should have received a copy of the GNU General Public License * along with EspoCRM. If not, see http://www.gnu.org/licenses/. - ************************************************************************/ + ************************************************************************/ Espo.define('Views.Record.Panels.DefaultSide', 'Views.Record.Panels.Side', function (Dep) { diff --git a/frontend/client/src/views/record/panels/relationship.js b/frontend/client/src/views/record/panels/relationship.js index 84bbcc45ce..afcb16e0d5 100644 --- a/frontend/client/src/views/record/panels/relationship.js +++ b/frontend/client/src/views/record/panels/relationship.js @@ -138,7 +138,9 @@ Espo.define('Views.Record.Panels.Relationship', ['Views.Record.Panels.Bottom', ' this.collection.fetch(); }, - actionViewRelated: function (id) { + actionViewRelated: function (data) { + var id = data.id; + this.notify('Loading...'); this.createView('quickDetail', 'Modals.Detail', { scope: this.collection.get(id).name, @@ -154,7 +156,9 @@ Espo.define('Views.Record.Panels.Relationship', ['Views.Record.Panels.Bottom', ' }.bind(this)); }, - actionEditRelated: function (id) { + actionEditRelated: function (data) { + var id = data.id; + this.notify('Loading...'); this.createView('quickEdit', 'Modals.Edit', { scope: this.collection.get(id).name, @@ -170,7 +174,9 @@ Espo.define('Views.Record.Panels.Relationship', ['Views.Record.Panels.Bottom', ' }.bind(this)); }, - actionUnlinkRelated: function (id) { + actionUnlinkRelated: function (data) { + var id = data.id; + var self = this; if (confirm(this.translate('unlinkRecordConfirmation', 'messages'))) { var model = this.collection.get(id); @@ -193,7 +199,9 @@ Espo.define('Views.Record.Panels.Relationship', ['Views.Record.Panels.Bottom', ' } }, - actionRemoveRelated: function (id) { + actionRemoveRelated: function (data) { + var id = data.id; + var self = this; if (confirm(this.translate('removeRecordConfirmation', 'messages'))) { var model = this.collection.get(id); diff --git a/frontend/client/src/views/stream/list.js b/frontend/client/src/views/stream/list.js index f1dcf46f96..e8ed50cabe 100644 --- a/frontend/client/src/views/stream/list.js +++ b/frontend/client/src/views/stream/list.js @@ -107,6 +107,22 @@ Espo.define('Views.Stream.List', 'Views.Record.ListExpanded', function (Dep) { }); }, + actionViewRecord: function (data) { + var id = data.id; + var scope = data.scope; + + this.notify('Loading...'); + this.createView('quickDetail', 'Modals.Detail', { + scope: scope, + id: id + }, function (view) { + view.once('after:render', function () { + Espo.Ui.notify(false); + }); + view.render(); + }.bind(this)); + } + }); }); diff --git a/frontend/client/src/views/stream/notes/email-received.js b/frontend/client/src/views/stream/notes/email-received.js index db31e450d3..ce536a326b 100644 --- a/frontend/client/src/views/stream/notes/email-received.js +++ b/frontend/client/src/views/stream/notes/email-received.js @@ -27,9 +27,17 @@ Espo.define('Views.Stream.Notes.EmailReceived', 'Views.Stream.Note', function (D isRemovable: true, + data: function () { + return _.extend({ + emailId: this.emailId + }, Dep.prototype.data.call(this)); + }, + setup: function () { var data = this.model.get('data') || {}; + this.emailId = data.emailId; + if (this.model.get('post')) { this.createField('post', null, null, 'Stream.Fields.Post'); } diff --git a/frontend/client/src/views/stream/notes/email-sent.js b/frontend/client/src/views/stream/notes/email-sent.js index 3112dd12c6..0ef7f11b44 100644 --- a/frontend/client/src/views/stream/notes/email-sent.js +++ b/frontend/client/src/views/stream/notes/email-sent.js @@ -27,9 +27,17 @@ Espo.define('Views.Stream.Notes.EmailSent', 'Views.Stream.Note', function (Dep) isRemovable: true, + data: function () { + return _.extend({ + emailId: this.emailId + }, Dep.prototype.data.call(this)); + }, + setup: function () { var data = this.model.get('data') || {}; + this.emailId = data.emailId; + if (this.model.get('post')) { this.createField('post', null, null, 'Stream.Fields.Post'); }