Compare commits

...

51 Commits

Author SHA1 Message Date
yuri 0a0f8da2f4 fix auth for 5.5 2015-10-22 10:41:07 +03:00
yuri bb5d5a0ccf text filter default search by email address 2015-10-21 17:14:57 +03:00
yuri 1bd5eac103 ver 2015-10-21 10:09:21 +03:00
yuri 61957e628b fix optOut 2015-10-21 10:07:15 +03:00
yuri c5296bf906 typo 2015-10-20 17:52:26 +03:00
yuri a16919f10b fix typo 2015-10-20 17:38:04 +03:00
yuri 7050757e4e fix campaign type 2015-10-20 17:22:52 +03:00
yuri d27e9c91e7 import: dont import if no fields 2015-10-20 15:47:42 +03:00
yuri 5e1c7bce33 leads actual filter 2015-10-20 15:38:25 +03:00
yuri a23ac54da0 email template: translate enum 2015-10-20 15:32:01 +03:00
yuri 260c050f36 fix email address 2 2015-10-20 13:01:14 +03:00
yuri fc5c07927f fix email address case 2015-10-20 12:57:42 +03:00
yuri d321f0d701 email invitees duplicates 2015-10-20 12:32:50 +03:00
yuri 95cbc138f7 meeting/call/task and converted leads 2015-10-20 12:27:05 +03:00
yuri 395063ea35 order global search 2015-10-20 11:42:16 +03:00
yuri 835f95eb52 email template list layout 2015-10-20 11:29:05 +03:00
yuri c0f6c91a0e fix email draft 2015-10-20 11:26:09 +03:00
yuri b410d0e66f todays task 2015-10-19 17:43:32 +03:00
yuri d04f72cfd8 vers 2015-10-19 16:14:44 +03:00
yuri a9203b8e22 fix global search 2015-10-19 16:13:52 +03:00
yuri e89c7c9328 email filter improvement 2015-10-19 15:36:22 +03:00
yuri 7808865080 import csv label 2015-10-19 15:27:09 +03:00
yuri 404e2de3b6 fix email isRead 2015-10-16 17:19:51 +03:00
yuri f02dabc540 industry list 2015-10-16 13:50:42 +03:00
yuri c29da46a97 fix client side access denied 2015-10-16 13:07:37 +03:00
yuri b7702d2418 order fields in entity manager 2015-10-16 12:40:15 +03:00
yuri 2bc56db4c6 fix edit view link to detail 2015-10-16 12:33:59 +03:00
yuri dd0ef5455e fix 2015-10-16 10:40:45 +03:00
yuri 901bee6d3f fix campaign 2015-10-15 11:52:25 +03:00
yuri 72a0415207 fix orderBy by alias 2015-10-14 13:03:08 +03:00
yuri de69652137 fix id in model.set 2015-10-14 11:35:21 +03:00
yuri 1cd2d6b35e target lists field not importable 2015-10-12 10:43:50 +03:00
yuri 9888ec8a6f fix global searct 2015-10-12 10:30:16 +03:00
yuri ea5321577a fix target list import 2015-10-08 17:55:48 +03:00
yuri 23c772e029 fix config 2015-10-07 16:53:22 +03:00
yuri e67387d9ea additionalSelectColumns 2015-10-07 15:00:03 +03:00
yuri 2156094407 cleanup 2015-10-07 12:21:59 +03:00
yuri 03d5bf1ef2 tree impr 2015-10-07 12:18:01 +03:00
yuri 42f57409c8 list tree imp 2015-10-07 12:08:11 +03:00
yuri 69d7ce408d fix preferences layout 2015-10-07 11:24:52 +03:00
yuri 15b3c0440c lead converted panel change 2015-10-07 10:56:56 +03:00
yuri e1f0715c4d email import: relate to converted entity if lead is converted 2015-10-07 10:35:07 +03:00
yuri 15aec72e97 fix double quick view 2015-10-07 10:33:47 +03:00
yuri 66eade5db7 v 2015-10-07 10:20:37 +03:00
yuri 3d89e25349 label 2015-10-05 14:36:52 +03:00
yuri 7c890aa83a fix empty tablist 2015-10-02 17:23:02 +03:00
yuri 62a29c86ab fix record controller 2015-10-02 15:27:34 +03:00
yuri bd57b6bb8e detailLayout param 2 2015-10-02 15:10:13 +03:00
yuri 9ab1d16ea0 detailLayout param 2015-10-02 15:09:39 +03:00
yuri 435aa28ca2 iconHtml for menu items 2015-10-01 13:11:05 +03:00
yuri 4bd375f154 fix notice 2015-09-30 17:22:15 +03:00
74 changed files with 424 additions and 161 deletions
@@ -29,7 +29,7 @@ class GlobalSearch extends \Espo\Core\Controllers\Base
{
public function actionSearch($params, $data, $request)
{
$query = $params['query'];
$query = $request->get('q');
$offset = intval($request->get('offset'));
$maxSize = intval($request->get('maxSize'));
@@ -170,6 +170,7 @@ class Record extends Base
$asc = $request->get('asc') === 'true';
$sortBy = $request->get('sortBy');
$q = $request->get('q');
$textFilter = $request->get('textFilter');
if (empty($maxSize)) {
$maxSize = self::MAX_SIZE_LIMIT;
@@ -36,7 +36,7 @@ class FiltersMatcher
{
foreach ($filterList as $filter) {
if ($filter->get('from')) {
if (strtolower($filter->get('from')) === strtolower($email->get('from'))) {
if ($this->matchString(strtolower($filter->get('from')), strtolower($email->get('from')))) {
return true;
}
}
@@ -44,7 +44,7 @@ class FiltersMatcher
if ($email->get('to')) {
$toArr = explode(';', $email->get('to'));
foreach ($toArr as $to) {
if (strtolower($to) === strtolower($filter->get('to'))) {
if ($this->matchString(strtolower($filter->get('to')), strtolower($to))) {
return true;
}
}
+22
View File
@@ -194,6 +194,28 @@ class Importer
$n = sscanf($reference, '%s %s %d %d espo', $parentType, $parentId, $emailSent, $number);
if ($n == 4 && $emailSent < time()) {
if (!empty($parentType) && !empty($parentId)) {
if ($parentType == 'Lead') {
$parent = $this->getEntityManager()->getEntity('Lead', $parentId);
if ($parent && $parent->get('status') == 'Converted') {
if ($parent->get('createdAccountId')) {
$account = $this->getEntityManager()->getEntity('Account', $parent->get('createdAccountId'));
if ($account) {
$parentType = 'Account';
$parentId = $account->id;
}
} else {
if ($this->getConfig()->get('b2cMode')) {
if ($parent->get('createdContactId')) {
$contact = $this->getEntityManager()->getEntity('Contact', $parent->get('createdContactId'));
if ($contact) {
$parentType = 'Contact';
$parentId = $contact->id;
}
}
}
}
}
}
$email->set('parentType', $parentType);
$email->set('parentId', $parentId);
$parentFound = true;
@@ -795,7 +795,7 @@ class Base
foreach ($fieldList as $field) {
if (
strlen($item['value']) >= self::MIN_LENGTH_FOR_CONTENT_SEARCH
strlen($textFilter) >= self::MIN_LENGTH_FOR_CONTENT_SEARCH
&&
!empty($fieldDefs[$field]['type']) && $fieldDefs[$field]['type'] == 'text'
) {
+4 -1
View File
@@ -55,7 +55,10 @@ class Auth extends \Slim\Middleware
}
$espoCgiAuth = $req->headers('HTTP_ESPO_CGI_AUTH');
if ( !isset($authUsername) && !isset($authPassword) && !empty($espoCgiAuth) ) {
if (empty($espoCgiAuth)) {
$espoCgiAuth = $req->headers('REDIRECT_HTTP_ESPO_CGI_AUTH');
}
if (!isset($authUsername) && !isset($authPassword) && !empty($espoCgiAuth)) {
list($authUsername, $authPassword) = explode(':' , base64_decode(substr($espoCgiAuth, 6)));
}
+12 -2
View File
@@ -150,7 +150,17 @@ class Config
$removeData = empty($this->removeData) ? null : $this->removeData;
$result = $this->getFileManager()->mergePhpContents($this->configPath, $values, $removeData);
$data = include($this->configPath);
foreach ($values as $key => $value) {
$data[$key] = $value;
}
foreach ($removeData as $key) {
unset($data[$key]);
}
$result = $this->getFileManager()->putPhpContents($this->configPath, $data);
if ($result) {
$this->changedData = array();
@@ -220,7 +230,7 @@ class Config
$restrictItems = $this->getRestrictItems($isAdmin);
$values = array();
foreach($data as $key => $item) {
foreach ($data as $key => $item) {
if (!in_array($key, $restrictItems)) {
$values[$key]= $item;
}
+3 -4
View File
@@ -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\Entities;
@@ -33,7 +33,6 @@ class EmailAddress extends \Espo\Core\ORM\Entity
throw new Error("Not valid email address '{$value}'");
}
$this->valuesContainer['name'] = $value;
$this->set('lower', strtolower($value));
}
$this->set('lower', strtolower($value));
}
}
@@ -75,11 +75,8 @@ class Unsubscribe extends \Espo\Core\EntryPoints\Base
$link = $m[$target->getEntityType()];
}
if ($link) {
if ($campaign) {
$targetListList = $campaign->get('targetLists');
} else {
$targetListList = $massEmail->get('targetLists');
}
$targetListList = $massEmail->get('targetLists');
foreach ($targetListList as $targetList) {
$this->getEntityManager()->getRepository('TargetList')->updateRelation($targetList, $link, $target->id, array(
'optedOut' => true
@@ -45,7 +45,7 @@ class Contact extends \Espo\Core\ORM\Repositories\RDB
$result = parent::afterSave($entity, $options);
$this->handleAfterSaveAccounts($entity, $options);
if ($entity->has('targetListId') && $entity->isNew()) {
if ($entity->has('targetListId')) {
$this->relate($entity, 'targetLists', $entity->get('targetListId'));
}
@@ -35,10 +35,17 @@ class Meeting extends \Espo\Core\ORM\Repositories\RDB
if (!empty($parentId) || !empty($parentType)) {
$parent = $this->getEntityManager()->getEntity($parentType, $parentId);
if (!empty($parent)) {
$accountId = null;
if ($parent->getEntityType() == 'Account') {
$accountId = $parent->id;
} else if ($parent->has('accountId')) {
} else if ($parent->get('accountId')) {
$accountId = $parent->get('accountId');
} else if ($parent->getEntityType() == 'Lead') {
if ($parent->get('status') == 'Converted') {
if ($parent->get('createdAccountId')) {
$accountId = $parent->get('createdAccountId');
}
}
}
if (!empty($accountId)) {
$entity->set('accountId', $accountId);
@@ -98,10 +98,17 @@ class Task extends \Espo\Core\ORM\Repositories\RDB
if (!empty($parentId) || !empty($parentType)) {
$parent = $this->getEntityManager()->getEntity($parentType, $parentId);
if (!empty($parent)) {
$accountId = null;
if ($parent->getEntityType() == 'Account') {
$accountId = $parent->id;
} else if ($parent->has('accountId')) {
} else if ($parent->get('accountId')) {
$accountId = $parent->get('accountId');
} else if ($parent->getEntityType() == 'Lead') {
if ($parent->get('status') == 'Converted') {
if ($parent->get('createdAccountId')) {
$accountId = $parent->get('createdAccountId');
}
}
}
if (!empty($accountId)) {
$entity->set('accountId', $accountId);
@@ -56,6 +56,7 @@
},
"presetFilters": {
"active": "Aktiv",
"actual": "Tatsächlich",
"converted": "Umgewandelt"
}
}
@@ -40,6 +40,7 @@
"Automotive": "Automotive",
"Banking": "Banking",
"Biotechnology": "Biotechnology",
"Building Materials & Equipment": "Building Materials & Equipment",
"Chemical": "Chemical",
"Computer": "Computer",
"Education": "Education",
@@ -56,6 +56,7 @@
},
"presetFilters": {
"active": "Active",
"actual": "Actual",
"converted": "Converted"
}
}
@@ -50,6 +50,7 @@
}
},
"presetFilters": {
"active": "Actif"
"active": "Actif",
"actual": "En cours"
}
}
@@ -45,6 +45,7 @@
}
},
"presetFilters": {
"actual": "Werkelijke",
"active": "Actief"
}
}
@@ -48,6 +48,7 @@
}
},
"presetFilters": {
"actual": "Atual",
"active": "Ativo"
}
}
@@ -45,6 +45,7 @@
}
},
"presetFilters": {
"active": "Активный"
"actual": "Актуальные",
"active": "Активные"
}
}
@@ -30,8 +30,8 @@
"Complete": "Завершить"
},
"presetFilters": {
"actual": "Actual",
"completed": "Завершена",
"actual": "Актуальные",
"completed": "Завершенные",
"todays": "На сегодня",
"overdue": "Просроченные"
}
@@ -24,7 +24,8 @@
{
"name":"statistics",
"label":"Statistics",
"view":"Crm:Campaign.Record.Panels.Statistics"
"view":"Crm:Campaign.Record.Panels.Statistics",
"hidden": true
}
]
},
@@ -29,12 +29,9 @@
{
"name":"convertedTo",
"label":"Converted To",
"view": "Record.Panels.Side",
"view": "crm:views/lead/record/panels/converted-to",
"notRefreshable": true,
"hidden": true,
"options": {
"fieldList": ["createdAccount", "createdContact", "createdOpportunity"]
}
"hidden": true
},
{
"name":"activities",
@@ -51,6 +48,33 @@
"label":"Tasks",
"view":"Crm:Record.Panels.Tasks"
}
],
"edit": [
{
"name":"convertedTo",
"label":"Converted To",
"view": "crm:views/lead/record/panels/converted-to",
"notRefreshable": true,
"hidden": true
}
],
"detailSmall": [
{
"name":"convertedTo",
"label":"Converted To",
"view": "crm:views/lead/record/panels/converted-to",
"notRefreshable": true,
"hidden": true
}
],
"editSmall": [
{
"name":"convertedTo",
"label":"Converted To",
"view": "crm:views/lead/record/panels/converted-to",
"notRefreshable": true,
"hidden": true
}
]
},
"relationshipPanels": {
@@ -66,7 +90,7 @@
},
"filterList": [
{
"name":"active"
"name":"actual"
},
{
"name":"converted",
@@ -30,6 +30,7 @@
"Automotive",
"Banking",
"Biotechnology",
"Building Materials & Equipment",
"Chemical",
"Computer",
"Education",
@@ -47,7 +48,7 @@
"Real Estate",
"Service",
"Sports",
"Sofware",
"Software",
"Technology",
"Telecommunications",
"Television",
@@ -11,7 +11,8 @@
},
"type": {
"type": "enum",
"options": ["Email", "Newsletter", "Web", "Television", "Radio", "Mail"]
"options": ["Email", "Newsletter", "Web", "Television", "Radio", "Mail"],
"default": "Email"
},
"startDate": {
"type": "date"
@@ -131,6 +131,7 @@
"layoutDetailDisabled": true,
"layoutListDisabled": true,
"layoutMassUpdateDisabled": true,
"importDisabled": true,
"noLoad": true
},
"targetList": {
@@ -237,7 +238,8 @@
},
"collection": {
"sortBy": "name",
"asc": true
"asc": true,
"textFilterFields": ["name", "emailAddress"]
},
"indexes": {
"firstName": {
@@ -255,7 +255,7 @@
"collection": {
"sortBy": "createdAt",
"asc": false,
"textFilterFields": ["name", "accountName"]
"textFilterFields": ["name", "accountName", "emailAddress"]
},
"indexes": {
"firstName": {
@@ -31,6 +31,13 @@ class Lead extends \Espo\Core\SelectManagers\Base
);
}
protected function filterActual(&$result)
{
$result['whereClause'][] = array(
'status!=' => ['Converted', 'Recycled', 'Dead']
);
}
protected function filterConverted(&$result)
{
$result['whereClause'][] = array(
@@ -71,6 +71,15 @@ class Task extends \Espo\Core\SelectManagers\Base
];
}
protected function filterTodays(&$result)
{
$result['whereClause'][] = $this->convertDateTimeWhere(array(
'type' => 'today',
'field' => 'dateEnd',
'timeZone' => $this->getUserTimeZone()
));
}
protected function convertDateTimeWhere($item)
{
$result = parent::convertDateTimeWhere($item);
@@ -243,10 +243,10 @@ class MassEmail extends \Espo\Services\Record
$this->setFailed($massEmail);
return;
}
$attachmetList = $emailTemplate->get('attachmets');
$attachmentList = $emailTemplate->get('attachments');
foreach ($queueItemList as $queueItem) {
$this->sendQueueItem($queueItem, $massEmail, $emailTemplate, $attachmetList, $campaign, $isTest);
$this->sendQueueItem($queueItem, $massEmail, $emailTemplate, $attachmentList, $campaign, $isTest);
}
if (!$isTest) {
@@ -328,7 +328,7 @@ class MassEmail extends \Espo\Services\Record
return $email;
}
protected function sendQueueItem(Entity $queueItem, Entity $massEmail, Entity $emailTemplate, $attachmetList = [], $campaign = null, $isTest = false)
protected function sendQueueItem(Entity $queueItem, Entity $massEmail, Entity $emailTemplate, $attachmentList = [], $campaign = null, $isTest = false)
{
$target = $this->getEntityManager()->getEntity($queueItem->get('targetType'), $queueItem->get('targetId'));
if (!$target || !$target->id || !$target->get('emailAddress')) {
@@ -379,7 +379,7 @@ class MassEmail extends \Espo\Services\Record
$header->setId($queueItem->id);
$message->getHeaders()->addHeader($header);
$this->getMailSender()->useGlobal()->send($email, $params, $message, $attachmetList);
$this->getMailSender()->useGlobal()->send($email, $params, $message, $attachmentList);
$emailObject = $emailTemplate;
if ($massEmail->get('storeSentEmails')) {
@@ -399,7 +399,6 @@ class MassEmail extends \Espo\Services\Record
} catch (\Exception $e) {
if ($queueItem->get('attemptCount') >= self::MAX_ATTEMPT_COUNT) {
$this->setQueueItemFailed($queueItem);
$queueItem->set('status', 'Failed');
}
$this->getEntityManager()->saveEntity($queueItem);
@@ -81,19 +81,30 @@ class Meeting extends \Espo\Services\Record
{
$invitationManager = $this->getInvitationManager();
$emailHash = array();
$users = $entity->get('users');
foreach ($users as $user) {
$invitationManager->sendInvitation($entity, $user, 'users');
if ($user->get('emailAddress') && !array_key_exists($user->get('emailAddress'), $emailHash)) {
$invitationManager->sendInvitation($entity, $user, 'users');
$emailHash[$user->get('emailAddress')] = true;
}
}
$contacts = $entity->get('contacts');
foreach ($contacts as $contact) {
$invitationManager->sendInvitation($entity, $contact, 'contacts');
if ($contact->get('emailAddress') && !array_key_exists($contact->get('emailAddress'), $emailHash)) {
$invitationManager->sendInvitation($entity, $contact, 'contacts');
$emailHash[$user->get('emailAddress')] = true;
}
}
$leads = $entity->get('leads');
foreach ($leads as $lead) {
$invitationManager->sendInvitation($entity, $lead, 'leads');
if ($lead->get('emailAddress') && !array_key_exists($lead->get('emailAddress'), $emailHash)) {
$invitationManager->sendInvitation($entity, $lead, 'leads');
$emailHash[$user->get('emailAddress')] = true;
}
}
return true;
+7 -1
View File
@@ -113,6 +113,12 @@ abstract class Base
}
}
if (!empty($params['additionalSelectColumns']) && is_array($params['additionalSelectColumns'])) {
foreach ($params['additionalSelectColumns'] as $column => $field) {
$selectPart .= ", " . $column . " AS `{$field}`";
}
}
} else {
$aggDist = false;
if ($params['distinct'] && $params['aggregation'] == 'COUNT') {
@@ -427,7 +433,7 @@ abstract class Base
{
if (strpos($orderBy, '.') !== false) {
list($alias, $field) = explode('.', $orderBy);
$fieldPath = $this->toDb($alias) . '.' . $this->toDb($this->sanitize($field));
$fieldPath = $this->sanitize($alias) . '.' . $this->toDb($this->sanitize($field));
} else {
$fieldPath = $this->getFieldPath($entity, $orderBy);
}
+18 -5
View File
@@ -65,7 +65,7 @@ class EmailAddress extends \Espo\Core\ORM\Repositories\RDB
$pdo = $this->getEntityManager()->getPDO();
$sql = "
SELECT email_address.name, email_address.invalid, email_address.opt_out AS optOut, entity_email_address.primary
SELECT email_address.name, email_address.lower, email_address.invalid, email_address.opt_out AS optOut, entity_email_address.primary
FROM entity_email_address
JOIN email_address ON email_address.id = entity_email_address.email_address_id AND email_address.deleted = 0
WHERE
@@ -80,6 +80,7 @@ class EmailAddress extends \Espo\Core\ORM\Repositories\RDB
foreach ($rows as $row) {
$obj = new \StdClass();
$obj->emailAddress = $row['name'];
$obj->lower = $row['lower'];
$obj->primary = ($row['primary'] == '1') ? true : false;
$obj->optOut = ($row['optOut'] == '1') ? true : false;
$obj->invalid = ($row['invalid'] == '1') ? true : false;
@@ -180,22 +181,25 @@ class EmailAddress extends \Espo\Core\ORM\Repositories\RDB
foreach ($emailAddressData as $row) {
$key = $row->emailAddress;
if (!empty($key)) {
$key = strtolower($key);
$hash[$key] = array(
'primary' => $row->primary ? true : false,
'optOut' => $row->optOut ? true : false,
'invalid' => $row->invalid ? true : false,
'emailAddress' => $row->emailAddress
);
}
}
$hashPrev = array();
foreach ($previousEmailAddressData as $row) {
$key = $row->emailAddress;
$key = $row->lower;
if (!empty($key)) {
$hashPrev[$key] = array(
'primary' => $row->primary ? true : false,
'optOut' => $row->optOut ? true : false,
'invalid' => $row->invalid ? true : false,
'emailAddress' => $row->emailAddress
);
}
}
@@ -216,7 +220,10 @@ class EmailAddress extends \Espo\Core\ORM\Repositories\RDB
if (array_key_exists($key, $hashPrev)) {
$new = false;
$changed = $hash[$key]['optOut'] != $hashPrev[$key]['optOut'] || $hash[$key]['invalid'] != $hashPrev[$key]['invalid'];
$changed =
$hash[$key]['optOut'] != $hashPrev[$key]['optOut'] ||
$hash[$key]['invalid'] != $hashPrev[$key]['invalid'] ||
$hash[$key]['emailAddress'] !== $hashPrev[$key]['emailAddress'];
if ($hash[$key]['primary']) {
if ($hash[$key]['primary'] == $hashPrev[$key]['primary']) {
$primary = false;
@@ -259,6 +266,7 @@ class EmailAddress extends \Espo\Core\ORM\Repositories\RDB
$emailAddress->set(array(
'optOut' => $hash[$address]['optOut'],
'invalid' => $hash[$address]['invalid'],
'name' => $hash[$address]['emailAddress']
));
$this->save($emailAddress);
}
@@ -270,16 +278,21 @@ class EmailAddress extends \Espo\Core\ORM\Repositories\RDB
$emailAddress = $this->get();
$emailAddress->set(array(
'name' => $address,
'name' => $hash[$address]['emailAddress'],
'optOut' => $hash[$address]['optOut'],
'invalid' => $hash[$address]['invalid'],
));
$this->save($emailAddress);
} else {
if ($emailAddress->get('optOut') != $hash[$address]['optOut'] || $emailAddress->get('invalid') != $hash[$address]['invalid']) {
if (
$emailAddress->get('optOut') != $hash[$address]['optOut'] ||
$emailAddress->get('invalid') != $hash[$address]['invalid'] ||
$emailAddress->get('emailAddress') != $hash[$address]['emailAddress']
) {
$emailAddress->set(array(
'optOut' => $hash[$address]['optOut'],
'invalid' => $hash[$address]['invalid'],
'name' => $hash[$address]['emailAddress']
));
$this->save($emailAddress);
}
@@ -18,7 +18,8 @@
"Create Only": "Nur erstellen",
"Create and Update": "Erstellen und aktualisieren",
"Update Only": "Nur aktualisieren",
"Update by": "Aktualisieren durch"
"Update by": "Aktualisieren durch",
"File (CSV)": "Datei (CSV)"
},
"messages": {
"utf8": "Sollte UTF-8 kodiert sein",
@@ -12,8 +12,8 @@
"name": "Just a name of the filter.",
"subject": "Use wildcard *:\n\ntext* - starts with text,\n*text* - contains text,\n*text - ends with text.",
"bodyContains": "Body of email contains any of specified words or phrases.",
"from": "Emails being sent from the specified address. Leave empty if not needed.",
"to": "Emails being sent to the specified address. Leave empty if not needed.",
"from": "Emails being sent from the specified address. Leave empty if not needed. You can use wildcard *.",
"to": "Emails being sent to the specified address. Leave empty if not needed. You can use wildcard *.",
"parent": "Leave it empty to apply this filter globally (to all incoming emails)."
}
}
@@ -39,6 +39,7 @@
},
"messages": {
"entityCreated": "Entity has been created",
"linkAlreadyExists": "Link name conflict."
"linkAlreadyExists": "Link name conflict.",
"linkConflict": "Link with the same name already exists."
}
}
@@ -18,7 +18,8 @@
"Create Only": "Create Only",
"Create and Update": "Create & Update",
"Update Only": "Update Only",
"Update by": "Update by"
"Update by": "Update by",
"File (CSV)": "File (CSV)"
},
"messages": {
"utf8": "Should be UTF-8 encoded",
@@ -1,3 +1,4 @@
[
{"name": "name", "width": 90, "link": true}
{"name": "name", "link": true},
{"name": "assignedUser", "width": 20}
]
@@ -0,0 +1,4 @@
[
{"name": "name", "link": true},
{"name": "assignedUser", "width": 30}
]
@@ -43,10 +43,6 @@
{
"name": "defaultReminders"
}
],
[
{"name":"theme"},
false
]
]
},
@@ -9,12 +9,14 @@
"from": {
"type": "varchar",
"maxLength": 255,
"tooltip": true
"tooltip": true,
"trim": true
},
"to": {
"type": "varchar",
"maxLength": 255,
"tooltip": true
"tooltip": true,
"trim": true
},
"subject": {
"type": "varchar",
+2 -3
View File
@@ -87,12 +87,11 @@
},
{
"route":"/GlobalSearch/:query",
"route":"/GlobalSearch",
"method":"get",
"params":{
"controller":"GlobalSearch",
"action":"search",
"query": ":query"
"action":"search"
}
},
+16 -5
View File
@@ -36,6 +36,7 @@ class EmailTemplate extends Record
{
$this->dependencies[] = 'fileManager';
$this->dependencies[] = 'dateTime';
$this->dependencies[] = 'language';
}
protected function getFileManager()
@@ -48,6 +49,11 @@ class EmailTemplate extends Record
return $this->injections['dateTime'];
}
protected function getLanguage()
{
return $this->getInjection('language');
}
public function parseTemplate(Entity $emailTemplate, array $params = array(), $copyAttachments = false)
{
$entityHash = array();
@@ -154,17 +160,22 @@ class EmailTemplate extends Record
protected function parseText($type, Entity $entity, $text)
{
$fieldList = array_keys($entity->getFields());
$fieldList[] = $id;
foreach ($fieldList as $field) {
$value = $entity->get($field);
if (is_object($value)) {
continue;
}
if ($entity->fields[$field]['type'] == 'date') {
$value = $this->getDateTime()->convertSystemDateToGlobal($value);
} else if ($entity->fields[$field]['type'] == 'datetime') {
$value = $this->getDateTime()->convertSystemDateTimeToGlobal($value);
$fieldType = $this->getMetadata()->get('entityDefs.' . $entity->getEntityType() .'.fields.' . $field . '.type');
if ($fieldType === 'enum') {
$value = $this->getLanguage()->translateOption($value, $field, $entity->getEntityType());
} else {
if ($entity->fields[$field]['type'] == 'date') {
$value = $this->getDateTime()->convertSystemDateToGlobal($value);
} else if ($entity->fields[$field]['type'] == 'datetime') {
$value = $this->getDateTime()->convertSystemDateTimeToGlobal($value);
}
}
$text = str_replace('{' . $type . '.' . $field . '}', $value, $text);
}
+9 -1
View File
@@ -95,7 +95,15 @@ class GlobalSearch extends \Espo\Core\Services\Base
$row = $sth->fetch(\PDO::FETCH_ASSOC);
$totalCount = $row['COUNT'];
$unionSql .= " ORDER BY name";
if (count($entityTypeList)) {
$entityListQuoted = [];
foreach ($entityTypeList as $entityType) {
$entityListQuoted[] = $pdo->quote($entityType);
}
$unionSql .= " ORDER BY FIELD(entityType, ".implode(', ', $entityListQuoted)."), name";
} else {
$unionSql .= " ORDER BY name";
}
$unionSql .= " LIMIT :offset, :maxSize";
$sth = $pdo->prepare($unionSql);
+13 -9
View File
@@ -257,7 +257,7 @@ class Import extends \Espo\Services\Record
return true;
}
public function import($scope, array $fields, $attachmentId, array $params = array())
public function import($scope, array $importFieldList, $attachmentId, array $params = array())
{
$delimiter = ',';
if (!empty($params['fieldDelimiter'])) {
@@ -297,7 +297,7 @@ class Import extends \Espo\Services\Record
if (count($arr) == 1 && empty($arr[0])) {
continue;
}
$r = $this->importRow($scope, $fields, $arr, $params);
$r = $this->importRow($scope, $importFieldList, $arr, $params);
if (empty($r)) {
continue;
}
@@ -334,7 +334,7 @@ class Import extends \Espo\Services\Record
);
}
public function importRow($scope, array $fields, array $row, array $params = array())
public function importRow($scope, array $importFieldList, array $row, array $params = array())
{
$id = null;
$action = 'create';
@@ -342,15 +342,19 @@ class Import extends \Espo\Services\Record
$action = $params['action'];
}
if (empty($importFieldList)) {
return;
}
if (in_array($action, ['createAndUpdate', 'update'])) {
if (!empty($params['updateBy']) && is_array($params['updateBy'])) {
$updateByFieldList = [];
$whereClause = array();
foreach ($params['updateBy'] as $i) {
if (array_key_exists($i, $fields)) {
$updateByFieldList[] = $fields[$i];
$whereClause[$fields[$i]] = $row[$i];
if (array_key_exists($i, $importFieldList)) {
$updateByFieldList[] = $importFieldList[$i];
$whereClause[$importFieldList[$i]] = $row[$i];
}
}
}
@@ -399,7 +403,7 @@ class Import extends \Espo\Services\Record
}
}
foreach ($fields as $i => $field) {
foreach ($importFieldList as $i => $field) {
if (!empty($field)) {
$value = $row[$i];
if ($field == 'id') {
@@ -457,7 +461,7 @@ class Import extends \Espo\Services\Record
$isPrimary = false;
if (empty($phoneNumberData)) {
$phoneNumberData = [];
if (!in_array('phoneNumber', $fields)) {
if (!in_array('phoneNumber', $importFieldList)) {
$isPrimary = true;
}
}
@@ -475,7 +479,7 @@ class Import extends \Espo\Services\Record
}
}
foreach ($fields as $i => $field) {
foreach ($importFieldList as $i => $field) {
if (array_key_exists($field, $fieldsDefs) && $fieldsDefs[$field]['type'] == Entity::FOREIGN) {
if ($entity->has($field)) {
$relation = $fieldsDefs[$field]['relation'];
@@ -30,7 +30,6 @@
this.menu.buttons.push({
'label': 'Send Invitations',
'action': 'sendInvitations',
icon: 'glyphicon glyphicon-send',
'acl': 'edit',
});
}
@@ -56,7 +56,7 @@ Espo.define('Crm:Views.Dashlets.Leads', 'Views.Dashlets.Abstract.RecordList', fu
bool: {
onlyMy: true,
},
primary: 'active'
primary: 'actual'
},
},
@@ -25,31 +25,6 @@ Espo.define('Crm:Views.Lead.Record.DetailSide', 'Views.Record.DetailSide', funct
setupPanels: function () {
/*var panel = {
name: 'convertedTo',
label: 'Converted To',
view: 'Record.Panels.Side',
notRefreshable: true,
options: {
fieldList: [],
mode: 'detail',
}
};
panel.options.fieldList.push('createdAccount');
panel.options.fieldList.push('createdContact');
panel.options.fieldList.push('createdOpportunity');
this.panels = Espo.Utils.clone(this.panels);
this.panels.splice(1, 0, panel);*/
}
});
@@ -0,0 +1,45 @@
/************************************************************************
* 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('crm:views/lead/record/panels/converted-to', 'views/record/panels/side', function (Dep) {
return Dep.extend({
setup: function () {
this.fieldList = [];
if (this.getAcl().check('Account')) {
this.fieldList.push('createdAccount');
}
if (this.getAcl().check('Contact')) {
this.fieldList.push('createdContact');
}
if (this.getAcl().check('Opportunity')) {
this.fieldList.push('createdOpportunity');
}
Dep.prototype.setup.call(this);
}
});
});
@@ -29,7 +29,7 @@ Espo.define('crm:views/mass-email/record/row-actions/for-campaign', 'views/recor
if (this.options.acl.edit && !~['Complete'].indexOf(this.model.get('status'))) {
actionList.unshift({
action: 'sendTest',
label: 'Sent Test',
label: 'Send Test',
data: {
id: this.model.id
}
@@ -30,7 +30,6 @@ Espo.define('Crm:Views.Meeting.Detail', 'Views.Detail', function (Dep) {
this.menu.buttons.push({
'label': 'Send Invitations',
'action': 'sendInvitations',
icon: 'glyphicon glyphicon-send',
'acl': 'edit',
});
}
@@ -30,7 +30,7 @@ Espo.define('Crm:Views.Task.Detail', 'Views.Detail', function (Dep) {
this.menu.buttons.push({
'label': 'Complete',
'action': 'setCompleted',
icon: 'glyphicon glyphicon-ok',
'iconHtml': '<span class="glyphicon glyphicon-ok"></span>',
'acl': 'edit',
});
}
+2 -1
View File
@@ -6,6 +6,7 @@
<div class="header-buttons btn-group pull-right">
{{#each items.buttons}}
<a {{#if link}}href="{{link}}"{{else}}href="javascript:"{{/if}} class="btn btn-{{#if style}}{{style}}{{else}}default{{/if}} action{{#if hidden}} hidden{{/if}}" data-action="{{name}}"{{#each data}} data-{{@key}}="{{./this}}"{{/each}}>
{{#if iconHtml}}{{{iconHtml}}}{{/if}}
{{#if html}}{{{html}}}{{else}}{{translate label scope=../../scope}}{{/if}}
</a>
{{/each}}
@@ -30,7 +31,7 @@
</button>
<ul class="dropdown-menu pull-right">
{{#each items.dropdown}}
<li class="{{#if hidden}}hidden{{/if}}"><a {{#if link}}href="{{link}}"{{else}}href="javascript:"{{/if}} class="action" data-action="{{name}}"{{#each data}} data-{{@key}}="{{./this}}"{{/each}}>{{#if html}}{{{html}}}{{else}}{{translate label scope=../../../scope}}{{/if}}</a></li>
<li class="{{#if hidden}}hidden{{/if}}"><a {{#if link}}href="{{link}}"{{else}}href="javascript:"{{/if}} class="action" data-action="{{name}}"{{#each data}} data-{{@key}}="{{./this}}"{{/each}}>{{#if iconHtml}}{{{iconHtml}}} {{/if}}{{#if html}}{{{html}}}{{else}}{{translate label scope=../../../scope}}{{/if}}</a></li>
{{/each}}
</ul>
</div>
@@ -13,7 +13,7 @@
</select>
</div>
<div class="col-sm-4 form-group">
<label class="control-label">{{translate 'File' scope='Import'}}</label>
<label class="control-label">{{translate 'File (CSV)' scope='Import'}}</label>
<div>
<input type="file" id="import-file">
</div>
+1 -1
View File
@@ -152,7 +152,7 @@ Espo.define('controller', [], function () {
handleAccessGlobal: function () {
if (!this.checkAccessGlobal()) {
throw new Espo.Exceptions.AccessDenied("Denied access to action '" + this.name + "#" + action + "'");
throw new Espo.Exceptions.AccessDenied("Denied access to '" + this.name + "'");
}
},
+12
View File
@@ -42,6 +42,18 @@ Espo.define('model', [], function () {
Dep.prototype.initialize.call(this);
},
set: function (key, val, options) {
if (typeof key === 'object') {
var o = key;
if (this.idAttribute in o) {
this.id = o[this.idAttribute];
}
} else if (key === 'id') {
this.id = val;
}
return Dep.prototype.set.call(this, key, val, options);
},
get: function (key) {
if (key === 'id' && this.id) {
return this.id;
@@ -142,7 +142,9 @@ Espo.define('views/admin/entity-manager/modals/edit-entity', ['views/modal', 'mo
return false;
}
return true;
}, this);
}, 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) {
+1 -1
View File
@@ -67,7 +67,7 @@ Espo.define('views/edit', 'views/main', function (Dep) {
if (this.options.noHeaderLinks) {
arr.push(name);
} else {
arr.push('<a href="#' + this.model.name + '/view/' + this.model.id + '" class="action" data-action="navigateToRoot">' + name + '</a>');
arr.push('<a href="#' + this.model.name + '/view/' + this.model.id + '" class="action">' + name + '</a>');
}
}
return this.buildHeaderHtml(arr);
+13
View File
@@ -255,6 +255,19 @@ Espo.define('views/email/detail', ['views/detail', 'email-helper'], function (De
this.model.set('status', 'Sent');
$send.remove();
this.menu = this.backedMenu;
if (record.mode !== 'detail') {
record.setDetailMode();
record.setFieldReadOnly('dateSent');
record.setFieldReadOnly('name');
record.setFieldReadOnly('attachments');
record.setFieldReadOnly('isHtml');
record.setFieldReadOnly('from');
record.setFieldReadOnly('to');
record.setFieldReadOnly('cc');
record.setFieldReadOnly('bcc');
}
}, this);
this.listenToOnce(record, 'cancel:save', function () {
@@ -58,7 +58,7 @@ Espo.define('views/email/record/detail', 'views/record/detail', function (Dep) {
if (!this.model.get('isRead')) {
this.model.set({
isRead: true
}, {silent: true});
});
}
}, this);
@@ -161,6 +161,10 @@ Espo.define('views/email/record/detail', 'views/record/detail', function (Dep) {
afterRender: function () {
Dep.prototype.afterRender.call(this);
if (this.model.get('status') === 'Draft') {
this.setFieldReadOnly('dateSent');
}
if (this.isRestricted) {
this.handleAttachmentField();
this.listenTo(this.model, 'change:attachmentsIds', function () {
@@ -55,6 +55,10 @@ Espo.define('views/email/record/edit', ['views/record/edit', 'views/email/record
afterRender: function () {
Dep.prototype.afterRender.call(this);
if (this.model.get('status') === 'Draft') {
this.setFieldReadOnly('dateSent');
}
this.handleAttachmentField();
this.listenTo(this.model, 'change:attachmentsIds', function () {
this.handleAttachmentField();
@@ -19,11 +19,11 @@
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
************************************************************************/
Espo.define('Views.GlobalSearch.GlobalSearch', 'View', function (Dep) {
Espo.define('views/global-search/global-search', 'view', function (Dep) {
return Dep.extend({
template: 'global-search.global-search',
template: 'global-search/global-search',
events: {
'keypress #global-search-input': function (e) {
@@ -57,13 +57,13 @@ Espo.define('Views.GlobalSearch.GlobalSearch', 'View', function (Dep) {
runSearch: function (text) {
var text = this.$input.val();
if (text != '' && text.length > 2) {
text = encodeURI(text);
text = text;
this.search(text);
}
},
search: function (text) {
this.collection.url = this.collection.urlRoot = 'GlobalSearch/' + text;
this.collection.url = this.collection.urlRoot = 'GlobalSearch?q=' + encodeURIComponent(text);
this.showPanel();
},
+1 -1
View File
@@ -19,7 +19,7 @@
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
************************************************************************/
Espo.define('Views.Import.Detail', 'Views.Detail', function (Dep) {
Espo.define('views/import/detail', 'views/detail', function (Dep) {
return Dep.extend({
+2 -2
View File
@@ -18,11 +18,11 @@
* 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.Import.Index', 'View', function (Dep) {
Espo.define('views/import/index', 'view', function (Dep) {
return Dep.extend({
template: 'import.index',
template: 'import/index',
data: function () {
return {
+1 -1
View File
@@ -19,7 +19,7 @@
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
************************************************************************/
Espo.define('Views.Import.List', 'Views.List', function (Dep) {
Espo.define('views/import/list', 'views/list', function (Dep) {
return Dep.extend({
+3 -2
View File
@@ -18,11 +18,12 @@
* 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.Import.Step1', 'View', function (Dep) {
Espo.define('views/import/step1', 'view', function (Dep) {
return Dep.extend({
template: 'import.step-1',
template: 'import/step-1',
events: {
'change #import-file': function (e) {
+3 -2
View File
@@ -18,11 +18,12 @@
* 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.Import.Step2', 'View', function (Dep) {
Espo.define('views/import/step2', 'view', function (Dep) {
return Dep.extend({
template: 'import.step-2',
template: 'import/step-2',
events: {
'click button[data-action="back"]': function () {
+14 -1
View File
@@ -34,6 +34,8 @@ Espo.define('views/record/detail', 'views/record/base', function (Dep) {
gridLayout: null,
detailLayout: null,
/**
* @property {string} or {bool} ['both', 'top', 'bottom', false, true] Where to display buttons.
*/
@@ -338,6 +340,8 @@ Espo.define('views/record/detail', 'views/record/base', function (Dep) {
this.layoutName = this.options.layoutName || this.layoutName;
this.detailLayout = this.options.detailLayout || this.detailLayout;
this.type = this.options.type || this.type;
this.buttons = this.options.buttons || this.buttons;
@@ -627,10 +631,19 @@ Espo.define('views/record/detail', 'views/record/base', function (Dep) {
return;
}
if (this.detailLayout) {
this.gridLayout = {
type: 'record',
layout: this.convertDetailLayout(this.detailLayout)
};
callback(this.gridLayout);
return;
}
this._helper.layoutManager.get(this.model.name, this.layoutName, function (simpleLayout) {
this.gridLayout = {
type: 'record',
layout: this.convertDetailLayout(simpleLayout),
layout: this.convertDetailLayout(simpleLayout)
};
callback(this.gridLayout);
}.bind(this));
@@ -19,16 +19,18 @@
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
************************************************************************/
Espo.define('Views.Record.ListTreeItem', 'View', function (Dep) {
Espo.define('views/record/list-tree-item', 'view', function (Dep) {
return Dep.extend({
template: 'record.list-tree-item',
template: 'record/list-tree-item',
isEnd: false,
level: 0,
listViewName: 'views/record/list-tree',
data: function () {
return {
name: this.model.get('name'),
@@ -120,7 +122,7 @@ Espo.define('Views.Record.ListTreeItem', 'View', function (Dep) {
view.render();
};
}
this.createView('children', 'Record.ListTree', {
this.createView('children', this.listViewName, {
collection: childCollection,
el: this.options.el + ' > .children',
createDisabled: this.options.createDisabled,
+18 -12
View File
@@ -19,11 +19,11 @@
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
************************************************************************/
Espo.define('Views.Record.ListTree', 'Views.Record.List', function (Dep) {
Espo.define('views/record/list-tree', 'views/record/list', function (Dep) {
return Dep.extend({
template: 'record.list-tree',
template: 'record/list-tree',
showMore: false,
@@ -53,6 +53,8 @@ Espo.define('Views.Record.ListTree', 'Views.Record.List', function (Dep) {
level: 0,
itemViewName: 'views/record/list-tree-item',
data: function () {
var data = Dep.prototype.data.call(this);
data.createDisabled = this.createDisabled;
@@ -151,7 +153,7 @@ Espo.define('Views.Record.ListTree', 'Views.Record.List', function (Dep) {
var built = 0;
modelList.forEach(function (model, i) {
this.rows.push('row-' + i);
this.createView('row-' + i, 'Record.ListTreeItem', {
this.createView('row-' + i, this.itemViewName, {
model: model,
collection: this.collection,
el: this.options.el + ' ' + this.getRowSelector(model.id),
@@ -186,14 +188,22 @@ Espo.define('Views.Record.ListTree', 'Views.Record.List', function (Dep) {
return this.options.el + ' li[data-id="' + model.id + '"] span.cell-' + item.name;
},
getCreateAttributes: function () {
return {};
},
actionCreate: function (data, e) {
e.stopPropagation();
var parentId = null;
var parentName = null;
var attributes = this.getCreateAttributes();
attributes.order = this.collection.length + 1;
attributes.parentId = null;
attributes.parentName = null;
if (this.model) {
parentId = this.model.id;
parentName = this.model.get('name');
attributes.parentId = this.model.id;
attributes.parentName = this.model.get('name');
}
var scope = this.collection.name;
@@ -201,11 +211,7 @@ Espo.define('Views.Record.ListTree', 'Views.Record.List', function (Dep) {
var viewName = this.getMetadata().get('clientDefs.' + scope + '.modalViews.edit') || 'Modals.Edit';
this.createView('quickCreate', viewName, {
scope: scope,
attributes: {
parentId: parentId,
parentName: parentName,
order: this.collection.length + 1
}
attributes: attributes
}, function (view) {
view.render();
this.listenToOnce(view, 'after:save', function (model) {
@@ -17,49 +17,58 @@
*
* 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.Settings.Fields.CurrencyRates', 'Views.Fields.Base', function (Dep) {
************************************************************************/
Espo.define('views/settings/fields/currency-rates', 'views/fields/base', function (Dep) {
return Dep.extend({
editTemplate: 'settings.fields.currency-rates.edit',
editTemplate: 'settings/fields/currency-rates/edit',
data: function () {
var baseCurrency = this.model.get('baseCurrency');
var currencyRates = this.model.get('currencyRates') || {};
var rateValues = {};
this.model.get('currencyList').forEach(function (currency) {
if (currency != baseCurrency) {
rateValues[currency] = currencyRates[currency] || 1.00;
}
}, this);
return {
rateValues: rateValues
};
},
setup: function () {
},
fetch: function () {
var data = {};
var currencyRates = {};
var baseCurrency = this.model.get('baseCurrency');
this.model.get('currencyList').forEach(function (currency) {
var currencyList = this.model.get('currencyList') || [];
currencyList.forEach(function (currency) {
if (currency != baseCurrency) {
currencyRates[currency] = parseFloat(this.$el.find('input[data-currency="'+currency+'"]').val() || 1);
}
}, this);
delete currencyRates[baseCurrency];
for (var c in currencyRates) {
if (!~currencyList.indexOf(c)) {
delete currencyRates[c];
}
}
data[this.name] = currencyRates;
return data;
},
}
});
});
+2
View File
@@ -93,6 +93,8 @@ Espo.define('Views.Site.Navbar', 'View', function (Dep) {
var tabList = this.getPreferences().get('useCustomTabList') ? this.getPreferences().get('tabList') : this.getConfig().get('tabList');
tabList = tabList || [];
this.tabList = tabList.filter(function (scope) {
if (this.getMetadata().get('scopes.' + scope + '.acl')) {
return this.getAcl().check(scope);
+3 -1
View File
@@ -111,7 +111,9 @@ Espo.define('views/stream/list', 'views/record/list-expanded', function (Dep) {
});
},
actionViewRecord: function (data) {
actionViewRecord: function (data, e) {
e.stopPropagation();
var id = data.id;
var scope = data.scope;
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "espocrm",
"version": "3.7.1",
"version": "3.7.4",
"description": "",
"main": "index.php",
"repository": {
@@ -89,6 +89,15 @@ class FiltersMatcherTest extends \PHPUnit_Framework_TestCase
$filterList = [$filter];
$this->assertTrue($this->object->match($email, $filterList));
$email = new \Espo\Entities\Email($this->emailDefs);
$email->set('from', 'test@tester');
$filter = new \Espo\Entities\EmailFilter($this->filterDefs);
$filter->set(array(
'from' => '*@tester'
));
$filterList = [$filter];
$this->assertTrue($this->object->match($email, $filterList));
$email->set('from', 'test@tester');
$email->set('to', 'test@tester;baraka@tester');
$filter = new \Espo\Entities\EmailFilter($this->filterDefs);
@@ -98,6 +107,15 @@ class FiltersMatcherTest extends \PHPUnit_Framework_TestCase
$filterList = [$filter];
$this->assertTrue($this->object->match($email, $filterList));
$email->set('from', 'test@tester');
$email->set('to', 'test@tester;baraka@man');
$filter = new \Espo\Entities\EmailFilter($this->filterDefs);
$filter->set(array(
'to' => '*@tester'
));
$filterList = [$filter];
$this->assertTrue($this->object->match($email, $filterList));
$email->set('subject', 'test hello man');
$filter = new \Espo\Entities\EmailFilter($this->filterDefs);
$filter->set(array(