Merge branch 'hotfix/5.6.12' of ssh://172.20.0.1/var/git/espo/backend into hotfix/5.6.12
This commit is contained in:
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2019 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
|
||||
* Website: https://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/.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Core\Exceptions;
|
||||
|
||||
class ConflictSilent extends Conflict
|
||||
{
|
||||
public $logLevel = 'notice';
|
||||
}
|
||||
@@ -54,7 +54,7 @@ class EntityManager
|
||||
|
||||
private $linkForbiddenNameList = ['posts', 'stream', 'subscription', 'followers', 'action', 'null', 'false', 'true'];
|
||||
|
||||
private $forbiddenEntityTypeNameList = ['PortalUser', 'ApiUser', 'Timeline', 'About', 'Admin', 'Null', 'False', 'True'];
|
||||
private $forbiddenEntityTypeNameList = ['Common', 'PortalUser', 'ApiUser', 'Timeline', 'About', 'Admin', 'Null', 'False', 'True'];
|
||||
|
||||
public function __construct(Metadata $metadata, Language $language, File\Manager $fileManager, Config $config, Container $container = null)
|
||||
{
|
||||
|
||||
@@ -33,7 +33,17 @@ use Espo\ORM\Entity;
|
||||
|
||||
class Lead extends \Espo\Core\ORM\Repositories\RDB
|
||||
{
|
||||
public function afterSave(Entity $entity, array $options = array())
|
||||
public function beforeSave(Entity $entity, array $options = [])
|
||||
{
|
||||
if (!$entity->get('convertedAt') && $entity->get('status') === 'Converted' && $entity->isAttributeChanged('status')) {
|
||||
$convertedAt = date('Y-m-d H:i:s');
|
||||
$entity->set('convertedAt', $convertedAt);
|
||||
}
|
||||
|
||||
parent::beforeSave($entity, $options);
|
||||
}
|
||||
|
||||
public function afterSave(Entity $entity, array $options = [])
|
||||
{
|
||||
parent::afterSave($entity, $options);
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
"createdAccount": "Account",
|
||||
"createdContact": "Contact",
|
||||
"createdOpportunity": "Opportunity",
|
||||
"convertedAt": "Converted At",
|
||||
"campaign": "Campaign",
|
||||
"targetLists": "Target Lists",
|
||||
"targetList": "Target List",
|
||||
|
||||
@@ -6,6 +6,11 @@
|
||||
"recordViews":{
|
||||
"detail":"crm:views/lead/record/detail"
|
||||
},
|
||||
"defaultSidePanelFieldList": [
|
||||
":assignedUser",
|
||||
"teams",
|
||||
"convertedAt"
|
||||
],
|
||||
"sidePanels":{
|
||||
"detail":[
|
||||
{
|
||||
@@ -132,6 +137,26 @@
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"convertedAt": {
|
||||
"visible": {
|
||||
"conditionGroup": [
|
||||
{
|
||||
"type": "and",
|
||||
"value": [
|
||||
{
|
||||
"type": "equals",
|
||||
"attribute": "status",
|
||||
"value": "Converted"
|
||||
},
|
||||
{
|
||||
"type": "isNotEmpty",
|
||||
"attribute": "convertedAt"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"panels": {
|
||||
|
||||
@@ -100,6 +100,12 @@
|
||||
"description": {
|
||||
"type": "text"
|
||||
},
|
||||
"convertedAt": {
|
||||
"type": "datetime",
|
||||
"layoutDetailDisabled": true,
|
||||
"layoutMassUpdateDisabled": true,
|
||||
"readOnly": true
|
||||
},
|
||||
"createdAt": {
|
||||
"type": "datetime",
|
||||
"readOnly": true
|
||||
|
||||
@@ -91,7 +91,6 @@
|
||||
"massEmailOpenTracking": "Email Open Tracking",
|
||||
"activitiesEntityList": "Activities Entity List",
|
||||
"historyEntityList": "History Entity List",
|
||||
"b2cMode": "B2C Mode",
|
||||
"currencyFormat": "Currency Format",
|
||||
"currencyDecimalPlaces": "Currency Decimal Places",
|
||||
"aclStrictMode": "ACL Strict Mode",
|
||||
|
||||
@@ -51,7 +51,7 @@ class Email extends \Espo\Core\SelectManagers\Base
|
||||
$skipIndex = true;
|
||||
break;
|
||||
} else {
|
||||
if (isset($item['attribute']) && $this->getSeed()->getAttributeParam($item['attribute'], 'type') === 'foreignId') {
|
||||
if (isset($item['attribute'])) {
|
||||
$skipIndex = true;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -41,5 +41,10 @@ class EmailFilter extends Record
|
||||
if (!$this->getAcl()->check($entity, 'edit')) {
|
||||
throw new Forbidden();
|
||||
}
|
||||
|
||||
if ($entity->get('isGlobal')) {
|
||||
$entity->set('parentId', null);
|
||||
$entity->set('parentType', null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,6 +38,7 @@ use \Espo\Core\Exceptions\Conflict;
|
||||
use \Espo\Core\Exceptions\NotFound;
|
||||
use \Espo\Core\Exceptions\NotFoundSilent;
|
||||
use \Espo\Core\Exceptions\ForbiddenSilent;
|
||||
use \Espo\Core\Exceptions\ConflictSilent;
|
||||
|
||||
use \Espo\Core\Utils\Util;
|
||||
|
||||
@@ -830,7 +831,7 @@ class Record extends \Espo\Core\Services\Base
|
||||
'reason' => 'Duplicate',
|
||||
'data' => $data
|
||||
];
|
||||
throw new Conflict(json_encode($reason));
|
||||
throw new ConflictSilent(json_encode($reason));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -154,6 +154,8 @@ Espo.define('crm:views/contact/fields/accounts', 'views/fields/link-multiple-wit
|
||||
},
|
||||
|
||||
addLinkHtml: function (id, name) {
|
||||
name = name || id;
|
||||
|
||||
if (this.mode == 'search') {
|
||||
return Dep.prototype.addLinkHtml.call(this, id, name);
|
||||
}
|
||||
|
||||
@@ -43,8 +43,7 @@ Espo.define('crm:views/lead/record/panels/converted-to', 'views/record/panels/si
|
||||
if (this.getAcl().check('Opportunity') && !this.getMetadata().get('scopes.Opportunity.disabled')) {
|
||||
this.fieldList.push('createdOpportunity');
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
<img src="{{url}}" style="max-width: 100%;">
|
||||
</div>
|
||||
|
||||
{{#if size}}
|
||||
<div class="margin">
|
||||
{{translate 'Original'}}: <a href="{{originalUrl}}" target="_blank">{{name}}</a>
|
||||
<div class="original-link-container margin{{#unless showOriginalLink}} hidden{{/unless}}">
|
||||
<a href="{{originalUrl}}" target="_blank">{{translate 'Original'}}</a>
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
@@ -106,7 +106,7 @@ Espo.define('views/fields/link-multiple-with-columns', 'views/fields/link-multip
|
||||
},
|
||||
|
||||
getDetailLinkHtml: function (id, name) {
|
||||
name = name || this.nameHash[id];
|
||||
name = name || this.nameHash[id] || id;
|
||||
|
||||
var roleHtml = '';
|
||||
|
||||
|
||||
@@ -123,6 +123,8 @@ Espo.define('views/fields/link-multiple-with-primary', 'views/fields/link-multip
|
||||
},
|
||||
|
||||
addLinkHtml: function (id, name) {
|
||||
name = name || id;
|
||||
|
||||
if (this.mode == 'search') {
|
||||
return Dep.prototype.addLinkHtml.call(this, id, name);
|
||||
}
|
||||
@@ -130,7 +132,7 @@ Espo.define('views/fields/link-multiple-with-primary', 'views/fields/link-multip
|
||||
var $container = this.$el.find('.link-container');
|
||||
var $el = $('<div class="form-inline list-group-item link-with-role clearfix link-group-item-with-primary">').addClass('link-' + id).attr('data-id', id);
|
||||
|
||||
var nameHtml = '<div>' + this.getHelper().escapeString(name) + ' ' + '</div>';
|
||||
var nameHtml = '<div>' + this.getHelper().escapeString(name) || id + ' ' + '</div>';
|
||||
var removeHtml = '<a href="javascript:" class="pull-right" data-id="' + id + '" data-action="clearLink"><span class="fas fa-times"></a>';
|
||||
|
||||
$left = $('<div>');
|
||||
|
||||
@@ -70,7 +70,7 @@ Espo.define('views/fields/link-multiple-with-role', 'views/fields/link-multiple'
|
||||
},
|
||||
|
||||
getDetailLinkHtml: function (id, name) {
|
||||
name = name || this.nameHash[id];
|
||||
name = name || this.nameHash[id] || id;
|
||||
if (!name && id) {
|
||||
name = this.translate(this.foreignScope, 'scopeNames');
|
||||
}
|
||||
@@ -158,6 +158,8 @@ Espo.define('views/fields/link-multiple-with-role', 'views/fields/link-multiple'
|
||||
},
|
||||
|
||||
addLinkHtml: function (id, name) {
|
||||
name = name || id;
|
||||
|
||||
if (this.mode == 'search') {
|
||||
return Dep.prototype.addLinkHtml.call(this, id, name);
|
||||
}
|
||||
|
||||
@@ -307,6 +307,8 @@ Espo.define('views/fields/link-multiple', 'views/fields/base', function (Dep) {
|
||||
},
|
||||
|
||||
addLinkHtml: function (id, name) {
|
||||
name = name || id;
|
||||
|
||||
var $container = this.$el.find('.link-container');
|
||||
var $el = $('<div />').addClass('link-' + id).addClass('list-group-item').attr('data-id', id);
|
||||
$el.html(this.getHelper().escapeString(name || id) + ' ');
|
||||
|
||||
@@ -26,13 +26,13 @@
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
Espo.define('views/fields/link-one', 'views/fields/link', function (Dep) {
|
||||
define('views/fields/link-one', 'views/fields/link', function (Dep) {
|
||||
|
||||
return Dep.extend({
|
||||
|
||||
readOnly: true,
|
||||
|
||||
searchTypeList: ['is', 'isOneOf'],
|
||||
searchTypeList: ['is', 'isEmpty', 'isNotEmpty', 'isOneOf'],
|
||||
|
||||
fetchSearch: function () {
|
||||
var type = this.$el.find('select.search-type').val();
|
||||
@@ -46,12 +46,12 @@ Espo.define('views/fields/link-one', 'views/fields/link', function (Dep) {
|
||||
data: {
|
||||
type: type,
|
||||
oneOfIdList: this.searchData.oneOfIdList,
|
||||
oneOfNameHash: this.searchData.oneOfNameHash
|
||||
}
|
||||
oneOfNameHash: this.searchData.oneOfNameHash,
|
||||
},
|
||||
};
|
||||
return data;
|
||||
|
||||
} else {
|
||||
} else if (type == 'is' || !type) {
|
||||
if (!value) {
|
||||
return false;
|
||||
}
|
||||
@@ -61,8 +61,26 @@ Espo.define('views/fields/link-one', 'views/fields/link', function (Dep) {
|
||||
value: value,
|
||||
data: {
|
||||
type: type,
|
||||
nameValue: this.$el.find('[data-name="' + this.nameName + '"]').val()
|
||||
}
|
||||
nameValue: this.$el.find('[data-name="' + this.nameName + '"]').val(),
|
||||
},
|
||||
};
|
||||
return data;
|
||||
|
||||
} else if (type === 'isEmpty') {
|
||||
var data = {
|
||||
type: 'isNotLinked',
|
||||
data: {
|
||||
type: type,
|
||||
},
|
||||
};
|
||||
return data;
|
||||
|
||||
} else if (type === 'isNotEmpty') {
|
||||
var data = {
|
||||
type: 'isLinked',
|
||||
data: {
|
||||
type: type,
|
||||
},
|
||||
};
|
||||
return data;
|
||||
}
|
||||
|
||||
@@ -186,7 +186,7 @@ Espo.define('views/fields/link-parent', 'views/fields/base', function (Dep) {
|
||||
},
|
||||
|
||||
select: function (model) {
|
||||
this.$elementName.val(model.get('name'));
|
||||
this.$elementName.val(model.get('name') || model.id);
|
||||
this.$elementId.val(model.get('id'));
|
||||
this.trigger('change');
|
||||
},
|
||||
|
||||
@@ -167,11 +167,11 @@ Espo.define('views/fields/link', 'views/fields/base', function (Dep) {
|
||||
},
|
||||
|
||||
select: function (model) {
|
||||
this.$elementName.val(model.get('name'));
|
||||
this.$elementName.val(model.get('name') || model.id);
|
||||
this.$elementId.val(model.get('id'));
|
||||
if (this.mode === 'search') {
|
||||
this.searchData.idValue = model.get('id');
|
||||
this.searchData.nameValue = model.get('name');
|
||||
this.searchData.nameValue = model.get('name') || model.id;
|
||||
}
|
||||
this.trigger('change');
|
||||
},
|
||||
|
||||
@@ -71,7 +71,7 @@ define('views/fields/wysiwyg', ['views/fields/text', 'lib!Summernote'], function
|
||||
['para', ['ul', 'ol', 'paragraph']],
|
||||
['height', ['height']],
|
||||
['table', ['table', 'espoLink', 'espoImage', 'hr']],
|
||||
['misc',['codeview', 'fullscreen']]
|
||||
['misc', ['codeview', 'fullscreen']]
|
||||
];
|
||||
|
||||
this.buttons = {};
|
||||
@@ -368,6 +368,8 @@ define('views/fields/wysiwyg', ['views/fields/text', 'lib!Summernote'], function
|
||||
keyMap.pc['CTRL+K'] = 'espoLink.show';
|
||||
keyMap.mac['CMD+K'] = 'espoLink.show';
|
||||
|
||||
var toolbar = this.toolbar;
|
||||
|
||||
var options = {
|
||||
espoView: this,
|
||||
lang: this.getConfig().get('language'),
|
||||
@@ -408,7 +410,7 @@ define('views/fields/wysiwyg', ['views/fields/text', 'lib!Summernote'], function
|
||||
onCreateLink: function (link) {
|
||||
return link;
|
||||
},
|
||||
toolbar: this.toolbar,
|
||||
toolbar: toolbar,
|
||||
buttons: this.buttons,
|
||||
dialogsInBody: this.$el,
|
||||
codeviewFilter: true,
|
||||
@@ -710,6 +712,81 @@ define('views/fields/wysiwyg', ['views/fields/text', 'lib!Summernote'], function
|
||||
}
|
||||
},
|
||||
|
||||
'fullscreen': function (context) {
|
||||
var ui = $.summernote.ui;
|
||||
var options = context.options;
|
||||
var self = options.espoView;
|
||||
var lang = options.langInfo;
|
||||
|
||||
this.$window = $(window);
|
||||
this.$scrollbar = $('html, body');
|
||||
|
||||
this.initialize = function () {
|
||||
this.$editor = context.layoutInfo.editor;
|
||||
this.$toolbar = context.layoutInfo.toolbar;
|
||||
this.$editable = context.layoutInfo.editable;
|
||||
this.$codable = context.layoutInfo.codable;
|
||||
|
||||
this.$modal = self.$el.closest('.modal');
|
||||
this.isInModal = this.$modal.length > 0;
|
||||
};
|
||||
|
||||
this.resizeTo = function (size) {
|
||||
this.$editable.css('height', size.h);
|
||||
this.$codable.css('height', size.h);
|
||||
if (this.$codable.data('cmeditor')) {
|
||||
this.$codable.data('cmeditor').setsize(null, size.h);
|
||||
}
|
||||
};
|
||||
|
||||
this.onResize = function () {
|
||||
this.resizeTo({
|
||||
h: this.$window.height() - this.$toolbar.outerHeight(),
|
||||
});
|
||||
};
|
||||
|
||||
this.isFullscreen = function () {
|
||||
return this.$editor.hasClass('fullscreen');
|
||||
};
|
||||
|
||||
this.destroy = function () {
|
||||
this.$window.off('resize.summernote' + self.cid);
|
||||
if (this.isInModal) {
|
||||
this.$modal.css('overflow-y', '');
|
||||
} else {
|
||||
this.$scrollbar.css('overflow', '');
|
||||
}
|
||||
}
|
||||
|
||||
this.toggle = function () {
|
||||
this.$editor.toggleClass('fullscreen');
|
||||
if (this.isFullscreen()) {
|
||||
this.$editable.data('orgHeight', this.$editable.css('height'));
|
||||
this.$editable.data('orgMaxHeight', this.$editable.css('maxHeight'));
|
||||
this.$editable.css('maxHeight', '');
|
||||
this.$window.on('resize.summernote' + self.cid, this.onResize.bind(this)).trigger('resize');
|
||||
if (this.isInModal) {
|
||||
this.$modal.css('overflow-y', 'hidden');
|
||||
} else {
|
||||
this.$scrollbar.css('overflow', 'hidden');
|
||||
}
|
||||
this._isFullscreen = true;
|
||||
} else {
|
||||
this.$window.off('resize.summernote' + self.cid);
|
||||
this.resizeTo({ h: this.$editable.data('orgHeight') });
|
||||
this.$editable.css('maxHeight', this.$editable.css('orgMaxHeight'));
|
||||
if (this.isInModal) {
|
||||
this.$modal.css('overflow-y', '');
|
||||
} else {
|
||||
this.$scrollbar.css('overflow', '');
|
||||
}
|
||||
this._isFullscreen = false;
|
||||
}
|
||||
|
||||
context.invoke('toolbar.updateFullscreen', this.isFullscreen());
|
||||
};
|
||||
},
|
||||
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
@@ -53,7 +53,7 @@ Espo.define('views/modals/image-preview', ['views/modal', 'lib!exif'], function
|
||||
name: this.options.name,
|
||||
url: this.getImageUrl(),
|
||||
originalUrl: this.getOriginalImageUrl(),
|
||||
size: this.size
|
||||
showOriginalLink: this.size,
|
||||
};
|
||||
},
|
||||
|
||||
@@ -99,7 +99,9 @@ Espo.define('views/modals/image-preview', ['views/modal', 'lib!exif'], function
|
||||
|
||||
$img.on('load', function () {
|
||||
var self = this;
|
||||
EXIF.getData($img.get(0), function () {
|
||||
var imgEl = $img.get(0);
|
||||
|
||||
EXIF.getData(imgEl, function () {
|
||||
var orientation = EXIF.getTag(this, 'Orientation');
|
||||
switch (orientation) {
|
||||
case 2:
|
||||
@@ -128,6 +130,10 @@ Espo.define('views/modals/image-preview', ['views/modal', 'lib!exif'], function
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
if (imgEl.naturalWidth > imgEl.clientWidth) {
|
||||
this.$el.find('.original-link-container').removeClass('hidden');
|
||||
}
|
||||
}.bind(this));
|
||||
|
||||
if (this.navigationEnabled) {
|
||||
|
||||
Reference in New Issue
Block a user