Merge branch 'hotfix/5.0.6'

This commit is contained in:
yuri
2018-02-14 15:16:59 +02:00
64 changed files with 619 additions and 427 deletions
+20 -1
View File
@@ -50,13 +50,19 @@ class Htmlizer
protected $entityManager;
public function __construct(FileManager $fileManager, DateTime $dateTime, NumberUtil $number, $acl = null, $entityManager = null)
protected $metadata;
protected $language;
public function __construct(FileManager $fileManager, DateTime $dateTime, NumberUtil $number, $acl = null, $entityManager = null, $metadata = null, $language = null)
{
$this->fileManager = $fileManager;
$this->dateTime = $dateTime;
$this->number = $number;
$this->acl = $acl;
$this->entityManager = $entityManager;
$this->metadata = $metadata;
$this->language = $language;
}
protected function getAcl()
@@ -148,6 +154,14 @@ class Htmlizer
if (array_key_exists($field, $data)) {
$keyRaw = $field . '_RAW';
$data[$keyRaw] = $data[$field];
$fieldType = $this->getFieldType($entity->getEntityType(), $field);
if ($fieldType === 'enum') {
if ($this->language) {
$data[$field] = $this->language->translateOption($data[$field], $field, $entity->getEntityType());
}
}
$data[$field] = $this->format($data[$field]);
}
}
@@ -269,4 +283,9 @@ class Htmlizer
return $html;
}
protected function getFieldType($entityType, $field) {
if (!$this->metadata) return;
return $this->metadata->get(['entityDefs', $entityType, 'fields', $field, 'type']);
}
}
+10 -5
View File
@@ -186,7 +186,6 @@ class Base
{
$this->prepareResult($result);
$whereClause = array();
foreach ($where as $item) {
if (!isset($item['type'])) continue;
@@ -207,10 +206,17 @@ class Base
}
}
$whereClause = $this->convertWhere($where);
$result['whereClause'] = array_merge($result['whereClause'], $whereClause);
}
public function convertWhere(array $where, $ignoreAdditionaFilterTypes = false)
{
$whereClause = [];
$ignoreTypeList = array_merge(['bool', 'primary'], $this->additionalFilterTypeList);
$additionalFilters = array();
foreach ($where as $item) {
if (!isset($item['type'])) continue;
@@ -221,7 +227,7 @@ class Base
$whereClause[] = $part;
}
} else {
if (in_array($type, $this->additionalFilterTypeList)) {
if (!$ignoreAdditionaFilterTypes && in_array($type, $this->additionalFilterTypeList)) {
if (!empty($item['value'])) {
$methodName = 'apply' . ucfirst($type);
@@ -242,7 +248,7 @@ class Base
}
}
$result['whereClause'] = array_merge($result['whereClause'], $whereClause);
return $whereClause;
}
protected function applyLinkedWith($link, $idsValue, &$result)
@@ -1563,4 +1569,3 @@ class Base
$this->filterFollowed($result);
}
}
+1 -9
View File
@@ -139,7 +139,7 @@ return array (
'x' => 2,
'y' => 2,
'width' => 2,
'height' => 2
'height' => 4
],
(object) [
'id' => 'default-stream',
@@ -148,14 +148,6 @@ return array (
'y' => 0,
'width' => 2,
'height' => 4
],
(object) [
'id' => 'default-tasks',
'name' => 'Tasks',
'x' => 2,
'y' => 0,
'width' => 2,
'height' => 2
]
]
]
@@ -115,7 +115,7 @@ class SubscribeAgain extends \Espo\Core\EntryPoints\Base
}
echo $this->getLanguage()->translate('subscribedAgain', 'messages', 'Campaign');
echo '<br><br>';
echo '<a href="?entryPoint=unsubscribe&id='.$queueItemId.'">' . $this->getLanguage()->translate('Unsubscribe again', 'labels', 'Campaign') . '</a>';
echo '<a href="?entryPoint=unsubscribe&id='.htmlspecialchars($queueItemId).'">' . $this->getLanguage()->translate('Unsubscribe again', 'labels', 'Campaign') . '</a>';
}
}
}
@@ -115,7 +115,7 @@ class Unsubscribe extends \Espo\Core\EntryPoints\Base
}
echo $this->getLanguage()->translate('unsubscribed', 'messages', 'Campaign');
echo '<br><br>';
echo '<a href="?entryPoint=subscribeAgain&id='.$queueItemId.'">' . $this->getLanguage()->translate('Subscribe again', 'labels', 'Campaign') . '</a>';
echo '<a href="?entryPoint=subscribeAgain&id='.htmlspecialchars($queueItemId).'">' . $this->getLanguage()->translate('Subscribe again', 'labels', 'Campaign') . '</a>';
}
}
}
@@ -9,12 +9,12 @@
"priority": "Priority",
"type": "Type",
"description": "Description",
"inboundEmail": "Inbound Email",
"inboundEmail": "Group Email Account",
"lead": "Lead",
"attachments": "Attachments"
},
"links": {
"inboundEmail": "Inbound Email",
"inboundEmail": "Group Email Account",
"account": "Account",
"contact": "Contact (Primary)",
"Contacts": "Contacts",
@@ -96,8 +96,6 @@
"Copy Billing": "Копія рахунку"
},
"presetFilters": {
"customers": "Customers",
"partners": "Partners",
"recentlyCreated": "Нещодавно Створений"
}
}
@@ -1,6 +1,5 @@
{
"fields": {
"url": "URL",
"urlToUse": "Код для вставки замість URL",
"campaign": "Кампанія"
},
@@ -9,11 +9,9 @@
"priority": "Пріоритет",
"type": "Тип",
"description": "Опис",
"inboundEmail": "Вхідний лист",
"lead": "Лід"
},
"links": {
"inboundEmail": "Вхідний лист",
"account": "Контрагент",
"contact": "Контакт (Основний)",
"Contacts": "Контакти",
@@ -29,7 +29,7 @@
"Canceled": "Скасовано"
},
"type": {
"": "Жоден",
"": "Немає",
"Contract": "Контракт",
"NDA": "\n NDA",
"EULA": "\n EULA",
@@ -49,7 +49,7 @@
"Dead": "Мертвий"
},
"source": {
"": "Жоден",
"": "Немає",
"Call": "Дзвінок",
"Email": "Емейл",
"Existing Customer": "Існуючий замовник",
@@ -26,8 +26,6 @@
"stage": {
"Prospecting": "Проспектінг",
"Qualification": "Кваліфікація",
"Proposal": "Пропозиція",
"Negotiation": "Переговори",
"Needs Analysis": "Вимагає аналізу",
"Value Proposition": "Цінова пропозиція",
"Id. Decision Makers": "Визначення осіб, що приймають рішення",
@@ -35,7 +33,9 @@
"Proposal/Price Quote": "Квота пропозицій/цін",
"Negotiation/Review": "Переговори/перегляд",
"Closed Won": "Закрито переможно",
"Closed Lost": "Закрито провалом"
"Closed Lost": "Закрито провалом",
"Proposal": "Пропозиція",
"Negotiation": "Переговори"
}
},
"labels": {
@@ -5,13 +5,10 @@
"status": "Статус",
"dateStart": "Дата початку",
"dateEnd": "Кінцева дата",
"dateStartDate": "Date Start (all day)",
"dateEndDate": "Date End (all day)",
"priority": "Пріоритет",
"description": "Опис",
"isOverdue": "Прострочено",
"account": "Контрагент",
"dateCompleted": "Date Completed",
"attachments": "Вкладення",
"reminders": "Нагадування"
},
@@ -88,5 +88,6 @@
}
}
}
}
},
"iconClass": "glyphicon glyphicon-phone-alt"
}
@@ -1,103 +1,119 @@
{
"controller": "controllers/record",
"aclPortal": "crm:acl-portal/contact",
"views":{
"detail":"crm:views/contact/detail"
},
"recordViews":{
"detail": "crm:views/contact/record/detail",
"detailQuick": "crm:views/contact/record/detail-small"
},
"defaultSidePanelFieldLists": {
"detail": [
{
"name": "assignedUser"
},
{
"name": "teams"
},
{
"name": "portalUser"
}
],
"detailSmall": [
{
"name": "assignedUser"
},
{
"name": "teams"
},
{
"name": "portalUser"
}
]
},
"sidePanels":{
"detail":[
{
"name":"activities",
"label":"Activities",
"view":"crm:views/record/panels/activities",
"aclScope": "Activities"
},
{
"name":"history",
"label":"History",
"view":"crm:views/record/panels/history",
"aclScope": "Activities"
},
{
"name":"tasks",
"label":"Tasks",
"view":"crm:views/record/panels/tasks",
"aclScope": "Task"
}
],
"detailSmall":[
{
"name":"activities",
"label":"Activities",
"view":"crm:views/record/panels/activities",
"aclScope": "Activities"
},
{
"name":"history",
"label":"History",
"view":"crm:views/record/panels/history",
"aclScope": "Activities"
},
{
"name":"tasks",
"label":"Tasks",
"view":"crm:views/record/panels/tasks",
"aclScope": "Task"
}
]
},
"relationshipPanels": {
"campaignLogRecords": {
"rowActionsView": "views/record/row-actions/empty",
"select": false,
"create": false
},
"opportunities":{
"layout":"listForAccount"
},
"targetLists": {
"create": false,
"rowActionsView": "views/record/row-actions/relationship-unlink-only"
}
},
"boolFilterList": ["onlyMy"],
"additionalLayouts": {
"detailConvert": {
"type": "detail"
},
"listForAccount": {
"type": "listSmall"
}
},
"filterList": [
"portalUsers"
]
}
"controller": "controllers/record",
"aclPortal": "crm:acl-portal/contact",
"views": {
"detail": "crm:views/contact/detail"
},
"recordViews": {
"detail": "crm:views/contact/record/detail",
"detailQuick": "crm:views/contact/record/detail-small"
},
"defaultSidePanelFieldLists": {
"detail": [
{
"name": "assignedUser"
},
{
"name": "teams"
},
{
"name": "portalUser"
}
],
"detailSmall": [
{
"name": "assignedUser"
},
{
"name": "teams"
},
{
"name": "portalUser"
}
]
},
"sidePanels": {
"detail": [
{
"name": "activities",
"label": "Activities",
"view": "crm:views/record/panels/activities",
"aclScope": "Activities"
},
{
"name": "history",
"label": "History",
"view": "crm:views/record/panels/history",
"aclScope": "Activities"
},
{
"name": "tasks",
"label": "Tasks",
"view": "crm:views/record/panels/tasks",
"aclScope": "Task"
}
],
"detailSmall": [
{
"name": "activities",
"label": "Activities",
"view": "crm:views/record/panels/activities",
"aclScope": "Activities"
},
{
"name": "history",
"label": "History",
"view": "crm:views/record/panels/history",
"aclScope": "Activities"
},
{
"name": "tasks",
"label": "Tasks",
"view": "crm:views/record/panels/tasks",
"aclScope": "Task"
}
]
},
"relationshipPanels": {
"campaignLogRecords": {
"rowActionsView": "views/record/row-actions/empty",
"select": false,
"create": false
},
"opportunities": {
"layout": "listForAccount"
},
"targetLists": {
"create": false,
"rowActionsView": "views/record/row-actions/relationship-unlink-only"
}
},
"boolFilterList": [
"onlyMy"
],
"additionalLayouts": {
"detailConvert": {
"type": "detail"
},
"listForAccount": {
"type": "listSmall"
}
},
"filterList": [
"portalUsers"
],
"dynamicLogic": {
"fields": {
"title": {
"visible": {
"conditionGroup": [
{
"type": "isNotEmpty",
"attribute": "accountId"
}
]
}
}
}
}
}
@@ -95,5 +95,6 @@
}
}
}
}
},
"iconClass": "glyphicon glyphicon-briefcase"
}
@@ -1,73 +1,76 @@
{
"controller": "controllers/record",
"recordViews":{
"list": "crm:views/task/record/list",
"detail": "crm:views/task/record/detail"
},
"views": {
"list": "crm:views/task/list",
"detail": "crm:views/task/detail"
},
"dynamicLogic": {
"fields": {
"dateCompleted": {
"visible": {
"conditionGroup": [
{
"type": "equals",
"attribute": "status",
"value": "Completed"
}
]
}
},
"reminders": {
"visible": {
"conditionGroup": [
{
"type": "and",
"value": [
"controller": "controllers/record",
"recordViews": {
"list": "crm:views/task/record/list",
"detail": "crm:views/task/record/detail"
},
"views": {
"list": "crm:views/task/list",
"detail": "crm:views/task/detail"
},
"dynamicLogic": {
"fields": {
"dateCompleted": {
"visible": {
"conditionGroup": [
{
"type": "isNotEmpty",
"attribute": "dateEnd"
},
{
"type": "isEmpty",
"attribute": "dateEndDate"
},
{
"type": "notEquals",
"attribute": "status",
"value": "Completed"
},
{
"type": "notEquals",
"attribute": "status",
"value": "Canceled"
"type": "equals",
"attribute": "status",
"value": "Completed"
}
]
}
]
]
}
},
"reminders": {
"visible": {
"conditionGroup": [
{
"type": "and",
"value": [
{
"type": "isNotEmpty",
"attribute": "dateEnd"
},
{
"type": "isEmpty",
"attribute": "dateEndDate"
},
{
"type": "notEquals",
"attribute": "status",
"value": "Completed"
},
{
"type": "notEquals",
"attribute": "status",
"value": "Canceled"
}
]
}
]
}
}
}
}
},
"filterList": [
"actual",
{
"name":"completed",
"style": "success"
},
{
"name":"todays"
},
{
"name":"overdue",
"style": "danger"
},
{
"name":"deferred"
}
],
"boolFilterList": ["onlyMy"]
}
}
},
"filterList": [
"actual",
{
"name": "completed",
"style": "success"
},
{
"name": "todays"
},
{
"name": "overdue",
"style": "danger"
},
{
"name": "deferred"
}
],
"boolFilterList": [
"onlyMy"
],
"iconClass": "glyphicon glyphicon-list-alt"
}
@@ -24,7 +24,7 @@
"defaults": {
"displayRecords": 5,
"autorefreshInterval": 0.5,
"enabledScopeList": ["Meeting", "Call"]
"enabledScopeList": ["Meeting", "Call", "Task"]
},
"layout": [
{
@@ -47,7 +47,7 @@
"bool": {
"onlyMy": true
},
"primary": "actualStartingNotInPast"
"primary": "actualStartingNotInFuture"
}
},
"layout": [
@@ -5,6 +5,8 @@
"acl": true,
"aclPortal": true,
"aclPortalLevelList": ["all", "account", "contact", "own", "no"],
"activityStatusList": ["Not Started", "Started"],
"historyStatusList": ["Completed"],
"module": "Crm",
"customizable": true,
"importable": true,
@@ -55,7 +55,7 @@ class Task extends \Espo\Core\SelectManagers\Base
);
}
protected function filterActualStartingNotInPast(&$result)
protected function filterActualStartingNotInFuture(&$result)
{
$result['whereClause'][] = array(
array(
@@ -1160,7 +1160,7 @@ class Activities extends \Espo\Core\Services\Base
$unionPartList = [];
foreach ($entityTypeList as $entityType) {
if (!$this->getMetadata()->get(['scopes', $entityType, 'activity'])) continue;
if (!$this->getMetadata()->get(['scopes', $entityType, 'activity']) && $entityType !== 'Task') continue;
if (!$this->getAcl()->checkScope($entityType, 'read')) continue;
$selectParams = array(
@@ -1168,6 +1168,7 @@ class Activities extends \Espo\Core\Services\Base
'id',
'name',
'dateStart',
'dateEnd',
['VALUE:' . $entityType, 'entityType']
]
);
@@ -1180,36 +1181,39 @@ class Activities extends \Espo\Core\Services\Base
$selectManager->applyTextFilter($params['textFilter'], $selectParams);
}
$statusList = $this->getMetadata()->get(['scopes', $entityType, 'activityStatusList'], ['Planned']);
if (!$this->getMetadata()->get(['entityDefs', $entityType, 'fields', 'dateStart'])) continue;
if (!$this->getMetadata()->get(['entityDefs', $entityType, 'fields', 'dateEnd'])) continue;
$selectManager->applyBoolFilter('onlyMy', $selectParams);
$selectManager->addAndWhere([
'status' => $statusList
], $selectParams);
$selectManager->addOrWhere([
$selectManager->convertDateTimeWhere(array(
'type' => 'today',
'field' => 'dateStart',
'timeZone' => $selectManager->getUserTimeZone()
)),
[
if ($entityType === 'Task') {
$selectManager->applyPrimaryFilter('actualStartingNotInFuture', $selectParams);
} else {
$selectManager->applyPrimaryFilter('planned', $selectParams);
$selectManager->addOrWhere([
$selectManager->convertDateTimeWhere(array(
'type' => 'future',
'field' => 'dateEnd',
'type' => 'today',
'field' => 'dateStart',
'timeZone' => $selectManager->getUserTimeZone()
)),
$selectManager->convertDateTimeWhere(array(
'type' => 'before',
'field' => 'dateStart',
'value' => (new \DateTime())->modify('+' . self::UPCOMING_ACTIVITIES_FUTURE_DAYS . ' days')->format('Y-m-d H:i:s'),
'timeZone' => $selectManager->getUserTimeZone()
))
]
], $selectParams);
[
$selectManager->convertDateTimeWhere(array(
'type' => 'future',
'field' => 'dateEnd',
'timeZone' => $selectManager->getUserTimeZone()
)),
$selectManager->convertDateTimeWhere(array(
'type' => 'before',
'field' => 'dateStart',
'value' => (new \DateTime())->modify('+' . self::UPCOMING_ACTIVITIES_FUTURE_DAYS . ' days')->format('Y-m-d H:i:s'),
'timeZone' => $selectManager->getUserTimeZone()
))
]
], $selectParams);
}
$sql = $this->getEntityManager()->getQuery()->createSelectQuery($entityType, $selectParams);
@@ -1232,7 +1236,7 @@ class Activities extends \Espo\Core\Services\Base
$row = $sth->fetch(\PDO::FETCH_ASSOC);
$totalCount = $row['COUNT'];
$unionSql .= " ORDER BY dateStart ASC";
$unionSql .= " ORDER BY dateStart, dateEnd ASC";
$unionSql .= " LIMIT :offset, :maxSize";
$sth = $pdo->prepare($unionSql);
@@ -54,7 +54,8 @@
},
"links": {
"filters": "Filters",
"emails": "Emails"
"emails": "Emails",
"assignToUser": "Assign to User"
},
"options": {
"status": {
@@ -9,7 +9,6 @@
"Customization": "Користувацькі налаштування",
"Available Fields": "Доступні поля",
"Layout": "Макет",
"Entity Manager": "Entity Manager",
"Add Panel": "Додати панель",
"Add Field": "Додати поле",
"Settings": "Налаштування",
@@ -82,17 +81,11 @@
"currency": "Валюта",
"date": "Дата",
"datetime": "Дата, час",
"datetimeOptional": "Date/DateTime",
"email": "Емейл",
"enum": "Список",
"enumInt": "Список цілі числа",
"enumFloat": "Список дробні числа",
"float": "Десятовий дріб",
"int": "Ціле число",
"link": "Link",
"linkMultiple": "Link Multiple",
"linkParent": "Link Parent",
"multienim": "Множинний список",
"phone": "Телефон",
"text": "Текст",
"url": "URL-адреса",
@@ -107,6 +100,7 @@
"wysiwyg": "Редактор",
"map": "Карта",
"currencyConverted": "Валюта (ковертована)",
"int": "Ціле число",
"number": "Номер"
},
"fields": {
@@ -119,14 +113,11 @@
"options": "Опції",
"after": "Після (поле)",
"before": "Перед (поле)",
"link": "Link",
"field": "Поле",
"min": "Мінімум",
"max": "Максимум",
"translation": "Переклад",
"previewSize": "Розмір передперегляду",
"noEmptyString": "Немає вільного рядка",
"defaultType": "Default Type",
"seeMoreDisabled": "Відключити обрізку тексту",
"entityList": "Список об'єктів",
"isSorted": "Відсортовано (за алфавітом)",
@@ -149,7 +140,8 @@
"dynamicLogicRequired": "Умови, які роблять поле обов’язковим",
"dynamicLogicOptions": "Умовні варіанти",
"probabilityMap": "Стадія імовірності (%)",
"readOnly": "Виключно читання"
"readOnly": "Виключно читання",
"noEmptyString": "Немає вільного рядка"
},
"messages": {
"selectEntityType": "Оберіть тип сутности у лівому меню.",
@@ -163,8 +155,7 @@
"upgradeDone": "EspoCRM оновлено до версії <strong>{version}</strong>.",
"upgradeBackup": "Перед оновленням рекомендуємо створити резевну копію файлів EspoCRM та даних",
"thousandSeparatorEqualsDecimalMark": "Розділювач тисячних не може бути таким самим, як розділювач десяткових.",
"userHasNoEmailAddress": "В користувача не вказана адреса електронної скриньки.",
"uninstallConfirmation": "Ви впевнені, що хочете видалити розширення?"
"userHasNoEmailAddress": "В користувача не вказана адреса електронної скриньки."
},
"descriptions": {
"settings": "Системні налаштування додатку.",
@@ -189,10 +180,8 @@
"currency": "Налаштування валюти та курсу обміну.",
"extensions": "Встановлення або видалення розширень.",
"integrations": "Інтеграція зі сторонніми сервісами.",
"notifications": "In-app and email notification settings.",
"inboundEmails": "Групувати поштові акаунти IMAP. Імпорт пошти та інтерфейс доступу до звернення через електронну пошту.",
"portalUsers": "Користувачі порталу.",
"entityManager": "Create and edit custom entities. Manage fields and relationships.",
"emailFilters": "Електронні повідомлення, які відповідають вказаному фільтру, імпортуватися не будуть",
"actionHistory": "Лоґ дій користуча."
},
@@ -1,7 +1,4 @@
{
"label": {
"Field": "Поле"
},
"options": {
"operators": {
"equals": "Так само",
@@ -30,11 +30,11 @@
"name": "Тема",
"isReplied": "Відповіли",
"isNotReplied": "Без відповіді",
"sentBy": "Надіслав (Користувач)",
"folder": "Папка",
"inboundEmails": "Група облікових записів",
"emailAccounts": "Особисті облікові записи",
"hasAttachment": "Має Вкладення"
"hasAttachment": "Має Вкладення",
"sentBy": "Надіслав (Користувач)"
},
"links": {
"replied": "Відповіли",
@@ -70,8 +70,6 @@
"Mark Read": "Прочитане",
"Sending...": "Шле...",
"Save Draft": "Зберегти чернетку",
"Mark all as read": "Mark all as read",
"Show Plain Text": "Show Plain Text",
"Mark as Important": "Відмітити важливим",
"Unmark Importance": "Відмітити не важливим",
"Move to Trash": "Видалити в сміття",
@@ -89,8 +87,6 @@
"presetFilters": {
"sent": "Відправлено",
"archived": "В архіві",
"inbox": "Inbox",
"drafts": "Drafts",
"trash": "Сміття",
"important": "Важливо"
},
@@ -7,7 +7,6 @@
"password": "Пароль",
"port": "Порт",
"monitoredFolders": "Відслідковувані теки",
"ssl": "SSL",
"fetchSince": "Вибірки з",
"emailAddress": "Поштова скринька",
"sentFolder": "Папка відправлені",
@@ -34,15 +33,12 @@
},
"labels": {
"Create EmailAccount": "Додати емейл-акаунт",
"IMAP": "IMAP",
"Main": "Основне",
"Test Connection": "Перевірка з'єднання",
"Send Test Email": "Надіслати тестове електронне повідомлення",
"SMTP": "SMTP"
"Send Test Email": "Надіслати тестове електронне повідомлення"
},
"messages": {
"couldNotConnectToImap": "Не вдається підключитися до сервера IMAP",
"connectionIsOk": "Connection is Ok"
"couldNotConnectToImap": "Не вдається підключитися до сервера IMAP"
},
"tooltips": {
"monitoredFolders": "You can add 'Sent' folder to sync emails sent from external email client.",
@@ -14,10 +14,6 @@
"stream": "Потік",
"label": "Мітка",
"linkType": "Тип посилання",
"entityForeign": "Foreign Entity",
"linkForeign": "Foreign Link",
"link": "Link",
"labelForeign": "Foreign Label",
"sortBy": "Сортування за замовчуванням (поле)",
"sortDirection": "Сортування за замовчуванням (напрямок)",
"relationName": "Назва середньої таблиці",
@@ -35,7 +31,6 @@
"": "Нема",
"Base": "База",
"Person": "Особа",
"CategoryTree": "Category Tree",
"Event": "Подія",
"BasePlus": "База плюс",
"Company": "Компанія"
@@ -46,10 +41,6 @@
"manyToOne": "Багато-до-одного",
"parentToChildren": "Від батька до сина",
"childrenToParent": "Від сина до батька"
},
"sortDirection": {
"asc": "Ascending",
"desc": "Descending"
}
},
"messages": {
@@ -3,11 +3,5 @@
"fieldList": "Список полів",
"exportAllFields": "Експортувати всі поля",
"format": "Формат"
},
"options": {
"format": {
"csv": "CSV",
"xlsx": "XLSX (Excel)"
}
}
}
@@ -4,7 +4,7 @@
},
"options": {
"dateTimeDefault": {
"": "Жоден",
"": "Немає",
"javascript: return this.dateTime.getNow(1);": "На даний час",
"javascript: return this.dateTime.getNow(5);": "На даний час (5m)",
"javascript: return this.dateTime.getNow(15);": "На даний час (15m)",
@@ -30,7 +30,7 @@
"javascript: return this.dateTime.getDateTimeShiftedFromNow(1, 'week', 15);": "+1 тиждень"
},
"dateDefault": {
"": "Жоден",
"": "Немає",
"javascript: return this.dateTime.getToday();": "Сьогодні",
"javascript: return this.dateTime.getDateShiftedFromToday(1, 'days');": "+1 день",
"javascript: return this.dateTime.getDateShiftedFromToday(2, 'days');": "+2 дні",
@@ -45,7 +45,6 @@
"Dashboard": "Панель дашлетів",
"InboundEmail": "Inbound Email Accounts",
"Stream": "Потік",
"Import": "Import Results",
"Template": "Шаблони",
"Job": "Завдання",
"EmailFilter": "Фільтри пошти",
@@ -106,7 +105,6 @@
"Details": "Деталі",
"Add Field": "Додати поле",
"Add Dashlet": "Додати дашлет",
"Filter": "Filter",
"Edit Dashboard": "Змінити панель дашлетів",
"Add": "Додати",
"Add Item": "Додати елемент",
@@ -167,7 +165,6 @@
"change": "змінити",
"Change": "Зміна",
"Primary": "Первинне",
"Save Filter": "Save Filter",
"Administration": "Адміністрування",
"Run Import": "Запустити імпорт",
"Duplicate": "Дуплікат",
@@ -181,10 +178,6 @@
"Close": "Закрити",
"Yes": "Так",
"No": "Немає",
"Value": "Value",
"Current version": "Current version",
"List View": "List View",
"Tree View": "Tree View",
"Unlink All": "Від’єднати всі",
"Total": "Загальний",
"Print to PDF": "Друк в PDF",
@@ -208,14 +201,11 @@
"messages": {
"pleaseWait": "Будь ласка, зачекайте...",
"posting": "Постимо...",
"confirmLeaveOutMessage": "Are you sure you want to leave the form?",
"notModified": "Ви не внесли змін до запису",
"fieldIsRequired": "{field} обов'язкове",
"fieldShouldAfter": "{field} мусить бути після {otherField}",
"fieldShouldBefore": "{field} мусить бути до {otherField}",
"fieldShouldBeBetween": "{field} мусить бути між {min} і {max}",
"fieldShouldBeLess": "{field} мусить бути менше ніж {value}",
"fieldShouldBeGreater": "{field} мусить бути більше ніж {value}",
"fieldBadPasswordConfirm": "Правильність {field} не підтверджено",
"resetPreferencesDone": "Налаштування скинуті до значень за замовчуванням",
"confirmation": "Ви певні?",
@@ -237,7 +227,6 @@
"checkForNewNotifications": "Перевірити інформування",
"duplicate": "Створений Вами запис був дубльований",
"dropToAttach": "Відкріпити прикріплення",
"streamPostInfo": "Тип <strong>@username</strong> для згадування користувачів у дописі.\nПрипустимий синтаксис розмітки:`<code>code</code>`\n**<strong>strong text</strong>**\n*<em>emphasized text</em>*\n~<del>deleted text</del>~\n> blockquote\n[текст](url)",
"writeMessageToSelf": "Написати повідомлення в своєму потоці",
"checkForNewNotes": "Перевірити наявність оновлень потоку",
"internalPost": "Повідомлення буде видно тільки внутрішнім користувачам",
@@ -255,7 +244,10 @@
"fieldShouldBeInt": "{field} повинно бути цілим числом",
"fieldShouldBeDate": "{field} має бути дійсною дата",
"fieldShouldBeDatetime": "{field} має бути дійсним дата/час",
"internalPostTitle": "Повідомлення бачитимуть тільки внутрішні користувачі"
"internalPostTitle": "Повідомлення бачитимуть тільки внутрішні користувачі",
"fieldShouldBeLess": "{field} мусить бути менше ніж {value}",
"fieldShouldBeGreater": "{field} мусить бути більше ніж {value}",
"streamPostInfo": "Тип <strong>@username</strong> для згадування користувачів у дописі.\nПрипустимий синтаксис розмітки:`<code>code</code>`\n**<strong>strong text</strong>**\n*<em>emphasized text</em>*\n~<del>deleted text</del>~\n> blockquote\n[текст](url)"
},
"boolFilters": {
"onlyMy": "Тільки моє",
@@ -290,15 +282,8 @@
"description": "Опис",
"address": "Адреса",
"phoneNumber": "Телефон",
"phoneNumberMobile": "Phone (Mobile)",
"phoneNumberHome": "Phone (Home)",
"phoneNumberFax": "Phone (Fax)",
"phoneNumberOffice": "Phone (Office)",
"phoneNumberOther": "Phone (Other)",
"order": "Сортування",
"parent": "Батько",
"children": "Children",
"id": "ID"
"parent": "Батько"
},
"links": {
"assignedUser": "Відповідальний",
@@ -324,7 +309,6 @@
"streamMessages": {
"post": "{user} написав на {entityType} {entity}",
"attach": "{user} прикрипив до {entityType} {entity}",
"status": "{user} updated {field} of {entityType} {entity}",
"update": "{user} поновив {entityType} {entity}",
"postTargetTeam": "{user} написав команді {target}",
"postTargetTeams": "{user} написав командам {target}",
@@ -334,7 +318,6 @@
"postTargetYou": "{user} написав для вас",
"postTargetYouAndOthers": "{user} написав для {target} та вас",
"postTargetAll": "{user} написав для всіх",
"mentionInPost": "{user} mentioned {mentioned} in {entityType} {entity}",
"mentionYouInPost": "{user} згадав вас в {entityType} {entity} ",
"mentionInPostTarget": "{user} згаданий {mentioned} в повідомленні",
"mentionYouInPostTarget": "{user} згадав вас у повідомленні також {target}",
@@ -537,7 +520,6 @@
"afterXDays": "Після Х днів"
},
"searchRanges": {
"is": "Is",
"isEmpty": "Пусто",
"isNotEmpty": "Не пусто",
"isFromTeams": "Від команди",
@@ -550,9 +532,7 @@
"varcharSearchRanges": {
"equals": "Дорівнює",
"like": "Це довподоби (%)",
"startsWith": "Starts With",
"endsWith": "Закінчується",
"contains": "Contains",
"isEmpty": "Пусто",
"isNotEmpty": "Не пусто"
},
@@ -687,10 +667,8 @@
}
},
"themes": {
"Espo": "Espo",
"Sakura": "Сакура",
"Violet": "Фіолетовий",
"EspoRtl": "RTL Espo",
"EspoVertical": "Espo бокова панель",
"SakuraVertical": "Сакура бокова панель",
"VioletVertical": "Фіолет бокова панель",
@@ -1,6 +1,5 @@
{
"labels": {
"Revert Import": "Revert Import",
"Return to Import": "Повернутися до імпорту",
"Run Import": "Запустити імпорт",
"Back": "Назад",
@@ -11,10 +10,6 @@
"Updated": "Поновлено",
"Result": "Результат",
"Show records": "Показати записи",
"Remove Duplicates": "Remove Duplicates",
"importedCount": "Imported (count)",
"duplicateCount": "Duplicates (count)",
"updatedCount": "Updated (count)",
"Create Only": "Тільки створення",
"Create and Update": "Створення та оновлення",
"Update Only": "Тільки оновлення",
@@ -53,15 +48,10 @@
},
"messages": {
"utf8": "Мусить бути в кодуванні utf-8",
"duplicatesRemoved": "Duplicates removed",
"inIdle": "Виконати у фоновому режимі (для великих даних; через cron)"
},
"fields": {
"file": "Файл",
"entityType": "Entity Type",
"imported": "Imported Records",
"duplicates": "Duplicate Records",
"updated": "Updated Records",
"status": "Статус"
},
"options": {
@@ -10,7 +10,6 @@
"port": "Порт",
"monitoredFolders": "Відслідковувані теки",
"trashFolder": "Кошик",
"ssl": "SSL",
"createCase": "Створити Звернення",
"reply": "Авто-Відповідь",
"caseDistribution": "Дистрибуція Звернень",
@@ -45,7 +44,7 @@
"Inactive": "Неактивний"
},
"caseDistribution": {
"": "Жоден",
"": "Немає",
"Direct-Assignment": "Пряме призначення",
"Round-Robin": "Циклічне",
"Least-Busy": "Найвільнішим"
@@ -53,7 +52,6 @@
},
"labels": {
"Create InboundEmail": "Створити емейл-акаунт",
"IMAP": "IMAP",
"Actions": "Дії",
"Main": "Основне"
},
@@ -5,9 +5,10 @@
"attempts": "Залишилось спроб",
"failedAttempts": "Невдалі спроби",
"serviceName": "Обслуговування",
"method": "Метод",
"methodName": "Метод",
"scheduledJob": "Запланована робота",
"data": "Дата"
"data": "Дата",
"method": "Метод"
},
"options": {
"status": {
@@ -3,7 +3,6 @@
"name": "Ім'я",
"logo": "Лого",
"companyLogo": "Лого",
"url": "URL",
"portalRoles": "Ролі",
"isActive": "Активний",
"isDefault": "Чи за замовчуванням",
@@ -5,7 +5,6 @@
"labels": {
"Access": "Доступ",
"Create PortalRole": "Створити Роль порталу",
"Scope Level": "Область застосування Рівень",
"Field Level": "Field Level"
"Scope Level": "Область застосування Рівень"
}
}
@@ -18,19 +18,18 @@
"smtpPassword": "Пароль",
"smtpEmailAddress": "Поштова скринька",
"exportDelimiter": "Експортувати роздільник даних",
"autoFollowEntityTypeList": "Авто-підписка",
"signature": "Підпис емейла",
"dashboardTabList": "Список меню",
"tabList": "Список меню",
"defaultReminders": "Default Reminders",
"theme": "Тема",
"useCustomTabList": "Власний список меню",
"emailReplyToAllByDefault": "Емайл Відповісти Все за замовчуванням",
"receiveAssignmentEmailNotifications": "Отримувати повідомлення при призначенні",
"receiveMentionEmailNotifications": "Сповіщення по електронні пошті про згадування в повідомленнях",
"receiveStreamEmailNotifications": "Сповіщення по електронні пошті про повідомлення та оновлення статусу",
"dashboardLayout": "Макет панелі дашлетів",
"emailReplyForceHtml": "Відправити відповідь в HTML",
"autoFollowEntityTypeList": "Авто-підписка",
"emailReplyToAllByDefault": "Емайл Відповісти Все за замовчуванням",
"doNotFillAssignedUserIfNotRequired": "Не назначати користувача, якщо це не обов’язково",
"followEntityOnStreamPost": "Автоматично підписатись після публікації в потоці"
},
@@ -18,8 +18,7 @@
"labels": {
"Access": "Доступ",
"Create Role": "Створити роль",
"Scope Level": "Область застосування Рівень",
"Field Level": "Field Level"
"Scope Level": "Область застосування Рівень"
},
"options": {
"accessList": {
@@ -35,25 +35,19 @@
"globalSearchEntityList": "Список сутнотей для Глобального пошуку",
"authenticationMethod": "Метод автентифікації",
"ldapHost": "Хост",
"ldapAccountCanonicalForm": "Account Canonical Form",
"ldapAccountDomainName": "Account Domain Name",
"ldapTryUsernameSplit": "Спробувати відділити ім'я користувача",
"ldapCreateEspoUser": "Створити користувача в EspoCRM",
"ldapUserLoginFilter": "Фільтр логіну користувача",
"ldapAccountDomainNameShort": "Account Domain Name Short",
"ldapOptReferrals": "Оптові реферали",
"exportDisabled": "Вимкнути експортування (доступно лише адміністру)",
"b2cMode": "Режим В2С",
"avatarsDisabled": "Вимкнути аватари",
"followCreatedEntities": "Підписатися на створені сутності",
"displayListViewRecordCount": "Дисплей Загальна кількість (у вигляді списку)",
"theme": "Тема",
"userThemesDisabled": "Відключення теми користувача",
"emailMessageMaxSize": "Емайл Максимальний розмір (Мб)",
"massEmailMaxPerHourCount": "Максимальна кількість відісланих за годину листів",
"personalEmailMaxPortionSize": "Максимальний розмір частини електронної пошти для витягнення особистого облікового запису",
"inboundEmailMaxPortionSize": "Максимальний розмір частини електронної пошти для вибірки облікових записів груп",
"maxEmailAccountCount": "Максимальна кількість особистих болікових записів на користувача",
"authTokenLifetime": "Час існування токенів аутентифікації (в годинах)",
"authTokenMaxIdleTime": "Максимальний час простою токену аутентифікації (години)",
"dashboardLayout": "Макет панелі дашлетів (за замовчуванням)",
@@ -86,7 +80,9 @@
"activitiesEntityList": "Список сутностей Діяльності",
"historyEntityList": "Список сутностей Історії",
"currencyFormat": "Формат валюти",
"currencyDecimalPlaces": "Currency Decimal Places"
"followCreatedEntities": "Підписатися на створені сутності",
"massEmailMaxPerHourCount": "Максимальна кількість відісланих за годину листів",
"maxEmailAccountCount": "Максимальна кількість особистих болікових записів на користувача"
},
"options": {
"weekStart": {
@@ -101,7 +97,6 @@
"tooltips": {
"recordsPerPage": "Кількість записів, що початково відображаються у списках.",
"recordsPerPageSmall": "Кількість записів, що початково відображаються у панелях зв'язків.",
"outboundEmailIsShared": "Дозволити користувачам надсилати повідомлення через цей SMTP.",
"followCreatedEntities": "Користувачі будуть автоматично підписані на записи, які вони створюють",
"emailMessageMaxSize": "Усі вхідні повідомлення електронної пошти, що перевищують зазначений розмір вивантажуватимуться без тексту і вкладень.",
"authTokenLifetime": "Визначає, як довго можуть існувати токени.\n0 - означає відсутність закінчення терміну дії.",
@@ -129,15 +124,14 @@
"ldapUserTeams": "Команди для створеного користувача. Детальніше в профілі користувача.",
"ldapUserDefaultTeam": "Команди для створеного користувача за замовчуванням. Детальніше про це читайте профіль користувача.",
"b2cMode": "За замовчуванням EspoCRM адаптований для B2B. Ви можете переключити його на B2C.",
"currencyDecimalPlaces": "Кількість знаків після десяткової коми. "
"currencyDecimalPlaces": "Кількість знаків після десяткової коми. ",
"outboundEmailIsShared": "Дозволити користувачам надсилати повідомлення через цей SMTP."
},
"labels": {
"System": "Система",
"Locale": "Локаль",
"SMTP": "Протокол SMTP",
"Configuration": "Конфігурація",
"In-app Notifications": "In-app Notifications",
"Email Notifications": "Email Notifications",
"Currency Settings": "Налаштування валюти",
"Currency Rates": "Курси валют",
"Mass Email": "Масова розсилка електронної пошти",
@@ -76,5 +76,6 @@
],
"defaultFilterData": {
},
"boolFilterList": []
"boolFilterList": [],
"iconClass": "glyphicon glyphicon-envelope"
}
@@ -3,6 +3,8 @@
"layouts": false,
"tab": true,
"acl": "recordAllTeamNo",
"aclPortal": true,
"aclPortalLevelList": ["all", "no"],
"customizable": true,
"disabled": false
}
+10 -1
View File
@@ -53,6 +53,7 @@ class Pdf extends \Espo\Core\Services\Base
$this->addDependency('dateTime');
$this->addDependency('number');
$this->addDependency('entityManager');
$this->addDependency('defaultLanguage');
}
protected function getAcl()
@@ -95,7 +96,15 @@ class Pdf extends \Espo\Core\Services\Base
throw new Forbidden();
}
$htmlizer = new Htmlizer($this->getFileManager(), $this->getInjection('dateTime'), $this->getInjection('number'), $this->getAcl(), $this->getInjection('entityManager'));
$htmlizer = new Htmlizer(
$this->getFileManager(),
$this->getInjection('dateTime'),
$this->getInjection('number'),
$this->getAcl(),
$this->getInjection('entityManager'),
$this->getInjection('metadata'),
$this->getInjection('defaultLanguage')
);
$pdf = new \Espo\Core\Pdf\Tcpdf();
+6 -7
View File
@@ -397,13 +397,6 @@ class Record extends \Espo\Core\Services\Base
$assignmentPermission = $this->getAcl()->get('assignmentPermission');
if (empty($assignedUserId)) {
if ($assignmentPermission === 'no') {
return false;
}
return true;
}
if ($assignmentPermission === true || $assignmentPermission === 'yes' || !in_array($assignmentPermission, ['team', 'no'])) {
return true;
}
@@ -419,6 +412,12 @@ class Record extends \Espo\Core\Services\Base
}
if ($toProcess) {
if (empty($assignedUserId)) {
if ($assignmentPermission == 'no') {
return false;
}
return true;
}
if ($assignmentPermission == 'no') {
if ($this->getUser()->id != $assignedUserId) {
return false;
@@ -83,15 +83,22 @@ Espo.define('crm:views/dashlets/abstract/chart', ['views/dashlets/abstract/base'
}
}
this.once('after:render', function () {
$(window).on('resize.chart' + this.name, function () {
this.on('resize', function () {
if (!this.isRendered()) return;
setTimeout(function () {
this.adjustContainer();
this.draw();
}.bind(this));
}.bind(this), 50);
}, this);
$(window).on('resize.chart' + this.id, function () {
this.adjustContainer();
this.draw();
}.bind(this));
this.once('remove', function () {
$(window).off('resize.chart' + this.name)
$(window).off('resize.chart' + this.id)
}, this);
},
@@ -34,7 +34,7 @@ Espo.define('crm:views/dashlets/activities', ['views/dashlets/abstract/base', 'm
_template: '<div class="list-container">{{{list}}}</div>',
rowActionsView: 'crm:views/meeting/record/row-actions/dashlet',
rowActionsView: 'crm:views/record/row-actions/activities-dashlet',
defaultListLayout: {
rows: [
@@ -57,6 +57,29 @@ Espo.define('crm:views/dashlets/activities', ['views/dashlets/abstract/base', 'm
]
},
listLayoutEntityTypeMap: {
Task: {
rows: [
[
{
name: 'ico',
view: 'crm:views/fields/ico',
params: {
notRelationship: true
}
},
{
name: 'name',
link: true,
},
],
[
{name: 'dateEnd'}
]
]
}
},
init: function () {
Dep.prototype.init.call(this);
},
@@ -68,6 +91,10 @@ Espo.define('crm:views/dashlets/activities', ['views/dashlets/abstract/base', 'm
this.listLayout = {};
this.scopeList.forEach(function (item) {
if (item in this.listLayoutEntityTypeMap) {
this.listLayout[item] = this.listLayoutEntityTypeMap[item];
return;
}
this.listLayout[item] = this.defaultListLayout;
}, this);
@@ -106,7 +133,7 @@ Espo.define('crm:views/dashlets/activities', ['views/dashlets/abstract/base', 'm
this.collection.data.entityTypeList = this.scopeList;
this.listenToOnce(this.collection, 'sync', function () {
this.createView('list', 'crm:views/meeting/record/list-expanded', {
this.createView('list', 'crm:views/record/list-activities-dashlet', {
el: this.options.el + ' > .list-container',
pagination: false,
type: 'list',
@@ -32,10 +32,21 @@ Espo.define('crm:views/dashlets/options/activities', 'views/dashlets/options/bas
init: function () {
Dep.prototype.init.call(this);
this.fields.enabledScopeList.options = this.getConfig().get('activitiesEntityList') || [];
var activitiesEntityList = [];
var entityTypeList = [];
var activitiesEntityList = Espo.Utils.clone(this.getConfig().get('activitiesEntityList') || []);
activitiesEntityList.push('Task');
activitiesEntityList.forEach(function (item) {
if (this.getMetadata().get(['scopes', item, 'disabled'])) return;
if (!this.getAcl().checkScope(item)) return;
entityTypeList.push(item);
}, this);
this.fields.enabledScopeList.options = entityTypeList;
}
});
});
@@ -32,6 +32,8 @@ Espo.define('crm:views/dashlets/sales-by-month', 'crm:views/dashlets/abstract/ch
name: 'SalesByMonth',
columnWidth: 50,
setupDefaultOptions: function () {
this.defaultOptions['dateFrom'] = this.defaultOptions['dateFrom'] || moment().format('YYYY') + '-01-01';
this.defaultOptions['dateTo'] = this.defaultOptions['dateTo'] || moment().format('YYYY') + '-12-31';
@@ -94,8 +96,17 @@ Espo.define('crm:views/dashlets/sales-by-month', 'crm:views/dashlets/abstract/ch
this.colorBad = this.successColor;
},
getTickNumber: function () {
var containerWidth = this.$container.width();
var tickNumber = Math.floor(containerWidth / this.columnWidth);
return tickNumber;
},
draw: function () {
var self = this;
var tickNumber = this.getTickNumber();
this.flotr.draw(this.$container.get(0), this.chartData, {
shadowSize: false,
bars: {
@@ -131,11 +142,12 @@ Espo.define('crm:views/dashlets/sales-by-month', 'crm:views/dashlets/abstract/ch
xaxis: {
min: 0,
color: this.textColor,
noTicks: tickNumber,
tickFormatter: function (value) {
if (value % 1 == 0) {
var i = parseInt(value);
if (i in self.monthList) {
if (self.monthList.length > 12 && i === self.monthList.length - 1) {
if (self.monthList.length - tickNumber > 5 && i === self.monthList.length - 1) {
return '';
}
return moment(self.monthList[i] + '-01').format('MMM YYYY');
+6 -16
View File
@@ -34,25 +34,15 @@ Espo.define('crm:views/fields/ico', 'views/fields/base', function (Dep) {
var icoTpl;
if (this.params.notRelationship) {
icoTpl = '<span class="glyphicon glyphicon-{icoName} text-muted action" style="cursor: pointer" title="'+this.translate('View')+'" data-action="quickView" data-id="'+this.model.id+'" data-scope="'+this.model.name+'"></span>';
icoTpl = '<span class="{iconClass} text-muted action icon" style="cursor: pointer" title="'+this.translate('View')+'" data-action="quickView" data-id="'+this.model.id+'" data-scope="'+this.model.name+'"></span>';
} else {
icoTpl = '<span class="glyphicon glyphicon-{icoName} text-muted action" style="cursor: pointer" title="'+this.translate('View')+'" data-action="quickView" data-id="'+this.model.id+'"></span>';
icoTpl = '<span class="{iconClass} text-muted action icon" style="cursor: pointer" title="'+this.translate('View')+'" data-action="quickView" data-id="'+this.model.id+'"></span>';
}
switch (this.model.name) {
case 'Meeting':
tpl = icoTpl.replace('{icoName}', 'briefcase');
break;
case 'Call':
tpl = icoTpl.replace('{icoName}', 'phone-alt');
break;
case 'Email':
tpl = icoTpl.replace('{icoName}', 'envelope');
break;
default:
tpl = icoTpl.replace('{icoName}', 'calendar');
break;
}
var iconClass = this.getMetadata().get(['clientDefs', this.model.name, 'iconClass']) || 'glyphicon glyphicon-briefcase';
tpl = icoTpl.replace('{iconClass}', iconClass);
this._template = tpl;
}
@@ -0,0 +1,47 @@
/************************************************************************
* 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/list-activities-dashlet', ['views/record/list-expanded', 'crm:views/meeting/record/list', 'crm:views/task/record/list'], function (Dep, MeetingList, TaskList) {
return Dep.extend({
actionSetHeld: function (data) {
MeetingList.prototype.actionSetHeld.call(this, data);
},
actionSetNotHeld: function (data) {
MeetingList.prototype.actionSetNotHeld.call(this, data);
},
actionSetCompleted: function (data) {
TaskList.prototype.actionSetCompleted.call(this, data);
}
});
});
@@ -0,0 +1,89 @@
/************************************************************************
* 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/activities-dashlet', 'views/record/row-actions/view-and-edit', function (Dep) {
return Dep.extend({
getActionList: function () {
var actionList = Dep.prototype.getActionList.call(this);
var scope = this.model.name;
actionList.forEach(function (item) {
item.data = item.data || {};
item.data.scope = this.model.name
}, this);
if (scope === 'Task') {
if (this.options.acl.edit && !~['Completed', 'Canceled'].indexOf(this.model.get('status'))) {
actionList.push({
action: 'setCompleted',
label: 'Complete',
data: {
id: this.model.id
}
});
}
} else {
if (this.options.acl.edit && !~['Held', 'Not Held'].indexOf(this.model.get('status'))) {
actionList.push({
action: 'setHeld',
label: 'Set Held',
data: {
id: this.model.id,
scope: this.model.name
}
});
actionList.push({
action: 'setNotHeld',
label: 'Set Not Held',
data: {
id: this.model.id,
scope: this.model.name
}
});
}
}
if (this.options.acl.edit) {
actionList.push({
action: 'quickRemove',
label: 'Remove',
data: {
id: this.model.id,
scope: this.model.name
}
});
}
return actionList;
}
});
});
@@ -11,9 +11,7 @@
{{{avatar}}}
</div>
<div class="stream-head-text-container">
{{#if statusText}}
<span class="label label-{{statusStyle}}">{{statusText}}</span>
{{/if}}
{{#if iconHtml}}{{{iconHtml}}}{{/if}}
<span class="text-muted message">{{{message}}}</span>
</div>
</div>
+1 -3
View File
@@ -11,9 +11,7 @@
{{{avatar}}}
</div>
<div class="stream-head-text-container">
{{#if statusText}}
<span class="label label-{{statusStyle}}">{{statusText}}</span>
{{/if}}
{{#if statusText}}<span class="label label-{{statusStyle}}">{{statusText}}</span>{{/if}}
<span class="text-muted message">{{{message}}}</span>
</div>
</div>
@@ -11,7 +11,7 @@
{{{avatar}}}
</div>
<div class="stream-head-text-container">
<span class="text-muted"><span class="glyphicon glyphicon-envelope action" style="cursor: pointer;" title="{{translate 'View'}}" data-action="quickView" data-id="{{emailId}}" data-scope="Email"></span>
<span class="text-muted"><span class="glyphicon glyphicon-envelope action icon" style="cursor: pointer;" title="{{translate 'View'}}" data-action="quickView" data-id="{{emailId}}" data-scope="Email"></span>
{{{message}}}
</span>
</div>
@@ -10,7 +10,7 @@
{{{avatar}}}
</div>
<div class="stream-head-text-container">
<span class="text-muted"><span class="glyphicon glyphicon-envelope action" style="cursor: pointer;" title="{{translate 'View'}}" data-action="quickView" data-id="{{emailId}}" data-scope="Email"></span>
<span class="text-muted"><span class="glyphicon glyphicon-envelope action icon" style="cursor: pointer;" title="{{translate 'View'}}" data-action="quickView" data-id="{{emailId}}" data-scope="Email"></span>
{{{message}}}
</span>
</div>
+9 -1
View File
@@ -134,7 +134,15 @@ Espo.define('collection', [], function () {
options.data.asc = this.asc;
options.data.where = this.getWhere();
return Backbone.Collection.prototype.fetch.call(this, options);
this.lastXhr = Backbone.Collection.prototype.fetch.call(this, options);
return this.lastXhr;
},
abortLastFetch: function () {
if (this.lastXhr && this.lastXhr.readyState < 4) {
this.lastXhr.abort();
}
},
getWhere: function () {
+10 -3
View File
@@ -116,6 +116,7 @@ Espo.define('views/email/list', 'views/list', function (Dep) {
},
loadFolders: function () {
var xhr = null;
this.getFolderCollection(function (collection) {
this.createView('folders', 'views/email-folder/list-side', {
collection: collection,
@@ -129,10 +130,16 @@ Espo.define('views/email/list', 'views/list', function (Dep) {
this.selectedFolderId = id;
this.applyFolder();
if (xhr && xhr.readyState < 4) {
xhr.abort();
}
this.notify('Please wait...');
this.collection.fetch().then(function () {
this.notify(false);
}.bind(this));
xhr = this.collection.fetch({
success: function () {
this.notify(false);
}.bind(this)
});
if (id !== this.defaultFolderId) {
this.getRouter().navigate('#Email/list/folder=' + id);
+5
View File
@@ -235,7 +235,10 @@ Espo.define('views/list-with-categories', 'views/list', function (Dep) {
this.applyCategoryToNestedCategoriesCollection();
this.applyCategoryToCollection();
this.collection.abortLastFetch();
if (this.nestedCategoriesCollection) {
this.nestedCategoriesCollection.abortLastFetch();
Espo.Ui.notify(this.translate('loading', 'messages'));
Promise.all([
this.nestedCategoriesCollection.fetch().then(function () {
@@ -377,6 +380,8 @@ Espo.define('views/list-with-categories', 'views/list', function (Dep) {
this.applyCategoryToCollection();
this.collection.abortLastFetch();
this.notify('Please wait...');
this.listenToOnce(this.collection, 'sync', function () {
this.notify(false);
+2 -1
View File
@@ -114,7 +114,8 @@ Espo.define('views/login', 'view', function (Dep) {
user: data.user,
preferences: data.preferences,
acl: data.acl,
settings: data.settings
settings: data.settings,
appParams: data.appParams
});
}.bind(this),
error: function (xhr) {
+11 -15
View File
@@ -118,7 +118,7 @@ Espo.define('views/record/detail', ['views/record/base', 'view-record-helper'],
inlineEditDisabled: false,
printPdfAction: false,
printPdfAction: true,
portalLayoutDisabled: false,
@@ -223,17 +223,11 @@ Espo.define('views/record/detail', ['views/record/base', 'view-record-helper'],
}
}
if (this.type === 'detail') {
var printPdfAction = this.printPdfAction;
if (this.type === 'detail' && this.printPdfAction) {
var printPdfAction = true;
if (!printPdfAction) {
if (~(this.getHelper().getAppParam('templateEntityTypeList') || []).indexOf(this.entityType)) {
printPdfAction = true;
}
}
if (printPdfAction && !this.getAcl().check('Template', 'read')) {
printPdfAction = false
if (!~(this.getHelper().getAppParam('templateEntityTypeList') || []).indexOf(this.entityType)) {
printPdfAction = false;
}
if (printPdfAction) {
@@ -783,15 +777,17 @@ Espo.define('views/record/detail', ['views/record/base', 'view-record-helper'],
}
var id = model.id;
var scope = model.name || this.scope;
var url;
if (this.mode === 'edit') {
url = '#' + this.scope + '/edit/' + id;
url = '#' + scope + '/edit/' + id;
} else {
url = '#' + this.scope + '/view/' + id;
url = '#' + scope + '/view/' + id;
}
this.getRouter().navigate('#' + this.scope + '/view/' + id, {trigger: false});
this.getRouter().dispatch(this.scope, 'view', {
this.getRouter().navigate('#' + scope + '/view/' + id, {trigger: false});
this.getRouter().dispatch(scope, 'view', {
id: id,
model: model,
indexOfRecord: indexOfRecord
+14 -12
View File
@@ -235,14 +235,7 @@ Espo.define('views/record/search', 'view', function (Dep) {
this.resetFilters();
},
'click button[data-action="refresh"]': function (e) {
this.notify('Loading...');
this.listenToOnce(this.collection, 'sync', function () {
this.notify(false);
}.bind(this));
this.collection.reset();
this.collection.fetch();
this.refresh();
},
'click a[data-action="selectPreset"]': function (e) {
var presetName = $(e.currentTarget).data('name') || null;
@@ -279,6 +272,15 @@ Espo.define('views/record/search', 'view', function (Dep) {
}
},
refresh: function () {
this.notify('Loading...');
this.collection.abortLastFetch();
this.collection.reset();
this.collection.fetch().then(function () {
Espo.Ui.notify(false);
});
},
selectPreset: function (presetName, forceClearAdvancedFilters) {
var wasPreset = !(this.primary == this.presetName);
@@ -546,13 +548,13 @@ Espo.define('views/record/search', 'view', function (Dep) {
},
updateCollection: function () {
this.collection.abortLastFetch();
this.collection.reset();
this.notify('Please wait...');
this.listenTo(this.collection, 'sync', function () {
this.notify(false);
}.bind(this));
this.collection.where = this.searchManager.getWhere();
this.collection.fetch();
this.collection.fetch().then(function () {
Espo.Ui.notify(false);
});
},
getPresetFilterList: function () {
+7 -1
View File
@@ -182,8 +182,14 @@ Espo.define('views/stream/note', 'view', function (Dep) {
id = 'system';
}
return '<img class="avatar" width="20" src="'+this.getBasePath()+'?entryPoint=avatar&size=small&id=' + id + '&t='+t+'">';
},
getIconHtml: function (scope, id) {
if (this.isThis && scope === this.parentModel.name) return;
var iconClass = this.getMetadata().get(['clientDefs', scope, 'iconClass']);
if (!iconClass) return;
return '<span class="'+iconClass+' action text-muted icon" style="cursor: pointer;" title="'+this.translate('View')+'" data-action="quickView" data-id="'+id+'" data-scope="'+scope+'"></span>';
}
});
});
@@ -26,17 +26,18 @@
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
Espo.define('Views.Stream.Notes.CreateRelated', 'Views.Stream.Note', function (Dep) {
Espo.define('views/stream/notes/create-related', 'views/stream/note', function (Dep) {
return Dep.extend({
template: 'stream.notes.create-related',
template: 'stream/notes/create-related',
messageName: 'createRelated',
data: function () {
return _.extend({
relatedTypeString: this.translateEntityType(this.entityType)
relatedTypeString: this.translateEntityType(this.entityType),
iconHtml: this.getIconHtml(this.entityType, this.entityId)
}, Dep.prototype.data.call(this));
},
@@ -58,7 +59,7 @@ Espo.define('Views.Stream.Notes.CreateRelated', 'Views.Stream.Note', function (D
this.messageData['relatedEntity'] = '<a href="#' + this.entityType + '/view/' + this.entityId + '">' + this.entityName +'</a>';
this.createMessage();
},
}
});
});
+27
View File
@@ -1224,6 +1224,24 @@ body > footer > p a:visited {
}
}
.label {
padding: .09em .5em .2em;
}
.expanded-row {
span.label {
position: relative;
top: -2px;
}
}
.stream-head-text-container {
span.label {
position: relative;
top: -1px;
}
}
.stream-head-container {
padding-bottom: 3px;
}
@@ -1296,10 +1314,19 @@ stream-head-text-container .span {
font-size: 0.9em;
}
.flotr-grid-label-y {
min-height: 1.2em;
line-height: 1.1em;
max-height: 2.1em;
overflow: hidden;
}
.flotr-grid-label-x {
min-height: 1.2em;
max-height: 2.1em;
line-height: 1.1em;
overflow: hidden;
padding: 0 1px;
}
.legend-container td.flotr-legend-label {
-7
View File
@@ -18,9 +18,6 @@
"twitter": "Твіттер",
"forum": "форум",
"Installation Guide": "Керівництво з установки",
"admin": "admin",
"localhost": "localhost",
"port": "3306",
"Locale": "Локаль",
"Outbound Email Configuration": "Налаштування вихідної пошти",
"SMTP": "Протокол SMTP",
@@ -109,10 +106,6 @@
"mysqlSettingError": "EspoCRM потребує, щоби MySQL \"{NAME}\" було встановлено на {VALUE}"
},
"options": {
"db driver": {
"mysqli": "MySQLi",
"pdo_mysql": "PDO MySQL"
},
"modRewriteInstruction": {
"apache": {
"windows": "<br> <pre>1. Знайти файл httpd.conf файл (зазвичай його можна знайти у теці, званій conf, config або ще якось так)<br> Н2. Всередині файла httpd.conf розкоментувати рядок LoadModule rewrite_module модулі/через mod_rewrite.so (видалити знак '#' на початку рядка)<br> 3. Також пересвідчитися, що рядок ClearModuleList некоментований і переконайтеся, що рядок AddModule mod_rewrite.c не закомментирований.</pre>",