Просмотр исходного кода

Ticket #5439 - Notifications: Allow to customize email templates.

AntonLV 6 месяцев назад
Родитель
Сommit
c48cc90e1d

+ 14 - 5
modules/boonex/notifications/classes/BxNtfsConfig.php

@@ -56,10 +56,14 @@ class BxNtfsConfig extends BxBaseModNotificationsConfig
             'PARAM_PROCESSED_EVENT' => 'bx_notifications_processed_event',
 
             // objects
+            'OBJECT_FORM_ETEMPLATE' => 'bx_notifications_etemplate',
+            'OBJECT_FORM_ETEMPLATE_DISPLAY_ADD' => 'bx_notifications_etemplate_add',
+            'OBJECT_FORM_ETEMPLATE_DISPLAY_EDIT' => 'bx_notifications_etemplate_edit',
             'OBJECT_MENU_SUBMENU' => 'bx_notifications_submenu', // main module submenu
             'OBJECT_MENU_SETTINGS' => 'bx_notifications_settings', // settings submenu
             'OBJECT_GRID_SETTINGS_ADMINISTRATION' => 'bx_notifications_settings_administration',
             'OBJECT_GRID_SETTINGS_COMMON' => 'bx_notifications_settings_common',
+            'OBJECT_GRID_ETEMPLATES' => 'bx_notifications_etemplates',
 
             // some language keys
             'T' => array(
@@ -114,13 +118,18 @@ class BxNtfsConfig extends BxBaseModNotificationsConfig
         );
 
         $sHtmlPrefix = str_replace('_', '-', $this->_sName);
-        $this->_aHtmlIds = array(
-            'view' => array(
+        $this->_aHtmlIds = [
+            'main' => [
+                'field_action' => $sHtmlPrefix . '-field-action',
+            ],
+            'view' => [
                 'block' => $sHtmlPrefix,
                 'events' => $sHtmlPrefix . '-events',
-                'event' => $sHtmlPrefix . '-event-'
-            )
-        );
+                'event' => $sHtmlPrefix . '-event-',
+                'add_etemplate_popup' => $sHtmlPrefix . '-etemplate-add',
+                'edit_etemplate_popup' => $sHtmlPrefix . '-etemplate-edit',
+            ]
+        ];
     }
 
     public function init(&$oDb)

+ 65 - 0
modules/boonex/notifications/classes/BxNtfsDb.php

@@ -14,6 +14,7 @@ class BxNtfsDb extends BxBaseModNotificationsDb
     protected $_sTableEvt2Usr;
     protected $_sTableQueue;
     protected $_sTableRead;
+    protected $_sTableEtemplates;
 
     /*
      * Constructor.
@@ -31,6 +32,25 @@ class BxNtfsDb extends BxBaseModNotificationsDb
         $this->_sTableEvt2Usr = $this->_sPrefix . 'events2users';
         $this->_sTableQueue = $this->_sPrefix . 'queue';
         $this->_sTableRead = $this->_sPrefix . 'read';
+        $this->_sTableEtemplates = $this->_sPrefix . 'etemplates';
+    }
+
+    public function getHandlerTypes()
+    {
+        return $this->getColumn("SELECT DISTINCT `alert_unit` FROM `{$this->_sTableHandlers}` WHERE `type`='insert'");
+    }
+
+    public function getHandlerActions($sUnit = '')
+    {
+        $aBindings = [];
+        $sWhereClause = "";
+
+        if($sUnit) {
+            $aBindings['alert_unit'] = $sUnit;
+            $sWhereClause .= " AND `alert_unit`=:alert_unit";
+        }
+
+        return $this->getColumn("SELECT DISTINCT `alert_action` FROM `{$this->_sTableHandlers}` WHERE `type`='insert'" . $sWhereClause, $aBindings);
     }
 
     public function markAsClicked($iUserId, $iEventId)
@@ -511,6 +531,51 @@ class BxNtfsDb extends BxBaseModNotificationsDb
         return (int)$this->query("DELETE FROM `" . $this->_sTableQueue . "` WHERE `id` IN (" . $this->implode_escape($mixedId) . ")") > 0;
     }
     
+    public function getEtemplates($aParams)
+    {
+    	$aMethod = ['name' => 'getAll', 'params' => [0 => 'query']];
+
+    	$sSelectClause = "*";
+    	$sWhereClause = $sOrderClause = $sLimitClause = "";
+
+        switch($aParams['sample']) {
+            case 'id':
+            	$aMethod['name'] = 'getRow';
+            	$aMethod['params'][1] = [
+                    'id' => $aParams['id']
+                ];
+
+                $sWhereClause = " AND `id`=:id";
+                break;
+
+            case 'type_action':
+            	$aMethod['name'] = 'getRow';
+            	$aMethod['params'][1] = [
+                    'type' => $aParams['type'],
+                    'action' => $aParams['action']
+                ];
+
+                $sWhereClause = " AND `type`=:type AND `action`=:action";
+
+                if(isset($aParams['active'])) {
+                    $aMethod['params'][1]['active'] = (int)$aParams['active'];
+
+                    $sWhereClause .= " AND `active`=:active";
+                }
+                break;
+        }
+
+        $sOrderClause = !empty($sOrderClause) ? "ORDER BY " . $sOrderClause : $sOrderClause;
+        $sLimitClause = !empty($sLimitClause) ? "LIMIT " . $sLimitClause : $sLimitClause;
+
+        $aMethod['params'][0] = "SELECT
+                " . $sSelectClause . "
+            FROM `" . $this->_sTableEtemplates . "`
+            WHERE 1" . $sWhereClause . " " . $sOrderClause . " " . $sLimitClause;
+
+        return call_user_func_array([$this, $aMethod['name']], $aMethod['params']);
+    }
+    
     public function cleanEvents($iClearIntervalInDays)
     {
         $this->query("DELETE FROM `{$this->_sTable}` WHERE `date` < :date", array('date' => time() - $iClearIntervalInDays * 86400));

+ 157 - 0
modules/boonex/notifications/classes/BxNtfsGridEtemplates.php

@@ -0,0 +1,157 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Notifications Notifications
+ * @ingroup     UnaModules
+ * 
+ * @{
+ */
+
+class BxNtfsGridEtemplates extends BxTemplGrid
+{
+    protected $_sModule;
+    protected $_oModule;
+
+    public function __construct ($aOptions, $oTemplate = false)
+    {
+        parent::__construct ($aOptions, $oTemplate);
+
+        $this->_sModule = 'bx_notifications';
+        $this->_oModule = BxDolModule::getInstance($this->_sModule);
+    }
+
+    public function getCode($isDisplayHeader = true)
+    {
+        $sResult = parent::getCode($isDisplayHeader);
+        if(!$sResult)
+            return $sResult;
+
+        return $sResult . $this->_oModule->_oTemplate->getJsCode('main');
+    }
+
+    public function performActionAdd()
+    {
+        $sAction = 'add';
+
+        $oForm = $this->_getFormObject($sAction);
+        $oForm->initChecker();
+        if($oForm->isSubmittedAndValid()) {
+            if(($iId = $oForm->insert()) !== false)
+                $aRes = ['grid' => $this->getCode(false), 'blink' => $iId];
+            else
+                $aRes = ['msg' => _t('_bx_ntfs_txt_err_cannot_perform')];
+
+            echoJson($aRes);
+        }
+        else {
+            $sContent = BxTemplFunctions::getInstance()->popupBox($this->_oModule->_oConfig->getHtmlIds('view', 'add_etemplate_popup'), _t('_bx_ntfs_grid_popup_title_ett_add'), $this->_oModule->_oTemplate->parseHtmlByName('etemplate_form.html', [
+                'form_id' => $oForm->aFormAttrs['id'],
+                'form' => $oForm->getCode(true),
+                'object' => $this->_sObject,
+                'action' => $sAction
+            ]));
+
+            echoJson(['popup' => ['html' => $sContent, 'options' => ['closeOnOuterClick' => false, 'removeOnClose' => true]]]);
+        }
+    }
+
+    public function performActionEdit()
+    {
+        $sAction = 'edit';
+
+        $iId = $this->_getId();
+        $aEtemplate = $this->_oModule->_oDb->getEtemplates(['sample' => 'id', 'id' => $iId]);
+        if(empty($aEtemplate) || !is_array($aEtemplate))
+            return echoJson([]);
+
+        $oForm = $this->_getFormObject($sAction, $aEtemplate);
+        $oForm->initChecker($aEtemplate);
+        if($oForm->isSubmittedAndValid()) {
+            if($oForm->update($iId) !== false)
+                $aRes = ['grid' => $this->getCode(false), 'blink' => $iId];
+            else
+                $aRes = ['msg' => _t('_bx_ntfs_txt_err_cannot_perform')];
+
+            echoJson($aRes);
+        }
+        else {
+            $sContent = BxTemplFunctions::getInstance()->popupBox($this->_oModule->_oConfig->getHtmlIds('edit_profile_popup'), _t('_bx_ntfs_grid_popup_title_ett_edit'), $this->_oModule->_oTemplate->parseHtmlByName('etemplate_form.html', [
+                'form_id' => $oForm->aFormAttrs['id'],
+                'form' => $oForm->getCode(true),
+                'object' => $this->_sObject,
+                'action' => $sAction
+            ]));
+
+            echoJson(['popup' => ['html' => $sContent, 'options' => ['closeOnOuterClick' => false, 'removeOnClose' => true]]]);
+        }
+    }
+
+    protected function _getCellType($mixedValue, $sKey, $aField, $aRow)
+    {
+        return parent::_getCellDefault($this->_oModule->_oTemplate->getTypeTitle($mixedValue), $sKey, $aField, $aRow);
+    }
+
+    protected function _getCellAction($mixedValue, $sKey, $aField, $aRow)
+    {
+        return parent::_getCellDefault($this->_oModule->_oTemplate->getActionTitle($mixedValue), $sKey, $aField, $aRow);
+    }
+
+    protected function _getActionsDisabledBehavior($aRow)
+    {
+        return false;
+    }
+
+    protected function _getFormObject($sAction, $aItem = [])
+    {
+        $CNF = &$this->_oModule->_oConfig->CNF;
+
+        $oForm = BxDolForm::getObjectInstance($CNF['OBJECT_FORM_ETEMPLATE'], $CNF['OBJECT_FORM_ETEMPLATE_DISPLAY_' . strtoupper($sAction)]);
+        $oForm->aFormAttrs['action'] = BX_DOL_URL_ROOT . 'grid.php?o=' . $this->_sObject . '&a=' . $sAction;
+        if(!empty($aItem['id']))
+            $oForm->aFormAttrs['action'] .= '&id=' . $aItem['id'];
+
+        if(($sK = 'type') && isset($oForm->aInputs[$sK])) {
+            $oForm->aInputs[$sK] = array_merge($oForm->aInputs[$sK], [
+                'attrs' => [
+                    'onchange' => $this->_oModule->_oConfig->getJsObject('main') . '.onChangeType(this)',
+                ],
+                'values' => [
+                    ['key' => '', 'value' => _t('_sys_please_select')]
+                ]
+            ]);
+
+            $aTypes = $this->_oModule->_oDb->getHandlerTypes();
+            foreach($aTypes as $sType)
+                $oForm->aInputs[$sK]['values'][] = ['key' => $sType, 'value' => $this->_oModule->_oTemplate->getTypeTitle($sType)];
+        }
+
+        if(($sK = 'action') && isset($oForm->aInputs[$sK])) {
+            $oForm->aInputs[$sK] = array_merge($oForm->aInputs[$sK], [
+                'attrs' => [
+                    'id' => $this->_oModule->_oConfig->getHtmlIds('main', 'field_action'),
+                    'disabled' => 'disabled'
+                ],
+                'values' => [
+                    ['key' => '', 'value' => _t('_sys_please_select')]
+                ]
+            ]);
+        }
+
+        if(($sK = 'body') && isset($oForm->aInputs[$sK]))
+            $oForm->aInputs[$sK]['code'] = 1;
+
+        return $oForm;
+    }
+
+    protected function _getId()
+    {
+        if(($aIds = bx_get('ids')) && is_array($aIds)) 
+            return array_shift($aIds);
+
+        return ($iId = bx_get('id')) !== false ? (int)$iId : false;
+    }
+}
+
+/** @} */

+ 12 - 0
modules/boonex/notifications/classes/BxNtfsModule.php

@@ -66,6 +66,18 @@ class BxNtfsModule extends BxBaseModNotificationsModule
     /**
      * ACTION METHODS
      */
+    public function actionGetAction($sType)
+    {
+        $aActions = $this->_oDb->getHandlerActions($sType);
+        if(empty($aActions) || !is_array($aActions))
+            return echoJson(['code' => 1]);
+
+        echoJson([
+            'code' => 0, 
+            'content' => $this->_oTemplate->getSelectActions($aActions)
+        ]);
+    }
+
     function actionMarkAsClicked()
     {
         $iId = bx_process_input(bx_get('id'), BX_DATA_INT);

+ 14 - 1
modules/boonex/notifications/classes/BxNtfsStudioPage.php

@@ -9,6 +9,8 @@
  * @{
  */
 
+define('BX_DOL_STUDIO_MOD_TYPE_ETEMPLATES', 'etemplates_text');
+
 class BxNtfsStudioPage extends BxBaseModNotificationsStudioPage
 {
     public function __construct($sModule, $mixedPageName, $sPage = "")
@@ -20,7 +22,8 @@ class BxNtfsStudioPage extends BxBaseModNotificationsStudioPage
         $this->aMenuItems = array_merge($this->aMenuItems, array(
             BX_BASE_MOD_NTFS_DTYPE_SITE => array('name' => BX_BASE_MOD_NTFS_DTYPE_SITE, 'icon' => 'globe', 'title' => '_bx_ntfs_lmi_cpt_site'),
             BX_BASE_MOD_NTFS_DTYPE_EMAIL => array('name' => BX_BASE_MOD_NTFS_DTYPE_EMAIL, 'icon' => 'envelope', 'title' => '_bx_ntfs_lmi_cpt_email'),
-            BX_BASE_MOD_NTFS_DTYPE_PUSH => array('name' => BX_BASE_MOD_NTFS_DTYPE_PUSH, 'icon' => 'bullhorn', 'title' => '_bx_ntfs_lmi_cpt_push')
+            BX_BASE_MOD_NTFS_DTYPE_PUSH => array('name' => BX_BASE_MOD_NTFS_DTYPE_PUSH, 'icon' => 'bullhorn', 'title' => '_bx_ntfs_lmi_cpt_push'),
+            BX_DOL_STUDIO_MOD_TYPE_ETEMPLATES => array('name' => BX_DOL_STUDIO_MOD_TYPE_ETEMPLATES, 'icon' => 'file-word', 'title' => '_bx_ntfs_lmi_cpt_etemplates_text'),
         ));
     }
 
@@ -38,6 +41,16 @@ class BxNtfsStudioPage extends BxBaseModNotificationsStudioPage
     {
         return $this->_getDeliveryType(BX_BASE_MOD_NTFS_DTYPE_PUSH);
     }
+    
+    protected function getEtemplatesText()
+    {
+        $oGrid = BxDolGrid::getObjectInstance($this->_oModule->_oConfig->CNF['OBJECT_GRID_ETEMPLATES'], BxDolStudioTemplate::getInstance());
+        if(!$oGrid)
+            return '';
+
+        $this->_oModule->_oTemplate->addStudioJs(['main.js']);
+        return $oGrid->getCode();
+    }
 
     protected function _getDeliveryType($sDeliveryType)
     {

+ 82 - 20
modules/boonex/notifications/classes/BxNtfsTemplate.php

@@ -335,36 +335,56 @@ class BxNtfsTemplate extends BxBaseModNotificationsTemplate
         if(empty($sEvent) || empty($aEvent['content_parsed']))
             return false;
 
-        $sContent = is_array($aEvent['content_parsed']) && isset($aEvent['content_parsed']['email']) ? $aEvent['content_parsed']['email'] : $aEvent['content_parsed'];
-
-        $sSubject = $sContent;
-        if(($iEmailSubjectMaxLen = $this->_oConfig->getEmailSubjectMaxLen()) !== 0)
-            $sSubject = strmaxtextlen($sSubject, $iEmailSubjectMaxLen);
-        else 
-            $sSubject = trim(strip_tags($sSubject));
-
         $aContent = &$aEvent['content'];
 
-        $sSummary = '';
-        if(!empty($aContent['subentry_summary']))
-            $sSummary = $aContent['subentry_summary'];
-        if(empty($sSummary) && !empty($aContent['entry_summary']))
-            $sSummary = $aContent['entry_summary'];
+        $sIconUrl = !empty($aContent['owner_icon']) ? $aContent['owner_icon'] : $this->getIconUrl('std-icon.svg');
+        $sContentUrl = bx_absolute_url($this->_getContentLink($aEvent, getParam('sys_api_url_root_email') != ''));
+        $sContent = is_array($aEvent['content_parsed']) && isset($aEvent['content_parsed']['email']) ? $aEvent['content_parsed']['email'] : $aEvent['content_parsed'];
+        $sSummary = (($sK = 'subentry_summary') && ($sV = $aContent[$sK] ?? false)) || (($sK = 'entry_summary') && ($sV = $aContent[$sK] ?? false)) ? $sV : '';
+        $sDate = bx_process_output($aEvent['date'], BX_DATA_DATE_TS);
+
+        $aEtemplate = $this->_oDb->getEtemplates([
+            'sample' => 'type_action', 
+            'type' => $aEvent['type'], 
+            'action' => $aEvent['action'], 
+            'active' => 1
+        ]);
 
-        return [
-            'subject' => $sSubject,
-            'content' => $this->parseHtmlByName('et_new_event.html', [
-                'icon_url' => !empty($aContent['owner_icon']) ? $aContent['owner_icon'] : $this->getIconUrl('std-icon.svg'),
-                'content_url' => bx_absolute_url($this->_getContentLink($aEvent, getParam('sys_api_url_root_email') != '')),
+        $sSubject = $sBody = '';
+        if(!empty($aEtemplate) && is_array($aEtemplate)) {
+            $sSubject = $aEtemplate['subject'];
+            $sBody = bx_replace_markers($aEtemplate['body'], [
+                'icon_url' => $sIconUrl,
+                'content_url' => $sContentUrl,
                 'content' => $sContent,
-                'date' => bx_process_output($aEvent['date'], BX_DATA_DATE_TS),
+                'summary' => $sSummary,
+                'date' => $sDate
+            ]);
+        }
+        else {
+            $sSubject = $sContent;
+            $sBody = $this->parseHtmlByName('et_new_event.html', [
+                'icon_url' => $sIconUrl,
+                'content_url' => $sContentUrl,
+                'content' => $sContent,
+                'date' => $sDate,
                 'bx_if:show_summary' => [
                     'condition' => !empty($sSummary),
                     'content' => [
                         'summary' => $sSummary
                     ]
                 ]
-            ]),
+            ]);
+        }
+
+        if(($iEmailSubjectMaxLen = $this->_oConfig->getEmailSubjectMaxLen()) !== 0)
+            $sSubject = strmaxtextlen($sSubject, $iEmailSubjectMaxLen);
+        else 
+            $sSubject = trim(strip_tags($sSubject));
+
+        return [
+            'subject' => $sSubject,
+            'content' => $sBody,
             'settings' => !empty($aContent['settings']['email']) ? $aContent['settings']['email'] : []
         ];
     }
@@ -403,6 +423,48 @@ class BxNtfsTemplate extends BxBaseModNotificationsTemplate
         ));
     }
 
+    public function getSelectActions($aActions)
+    {
+        $aTmplVarsActions = [
+            ['value' => '', 'title' => _t('_sys_please_select')]
+        ];
+
+        foreach($aActions as $sAction)
+            $aTmplVarsActions[] = ['value' => $sAction, 'title' => $this->getActionTitle($sAction)];
+
+        return $this->parseHtmlByName('field_actions.html', [
+            'bx_repeat:actions' => $aTmplVarsActions
+        ]);
+    }
+
+    public function getTypeTitle($sType)
+    {
+        $sResult = '';
+        if(($sKey = '_bx_ntfs_alert_module_' . $sType) && ($_sKey = _t($sKey)) && strcmp($sKey, $_sKey) != 0)
+            $sResult = $_sKey;
+        else if(($sKey = '_' . $sType) && ($_sKey = _t($sKey)) && strcmp($sKey, $_sKey) != 0)
+            $sResult = $_sKey;
+        else if(($aModule = $this->_oDb->getModuleByName($sType)) && is_array($aModule) && ($_sKey = $aModule['title'] ?? false))
+            $sResult = $_sKey;
+        else
+            $sResult = $sType;
+
+        return $sResult;
+    }
+
+    public function getActionTitle($sAction)
+    {
+        $sResult = '';
+        if(($sKey = '_bx_ntfs_alert_action_' . $sAction) && ($_sKey = _t($sKey)) && strcmp($sKey, $_sKey) != 0)
+            $sResult = $_sKey;
+        else if(($sKey .= '_personal') && ($_sKey = _t($sKey)) && strcmp($sKey, $_sKey) != 0)
+            $sResult = $_sKey;
+        else
+            $sResult = $sAction;
+
+        return $sResult;
+    }
+
     protected function _processContent(&$aEvent)
     {
     	$aContent = $this->_getContent($aEvent);

+ 31 - 0
modules/boonex/notifications/install/langs/en.xml

@@ -3,6 +3,25 @@
     <string name="_bx_ntfs"><![CDATA[Notifications]]></string>
     <string name="_bx_notifications"><![CDATA[Notifications]]></string>
 
+    <string name="_bx_ntfs_form_etemplate"><![CDATA[Email Template]]></string>
+    <string name="_bx_ntfs_form_etemplate_display_add"><![CDATA[Add Email Template]]></string>
+    <string name="_bx_ntfs_form_etemplate_display_edit"><![CDATA[Edit Email Template]]></string>
+    <string name="_bx_ntfs_form_etemplate_input_controls"><![CDATA[Controls]]></string>
+    <string name="_bx_ntfs_form_etemplate_input_sys_do_submit"><![CDATA[Submit]]></string>
+    <string name="_bx_ntfs_form_etemplate_input_do_submit"><![CDATA[Submit]]></string>
+    <string name="_bx_ntfs_form_etemplate_input_sys_do_cancel"><![CDATA[Cancel]]></string>
+    <string name="_bx_ntfs_form_etemplate_input_do_cancel"><![CDATA[Cancel]]></string>
+    <string name="_bx_ntfs_form_etemplate_input_sys_type"><![CDATA[Type]]></string>
+    <string name="_bx_ntfs_form_etemplate_input_type"><![CDATA[Type]]></string>
+    <string name="_bx_ntfs_form_etemplate_input_sys_action"><![CDATA[Action]]></string>
+    <string name="_bx_ntfs_form_etemplate_input_action"><![CDATA[Action]]></string>
+    <string name="_bx_ntfs_form_etemplate_input_sys_subject"><![CDATA[Subject]]></string>
+    <string name="_bx_ntfs_form_etemplate_input_subject"><![CDATA[Subject]]></string>
+    <string name="_bx_ntfs_form_etemplate_input_sys_body"><![CDATA[Body]]></string>
+    <string name="_bx_ntfs_form_etemplate_input_body"><![CDATA[Body]]></string>
+    <string name="_bx_ntfs_form_etemplate_input_err_select"><![CDATA[This field is essential. Please select a value.]]></string>
+    <string name="_bx_ntfs_form_etemplate_input_err_enter"><![CDATA[This field is essential. Please fill it in.]]></string>
+
     <string name="_bx_ntfs_page_title_system_view"><![CDATA[Notifications]]></string>
     <string name="_bx_ntfs_page_title_view"><![CDATA[Notifications]]></string>
     <string name="_bx_ntfs_page_block_title_view"><![CDATA[Notifications]]></string>
@@ -36,6 +55,7 @@
     <string name="_bx_ntfs_lmi_cpt_site"><![CDATA[On Site]]></string>
     <string name="_bx_ntfs_lmi_cpt_email"><![CDATA[Email]]></string>
     <string name="_bx_ntfs_lmi_cpt_push"><![CDATA[Push]]></string>
+    <string name="_bx_ntfs_lmi_cpt_etemplates_text"><![CDATA[Email Texts]]></string>
 
     <string name="_bx_ntfs_options_category_system"><![CDATA[System]]></string>
     <string name="_bx_ntfs_option_events_per_page"><![CDATA[Number of items per page]]></string>
@@ -181,4 +201,15 @@
     <string name="_bx_ntfs_grid_column_title_value"><![CDATA[Default value]]></string>
     <string name="_bx_ntfs_grid_action_title_activate"><![CDATA[Activate]]></string>
     <string name="_bx_ntfs_grid_action_title_deactivate"><![CDATA[Deactivate]]></string>
+
+    <string name="_bx_ntfs_grid_column_title_ett_active"><![CDATA[Active]]></string>
+    <string name="_bx_ntfs_grid_column_title_ett_type"><![CDATA[Type]]></string>
+    <string name="_bx_ntfs_grid_column_title_ett_action"><![CDATA[Action]]></string>
+    <string name="_bx_ntfs_grid_column_title_ett_subject"><![CDATA[Subject]]></string>
+    <string name="_bx_ntfs_grid_action_title_ett_add"><![CDATA[Add]]></string>
+    <string name="_bx_ntfs_grid_action_title_ett_edit"><![CDATA[Edit]]></string>
+    <string name="_bx_ntfs_grid_action_title_ett_delete"><![CDATA[Delete]]></string>
+    <string name="_bx_ntfs_grid_popup_title_ett_add"><![CDATA[Add Email Template]]></string>
+    <string name="_bx_ntfs_grid_popup_title_ett_edit"><![CDATA[Edit Email Template]]></string>
+    
 </resources>

+ 15 - 0
modules/boonex/notifications/install/sql/enable.sql

@@ -179,6 +179,21 @@ INSERT INTO `sys_grid_actions` (`object`, `type`, `name`, `title`, `icon`, `conf
 ('bx_notifications_settings_common', 'bulk', 'activate', '_bx_ntfs_grid_action_title_activate', '', 1, 1),
 ('bx_notifications_settings_common', 'bulk', 'deactivate', '_bx_ntfs_grid_action_title_deactivate', '', 1, 2);
 
+INSERT INTO `sys_objects_grid` (`object`, `source_type`, `source`, `table`, `field_id`, `field_order`, `field_active`, `paginate_url`, `paginate_per_page`, `paginate_simple`, `paginate_get_start`, `paginate_get_per_page`, `filter_fields`, `filter_fields_translatable`, `filter_mode`, `sorting_fields`, `visible_for_levels`, `override_class_name`, `override_class_file`) VALUES
+('bx_notifications_etemplates', 'Sql', 'SELECT * FROM `bx_notifications_etemplates` WHERE 1 ', 'bx_notifications_etemplates', 'id', '', 'active', '', 100, NULL, 'start', '', '', 'type,action,subject,content', 'auto', '', 2147483647, 'BxNtfsGridEtemplates', 'modules/boonex/notifications/classes/BxNtfsGridEtemplates.php');
+
+INSERT INTO `sys_grid_fields` (`object`, `name`, `title`, `width`, `translatable`, `chars_limit`, `params`, `order`) VALUES
+('bx_notifications_etemplates', 'switcher', '_bx_ntfs_grid_column_title_ett_active', '10%', 0, '', '', 10),
+('bx_notifications_etemplates', 'type', '_bx_ntfs_grid_column_title_ett_type', '15%', 0, '', '', 20),
+('bx_notifications_etemplates', 'action', '_bx_ntfs_grid_column_title_ett_action', '15%', 0, '', '', 30),
+('bx_notifications_etemplates', 'subject', '_bx_ntfs_grid_column_title_ett_subject', '40%', 0, '', '', 40),
+('bx_notifications_etemplates', 'actions', '', '20%', 0, '', '', 50);
+
+INSERT INTO `sys_grid_actions` (`object`, `type`, `name`, `title`, `icon`, `icon_only`, `confirm`, `order`) VALUES
+('bx_notifications_etemplates', 'independent', 'add', '_bx_ntfs_grid_action_title_ett_add', '', 0, 0, 1),
+('bx_notifications_etemplates', 'single', 'edit', '_bx_ntfs_grid_action_title_ett_edit', 'pencil-alt', 1, 0, 1),
+('bx_notifications_etemplates', 'single', 'delete', '_bx_ntfs_grid_action_title_ett_delete', 'remove', 1, 1, 2);
+
 
 -- CRON
 INSERT INTO `sys_cron_jobs` (`name`, `time`, `class`, `file`, `service_call`) VALUES

+ 44 - 0
modules/boonex/notifications/install/sql/install.sql

@@ -221,6 +221,50 @@ CREATE TABLE IF NOT EXISTS `bx_notifications_queue` (
   PRIMARY KEY  (`id`)
 );
 
+CREATE TABLE IF NOT EXISTS `bx_notifications_etemplates` (
+  `id` int(11) NOT NULL auto_increment,
+  `type` varchar(255) NOT NULL,
+  `action` varchar(255) NOT NULL,
+  `subject` varchar(255) NOT NULL default '',
+  `body` text NOT NULL,
+  `active` tinyint(4) NOT NULL default '0',
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `etemplate` (`type`, `action`)
+);
+
+
+-- FORMS: etemplate
+INSERT INTO `sys_objects_form` (`object`, `module`, `title`, `action`, `form_attrs`, `submit_name`, `table`, `key`, `uri`, `uri_title`, `params`, `deletable`, `active`, `override_class_name`, `override_class_file`) VALUES
+('bx_notifications_etemplate', @sName, '_bx_ntfs_form_etemplate', '', '', 'do_submit', 'bx_notifications_etemplates', 'id', '', '', '', 0, 1, '', '');
+
+INSERT INTO `sys_form_displays` (`display_name`, `module`, `object`, `title`, `view_mode`) VALUES
+('bx_notifications_etemplate_add', @sName, 'bx_notifications_etemplate', '_bx_ntfs_form_etemplate_display_add', 0),
+('bx_notifications_etemplate_edit', @sName, 'bx_notifications_etemplate', '_bx_ntfs_form_etemplate_display_edit', 0);
+
+INSERT INTO `sys_form_inputs` (`object`, `module`, `name`, `value`, `values`, `checked`, `type`, `caption_system`, `caption`, `info`, `required`, `collapsed`, `html`, `attrs`, `attrs_tr`, `attrs_wrapper`, `checker_func`, `checker_params`, `checker_error`, `db_pass`, `db_params`, `editable`, `deletable`) VALUES
+('bx_notifications_etemplate', @sName, 'type', '', '', 0, 'select', '_bx_ntfs_form_etemplate_input_sys_type', '_bx_ntfs_form_etemplate_input_type', '', 1, 0, 0, '', '', '', 'Avail', '', '_bx_ntfs_form_etemplate_input_err_select', 'Xss', '', 0, 0),
+('bx_notifications_etemplate', @sName, 'action', '', '', 0, 'select', '_bx_ntfs_form_etemplate_input_sys_action', '_bx_ntfs_form_etemplate_input_action', '', 1, 0, 0, '', '', '', 'Avail', '', '_bx_ntfs_form_etemplate_input_err_select', 'Xss', '', 0, 0),
+('bx_notifications_etemplate', @sName, 'subject', '', '', 0, 'text', '_bx_ntfs_form_etemplate_input_sys_subject', '_bx_ntfs_form_etemplate_input_subject', '', 1, 0, 0, '', '', '', 'Avail', '', '_bx_ntfs_form_etemplate_input_err_enter', 'Xss', '', 0, 0),
+('bx_notifications_etemplate', @sName, 'body', '', '', 0, 'textarea', '_bx_ntfs_form_etemplate_input_sys_body', '_bx_ntfs_form_etemplate_input_body', '', 1, 0, 0, '', '', '', 'Avail', '', '_bx_ntfs_form_etemplate_input_err_enter', 'XssHtml', '', 0, 0),
+('bx_notifications_etemplate', @sName, 'controls', '', 'do_submit,do_cancel', 0, 'input_set', '_bx_ntfs_form_etemplate_input_controls', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 0, 0),
+('bx_notifications_etemplate', @sName, 'do_submit', '_bx_ntfs_form_etemplate_input_do_submit', '', 0, 'submit', '_bx_ntfs_form_etemplate_input_sys_do_submit', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 0, 0),
+('bx_notifications_etemplate', @sName, 'do_cancel', '_bx_ntfs_form_etemplate_input_do_cancel', '', 0, 'button', '_bx_ntfs_form_etemplate_input_do_cancel', '', '', 0, 0, 0, 'a:2:{s:7:"onclick";s:45:"$(''.bx-popup-applied:visible'').dolPopupHide()";s:5:"class";s:22:"bx-def-margin-sec-left";}', '', '', '', '', '', '', '', 0, 0);
+
+INSERT INTO `sys_form_display_inputs` (`display_name`, `input_name`, `visible_for_levels`, `active`, `order`) VALUES
+('bx_notifications_etemplate_add', 'type', 2147483647, 1, 1),
+('bx_notifications_etemplate_add', 'action', 2147483647, 1, 2),
+('bx_notifications_etemplate_add', 'subject', 2147483647, 1, 3),
+('bx_notifications_etemplate_add', 'body', 2147483647, 1, 4),
+('bx_notifications_etemplate_add', 'controls', 2147483647, 1, 5),
+('bx_notifications_etemplate_add', 'do_submit', 2147483647, 1, 6),
+('bx_notifications_etemplate_add', 'do_cancel', 2147483647, 1, 7),
+
+('bx_notifications_etemplate_edit', 'subject', 2147483647, 1, 1),
+('bx_notifications_etemplate_edit', 'body', 2147483647, 1, 2),
+('bx_notifications_etemplate_edit', 'controls', 2147483647, 1, 3),
+('bx_notifications_etemplate_edit', 'do_submit', 2147483647, 1, 4),
+('bx_notifications_etemplate_edit', 'do_cancel', 2147483647, 1, 5);
+
 
 -- STUDIO PAGE & WIDGET
 INSERT INTO `sys_std_pages`(`index`, `name`, `header`, `caption`, `icon`) VALUES

+ 7 - 0
modules/boonex/notifications/install/sql/uninstall.sql

@@ -6,6 +6,13 @@ DROP TABLE IF EXISTS `bx_notifications_handlers`, `bx_notifications_settings`, `
 DROP TABLE IF EXISTS `bx_notifications_queue`;
 
 
+-- FORMS
+DELETE FROM `sys_objects_form` WHERE `module` = @sName;
+DELETE FROM `sys_form_displays` WHERE `module` = @sName;
+DELETE FROM `sys_form_inputs` WHERE `module` = @sName;
+DELETE FROM `sys_form_display_inputs` WHERE `display_name` LIKE 'bx_notifications_%';
+
+
 -- STUDIO PAGE & WIDGET
 DELETE FROM `tp`, `tw`, `twb`, `tpw` 
 USING `sys_std_pages` AS `tp` LEFT JOIN `sys_std_widgets` AS `tw` ON `tp`.`id` = `tw`.`page_id` LEFT JOIN `sys_std_widgets_bookmarks` AS `twb` ON `tw`.`id` = `twb`.`widget_id` LEFT JOIN `sys_std_pages_widgets` AS `tpw` ON `tw`.`id` = `tpw`.`widget_id`

+ 38 - 12
modules/boonex/notifications/js/main.js

@@ -1,28 +1,54 @@
-function BxNtfsMain() {}
+function BxNtfsMain(oOptions) {
+    this._sActionsUri = oOptions.sActionUri;
+    this._sActionsUrl = oOptions.sActionUrl;
+    this._sAnimationEffect = oOptions.sAnimationEffect == undefined ? 'slide' : oOptions.sAnimationEffect;
+    this._iAnimationSpeed = oOptions.iAnimationSpeed == undefined ? 'slow' : oOptions.iAnimationSpeed;
+    this._aHtmlIds = oOptions.aHtmlIds == undefined ? {} : oOptions.aHtmlIds;
+    this._oRequestParams = oOptions.oRequestParams == undefined ? {} : oOptions.oRequestParams;
+}
+
+BxNtfsMain.prototype.onChangeType = function(oElement) {
+    var $this = this;
+    var oData = this._getDefaultData();
+
+    jQuery.get(
+        this._sActionsUrl + 'get_action/' + $(oElement).val(),
+        oData,
+        function(oData) {
+            if(!oData || oData.code != 0)
+                return;
+console.log($this._aHtmlIds);
+            $('#' + $this._aHtmlIds['field_action']).html(oData.content).removeAttr('disabled');
+        },
+        'json'
+    );
+
+    return false;
+};
 
 BxNtfsMain.prototype.loadingInButton = function(e, bShow) {
-	if($(e).length)
-		bx_loading_btn($(e), bShow);
-	else
-		bx_loading($('body'), bShow);	
+    if($(e).length)
+        bx_loading_btn($(e), bShow);
+    else
+        bx_loading($('body'), bShow);	
 };
 
 BxNtfsMain.prototype.loadingInItem = function(e, bShow) {
-	var oParent = $(e).length ? $(e).parents('.bx-ntfs-item:first') : $('body'); 
-	bx_loading(oParent, bShow);
+    var oParent = $(e).length ? $(e).parents('.bx-ntfs-item:first') : $('body'); 
+    bx_loading(oParent, bShow);
 };
 
 BxNtfsMain.prototype.loadingInBlock = function(e, bShow) {
-	var oParent = $(e).length ? $(e).parents('.bx-db-container:first') : $('body'); 
-	bx_loading(oParent, bShow);
+    var oParent = $(e).length ? $(e).parents('.bx-db-container:first') : $('body'); 
+    bx_loading(oParent, bShow);
 };
 
 BxNtfsMain.prototype._loading = function(e, bShow) {
-	var oParent = $(e).length ? $(e) : $('body'); 
-	bx_loading(oParent, bShow);
+    var oParent = $(e).length ? $(e) : $('body'); 
+    bx_loading(oParent, bShow);
 };
 
 BxNtfsMain.prototype._getDefaultData = function () {
-	var oDate = new Date();
+    var oDate = new Date();
     return jQuery.extend({}, this._oRequestParams, {_t:oDate.getTime()});
 };

+ 19 - 0
modules/boonex/notifications/template/etemplate_form.html

@@ -0,0 +1,19 @@
+<div class="__style_prefix__-etemplate-form">
+    <div class="__style_prefix__-etemplate-form-cnt">
+        __form__
+        <script language="javascript">
+            $(document).ready(function () {
+                $("#__form_id__").ajaxForm({ 
+                    dataType: "json",
+                    beforeSubmit: function (formData, jqForm, options) {
+                        bx_loading($("#__form_id__"), true);
+                    },
+                    success: function (data) {
+                        $(".bx-popup-applied:visible").dolPopupHide();
+                        glGrids.__object__.processJson(data, '__action__');
+                    }
+                });
+            });
+        </script>
+    </div>
+</div>

+ 1 - 0
modules/boonex/notifications/template/field_actions.html

@@ -0,0 +1 @@
+<bx_repeat:actions><option value="__value__">__title__</option></bx_repeat:actions>

+ 30 - 0
modules/boonex/russian/data/langs/bx_notifications/ru.xml

@@ -3,6 +3,25 @@
     <string name="_bx_ntfs"><![CDATA[Уведомления]]></string>
     <string name="_bx_notifications"><![CDATA[Уведомления]]></string>
 
+    <string name="_bx_ntfs_form_etemplate"><![CDATA[Шаблон электронного письма]]></string>
+    <string name="_bx_ntfs_form_etemplate_display_add"><![CDATA[Добавить шаблон электронного письма]]></string>
+    <string name="_bx_ntfs_form_etemplate_display_edit"><![CDATA[Редактировать шаблон электронного письма]]></string>
+    <string name="_bx_ntfs_form_etemplate_input_controls"><![CDATA[Элементы управления]]></string>
+    <string name="_bx_ntfs_form_etemplate_input_sys_do_submit"><![CDATA[Выполнить]]></string>
+    <string name="_bx_ntfs_form_etemplate_input_do_submit"><![CDATA[Выполнить]]></string>
+    <string name="_bx_ntfs_form_etemplate_input_sys_do_cancel"><![CDATA[Отменить]]></string>
+    <string name="_bx_ntfs_form_etemplate_input_do_cancel"><![CDATA[Отменить]]></string>
+    <string name="_bx_ntfs_form_etemplate_input_sys_type"><![CDATA[Тип]]></string>
+    <string name="_bx_ntfs_form_etemplate_input_type"><![CDATA[Тип]]></string>
+    <string name="_bx_ntfs_form_etemplate_input_sys_action"><![CDATA[Действие]]></string>
+    <string name="_bx_ntfs_form_etemplate_input_action"><![CDATA[Действие]]></string>
+    <string name="_bx_ntfs_form_etemplate_input_sys_subject"><![CDATA[Тема]]></string>
+    <string name="_bx_ntfs_form_etemplate_input_subject"><![CDATA[Тема]]></string>
+    <string name="_bx_ntfs_form_etemplate_input_sys_body"><![CDATA[Текст]]></string>
+    <string name="_bx_ntfs_form_etemplate_input_body"><![CDATA[Текст]]></string>
+    <string name="_bx_ntfs_form_etemplate_input_err_select"><![CDATA[Это поле обязательно для заполнения. Пожалуйста, выберите значение.]]></string>
+    <string name="_bx_ntfs_form_etemplate_input_err_enter"><![CDATA[Это поле обязательно для заполнения. Пожалуйста, заполните его.]]></string>
+
     <string name="_bx_ntfs_page_title_system_view"><![CDATA[Уведомления]]></string>
     <string name="_bx_ntfs_page_title_view"><![CDATA[Уведомления]]></string>
     <string name="_bx_ntfs_page_block_title_view"><![CDATA[Уведомления]]></string>
@@ -36,6 +55,7 @@
     <string name="_bx_ntfs_lmi_cpt_site"><![CDATA[На сайте]]></string>
     <string name="_bx_ntfs_lmi_cpt_email"><![CDATA[Email]]></string>
     <string name="_bx_ntfs_lmi_cpt_push"><![CDATA[Push]]></string>
+    <string name="_bx_ntfs_lmi_cpt_etemplates_text"><![CDATA[Тексты email-ов]]></string>
 
     <string name="_bx_ntfs_options_category_system"><![CDATA[Системные]]></string>
     <string name="_bx_ntfs_option_events_per_page"><![CDATA[Количество элементов на странице]]></string>
@@ -181,4 +201,14 @@
     <string name="_bx_ntfs_grid_column_title_value"><![CDATA[Значение по умолчанию]]></string>
     <string name="_bx_ntfs_grid_action_title_activate"><![CDATA[Включить]]></string>
     <string name="_bx_ntfs_grid_action_title_deactivate"><![CDATA[Отключить]]></string>
+
+    <string name="_bx_ntfs_grid_column_title_ett_active"><![CDATA[Включено]]></string>
+    <string name="_bx_ntfs_grid_column_title_ett_type"><![CDATA[Тип]]></string>
+    <string name="_bx_ntfs_grid_column_title_ett_action"><![CDATA[Действие]]></string>
+    <string name="_bx_ntfs_grid_column_title_ett_subject"><![CDATA[Тема]]></string>
+    <string name="_bx_ntfs_grid_action_title_ett_add"><![CDATA[Добавить]]></string>
+    <string name="_bx_ntfs_grid_action_title_ett_edit"><![CDATA[Редактировать]]></string>
+    <string name="_bx_ntfs_grid_action_title_ett_delete"><![CDATA[Удалить]]></string>
+    <string name="_bx_ntfs_grid_popup_title_ett_add"><![CDATA[Добавить шаблон электронного письма]]></string>
+    <string name="_bx_ntfs_grid_popup_title_ett_edit"><![CDATA[Редактировать шаблон электронного письма]]></string>
 </resources>