Merge branch 'master' of ssh://172.20.0.1/var/git/espo/backend

This commit is contained in:
Taras Machyshyn
2017-04-10 15:56:24 +03:00
39 changed files with 685 additions and 91 deletions
+3 -3
View File
@@ -46,10 +46,10 @@ class HookManager
*
* @var array
*/
protected $ignoredMethods = array(
protected $ignoredMethodList = array(
'__construct',
'getDependencyList',
'inject',
'inject'
);
protected $paths = array(
@@ -168,7 +168,7 @@ class HookManager
$className = Util::getClassName($hookFilePath);
$classMethods = get_class_methods($className);
$hookMethods = array_diff($classMethods, $this->ignoredMethods);
$hookMethods = array_diff($classMethods, $this->ignoredMethodList);
foreach($hookMethods as $hookName) {
$entityHookData = isset($hookData[$scopeName][$hookName]) ? $hookData[$scopeName][$hookName] : array();
@@ -189,6 +189,13 @@ class RDB extends \Espo\ORM\Repositories\RDB implements Injectable
$this->getEntityManager()->getHookManager()->process($this->entityType, 'afterRemove', $entity, $options);
}
protected function afterMassRelate(Entity $entity, $relationName, array $params = array(), array $options = array())
{
$options['params'] = $params;
$this->getEntityManager()->getHookManager()->process($this->entityType, 'afterMassRelate', $entity, $options);
}
public function remove(Entity $entity, array $options = array())
{
$result = parent::remove($entity, $options);
+7
View File
@@ -61,6 +61,13 @@ class Auth extends \Slim\Middleware
list($authUsername, $authPassword) = explode(':', base64_decode($espoAuth));
}
if (!isset($authUsername)) {
if (!empty($_COOKIE['auth-username']) && !empty($_COOKIE['auth-token'])) {
$authUsername = $_COOKIE['auth-username'];
$authPassword = $_COOKIE['auth-token'];
}
}
$espoCgiAuth = $req->headers('HTTP_ESPO_CGI_AUTH');
if (empty($espoCgiAuth)) {
$espoCgiAuth = $req->headers('REDIRECT_HTTP_ESPO_CGI_AUTH');
+3 -2
View File
@@ -157,8 +157,9 @@ return array (
'activitiesEntityList' => ['Meeting', 'Call'],
'historyEntityList' => ['Meeting', 'Call', 'Email'],
'lastViewedCount' => 20,
'cleanupJobPeriod' => '-1 month',
'cleanupActionHistoryPeriod' => '-15 days',
'cleanupJobPeriod' => '1 month',
'cleanupActionHistoryPeriod' => '15 days',
'cleanupAuthTokenPeriod' => '1 month',
'isInstalled' => false
);
+20 -4
View File
@@ -33,9 +33,11 @@ use \Espo\Core\Exceptions;
class Cleanup extends \Espo\Core\Jobs\Base
{
protected $cleanupJobPeriod = '-1 month';
protected $cleanupJobPeriod = '1 month';
protected $cleanupActionHistoryPeriod = '-15 days';
protected $cleanupActionHistoryPeriod = '15 days';
protected $cleanupAuthTokenPeriod = '1 month';
public function run()
{
@@ -46,6 +48,7 @@ class Cleanup extends \Espo\Core\Jobs\Base
$this->cleanupNotes();
$this->cleanupNotifications();
$this->cleanupActionHistory();
$this->cleanupAuthToken();
}
protected function cleanupJobs()
@@ -83,7 +86,7 @@ class Cleanup extends \Espo\Core\Jobs\Base
protected function cleanupActionHistory()
{
$period = $this->getConfig()->get('cleanupActionHistoryPeriod', $this->cleanupActionHistoryPeriod);
$period = '-' . $this->getConfig()->get('cleanupActionHistoryPeriod', $this->cleanupActionHistoryPeriod);
$datetime = new \DateTime();
$datetime->modify($period);
@@ -94,9 +97,22 @@ class Cleanup extends \Espo\Core\Jobs\Base
$sth->execute();
}
protected function cleanupAuthToken()
{
$period = '-' . $this->getConfig()->get('cleanupAuthTokenPeriod', $this->cleanupAuthTokenPeriod);
$datetime = new \DateTime();
$datetime->modify($period);
$query = "DELETE FROM `auth_token` WHERE DATE(modified_at) < '" . $datetime->format('Y-m-d') . "' AND is_active = 0";
$pdo = $this->getEntityManager()->getPDO();
$sth = $pdo->prepare($query);
$sth->execute();
}
protected function getCleanupJobFromDate()
{
$period = $this->getConfig()->get('cleanupJobPeriod', $this->cleanupJobPeriod);
$period = '-' . $this->getConfig()->get('cleanupJobPeriod', $this->cleanupJobPeriod);
$datetime = new \DateTime();
$datetime->modify($period);
return $datetime->format('Y-m-d');
@@ -39,7 +39,6 @@
}
},
"tooltips": {
"portals": "Vil vises i alle portaler hvis den forbliver tom. Vil kun vises i valgte portaler hvis udfyldt."
},
"presetFilters": {
"published": "Publiseret"
@@ -39,7 +39,6 @@
}
},
"tooltips": {
"portals": "Wenn in diesem Feld etwas eingetragen ist, wird dieser Artikel nur in den gewählten Portalen angezeigt. Ist das Feld leer ist der Artikel in allen Portalen zu sehen."
},
"presetFilters": {
"published": "Publiziert"
@@ -39,7 +39,7 @@
}
},
"tooltips": {
"portals": "If not empty then this article will be available only in specified portals. If empty then it will available in all portals."
"portals": "Article will be available only in specified portals."
},
"presetFilters": {
"published": "Published"
@@ -39,7 +39,6 @@
}
},
"tooltips": {
"portals": "Si no está vacía, entonces este artículo estará disponible solo en portales específicos. Si está vacío, entonces estará disponible en todos los portales.\t"
},
"presetFilters": {
"published": "Publicado"
@@ -35,7 +35,7 @@
}
},
"tooltips": {
"portals": "If not empty then this article will be available only in specified portals. If empty then it will available in all portals."
},
"presetFilters": {
"published": "Publié"
@@ -35,7 +35,6 @@
}
},
"tooltips": {
"portals": "Jika tidak kosong maka artikel ini akan tersedia hanya dalam portal yang ditentukan. Jika kosong maka akan tersedia di semua portal."
},
"presetFilters": {
"published": "Diterbitkan"
@@ -37,7 +37,6 @@
}
},
"tooltips": {
"portals": "Se non è vuoto allora questo articolo sarà disponibile solo nei portali specifici. Se vuoto, allora sarà disponibile in tutti i portali ."
},
"presetFilters": {
"published": "Pubblicato"
@@ -39,7 +39,6 @@
}
},
"tooltips": {
"portals": "Vil vises i alle portaler hvis den forblir tom. Vil kun vises i valgte portaler hvis utfylt."
},
"presetFilters": {
"published": "Publisert"
@@ -34,7 +34,6 @@
}
},
"tooltips": {
"portals": "If not empty then this article will be available only in specified portals. If empty then it will available in all portals."
},
"presetFilters": {
"published": "Published"
@@ -34,7 +34,7 @@
}
},
"tooltips": {
"portals": "Если не пусто, то эта статья будет доступна только в указанных порталах. Если пусто, то будет доступна во всех порталах."
"portals": "Статья будет доступна только в указанных порталах."
},
"presetFilters": {
"published": "Опубликована"
@@ -37,7 +37,6 @@
}
},
"tooltips": {
"portals": "如果不是空的那么这篇文章将只能在指定门户可用。如果是空的那么在所有门户她都可用"
},
"presetFilters": {
"published": "公布的"
@@ -3,7 +3,8 @@
"layouts": true,
"tab": true,
"acl": true,
"aclPortal": "recordAllAccountOwnNo",
"aclPortal": true,
"aclPortalLevelList": ["all", "account", "contact", "own", "no"],
"module": "Crm",
"customizable": true,
"importable": false,
@@ -50,9 +50,6 @@ class KnowledgeBaseArticle extends \Espo\Core\SelectManagers\Base
$this->addOrWhere(array(
array(
'portals.id' => $this->getUser()->get('portalId')
),
array(
'portals.id' => null
)
), $result);
}
@@ -103,45 +103,6 @@ class KnowledgeBaseArticle extends \Espo\Services\Record
);
}
public function moveToTop($id, $where = null)
{
$entity = $this->getEntityManager()->getEntity('KnowledgeBaseArticle', $id);
if (!$entity) throw new NotFound();
if (!$this->getAcl()->check($entity, 'edit')) throw new Forbidden();
$currentIndex = $entity->get('order');
if (!is_int($currentIndex)) throw new Error();
if (!$where) {
$where = array();
}
$params = array(
'where' => $where
);
$selectManager = $this->getSelectManager();
$selectParams = $selectManager->buildSelectParams($params, true, true);
$selectParams['whereClause'][] = array(
'order<' => $currentIndex
);
$selectManager->applyOrder('order', false, $selectParams);
$previousEntity = $this->getRepository()->findOne($selectParams);
if (!$previousEntity) return;
$entity->set('order', $previousEntity->get('order'));
$previousEntity->set('order', $currentIndex);
$this->getEntityManager()->saveEntity($entity);
$this->getEntityManager()->saveEntity($previousEntity);
}
public function moveUp($id, $where = null)
{
$entity = $this->getEntityManager()->getEntity('KnowledgeBaseArticle', $id);
@@ -217,6 +178,43 @@ class KnowledgeBaseArticle extends \Espo\Services\Record
$this->getEntityManager()->saveEntity($entity);
$this->getEntityManager()->saveEntity($nextEntity);
}
public function moveToTop($id, $where = null)
{
$entity = $this->getEntityManager()->getEntity('KnowledgeBaseArticle', $id);
if (!$entity) throw new NotFound();
if (!$this->getAcl()->check($entity, 'edit')) throw new Forbidden();
$currentIndex = $entity->get('order');
if (!is_int($currentIndex)) throw new Error();
if (!$where) {
$where = array();
}
$params = array(
'where' => $where
);
$selectManager = $this->getSelectManager();
$selectParams = $selectManager->buildSelectParams($params, true, true);
$selectParams['whereClause'][] = array(
'order<' => $currentIndex
);
$selectManager->applyOrder('order', false, $selectParams);
$previousEntity = $this->getRepository()->findOne($selectParams);
if (!$previousEntity) return;
$entity->set('order', $previousEntity->get('order') - 1);
$this->getEntityManager()->saveEntity($entity);
}
public function moveToBottom($id, $where = null)
{
$entity = $this->getEntityManager()->getEntity('KnowledgeBaseArticle', $id);
@@ -248,10 +246,8 @@ class KnowledgeBaseArticle extends \Espo\Services\Record
if (!$nextEntity) return;
$entity->set('order', $nextEntity->get('order'));
$nextEntity->set('order', $currentIndex);
$entity->set('order', $nextEntity->get('order') + 1);
$this->getEntityManager()->saveEntity($entity);
$this->getEntityManager()->saveEntity($nextEntity);
}
}
@@ -337,8 +337,6 @@ class MassEmail extends \Espo\Services\Record
$body = $emailData['body'];
$optOutUrl = $this->getConfig()->get('siteUrl') . '?entryPoint=unsubscribe&id=' . $queueItem->id;
$optOutLink = '<a href="'.$optOutUrl.'">'.$this->getLanguage()->translate('Unsubscribe', 'labels', 'Campaign').'</a>';
@@ -453,6 +451,13 @@ class MassEmail extends \Espo\Services\Record
$header->setId($queueItem->id);
$message->getHeaders()->addHeader($header);
$message->getHeaders()->addHeaderLine('Precedence', 'bulk');
if (!$this->getConfig()->get('massEmailDisableMandatoryOptOutLink')) {
$optOutUrl = $this->getConfig()->getSiteUrl() . '?entryPoint=unsubscribe&id=' . $queueItem->id;
$message->getHeaders()->addHeaderLine('List-Unsubscribe', '<' . $optOutUrl . '>');
}
$this->getMailSender()->useGlobal()->send($email, $params, $message, $attachmentList);
$isSent = true;
@@ -48,6 +48,14 @@ class TargetList extends \Espo\Services\Record
'User' => 'users'
);
protected function init()
{
parent::init();
$this->addDependencyList([
'hookManager'
]);
}
public function loadAdditionalFields(Entity $entity)
{
parent::loadAdditionalFields($entity);
@@ -178,6 +186,7 @@ class TargetList extends \Espo\Services\Record
}
if ($sql) {
if ($pdo->query($sql)) {
$this->getInjection('hookManager')->process('TargetList', 'afterUnlinkAll', $entity, array('link' => $link));
return true;
}
}
+15 -5
View File
@@ -354,22 +354,26 @@ class RDB extends \Espo\ORM\Repository
protected function beforeRelate(Entity $entity, $relationName, $foreign, $data = null, array $options = array())
{
}
protected function afterRelate(Entity $entity, $relationName, $foreign, $data = null, array $options = array())
{
}
protected function beforeUnrelate(Entity $entity, $relationName, $foreign, array $options = array())
{
}
protected function afterUnrelate(Entity $entity, $relationName, $foreign, array $options = array())
{
}
protected function beforeMassRelate(Entity $entity, $relationName, array $params = array(), array $options = array())
{
}
protected function afterMassRelate(Entity $entity, $relationName, array $params = array(), array $options = array())
{
}
public function updateRelation(Entity $entity, $relationName, $foreign, $data)
@@ -391,12 +395,18 @@ class RDB extends \Espo\ORM\Repository
return null;
}
public function massRelate(Entity $entity, $relationName, array $params = array())
public function massRelate(Entity $entity, $relationName, array $params = array(), array $options = array())
{
if (!$entity->id) {
return;
}
return $this->getMapper()->massRelate($entity, $relationName, $params);
$this->beforeMassRelate($entity, $relationName, $params, $options);
$result = $this->getMapper()->massRelate($entity, $relationName, $params);
if ($result) {
$this->afterMassRelate($entity, $relationName, $params, $options);
}
return $result;
}
public function getAll()
@@ -8,7 +8,12 @@
"isDoubleHeight": "Height 2x",
"mode": "Mode",
"enabledScopeList": "What to display",
"users": "Users"
"users": "Users",
"entityType": "Entity Type",
"primaryFilter": "Primary Filter",
"boolFilterList": "Additional Filters",
"sortBy": "Order (field)",
"sortDirection": "Order (direction)"
},
"options": {
"mode": {
@@ -19,5 +24,8 @@
"agendaDay": "Day (agenda)",
"timeline": "Timeline"
}
},
"messages": {
"selectEntityType": "Select Entity Type in dashlet options."
}
}
@@ -313,7 +313,8 @@
},
"dashlets": {
"Stream": "Stream",
"Emails": "My Inbox"
"Emails": "My Inbox",
"Records": "Record List"
},
"notificationMessages": {
"assign": "{entityType} {entity} has been assigned to you",
@@ -0,0 +1,80 @@
{
"options": {
"fields": {
"title": {
"type": "varchar",
"required": true
},
"autorefreshInterval": {
"type": "enumFloat",
"options": [0, 0.5, 1, 2, 5, 10]
},
"displayRecords": {
"type": "enumInt",
"options": [3, 4, 5, 10, 15, 20, 30, 50]
},
"entityType": {
"type": "enum",
"view": "views/dashlets/fields/records/entity-type",
"translation": "Global.scopeNames"
},
"primaryFilter": {
"type": "enum",
"view": "views/dashlets/fields/records/primary-filter"
},
"boolFilterList": {
"type": "multiEnum",
"view": "views/dashlets/fields/records/bool-filter-list"
},
"sortBy": {
"type": "enum",
"view": "views/dashlets/fields/records/sort-by"
},
"sortDirection": {
"type": "enum",
"view": "views/dashlets/fields/records/sort-direction",
"options": ["asc", "desc"],
"translation": "EntityManager.options.sortDirection"
}
},
"defaults": {
"displayRecords": 10,
"autorefreshInterval": 0.5,
"expandedLayout": {
"rows": [
[
{
"name": "name",
"link": true
}
]
]
}
},
"layout": [
{
"rows": [
[
{"name": "title"}
],
[
{"name": "entityType"},
false
],
[
{"name": "primaryFilter"},
{"name": "sortBy"}
],
[
{"name": "boolFilterList"},
{"name": "sortDirection"}
],
[
{"name": "displayRecords"},
{"name": "autorefreshInterval"}
]
]
}
]
}
}
+18 -10
View File
@@ -391,7 +391,7 @@ Espo.define(
this.auth = Base64.encode(data.auth.userName + ':' + data.auth.token);
this.storage.set('user', 'auth', this.auth);
this.setCookieAuthToken(data.auth.token);
this.setCookieAuth(data.auth.userName, data.auth.token);
this.initUserData(data, function () {
this.trigger('auth');
@@ -426,21 +426,24 @@ Espo.define(
this.doAction({action: 'login'});
this.language.clearCache();
this.unsetCookieAuthToken();
this.unsetCookieAuth();
xhr = new XMLHttpRequest;
xhr.open('GET', this.url + '/', true, 'logout', 'logout');
xhr.open('GET', this.url + '/');
xhr.setRequestHeader('Authorization', 'Basic ' + Base64.encode('**logout:logout'));
xhr.send('');
xhr.abort();
},
setCookieAuthToken: function (token) {
setCookieAuth: function (username, token) {
var date = new Date();
date.setTime(date.getTime() + (1000 * 24*60*60*1000));
document.cookie = 'auth-username='+username+'; expires='+date.toGMTString()+'; path=/';
document.cookie = 'auth-token='+token+'; expires='+date.toGMTString()+'; path=/';
},
unsetCookieAuthToken: function () {
unsetCookieAuth: function () {
document.cookie = 'auth-username' + '=; expires=Thu, 01 Jan 1970 00:00:01 GMT; path=/';
document.cookie = 'auth-token' + '=; expires=Thu, 01 Jan 1970 00:00:01 GMT; path=/';
},
@@ -485,14 +488,19 @@ Espo.define(
return;
}
var arr = Base64.decode(this.auth).split(':');
var xhr = new XMLHttpRequest();
xhr.open('GET', this.basePath + this.url + '/', true, arr[0], arr[1]);
xhr.open('GET', this.basePath + this.url + '/');
xhr.setRequestHeader('Authorization', 'Basic ' + this.auth);
xhr.onreadystatechange = function () {
if (callback) {
callback();
}
}
xhr.send('');
if (callback) {
callback();
}
}.bind(this));
},
+1 -1
View File
@@ -43,7 +43,7 @@ Espo.define('view-helper', [], function () {
this.mdReplace = [
'<a href="$2">$1</a>',
function (s, string) {
return '<code>' + string.replace(/\*/g, '&#42;').replace(/\~/g, '&#126;') + '</code>';
return '<pre><code>' + string.replace(/\*/g, '&#42;').replace(/\~/g, '&#126;') + '</code></pre>';
},
function (s, string) {
return '<code>' + string.replace(/\*/g, '&#42;').replace(/\~/g, '&#126;') + '</code>';
@@ -60,9 +60,20 @@ Espo.define('views/dashlets/abstract/record-list', ['views/dashlets/abstract/bas
return this.getAcl().check(this.scope, 'read');
},
getSearchData: function () {
return this.getOption('searchData');
},
afterRender: function () {
this.getCollectionFactory().create(this.scope, function (collection) {
var searchManager = this.searchManager = new SearchManager(collection, 'list', null, this.getDateTime(), this.getOption('searchData'));
var searchData = this.getSearchData();
var searchManager = this.searchManager = new SearchManager(collection, 'list', null, this.getDateTime(), searchData);
if (!this.scope) {
this.$el.find('.list-container').html(this.translate('selectEntityType', 'messages', 'DashletOptions'));
return;
}
if (!this.checkAccess()) {
this.$el.find('.list-container').html(this.translate('No Access'));
@@ -76,6 +87,13 @@ Espo.define('views/dashlets/abstract/record-list', ['views/dashlets/abstract/bas
this.collection = collection;
collection.sortBy = this.getOption('sortBy') || this.collection.sortBy;
collection.asc = this.getOption('asc') || this.collection.asc;
if (this.getOption('sortDirection') === 'asc') {
collection.asc = true;
} else if (this.getOption('sortDirection') === 'desc') {
collection.asc = false;
}
collection.maxSize = this.getOption('displayRecords');
collection.where = searchManager.getWhere();
@@ -102,7 +120,7 @@ Espo.define('views/dashlets/abstract/record-list', ['views/dashlets/abstract/bas
},
setupActionList: function () {
if (this.getAcl().checkScope(this.scope, 'create')) {
if (this.scope && this.getAcl().checkScope(this.scope, 'create')) {
this.actionList.unshift({
name: 'create',
html: this.translate('Create ' + this.scope, 'labels', this.scope),
@@ -113,6 +131,8 @@ Espo.define('views/dashlets/abstract/record-list', ['views/dashlets/abstract/bas
},
actionRefresh: function () {
if (!this.collection) return;
this.collection.where = this.searchManager.getWhere();
this.collection.fetch();
},
@@ -0,0 +1,61 @@
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM - Open Source CRM application.
* Copyright (C) 2014-2017 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/.
*
* 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.
************************************************************************/
Espo.define('views/dashlets/fields/records/bool-filter-list', 'views/fields/multi-enum', function (Dep) {
return Dep.extend({
setup: function () {
Dep.prototype.setup.call(this);
this.listenTo(this.model, 'change:entityType', function () {
this.setupOptions();
this.reRender();
}, this);
},
setupOptions: function () {
var entityType = this.model.get('entityType');
if (!entityType) {
this.params.options = [];
return;
}
this.params.options = this.getMetadata().get(['clientDefs', entityType, 'boolFilterList']) || [];
if (this.getMetadata().get(['scopes', entityType, 'stream']) && this.getAcl().checkScope(entityType, 'stream')) {
this.params.options.push('followed');
}
this.translatedOptions = {};
this.params.options.forEach(function (item) {
this.translatedOptions[item] = this.translate(item, 'boolFilters', entityType);
}, this);
}
});
});
@@ -0,0 +1,76 @@
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM - Open Source CRM application.
* Copyright (C) 2014-2017 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/.
*
* 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.
************************************************************************/
Espo.define('views/dashlets/fields/records/entity-type', 'views/fields/enum', function (Dep) {
return Dep.extend({
setup: function () {
Dep.prototype.setup.call(this);
this.on('change', function () {
var o = {
primaryFilter: null,
boolFilterList: [],
title: this.translate('Records', 'dashlets'),
sortBy: null,
sortDirection: 'asc'
};
var entityType = this.model.get('entityType');
if (entityType) {
o.title = this.translate(entityType, 'scopeNamesPlural');
o.sortBy = this.getMetadata().get(['entityDefs', entityType, 'collection', 'sortBy']);
var asc = this.getMetadata().get(['entityDefs', entityType, 'collection', 'asc']);
if (asc) {
o.sortDirection = 'asc';
} else {
o.sortDirection = 'desc';
}
}
this.model.set(o);
}, this);
},
setupOptions: function () {
this.params.options = Object.keys(this.getMetadata().get('scopes')).filter(function (scope) {
if (this.getMetadata().get('scopes.' + scope + '.disabled')) return;
if (!this.getAcl().checkScope(scope, 'read')) return;
if (!this.getMetadata().get(['scopes', scope, 'entity'])) return;
if (!this.getMetadata().get(['scopes', scope, 'object'])) return;
return true;
}, this).sort(function (v1, v2) {
return this.translate(v1, 'scopeNames').localeCompare(this.translate(v2, 'scopeNames'));
}.bind(this));
this.params.options.unshift('');
}
});
});
@@ -0,0 +1,68 @@
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM - Open Source CRM application.
* Copyright (C) 2014-2017 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/.
*
* 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.
************************************************************************/
Espo.define('views/dashlets/fields/records/primary-filter', 'views/fields/enum', function (Dep) {
return Dep.extend({
setup: function () {
Dep.prototype.setup.call(this);
this.listenTo(this.model, 'change:entityType', function () {
this.setupOptions();
this.reRender();
}, this);
},
setupOptions: function () {
var entityType = this.model.get('entityType');
if (!entityType) {
this.params.options = [];
return;
}
var filterList = this.getMetadata().get(['clientDefs', entityType, 'filterList']) || [];
this.params.options = [];
filterList.forEach(function (item) {
if (typeof item === 'object' && item.name) {
this.params.options.push(item.name);
return;
}
this.params.options.push(item);
}, this);
this.params.options.unshift('all');
this.translatedOptions = {};
this.params.options.forEach(function (item) {
this.translatedOptions[item] = this.translate(item, 'presetFilters', entityType);
}, this);
}
});
});
@@ -0,0 +1,71 @@
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM - Open Source CRM application.
* Copyright (C) 2014-2017 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/.
*
* 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.
************************************************************************/
Espo.define('views/dashlets/fields/records/sort-by', 'views/fields/enum', function (Dep) {
return Dep.extend({
setup: function () {
Dep.prototype.setup.call(this);
this.listenTo(this.model, 'change:entityType', function () {
this.setupOptions();
this.reRender();
}, this);
},
setupOptions: function () {
var entityType = this.model.get('entityType');
var scope = entityType;
if (!entityType) {
this.params.options = [];
return;
}
var fieldDefs = this.getMetadata().get('entityDefs.' + scope + '.fields') || {};
var orderableFieldList = Object.keys(fieldDefs).filter(function (item) {
if (fieldDefs[item].notStorable) {
return false;
}
return true;
}, this).sort(function (v1, v2) {
return this.translate(v1, 'fields', scope).localeCompare(this.translate(v2, 'fields', scope));
}.bind(this));
var translatedOptions = {};
orderableFieldList.forEach(function (item) {
translatedOptions[item] = this.translate(item, 'fields', scope);
}, this);
this.params.options = orderableFieldList;
this.translatedOptions = translatedOptions;
}
});
});
@@ -0,0 +1,43 @@
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM - Open Source CRM application.
* Copyright (C) 2014-2017 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/.
*
* 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.
************************************************************************/
Espo.define('views/dashlets/fields/records/sort-direction', 'views/fields/enum', function (Dep) {
return Dep.extend({
setup: function () {
Dep.prototype.setup.call(this);
this.listenTo(this.model, 'change:entityType', function () {
this.setupOptions();
this.reRender();
}, this);
}
});
});
+75
View File
@@ -0,0 +1,75 @@
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM - Open Source CRM application.
* Copyright (C) 2014-2017 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/.
*
* 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.
************************************************************************/
Espo.define('views/dashlets/records', 'views/dashlets/abstract/record-list', function (Dep) {
return Dep.extend({
name: 'Records',
scope: null,
rowActionsView: 'views/record/row-actions/view-and-edit',
listView: 'views/email/record/list-expanded',
init: function () {
Dep.prototype.init.call(this);
this.scope = this.getOption('entityType');
},
getSearchData: function () {
var data = {
primary: this.getOption('primaryFilter')
};
var bool = {};
(this.getOption('boolFilterList') || []).forEach(function (item) {
bool[item] = true;
}, this);
data.bool = bool;
return data;
},
setupActionList: function () {
var scope = this.getOption('entityType');
if (scope && this.getAcl().checkScope(scope, 'create')) {
this.actionList.unshift({
name: 'create',
html: this.translate('Create ' + scope, 'labels', scope),
iconHtml: '<span class="glyphicon glyphicon-plus"></span>',
url: '#' + scope + '/create'
});
}
},
});
});
+22
View File
@@ -294,6 +294,28 @@ Espo.define('views/email/record/detail', 'views/record/detail', function (Dep) {
this.save();
},
exitAfterDelete: function () {
var folderId = ((this.collection || {}).data || {}).folderId || null;
if (folderId === 'inbox') {
folderId = null;
}
var options = {
isReturn: true,
isReturnThroughLink: false,
folder: folderId
};
var url = '#' + this.scope;
var action = null;
if (folderId) {
action = 'list';
url += '/list/folder=' + folderId;
}
this.getRouter().dispatch(this.scope, action, options);
this.getRouter().navigate(url, {trigger: false});
}
});
});
+8 -1
View File
@@ -612,7 +612,7 @@ Espo.define('views/record/detail', ['views/record/base', 'view-record-helper'],
this.recordHelper = new ViewRecordHelper(this.defaultFieldStates, this.defaultFieldStates);
var collection = this.model.collection;
var collection = this.collection = this.model.collection;
if (collection) {
this.listenTo(this.model, 'destroy', function () {
collection.remove(this.model.id);
@@ -1174,6 +1174,13 @@ Espo.define('views/record/detail', ['views/record/base', 'view-record-helper'],
if (this.returnUrl) {
url = this.returnUrl;
} else {
if (after) {
var methodName = 'exitAfter' + Espo.Utils.upperCaseFirst(after);
if (methodName in this) {
this[methodName]();
return;
}
}
if (after == 'delete') {
this.getRouter().dispatch(this.scope, null, {
isReturn: true
+1 -1
View File
@@ -271,7 +271,7 @@ Espo.define('views/record/list', 'view', function (Dep) {
this.massActionsDisabled = this.options.massActionsDisabled || this.massActionsDisabled;
if (this.massActionsDisabled) {
if (this.massActionsDisabled && !this.selectable) {
this.checkboxes = false;
}
+8
View File
@@ -747,6 +747,10 @@ td.cell[data-name="buttons"] > .btn-group {
height: ~"calc(100% - 29px)";
}
}
.grid-stack-item-content {
overflow-x: visible;
overflow-y: visible;
}
}
.ui-resizable-handle:before {
@@ -1334,6 +1338,10 @@ h5 {
position: relative;
}
code {
font-style: italic;
}
@media screen and (min-width: @screen-sm-min) {
#global-search-panel {
margin-top: 5px;
+6 -1
View File
@@ -6,7 +6,6 @@
@font-family-base: @font-family-sans-serif;
@headings-font-family: @font-family-base;
@border-radius-base: 0;
@border-radius-large: 0;
@border-radius-small: 0;
@@ -57,6 +56,12 @@
@btn-default-bg: @main-gray;
@btn-default-border: @main-gray;
@code-bg: @main-gray;
@code-color: @text-color;
@pre-border-color: @main-gray;
@pre-bg: @main-gray;
@btn-success-border: @btn-success-bg;
@btn-primary-border: @btn-primary-bg;
@btn-danger-border: @btn-danger-bg;