Compare commits
28 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a4c15992a9 | |||
| 14d1173a0c | |||
| 1e7acbdbd2 | |||
| 35e729b25c | |||
| 4ee5ea78e3 | |||
| fe971f9f67 | |||
| a828523f26 | |||
| af9ca6788e | |||
| 36d1c3af63 | |||
| 1853e98209 | |||
| f526d43798 | |||
| ae8c76cecb | |||
| 2b32c94543 | |||
| b6f5909df1 | |||
| ef35bbbb63 | |||
| 64f2cc6c7e | |||
| a16635eb26 | |||
| 6e614f0a7d | |||
| 859f4eab0a | |||
| 104e0b9079 | |||
| 612abbf5c0 | |||
| 2dfbf71806 | |||
| c43f4d129d | |||
| 8d47a48f62 | |||
| 9a333e6e38 | |||
| f6e0ef8cc6 | |||
| 36a45717f1 | |||
| 86f63d72e1 |
@@ -469,7 +469,7 @@ class Xlsx extends \Espo\Core\Injectable
|
||||
|
||||
} else {
|
||||
if (array_key_exists($name, $row)) {
|
||||
$sheet->setCellValue("$col$rowNumber", $row[$name]);
|
||||
$sheet->setCellValueExplicit("$col$rowNumber", $row[$name], \PhpOffice\PhpSpreadsheet\Cell\DataType::TYPE_STRING);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1007,7 +1007,7 @@ class Base
|
||||
foreach ($item['value'] as $i) {
|
||||
$a = $this->getWherePart($i, $result);
|
||||
foreach ($a as $left => $right) {
|
||||
if (!empty($right) || is_null($right) || $right === '') {
|
||||
if (!empty($right) || is_null($right) || $right === '' || $right === 0 || $right === false) {
|
||||
$arr[] = array($left => $right);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -251,6 +251,8 @@ class LDAP extends Base
|
||||
$data[$fieldName] = $fieldValue;
|
||||
}
|
||||
|
||||
$this->getAuth()->useNoAuth();
|
||||
|
||||
$user = $this->getEntityManager()->getEntity('User');
|
||||
$user->set($data);
|
||||
|
||||
|
||||
@@ -315,12 +315,121 @@ class MySqlPlatform extends \Doctrine\DBAL\Platforms\MySqlPlatform
|
||||
$options['collate'] = 'utf8mb4_unicode_ci';
|
||||
}
|
||||
|
||||
return parent::_getCreateTableSQL($tableName, $columns, $options);
|
||||
$queryFields = $this->getColumnDeclarationListSQL($columns);
|
||||
|
||||
if (isset($options['uniqueConstraints']) && ! empty($options['uniqueConstraints'])) {
|
||||
foreach ($options['uniqueConstraints'] as $index => $definition) {
|
||||
$queryFields .= ', ' . $this->getUniqueConstraintDeclarationSQL($index, $definition);
|
||||
}
|
||||
}
|
||||
|
||||
// add all indexes
|
||||
if (isset($options['indexes']) && ! empty($options['indexes'])) {
|
||||
foreach($options['indexes'] as $index => $definition) {
|
||||
$queryFields .= ', ' . $this->getIndexDeclarationSQL($index, $definition);
|
||||
}
|
||||
}
|
||||
|
||||
// attach all primary keys
|
||||
if (isset($options['primary']) && ! empty($options['primary'])) {
|
||||
$keyColumns = array_unique(array_values($options['primary']));
|
||||
$queryFields .= ', PRIMARY KEY(' . implode(', ', $keyColumns) . ')';
|
||||
}
|
||||
|
||||
$query = 'CREATE ';
|
||||
|
||||
if (!empty($options['temporary'])) {
|
||||
$query .= 'TEMPORARY ';
|
||||
}
|
||||
|
||||
$query .= 'TABLE ' . $this->espoQuote($tableName) . ' (' . $queryFields . ') ';
|
||||
$query .= $this->buildTableOptions($options);
|
||||
$query .= $this->buildPartitionOptions($options);
|
||||
|
||||
$sql[] = $query;
|
||||
|
||||
if (isset($options['foreignKeys'])) {
|
||||
foreach ((array) $options['foreignKeys'] as $definition) {
|
||||
$sql[] = $this->getCreateForeignKeySQL($definition, $tableName);
|
||||
}
|
||||
}
|
||||
|
||||
return $sql;
|
||||
}
|
||||
|
||||
public function getColumnCollationDeclarationSQL($collation)
|
||||
{
|
||||
return $this->getCollationFieldDeclaration($collation);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build SQL for table options
|
||||
*
|
||||
* @param array $options
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function buildTableOptions(array $options)
|
||||
{
|
||||
if (isset($options['table_options'])) {
|
||||
return $options['table_options'];
|
||||
}
|
||||
|
||||
$tableOptions = array();
|
||||
|
||||
// Charset
|
||||
if ( ! isset($options['charset'])) {
|
||||
$options['charset'] = 'utf8';
|
||||
}
|
||||
|
||||
$tableOptions[] = sprintf('DEFAULT CHARACTER SET %s', $options['charset']);
|
||||
|
||||
// Collate
|
||||
if ( ! isset($options['collate'])) {
|
||||
$options['collate'] = 'utf8_unicode_ci';
|
||||
}
|
||||
|
||||
$tableOptions[] = sprintf('COLLATE %s', $options['collate']);
|
||||
|
||||
// Engine
|
||||
if ( ! isset($options['engine'])) {
|
||||
$options['engine'] = 'InnoDB';
|
||||
}
|
||||
|
||||
$tableOptions[] = sprintf('ENGINE = %s', $options['engine']);
|
||||
|
||||
// Auto increment
|
||||
if (isset($options['auto_increment'])) {
|
||||
$tableOptions[] = sprintf('AUTO_INCREMENT = %s', $options['auto_increment']);
|
||||
}
|
||||
|
||||
// Comment
|
||||
if (isset($options['comment'])) {
|
||||
$comment = trim($options['comment'], " '");
|
||||
|
||||
$tableOptions[] = sprintf("COMMENT = '%s' ", str_replace("'", "''", $comment));
|
||||
}
|
||||
|
||||
// Row format
|
||||
if (isset($options['row_format'])) {
|
||||
$tableOptions[] = sprintf('ROW_FORMAT = %s', $options['row_format']);
|
||||
}
|
||||
|
||||
return implode(' ', $tableOptions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build SQL for partition options.
|
||||
*
|
||||
* @param array $options
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function buildPartitionOptions(array $options)
|
||||
{
|
||||
return (isset($options['partition_options']))
|
||||
? ' ' . $options['partition_options']
|
||||
: '';
|
||||
}
|
||||
//end: ESPO
|
||||
}
|
||||
@@ -63,6 +63,9 @@ class TargetList extends \Espo\Core\Controllers\Record
|
||||
if (empty($data->targetId)) {
|
||||
throw new BadRequest();
|
||||
}
|
||||
$data->id = strval($data->id);
|
||||
$data->targetId = strval($data->targetId);
|
||||
|
||||
return $this->getRecordService()->optOut($data->id, $data->targetType, $data->targetId);
|
||||
}
|
||||
|
||||
@@ -77,6 +80,9 @@ class TargetList extends \Espo\Core\Controllers\Record
|
||||
if (empty($data->targetId)) {
|
||||
throw new BadRequest();
|
||||
}
|
||||
$data->id = strval($data->id);
|
||||
$data->targetId = strval($data->targetId);
|
||||
|
||||
return $this->getRecordService()->cancelOptOut($data->id, $data->targetType, $data->targetId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,11 +3,14 @@
|
||||
"name": "Name",
|
||||
"description": "Description",
|
||||
"entryCount": "Entry Count",
|
||||
"optedOutCount": "Opted Out Count",
|
||||
"campaigns": "Campaigns",
|
||||
"endDate": "End Date",
|
||||
"targetLists": "Target Lists",
|
||||
"includingActionList": "Including",
|
||||
"excludingActionList": "Excluding"
|
||||
"excludingActionList": "Excluding",
|
||||
"targetStatus": "Target Status",
|
||||
"isOptedOut": "Is Opted Out"
|
||||
},
|
||||
"links": {
|
||||
"accounts": "Accounts",
|
||||
@@ -23,6 +26,9 @@
|
||||
"Television": "Television",
|
||||
"Radio": "Radio",
|
||||
"Newsletter": "Newsletter"
|
||||
},
|
||||
"targetStatus": {
|
||||
"Opted Out": "Opted Out"
|
||||
}
|
||||
},
|
||||
"labels": {
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
"label":"Overview",
|
||||
"rows":[
|
||||
[{"name":"name"}, {"name":"entryCount"}],
|
||||
[false, {"name":"optedOutCount"}],
|
||||
[{"name":"description", "fullWidth": true}]
|
||||
]
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
"rows": [
|
||||
[{"name":"name", "fullWidth": true}],
|
||||
[{"name":"entryCount", "fullWidth": true}],
|
||||
[{"name":"optedOutCount", "fullWidth": true}],
|
||||
[{"name":"description", "fullWidth": true}]
|
||||
]
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
[
|
||||
{"name":"name", "link":true},
|
||||
{"name":"entryCount", "width": 25, "notSortable": true}
|
||||
{"name":"targetStatus", "width": 25, "notSortable": true}
|
||||
]
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[
|
||||
"contacts",
|
||||
"leads",
|
||||
"users",
|
||||
"accounts"
|
||||
"accounts",
|
||||
"users"
|
||||
]
|
||||
|
||||
@@ -61,7 +61,9 @@
|
||||
"create": false
|
||||
},
|
||||
"targetLists": {
|
||||
"layout": "listForTarget"
|
||||
"rowActionsView": "crm:views/record/row-actions/relationship-target",
|
||||
"layout": "listForTarget",
|
||||
"view": "crm:views/record/panels/target-lists"
|
||||
}
|
||||
},
|
||||
"filterList": [
|
||||
|
||||
@@ -85,8 +85,9 @@
|
||||
},
|
||||
"targetLists": {
|
||||
"create": false,
|
||||
"rowActionsView": "views/record/row-actions/relationship-unlink-only",
|
||||
"layout": "listForTarget"
|
||||
"rowActionsView": "crm:views/record/row-actions/relationship-target",
|
||||
"layout": "listForTarget",
|
||||
"view": "crm:views/record/panels/target-lists"
|
||||
}
|
||||
},
|
||||
"boolFilterList": [
|
||||
|
||||
@@ -112,14 +112,15 @@
|
||||
},
|
||||
"relationshipPanels":{
|
||||
"campaignLogRecords":{
|
||||
"rowActionsView":"Record.RowActions.Empty",
|
||||
"rowActionsView":"views/record/row-actions/empty",
|
||||
"select":false,
|
||||
"create":false
|
||||
},
|
||||
"targetLists":{
|
||||
"create":false,
|
||||
"rowActionsView":"views/record/row-actions/relationship-unlink-only",
|
||||
"layout": "listForTarget"
|
||||
"create": false,
|
||||
"rowActionsView": "crm:views/record/row-actions/relationship-target",
|
||||
"layout": "listForTarget",
|
||||
"view": "crm:views/record/panels/target-lists"
|
||||
}
|
||||
},
|
||||
"filterList":[
|
||||
|
||||
@@ -206,6 +206,12 @@
|
||||
"layoutListDisabled": true,
|
||||
"readOnly": true,
|
||||
"view": "views/fields/link-one"
|
||||
},
|
||||
"targetListIsOptedOut": {
|
||||
"type": "bool",
|
||||
"notStorable": true,
|
||||
"readOnly": true,
|
||||
"disabled": true
|
||||
}
|
||||
},
|
||||
"links": {
|
||||
|
||||
@@ -289,6 +289,12 @@
|
||||
"layoutListDisabled": true,
|
||||
"readOnly": true,
|
||||
"view": "views/fields/link-one"
|
||||
},
|
||||
"targetListIsOptedOut": {
|
||||
"type": "bool",
|
||||
"notStorable": true,
|
||||
"readOnly": true,
|
||||
"disabled": true
|
||||
}
|
||||
},
|
||||
"links": {
|
||||
|
||||
@@ -194,6 +194,12 @@
|
||||
"layoutMassUpdateDisabled": true,
|
||||
"layoutFiltersDisabled": true,
|
||||
"entity": "TargetList"
|
||||
},
|
||||
"targetListIsOptedOut": {
|
||||
"type": "bool",
|
||||
"notStorable": true,
|
||||
"readOnly": true,
|
||||
"disabled": true
|
||||
}
|
||||
},
|
||||
"links": {
|
||||
|
||||
@@ -8,7 +8,17 @@
|
||||
"entryCount": {
|
||||
"type": "int",
|
||||
"readOnly": true,
|
||||
"notStorable": true
|
||||
"notStorable": true,
|
||||
"layoutFiltersDisabled": true,
|
||||
"layoutMassUpdateDisabled": true
|
||||
},
|
||||
"optedOutCount": {
|
||||
"type": "int",
|
||||
"readOnly": true,
|
||||
"notStorable": true,
|
||||
"layoutListDisabled": true,
|
||||
"layoutFiltersDisabled": true,
|
||||
"layoutMassUpdateDisabled": true
|
||||
},
|
||||
"description": {
|
||||
"type": "text"
|
||||
@@ -60,6 +70,28 @@
|
||||
"layoutLinkDisabled": true,
|
||||
"notStorable": true,
|
||||
"disabled": true
|
||||
},
|
||||
"targetStatus": {
|
||||
"type": "enum",
|
||||
"options": ["", "Opted Out"],
|
||||
"notStorable": true,
|
||||
"readOnly": true,
|
||||
"layoutListDisabled": true,
|
||||
"layoutDetailDisabled": true,
|
||||
"layoutMassUpdateDisabled": true,
|
||||
"exportDisabled": true,
|
||||
"importDisabled": true,
|
||||
"view": "crm:views/target-list/fields/target-status"
|
||||
},
|
||||
"isOptedOut": {
|
||||
"type": "bool",
|
||||
"notStorable": true,
|
||||
"readOnly": true,
|
||||
"layoutListDisabled": true,
|
||||
"layoutDetailDisabled": true,
|
||||
"layoutMassUpdateDisabled": true,
|
||||
"exportDisabled": true,
|
||||
"importDisabled": true
|
||||
}
|
||||
},
|
||||
"links": {
|
||||
|
||||
@@ -4,6 +4,12 @@
|
||||
"type": "hasMany",
|
||||
"entity": "TargetList",
|
||||
"foreign": "users"
|
||||
},
|
||||
"targetListIsOptedOut": {
|
||||
"type": "bool",
|
||||
"notStorable": true,
|
||||
"readOnly": true,
|
||||
"disabled": true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,6 +39,11 @@ class Account extends \Espo\Services\Record
|
||||
'role' => 'accountRole',
|
||||
'isInactive' => 'accountIsInactive'
|
||||
)
|
||||
),
|
||||
'targetLists' => array(
|
||||
'additionalColumns' => array(
|
||||
'optedOut' => 'isOptedOut'
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
@@ -114,7 +114,8 @@ class Activities extends \Espo\Core\Services\Base
|
||||
'parentType',
|
||||
'parentId',
|
||||
'status',
|
||||
'createdAt'
|
||||
'createdAt',
|
||||
['VALUE:', 'hasAttachment']
|
||||
],
|
||||
'leftJoins' => [['users', 'usersLeft']],
|
||||
'whereClause' => array(
|
||||
@@ -165,7 +166,8 @@ class Activities extends \Espo\Core\Services\Base
|
||||
'parentType',
|
||||
'parentId',
|
||||
'status',
|
||||
'createdAt'
|
||||
'createdAt',
|
||||
['VALUE:', 'hasAttachment']
|
||||
],
|
||||
'leftJoins' => [['users', 'usersLeft']],
|
||||
'whereClause' => array(
|
||||
@@ -223,7 +225,8 @@ class Activities extends \Espo\Core\Services\Base
|
||||
'parentType',
|
||||
'parentId',
|
||||
'status',
|
||||
'createdAt'
|
||||
'createdAt',
|
||||
'hasAttachment'
|
||||
],
|
||||
'leftJoins' => [['users', 'usersLeft']],
|
||||
'whereClause' => array(
|
||||
@@ -269,7 +272,8 @@ class Activities extends \Espo\Core\Services\Base
|
||||
'parentType',
|
||||
'parentId',
|
||||
'status',
|
||||
'createdAt'
|
||||
'createdAt',
|
||||
['VALUE:', 'hasAttachment']
|
||||
],
|
||||
'whereClause' => array(),
|
||||
'customJoin' => ''
|
||||
@@ -375,7 +379,8 @@ class Activities extends \Espo\Core\Services\Base
|
||||
'parentType',
|
||||
'parentId',
|
||||
'status',
|
||||
'createdAt'
|
||||
'createdAt',
|
||||
['VALUE:', 'hasAttachment']
|
||||
],
|
||||
'whereClause' => array()
|
||||
);
|
||||
@@ -480,7 +485,8 @@ class Activities extends \Espo\Core\Services\Base
|
||||
'parentType',
|
||||
'parentId',
|
||||
'status',
|
||||
'createdAt'
|
||||
'createdAt',
|
||||
'hasAttachment'
|
||||
],
|
||||
'whereClause' => array(),
|
||||
'customJoin' => ''
|
||||
@@ -627,15 +633,21 @@ class Activities extends \Espo\Core\Services\Base
|
||||
|
||||
$sth->execute();
|
||||
|
||||
$rows = $sth->fetchAll(PDO::FETCH_ASSOC);
|
||||
$rowList = $sth->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
$list = array();
|
||||
foreach ($rows as $row) {
|
||||
$boolAttributeList = ['hasAttachment'];
|
||||
|
||||
$list = [];
|
||||
foreach ($rowList as $row) {
|
||||
foreach ($boolAttributeList as $attribute) {
|
||||
if (!array_key_exists($attribute, $row)) continue;
|
||||
$row[$attribute] = $row[$attribute] == '1' ? true : false;
|
||||
}
|
||||
$list[] = $row;
|
||||
}
|
||||
|
||||
return array(
|
||||
'list' => $rows,
|
||||
'list' => $list,
|
||||
'total' => $totalCount
|
||||
);
|
||||
}
|
||||
@@ -1004,7 +1016,8 @@ class Activities extends \Espo\Core\Services\Base
|
||||
($seed->hasAttribute('parentType') ? ['parentType', 'parentType'] : ['VALUE:', 'parentType']),
|
||||
($seed->hasAttribute('parentId') ? ['parentId', 'parentId'] : ['VALUE:', 'parentId']),
|
||||
'status',
|
||||
'createdAt'
|
||||
'createdAt',
|
||||
['VALUE:', 'hasAttachment']
|
||||
];
|
||||
|
||||
$selectParams = $selectManager->getEmptySelectParams();
|
||||
|
||||
@@ -43,6 +43,14 @@ class Contact extends \Espo\Core\Templates\Services\Person
|
||||
'title'
|
||||
];
|
||||
|
||||
protected $linkSelectParams = array(
|
||||
'targetLists' => array(
|
||||
'additionalColumns' => array(
|
||||
'optedOut' => 'isOptedOut'
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
protected function afterCreateEntity(Entity $entity, $data)
|
||||
{
|
||||
if (!empty($data->emailId)) {
|
||||
|
||||
@@ -43,6 +43,14 @@ class Lead extends \Espo\Core\Templates\Services\Person
|
||||
$this->addDependency('container');
|
||||
}
|
||||
|
||||
protected $linkSelectParams = array(
|
||||
'targetLists' => array(
|
||||
'additionalColumns' => array(
|
||||
'optedOut' => 'isOptedOut'
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
protected function getFieldManager()
|
||||
{
|
||||
return $this->getInjection('container')->get('fieldManager');
|
||||
|
||||
@@ -48,6 +48,29 @@ class TargetList extends \Espo\Services\Record
|
||||
'User' => 'users'
|
||||
);
|
||||
|
||||
protected $linkSelectParams = [
|
||||
'accounts' => [
|
||||
'additionalColumns' => [
|
||||
'optedOut' => 'targetListIsOptedOut'
|
||||
]
|
||||
],
|
||||
'contacts' => [
|
||||
'additionalColumns' => [
|
||||
'optedOut' => 'targetListIsOptedOut'
|
||||
]
|
||||
],
|
||||
'leads' => [
|
||||
'additionalColumns' => [
|
||||
'optedOut' => 'targetListIsOptedOut'
|
||||
]
|
||||
],
|
||||
'users' => [
|
||||
'additionalColumns' => [
|
||||
'optedOut' => 'targetListIsOptedOut'
|
||||
]
|
||||
]
|
||||
];
|
||||
|
||||
protected function init()
|
||||
{
|
||||
parent::init();
|
||||
@@ -60,6 +83,7 @@ class TargetList extends \Espo\Services\Record
|
||||
{
|
||||
parent::loadAdditionalFields($entity);
|
||||
$this->loadEntryCountField($entity);
|
||||
$this->loadOptedOutCountField($entity);
|
||||
}
|
||||
|
||||
public function loadAdditionalFieldsForList(Entity $entity)
|
||||
@@ -78,6 +102,34 @@ class TargetList extends \Espo\Services\Record
|
||||
$entity->set('entryCount', $count);
|
||||
}
|
||||
|
||||
protected function loadOptedOutCountField(Entity $entity)
|
||||
{
|
||||
$count = 0;
|
||||
|
||||
|
||||
$count += $this->getEntityManager()->getRepository('Contact')->join(['targetLists'])->where([
|
||||
'targetListsMiddle.targetListId' => $entity->id,
|
||||
'targetListsMiddle.optedOut' => 1
|
||||
])->count();
|
||||
|
||||
$count += $this->getEntityManager()->getRepository('Lead')->join(['targetLists'])->where([
|
||||
'targetListsMiddle.targetListId' => $entity->id,
|
||||
'targetListsMiddle.optedOut' => 1
|
||||
])->count();
|
||||
|
||||
$count += $this->getEntityManager()->getRepository('Account')->join(['targetLists'])->where([
|
||||
'targetListsMiddle.targetListId' => $entity->id,
|
||||
'targetListsMiddle.optedOut' => 1
|
||||
])->count();
|
||||
|
||||
$count += $this->getEntityManager()->getRepository('User')->join(['targetLists'])->where([
|
||||
'targetListsMiddle.targetListId' => $entity->id,
|
||||
'targetListsMiddle.optedOut' => 1
|
||||
])->count();
|
||||
|
||||
$entity->set('optedOutCount', $count);
|
||||
}
|
||||
|
||||
protected function afterCreate(Entity $entity, array $data = array())
|
||||
{
|
||||
if (array_key_exists('sourceCampaignId', $data) && !empty($data['includingActionList'])) {
|
||||
|
||||
@@ -52,7 +52,7 @@
|
||||
"Team": "Teams",
|
||||
"Role": "Roles",
|
||||
"EmailTemplate": "Email Templates",
|
||||
"EmailTemplateCategory": "Email Template Category",
|
||||
"EmailTemplateCategory": "Email Template Categories",
|
||||
"EmailAccount": "Personal Email Accounts",
|
||||
"EmailAccountScope": "Personal Email Accounts",
|
||||
"OutboundEmail": "Outbound Emails",
|
||||
@@ -338,7 +338,8 @@
|
||||
"children": "Children",
|
||||
"id": "ID",
|
||||
"ids": "IDs",
|
||||
"names": "Names"
|
||||
"names": "Names",
|
||||
"targetListIsOptedOut": "Is Opted Out (Target List)"
|
||||
},
|
||||
"links": {
|
||||
"assignedUser": "Assigned User",
|
||||
|
||||
@@ -98,7 +98,8 @@
|
||||
"scopeColorsDisabled": "Disable scope colors",
|
||||
"tabColorsDisabled": "Disable tab colors",
|
||||
"tabIconsDisabled": "Disable tab icons",
|
||||
"emailAddressIsOptedOutByDefault": "Mark new email addresses as opted-out"
|
||||
"emailAddressIsOptedOutByDefault": "Mark new email addresses as opted-out",
|
||||
"outboundEmailBccAddress": "BCC address for external clients"
|
||||
},
|
||||
"options": {
|
||||
"weekStart": {
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
"label": "Configuration",
|
||||
"rows": [
|
||||
[{"name": "outboundEmailFromAddress"}, {"name": "outboundEmailIsShared"}],
|
||||
[{"name": "outboundEmailFromName"}, false]
|
||||
[{"name": "outboundEmailFromName"}, {"name": "outboundEmailBccAddress"}]
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
@@ -101,6 +101,14 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"relationshipPanels":{
|
||||
"targetLists":{
|
||||
"create": false,
|
||||
"rowActionsView": "crm:views/record/row-actions/relationship-target",
|
||||
"layout": "listForTarget",
|
||||
"view": "crm:views/record/panels/target-lists"
|
||||
}
|
||||
},
|
||||
"filterList": [
|
||||
"active"
|
||||
],
|
||||
|
||||
@@ -469,6 +469,10 @@
|
||||
"emailAddressIsOptedOutByDefault": {
|
||||
"type": "bool",
|
||||
"tooltip": true
|
||||
},
|
||||
"outboundEmailBccAddress": {
|
||||
"type": "varchar",
|
||||
"trim": true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,5 @@
|
||||
"notMergeable": true,
|
||||
"notCreatable": true,
|
||||
"filter": false,
|
||||
"fieldDefs": {
|
||||
"notStorable": true
|
||||
}
|
||||
"skipOrmDefs": true
|
||||
}
|
||||
|
||||
@@ -15,7 +15,5 @@
|
||||
"notMergeable": true,
|
||||
"notCreatable": true,
|
||||
"filter": false,
|
||||
"fieldDefs": {
|
||||
"notStorable": true
|
||||
}
|
||||
"skipOrmDefs": true
|
||||
}
|
||||
|
||||
@@ -15,7 +15,5 @@
|
||||
"notMergeable": true,
|
||||
"notCreatable": true,
|
||||
"filter": false,
|
||||
"fieldDefs": {
|
||||
"notStorable": true
|
||||
}
|
||||
"skipOrmDefs": true
|
||||
}
|
||||
|
||||
@@ -523,16 +523,18 @@ class Import extends \Espo\Services\Record
|
||||
if ($value !== '') {
|
||||
$type = $this->getMetadata()->get("entityDefs.{$scope}.fields.{$field}.type");
|
||||
if ($type == 'personName') {
|
||||
$lastNameField = 'last' . ucfirst($field);
|
||||
$firstNameField = 'first' . ucfirst($field);
|
||||
$firstNameAttribute = 'first' . ucfirst($field);
|
||||
$lastNameAttribute = 'last' . ucfirst($field);
|
||||
|
||||
$personName = $this->parsePersonName($value, $params['personNameFormat']);
|
||||
|
||||
if (!$entity->get($firstNameField)) {
|
||||
$entity->set($firstNameField, $personName['firstName']);
|
||||
if (!$entity->get($firstNameAttribute)) {
|
||||
$personName['firstName'] = $this->prepareAttributeValue($entity, $firstNameAttribute, $personName['firstName']);
|
||||
$entity->set($firstNameAttribute, $personName['firstName']);
|
||||
}
|
||||
if (!$entity->get($lastNameField)) {
|
||||
$entity->set($lastNameField, $personName['lastName']);
|
||||
if (!$entity->get($lastNameAttribute)) {
|
||||
$personName['lastName'] = $this->prepareAttributeValue($entity, $lastNameAttribute, $personName['lastName']);
|
||||
$entity->set($lastNameAttribute, $personName['lastName']);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
@@ -652,6 +654,19 @@ class Import extends \Espo\Services\Record
|
||||
return $result;
|
||||
}
|
||||
|
||||
protected function prepareAttributeValue($entity, $attribute, $value)
|
||||
{
|
||||
if ($entity->getAttributeType($attribute) === $entity::VARCHAR) {
|
||||
$maxLength = $entity->getAttributeParam($attribute, 'len');
|
||||
if ($maxLength) {
|
||||
if (mb_strlen($value) > $maxLength) {
|
||||
$value = substr($value, 0, $maxLength);
|
||||
}
|
||||
}
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
|
||||
protected function parsePersonName($value, $format)
|
||||
{
|
||||
$firstName = '';
|
||||
@@ -711,6 +726,7 @@ class Import extends \Espo\Services\Record
|
||||
if ($dt) {
|
||||
return $dt->format('Y-m-d');
|
||||
}
|
||||
return null;
|
||||
break;
|
||||
case Entity::DATETIME:
|
||||
$timezone = new \DateTimeZone(isset($params['timezone']) ? $params['timezone'] : 'UTC');
|
||||
@@ -719,6 +735,7 @@ class Import extends \Espo\Services\Record
|
||||
$dt->setTimezone(new \DateTimeZone('UTC'));
|
||||
return $dt->format('Y-m-d H:i:s');
|
||||
}
|
||||
return null;
|
||||
break;
|
||||
case Entity::FLOAT:
|
||||
$a = explode($decimalMark, $value);
|
||||
@@ -746,6 +763,8 @@ class Import extends \Espo\Services\Record
|
||||
}
|
||||
}
|
||||
|
||||
$value = $this->prepareAttributeValue($entity, $attribute, $value);
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
|
||||
@@ -63,6 +63,14 @@ class User extends Record
|
||||
'accountsIds'
|
||||
];
|
||||
|
||||
protected $linkSelectParams = array(
|
||||
'targetLists' => array(
|
||||
'additionalColumns' => array(
|
||||
'optedOut' => 'isOptedOut'
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
protected function getMailSender()
|
||||
{
|
||||
return $this->getContainer()->get('mailSender');
|
||||
|
||||
@@ -393,10 +393,13 @@ Espo.define('crm:views/calendar/calendar', ['view', 'lib!full-calendar'], functi
|
||||
|
||||
handleAllDay: function (event, notInitial) {
|
||||
if (~this.allDayScopeList.indexOf(event.scope)) {
|
||||
event.allDay = true;
|
||||
event.allDay = event.allDayCopy = true;
|
||||
if (!notInitial) {
|
||||
if (event.end) {
|
||||
event.start = event.end;
|
||||
if (event.end.hours() === 0 && event.end.minutes() === 0) {
|
||||
event.start.add(-1, 'days');
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
@@ -423,6 +426,8 @@ Espo.define('crm:views/calendar/calendar', ['view', 'lib!full-calendar'], functi
|
||||
event.allDay = false;
|
||||
}
|
||||
}
|
||||
|
||||
event.allDayCopy = event.allDay;
|
||||
},
|
||||
|
||||
convertToFcEvents: function (list) {
|
||||
@@ -579,6 +584,17 @@ Espo.define('crm:views/calendar/calendar', ['view', 'lib!full-calendar'], functi
|
||||
this.fetchEvents(fromStr, toStr, callback);
|
||||
}.bind(this),
|
||||
eventDrop: function (event, delta, revertFunc) {
|
||||
if (event.start.hasTime()) {
|
||||
if (event.allDayCopy) {
|
||||
revertFunc();
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (!event.allDayCopy) {
|
||||
revertFunc();
|
||||
return;
|
||||
}
|
||||
}
|
||||
var eventCloned = Espo.Utils.clone(event);
|
||||
|
||||
var dateStart = this.convertTime(event.start) || null;
|
||||
@@ -625,6 +641,7 @@ Espo.define('crm:views/calendar/calendar', ['view', 'lib!full-calendar'], functi
|
||||
this.getModelFactory().create(event.scope, function (model) {
|
||||
model.once('sync', function () {
|
||||
this.notify(false);
|
||||
this.$calendar.fullCalendar('updateEvent', event);
|
||||
}, this);
|
||||
model.id = event.recordId;
|
||||
model.save(attributes, {patch: true}).fail(function () {
|
||||
@@ -645,6 +662,7 @@ Espo.define('crm:views/calendar/calendar', ['view', 'lib!full-calendar'], functi
|
||||
this.getModelFactory().create(event.scope, function (model) {
|
||||
model.once('sync', function () {
|
||||
this.notify(false);
|
||||
this.$calendar.fullCalendar('updateEvent', event);
|
||||
}.bind(this));
|
||||
model.id = event.recordId;
|
||||
model.save(attributes, {patch: true}).fail(function () {
|
||||
|
||||
@@ -52,7 +52,8 @@ Espo.define('crm:views/record/panels/history', 'crm:views/record/panels/activiti
|
||||
],
|
||||
[
|
||||
{name: 'status'},
|
||||
{name: 'dateSent'}
|
||||
{name: 'dateSent'},
|
||||
{name: 'hasAttachment', view: 'views/email/fields/has-attachment'}
|
||||
]
|
||||
]
|
||||
},
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2018 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('crm:views/record/panels/target-lists', 'views/record/panels/relationship', function (Dep) {
|
||||
|
||||
return Dep.extend({
|
||||
|
||||
actionOptOut: function (data) {
|
||||
this.confirm(this.translate('confirmation', 'messages'), function () {
|
||||
$.ajax({
|
||||
url: 'TargetList/action/optOut',
|
||||
type: 'POST',
|
||||
data: JSON.stringify({
|
||||
id: data.id,
|
||||
targetId: this.model.id,
|
||||
targetType: this.model.name
|
||||
})
|
||||
}).done(function () {
|
||||
this.collection.fetch();
|
||||
Espo.Ui.success(this.translate('Done'));
|
||||
this.model.trigger('opt-out');
|
||||
}.bind(this));
|
||||
}, this);
|
||||
},
|
||||
|
||||
actionCancelOptOut: function (data) {
|
||||
this.confirm(this.translate('confirmation', 'messages'), function () {
|
||||
$.ajax({
|
||||
url: 'TargetList/action/cancelOptOut',
|
||||
type: 'POST',
|
||||
data: JSON.stringify({
|
||||
id: data.id,
|
||||
targetId: this.model.id,
|
||||
targetType: this.model.name
|
||||
})
|
||||
}).done(function () {
|
||||
this.collection.fetch();
|
||||
Espo.Ui.success(this.translate('Done'));
|
||||
this.collection.fetch();
|
||||
this.model.trigger('cancel-opt-out');
|
||||
}.bind(this));
|
||||
}, this);
|
||||
}
|
||||
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,60 @@
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2018 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('crm:views/record/row-actions/relationship-target', 'views/record/row-actions/relationship-unlink-only', function (Dep) {
|
||||
|
||||
return Dep.extend({
|
||||
|
||||
getActionList: function () {
|
||||
var list = Dep.prototype.getActionList.call(this);
|
||||
|
||||
if (this.options.acl.edit) {
|
||||
if (this.model.get('isOptedOut')) {
|
||||
list.push({
|
||||
action: 'cancelOptOut',
|
||||
html: this.translate('Cancel Opt-Out', 'labels', 'TargetList'),
|
||||
data: {
|
||||
id: this.model.id
|
||||
}
|
||||
});
|
||||
} else {
|
||||
list.push({
|
||||
action: 'optOut',
|
||||
html: this.translate('Opt-Out', 'labels', 'TargetList'),
|
||||
data: {
|
||||
id: this.model.id
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
@@ -0,0 +1,41 @@
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2018 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('crm:views/target-list/fields/target-status', 'views/fields/base', function (Dep) {
|
||||
|
||||
return Dep.extend({
|
||||
|
||||
getValueForDisplay: function () {
|
||||
if (this.model.get('isOptedOut')) {
|
||||
return this.getLanguage().translateOption('Opted Out', 'targetStatus', 'TargetList');
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -108,6 +108,10 @@ Espo.define('crm:views/target-list/record/panels/opted-out', ['views/record/pane
|
||||
this.listenTo(this.model, 'opt-out', function () {
|
||||
this.actionRefresh();
|
||||
}, this);
|
||||
|
||||
this.listenTo(this.model, 'cancel-opt-out', function () {
|
||||
this.actionRefresh();
|
||||
}, this);
|
||||
},
|
||||
|
||||
afterRender: function () {
|
||||
|
||||
@@ -48,8 +48,26 @@ Espo.define('crm:views/target-list/record/panels/relationship', 'views/record/pa
|
||||
this.model.trigger('opt-out');
|
||||
}.bind(this));
|
||||
}, this);
|
||||
},
|
||||
|
||||
actionCancelOptOut: function (data) {
|
||||
this.confirm(this.translate('confirmation', 'messages'), function () {
|
||||
$.ajax({
|
||||
url: 'TargetList/action/cancelOptOut',
|
||||
type: 'POST',
|
||||
data: JSON.stringify({
|
||||
id: this.model.id,
|
||||
targetId: data.id,
|
||||
targetType: data.type
|
||||
})
|
||||
}).done(function () {
|
||||
this.collection.fetch();
|
||||
Espo.Ui.success(this.translate('Done'));
|
||||
this.collection.fetch();
|
||||
this.model.trigger('cancel-opt-out');
|
||||
}.bind(this));
|
||||
}, this);
|
||||
}
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -33,17 +33,27 @@ Espo.define('crm:views/target-list/record/row-actions/default', 'views/record/ro
|
||||
getActionList: function () {
|
||||
var list = Dep.prototype.getActionList.call(this);
|
||||
if (this.options.acl.edit) {
|
||||
list.push({
|
||||
action: 'optOut',
|
||||
label: 'Opt-Out',
|
||||
data: {
|
||||
id: this.model.id,
|
||||
type: this.model.name
|
||||
}
|
||||
});
|
||||
if (this.model.get('targetListIsOptedOut')) {
|
||||
list.push({
|
||||
action: 'cancelOptOut',
|
||||
label: 'Cancel Opt-Out',
|
||||
data: {
|
||||
id: this.model.id,
|
||||
type: this.model.name
|
||||
}
|
||||
});
|
||||
} else {
|
||||
list.push({
|
||||
action: 'optOut',
|
||||
label: 'Opt-Out',
|
||||
data: {
|
||||
id: this.model.id,
|
||||
type: this.model.name
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -1,21 +1,34 @@
|
||||
|
||||
<div class="group-head">
|
||||
<div class="group-head" data-level="{{level}}">
|
||||
{{#ifNotEqual level 0}}
|
||||
<a class="pull-right" href="javascript:" data-action="remove"><span class="glyphicon glyphicon-remove"></span></a>
|
||||
{{/ifNotEqual}}
|
||||
<span>{{translate operator category='logicalOperators' scope='Admin'}}</span>
|
||||
{{#ifNotEqual level 0}}
|
||||
<div>(</div>
|
||||
{{else}}
|
||||
|
||||
{{/ifNotEqual}}
|
||||
</div>
|
||||
|
||||
<div class="item-list" data-level="{{level}}">
|
||||
{{#each viewDataList}}
|
||||
<div data-view-key="{{key}}">{{{var key ../this}}}</div>
|
||||
<div class="group-operator" data-view-ref-key="{{key}}">{{translate ../groupOperator category='logicalOperators' scope='Admin'}}</div>
|
||||
{{/each}}
|
||||
</div>
|
||||
|
||||
<div class="group-bottom" data-level="{{level}}">
|
||||
<div class="btn-group">
|
||||
<button class="btn btn-link btn-sm dropdown-toggle" data-toggle="dropdown"><span class="glyphicon glyphicon-plus"></span></button>
|
||||
<a class="dropdown-toggle small" href="javascript:" data-toggle="dropdown">{{translate groupOperator category='logicalOperators' scope='Admin'}} <span class="glyphicon glyphicon-plus"></span></a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a href="javascript:" data-action="addField">{{translate 'Field' scope='DynamicLogic'}}</a></li>
|
||||
<li><a href="javascript:" data-action="addAnd">{{translate 'and' category='logicalOperators' scope='Admin'}}</a></li>
|
||||
<li><a href="javascript:" data-action="addOr">{{translate 'or' category='logicalOperators' scope='Admin'}}</a></li>
|
||||
<li><a href="javascript:" data-action="addNot">{{translate 'not' category='logicalOperators' scope='Admin'}}</a></li>
|
||||
<li><a href="javascript:" data-action="addAnd">(... {{translate 'and' category='logicalOperators' scope='Admin'}} ...)</a></li>
|
||||
<li><a href="javascript:" data-action="addOr">(... {{translate 'or' category='logicalOperators' scope='Admin'}} ...)</a></li>
|
||||
<li><a href="javascript:" data-action="addNot">{{translate 'not' category='logicalOperators' scope='Admin'}} (...)</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="item-list">
|
||||
{{#each viewDataList}}
|
||||
<div data-view-key="{{key}}">{{{var key ../this}}}</div>
|
||||
{{/each}}
|
||||
</div>
|
||||
|
||||
{{#ifNotEqual level 0}}
|
||||
<div>)</div>
|
||||
{{/ifNotEqual}}
|
||||
|
||||
@@ -1,17 +1,23 @@
|
||||
|
||||
<div class="group-head">
|
||||
<div class="group-head" data-level="{{level}}">
|
||||
<a class="pull-right" href="javascript:" data-action="remove"><span class="glyphicon glyphicon-remove"></span></a>
|
||||
<span>{{translate 'not' category='logicalOperators' scope='Admin'}}</span>
|
||||
<div>{{translate 'not' category='logicalOperators' scope='Admin'}} (</div>
|
||||
</div>
|
||||
|
||||
<div class="item-list" data-level="{{level}}">
|
||||
<div data-view-key="{{viewKey}}">{{#if hasItem}}{{{var viewKey this}}}{{/if}}</div>
|
||||
</div>
|
||||
|
||||
<div class="group-bottom" data-level="{{level}}">
|
||||
<div class="btn-group">
|
||||
<button class="btn btn-link btn-sm dropdown-toggle" data-toggle="dropdown"><span class="glyphicon glyphicon-plus"></span></button>
|
||||
<a class="dropdown-toggle small" href="javascript:" data-toggle="dropdown"><span class="glyphicon glyphicon-plus"></span></a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a href="javascript:" data-action="addField">{{translate 'Field' scope='DynamicLogic'}}</a></li>
|
||||
<li><a href="javascript:" data-action="addAnd">{{translate 'and' category='logicalOperators' scope='Admin'}}</a></li>
|
||||
<li><a href="javascript:" data-action="addOr">{{translate 'or' category='logicalOperators' scope='Admin'}}</a></li>
|
||||
<li><a href="javascript:" data-action="addNot">{{translate 'not' category='logicalOperators' scope='Admin'}}</a></li>
|
||||
<li><a href="javascript:" data-action="addAnd">(... {{translate 'and' category='logicalOperators' scope='Admin'}} ...)</a></li>
|
||||
<li><a href="javascript:" data-action="addOr">(... {{translate 'or' category='logicalOperators' scope='Admin'}} ...)</a></li>
|
||||
<li><a href="javascript:" data-action="addNot">{{translate 'not' category='logicalOperators' scope='Admin'}} (...)</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="item-list">
|
||||
<div data-view-key="{{viewKey}}">{{#if hasItem}}{{{var viewKey this}}}{{/if}}</div>
|
||||
</div>
|
||||
|
||||
<div>)</div>
|
||||
@@ -0,0 +1 @@
|
||||
{{#if value}}<span class="glyphicon glyphicon-paperclip small"></span>{{/if}}
|
||||
@@ -36,7 +36,8 @@ Espo.define('views/admin/dynamic-logic/conditions/group-base', 'view', function
|
||||
return {
|
||||
viewDataList: this.viewDataList,
|
||||
operator: this.operator,
|
||||
level: this.level
|
||||
level: this.level,
|
||||
groupOperator: this.getGroupOperator()
|
||||
};
|
||||
},
|
||||
|
||||
@@ -45,16 +46,16 @@ Espo.define('views/admin/dynamic-logic/conditions/group-base', 'view', function
|
||||
e.stopPropagation();
|
||||
this.trigger('remove-item');
|
||||
},
|
||||
'click > div.group-head [data-action="addField"]': function (e) {
|
||||
'click > div.group-bottom [data-action="addField"]': function (e) {
|
||||
this.actionAddField();
|
||||
},
|
||||
'click > div.group-head [data-action="addAnd"]': function (e) {
|
||||
'click > div.group-bottom [data-action="addAnd"]': function (e) {
|
||||
this.actionAddGroup('and');
|
||||
},
|
||||
'click > div.group-head [data-action="addOr"]': function (e) {
|
||||
'click > div.group-bottom [data-action="addOr"]': function (e) {
|
||||
this.actionAddGroup('or');
|
||||
},
|
||||
'click > div.group-head [data-action="addNot"]': function (e) {
|
||||
'click > div.group-bottom [data-action="addNot"]': function (e) {
|
||||
this.actionAddGroup('not');
|
||||
}
|
||||
},
|
||||
@@ -79,6 +80,12 @@ Espo.define('views/admin/dynamic-logic/conditions/group-base', 'view', function
|
||||
}, this);
|
||||
},
|
||||
|
||||
getGroupOperator: function () {
|
||||
if (this.operator === 'or') return 'or';
|
||||
|
||||
return 'and';
|
||||
},
|
||||
|
||||
getKey: function (i) {
|
||||
return 'view-' + this.level.toString() + '-' + this.number.toString() + '-' + i.toString();
|
||||
},
|
||||
@@ -126,6 +133,8 @@ Espo.define('views/admin/dynamic-logic/conditions/group-base', 'view', function
|
||||
view.render()
|
||||
}
|
||||
|
||||
this.controlAddItemVisibility();
|
||||
|
||||
this.listenToOnce(view, 'remove-item', function () {
|
||||
this.removeItem(number);
|
||||
}, this);
|
||||
@@ -151,6 +160,7 @@ Espo.define('views/admin/dynamic-logic/conditions/group-base', 'view', function
|
||||
this.clearView(key);
|
||||
|
||||
this.$el.find('[data-view-key="'+key+'"]').remove();
|
||||
this.$el.find('[data-view-ref-key="'+key+'"]').remove();
|
||||
|
||||
var index = -1;
|
||||
this.viewDataList.forEach(function (data, i) {
|
||||
@@ -161,6 +171,8 @@ Espo.define('views/admin/dynamic-logic/conditions/group-base', 'view', function
|
||||
if (~index) {
|
||||
this.viewDataList.splice(index, 1);
|
||||
}
|
||||
|
||||
this.controlAddItemVisibility();
|
||||
},
|
||||
|
||||
actionAddField: function () {
|
||||
@@ -216,6 +228,10 @@ Espo.define('views/admin/dynamic-logic/conditions/group-base', 'view', function
|
||||
addItemContainer: function (i) {
|
||||
var $item = $('<div data-view-key="'+this.getKey(i)+'"></div>');
|
||||
this.$el.find('> .item-list').append($item);
|
||||
|
||||
var groupOperatorLabel = this.translate(this.getGroupOperator(), 'logicalOperators', 'Admin');
|
||||
var $operatorItem = $('<div class="group-operator" data-view-ref-key="'+this.getKey(i)+'">' + groupOperatorLabel +'</div>');
|
||||
this.$el.find('> .item-list').append($operatorItem);
|
||||
},
|
||||
|
||||
actionAddGroup: function (operator) {
|
||||
@@ -231,6 +247,12 @@ Espo.define('views/admin/dynamic-logic/conditions/group-base', 'view', function
|
||||
});
|
||||
},
|
||||
|
||||
afterRender: function () {
|
||||
this.controlAddItemVisibility();
|
||||
},
|
||||
|
||||
controlAddItemVisibility: function () {}
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
@@ -38,7 +38,9 @@ Espo.define('views/admin/dynamic-logic/conditions/not', 'views/admin/dynamic-log
|
||||
return {
|
||||
viewKey: this.viewKey,
|
||||
operator: this.operator,
|
||||
hasItem: this.hasView(this.viewKey)
|
||||
hasItem: this.hasView(this.viewKey),
|
||||
level: this.level,
|
||||
groupOperator: this.getGroupOperator()
|
||||
};
|
||||
},
|
||||
|
||||
@@ -60,6 +62,8 @@ Espo.define('views/admin/dynamic-logic/conditions/not', 'views/admin/dynamic-log
|
||||
removeItem: function () {
|
||||
var key = this.getKey();
|
||||
this.clearView(key);
|
||||
|
||||
this.controlAddItemVisibility();
|
||||
},
|
||||
|
||||
getKey: function () {
|
||||
@@ -78,7 +82,15 @@ Espo.define('views/admin/dynamic-logic/conditions/not', 'views/admin/dynamic-log
|
||||
},
|
||||
|
||||
fetch: function () {
|
||||
var value = this.getView(this.viewKey).fetch();
|
||||
var view = this.getView(this.viewKey);
|
||||
if (!view) return {
|
||||
type: 'and',
|
||||
value: []
|
||||
};
|
||||
|
||||
var value = view.fetch();
|
||||
|
||||
console.log(value);
|
||||
|
||||
return {
|
||||
type: this.operator,
|
||||
@@ -86,6 +98,14 @@ Espo.define('views/admin/dynamic-logic/conditions/not', 'views/admin/dynamic-log
|
||||
};
|
||||
},
|
||||
|
||||
controlAddItemVisibility: function () {
|
||||
if (this.getView(this.getKey())) {
|
||||
this.$el.find(' > .group-bottom').addClass('hidden');
|
||||
} else {
|
||||
this.$el.find(' > .group-bottom').removeClass('hidden');
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
@@ -269,7 +269,7 @@ Espo.define('views/admin/entity-manager/modals/edit-entity', ['views/modal', 'mo
|
||||
});
|
||||
|
||||
var optionList = Object.keys(fieldDefs).filter(function (item) {
|
||||
if (!~['varchar', 'text', 'phone', 'email', 'personName', 'number'].indexOf(this.getMetadata().get(['entityDefs', scope, 'fields', item, 'type']))) {
|
||||
if (!~['varchar', 'wysiwyg', 'text', 'phone', 'email', 'personName', 'number'].indexOf(this.getMetadata().get(['entityDefs', scope, 'fields', item, 'type']))) {
|
||||
return false;
|
||||
}
|
||||
if (this.getMetadata().get(['entityDefs', scope, 'fields', item, 'disabled'])) {
|
||||
|
||||
@@ -108,11 +108,17 @@ Espo.define('views/admin/layouts/base', 'view', function (Dep) {
|
||||
fetch: function () {},
|
||||
|
||||
setup: function () {
|
||||
this.dataAttributeList = _.clone(this.dataAttributeList);
|
||||
this.buttonList = _.clone(this.buttonList);
|
||||
this.events = _.clone(this.events);
|
||||
this.scope = this.options.scope;
|
||||
this.type = this.options.type;
|
||||
|
||||
this.dataAttributeList =
|
||||
this.getMetadata().get(['clientDefs', this.scope, 'additionalLayouts', this.type, 'dataAttributeList'])
|
||||
||
|
||||
this.dataAttributeList;
|
||||
|
||||
this.dataAttributeList = Espo.Utils.clone(this.dataAttributeList);
|
||||
},
|
||||
|
||||
unescape: function (string) {
|
||||
|
||||
@@ -30,7 +30,7 @@ Espo.define('views/admin/layouts/list', 'views/admin/layouts/rows', function (De
|
||||
|
||||
return Dep.extend({
|
||||
|
||||
dataAttributeList: ['name', 'width', 'link', 'notSortable', 'align', 'view', 'customLabel'],
|
||||
dataAttributeList: ['name', 'width', 'link', 'notSortable', 'align', 'view', 'customLabel', 'widthPx'],
|
||||
|
||||
dataAttributesDefs: {
|
||||
link: {type: 'bool'},
|
||||
@@ -48,6 +48,10 @@ Espo.define('views/admin/layouts/list', 'views/admin/layouts/rows', function (De
|
||||
type: 'varchar',
|
||||
readOnly: true
|
||||
},
|
||||
widthPx: {
|
||||
type: 'int',
|
||||
readOnly: true
|
||||
},
|
||||
name: {
|
||||
type: 'varchar',
|
||||
readOnly: true
|
||||
|
||||
@@ -92,6 +92,14 @@ Espo.define('views/detail', 'views/main', function (Dep) {
|
||||
el: '#main > .header',
|
||||
scope: this.scope
|
||||
});
|
||||
|
||||
this.listenTo(this.model, 'sync', function (model) {
|
||||
if (model.hasChanged('name')) {
|
||||
if (this.getView('header')) {
|
||||
this.getView('header').reRender();
|
||||
}
|
||||
}
|
||||
}, this);
|
||||
},
|
||||
|
||||
setupRecord: function () {
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2018 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/email/fields/has-attachment', 'views/fields/base', function (Dep) {
|
||||
|
||||
return Dep.extend({
|
||||
|
||||
listTemplate: 'email/fields/has-attachment/detail',
|
||||
|
||||
detailTemplate: 'email/fields/has-attachment/detail',
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
@@ -342,7 +342,12 @@ Espo.define('views/fields/email', 'views/fields/varchar', function (Dep) {
|
||||
}
|
||||
|
||||
if (this.getPreferences().get('emailUseExternalClient')) {
|
||||
document.location.href = 'mailto:' + emailAddress;
|
||||
require('email-helper', function (EmailHelper) {
|
||||
var emailHelper = new EmailHelper();
|
||||
var link = emailHelper.composeMailToLink(attributes, this.getConfig().get('outboundEmailBccAddress'));
|
||||
document.location.href = link;
|
||||
}.bind(this));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -106,14 +106,14 @@ Espo.define('views/import/step2', 'view', function (Dep) {
|
||||
afterRender: function () {
|
||||
$container = $('#mapping-container');
|
||||
|
||||
$table = $('<table>').addClass('table').addClass('table-bordered');
|
||||
$table = $('<table>').addClass('table').addClass('table-bordered').css('table-layout', 'fixed');
|
||||
|
||||
$row = $('<tr>');
|
||||
if (this.formData.headerRow) {
|
||||
$cell = $('<th>').attr('width', '27%').html(this.translate('Header Row Value', 'labels', 'Import'));
|
||||
$cell = $('<th>').attr('width', '25%').html(this.translate('Header Row Value', 'labels', 'Import'));
|
||||
$row.append($cell);
|
||||
}
|
||||
$cell = $('<th>').attr('width', '33%').html(this.translate('Field', 'labels', 'Import'));
|
||||
$cell = $('<th>').attr('width', '25%').html(this.translate('Field', 'labels', 'Import'));
|
||||
$row.append($cell);
|
||||
$cell = $('<th>').html(this.translate('First Row Value', 'labels', 'Import'));
|
||||
$row.append($cell);
|
||||
@@ -139,7 +139,7 @@ Espo.define('views/import/step2', 'view', function (Dep) {
|
||||
value = value.substr(0, 200) + '...';
|
||||
}
|
||||
|
||||
$cell = $('<td>').html(value);
|
||||
$cell = $('<td>').css('overflow', 'hidden').html(value);
|
||||
$row.append($cell);
|
||||
|
||||
if (~['update', 'createAndUpdate'].indexOf(this.formData.action)) {
|
||||
|
||||
@@ -134,7 +134,7 @@ Espo.define('views/record/list-expanded', 'views/record/list', function (Dep) {
|
||||
},
|
||||
|
||||
getItemEl: function (model, item) {
|
||||
return this.options.el + ' li[data-id="' + model.id + '"] .cell[data-name="' + item.name + '"]';
|
||||
return this.options.el + ' li[data-id="' + model.id + '"] .cell[data-name="' + item.field + '"]';
|
||||
},
|
||||
|
||||
getRowContainerHtml: function (id) {
|
||||
|
||||
@@ -1840,6 +1840,9 @@ h5 {
|
||||
}
|
||||
|
||||
.dynamic-logic-expression-container {
|
||||
div.item-list[data-level="0"] {
|
||||
margin-left: 0;
|
||||
}
|
||||
div.item-list {
|
||||
margin-left: 30px;
|
||||
}
|
||||
@@ -1854,6 +1857,15 @@ h5 {
|
||||
line-height: 33px;
|
||||
}
|
||||
}
|
||||
.group-operator:last-child {
|
||||
display: none;
|
||||
}
|
||||
.group-bottom[data-level="0"] {
|
||||
margin-left: 0;
|
||||
}
|
||||
.group-bottom {
|
||||
margin-left: 30px;
|
||||
}
|
||||
}
|
||||
|
||||
.dynamic-logic-options {
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "espocrm",
|
||||
"version": "5.2.4",
|
||||
"version": "5.2.5",
|
||||
"description": "",
|
||||
"main": "index.php",
|
||||
"repository": {
|
||||
|
||||
Reference in New Issue
Block a user