From bddbfc33b8c2c57e57e224b7bd6538d65bd1900e Mon Sep 17 00:00:00 2001 From: Yuri Kuznetsov Date: Tue, 10 Jun 2025 18:16:06 +0300 Subject: [PATCH] pdf template status --- .../AppParams/TemplateEntityTypeList.php | 41 +++++++++--------- .../Select/Template/PrimaryFilters/Active.php | 42 +++++++++++++++++++ application/Espo/Entities/Template.php | 7 ++++ .../Espo/Resources/i18n/en_US/Global.json | 3 +- .../Espo/Resources/i18n/en_US/Template.json | 7 +++- .../Resources/layouts/EmailTemplate/list.json | 21 ++++++++-- .../layouts/EmailTemplate/listSmall.json | 3 +- .../Resources/layouts/Template/detail.json | 18 ++++---- .../layouts/Template/detailSmall.json | 7 ++-- .../Espo/Resources/layouts/Template/list.json | 5 ++- .../metadata/clientDefs/Template.json | 6 +++ .../metadata/entityDefs/Template.json | 12 ++++++ .../metadata/selectDefs/Template.json | 3 ++ application/Espo/Tools/Pdf/Service.php | 37 +++++++--------- client/src/views/modals/select-template.js | 2 + 15 files changed, 151 insertions(+), 63 deletions(-) create mode 100644 application/Espo/Classes/Select/Template/PrimaryFilters/Active.php diff --git a/application/Espo/Classes/AppParams/TemplateEntityTypeList.php b/application/Espo/Classes/AppParams/TemplateEntityTypeList.php index 27d4d90672..44d24f9a29 100644 --- a/application/Espo/Classes/AppParams/TemplateEntityTypeList.php +++ b/application/Espo/Classes/AppParams/TemplateEntityTypeList.php @@ -30,29 +30,27 @@ namespace Espo\Classes\AppParams; use Espo\Core\Acl; +use Espo\Core\Exceptions\BadRequest; +use Espo\Core\Exceptions\Forbidden; use Espo\Core\ORM\EntityManager; use Espo\Core\Select\SelectBuilderFactory; use Espo\Entities\Template; use Espo\Tools\App\AppParam; +use RuntimeException; /** * Returns a list of entity types for which a PDF template exists. + * + * @noinspection PhpUnused */ class TemplateEntityTypeList implements AppParam { - private Acl $acl; - private SelectBuilderFactory $selectBuilderFactory; - private EntityManager $entityManager; public function __construct( - Acl $acl, - SelectBuilderFactory $selectBuilderFactory, - EntityManager $entityManager - ) { - $this->acl = $acl; - $this->selectBuilderFactory = $selectBuilderFactory; - $this->entityManager = $entityManager; - } + private Acl $acl, + private SelectBuilderFactory $selectBuilderFactory, + private EntityManager $entityManager, + ) {} /** * @return string[] @@ -65,14 +63,19 @@ class TemplateEntityTypeList implements AppParam $list = []; - $query = $this->selectBuilderFactory - ->create() - ->from(Template::ENTITY_TYPE) - ->withAccessControlFilter() - ->buildQueryBuilder() - ->select(['entityType']) - ->group(['entityType']) - ->build(); + try { + $query = $this->selectBuilderFactory + ->create() + ->from(Template::ENTITY_TYPE) + ->withAccessControlFilter() + ->buildQueryBuilder() + ->select(['entityType']) + ->where(['status' => Template::STATUS_ACTIVE]) + ->group(['entityType']) + ->build(); + } catch (BadRequest|Forbidden $e) { + throw new RuntimeException('', 0, $e); + } $templateCollection = $this->entityManager ->getRDBRepositoryByClass(Template::class) diff --git a/application/Espo/Classes/Select/Template/PrimaryFilters/Active.php b/application/Espo/Classes/Select/Template/PrimaryFilters/Active.php new file mode 100644 index 0000000000..09fe45bcae --- /dev/null +++ b/application/Espo/Classes/Select/Template/PrimaryFilters/Active.php @@ -0,0 +1,42 @@ +. + * + * 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 Affero General Public License version 3. + * + * In accordance with Section 7(b) of the GNU Affero General Public License version 3, + * these Appropriate Legal Notices must retain the display of the "EspoCRM" word. + ************************************************************************/ + +namespace Espo\Classes\Select\Template\PrimaryFilters; + +use Espo\Core\Select\Primary\Filter; +use Espo\Entities\Template; +use Espo\ORM\Query\SelectBuilder as QueryBuilder; + +class Active implements Filter +{ + public function apply(QueryBuilder $queryBuilder): void + { + $queryBuilder->where(['status' => Template::STATUS_ACTIVE]); + } +} diff --git a/application/Espo/Entities/Template.php b/application/Espo/Entities/Template.php index 39ab2047ae..1046d8fb67 100644 --- a/application/Espo/Entities/Template.php +++ b/application/Espo/Entities/Template.php @@ -36,6 +36,8 @@ class Template extends Entity { public const ENTITY_TYPE = 'Template'; + public const STATUS_ACTIVE = 'Active'; + public function getTargetEntityType(): string { $entityType = $this->get('entityType'); @@ -46,4 +48,9 @@ class Template extends Entity return $entityType; } + + public function isActive(): bool + { + return $this->get('status') === self::STATUS_ACTIVE; + } } diff --git a/application/Espo/Resources/i18n/en_US/Global.json b/application/Espo/Resources/i18n/en_US/Global.json index b3db56c93b..a7915be899 100644 --- a/application/Espo/Resources/i18n/en_US/Global.json +++ b/application/Espo/Resources/i18n/en_US/Global.json @@ -453,7 +453,8 @@ "presetFilters": { "followed": "Followed", "all": "All", - "starred": "Starred" + "starred": "Starred", + "active": "Active" }, "massActions": { "delete": "Delete", diff --git a/application/Espo/Resources/i18n/en_US/Template.json b/application/Espo/Resources/i18n/en_US/Template.json index 81eb635144..6050d81f16 100644 --- a/application/Espo/Resources/i18n/en_US/Template.json +++ b/application/Espo/Resources/i18n/en_US/Template.json @@ -20,7 +20,8 @@ "pageHeight": "Page Height (mm)", "fontFace": "Font", "title": "Title", - "style": "Style" + "style": "Style", + "status": "Status" }, "links": { }, @@ -28,6 +29,10 @@ "Create Template": "Create Template" }, "options": { + "status": { + "Active": "Active", + "Inactive": "Inactive" + }, "pageOrientation": { "Portrait": "Portrait", "Landscape": "Landscape" diff --git a/application/Espo/Resources/layouts/EmailTemplate/list.json b/application/Espo/Resources/layouts/EmailTemplate/list.json index c54d30019e..1aa7555f13 100644 --- a/application/Espo/Resources/layouts/EmailTemplate/list.json +++ b/application/Espo/Resources/layouts/EmailTemplate/list.json @@ -1,5 +1,20 @@ [ - {"name": "name", "link": true}, - {"name": "assignedUser", "width": 20}, - {"name": "createdAt", "width": 20} + { + "name": "name", + "link": true + }, + { + "name": "assignedUser", + "width": 20 + }, + { + "name": "oneOff", + "width": 11, + "hidden": true + }, + { + "name": "createdAt", + "width": 20, + "hidden": true + } ] diff --git a/application/Espo/Resources/layouts/EmailTemplate/listSmall.json b/application/Espo/Resources/layouts/EmailTemplate/listSmall.json index 2aecb9c73b..937d138304 100644 --- a/application/Espo/Resources/layouts/EmailTemplate/listSmall.json +++ b/application/Espo/Resources/layouts/EmailTemplate/listSmall.json @@ -1,5 +1,4 @@ [ {"name": "name", "link": true}, - {"name": "assignedUser", "width": 22}, - {"name": "createdAt", "width": 22} + {"name": "assignedUser", "width": 23} ] diff --git a/application/Espo/Resources/layouts/Template/detail.json b/application/Espo/Resources/layouts/Template/detail.json index 52a81b582b..00d45ab90a 100644 --- a/application/Espo/Resources/layouts/Template/detail.json +++ b/application/Espo/Resources/layouts/Template/detail.json @@ -1,21 +1,25 @@ [ { - "label": "", "rows": [ [ { - "name":"name" + "name": "name" }, { - "name":"entityType" + "name": "status" } ], - [{"name":"variables","fullWidth":true, "view": "Template.Fields.Variables"}], - [{"name":"body","fullWidth":true}] + [ + { + "name": "entityType" + }, + false + ], + [{"name": "variables", "view": "views/template/fields/variables"}], + [{"name":"body"}] ] }, { - "label": "", "rows": [ [{"name":"pageOrientation"}, {"name":"pageFormat"}], [{"name":"pageWidth"}, {"name":"pageHeight"}], @@ -23,7 +27,6 @@ ] }, { - "label": "", "rows": [ [false, {"name":"topMargin"}, false], [{"name":"leftMargin"}, false, {"name":"rightMargin"}], @@ -31,7 +34,6 @@ ] }, { - "label": "", "rows": [ [{"name": "title"}, false], [{"name":"printHeader"}, {"name":"headerPosition"}], diff --git a/application/Espo/Resources/layouts/Template/detailSmall.json b/application/Espo/Resources/layouts/Template/detailSmall.json index 53ae62df8e..295a980d82 100644 --- a/application/Espo/Resources/layouts/Template/detailSmall.json +++ b/application/Espo/Resources/layouts/Template/detailSmall.json @@ -1,10 +1,9 @@ [ { - "label": "", "rows": [ - [{"name":"name"}], - [{"name":"entityType"}, false], - [{"name":"body"}] + [{"name": "name"}], + [{"name": "entityType"}, {"name": "status"}], + [{"name": "body"}] ] } ] diff --git a/application/Espo/Resources/layouts/Template/list.json b/application/Espo/Resources/layouts/Template/list.json index 541fa58acd..e5f94af0fd 100644 --- a/application/Espo/Resources/layouts/Template/list.json +++ b/application/Espo/Resources/layouts/Template/list.json @@ -1,4 +1,5 @@ [ - {"name": "name", "width": 50, "link": true}, - {"name": "entityType"} + {"name": "name", "link": true}, + {"name": "entityType", "width": 25}, + {"name": "status", "width": 25} ] diff --git a/application/Espo/Resources/metadata/clientDefs/Template.json b/application/Espo/Resources/metadata/clientDefs/Template.json index 3ab2902902..6f893cd608 100644 --- a/application/Espo/Resources/metadata/clientDefs/Template.json +++ b/application/Espo/Resources/metadata/clientDefs/Template.json @@ -5,5 +5,11 @@ "edit": "views/template/record/edit" }, "mergeDisabled": true, + "filterList": [ + "active" + ], + "selectDefaultFilters": { + "filter": "active" + }, "iconClass": "fas fa-file-pdf" } diff --git a/application/Espo/Resources/metadata/entityDefs/Template.json b/application/Espo/Resources/metadata/entityDefs/Template.json index 245fd0d0c1..8ea2334050 100644 --- a/application/Espo/Resources/metadata/entityDefs/Template.json +++ b/application/Espo/Resources/metadata/entityDefs/Template.json @@ -24,6 +24,18 @@ "translation": "Global.scopeNames", "view": "views/template/fields/entity-type" }, + "status": { + "type": "enum", + "options": [ + "Active", + "Inactive" + ], + "default": "Active", + "style": { + "Inactive": "info" + }, + "maxLength": 8 + }, "leftMargin": { "type": "float", "default": 10 diff --git a/application/Espo/Resources/metadata/selectDefs/Template.json b/application/Espo/Resources/metadata/selectDefs/Template.json index e9788d0f4a..2bb265099c 100644 --- a/application/Espo/Resources/metadata/selectDefs/Template.json +++ b/application/Espo/Resources/metadata/selectDefs/Template.json @@ -1,5 +1,8 @@ { "accessControlFilterClassNameMap": { "mandatory": "Espo\\Classes\\Select\\Template\\AccessControlFilters\\Mandatory" + }, + "primaryFilterClassNameMap": { + "active": "Espo\\Classes\\Select\\Template\\PrimaryFilters\\Active" } } diff --git a/application/Espo/Tools/Pdf/Service.php b/application/Espo/Tools/Pdf/Service.php index 349a85b67f..a7cb386791 100644 --- a/application/Espo/Tools/Pdf/Service.php +++ b/application/Espo/Tools/Pdf/Service.php @@ -43,28 +43,14 @@ class Service { private const DEFAULT_ENGINE = 'Dompdf'; - private EntityManager $entityManager; - private Acl $acl; - private ServiceContainer $serviceContainer; - private DataLoaderManager $dataLoaderManager; - private Config $config; - private Builder $builder; - public function __construct( - EntityManager $entityManager, - Acl $acl, - ServiceContainer $serviceContainer, - DataLoaderManager $dataLoaderManager, - Config $config, - Builder $builder - ) { - $this->entityManager = $entityManager; - $this->acl = $acl; - $this->serviceContainer = $serviceContainer; - $this->dataLoaderManager = $dataLoaderManager; - $this->config = $config; - $this->builder = $builder; - } + private EntityManager $entityManager, + private Acl $acl, + private ServiceContainer $serviceContainer, + private DataLoaderManager $dataLoaderManager, + private Config $config, + private Builder $builder, + ) {} /** * Generate a PDF. @@ -97,13 +83,18 @@ class Service throw new NotFound("Record not found."); } - /** @var ?TemplateEntity $template */ - $template = $this->entityManager->getEntityById(TemplateEntity::ENTITY_TYPE, $templateId); + $template = $this->entityManager + ->getRDBRepositoryByClass(TemplateEntity::class) + ->getById($templateId); if (!$template) { throw new NotFound("Template not found."); } + if (!$template->isActive()) { + throw new Forbidden("Template is not active."); + } + if ($applyAcl && !$this->acl->checkEntityRead($entity)) { throw new Forbidden("No access to record."); } diff --git a/client/src/views/modals/select-template.js b/client/src/views/modals/select-template.js index 521b943edc..31eb3a91b9 100644 --- a/client/src/views/modals/select-template.js +++ b/client/src/views/modals/select-template.js @@ -47,6 +47,8 @@ class SelectTemplateModalView extends SelectRecordsModalView { }); this.collection.where = this.searchManager.getWhere(); + + this.collection.data.primaryFilter = 'active'; } afterRender() {