email improvements
This commit is contained in:
@@ -18,7 +18,7 @@
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
|
||||
************************************************************************/
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Controllers;
|
||||
|
||||
@@ -29,18 +29,18 @@ use \Espo\Core\Exceptions\Error;
|
||||
class Email extends \Espo\Core\Controllers\Record
|
||||
{
|
||||
public function actionGetCopiedAttachments($params, $data, $request)
|
||||
{
|
||||
{
|
||||
$id = $request->get('id');
|
||||
|
||||
|
||||
return $this->getRecordService()->getCopiedAttachments($id);
|
||||
}
|
||||
|
||||
|
||||
public function actionSendTestEmail($params, $data, $request)
|
||||
{
|
||||
if (!$request->isPost()) {
|
||||
throw new BadRequest();
|
||||
}
|
||||
|
||||
|
||||
if (empty($data['password'])) {
|
||||
if ($data['type'] == 'preferences') {
|
||||
if (!$this->getUser()->isAdmin() && $data['id'] != $this->getUser()->id) {
|
||||
@@ -50,7 +50,7 @@ class Email extends \Espo\Core\Controllers\Record
|
||||
if (!$preferences) {
|
||||
throw new Error();
|
||||
}
|
||||
|
||||
|
||||
$data['password'] = $this->getContainer()->get('crypt')->decrypt($preferences->get('smtpPassword'));
|
||||
} else {
|
||||
if (!$this->getUser()->isAdmin()) {
|
||||
@@ -59,8 +59,21 @@ class Email extends \Espo\Core\Controllers\Record
|
||||
$data['password'] = $this->getConfig()->get('smtpPassword');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return $this->getRecordService()->sendTestEmail($data);
|
||||
}
|
||||
|
||||
public function actionMarkAsRead($params, $data, $request)
|
||||
{
|
||||
if (!$request->isPost()) {
|
||||
throw new BadRequest();
|
||||
}
|
||||
if (empty($data['ids']) || !is_array($data['ids'])) {
|
||||
throw new BadRequest();
|
||||
}
|
||||
$ids = $data['ids'];
|
||||
|
||||
return $this->getRecordService()->markAsReadByIds($ids);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -24,7 +24,8 @@
|
||||
"Draft": "Draft",
|
||||
"Sending": "Sending",
|
||||
"Sent": "Sent",
|
||||
"Archived": "Archived"
|
||||
"Archived": "Archived",
|
||||
"Received": "Received"
|
||||
},
|
||||
"labels": {
|
||||
"Create Email": "Archive Email",
|
||||
@@ -38,7 +39,8 @@
|
||||
"Email Accounts": "Email Accounts",
|
||||
"Send Test Email": "Send Test Email",
|
||||
"Send": "Send",
|
||||
"Email Address": "Email Address"
|
||||
"Email Address": "Email Address",
|
||||
"Mark Read": "Mark Read"
|
||||
},
|
||||
"messages": {
|
||||
"noSmtpSetup": "No SMTP setup. {link}.",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[
|
||||
{"name":"personStringData","width":16,"notSortable": true, "customLabel": ""},
|
||||
{"name":"name","width":32,"link":true,"notSortable": true},
|
||||
{"name":"subject","width":32,"link":true,"notSortable": true},
|
||||
{"name":"status","notSortable": true, "width":10},
|
||||
{"name":"parent","notSortable": true},
|
||||
{"name":"dateSent","view": "Fields.DatetimeShort", "notSortable": true, "width":10, "align": "right"}
|
||||
|
||||
@@ -8,7 +8,8 @@
|
||||
"type": "varchar",
|
||||
"required": true,
|
||||
"db": false,
|
||||
"notStorable": true
|
||||
"notStorable": true,
|
||||
"view": "Email.Fields.Subject"
|
||||
},
|
||||
"fromName": {
|
||||
"type": "varchar"
|
||||
@@ -44,6 +45,11 @@
|
||||
"notStorable": true,
|
||||
"disabled": true
|
||||
},
|
||||
"isRead": {
|
||||
"type": "bool",
|
||||
"notStorable": true,
|
||||
"default": true
|
||||
},
|
||||
"nameHash": {
|
||||
"type": "text",
|
||||
"notStorable": true,
|
||||
@@ -101,7 +107,7 @@
|
||||
},
|
||||
"status": {
|
||||
"type": "enum",
|
||||
"options": ["Draft", "Sending", "Sent", "Archived"],
|
||||
"options": ["Draft", "Sending", "Sent", "Received", "Archived"],
|
||||
"readOnly": true,
|
||||
"default": "Archived"
|
||||
},
|
||||
@@ -167,7 +173,13 @@
|
||||
"users": {
|
||||
"type": "hasMany",
|
||||
"entity": "User",
|
||||
"foreign": "emails"
|
||||
"foreign": "emails",
|
||||
"additionalColumns": {
|
||||
"isRead": {
|
||||
"type": "bool",
|
||||
"default": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"attachments": {
|
||||
"type": "hasChildren",
|
||||
|
||||
@@ -206,10 +206,34 @@ class Email extends Record
|
||||
|
||||
$this->loadAttachmentsTypes($entity);
|
||||
|
||||
$this->markAsRead($entity->id);
|
||||
}
|
||||
return $entity;
|
||||
}
|
||||
|
||||
public function markAsReadByIds(array $ids)
|
||||
{
|
||||
foreach ($ids as $id) {
|
||||
$this->markAsRead($id);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public function markAsRead($id)
|
||||
{
|
||||
|
||||
$pdo = $this->getEntityManager()->getPDO();
|
||||
$sql = "
|
||||
UPDATE email_user SET is_read = 1
|
||||
WHERE
|
||||
deleted = 0 AND
|
||||
user_id = " . $pdo->quote($this->getUser()->id) . " AND
|
||||
email_id = " . $pdo->quote($id) . "
|
||||
";
|
||||
$pdo->query($sql);
|
||||
return true;
|
||||
}
|
||||
|
||||
public function loadAdditionalFieldsForList(Entity $entity)
|
||||
{
|
||||
parent::loadAdditionalFieldsForList($entity);
|
||||
@@ -246,8 +270,26 @@ class Email extends Record
|
||||
}
|
||||
$entity->set('personStringData', 'To: ' . implode(', ', $arr));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$pdo = $this->getEntityManager()->getPDO();
|
||||
|
||||
$sql = "
|
||||
SELECT is_read AS 'isRead' FROM email_user
|
||||
WHERE
|
||||
deleted = 0 AND
|
||||
user_id = " . $pdo->quote($this->getUser()->id) . " AND
|
||||
email_id = " . $pdo->quote($entity->id) . "
|
||||
";
|
||||
|
||||
$sth = $pdo->prepare($sql);
|
||||
$sth->execute();
|
||||
if ($row = $sth->fetch(\PDO::FETCH_ASSOC)) {
|
||||
$isRead = !empty($row['isRead']) ? true : false;
|
||||
} else {
|
||||
$isRead = true;
|
||||
}
|
||||
$entity->set('isRead', $isRead);
|
||||
}
|
||||
|
||||
protected function loadAttachmentsTypes(Entity $entity)
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
{{#unless isRead}}<strong>{{/unless}}
|
||||
<a href="#{{model.name}}/view/{{model.id}}" class="link" data-id="{{model.id}}" title="{{value}}">{{value}}</a>
|
||||
{{#unless isRead}}</strong>{{/unless}}
|
||||
@@ -6,7 +6,7 @@
|
||||
{{{pagination}}}
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
|
||||
{{#if checkboxes}}
|
||||
<div class="btn-group actions">
|
||||
<button type="button" class="btn btn-default btn-sm dropdown-toggle actions-button" data-toggle="dropdown" disabled>
|
||||
@@ -14,12 +14,12 @@
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
{{#each actions}}
|
||||
<li><a href="javascript:" data-action="{{name}}">{{translate label scope=../scope}}</a></li>
|
||||
<li><a href="javascript:" data-action="{{name}}" class='mass-action'>{{translate label scope=../scope}}</a></li>
|
||||
{{/each}}
|
||||
</ul>
|
||||
</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
<div class="list list-expanded">
|
||||
@@ -35,7 +35,7 @@
|
||||
{{#if showCount}}
|
||||
<div class="pull-right text-muted more-count">{{moreCount}}</div>
|
||||
{{/if}}
|
||||
<span>{{translate 'Show more'}}</span>
|
||||
<span>{{translate 'Show more'}}</span>
|
||||
</a>
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
{{#each actions}}
|
||||
<li><a href="javascript:" data-action="{{name}}">{{translate label scope=../scope}}</a></li>
|
||||
<li><a href="javascript:" data-action="{{name}}" class='mass-action'>{{translate label scope=../scope}}</a></li>
|
||||
{{/each}}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
@@ -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/.
|
||||
************************************************************************/
|
||||
************************************************************************/
|
||||
(function (Espo, Backbone, _, Bull, $) {
|
||||
|
||||
Espo.View = Bull.View.extend({
|
||||
@@ -43,6 +43,15 @@
|
||||
Espo.Ui.notify(text, type, timeout);
|
||||
},
|
||||
|
||||
reRender: function () {
|
||||
if (this.isRendered()) {
|
||||
this.render();
|
||||
} else if (this.isBeingRendered()) {
|
||||
this.once('after:render', function () {
|
||||
this.render();
|
||||
}, this);
|
||||
}
|
||||
},
|
||||
|
||||
getHelper: function () {
|
||||
return this._helper;
|
||||
@@ -131,7 +140,7 @@
|
||||
return this._helper.fieldManager;
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
getBaseController: function () {
|
||||
if (this._helper) {
|
||||
return this._helper.baseController;
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2015 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
|
||||
* Website: http://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* EspoCRM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* 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.Email.Fields.Subject', 'Views.Fields.Varchar', function (Dep) {
|
||||
|
||||
return Dep.extend({
|
||||
|
||||
listLinkTemplate: 'email.fields.subject.list-link',
|
||||
|
||||
data: function () {
|
||||
return _.extend({
|
||||
'isRead': this.model.get('isRead')
|
||||
}, Dep.prototype.data.call(this));
|
||||
},
|
||||
|
||||
getValueForDisplay: function () {
|
||||
return this.model.get('name');
|
||||
},
|
||||
|
||||
getAttributeList: function () {
|
||||
return ['name', 'isRead'];
|
||||
},
|
||||
|
||||
setup: function () {
|
||||
Dep.prototype.setup.call(this);
|
||||
this.listenTo(this.model, 'change:isRead', function () {
|
||||
this.reRender();
|
||||
}, this);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
@@ -59,6 +59,7 @@ Espo.define('Views.Email.List', 'Views.List', function (Dep) {
|
||||
};
|
||||
},
|
||||
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -17,18 +17,46 @@
|
||||
*
|
||||
* 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.Email.Record.List', 'Views.Record.List', function (Dep) {
|
||||
|
||||
return Dep.extend({
|
||||
|
||||
|
||||
mergeAction: false,
|
||||
|
||||
|
||||
massUpdateAction: false,
|
||||
|
||||
|
||||
exportAction: false,
|
||||
|
||||
|
||||
setup: function () {
|
||||
Dep.prototype.setup.call(this);
|
||||
|
||||
this.actions.push({
|
||||
name: 'markAsRead',
|
||||
label: 'Mark Read',
|
||||
action: function (e) {
|
||||
var ids = [];
|
||||
for (var i in this.checkedList) {
|
||||
ids.push(this.checkedList[i]);
|
||||
}
|
||||
$.ajax({
|
||||
url: 'Email/action/markAsRead',
|
||||
type: 'POST',
|
||||
data: JSON.stringify({
|
||||
ids: ids
|
||||
})
|
||||
});
|
||||
ids.forEach(function (id) {
|
||||
var model = this.collection.get(id);
|
||||
if (model) {
|
||||
model.set('isRead', true);
|
||||
}
|
||||
}, this);
|
||||
}.bind(this)
|
||||
});
|
||||
},
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -280,13 +280,7 @@ Espo.define('Views.Fields.Base', 'View', function (Dep) {
|
||||
});
|
||||
|
||||
if (changed) {
|
||||
if (this.isRendered()) {
|
||||
this.render();
|
||||
} else if (this.isBeingRendered()) {
|
||||
this.once('after:render', function () {
|
||||
this.render();
|
||||
}, this);
|
||||
}
|
||||
this.reRender();
|
||||
}
|
||||
}
|
||||
}.bind(this));
|
||||
|
||||
@@ -145,6 +145,15 @@ Espo.define('Views.Record.List', 'View', function (Dep) {
|
||||
'click .checkbox-dropdown [data-action="selectAllResult"]': function (e) {
|
||||
this.selectAllResult();
|
||||
},
|
||||
'click .actions a.mass-action': function (e) {
|
||||
$el = $(e.currentTarget);
|
||||
var action = $el.data('action');
|
||||
this.actions.forEach(function (item) {
|
||||
if (item.name == action) {
|
||||
item.action.call(this, e);
|
||||
}
|
||||
}, this);
|
||||
}
|
||||
},
|
||||
|
||||
actions: [],
|
||||
@@ -430,13 +439,13 @@ Espo.define('Views.Record.List', 'View', function (Dep) {
|
||||
this.actions = [];
|
||||
}
|
||||
|
||||
if (this.checkboxes) {
|
||||
/*if (this.checkboxes) {
|
||||
this.actions.forEach(function (item) {
|
||||
this.events['click .actions a[data-action="' + item.name + '"]'] = function (e) {
|
||||
item.action.call(this, e);
|
||||
}.bind(this);
|
||||
}.bind(this));
|
||||
}
|
||||
}*/
|
||||
|
||||
this.listenTo(this.collection, 'sync', function () {
|
||||
if (this.noRebuild) {
|
||||
|
||||
Reference in New Issue
Block a user