mirror of
https://github.com/espocrm/espocrm.git
synced 2026-06-28 06:56:05 +00:00
layout sets
This commit is contained in:
@@ -30,62 +30,49 @@
|
||||
namespace Espo\Controllers;
|
||||
|
||||
use Espo\Core\Utils as Utils;
|
||||
use \Espo\Core\Exceptions\NotFound;
|
||||
use \Espo\Core\Exceptions\Error;
|
||||
use \Espo\Core\Exceptions\Forbidden;
|
||||
use \Espo\Core\Exceptions\BadRequest;
|
||||
use Espo\Core\Exceptions\NotFound;
|
||||
use Espo\Core\Exceptions\Error;
|
||||
use Espo\Core\Exceptions\Forbidden;
|
||||
use Espo\Core\Exceptions\BadRequest;
|
||||
|
||||
class Layout extends \Espo\Core\Controllers\Base
|
||||
{
|
||||
public function actionRead($params, $data)
|
||||
public function getActionRead($params, $data)
|
||||
{
|
||||
return $this->getServiceFactory()->create('Layout')->getForFrontend($params['scope'], $params['name']);
|
||||
$scope = $params['scope'] ?? null;
|
||||
$name = $params['name'] ?? null;
|
||||
|
||||
return $this->getServiceFactory()->create('Layout')->getForFrontend($scope, $name);
|
||||
}
|
||||
|
||||
public function actionUpdate($params, $data, $request)
|
||||
public function putActionUpdate($params, $data, $request)
|
||||
{
|
||||
if (is_object($data)) {
|
||||
$data = get_object_vars($data);
|
||||
}
|
||||
if (is_object($data)) $data = get_object_vars($data);
|
||||
|
||||
if (!$this->getUser()->isAdmin()) {
|
||||
throw new Forbidden();
|
||||
}
|
||||
if (!$this->getUser()->isAdmin()) throw new Forbidden();
|
||||
|
||||
if (!$request->isPut() && !$request->isPatch()) {
|
||||
throw new BadRequest();
|
||||
}
|
||||
$scope = $params['scope'] ?? null;
|
||||
$name = $params['name'] ?? null;
|
||||
$setId = $params['setId'] ?? null;
|
||||
|
||||
$layoutManager = $this->getContainer()->get('layout');
|
||||
$layoutManager->set($data, $params['scope'], $params['name']);
|
||||
$result = $layoutManager->save();
|
||||
|
||||
if ($result === false) {
|
||||
throw new Error("Error while saving layout.");
|
||||
}
|
||||
|
||||
$this->getContainer()->get('dataManager')->updateCacheTimestamp();
|
||||
|
||||
return $layoutManager->get($params['scope'], $params['name']);
|
||||
}
|
||||
|
||||
public function actionPatch($params, $data, $request)
|
||||
{
|
||||
return $this->actionUpdate($params, $data, $request);
|
||||
return $this->getServiceFactory()->create('Layout')->update($scope, $name, $setId, $data);
|
||||
}
|
||||
|
||||
public function postActionResetToDefault($params, $data, $request)
|
||||
{
|
||||
if (!$this->getUser()->isAdmin()) {
|
||||
throw new Forbidden();
|
||||
}
|
||||
if (!$this->getUser()->isAdmin()) throw new Forbidden();
|
||||
|
||||
if (empty($data->scope) || empty($data->name)) {
|
||||
throw new BadRequest();
|
||||
}
|
||||
if (empty($data->scope) || empty($data->name)) throw new BadRequest();
|
||||
|
||||
$this->getContainer()->get('dataManager')->updateCacheTimestamp();
|
||||
return $this->getServiceFactory()->create('Layout')->resetToDefault($data->scope, $data->name, $data->setId ?? null);
|
||||
}
|
||||
|
||||
return $this->getContainer()->get('layout')->resetToDefault($data->scope, $data->name);
|
||||
public function getActionGetOriginal($params, $data, $request)
|
||||
{
|
||||
if (!$this->getUser()->isAdmin()) throw new Forbidden();
|
||||
|
||||
return $this->getServiceFactory()->create('Layout')->getOriginal(
|
||||
$request->get('scope'), $request->get('name'), $request->get('setId')
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
42
application/Espo/Controllers/LayoutSet.php
Normal file
42
application/Espo/Controllers/LayoutSet.php
Normal file
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2020 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* EspoCRM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Controllers;
|
||||
|
||||
use Espo\Core\Exceptions\Forbidden;
|
||||
|
||||
class LayoutSet extends \Espo\Core\Controllers\Record
|
||||
{
|
||||
protected function checkControllerAccess()
|
||||
{
|
||||
if (!$this->getUser()->isAdmin()) {
|
||||
throw new Forbidden();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1863,6 +1863,7 @@ class Base
|
||||
$method = 'filter' . ucfirst($filter);
|
||||
if (method_exists($this, $method)) {
|
||||
$this->$method($result);
|
||||
return;
|
||||
} else {
|
||||
$className = $this->getMetadata()->get(['entityDefs', $this->entityType, 'collection', 'filters', $filter, 'className']);
|
||||
if ($className) {
|
||||
@@ -1877,7 +1878,10 @@ class Base
|
||||
}
|
||||
$impl->applyFilter($this->entityType, $filter, $result, $this);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
$result['whereClause'][] = ['id' => null];
|
||||
}
|
||||
|
||||
public function applyFilter(string $filter, array &$result)
|
||||
|
||||
@@ -99,6 +99,7 @@ class Currency extends Base
|
||||
'orderBy' => [
|
||||
'sql' => $converedFieldName . " {direction}",
|
||||
'leftJoins' => $leftJoins,
|
||||
'additionalSelect' => ["{$alias}.rate"],
|
||||
],
|
||||
'attributeRole' => 'valueConverted',
|
||||
'fieldType' => 'currency',
|
||||
@@ -107,6 +108,7 @@ class Currency extends Base
|
||||
$defs[$entityType]['fields'][$fieldName]['orderBy'] = [
|
||||
'sql' => $part . " * {$alias}.rate {direction}",
|
||||
'leftJoins' => $leftJoins,
|
||||
'additionalSelect' => ["{$alias}.rate"],
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
34
application/Espo/Entities/LayoutRecord.php
Normal file
34
application/Espo/Entities/LayoutRecord.php
Normal file
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2020 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* EspoCRM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Entities;
|
||||
|
||||
class LayoutRecord extends \Espo\Core\ORM\Entity
|
||||
{
|
||||
}
|
||||
34
application/Espo/Entities/LayoutSet.php
Normal file
34
application/Espo/Entities/LayoutSet.php
Normal file
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2020 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* EspoCRM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Entities;
|
||||
|
||||
class LayoutSet extends \Espo\Core\ORM\Entity
|
||||
{
|
||||
}
|
||||
@@ -29,10 +29,10 @@
|
||||
|
||||
namespace Espo\EntryPoints;
|
||||
|
||||
use \Espo\Core\Exceptions\NotFound;
|
||||
use \Espo\Core\Exceptions\Forbidden;
|
||||
use \Espo\Core\Exceptions\BadRequest;
|
||||
use \Espo\Core\Exceptions\Error;
|
||||
use Espo\Core\Exceptions\NotFound;
|
||||
use Espo\Core\Exceptions\Forbidden;
|
||||
use Espo\Core\Exceptions\BadRequest;
|
||||
use Espo\Core\Exceptions\Error;
|
||||
|
||||
class Avatar extends Image
|
||||
{
|
||||
@@ -40,7 +40,7 @@ class Avatar extends Image
|
||||
|
||||
public static $notStrictAuth = true;
|
||||
|
||||
protected $systemColor = [212,114,155];
|
||||
protected $systemColor = '#a4b5bd';
|
||||
|
||||
protected $colorList = [
|
||||
[111,168,214],
|
||||
@@ -63,8 +63,10 @@ class Avatar extends Image
|
||||
}
|
||||
$x = intval($sum % 128) + 1;
|
||||
|
||||
$index = intval($x * count($this->colorList) / 128);
|
||||
return $this->colorList[$index];
|
||||
$colorList = $this->getMetadata()->get(['app', 'avatars', 'colorList']) ?? $this->colorList;
|
||||
|
||||
$index = intval($x * count($colorList) / 128);
|
||||
return $colorList[$index];
|
||||
}
|
||||
|
||||
public function run()
|
||||
@@ -111,7 +113,7 @@ class Avatar extends Image
|
||||
$hash = $userId;
|
||||
$color = $this->getColor($userId);
|
||||
if ($hash === 'system') {
|
||||
$color = $this->systemColor;
|
||||
$color = $this->getMetadata()->get(['app', 'avatars', 'systemColor']) ?? $this->systemColor;
|
||||
}
|
||||
|
||||
$imgContent = $identicon->getImageData($hash, $width, $color);
|
||||
@@ -120,6 +122,4 @@ class Avatar extends Image
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -308,6 +308,7 @@ abstract class Base
|
||||
if (empty($params['customJoin'])) {
|
||||
$params['customJoin'] = '';
|
||||
}
|
||||
$params['additionalSelect'] = $params['additionalSelect'] ?? [];
|
||||
|
||||
$wherePart = $this->getWhere($entity, $whereClause, 'AND', $params);
|
||||
|
||||
@@ -318,9 +319,29 @@ abstract class Base
|
||||
}
|
||||
|
||||
if (empty($params['aggregation'])) {
|
||||
$selectPart = $this->getSelect($entity, $params['select'], $params['distinct'], $params['skipTextColumns'], $params['maxTextColumnsLength'], $params);
|
||||
$selectPart = $this->getSelect(
|
||||
$entity, $params['select'], $params['distinct'], $params['skipTextColumns'], $params['maxTextColumnsLength'], $params
|
||||
);
|
||||
|
||||
$orderPart = $this->getOrder($entity, $params['orderBy'], $params['order'], $params);
|
||||
|
||||
if (!empty($params['extraAdditionalSelect'])) {
|
||||
$extraSelect = [];
|
||||
foreach ($params['extraAdditionalSelect'] as $item) {
|
||||
if (!in_array($item, $params['select']) && !in_array($item, $params['additionalSelect'])) {
|
||||
$extraSelect[] = $item;
|
||||
}
|
||||
}
|
||||
if (count($extraSelect)) {
|
||||
$extraSelectPart = $this->getSelect(
|
||||
$entity, $extraSelect, false
|
||||
);
|
||||
if ($extraSelectPart) {
|
||||
$selectPart .= ', ' . $extraSelectPart;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($params['additionalColumns']) && is_array($params['additionalColumns']) && !empty($params['relationName'])) {
|
||||
foreach ($params['additionalColumns'] as $column => $field) {
|
||||
$itemAlias = $this->sanitizeSelectAlias($field);
|
||||
@@ -955,6 +976,16 @@ abstract class Base
|
||||
$params['joins'][] = $j;
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($fieldDefs[$type]['additionalSelect'])) {
|
||||
$params['extraAdditionalSelect'] = $params['extraAdditionalSelect'] ?? [];
|
||||
foreach ($fieldDefs[$type]['additionalSelect'] as $value) {
|
||||
$value = str_replace('{alias}', $alias, $value);
|
||||
if (!in_array($value, $params['extraAdditionalSelect'])) {
|
||||
$params['extraAdditionalSelect'][] = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $part;
|
||||
|
||||
68
application/Espo/Repositories/LayoutSet.php
Normal file
68
application/Espo/Repositories/LayoutSet.php
Normal file
@@ -0,0 +1,68 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2020 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* EspoCRM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Repositories;
|
||||
|
||||
use Espo\ORM\Entity;
|
||||
|
||||
class LayoutSet extends \Espo\Core\ORM\Repositories\RDB
|
||||
{
|
||||
protected function afterSave(Entity $entity, array $options = [])
|
||||
{
|
||||
parent::afterSave($entity);
|
||||
|
||||
if (!$entity->isNew() && $entity->has('layoutList')) {
|
||||
$listBefore = $entity->getFetched('layoutList') ?? [];
|
||||
$listNow = $entity->get('layoutList') ?? [];
|
||||
|
||||
foreach ($listBefore as $name) {
|
||||
if (!in_array($name, $listNow)) {
|
||||
$layout = $this->getEntityManager()->getRepository('LayoutRecord')->where([
|
||||
'layoutSetId' => $entity->id,
|
||||
'name' => $name,
|
||||
])->findOne();
|
||||
if ($layout) {
|
||||
$this->getEntityManager()->removeEntity($layout);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected function afterRemove(Entity $entity, array $options = [])
|
||||
{
|
||||
$layoutList = $this->getEntityManager()->getRepository('LayoutRecord')->where([
|
||||
'layoutSetId' => $entity->id,
|
||||
])->find();
|
||||
|
||||
foreach ($layoutList as $layout) {
|
||||
$this->getEntityManager()->removeEntity($layout);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -71,6 +71,7 @@
|
||||
"Permissions": "Permissions",
|
||||
"Email Addresses": "Email Addresses",
|
||||
"Phone Numbers": "Phone Numbers",
|
||||
"Layout Sets": "Layout Sets",
|
||||
"Success": "Success",
|
||||
"Fail": "Fail",
|
||||
"is recommended": "is recommended",
|
||||
@@ -262,6 +263,7 @@
|
||||
"emailAddresses": "All emailes addresses stored in the system.",
|
||||
"phoneNumbers": "All phone numbers stored in the system.",
|
||||
"dashboardTemplates": "Deploy dashboards to users.",
|
||||
"layoutSets": "Collections of layouts that can be assigned to teams & portals.",
|
||||
"pdfTemplates": "Templates for printing to PDF."
|
||||
},
|
||||
"options": {
|
||||
|
||||
@@ -51,6 +51,7 @@
|
||||
"ArrayValue": "Array Value",
|
||||
"DashboardTemplate": "Dashboard Template",
|
||||
"Currency": "Currency",
|
||||
"LayoutSet": "Layout Set",
|
||||
"Webhook": "Webhook"
|
||||
},
|
||||
"scopeNamesPlural": {
|
||||
@@ -94,6 +95,7 @@
|
||||
"ArrayValue": "Array Values",
|
||||
"DashboardTemplate": "Dashboard Templates",
|
||||
"Currency": "Currency",
|
||||
"LayoutSet": "Layout Sets",
|
||||
"Webhook": "Webhooks"
|
||||
},
|
||||
"labels": {
|
||||
|
||||
11
application/Espo/Resources/i18n/en_US/LayoutSet.json
Normal file
11
application/Espo/Resources/i18n/en_US/LayoutSet.json
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"fields": {
|
||||
"layoutList": "Layouts"
|
||||
},
|
||||
"labels": {
|
||||
"Create LayoutSet": "Create Layout Set",
|
||||
"Edit Layouts": "Edit Layouts"
|
||||
},
|
||||
"tooltips": {
|
||||
}
|
||||
}
|
||||
@@ -17,12 +17,14 @@
|
||||
"timeZone": "Time Zone",
|
||||
"weekStart": "First Day of Week",
|
||||
"defaultCurrency": "Default Currency",
|
||||
"layoutSet": "Layout Set",
|
||||
"customUrl": "Custom URL",
|
||||
"customId": "Custom ID"
|
||||
},
|
||||
"links": {
|
||||
"users": "Users",
|
||||
"portalRoles": "Roles",
|
||||
"layoutSet": "Layout Set",
|
||||
"notes": "Notes"
|
||||
},
|
||||
"tooltips": {
|
||||
|
||||
@@ -2,12 +2,14 @@
|
||||
"fields": {
|
||||
"name": "Name",
|
||||
"roles": "Roles",
|
||||
"layoutSet": "Layout Set",
|
||||
"positionList": "Position List"
|
||||
},
|
||||
"links": {
|
||||
"users": "Users",
|
||||
"notes": "Notes",
|
||||
"roles": "Roles",
|
||||
"layoutSet": "Layout Set",
|
||||
"inboundEmails": "Group Email Accounts"
|
||||
},
|
||||
"tooltips": {
|
||||
|
||||
17
application/Espo/Resources/layouts/LayoutSet/detail.json
Normal file
17
application/Espo/Resources/layouts/LayoutSet/detail.json
Normal file
@@ -0,0 +1,17 @@
|
||||
[
|
||||
{
|
||||
"label": "",
|
||||
"rows": [
|
||||
[{"name": "name"}, false],
|
||||
[
|
||||
{"name": "layoutList"},
|
||||
{
|
||||
"name": "edit",
|
||||
"customLabel": "",
|
||||
"view": "views/layout-set/fields/edit",
|
||||
"inlineEditDisabled": true
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,8 @@
|
||||
[
|
||||
{
|
||||
"label": "",
|
||||
"rows": [
|
||||
[{"name": "name"}]
|
||||
]
|
||||
}
|
||||
]
|
||||
3
application/Espo/Resources/layouts/LayoutSet/list.json
Normal file
3
application/Espo/Resources/layouts/LayoutSet/list.json
Normal file
@@ -0,0 +1,3 @@
|
||||
[
|
||||
{"name":"name", "link": true}
|
||||
]
|
||||
@@ -0,0 +1,3 @@
|
||||
[
|
||||
"teams"
|
||||
]
|
||||
@@ -20,6 +20,7 @@
|
||||
"label": "User Interface",
|
||||
"rows": [
|
||||
[{"name": "companyLogo"}, {"name": "theme"}],
|
||||
[{"name": "layoutSet"}, false],
|
||||
[{"name": "tabList"}, {"name": "quickCreateList"}],
|
||||
[{"name": "dashboardLayout", "fullWidth": true}]
|
||||
]
|
||||
|
||||
@@ -2,11 +2,16 @@
|
||||
{
|
||||
"rows": [
|
||||
[
|
||||
{"name": "name"}
|
||||
{"name": "name"},
|
||||
false
|
||||
],
|
||||
[
|
||||
{"name": "roles"},
|
||||
{"name": "positionList"}
|
||||
],
|
||||
[
|
||||
{"name": "layoutSet"},
|
||||
false
|
||||
]
|
||||
]
|
||||
}
|
||||
|
||||
@@ -257,6 +257,13 @@
|
||||
"iconClass": "fas fa-th-large",
|
||||
"description": "dashboardTemplates"
|
||||
},
|
||||
{
|
||||
"url": "#LayoutSet",
|
||||
"label": "Layout Sets",
|
||||
"iconClass": "fas fa-table",
|
||||
"description": "layoutSets"
|
||||
|
||||
},
|
||||
{
|
||||
"url": "#Attachment",
|
||||
"label": "Attachments",
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"controller": "controllers/layout-set",
|
||||
"searchPanelDisabled": true,
|
||||
"duplicateDisabled": true,
|
||||
"relationshipPanels": {
|
||||
"teams": {
|
||||
"createDisabled": true,
|
||||
"viewDisabled": true,
|
||||
"rowActionsView": "views/record/row-actions/relationship-unlink-only"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"fields": {
|
||||
"name": {
|
||||
"type": "varchar"
|
||||
},
|
||||
"layoutSet": {
|
||||
"type": "link"
|
||||
},
|
||||
"data": {
|
||||
"type": "jsonObject"
|
||||
}
|
||||
},
|
||||
"links": {
|
||||
"layoutSet": {
|
||||
"type": "belengsTo",
|
||||
"entity": "LayoutSet",
|
||||
"foreign": "layoutRecords"
|
||||
}
|
||||
},
|
||||
"indexes": {
|
||||
"nameLayoutSetId": {
|
||||
"columns": ["name", "layoutSetId"]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
{
|
||||
"fields": {
|
||||
"name": {
|
||||
"type": "varchar",
|
||||
"required": true,
|
||||
"maxLength": 100,
|
||||
"trim": true
|
||||
},
|
||||
"layoutList": {
|
||||
"type": "multiEnum",
|
||||
"displayAsList": true,
|
||||
"view": "views/layout-set/fields/layout-list"
|
||||
},
|
||||
"createdAt": {
|
||||
"type": "datetime",
|
||||
"readOnly": true
|
||||
},
|
||||
"modifiedAt": {
|
||||
"type": "datetime",
|
||||
"readOnly": true
|
||||
}
|
||||
},
|
||||
"links": {
|
||||
"layoutRecords": {
|
||||
"type": "hasMany",
|
||||
"entity": "LayoutRecord",
|
||||
"foreign": "layoutSet"
|
||||
},
|
||||
"teams": {
|
||||
"type": "hasMany",
|
||||
"entity": "Team",
|
||||
"foreign": "layoutSet"
|
||||
},
|
||||
"portals": {
|
||||
"type": "hasMany",
|
||||
"entity": "Portal",
|
||||
"foreign": "layoutSet"
|
||||
}
|
||||
},
|
||||
"collection": {
|
||||
"orderBy": "name",
|
||||
"order": "asc"
|
||||
}
|
||||
}
|
||||
@@ -94,6 +94,9 @@
|
||||
"customUrl": {
|
||||
"type": "url"
|
||||
},
|
||||
"layoutSet": {
|
||||
"type": "link"
|
||||
},
|
||||
"modifiedAt": {
|
||||
"type": "datetime",
|
||||
"readOnly": true
|
||||
@@ -136,6 +139,11 @@
|
||||
"type": "hasMany",
|
||||
"entity": "Note",
|
||||
"foreign": "portals"
|
||||
},
|
||||
"layoutSet": {
|
||||
"type": "belongsTo",
|
||||
"entity": "LayoutSet",
|
||||
"foreign": "portals"
|
||||
}
|
||||
},
|
||||
"collection": {
|
||||
|
||||
@@ -18,6 +18,9 @@
|
||||
"notStorable": true,
|
||||
"disabled": true
|
||||
},
|
||||
"layoutSet": {
|
||||
"type": "link"
|
||||
},
|
||||
"createdAt": {
|
||||
"type": "datetime",
|
||||
"readOnly": true
|
||||
@@ -47,6 +50,11 @@
|
||||
"type": "hasMany",
|
||||
"entity": "InboundEmail",
|
||||
"foreign": "teams"
|
||||
},
|
||||
"layoutSet": {
|
||||
"type": "belongsTo",
|
||||
"entity": "LayoutSet",
|
||||
"foreign": "teams"
|
||||
}
|
||||
},
|
||||
"collection": {
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"entity": true
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"entity": true
|
||||
}
|
||||
@@ -157,8 +157,8 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"route": "/:controller/layout/:name",
|
||||
"method": "patch",
|
||||
"route": "/:controller/layout/:name/:setId",
|
||||
"method": "put",
|
||||
"params": {
|
||||
"controller": "Layout",
|
||||
"scope": ":controller"
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
namespace Espo\Services;
|
||||
|
||||
use Espo\Core\Exceptions\NotFound;
|
||||
use Espo\Core\Exceptions\Error;
|
||||
|
||||
class Layout extends \Espo\Core\Services\Base
|
||||
{
|
||||
@@ -37,7 +38,10 @@ class Layout extends \Espo\Core\Services\Base
|
||||
{
|
||||
$this->addDependency('acl');
|
||||
$this->addDependency('layout');
|
||||
$this->addDependency('entityManager');
|
||||
$this->addDependency('metadata');
|
||||
$this->addDependency('dataManager');
|
||||
$this->addDependency('user');
|
||||
}
|
||||
|
||||
protected function getAcl()
|
||||
@@ -52,10 +56,53 @@ class Layout extends \Espo\Core\Services\Base
|
||||
|
||||
public function getForFrontend(string $scope, string $name)
|
||||
{
|
||||
$dataString = $this->getInjection('layout')->get($scope, $name);
|
||||
$layoutSetId = null;
|
||||
$data = null;
|
||||
|
||||
$em = $this->getInjection('entityManager');
|
||||
$user = $this->getInjection('user');
|
||||
|
||||
if ($user->isPortal()) {
|
||||
$portalId = $user->get('portalId');
|
||||
if ($portalId) {
|
||||
$portal = $em->getRepository('Portal')->select(['layoutSetId'])->where(['id' => $portalId])->findOne();
|
||||
if ($portal) {
|
||||
$layoutSetId = $portal->get('layoutSetId');
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$teamId = $user->get('defaultTeamId');
|
||||
if ($teamId) {
|
||||
$team = $em->getRepository('Team')->select(['layoutSetId'])->where(['id' => $teamId])->findOne();
|
||||
if ($team) {
|
||||
$layoutSetId = $team->get('layoutSetId');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($layoutSetId) {
|
||||
$nameReal = $name;
|
||||
|
||||
if ($user->isPortal()) {
|
||||
if (substr($name, -6) === 'Portal') {
|
||||
$nameReal = substr($name, 0, -6);
|
||||
}
|
||||
}
|
||||
|
||||
$layout = $this->getRecordFromSet($scope, $nameReal, $layoutSetId, true);
|
||||
if ($layout) {
|
||||
$data = $layout->get('data');
|
||||
}
|
||||
}
|
||||
|
||||
if (!$data) {
|
||||
$dataString = $this->getInjection('layout')->get($scope, $name);
|
||||
} else {
|
||||
$dataString = json_encode($data);
|
||||
}
|
||||
|
||||
if (!$dataString) {
|
||||
throw new NotFound("Layout {$scope}:{$scope} is not found.");
|
||||
throw new NotFound("Layout {$scope}:{$name} is not found.");
|
||||
}
|
||||
|
||||
if (!$this->getUser()->isAdmin()) {
|
||||
@@ -80,4 +127,90 @@ class Layout extends \Espo\Core\Services\Base
|
||||
|
||||
return $dataString;
|
||||
}
|
||||
|
||||
protected function getRecordFromSet(string $scope, string $name, string $setId, bool $skipCheck = false)
|
||||
{
|
||||
$em = $this->getInjection('entityManager');
|
||||
$layoutSet = $em->getEntity('LayoutSet', $setId);
|
||||
if (!$layoutSet) throw new NotFound();
|
||||
|
||||
$layoutList = $layoutSet->get('layoutList') ?? [];
|
||||
|
||||
$fullName = $scope . '.' . $name;
|
||||
|
||||
if (!in_array($fullName, $layoutList)) {
|
||||
if ($skipCheck) return null;
|
||||
throw new NotFound("Layout {$fullName} is no allowed in set.");
|
||||
}
|
||||
|
||||
$layout = $em->getRepository('LayoutRecord')->where([
|
||||
'layoutSetId' => $setId,
|
||||
'name' => $fullName,
|
||||
])->findOne();
|
||||
|
||||
return $layout;
|
||||
}
|
||||
|
||||
public function update(string $scope, string $name, ?string $setId, $data)
|
||||
{
|
||||
if ($setId) {
|
||||
$layout = $this->getRecordFromSet($scope, $name, $setId);
|
||||
|
||||
$em = $this->getInjection('entityManager');
|
||||
|
||||
if (!$layout) {
|
||||
$layout = $em->getEntity('LayoutRecord');
|
||||
$layout->set([
|
||||
'layoutSetId' => $setId,
|
||||
'name' => $scope . '.' . $name,
|
||||
]);
|
||||
}
|
||||
|
||||
$layout->set('data', $data);
|
||||
|
||||
$em->saveEntity($layout);
|
||||
|
||||
return $layout->get('data');
|
||||
}
|
||||
|
||||
$layoutManager = $this->getInjection('layout');
|
||||
|
||||
$layoutManager->set($data, $scope, $name);
|
||||
$result = $layoutManager->save();
|
||||
|
||||
if ($result === false) throw new Error("Error while saving layout.");
|
||||
|
||||
$this->getInjection('dataManager')->updateCacheTimestamp();
|
||||
|
||||
return $layoutManager->get($scope, $name);
|
||||
}
|
||||
|
||||
public function resetToDefault(string $scope, string $name, ?string $setId = null)
|
||||
{
|
||||
$this->getInjection('dataManager')->updateCacheTimestamp();
|
||||
|
||||
if ($setId) {
|
||||
$layout = $this->getRecordFromSet($scope, $name, $setId);
|
||||
if ($layout) {
|
||||
$em = $this->getInjection('entityManager');
|
||||
$em->removeEntity($layout);
|
||||
}
|
||||
return $this->getInjection('layout')->get($scope, $name);
|
||||
}
|
||||
|
||||
return $this->getInjection('layout')->resetToDefault($scope, $name);
|
||||
}
|
||||
|
||||
public function getOriginal(string $scope, string $name, ?string $setId = null)
|
||||
{
|
||||
$this->getInjection('dataManager')->updateCacheTimestamp();
|
||||
|
||||
if ($setId) {
|
||||
$layout = $this->getRecordFromSet($scope, $name, $setId, true);
|
||||
if ($layout) {
|
||||
return $layout->get('data');
|
||||
}
|
||||
}
|
||||
return $this->getInjection('layout')->get($scope, $name);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
<div class="page-header"><h3><a href="#Admin">{{translate 'Administration'}}</a>
|
||||
<span class="breadcrumb-separator"><span class="chevron-right"></span></span>
|
||||
{{translate 'Layout Manager' scope='Admin'}}</h3></div>
|
||||
<div class="page-header"><h3>{{{headerHtml}}}</h3></div>
|
||||
|
||||
<div class="row">
|
||||
<div id="layouts-menu" class="col-sm-3">
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
|
||||
<input data-name="{{name}}" type="text">
|
||||
<input data-name="{{name}}" type="text" class="{{#if viewObject.params.displayAsList}}as-list{{/if}}">
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<div class="container content">
|
||||
<div class="col-md-6 col-md-offset-3 col-sm-8 col-sm-offset-2">
|
||||
<div class="col-md-6 col-md-offset-2 col-sm-8 col-sm-offset-1">
|
||||
<div class="panel panel-success">
|
||||
<div class="panel-body">
|
||||
<p>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<div class="container content">
|
||||
<div class="col-md-6 col-md-offset-3 col-sm-8 col-sm-offset-2">
|
||||
<div class="col-md-6 col-md-offset-2 col-sm-8 col-sm-offset-1">
|
||||
<div class="panel panel-success">
|
||||
<div class="panel-body">
|
||||
{{#if messageField}}
|
||||
|
||||
45
client/src/controllers/layout-set.js
Normal file
45
client/src/controllers/layout-set.js
Normal file
@@ -0,0 +1,45 @@
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2020 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* EspoCRM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
define('controllers/layout-set', 'controllers/record', function (Dep) {
|
||||
|
||||
return Dep.extend({
|
||||
|
||||
actionEditLayouts: function (options) {
|
||||
var id = options.id;
|
||||
if (!id) throw new Error("ID not passed.");
|
||||
|
||||
this.main('views/layout-set/layouts', {
|
||||
layoutSetId: id,
|
||||
scope: options.scope,
|
||||
type: options.type,
|
||||
});
|
||||
},
|
||||
|
||||
});
|
||||
});
|
||||
@@ -50,8 +50,12 @@ define('layout-manager', [], function () {
|
||||
return this.applicationId + '-' + scope + '-' + type;
|
||||
},
|
||||
|
||||
getUrl: function (scope, type) {
|
||||
return scope + '/layout/' + type;
|
||||
getUrl: function (scope, type, setId) {
|
||||
var url = scope + '/layout/' + type;
|
||||
if (setId) {
|
||||
url += '/' + setId;
|
||||
}
|
||||
return url;
|
||||
},
|
||||
|
||||
get: function (scope, type, callback, cache) {
|
||||
@@ -81,11 +85,8 @@ define('layout-manager', [], function () {
|
||||
}
|
||||
}
|
||||
|
||||
this.ajax({
|
||||
url: this.getUrl(scope, type),
|
||||
type: 'GET',
|
||||
dataType: 'json',
|
||||
success: function (layout) {
|
||||
Espo.Ajax.getRequest(this.getUrl(scope, type)).then(
|
||||
function (layout) {
|
||||
if (typeof callback === 'function') {
|
||||
callback(layout);
|
||||
}
|
||||
@@ -94,54 +95,61 @@ define('layout-manager', [], function () {
|
||||
this.cache.set('app-layout', key, layout);
|
||||
}
|
||||
}.bind(this)
|
||||
});
|
||||
);
|
||||
},
|
||||
|
||||
set: function (scope, type, layout, callback) {
|
||||
var key = this.getKey(scope, type);
|
||||
getOriginal: function (scope, type, setId, callback) {
|
||||
var url = 'Layout/action/getOriginal?scope='+scope+'&name='+type;
|
||||
if (setId) url += '&setId='+setId;
|
||||
|
||||
this.ajax({
|
||||
url: this.getUrl(scope, type),
|
||||
type: 'PUT',
|
||||
data: JSON.stringify(layout),
|
||||
success: function () {
|
||||
if (this.cache && key) {
|
||||
this.cache.set('app-layout', key, layout);
|
||||
Espo.Ajax.getRequest(url).then(
|
||||
function (layout) {
|
||||
if (typeof callback === 'function') {
|
||||
callback(layout);
|
||||
}
|
||||
this.data[key] = layout;
|
||||
}.bind(this)
|
||||
);
|
||||
},
|
||||
|
||||
set: function (scope, type, layout, callback, setId) {
|
||||
Espo.Ajax.putRequest(this.getUrl(scope, type, setId), layout).then(
|
||||
function () {
|
||||
var key = this.getKey(scope, type);
|
||||
if (this.cache && key) {
|
||||
this.cache.clear('app-layout', key);
|
||||
}
|
||||
delete this.data[key];
|
||||
this.trigger('sync');
|
||||
|
||||
if (typeof callback === 'function') {
|
||||
callback();
|
||||
}
|
||||
}.bind(this)
|
||||
});
|
||||
);
|
||||
},
|
||||
|
||||
resetToDefault: function (scope, type, callback) {
|
||||
var key = this.getKey(scope, type);
|
||||
|
||||
this.ajax({
|
||||
url: 'Layout/action/resetToDefault',
|
||||
type: 'POST',
|
||||
data: JSON.stringify({
|
||||
scope: scope,
|
||||
name: type
|
||||
}),
|
||||
success: function (layout) {
|
||||
resetToDefault: function (scope, type, callback, setId) {
|
||||
Espo.Ajax.postRequest('Layout/action/resetToDefault', {
|
||||
scope: scope,
|
||||
name: type,
|
||||
setId: setId,
|
||||
}).then(
|
||||
function (layout) {
|
||||
var key = this.getKey(scope, type);
|
||||
if (this.cache) {
|
||||
this.cache.clear('app-layout', key);
|
||||
}
|
||||
this.data[key] = layout;
|
||||
delete this.data[key];
|
||||
this.trigger('sync');
|
||||
|
||||
if (typeof callback === 'function') {
|
||||
callback();
|
||||
}
|
||||
}.bind(this)
|
||||
});
|
||||
}
|
||||
);
|
||||
},
|
||||
|
||||
}, Backbone.Events);
|
||||
|
||||
return LayoutManager;
|
||||
|
||||
});
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
Espo.define('views/admin/layouts/base', 'view', function (Dep) {
|
||||
define('views/admin/layouts/base', 'view', function (Dep) {
|
||||
|
||||
return Dep.extend({
|
||||
|
||||
@@ -92,13 +92,13 @@ Espo.define('views/admin/layouts/base', 'view', function (Dep) {
|
||||
if (typeof callback == 'function') {
|
||||
callback();
|
||||
}
|
||||
}.bind(this));
|
||||
}.bind(this), this.setId);
|
||||
},
|
||||
|
||||
resetToDefault: function () {
|
||||
this.getHelper().layoutManager.resetToDefault(this.scope, this.type, function () {
|
||||
this.cancel();
|
||||
}.bind(this));
|
||||
}.bind(this), this.options.setId);
|
||||
},
|
||||
|
||||
reset: function () {
|
||||
@@ -112,6 +112,7 @@ Espo.define('views/admin/layouts/base', 'view', function (Dep) {
|
||||
this.events = _.clone(this.events);
|
||||
this.scope = this.options.scope;
|
||||
this.type = this.options.type;
|
||||
this.setId = this.options.setId;
|
||||
|
||||
this.dataAttributeList =
|
||||
this.getMetadata().get(['clientDefs', this.scope, 'additionalLayouts', this.type, 'dataAttributeList'])
|
||||
|
||||
@@ -66,12 +66,12 @@ define('views/admin/layouts/default-side-panel', 'views/admin/layouts/rows', fun
|
||||
|
||||
loadLayout: function (callback) {
|
||||
this.getModelFactory().create(Espo.Utils.hyphenToUpperCamelCase(this.scope), function (model) {
|
||||
this.getHelper().layoutManager.get(this.scope, this.type, function (layout) {
|
||||
this.getHelper().layoutManager.getOriginal(this.scope, this.type, this.setId, function (layout) {
|
||||
this.readDataFromLayout(model, layout);
|
||||
if (callback) {
|
||||
callback();
|
||||
}
|
||||
}.bind(this), false);
|
||||
}.bind(this));
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
|
||||
@@ -26,10 +26,9 @@
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
Espo.define('views/admin/layouts/detail-convert', 'views/admin/layouts/detail', function (Dep) {
|
||||
define('views/admin/layouts/detail-convert', 'views/admin/layouts/detail', function (Dep) {
|
||||
|
||||
return Dep.extend({
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
Espo.define('views/admin/layouts/detail-small', 'views/admin/layouts/detail', function (Dep) {
|
||||
define('views/admin/layouts/detail-small', 'views/admin/layouts/detail', function (Dep) {
|
||||
|
||||
return Dep.extend({
|
||||
|
||||
@@ -34,4 +34,3 @@ Espo.define('views/admin/layouts/detail-small', 'views/admin/layouts/detail', fu
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
Espo.define('views/admin/layouts/detail', 'views/admin/layouts/grid', function (Dep) {
|
||||
define('views/admin/layouts/detail', 'views/admin/layouts/grid', function (Dep) {
|
||||
|
||||
return Dep.extend({
|
||||
|
||||
@@ -91,7 +91,7 @@ Espo.define('views/admin/layouts/detail', 'views/admin/layouts/grid', function (
|
||||
promiseList.push(
|
||||
new Promise(function (resolve) {
|
||||
this.getModelFactory().create(this.scope, function (m) {
|
||||
this.getHelper().layoutManager.get(this.scope, this.type, function (layoutLoaded) {
|
||||
this.getHelper().layoutManager.getOriginal(this.scope, this.type, this.setId, function (layoutLoaded) {
|
||||
layout = layoutLoaded;
|
||||
model = m;
|
||||
resolve();
|
||||
@@ -103,10 +103,14 @@ Espo.define('views/admin/layouts/detail', 'views/admin/layouts/grid', function (
|
||||
if (~['detail', 'detailSmall'].indexOf(this.type)) {
|
||||
promiseList.push(
|
||||
new Promise(function (resolve) {
|
||||
this.getHelper().layoutManager.get(this.scope, 'sidePanels' + Espo.Utils.upperCaseFirst(this.type), function (layoutLoaded) {
|
||||
this.sidePanelsLayout = layoutLoaded;
|
||||
resolve();
|
||||
}.bind(this));
|
||||
this.getHelper().layoutManager.getOriginal(
|
||||
this.scope, 'sidePanels' + Espo.Utils.upperCaseFirst(this.type),
|
||||
this.setId,
|
||||
function (layoutLoaded) {
|
||||
this.sidePanelsLayout = layoutLoaded;
|
||||
resolve();
|
||||
}.bind(this)
|
||||
);
|
||||
}.bind(this))
|
||||
);
|
||||
}
|
||||
@@ -116,24 +120,26 @@ Espo.define('views/admin/layouts/detail', 'views/admin/layouts/grid', function (
|
||||
function (resolve) {
|
||||
if (this.getMetadata().get(['clientDefs', scope, 'layoutDefaultSidePanelDisabled'])) resolve();
|
||||
|
||||
this.getHelper().layoutManager.get(this.scope, 'defaultSidePanel', function (layoutLoaded) {
|
||||
this.defaultSidePanelLayout = layoutLoaded;
|
||||
this.getHelper().layoutManager.getOriginal(this.scope, 'defaultSidePanel', this.setId,
|
||||
function (layoutLoaded) {
|
||||
this.defaultSidePanelLayout = layoutLoaded;
|
||||
|
||||
this.defaultPanelFieldList = Espo.Utils.clone(this.defaultPanelFieldList);
|
||||
this.defaultPanelFieldList = Espo.Utils.clone(this.defaultPanelFieldList);
|
||||
|
||||
layoutLoaded.forEach(function (item) {
|
||||
var field = item.name;
|
||||
if (!field) return;
|
||||
if (field === ':assignedUser') {
|
||||
field = 'assignedUser';
|
||||
}
|
||||
if (!~this.defaultPanelFieldList.indexOf(field)) {
|
||||
this.defaultPanelFieldList.push(field);
|
||||
}
|
||||
}, this);
|
||||
layoutLoaded.forEach(function (item) {
|
||||
var field = item.name;
|
||||
if (!field) return;
|
||||
if (field === ':assignedUser') {
|
||||
field = 'assignedUser';
|
||||
}
|
||||
if (!~this.defaultPanelFieldList.indexOf(field)) {
|
||||
this.defaultPanelFieldList.push(field);
|
||||
}
|
||||
}, this);
|
||||
|
||||
resolve();
|
||||
}.bind(this));
|
||||
resolve();
|
||||
}.bind(this)
|
||||
);
|
||||
}.bind(this)
|
||||
)
|
||||
);
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
Espo.define('views/admin/layouts/filters', 'views/admin/layouts/rows', function (Dep) {
|
||||
define('views/admin/layouts/filters', 'views/admin/layouts/rows', function (Dep) {
|
||||
|
||||
return Dep.extend({
|
||||
|
||||
@@ -47,7 +47,7 @@ Espo.define('views/admin/layouts/filters', 'views/admin/layouts/rows', function
|
||||
|
||||
loadLayout: function (callback) {
|
||||
this.getModelFactory().create(this.scope, function (model) {
|
||||
this.getHelper().layoutManager.get(this.scope, this.type, function (layout) {
|
||||
this.getHelper().layoutManager.getOriginal(this.scope, this.type, this.setId, function (layout) {
|
||||
|
||||
var allFields = [];
|
||||
for (var field in model.defs.fields) {
|
||||
@@ -86,7 +86,7 @@ Espo.define('views/admin/layouts/filters', 'views/admin/layouts/rows', function
|
||||
}
|
||||
|
||||
callback();
|
||||
}.bind(this), false);
|
||||
}.bind(this));
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
@@ -111,8 +111,7 @@ Espo.define('views/admin/layouts/filters', 'views/admin/layouts/rows', function
|
||||
return false;
|
||||
}
|
||||
return !model.getFieldParam(name, 'disabled') && !model.getFieldParam(name, 'layoutFiltersDisabled');
|
||||
}
|
||||
},
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -58,6 +58,7 @@ define('views/admin/layouts/index', 'view', function (Dep) {
|
||||
typeList: this.typeList,
|
||||
scope: this.scope,
|
||||
layoutScopeDataList: this.getLayoutScopeDataList(),
|
||||
headerHtml: this.getHeaderHtml(),
|
||||
};
|
||||
},
|
||||
|
||||
@@ -125,7 +126,8 @@ define('views/admin/layouts/index', 'view', function (Dep) {
|
||||
}, this);
|
||||
|
||||
this.on('after:render', function () {
|
||||
$("#layouts-menu button[data-scope='" + this.options.scope + "'][data-type='" + this.options.type + "']").addClass('disabled');
|
||||
$("#layouts-menu button[data-scope='" + this.options.scope + "'][data-type='" + this.options.type + "']")
|
||||
.addClass('disabled');
|
||||
this.renderLayoutHeader();
|
||||
if (!this.options.scope) {
|
||||
this.renderDefaultPage();
|
||||
@@ -143,16 +145,17 @@ define('views/admin/layouts/index', 'view', function (Dep) {
|
||||
this.scope = scope;
|
||||
this.type = type;
|
||||
|
||||
this.getRouter().navigate('#Admin/layouts/scope=' + scope + '&type=' + type, {trigger: false});
|
||||
this.navigate(scope, type);
|
||||
|
||||
this.notify('Loading...');
|
||||
|
||||
var typeReal = this.getMetadata().get('clientDefs.' + scope + '.additionalLayouts.' + type + '.type') || type;
|
||||
|
||||
this.createView('content', 'Admin.Layouts.' + Espo.Utils.upperCaseFirst(typeReal), {
|
||||
this.createView('content', 'views/admin/layouts/' + Espo.Utils.camelCaseToHyphen(typeReal), {
|
||||
el: '#layout-content',
|
||||
scope: scope,
|
||||
type: type,
|
||||
setId: this.setId,
|
||||
}, function (view) {
|
||||
this.renderLayoutHeader();
|
||||
view.render();
|
||||
@@ -161,6 +164,10 @@ define('views/admin/layouts/index', 'view', function (Dep) {
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
navigate: function (scope, type) {
|
||||
this.getRouter().navigate('#Admin/layouts/scope=' + scope + '&type=' + type, {trigger: false});
|
||||
},
|
||||
|
||||
renderDefaultPage: function () {
|
||||
$("#layout-header").html('').hide();
|
||||
$("#layout-content").html(this.translate('selectLayout', 'messages', 'Admin'));
|
||||
@@ -179,7 +186,14 @@ define('views/admin/layouts/index', 'view', function (Dep) {
|
||||
updatePageTitle: function () {
|
||||
this.setPageTitle(this.getLanguage().translate('Layout Manager', 'labels', 'Admin'));
|
||||
},
|
||||
|
||||
getHeaderHtml: function () {
|
||||
var separatorHtml = '<span class="breadcrumb-separator"><span class="chevron-right"></span></span>';
|
||||
|
||||
var html = "<a href=\"#Admin\">"+this.translate('Administration')+"</a> " + separatorHtml + ' ' +
|
||||
this.translate('Layout Manager', 'labels', 'Admin');
|
||||
|
||||
return html;
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
Espo.define('views/admin/layouts/kanban', 'views/admin/layouts/list', function (Dep) {
|
||||
define('views/admin/layouts/kanban', 'views/admin/layouts/list', function (Dep) {
|
||||
|
||||
return Dep.extend({
|
||||
|
||||
@@ -54,7 +54,7 @@ Espo.define('views/admin/layouts/kanban', 'views/admin/layouts/list', function (
|
||||
|
||||
ignoreList: [],
|
||||
|
||||
ignoreTypeList: []
|
||||
ignoreTypeList: [],
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
@@ -26,10 +26,9 @@
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
Espo.define('views/admin/layouts/list-small', 'views/admin/layouts/list', function (Dep) {
|
||||
define('views/admin/layouts/list-small', 'views/admin/layouts/list', function (Dep) {
|
||||
|
||||
return Dep.extend({
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
Espo.define('views/admin/layouts/list', 'views/admin/layouts/rows', function (Dep) {
|
||||
define('views/admin/layouts/list', 'views/admin/layouts/rows', function (Dep) {
|
||||
|
||||
return Dep.extend({
|
||||
|
||||
@@ -84,12 +84,12 @@ Espo.define('views/admin/layouts/list', 'views/admin/layouts/rows', function (De
|
||||
|
||||
loadLayout: function (callback) {
|
||||
this.getModelFactory().create(Espo.Utils.hyphenToUpperCamelCase(this.scope), function (model) {
|
||||
this.getHelper().layoutManager.get(this.scope, this.type, function (layout) {
|
||||
this.getHelper().layoutManager.getOriginal(this.scope, this.type, this.setId, function (layout) {
|
||||
this.readDataFromLayout(model, layout);
|
||||
if (callback) {
|
||||
callback();
|
||||
}
|
||||
}.bind(this), false);
|
||||
}.bind(this));
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
Espo.define('views/admin/layouts/mass-update', 'views/admin/layouts/rows', function (Dep) {
|
||||
define('views/admin/layouts/mass-update', 'views/admin/layouts/rows', function (Dep) {
|
||||
|
||||
return Dep.extend({
|
||||
|
||||
@@ -55,7 +55,7 @@ Espo.define('views/admin/layouts/mass-update', 'views/admin/layouts/rows', funct
|
||||
|
||||
loadLayout: function (callback) {
|
||||
this.getModelFactory().create(this.scope, function (model) {
|
||||
this.getHelper().layoutManager.get(this.scope, this.type, function (layout) {
|
||||
this.getHelper().layoutManager.getOriginal(this.scope, this.type, this.setId, function (layout) {
|
||||
|
||||
var allFields = [];
|
||||
for (var field in model.defs.fields) {
|
||||
@@ -97,7 +97,7 @@ Espo.define('views/admin/layouts/mass-update', 'views/admin/layouts/rows', funct
|
||||
}
|
||||
|
||||
callback();
|
||||
}.bind(this), false);
|
||||
}.bind(this));
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
@@ -125,7 +125,7 @@ Espo.define('views/admin/layouts/mass-update', 'views/admin/layouts/rows', funct
|
||||
if (layoutList && !~layoutList.indexOf(this.type)) return;
|
||||
|
||||
return !model.getFieldParam(name, 'disabled') && !model.getFieldParam(name, 'layoutMassUpdateDisabled') && !model.getFieldParam(name, 'readOnly');
|
||||
}
|
||||
},
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
Espo.define('views/admin/layouts/relationships', 'views/admin/layouts/rows', function (Dep) {
|
||||
define('views/admin/layouts/relationships', 'views/admin/layouts/rows', function (Dep) {
|
||||
|
||||
return Dep.extend({
|
||||
|
||||
@@ -65,7 +65,7 @@ Espo.define('views/admin/layouts/relationships', 'views/admin/layouts/rows', fun
|
||||
|
||||
loadLayout: function (callback) {
|
||||
this.getModelFactory().create(this.scope, function (model) {
|
||||
this.getHelper().layoutManager.get(this.scope, this.type, function (layout) {
|
||||
this.getHelper().layoutManager.getOriginal(this.scope, this.type, this.setId, function (layout) {
|
||||
|
||||
var allFields = [];
|
||||
for (var field in model.defs.links) {
|
||||
@@ -125,7 +125,7 @@ Espo.define('views/admin/layouts/relationships', 'views/admin/layouts/rows', fun
|
||||
}
|
||||
|
||||
callback();
|
||||
}.bind(this), false);
|
||||
}.bind(this));
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
@@ -138,4 +138,3 @@ Espo.define('views/admin/layouts/relationships', 'views/admin/layouts/rows', fun
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -26,13 +26,11 @@
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
Espo.define('views/admin/layouts/side-panels-detail-small', 'views/admin/layouts/side-panels-detail', function (Dep) {
|
||||
define('views/admin/layouts/side-panels-detail-small', 'views/admin/layouts/side-panels-detail', function (Dep) {
|
||||
|
||||
return Dep.extend({
|
||||
|
||||
viewType: 'detailSmall'
|
||||
viewType: 'detailSmall',
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
Espo.define('views/admin/layouts/side-panels-detail', 'views/admin/layouts/rows', function (Dep) {
|
||||
define('views/admin/layouts/side-panels-detail', 'views/admin/layouts/rows', function (Dep) {
|
||||
|
||||
return Dep.extend({
|
||||
|
||||
@@ -71,12 +71,12 @@ Espo.define('views/admin/layouts/side-panels-detail', 'views/admin/layouts/rows'
|
||||
},
|
||||
|
||||
loadLayout: function (callback) {
|
||||
this.getHelper().layoutManager.get(this.scope, this.type, function (layout) {
|
||||
this.getHelper().layoutManager.getOriginal(this.scope, this.type, this.setId, function (layout) {
|
||||
this.readDataFromLayout(layout);
|
||||
if (callback) {
|
||||
callback();
|
||||
}
|
||||
}.bind(this), false);
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
readDataFromLayout: function (layout) {
|
||||
@@ -188,5 +188,3 @@ Espo.define('views/admin/layouts/side-panels-detail', 'views/admin/layouts/rows'
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
|
||||
@@ -26,13 +26,11 @@
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
Espo.define('views/admin/layouts/side-panels-edit-small', 'views/admin/layouts/side-panels-detail', function (Dep) {
|
||||
define('views/admin/layouts/side-panels-edit-small', 'views/admin/layouts/side-panels-detail', function (Dep) {
|
||||
|
||||
return Dep.extend({
|
||||
|
||||
viewType: 'editSmall'
|
||||
viewType: 'editSmall',
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
|
||||
@@ -26,13 +26,11 @@
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
Espo.define('views/admin/layouts/side-panels-edit', 'views/admin/layouts/side-panels-detail', function (Dep) {
|
||||
define('views/admin/layouts/side-panels-edit', 'views/admin/layouts/side-panels-detail', function (Dep) {
|
||||
|
||||
return Dep.extend({
|
||||
|
||||
viewType: 'edit'
|
||||
viewType: 'edit',
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
|
||||
@@ -318,7 +318,7 @@ define(
|
||||
var entityType = this.typeHash[address] || null;
|
||||
var id = this.idHash[address] || null;
|
||||
|
||||
var addressHtml = '<span>' + address + '</span>';
|
||||
var addressHtml = this.getHelper().escapeString(address);
|
||||
|
||||
if (name) {
|
||||
name = this.getHelper().escapeString(name);
|
||||
@@ -329,14 +329,15 @@ define(
|
||||
lineHtml = '<div>' + '<a href="#' + entityType + '/view/' + id + '">' + name + '</a> <span class="text-muted">»</span> ' + addressHtml + '</div>';
|
||||
} else {
|
||||
if (name) {
|
||||
lineHtml = '<span>' + name + ' <span class="text-muted">»</span> ' + addressHtml + '</span>';
|
||||
lineHtml = '<span class="email-address-line">' + name + ' <span class="text-muted">»</span> <span>' +
|
||||
addressHtml + '</span></span>';
|
||||
} else {
|
||||
lineHtml = addressHtml;
|
||||
lineHtml = '<span class="email-address-line">' + addressHtml + '</span>';
|
||||
}
|
||||
}
|
||||
if (!id) {
|
||||
if (this.getAcl().check('Contact', 'edit')) {
|
||||
lineHtml += From.prototype.getCreateHtml.call(this, address);
|
||||
lineHtml = From.prototype.getCreateHtml.call(this, address) + lineHtml;
|
||||
}
|
||||
}
|
||||
lineHtml = '<div>' + lineHtml + '</div>';
|
||||
@@ -344,5 +345,4 @@ define(
|
||||
},
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
@@ -131,19 +131,21 @@ define(
|
||||
var entityType = this.typeHash[address] || null;
|
||||
var id = this.idHash[address] || null;
|
||||
|
||||
var addressHtml = '<span>' + address + '</span>';
|
||||
var addressHtml = this.getHelper().escapeString(address);
|
||||
|
||||
var lineHtml = '';
|
||||
if (id) {
|
||||
lineHtml = '<div>' + '<a href="#' + entityType + '/view/' + id + '">' + name + '</a> <span class="text-muted">»</span> ' + addressHtml + '</div>';
|
||||
lineHtml = '<div>' + '<a href="#' + entityType + '/view/' + id + '">' + name +
|
||||
'</a> <span class="text-muted">»</span> ' + addressHtml + '</div>';
|
||||
} else {
|
||||
if (this.getAcl().check('Contact', 'create') || this.getAcl().check('Lead', 'create')) {
|
||||
lineHtml += this.getCreateHtml(address);
|
||||
}
|
||||
if (name) {
|
||||
lineHtml += '<span>' + name + ' <span class="text-muted">»</span> ' + addressHtml + '</span>';
|
||||
lineHtml += '<span class="email-address-line">' + name +
|
||||
' <span class="text-muted">»</span> <span>' + addressHtml + '</span></span>';
|
||||
} else {
|
||||
lineHtml += addressHtml;
|
||||
lineHtml += '<span class="email-address-line">' + addressHtml + '</span>';
|
||||
}
|
||||
}
|
||||
lineHtml = '<div>' + lineHtml + '</div>';
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
Espo.define('views/fields/array-int', 'views/fields/array', function (Dep) {
|
||||
define('views/fields/array-int', 'views/fields/array', function (Dep) {
|
||||
|
||||
return Dep.extend({
|
||||
|
||||
@@ -57,9 +57,15 @@ Espo.define('views/fields/array-int', 'views/fields/array', function (Dep) {
|
||||
if (isNaN(value)) {
|
||||
return;
|
||||
}
|
||||
Dep.prototype.removeValue.call(this, value);
|
||||
}
|
||||
|
||||
var valueInternal = value.toString().replace(/"/g, '\\"');
|
||||
|
||||
this.$list.children('[data-value="' + valueInternal + '"]').remove();
|
||||
|
||||
var index = this.selected.indexOf(value);
|
||||
this.selected.splice(index, 1);
|
||||
this.trigger('change');
|
||||
},
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -102,8 +102,11 @@ define('views/fields/formula', 'views/fields/text', function (Dep) {
|
||||
|
||||
if (this.$editor.length && (this.mode === 'edit' || this.mode == 'detail' || this.mode == 'list')) {
|
||||
this.$editor
|
||||
.css('minHeight', this.height + 'px')
|
||||
.css('fontSize', '14px');
|
||||
|
||||
if (this.mode === 'edit') {
|
||||
this.$editor.css('minHeight', this.height + 'px');
|
||||
}
|
||||
var editor = this.editor = ace.edit(this.containerId);
|
||||
|
||||
editor.setOptions({
|
||||
|
||||
@@ -159,6 +159,7 @@ define('views/fields/multi-enum', ['views/fields/array', 'lib!Selectize'], funct
|
||||
highlight: false,
|
||||
searchField: ['label'],
|
||||
plugins: pluginList,
|
||||
copyClassesToDropdown: true,
|
||||
score: function (search) {
|
||||
var score = this.getScoreFunction(search);
|
||||
search = search.toLowerCase();
|
||||
|
||||
40
client/src/views/layout-set/fields/edit.js
Normal file
40
client/src/views/layout-set/fields/edit.js
Normal file
@@ -0,0 +1,40 @@
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2020 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* EspoCRM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
define('views/layout-set/fields/edit', ['views/fields/base'], function (Dep) {
|
||||
|
||||
return Dep.extend({
|
||||
|
||||
detailTemplateContent:
|
||||
"<a class=\"btn btn-default\" href=\"#LayoutSet/editLayouts/id={{model.id}}\">" +
|
||||
"{{translate 'Edit Layouts' scope='LayoutSet'}}</a>",
|
||||
|
||||
editTemplateContent: '',
|
||||
|
||||
});
|
||||
});
|
||||
73
client/src/views/layout-set/fields/layout-list.js
Normal file
73
client/src/views/layout-set/fields/layout-list.js
Normal file
@@ -0,0 +1,73 @@
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2020 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* EspoCRM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
define('views/layout-set/fields/layout-list', [
|
||||
'views/fields/multi-enum', 'views/admin/layouts/index'], function (Dep, LaouytsIndex) {
|
||||
|
||||
return Dep.extend({
|
||||
|
||||
typeList: [
|
||||
'list',
|
||||
'detail',
|
||||
'listSmall',
|
||||
'detailSmall',
|
||||
'filters',
|
||||
'massUpdate',
|
||||
'relationships',
|
||||
'sidePanelsDetail',
|
||||
'sidePanelsEdit',
|
||||
'sidePanelsDetailSmall',
|
||||
'sidePanelsEditSmall',
|
||||
],
|
||||
|
||||
setupOptions: function () {
|
||||
this.params.options = [];
|
||||
this.translatedOptions = {};
|
||||
|
||||
this.scopeList = Object.keys(this.getMetadata().get('scopes')).filter(function (item) {
|
||||
return this.getMetadata().get(['scopes', item, 'layouts']);
|
||||
}, this).sort(function (v1, v2) {
|
||||
return this.translate(v1, 'scopeNames').localeCompare(this.translate(v2, 'scopeNames'));
|
||||
}.bind(this));
|
||||
|
||||
var dataList = LaouytsIndex.prototype.getLayoutScopeDataList.call(this);
|
||||
|
||||
dataList.forEach(function (item1) {
|
||||
item1.typeList.forEach(function (type) {
|
||||
var item = item1.scope + '.' + type;
|
||||
if (type.substr(-6) === 'Portal') return;
|
||||
this.params.options.push(item);
|
||||
|
||||
this.translatedOptions[item] = this.translate(item1.scope, 'scopeNames') + '.' +
|
||||
this.translate(type, 'layouts', 'Admin');
|
||||
}, this);
|
||||
}, this);
|
||||
},
|
||||
|
||||
});
|
||||
});
|
||||
97
client/src/views/layout-set/layouts.js
Normal file
97
client/src/views/layout-set/layouts.js
Normal file
@@ -0,0 +1,97 @@
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2020 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* EspoCRM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
define('views/layout-set/layouts', 'views/admin/layouts/index', function (Dep) {
|
||||
|
||||
return Dep.extend({
|
||||
|
||||
setup: function () {
|
||||
Dep.prototype.setup.call(this);
|
||||
|
||||
var setId = this.setId = this.options.layoutSetId;
|
||||
|
||||
this.wait(
|
||||
this.getModelFactory().create('LayoutSet')
|
||||
.then(
|
||||
function (m) {
|
||||
this.sModel = m;
|
||||
m.id = setId;
|
||||
return m.fetch();
|
||||
}.bind(this)
|
||||
)
|
||||
);
|
||||
},
|
||||
|
||||
getLayoutScopeDataList: function () {
|
||||
var dataList = [];
|
||||
var list = this.sModel.get('layoutList') || [];
|
||||
|
||||
var scopeList = [];
|
||||
|
||||
list.forEach(function (item) {
|
||||
var arr = item.split('.');
|
||||
var scope = arr[0];
|
||||
if (~scopeList.indexOf(scope)) return;
|
||||
scopeList.push(scope);
|
||||
});
|
||||
|
||||
scopeList.forEach(function (scope) {
|
||||
var o = {};
|
||||
o.scope = scope;
|
||||
o.typeList = [];
|
||||
|
||||
list.forEach(function (item) {
|
||||
var arr = item.split('.');
|
||||
var scope = arr[0];
|
||||
var type = arr[1];
|
||||
if (scope !== o.scope) return;
|
||||
o.typeList.push(type);
|
||||
});
|
||||
|
||||
dataList.push(o);
|
||||
});
|
||||
|
||||
return dataList;
|
||||
},
|
||||
|
||||
getHeaderHtml: function () {
|
||||
var m = this.sModel;
|
||||
var separatorHtml = '<span class="breadcrumb-separator"><span class="chevron-right"></span></span>';
|
||||
|
||||
var html = "<a href=\"#LayoutSet\">"+this.translate('LayoutSet', 'scopeNamesPlural')+"</a> " + separatorHtml + ' ' +
|
||||
"<a href=\"#LayoutSet/view/"+m.id+"\">"+Handlebars.Utils.escapeExpression(m.get('name'))+"</a> " +
|
||||
separatorHtml + ' ' + this.translate('Edit Layouts', 'labels', 'LayoutSet');
|
||||
|
||||
return html;
|
||||
},
|
||||
|
||||
navigate: function (scope, type) {
|
||||
this.getRouter().navigate('#LayoutSet/editLayouts/id='+this.setId+'&scope='+scope + '&type='+type, {trigger: false});
|
||||
},
|
||||
});
|
||||
});
|
||||
@@ -2790,7 +2790,7 @@ table.table td.cell .complex-text {
|
||||
|
||||
.email-address-create-dropdown .btn {
|
||||
position: relative;
|
||||
top: -1px;
|
||||
top: -2px;
|
||||
padding: 0 4px;
|
||||
margin: 0;
|
||||
margin-bottom: 0;
|
||||
@@ -2798,6 +2798,11 @@ table.table td.cell .complex-text {
|
||||
line-height: 1.3;
|
||||
}
|
||||
|
||||
.email-address-create-dropdown + .email-address-line {
|
||||
display: block;
|
||||
width: ~"calc(100% - 17px)";
|
||||
}
|
||||
|
||||
#main > .calendar-container {
|
||||
margin-top: 10px;
|
||||
|
||||
@@ -3624,3 +3629,8 @@ a.link-gray {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.selectize-control.as-list .item {
|
||||
display: block;
|
||||
}
|
||||
Reference in New Issue
Block a user