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

Ticket #5186 - Tasks: Functionality improvements. Point 5.

AntonLV 11 месяцев назад
Родитель
Сommit
2f0d8fefb4

+ 31 - 0
modules/base/general/classes/BxBaseModGeneralGrid.php

@@ -38,6 +38,37 @@ class BxBaseModGeneralGrid extends BxTemplGrid
 
         return parent::_getFilterSelectOne($sFilterName, $sFilterValue, $aFilterValues, $mixedAddSelectOne, $bAsArray);
     }
+
+    protected function _initFilter($iNumber, $aValues = [])
+    {
+        $sFfName = '_sFilter' . $iNumber . 'Name';
+        $sFfValue = '_sFilter' . $iNumber . 'Value';
+        if(!property_exists($this, $sFfName) || !property_exists($this, $sFfValue))
+            return;
+
+        $this->$sFfName = 'filter' . $iNumber;
+        if(($sFfValues = '_aFilter' . $iNumber . 'Values') && property_exists($this, $sFfValues))
+            $this->$sFfValues = $aValues ?: [];
+
+        if(($sValue = bx_get($this->$sFfName)) !== false) {
+            $this->$sFfValue = bx_process_input($sValue);
+            $this->_aQueryAppend[$this->$sFfName] = $this->$sFfValue;
+        }
+    }
+
+    protected function _parseFilterValue(&$sFilter)
+    {
+        $iFilterParts = substr_count($sFilter, $this->_sParamsDivider);
+        if(!$iFilterParts)
+            return;
+
+        $aFilterParts = explode($this->_sParamsDivider, $sFilter);
+        for($i = 1; $i <= $iFilterParts; $i++)
+            if(($sField = '_sFilter' . $i . 'Value') && property_exists($this, $sField))
+                $this->$sField = $aFilterParts[$i - 1];
+
+        $sFilter = $aFilterParts[$iFilterParts];
+    }
 }
 
 /** @} */

+ 1 - 10
modules/base/text/classes/BxBaseModTextGridAdministration.php

@@ -88,16 +88,7 @@ class BxBaseModTextGridAdministration extends BxBaseModGeneralGridAdministration
     {
         $CNF = &$this->_oModule->_oConfig->CNF;
 
-        $aFilterParts = explode($this->_sParamsDivider, $sFilter);
-        switch (substr_count($sFilter, $this->_sParamsDivider)) {
-            case 1:
-                list($this->_sFilter1Value, $sFilter) = $aFilterParts;
-                break;
-
-            case 2:
-                list($this->_sFilter1Value, $this->_sFilter2Value, $sFilter) = $aFilterParts;
-                break;
-        }
+        $this->_parseFilterValue($sFilter);
 
     	if(!empty($this->_sFilter1Value))
             $this->_aOptions['source'] .= $this->_oModule->_oDb->prepareAsString(" AND `" . $this->_sStatusField . "`=?", $this->_sFilter1Value);

+ 38 - 3
modules/boonex/russian/data/langs/bx_tasks/ru.xml

@@ -220,7 +220,13 @@
     <string name="_bx_tasks_page_title_manage"><![CDATA[Управление]]></string>
     <string name="_bx_tasks_page_block_title_system_manage"><![CDATA[Управление собственными заданиями]]></string>
     <string name="_bx_tasks_page_block_title_system_manage_administration"><![CDATA[Управление всеми заданиями]]></string>
-    <string name="_bx_tasks_page_block_title_manage"><![CDATA[Управление]]></string>    
+    <string name="_bx_tasks_page_block_title_manage"><![CDATA[Управление]]></string>
+    <string name="_bx_tasks_page_title_sys_time_manage"><![CDATA[Управление собственным временем]]></string>
+    <string name="_bx_tasks_page_title_sys_time_manage_administration"><![CDATA[Управление всем временем]]></string>
+    <string name="_bx_tasks_page_title_time_manage"><![CDATA[Управление временем]]></string>
+    <string name="_bx_tasks_page_block_title_system_time_manage"><![CDATA[Управление собственным временем]]></string>
+    <string name="_bx_tasks_page_block_title_system_time_manage_administration"><![CDATA[Управление всем временем]]></string>
+    <string name="_bx_tasks_page_block_title_time_manage"><![CDATA[Управление временем]]></string>
     <string name="_bx_tasks_page_block_title_popular_keywords"><![CDATA[Популярные хэштеги]]></string>
     <string name="_bx_tasks_page_block_title_cats"><![CDATA[Задания Категории]]></string>
     <string name="_bx_tasks_page_block_title_sys_multicats"><![CDATA[Задания Категории(Мульти)]]></string>
@@ -303,8 +309,8 @@
     <string name="_bx_tasks_menu_set_title_entries_my"><![CDATA[Мои Задания Меню]]></string>
     <string name="_bx_tasks_menu_item_title_system_manage_my_tasks"><![CDATA[Мои Задания]]></string>
     <string name="_bx_tasks_menu_item_title_manage_my_tasks"><![CDATA[Задания]]></string>
-    <string name="_bx_tasks_menu_set_title_manage_tools"><![CDATA[Инструменты управления - Подменю]]></string>
-    <string name="_bx_tasks_menu_title_manage_tools"><![CDATA[Инструменты управления - Подменю]]></string>
+    <string name="_bx_tasks_menu_set_title_manage_tools"><![CDATA[Инструменты управления - Подменю элемента]]></string>
+    <string name="_bx_tasks_menu_title_manage_tools"><![CDATA[Инструменты управления - Подменю элемента]]></string>
     <string name="_bx_tasks_menu_item_title_system_manage_account"><![CDATA[Управление аккаунтом]]></string>
     <string name="_bx_tasks_menu_item_title_manage_account"><![CDATA[Управление аккаунтом]]></string>
     <string name="_bx_tasks_menu_item_title_system_admt_tasks"><![CDATA[Задания]]></string>
@@ -324,9 +330,36 @@
     <string name="_bx_tasks_menu_item_title_view_context_time"><![CDATA[Моё время]]></string>
     <string name="_bx_tasks_menu_item_title_system_view_context_time_administration"><![CDATA[Всё время]]></string>
     <string name="_bx_tasks_menu_item_title_view_context_time_administration"><![CDATA[Всё время]]></string>
+    <string name="_bx_tasks_menu_title_manage_tools_submenu"><![CDATA[Инструменты управления - Подменю]]></string>
+    <string name="_bx_tasks_menu_set_title_manage_tools_submenu"><![CDATA[Инструменты управления - Подменю]]></string>
+    <string name="_bx_tasks_menu_item_title_mt_submenu_entries_common"><![CDATA[Мои задания]]></string>
+    <string name="_bx_tasks_menu_item_title_mt_submenu_entries_administration"><![CDATA[Все задания]]></string>
+    <string name="_bx_tasks_menu_item_title_mt_submenu_time_common"><![CDATA[Моё время]]></string>
+    <string name="_bx_tasks_menu_item_title_mt_submenu_time_administration"><![CDATA[Всё время]]></string>
 
     <!-- Grids -->
+    <string name="_bx_tasks_grid_filter_item_title_adm_select_one_filter1"><![CDATA[Все статусы]]></string>
+    <string name="_bx_tasks_grid_filter_item_title_adm_select_one_filter2"><![CDATA[Любая аудитория]]></string>
+    <string name="_bx_tasks_grid_filter_item_title_adm_select_one_filter3"><![CDATA[Все модули]]></string>
+    <string name="_bx_tasks_grid_filter_item_title_adm_active"><![CDATA[Активные]]></string>
+    <string name="_bx_tasks_grid_filter_item_title_adm_hidden"><![CDATA[Спрятанные]]></string>
+    <string name="_bx_tasks_grid_filter_item_title_adm_pending"><![CDATA[В ожидании]]></string>
+    <string name="_bx_tasks_grid_column_title_adm_active"><![CDATA[Активные]]></string>
+    <string name="_bx_tasks_grid_column_title_adm_title"><![CDATA[Заголовок]]></string>
+    <string name="_bx_tasks_grid_column_title_adm_added"><![CDATA[Добавленные]]></string>
+    <string name="_bx_tasks_grid_column_title_adm_author"><![CDATA[Автор]]></string>
+    <string name="_bx_tasks_grid_action_title_adm_edit"><![CDATA[Редактировать]]></string>
+    <string name="_bx_tasks_grid_action_title_adm_delete"><![CDATA[Удалить]]></string>
+    <string name="_bx_tasks_grid_action_title_adm_more_actions"><![CDATA[Дополнительные действия]]></string>
+    <string name="_bx_tasks_grid_action_title_adm_audit_content"><![CDATA[Аудит действий]]></string>
+    <string name="_bx_tasks_grid_action_title_adm_clear_reports"><![CDATA[Очистить жалобы]]></string>
+    <string name="_bx_tasks_grid_column_title_adm_status_admin"><![CDATA[Модерация]]></string>
+    <string name="_bx_tasks_grid_action_err_delete"><![CDATA[Невозможно удалить выбранную(ные) публикацию(ции).]]></string>
+    <string name="_bx_tasks_grid_txt_account_manager"><![CDATA[Перенаправить в Управление аккаунтом.]]></string>
+
     <string name="_bx_tasks_grid_column_title_tm_author_id"><![CDATA[Профиль]]></string>
+    <string name="_bx_tasks_grid_column_title_tm_context_id"><![CDATA[Контекст]]></string>
+    <string name="_bx_tasks_grid_column_title_tm_context_module"><![CDATA[Модуль]]></string>
     <string name="_bx_tasks_grid_column_title_tm_object_id"><![CDATA[Задание]]></string>
     <string name="_bx_tasks_grid_column_title_tm_text"><![CDATA[Примечание]]></string>
     <string name="_bx_tasks_grid_column_title_tm_value"><![CDATA[Время]]></string>
@@ -336,6 +369,7 @@
     <string name="_bx_tasks_grid_action_title_tm_delete"><![CDATA[Удалить]]></string>
     <string name="_bx_tasks_grid_action_title_tm_calculate"><![CDATA[Рассчитать]]></string>
     <string name="_bx_tasks_grid_filter_item_title_tm_select_one_author_id"><![CDATA[Любой исполнитель]]></string>
+    <string name="_bx_tasks_grid_filter_item_title_tm_select_one_context_module"><![CDATA[Любой модуль]]></string>
     <string name="_bx_tasks_grid_filter_item_title_tm_select_one_object_id"><![CDATA[Любая задача]]></string>
 
     <string name="_bx_tasks_chart_growth"><![CDATA[Tasks: Growth]]></string>
@@ -420,6 +454,7 @@
     <string name="_bx_tasks_txt_filter_uncompleted"><![CDATA[Незавершенные Задания]]></string>
     <string name="_bx_tasks_txt_total"><![CDATA[Потрачено времени: {0}]]></string>
     <string name="_bx_tasks_txt_estimate"><![CDATA[Выделено времени: {0}]]></string>
+    <string name="_bx_tasks_txt_set"><![CDATA[set...]]></string>
 
     <string name="_bx_tasks_txt_err_cannot_perform_action"><![CDATA[Невозможно выполнить действие. Пожалуйста, оповестите нас об этой проблеме.]]></string>
     <string name="_bx_tasks_txt_err_cannot_perform_action"><![CDATA[Невозможно выполнить действие. Пожалуйста, оповестите нас об этой проблеме.]]></string>

+ 22 - 5
modules/boonex/tasks/classes/BxTasksConfig.php

@@ -2,6 +2,7 @@
 /**
  * Copyright (c) UNA, Inc - https://una.io
  * MIT License - https://opensource.org/licenses/MIT 
+ * 
  * @defgroup    Tasks Tasks
  * @ingroup     UnaModules
  *
@@ -161,8 +162,14 @@ class BxTasksConfig extends BxBaseModTextConfig
             'OBJECT_MENU_SNIPPET_META' => 'bx_tasks_snippet_meta', // menu for snippet meta info
             'OBJECT_MENU_MANAGE_TOOLS' => 'bx_tasks_menu_manage_tools', //manage menu in content administration tools
             'OBJECT_MENU_SUBMENU_VIEW_CONTEXT' => 'bx_tasks_view_context_submenu',
+            'OBJECT_MENU_MANAGE_TOOLS_SUBMENU' => 'bx_tasks_manage_tools_submenu',
+            'OBJECT_MENU_MANAGE_TOOLS' => 'bx_tasks_menu_manage_tools', //manage item menu in content administration tools
+            'OBJECT_GRID_ADMINISTRATION' => 'bx_tasks_administration',
+            'OBJECT_GRID_COMMON' => 'bx_tasks_common',
             'OBJECT_GRID_TIME_ADMINISTRATION' => 'bx_tasks_time_administration',
-            'OBJECT_GRID_TIME' => 'bx_tasks_time',
+            'OBJECT_GRID_TIME_COMMON' => 'bx_tasks_time_common',
+            'OBJECT_GRID_TIME_CONTEXT_ADMINISTRATION' => 'bx_tasks_time_context_administration',
+            'OBJECT_GRID_TIME_CONTEXT_COMMON' => 'bx_tasks_time_context_common',
             'OBJECT_GRID_CATEGORIES' => 'bx_tasks_categories',
             'OBJECT_UPLOADERS' => array('bx_tasks_simple', 'bx_tasks_html5'),
             'OBJECT_CONTENT_INFO' => 'bx_tasks',
@@ -218,8 +225,14 @@ class BxTasksConfig extends BxBaseModTextConfig
                 'form_field_author' => '_bx_tasks_form_entry_input_author',
                 'form_field_covers_uploader_simple' => '_bx_tasks_form_entry_input_covers_uploader_simple_title',
                 'form_field_covers_uploader_html5' => '_bx_tasks_form_entry_input_covers_uploader_html5_title',
-            	'filter_item_select_one_filter1' => '_bx_tasks_grid_filter_item_title_tm_select_one_author_id',
-                'filter_item_select_one_filter2' => '_bx_tasks_grid_filter_item_title_tm_select_one_object_id',
+                'grid_action_err_delete' => '_bx_tasks_grid_action_err_delete',
+                'grid_txt_account_manager' => '_bx_tasks_grid_txt_account_manager',
+                'filter_item_active' => '_bx_tasks_grid_filter_item_title_adm_active',
+            	'filter_item_hidden' => '_bx_tasks_grid_filter_item_title_adm_hidden',
+                'filter_item_pending' => '_bx_tasks_grid_filter_item_title_adm_pending',
+            	'filter_item_select_one_filter1' => '_bx_tasks_grid_filter_item_title_adm_select_one_filter1',
+                'filter_item_select_one_filter2' => '_bx_tasks_grid_filter_item_title_adm_select_one_filter2',
+                'filter_item_select_one_filter3' => '_bx_tasks_grid_filter_item_title_adm_select_one_filter3',
             	'menu_item_manage_my' => '_bx_tasks_menu_item_title_manage_my',
             	'menu_item_manage_all' => '_bx_tasks_menu_item_title_manage_all',
                 'txt_all_entries_by' => '_bx_tasks_txt_all_entries_by',
@@ -245,8 +258,12 @@ class BxTasksConfig extends BxBaseModTextConfig
         ]);
 
         $this->_aGridObjects = [
-            'time' => $this->CNF['OBJECT_GRID_TIME'],
-            'time-administration' => $this->CNF['OBJECT_GRID_TIME_ADMINISTRATION'],
+            'common' => $this->CNF['OBJECT_GRID_COMMON'],
+            'administration' => $this->CNF['OBJECT_GRID_ADMINISTRATION'],
+            'time_common' => $this->CNF['OBJECT_GRID_TIME_COMMON'],
+            'time_administration' => $this->CNF['OBJECT_GRID_TIME_ADMINISTRATION'],
+            'time_context_common' => $this->CNF['OBJECT_GRID_TIME_CONTEXT_COMMON'],
+            'time_context_administration' => $this->CNF['OBJECT_GRID_TIME_CONTEXT_ADMINISTRATION'],
         ];
 
         $sPrefix = str_replace('_', '-', $this->_sName);

+ 6 - 0
modules/boonex/tasks/classes/BxTasksDb.php

@@ -173,6 +173,12 @@ class BxTasksDb extends BxBaseModTextDb
 
                     $sWhereClause = "AND `ttt`.`id` = :id";
                     break;
+
+                case 'assignees':
+                    $aMethod['name'] = 'getColumn';
+
+                    $sSelectClause = 'DISTINCT `ttt`.`author_id`';
+                    break;
             }
 
         if(!empty($sOrderClause))

+ 3 - 1
modules/boonex/tasks/classes/BxTasksFormEntry.php

@@ -37,7 +37,7 @@ class BxTasksFormEntry extends BxBaseModTextFormEntry
     {
         $sValue = parent::genViewRowValue($aInput);
         if($this->_oModule->isAllowManage($this->_iContentId) && !empty($aInput['name']) && in_array($aInput['name'], $this->_aProperties))
-            $sValue = $this->_oModule->_oTemplate->parseLink('javascript:void(0)', $sValue ?: _t('_undefined'), [
+            $sValue = $this->_oModule->_oTemplate->parseLink('javascript:void(0)', $sValue ?: _t('_bx_tasks_txt_set'), [
                 'onclick' => 'javascript:' . $this->_oModule->_oConfig->getJsObject('tasks') . '.processTaskEdit' . bx_gen_method_name($aInput['name']) . '(' . $this->_iContentId . ', this)'
             ]);
 
@@ -89,6 +89,8 @@ class BxTasksFormEntry extends BxBaseModTextFormEntry
     {
         $CNF = &$this->_oModule->_oConfig->CNF;
 
+        $aValsToAdd[$CNF['FIELD_STATE']] ??= 1;
+
         if(isset($CNF['FIELD_ADDED']) && empty($aValsToAdd[$CNF['FIELD_ADDED']])) {
             $iAdded = 0;
             if(isset($this->aInputs[$CNF['FIELD_ADDED']]))

+ 43 - 0
modules/boonex/tasks/classes/BxTasksGridAdministration.php

@@ -0,0 +1,43 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT 
+ * 
+ * @defgroup    Tasks Tasks
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+class BxTasksGridAdministration extends BxBaseModTextGridAdministration
+{
+    protected $_sFilter3Name;
+    protected $_sFilter3Value;
+    protected $_aFilter3Values;
+
+    public function __construct ($aOptions, $oTemplate = false)
+    {
+    	$this->MODULE = 'bx_tasks';
+        parent::__construct ($aOptions, $oTemplate);
+
+        $this->_initFilter(3, $this->_oModule->getContexts());
+    }
+
+    protected function _getFilterControls()
+    {
+        $sContent = $this->_getFilterSelectOne($this->_sFilter3Name, $this->_sFilter3Value, $this->_aFilter3Values);
+        return $sContent . parent::_getFilterControls();
+    }
+    
+    protected function _getDataSql($sFilter, $sOrderField, $sOrderDir, $iStart, $iPerPage)
+    {
+        $this->_parseFilterValue($sFilter);
+
+        if(!empty($this->_sFilter3Value))
+            $this->_aOptions['source'] .= $this->_oModule->_oDb->prepareAsString(" AND `tp`.`type`=?", $this->_sFilter3Value);
+
+        return parent::_getDataSql($sFilter, $sOrderField, $sOrderDir, $iStart, $iPerPage);
+    }
+}
+
+/** @} */

+ 43 - 0
modules/boonex/tasks/classes/BxTasksGridCommon.php

@@ -0,0 +1,43 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT 
+ * 
+ * @defgroup    Tasks Tasks
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+class BxTasksGridCommon extends BxBaseModTextGridCommon
+{
+    protected $_sFilter3Name;
+    protected $_sFilter3Value;
+    protected $_aFilter3Values;
+
+    public function __construct ($aOptions, $oTemplate = false)
+    {
+    	$this->MODULE = 'bx_tasks';
+        parent::__construct ($aOptions, $oTemplate);
+
+        $this->_initFilter(3, $this->_oModule->getContexts());
+    }
+
+    protected function _getFilterControls()
+    {
+        $sContent = $this->_getFilterSelectOne($this->_sFilter3Name, $this->_sFilter3Value, $this->_aFilter3Values);
+        return $sContent . parent::_getFilterControls();
+    }
+
+    protected function _getDataSql($sFilter, $sOrderField, $sOrderDir, $iStart, $iPerPage)
+    {
+        $this->_parseFilterValue($sFilter);
+
+        if(!empty($this->_sFilter3Value))
+            $this->_aOptions['source'] .= $this->_oModule->_oDb->prepareAsString(" AND `tp`.`type`=?", $this->_sFilter3Value);
+
+        return parent::_getDataSql($sFilter, $sOrderField, $sOrderDir, $iStart, $iPerPage);
+    }
+}
+
+/** @} */

+ 133 - 146
modules/boonex/tasks/classes/BxTasksGridTime.php

@@ -8,106 +8,56 @@
  * @{
  */
 
-require_once('BxTasksGridTimeAdministration.php');
-
-class BxTasksGridTime extends BxTasksGridTimeAdministration
+class BxTasksGridTime extends BxBaseModGeneralGrid
 {
-    protected $_iLogged;
+    protected $_sFilter1Name;   //--- Assignees
+    protected $_sFilter1Value;
+    protected $_aFilter1Values;
+    protected $_sFilter2Name;   //--- Contexts/Tasks
+    protected $_sFilter2Value;
+    protected $_aFilter2Values;
+    protected $_sFilter3Name;   //--- Date from
+    protected $_sFilter3Value;
+    protected $_sFilter4Name;   //--- Date to
+    protected $_sFilter4Value;
 
     public function __construct ($aOptions, $oTemplate = false)
     {
-        parent::__construct ($aOptions, $oTemplate);
-
-        $this->_iLogged = bx_get_logged_profile_id();
-    }
-
-    public function performActionAdd()
-    {
-        $sAction = 'add';
-
-        $oForm = $this->_getFormObject($sAction);
-        $oForm->initChecker();
-        if($oForm->isSubmittedAndValid()) {
-            $iNow = time();
-            $aValsToAdd = [
-                'author_id' => $this->_iLogged,
-                'author_nip' => bx_get_ip_hash(getVisitorIP()),
-                'value' => $this->_oModule->_oConfig->timeA2I([(int)$oForm->getCleanValue('value_h'), (int)$oForm->getCleanValue('value_m')]),
-                'value_date' => $oForm->getCleanValue('value_date') ?: $iNow,
-                'date' => $iNow
-            ];
-
-            $iTrackId = $oForm->insert($aValsToAdd);
-            if(!$iTrackId)
-                return $this->_getActionResult(['msg' => _t('_bx_tasks_txt_err_cannot_perform_action')]);
-
-            $sSystem = $oForm->getCleanValue('sys');
-            $iObjectId = $oForm->getCleanValue('object_id');
-            if(($oTime = BxDolReport::getObjectInstance($sSystem, $iObjectId)) && $oTime->isEnabled())
-                $oTime->putReport($iObjectId, $this->_iLogged, $iTrackId);
+        $this->_sModule = 'bx_tasks';
 
-            return $this->_bIsApi ? [] : echoJson(['grid' => $this->getCode(false), 'blink' => $iTrackId]);    
-        }
-
-        if($this->_bIsApi)
-            return $this->getFormBlockAPI($oForm, $sAction);
+        parent::__construct ($aOptions, $oTemplate);
 
-        $sContent = BxTemplFunctions::getInstance()->popupBox($this->_oModule->_oConfig->getHtmlIds('time_popup'), _t('_bx_tasks_popup_title_time_add'), $this->_oModule->_oTemplate->parseHtmlByName('popup_time.html', [
-            'form_id' => $oForm->getId(),
-            'form' => $oForm->getCode(true),
-            'object' => $this->_sObject,
-            'action' => $sAction
-        ]));
+        $this->_sDefaultSortingOrder = 'DESC';
 
-        return echoJson(['popup' => ['html' => $sContent, 'options' => ['closeOnOuterClick' => false]]]);
+        /*
+         * Filters by date from/to
+         */
+        $this->_sFilter3Name = 'filter3';
+        $this->_sFilter4Name = 'filter4';
     }
 
-    public function performActionEdit()
+    public function performActionCalculate()
     {
-    	$CNF = &$this->_oModule->_oConfig->CNF;
-
-        $sAction = 'edit';
+        $sAction = 'calculate';
 
         $aIds = $this->_getIds();
         if($aIds === false)
             return $this->_getActionResult([]);
 
-        $iTrack = array_shift($aIds);
-        $aTrack = $this->_oModule->_oDb->getTimeTracks(['sample' => 'id', 'id' => $iTrack]);
-        if(empty($aTrack) || !is_array($aTrack))
-            return $this->_getActionResult([]);
-
-        $oForm = $this->_getFormObject($sAction, $aTrack);
-        $oForm->initChecker($aTrack);
-        if($oForm->isSubmittedAndValid()) {
-            $aValsToAdd = [
-                'value' => $this->_oModule->_oConfig->timeA2I([(int)$oForm->getCleanValue('value_h'), (int)$oForm->getCleanValue('value_m')]),
-            ];
-
-            if(!$oForm->update($iTrack, $aValsToAdd))
-                return $this->_getActionResult(['msg' => _t('_bx_tasks_txt_err_cannot_perform_action')]);
+        $iTotal = 0;
+        foreach($aIds as $iId) {
+            $aTrack = $this->_oModule->_oDb->getTimeTracks(['sample' => 'id', 'id' => $iId]);
+            if(empty($aTrack) || !is_array($aTrack))
+                continue;
 
-            $iObjectId = (int)$aTrack['object_id'];
-            $iAuthorId = (int)$aTrack['author_id'];
-            if(($oTime = BxDolReport::getObjectInstance($CNF['OBJECT_REPORTS_TIME'], $iObjectId)) && $oTime->isEnabled()) {
-                $oTime->putReport($iObjectId, $iAuthorId, $aTrack, true); //--- Revoke old value
-                $oTime->putReport($iObjectId, $iAuthorId, $iTrack); //--- Process new value
-            }
-
-            return $this->_bIsApi ? [] : echoJson(['grid' => $this->getCode(false), 'blink' => $iTrack]);    
+            $iTotal += $aTrack['value'];
         }
 
-        if($this->_bIsApi)
-            return $this->getFormBlockAPI($oForm, $sAction, $iLevel);
-
-        $sContent = BxTemplFunctions::getInstance()->popupBox($this->_oModule->_oConfig->getHtmlIds('time_popup'), _t('_bx_tasks_popup_title_time_edit'), $this->_oModule->_oTemplate->parseHtmlByName('popup_time.html', [
-            'form_id' => $oForm->getId(),
-            'form' => $oForm->getCode(true),
-            'object' => $this->_sObject,
-            'action' => $sAction
+        $sContent = BxTemplFunctions::getInstance()->transBox($this->_oModule->_oConfig->getHtmlIds('total_popup'), $this->_oModule->_oTemplate->parseHtmlByName('popup_total.html', [
+            'total' => $this->_oModule->_oConfig->timeI2S($iTotal)
         ]));
 
-        return echoJson(['popup' => ['html' => $sContent, 'options' => ['closeOnOuterClick' => false]]]);
+        return echoJson(['popup' => ['html' => $sContent, 'options' => ['closeOnOuterClick' => true]]]);
     }
 
     protected function _delete ($mixedId)
@@ -128,90 +78,127 @@ class BxTasksGridTime extends BxTasksGridTimeAdministration
         return $bResult;
     }
 
-    protected function _getFormObject($sAction, $aTrack = [])
+    protected function _getCellAuthorId($mixedValue, $sKey, $aField, $aRow)
+    {
+        if($this->_bIsApi)
+            return ['type' => 'profile', 'data' => BxDolProfile::getData($mixedValue)];
+
+        if(($oProfile = BxDolProfile::getInstanceMagic($mixedValue)) !== false)
+            $mixedValue = $oProfile->getUnit();
+
+        return parent::_getCellDefault($mixedValue, $sKey, $aField, $aRow);
+    }
+
+    protected function _getCellObjectId($mixedValue, $sKey, $aField, $aRow)
     {
         $CNF = &$this->_oModule->_oConfig->CNF;
 
-        $bActionAdd = $sAction == 'add';
-        $bActionEdit = $sAction == 'edit';
-
-        $bTrack = !empty($aTrack) && is_array($aTrack);
-
-        $aActionParams = [
-            'o' => $this->_sObject, 
-            'a' => $sAction,
-            'context_pid' => $this->_iContextPid
-        ];
-        if($bActionEdit && $bTrack)
-            $aActionParams['id'] = (int)$aTrack['id'];
-
-        $sForm = $CNF['OBJECT_FORM_TIME_DISPLAY_' . strtoupper($sAction)];
-        $oForm = BxDolForm::getObjectInstance($CNF['OBJECT_FORM_TIME'], $sForm);
-        $oForm->setId($sForm);
-        $oForm->setName($sForm);
-    	$oForm->setAction(BX_DOL_URL_ROOT . bx_append_url_params('grid.php', $aActionParams));
-
-        $oForm->aParams['db']['table'] = $CNF['TABLE_TIME_TRACK'];
-        if($bActionAdd) {
-            $oForm->aInputs['sys']['value'] = $CNF['OBJECT_REPORTS_TIME'];
-            $oForm->aInputs['action']['value'] = 'Report';
-            $oForm->aInputs['object_id'] = array_merge($oForm->aInputs['object_id'], [
-                'type' => 'select',
-                'values' => [['key' => 0, 'value' => _t('_sys_please_select')]],
-                'required' => true,
-                'checker' => [
-                    'func' => 'Avail',
-                    'error' => _t('_bx_tasks_form_time_input_object_id_err')
-                ]
-            ]);
-
-            $aTasks = $this->_oModule->_oDb->getTasks(-$this->_iContextPid);
-            foreach($aTasks as $aTask) {
-                if($aTask[$CNF['FIELD_STATUS_ADMIN']] !== 'active')
-                    continue;
-
-                $oForm->aInputs['object_id']['values'][] = [
-                    'key' => $aTask[$CNF['FIELD_ID']],
-                    'value' => $aTask[$CNF['FIELD_TITLE']]
-                ];
-            }
-        }
-        else if($bActionEdit) {
-            if($bTrack) {
-                list($value_h, $value_m) = $this->_oModule->_oConfig->timeI2A($aTrack['value']);
-
-                foreach($oForm->aInputs['value'] as $mixedKey => $mixedValue) {
-                    if(!is_numeric($mixedKey) || !is_array($mixedValue))
-                        continue;
-
-                    if(($iValue = ${$mixedValue['name']} ?? false) !== false)
-                        $oForm->aInputs['value'][$mixedKey]['value'] = (int)$iValue;
-                }
-            }
-        }
+        $sTitle = $aRow[$CNF['FIELD_TITLE']];
+        if((int)$aField['chars_limit'] > 0)
+            $sTitle = strmaxtextlen($sTitle, (int)$aField['chars_limit']);
+        if($sTitle == '')
+            $sTitle = _t('_sys_txt_no_title');
+
+        $sUrl = bx_absolute_url(BxDolPermalinks::getInstance()->permalink('page.php?i=' . $CNF['URI_VIEW_ENTRY'] . '&id=' . $mixedValue));
+        
+        if($this->_bIsApi)
+            return ['type' => 'link', 'data' => [
+                'text' => $aRow[$CNF['FIELD_TITLE']],
+                'url' => bx_api_get_relative_url($sUrl)
+            ]];
+        
+        return parent::_getCellDefault($this->_getEntryLink($sTitle, $sUrl, $aRow), $sKey, $aField, $aRow);
+    }
 
-        return $oForm;
+    protected function _getCellValue($mixedValue, $sKey, $aField, $aRow)
+    {
+        return parent::_getCellDefault($this->_oModule->_oConfig->timeI2S($mixedValue), $sKey, $aField, $aRow);
     }
 
-    protected function _getFilterControls()
+    protected function _getCellValueDate($mixedValue, $sKey, $aField, $aRow)
     {
-        $this->__getFilterControls();
+        return $this->_bIsApi ? [
+            'type' => 'time', 
+            'data' => $mixedValue
+        ] : parent::_getCellDefault($mixedValue ? bx_time_js($mixedValue, BX_FORMAT_DATE, true) : '', $sKey, $aField, $aRow);
+    }
 
-        $sContent = $this->_getFilterSelectOne($this->_sFilter2Name, $this->_sFilter2Value, $this->_aFilter2Values);
-        $sContent .= $this->_getFilterDatePicker($this->_sFilter3Name, $this->_sFilter3Value);
+    protected function _getActionDelete($sType, $sKey, $a, $isSmall = false, $isDisabled = false, $aRow = [])
+    {
+        if($this->_isAdministration())
+            $isDisabled = true;
+
+        return parent::_getActionDelete($sType, $sKey, $a, $isSmall, $isDisabled, $aRow);
+    }
+
+    protected function _getFcDefault()
+    {
+        return parent::_getFilterControls();
+    }
+
+    protected function _getFcDateSearch()
+    {
+        $sContent = $this->_getFilterDatePicker($this->_sFilter3Name, $this->_sFilter3Value);
         $sContent .= $this->_getFilterLabel('-');
         $sContent .= $this->_getFilterDatePicker($this->_sFilter4Name, $this->_sFilter4Value);
         $sContent .= $this->_getSearchInput();
-
         return $sContent;
     }
 
-    protected function _getDataSql($sFilter, $sOrderField, $sOrderDir, $iStart, $iPerPage)
+    protected function _getFilterOnChange()
     {
-        $this->_aOptions['source'] .= $this->_oModule->_oDb->prepareAsString(" AND `ttt`.`author_id`=?", $this->_iLogged);
+        return $this->_oModule->_oConfig->getJsObject('time') . '.onChangeFilter(this)';
+    }
 
+    protected function __getDataSql($sFilter, $sOrderField, $sOrderDir, $iStart, $iPerPage)
+    {
         return parent::_getDataSql($sFilter, $sOrderField, $sOrderDir, $iStart, $iPerPage);
     }
+
+    protected function _getEntryLink($sTitle, $sUrl, $aRow)
+    {
+        return $this->_oTemplate->parseHtmlByName('title_link.html', [
+            'href' => $sUrl,
+            'title' => bx_html_attribute($sTitle),
+            'content' => bx_process_output($sTitle),
+            'target' => '_blank'
+        ]);
+    }
+
+    protected function _isCommon()
+    {
+        $CNF = &$this->_oModule->_oConfig->CNF;
+
+        return in_array($this->_sObject, [$CNF['OBJECT_GRID_TIME_COMMON'], $CNF['OBJECT_GRID_TIME_CONTEXT_COMMON']]);
+    }
+
+    protected function _isAdministration()
+    {
+        $CNF = &$this->_oModule->_oConfig->CNF;
+
+        return in_array($this->_sObject, [$CNF['OBJECT_GRID_TIME_ADMINISTRATION'], $CNF['OBJECT_GRID_TIME_CONTEXT_ADMINISTRATION']]);
+    }
+
+    protected function _isContext()
+    {
+        $CNF = &$this->_oModule->_oConfig->CNF;
+
+        return in_array($this->_sObject, [$CNF['OBJECT_GRID_TIME_CONTEXT_ADMINISTRATION'], $CNF['OBJECT_GRID_TIME_CONTEXT_COMMON']]);
+    }
+
+    protected function _getIds()
+    {
+        $aIds = bx_get('ids');
+        if(!$aIds || !is_array($aIds)) {
+            $iId = (int)bx_get('id');
+            if(!$iId) 
+                return false;
+
+            $aIds = [$iId];
+        }
+
+        return $aIds;
+    }
 }
 
 /** @} */

+ 21 - 204
modules/boonex/tasks/classes/BxTasksGridTimeAdministration.php

@@ -8,211 +8,57 @@
  * @{
  */
 
-class BxTasksGridTimeAdministration extends BxBaseModGeneralGrid
-{
-    protected $_iContextPid;
-
-    protected $_sFilter1Name;
-    protected $_sFilter1Value;
-    protected $_aFilter1Values;
-    protected $_sFilter2Name;
-    protected $_sFilter2Value;
-    protected $_aFilter2Values;
-    protected $_sFilter3Name;   //--- Date from
-    protected $_sFilter3Value;
-    protected $_sFilter4Name;   //--- Date to
-    protected $_sFilter4Value;
+require_once('BxTasksGridTime.php');
 
+class BxTasksGridTimeAdministration extends BxTasksGridTime
+{
     public function __construct ($aOptions, $oTemplate = false)
     {
-        $this->_sModule = 'bx_tasks';
-
         parent::__construct ($aOptions, $oTemplate);
 
-        $this->_sDefaultSortingOrder = 'DESC';
-
-        if(($iContextPid = bx_get('context_pid')) !== false) 
-            $this->setContextPid($iContextPid);
-    }
-
-    public function setContextPid($iContextPid)
-    {
-        $CNF = &$this->_oModule->_oConfig->CNF;
-
-        $this->_iContextPid = (int)$iContextPid;
-        $this->_aQueryAppend['context_pid'] = $this->_iContextPid;
-
-        /*
-         * Filter by author_id
-         */
-        $this->_sFilter1Name = 'filter1';
-        $this->_aFilter1Values = [];
-        $this->_sFilter1Value = '';
-
-        if($this->_sObject == $CNF['OBJECT_GRID_TIME_ADMINISTRATION']) {
-            if(($oContext = BxDolProfile::getInstance($this->_iContextPid)) !== false) {
-                $aPids = bx_srv($oContext->getModule(), 'fans', [$oContext->getContentId(), true]);
-                foreach($aPids as $iPid)
-                    $this->_aFilter1Values[$iPid] = $oContext->getDisplayName($iPid);
-            }
-
-            if(($sFilter1 = bx_get($this->_sFilter1Name)) !== false) {
-                $this->_sFilter1Value = bx_process_input($sFilter1);
-                $this->_aQueryAppend[$this->_sFilter1Name] = $this->_sFilter1Value;
-            }
-        }
-
-        /*
-         * Filter by object_id
-         */
-        $this->_sFilter2Name = 'filter2';
-        $this->_aFilter2Values = [];
-        $this->_sFilter2Value = '';
-
-        $aTasks = $this->_oModule->_oDb->getTasks(-$this->_iContextPid);
-        foreach($aTasks as $aTask)
-            $this->_aFilter2Values[$aTask[$CNF['FIELD_ID']]] = $aTask[$CNF['FIELD_TITLE']];
-
-        if(($sFilter2 = bx_get($this->_sFilter2Name)) !== false) {
-            $this->_sFilter2Value = bx_process_input($sFilter2);
-            $this->_aQueryAppend[$this->_sFilter2Name] = $this->_sFilter2Value;
-        }
+        if($this->_isAdministration())
+            $this->_initFilter(1, $this->_oModule->getAssignees());
 
-        /*
-         * Filters by date from/to
-         */
-        $this->_sFilter3Name = 'filter3';
-        $this->_sFilter4Name = 'filter4';
+        $this->_initFilter(2, $this->_oModule->getContexts());
     }
 
-    public function performActionCalculate()
+    protected function _getCellContextModule($mixedValue, $sKey, $aField, $aRow)
     {
-        $sAction = 'calculate';
-
-        $aIds = $this->_getIds();
-        if($aIds === false)
-            return $this->_getActionResult([]);
-
-        $iTotal = 0;
-        foreach($aIds as $iId) {
-            $aTrack = $this->_oModule->_oDb->getTimeTracks(['sample' => 'id', 'id' => $iId]);
-            if(empty($aTrack) || !is_array($aTrack))
-                continue;
-
-            $iTotal += $aTrack['value'];
-        }
-
-        $sContent = BxTemplFunctions::getInstance()->transBox($this->_oModule->_oConfig->getHtmlIds('total_popup'), $this->_oModule->_oTemplate->parseHtmlByName('popup_total.html', [
-            'total' => $this->_oModule->_oConfig->timeI2S($iTotal)
-        ]));
-
-        return echoJson(['popup' => ['html' => $sContent, 'options' => ['closeOnOuterClick' => true]]]);
-    }
-
-    protected function _getCellAuthorId($mixedValue, $sKey, $aField, $aRow)
-    {
-        if($this->_bIsApi)
-            return ['type' => 'profile', 'data' => BxDolProfile::getData($mixedValue)];
-
-        if(($oProfile = BxDolProfile::getInstanceMagic($mixedValue)) !== false)
-            $mixedValue = $oProfile->getUnit();
+        if(($_sTitle = '_' . $mixedValue) && ($sTitle = _t($_sTitle)) && strcmp($_sTitle, $sTitle) != 0)
+            $mixedValue = $sTitle;
+        else if(($aModule = $this->_oModule->_oDb->getModuleByName($mixedValue)) && is_array($aModule))
+            $mixedValue = $aModule['title'] ?? _t('_undefined');
 
         return parent::_getCellDefault($mixedValue, $sKey, $aField, $aRow);
     }
-    
-    protected function _getCellObjectId($mixedValue, $sKey, $aField, $aRow)
-    {
-        $CNF = &$this->_oModule->_oConfig->CNF;
-
-        $sTitle = $aRow[$CNF['FIELD_TITLE']];
-        if((int)$aField['chars_limit'] > 0)
-            $sTitle = strmaxtextlen($sTitle, (int)$aField['chars_limit']);
-        if($sTitle == '')
-            $sTitle = _t('_sys_txt_no_title');
-
-        $sUrl = bx_absolute_url(BxDolPermalinks::getInstance()->permalink('page.php?i=' . $CNF['URI_VIEW_ENTRY'] . '&id=' . $mixedValue));
-        
-        if($this->_bIsApi)
-            return ['type' => 'link', 'data' => [
-                'text' => $aRow[$CNF['FIELD_TITLE']],
-                'url' => bx_api_get_relative_url($sUrl)
-            ]];
-        
-        return parent::_getCellDefault($this->_getEntryLink($sTitle, $sUrl, $aRow), $sKey, $aField, $aRow);
-    }
 
-    protected function _getCellValue($mixedValue, $sKey, $aField, $aRow)
+    protected function _getCellContextId($mixedValue, $sKey, $aField, $aRow)
     {
-        return parent::_getCellDefault($this->_oModule->_oConfig->timeI2S($mixedValue), $sKey, $aField, $aRow);
-    }
-
-    protected function _getCellValueDate($mixedValue, $sKey, $aField, $aRow)
-    {
-        return $this->_bIsApi ? [
-            'type' => 'time', 
-            'data' => $mixedValue
-        ] : parent::_getCellDefault($mixedValue ? bx_time_js($mixedValue, BX_FORMAT_DATE, true) : '', $sKey, $aField, $aRow);
-    }
+        if(($oContext = BxDolProfile::getInstance($mixedValue)) !== false)
+            $mixedValue = $oContext->getDisplayName();
 
-    protected function _getActionEdit($sType, $sKey, $a, $isSmall = false, $isDisabled = false, $aRow = [])
-    {
-        $CNF = &$this->_oModule->_oConfig->CNF;
-
-        if($this->_sObject == $CNF['OBJECT_GRID_TIME_ADMINISTRATION'])
-            $isDisabled = true;
-
-        return parent::_getActionDefault($sType, $sKey, $a, $isSmall, $isDisabled, $aRow);
+        return parent::_getCellDefault($mixedValue, $sKey, $aField, $aRow);
     }
 
-    protected function _getActionDelete($sType, $sKey, $a, $isSmall = false, $isDisabled = false, $aRow = [])
-    {
-        $CNF = &$this->_oModule->_oConfig->CNF;
-
-        if($this->_sObject == $CNF['OBJECT_GRID_TIME_ADMINISTRATION'])
-            $isDisabled = true;
-
-        return parent::_getActionDelete($sType, $sKey, $a, $isSmall, $isDisabled, $aRow);
-    }
-    
     protected function _getFilterControls()
     {
-        $this->__getFilterControls();
-
-        $sContent = $this->_getFilterSelectOne($this->_sFilter1Name, $this->_sFilter1Value, $this->_aFilter1Values);
-        $sContent .= $this->_getFilterSelectOne($this->_sFilter2Name, $this->_sFilter2Value, $this->_aFilter2Values);
-        $sContent .= $this->_getFilterDatePicker($this->_sFilter3Name, $this->_sFilter3Value);
-        $sContent .= $this->_getFilterLabel('-');
-        $sContent .= $this->_getFilterDatePicker($this->_sFilter4Name, $this->_sFilter4Value);
-        $sContent .= $this->_getSearchInput();
+        $this->_getFcDefault();
 
+        $sContent = $this->_getFilterSelectOne($this->_sFilter1Name, $this->_sFilter1Value, $this->_aFilter1Values, '_bx_tasks_grid_filter_item_title_tm_select_one_author_id');
+        $sContent .= $this->_getFilterSelectOne($this->_sFilter2Name, $this->_sFilter2Value, $this->_aFilter2Values, '_bx_tasks_grid_filter_item_title_tm_select_one_context_module');
+        $sContent .= $this->_getFcDateSearch();
         return $sContent;
     }
 
-    protected function _getFilterOnChange()
-    {
-        return $this->_oModule->_oConfig->getJsObject('time') . '.onChangeFilter(this)';
-    }
-
     protected function _getDataSql($sFilter, $sOrderField, $sOrderDir, $iStart, $iPerPage)
     {
-        $this->_aOptions['source'] .= $this->_oModule->_oDb->prepareAsString(" AND ABS(`tt`.`allow_view_to`)=?", $this->_iContextPid);
-
-        $aFilterParts = explode($this->_sParamsDivider, $sFilter);
-        switch (substr_count($sFilter, $this->_sParamsDivider)) {
-            case 3:
-                list($this->_sFilter2Value, $this->_sFilter3Value, $this->_sFilter4Value, $sFilter) = $aFilterParts;
-                break;
-
-            case 4:
-                list($this->_sFilter1Value, $this->_sFilter2Value, $this->_sFilter3Value, $this->_sFilter4Value, $sFilter) = $aFilterParts;
-                break;
-        }
+        $this->_parseFilterValue($sFilter);
 
     	if(!empty($this->_sFilter1Value))
             $this->_aOptions['source'] .= $this->_oModule->_oDb->prepareAsString(" AND `ttt`.`author_id`=?", $this->_sFilter1Value);
 
         if(!empty($this->_sFilter2Value))
-            $this->_aOptions['source'] .= $this->_oModule->_oDb->prepareAsString(" AND `ttt`.`object_id`=?", $this->_sFilter2Value);
+            $this->_aOptions['source'] .= $this->_oModule->_oDb->prepareAsString(" AND `tp`.`type`=?", $this->_sFilter2Value);
         
         if(!empty($this->_sFilter3Value))
             $this->_aOptions['source'] .= $this->_oModule->_oDb->prepareAsString(" AND `ttt`.`value_date`>=?", strtotime($this->_sFilter3Value));
@@ -222,35 +68,6 @@ class BxTasksGridTimeAdministration extends BxBaseModGeneralGrid
 
         return parent::_getDataSql($sFilter, $sOrderField, $sOrderDir, $iStart, $iPerPage);
     }
-
-    protected function _getEntryLink($sTitle, $sUrl, $aRow)
-    {
-        return $this->_oTemplate->parseHtmlByName('title_link.html', [
-            'href' => $sUrl,
-            'title' => bx_html_attribute($sTitle),
-            'content' => bx_process_output($sTitle),
-            'target' => '_blank'
-        ]);
-    }
-
-    protected function __getFilterControls()
-    {
-        parent::_getFilterControls();
-    }
-
-    protected function _getIds()
-    {
-        $aIds = bx_get('ids');
-        if(!$aIds || !is_array($aIds)) {
-            $iId = (int)bx_get('id');
-            if(!$iId) 
-                return false;
-
-            $aIds = [$iId];
-        }
-
-        return $aIds;
-    }
 }
 
 /** @} */

+ 41 - 0
modules/boonex/tasks/classes/BxTasksGridTimeCommon.php

@@ -0,0 +1,41 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT 
+ * @defgroup    Tasks Tasks
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+require_once('BxTasksGridTimeAdministration.php');
+
+class BxTasksGridTimeCommon extends BxTasksGridTimeAdministration
+{
+    protected $_iLogged;
+
+    public function __construct ($aOptions, $oTemplate = false)
+    {
+        parent::__construct ($aOptions, $oTemplate);
+
+        $this->_iLogged = bx_get_logged_profile_id();
+    }
+
+    protected function _getFilterControls()
+    {
+        $this->_getFcDefault();
+
+        $sContent = $this->_getFilterSelectOne($this->_sFilter2Name, $this->_sFilter2Value, $this->_aFilter2Values, '_bx_tasks_grid_filter_item_title_tm_select_one_context_module');
+        $sContent .= $this->_getFcDateSearch();
+        return $sContent;
+    }
+
+    protected function _getDataSql($sFilter, $sOrderField, $sOrderDir, $iStart, $iPerPage)
+    {
+        $this->_aOptions['source'] .= $this->_oModule->_oDb->prepareAsString(" AND `ttt`.`author_id`=?", $this->_iLogged);
+
+        return parent::_getDataSql($sFilter, $sOrderField, $sOrderDir, $iStart, $iPerPage);
+    }
+}
+
+/** @} */

+ 76 - 0
modules/boonex/tasks/classes/BxTasksGridTimeContextAdministration.php

@@ -0,0 +1,76 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT 
+ * @defgroup    Tasks Tasks
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+require_once('BxTasksGridTime.php');
+
+class BxTasksGridTimeContextAdministration extends BxTasksGridTime
+{
+    protected $_iContextPid;
+
+    public function __construct ($aOptions, $oTemplate = false)
+    {
+        parent::__construct ($aOptions, $oTemplate);
+
+        if(($iContextPid = bx_get('context_pid')) !== false) 
+            $this->setContextPid($iContextPid);
+    }
+
+    public function setContextPid($iContextPid)
+    {
+        $CNF = &$this->_oModule->_oConfig->CNF;
+
+        $this->_iContextPid = (int)$iContextPid;
+        $this->_aQueryAppend['context_pid'] = $this->_iContextPid;
+
+        /*
+         * Filter by author_id
+         */
+        if($this->_isAdministration())
+            $this->_initFilter(1, $this->_oModule->getContextMembers($this->_iContextPid));
+
+        /*
+         * Filter by object_id
+         */
+        $this->_initFilter(2, $this->_oModule->getContextEntries($this->_iContextPid));
+    }
+
+    protected function _getFilterControls()
+    {
+        $this->_getFcDefault();
+
+        $sContent = $this->_getFilterSelectOne($this->_sFilter1Name, $this->_sFilter1Value, $this->_aFilter1Values, '_bx_tasks_grid_filter_item_title_tm_select_one_author_id');
+        $sContent .= $this->_getFilterSelectOne($this->_sFilter2Name, $this->_sFilter2Value, $this->_aFilter2Values, '_bx_tasks_grid_filter_item_title_tm_select_one_object_id');
+        $sContent .= $this->_getFcDateSearch();
+        return $sContent;
+    }
+
+    protected function _getDataSql($sFilter, $sOrderField, $sOrderDir, $iStart, $iPerPage)
+    {
+        $this->_aOptions['source'] .= $this->_oModule->_oDb->prepareAsString(" AND ABS(`tt`.`allow_view_to`)=?", $this->_iContextPid);
+
+        $this->_parseFilterValue($sFilter);
+
+    	if(!empty($this->_sFilter1Value))
+            $this->_aOptions['source'] .= $this->_oModule->_oDb->prepareAsString(" AND `ttt`.`author_id`=?", $this->_sFilter1Value);
+
+        if(!empty($this->_sFilter2Value))
+            $this->_aOptions['source'] .= $this->_oModule->_oDb->prepareAsString(" AND `ttt`.`object_id`=?", $this->_sFilter2Value);
+        
+        if(!empty($this->_sFilter3Value))
+            $this->_aOptions['source'] .= $this->_oModule->_oDb->prepareAsString(" AND `ttt`.`value_date`>=?", strtotime($this->_sFilter3Value));
+
+        if(!empty($this->_sFilter4Value))
+            $this->_aOptions['source'] .= $this->_oModule->_oDb->prepareAsString(" AND `ttt`.`value_date`<=?", strtotime($this->_sFilter4Value));
+
+        return parent::__getDataSql($sFilter, $sOrderField, $sOrderDir, $iStart, $iPerPage);
+    }
+}
+
+/** @} */

+ 195 - 0
modules/boonex/tasks/classes/BxTasksGridTimeContextCommon.php

@@ -0,0 +1,195 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT 
+ * @defgroup    Tasks Tasks
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+require_once('BxTasksGridTimeContextAdministration.php');
+
+class BxTasksGridTimeContextCommon extends BxTasksGridTimeContextAdministration
+{
+    protected $_iLogged;
+
+    public function __construct ($aOptions, $oTemplate = false)
+    {
+        parent::__construct ($aOptions, $oTemplate);
+
+        $this->_iLogged = bx_get_logged_profile_id();
+    }
+
+    public function performActionAdd()
+    {
+        $sAction = 'add';
+
+        $oForm = $this->_getFormObject($sAction);
+        $oForm->initChecker();
+        if($oForm->isSubmittedAndValid()) {
+            $iNow = time();
+            $aValsToAdd = [
+                'author_id' => $this->_iLogged,
+                'author_nip' => bx_get_ip_hash(getVisitorIP()),
+                'value' => $this->_oModule->_oConfig->timeA2I([(int)$oForm->getCleanValue('value_h'), (int)$oForm->getCleanValue('value_m')]),
+                'value_date' => $oForm->getCleanValue('value_date') ?: $iNow,
+                'date' => $iNow
+            ];
+
+            $iTrackId = $oForm->insert($aValsToAdd);
+            if(!$iTrackId)
+                return $this->_getActionResult(['msg' => _t('_bx_tasks_txt_err_cannot_perform_action')]);
+
+            $sSystem = $oForm->getCleanValue('sys');
+            $iObjectId = $oForm->getCleanValue('object_id');
+            if(($oTime = BxDolReport::getObjectInstance($sSystem, $iObjectId)) && $oTime->isEnabled())
+                $oTime->putReport($iObjectId, $this->_iLogged, $iTrackId);
+
+            return $this->_bIsApi ? [] : echoJson(['grid' => $this->getCode(false), 'blink' => $iTrackId]);    
+        }
+
+        if($this->_bIsApi)
+            return $this->getFormBlockAPI($oForm, $sAction);
+
+        $sContent = BxTemplFunctions::getInstance()->popupBox($this->_oModule->_oConfig->getHtmlIds('time_popup'), _t('_bx_tasks_popup_title_time_add'), $this->_oModule->_oTemplate->parseHtmlByName('popup_time.html', [
+            'form_id' => $oForm->getId(),
+            'form' => $oForm->getCode(true),
+            'object' => $this->_sObject,
+            'action' => $sAction
+        ]));
+
+        return echoJson(['popup' => ['html' => $sContent, 'options' => ['closeOnOuterClick' => false]]]);
+    }
+
+    public function performActionEdit()
+    {
+    	$CNF = &$this->_oModule->_oConfig->CNF;
+
+        $sAction = 'edit';
+
+        $aIds = $this->_getIds();
+        if($aIds === false)
+            return $this->_getActionResult([]);
+
+        $iTrack = array_shift($aIds);
+        $aTrack = $this->_oModule->_oDb->getTimeTracks(['sample' => 'id', 'id' => $iTrack]);
+        if(empty($aTrack) || !is_array($aTrack))
+            return $this->_getActionResult([]);
+
+        $oForm = $this->_getFormObject($sAction, $aTrack);
+        $oForm->initChecker($aTrack);
+        if($oForm->isSubmittedAndValid()) {
+            $aValsToAdd = [
+                'value' => $this->_oModule->_oConfig->timeA2I([(int)$oForm->getCleanValue('value_h'), (int)$oForm->getCleanValue('value_m')]),
+            ];
+
+            if(!$oForm->update($iTrack, $aValsToAdd))
+                return $this->_getActionResult(['msg' => _t('_bx_tasks_txt_err_cannot_perform_action')]);
+
+            $iObjectId = (int)$aTrack['object_id'];
+            $iAuthorId = (int)$aTrack['author_id'];
+            if(($oTime = BxDolReport::getObjectInstance($CNF['OBJECT_REPORTS_TIME'], $iObjectId)) && $oTime->isEnabled()) {
+                $oTime->putReport($iObjectId, $iAuthorId, $aTrack, true); //--- Revoke old value
+                $oTime->putReport($iObjectId, $iAuthorId, $iTrack); //--- Process new value
+            }
+
+            return $this->_bIsApi ? [] : echoJson(['grid' => $this->getCode(false), 'blink' => $iTrack]);    
+        }
+
+        if($this->_bIsApi)
+            return $this->getFormBlockAPI($oForm, $sAction, $iLevel);
+
+        $sContent = BxTemplFunctions::getInstance()->popupBox($this->_oModule->_oConfig->getHtmlIds('time_popup'), _t('_bx_tasks_popup_title_time_edit'), $this->_oModule->_oTemplate->parseHtmlByName('popup_time.html', [
+            'form_id' => $oForm->getId(),
+            'form' => $oForm->getCode(true),
+            'object' => $this->_sObject,
+            'action' => $sAction
+        ]));
+
+        return echoJson(['popup' => ['html' => $sContent, 'options' => ['closeOnOuterClick' => false]]]);
+    }
+
+    protected function _getFormObject($sAction, $aTrack = [])
+    {
+        $CNF = &$this->_oModule->_oConfig->CNF;
+
+        $bActionAdd = $sAction == 'add';
+        $bActionEdit = $sAction == 'edit';
+
+        $bTrack = !empty($aTrack) && is_array($aTrack);
+
+        $aActionParams = [
+            'o' => $this->_sObject, 
+            'a' => $sAction,
+            'context_pid' => $this->_iContextPid
+        ];
+        if($bActionEdit && $bTrack)
+            $aActionParams['id'] = (int)$aTrack['id'];
+
+        $sForm = $CNF['OBJECT_FORM_TIME_DISPLAY_' . strtoupper($sAction)];
+        $oForm = BxDolForm::getObjectInstance($CNF['OBJECT_FORM_TIME'], $sForm);
+        $oForm->setId($sForm);
+        $oForm->setName($sForm);
+    	$oForm->setAction(BX_DOL_URL_ROOT . bx_append_url_params('grid.php', $aActionParams));
+
+        $oForm->aParams['db']['table'] = $CNF['TABLE_TIME_TRACK'];
+        if($bActionAdd) {
+            $oForm->aInputs['sys']['value'] = $CNF['OBJECT_REPORTS_TIME'];
+            $oForm->aInputs['action']['value'] = 'Report';
+            $oForm->aInputs['object_id'] = array_merge($oForm->aInputs['object_id'], [
+                'type' => 'select',
+                'values' => [['key' => 0, 'value' => _t('_sys_please_select')]],
+                'required' => true,
+                'checker' => [
+                    'func' => 'Avail',
+                    'error' => _t('_bx_tasks_form_time_input_object_id_err')
+                ]
+            ]);
+
+            $aTasks = $this->_oModule->_oDb->getTasks(-$this->_iContextPid);
+            foreach($aTasks as $aTask) {
+                if($aTask[$CNF['FIELD_STATUS_ADMIN']] !== 'active')
+                    continue;
+
+                $oForm->aInputs['object_id']['values'][] = [
+                    'key' => $aTask[$CNF['FIELD_ID']],
+                    'value' => $aTask[$CNF['FIELD_TITLE']]
+                ];
+            }
+        }
+        else if($bActionEdit) {
+            if($bTrack) {
+                list($value_h, $value_m) = $this->_oModule->_oConfig->timeI2A($aTrack['value']);
+
+                foreach($oForm->aInputs['value'] as $mixedKey => $mixedValue) {
+                    if(!is_numeric($mixedKey) || !is_array($mixedValue))
+                        continue;
+
+                    if(($iValue = ${$mixedValue['name']} ?? false) !== false)
+                        $oForm->aInputs['value'][$mixedKey]['value'] = (int)$iValue;
+                }
+            }
+        }
+
+        return $oForm;
+    }
+
+    protected function _getFilterControls()
+    {
+        $this->_getFcDefault();
+
+        $sContent = $this->_getFilterSelectOne($this->_sFilter2Name, $this->_sFilter2Value, $this->_aFilter2Values, '_bx_tasks_grid_filter_item_title_tm_select_one_object_id');
+        $sContent .= $this->_getFcDateSearch();
+        return $sContent;
+    }
+
+    protected function _getDataSql($sFilter, $sOrderField, $sOrderDir, $iStart, $iPerPage)
+    {
+        $this->_aOptions['source'] .= $this->_oModule->_oDb->prepareAsString(" AND `ttt`.`author_id`=?", $this->_iLogged);
+
+        return parent::_getDataSql($sFilter, $sOrderField, $sOrderDir, $iStart, $iPerPage);
+    }
+}
+
+/** @} */

+ 25 - 0
modules/boonex/tasks/classes/BxTasksMenuManageTools.php

@@ -0,0 +1,25 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT 
+ * 
+ * @defgroup    Tasks Tasks
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+/**
+ * 'Tasks manage tools' menu.
+ */
+class BxTasksMenuManageTools extends BxBaseModTextMenuManageTools
+{
+
+    public function __construct($aObject, $oTemplate = false)
+    {
+        $this->MODULE = 'bx_tasks';
+        parent::__construct($aObject, $oTemplate);
+    }
+}
+
+/** @} */

+ 85 - 22
modules/boonex/tasks/classes/BxTasksModule.php

@@ -260,6 +260,19 @@ class BxTasksModule extends BxBaseModTextModule implements iBxDolCalendarService
         echo json_encode($aEntries);
     }
 
+    public function serviceManageTools($sType = 'common')
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        $mixedResults = '';
+        if(!($mixedResults = parent::serviceManageTools($sType)))
+            return $mixedResults;
+
+        return array_merge(parent::serviceManageTools($sType), [
+            'menu' => BxDolMenu::getObjectInstance($CNF['OBJECT_MENU_MANAGE_TOOLS_SUBMENU'])
+        ]);
+    }
+
     public function serviceGetBlockMenuContext($iProfileId)
     {
         $CNF = &$this->_oConfig->CNF;
@@ -272,27 +285,19 @@ class BxTasksModule extends BxBaseModTextModule implements iBxDolCalendarService
         return $oMenu->getCode();
     }
 
-    public function serviceGetBlockManageTimeContext($iContextPid)
-    {
-        $CNF = &$this->_oConfig->CNF;
-
-        return $this->_getBlockManageTimeContext($CNF['OBJECT_GRID_TIME'], $iContextPid);
-    }
-    
-    public function serviceGetBlockAdministrateTimeContext($iContextPid)
+    public function serviceGetBlockManageTime($sType = 'common', $iContextPid = 0)
     {
         $CNF = &$this->_oConfig->CNF;
 
-        return $this->_getBlockManageTimeContext($CNF['OBJECT_GRID_TIME_ADMINISTRATION'], $iContextPid);
-    }
-
-    protected function _getBlockManageTimeContext($sGridObject, $iContextPid)
-    {
-        $oGrid = BxDolGrid::getObjectInstance($sGridObject);
+        $bContextPid = !empty($iContextPid);
+        
+        $sGrid = $CNF['OBJECT_GRID_TIME_' . ($bContextPid ? 'CONTEXT_' : '') . strtoupper($sType)];
+        $oGrid = BxDolGrid::getObjectInstance($sGrid);
         if(!$oGrid)
             return $this->_bIsApi ? [] : '';
 
-        $oGrid->setContextPid($iContextPid);
+        if($bContextPid)
+            $oGrid->setContextPid($iContextPid);
 
         if($this->_bIsApi)
             return [
@@ -304,9 +309,16 @@ class BxTasksModule extends BxBaseModTextModule implements iBxDolCalendarService
         $this->_oTemplate->addCss(array_merge($aCssCalendar, ['manage_tools.css', 'time.css']));
         $this->_oTemplate->addJs(array_merge($aJsCalendar, ['modules/base/text/js/|manage_tools.js', 'time.js']));
         $this->_oTemplate->addJsTranslation(['_sys_grid_search']);
-        return $this->_oTemplate->getJsCode('time', [
-            'sObjNameGrid' => $sGridObject
-        ]) . $oGrid->getCode();
+        $aResult = [
+            'content' => $this->_oTemplate->getJsCode('time', [
+                'sObjNameGrid' => $sGrid
+            ]) . $oGrid->getCode()
+        ];
+
+        if(!$bContextPid)
+            $aResult['menu'] = BxDolMenu::getObjectInstance($CNF['OBJECT_MENU_MANAGE_TOOLS_SUBMENU']);
+
+        return $aResult;
     }
 
     /**
@@ -533,24 +545,30 @@ class BxTasksModule extends BxBaseModTextModule implements iBxDolCalendarService
     public function serviceCheckAllowedCommentsTask($iContentId, $sObjectComments) 
     {
         $CNF = &$this->_oConfig->CNF;
+
         $aContentInfo = $this->_oDb->getContentInfoById($iContentId);
-        if ($aContentInfo[$CNF['FIELD_ALLOW_COMMENTS']] == 0)
+        if($aContentInfo[$CNF['FIELD_ALLOW_COMMENTS']] == 0)
             return false;
 
         return parent::serviceCheckAllowedCommentsTask($iContentId, $sObjectComments);
     }
-	
+
     public function serviceCheckAllowedCommentsView($iContentId, $sObjectComments) 
     {
         $CNF = &$this->_oConfig->CNF;
+
+        //negative id used in comments for reports
+        if($iContentId < 0)
+            return CHECK_ACTION_RESULT_ALLOWED;
+
         $aContentInfo = $this->_oDb->getContentInfoById($iContentId);
-        if ($aContentInfo[$CNF['FIELD_ALLOW_COMMENTS']] == 0)
+        if($aContentInfo[$CNF['FIELD_ALLOW_COMMENTS']] == 0)
             return false;
 
         return parent::serviceCheckAllowedCommentsView($iContentId, $sObjectComments);
     }
 	
-	/**
+    /**
      * @page service Service Calls
      * @section bx_tasks Tasks
      * @subsection bx_tasks-page_blocks Page Blocks
@@ -622,6 +640,51 @@ class BxTasksModule extends BxBaseModTextModule implements iBxDolCalendarService
     /**
      * Common methods
      */
+    public function getAssignees()
+    {
+        $aResults = [];
+        if(($oProfile = BxDolProfile::getInstance()) !== false && ($aIds = $this->_oDb->getTimeTracks(['sample' => 'assignees'])))
+            foreach($aIds as $iId)
+                $aResults[] = ['key' => $iId, 'value' => $oProfile->getDisplayName($iId)];
+
+        return $aResults;
+    }
+
+    public function getContexts()
+    {
+        $aContexts = [];
+
+        $aModules = bx_srv('system', 'get_modules_by_type', ['context', ['name_as_key' => true]]);
+        foreach($aModules as $sModule => $aModule)
+            $aContexts[$sModule] = ($_sTitle = '_' . $sModule) && ($sTitle = _t($_sTitle)) && strcmp($_sTitle, $sTitle) != 0 ? $sTitle : $aModule['title'];
+        
+        return $aContexts; 
+    }
+    
+    public function getContextMembers($iContextPid)
+    {
+        $aMembers = [];
+        if(($oContext = BxDolProfile::getInstance($iContextPid)) !== false) {
+            $aPids = bx_srv($oContext->getModule(), 'fans', [$oContext->getContentId(), true]);
+            foreach($aPids as $iPid)
+                $aMembers[$iPid] = $oContext->getDisplayName($iPid);
+        }
+
+        return $aMembers;
+    }
+
+    public function getContextEntries($iContextPid)
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        $aEntries = [];
+        if(($aTasks = $this->_oDb->getTasks(-$iContextPid)) && is_array($aTasks))
+            foreach($aTasks as $aTask)
+                $aEntries[$aTask[$CNF['FIELD_ID']]] = $aTask[$CNF['FIELD_TITLE']];
+
+        return $aEntries;
+    }
+
     public function onExpired($iContentId)
     {
         $CNF = &$this->_oConfig->CNF;

+ 39 - 3
modules/boonex/tasks/install/langs/en.xml

@@ -220,7 +220,13 @@
     <string name="_bx_tasks_page_title_manage"><![CDATA[Manage]]></string>
     <string name="_bx_tasks_page_block_title_system_manage"><![CDATA[Manage Own]]></string>
     <string name="_bx_tasks_page_block_title_system_manage_administration"><![CDATA[Manage All]]></string>
-    <string name="_bx_tasks_page_block_title_manage"><![CDATA[Manage]]></string>    
+    <string name="_bx_tasks_page_block_title_manage"><![CDATA[Manage]]></string>
+    <string name="_bx_tasks_page_title_sys_time_manage"><![CDATA[Manage Own Time]]></string>
+    <string name="_bx_tasks_page_title_sys_time_manage_administration"><![CDATA[Manage All Time]]></string>
+    <string name="_bx_tasks_page_title_time_manage"><![CDATA[Manage Time]]></string>
+    <string name="_bx_tasks_page_block_title_system_time_manage"><![CDATA[Manage Own Time]]></string>
+    <string name="_bx_tasks_page_block_title_system_time_manage_administration"><![CDATA[Manage All Time]]></string>
+    <string name="_bx_tasks_page_block_title_time_manage"><![CDATA[Manage Time]]></string>
     <string name="_bx_tasks_page_block_title_popular_keywords"><![CDATA[Popular Hashtags]]></string>
     <string name="_bx_tasks_page_block_title_cats"><![CDATA[Tasks Categories]]></string>
     <string name="_bx_tasks_page_block_title_sys_multicats"><![CDATA[Tasks Categories(Multi)]]></string>
@@ -305,8 +311,8 @@
     <string name="_bx_tasks_menu_set_title_entries_my"><![CDATA[My Tasks Menu]]></string>
     <string name="_bx_tasks_menu_item_title_system_manage_my_tasks"><![CDATA[My tasks]]></string>
     <string name="_bx_tasks_menu_item_title_manage_my_tasks"><![CDATA[Tasks]]></string>
-    <string name="_bx_tasks_menu_set_title_manage_tools"><![CDATA[Manage Tools Submenu]]></string>
-    <string name="_bx_tasks_menu_title_manage_tools"><![CDATA[Manage Tools Submenu]]></string>
+    <string name="_bx_tasks_menu_set_title_manage_tools"><![CDATA[Manage Tools - Item Submenu]]></string>
+    <string name="_bx_tasks_menu_title_manage_tools"><![CDATA[Manage Tools - Item Submenu]]></string>
     <string name="_bx_tasks_menu_item_title_system_manage_account"><![CDATA[Manage account]]></string>
     <string name="_bx_tasks_menu_item_title_manage_account"><![CDATA[Manage account]]></string>
     <string name="_bx_tasks_menu_item_title_system_admt_tasks"><![CDATA[Tasks]]></string>
@@ -326,9 +332,37 @@
     <string name="_bx_tasks_menu_item_title_view_context_time"><![CDATA[My Time]]></string>
     <string name="_bx_tasks_menu_item_title_system_view_context_time_administration"><![CDATA[All Time]]></string>
     <string name="_bx_tasks_menu_item_title_view_context_time_administration"><![CDATA[All Time]]></string>
+    <string name="_bx_tasks_menu_title_manage_tools_submenu"><![CDATA[Manage Tools Submenu]]></string>
+    <string name="_bx_tasks_menu_set_title_manage_tools_submenu"><![CDATA[Manage Tools Submenu]]></string>
+    <string name="_bx_tasks_menu_item_title_mt_submenu_entries_common"><![CDATA[My Tasks]]></string>
+    <string name="_bx_tasks_menu_item_title_mt_submenu_entries_administration"><![CDATA[All Tasks]]></string>
+    <string name="_bx_tasks_menu_item_title_mt_submenu_time_common"><![CDATA[My Time]]></string>
+    <string name="_bx_tasks_menu_item_title_mt_submenu_time_administration"><![CDATA[All Time]]></string>
 
     <!-- Grids -->
+    <string name="_bx_tasks_grid_filter_item_title_adm_select_one_filter1"><![CDATA[All Statuses]]></string>
+    <string name="_bx_tasks_grid_filter_item_title_adm_select_one_filter2"><![CDATA[Any Audience]]></string>
+    <string name="_bx_tasks_grid_filter_item_title_adm_select_one_filter3"><![CDATA[All Modules]]></string>
+    <string name="_bx_tasks_grid_filter_item_title_adm_active"><![CDATA[Active]]></string>
+    <string name="_bx_tasks_grid_filter_item_title_adm_hidden"><![CDATA[Hidden]]></string>
+    <string name="_bx_tasks_grid_filter_item_title_adm_pending"><![CDATA[Pending]]></string>
+    <string name="_bx_tasks_grid_column_title_adm_active"><![CDATA[Active]]></string>
+    <string name="_bx_tasks_grid_column_title_adm_title"><![CDATA[Title]]></string>
+    <string name="_bx_tasks_grid_action_title_adm_audit_content"><![CDATA[Audit actions]]></string>
+    <string name="_bx_tasks_grid_column_title_adm_added"><![CDATA[Added]]></string>
+    <string name="_bx_tasks_grid_column_title_adm_author"><![CDATA[Author]]></string>>
+    <string name="_bx_tasks_grid_action_title_adm_add"><![CDATA[Add]]></string>
+    <string name="_bx_tasks_grid_action_title_adm_edit"><![CDATA[Edit]]></string>
+    <string name="_bx_tasks_grid_action_title_adm_delete"><![CDATA[Delete]]></string>
+    <string name="_bx_tasks_grid_action_title_adm_clear_reports"><![CDATA[Сlear reports]]></string>
+    <string name="_bx_tasks_grid_action_title_adm_more_actions"><![CDATA[More Actions]]></string>
+    <string name="_bx_tasks_grid_column_title_adm_status_admin"><![CDATA[Moderation]]></string>
+    <string name="_bx_tasks_grid_action_err_delete"><![CDATA[Cannot delete the selected task(s).]]></string>
+    <string name="_bx_tasks_grid_txt_account_manager"><![CDATA[Redirect to manage account.]]></string>
+
     <string name="_bx_tasks_grid_column_title_tm_author_id"><![CDATA[Profile]]></string>
+    <string name="_bx_tasks_grid_column_title_tm_context_id"><![CDATA[Context]]></string>
+    <string name="_bx_tasks_grid_column_title_tm_context_module"><![CDATA[Module]]></string>
     <string name="_bx_tasks_grid_column_title_tm_object_id"><![CDATA[Task]]></string>
     <string name="_bx_tasks_grid_column_title_tm_text"><![CDATA[Note]]></string>
     <string name="_bx_tasks_grid_column_title_tm_value"><![CDATA[Time]]></string>
@@ -338,6 +372,7 @@
     <string name="_bx_tasks_grid_action_title_tm_delete"><![CDATA[Remove]]></string>
     <string name="_bx_tasks_grid_action_title_tm_calculate"><![CDATA[Calculate]]></string>
     <string name="_bx_tasks_grid_filter_item_title_tm_select_one_author_id"><![CDATA[Any Assignee]]></string>
+    <string name="_bx_tasks_grid_filter_item_title_tm_select_one_context_module"><![CDATA[Any Module]]></string>
     <string name="_bx_tasks_grid_filter_item_title_tm_select_one_object_id"><![CDATA[Any Task]]></string>
 
     <string name="_bx_tasks_chart_growth"><![CDATA[Tasks: Growth]]></string>
@@ -422,6 +457,7 @@
     <string name="_bx_tasks_txt_filter_uncompleted"><![CDATA[Uncompleted Tasks]]></string>
     <string name="_bx_tasks_txt_total"><![CDATA[Total: {0}]]></string>
     <string name="_bx_tasks_txt_estimate"><![CDATA[Estimate: {0}]]></string>
+    <string name="_bx_tasks_txt_set"><![CDATA[set...]]></string>
 
     <string name="_bx_tasks_txt_err_cannot_perform_action"><![CDATA[Cannot perform action. Please report.]]></string>
     <string name="_bx_tasks_txt_err_cannot_perform_action"><![CDATA[Cannot perform action. Please report.]]></string>

+ 2 - 2
modules/boonex/tasks/install/sql/disable.sql

@@ -8,12 +8,12 @@ DELETE FROM `sys_options_types` WHERE `id` = @iTypeId;
 
 -- PAGES
 DELETE FROM `sys_objects_page` WHERE `module` = 'bx_tasks';
-DELETE FROM `sys_pages_blocks` WHERE `module` = 'bx_tasks' OR `object` IN('bx_tasks_create_entry', 'bx_tasks_edit_entry', 'bx_tasks_delete_entry', 'bx_tasks_view_entry', 'bx_tasks_view_entry_comments', 'bx_tasks_context', 'bx_tasks_context_time', 'bx_tasks_context_time_administration');
+DELETE FROM `sys_pages_blocks` WHERE `module` = 'bx_tasks' OR `object` IN('bx_tasks_create_entry', 'bx_tasks_edit_entry', 'bx_tasks_delete_entry', 'bx_tasks_view_entry', 'bx_tasks_view_entry_comments', 'bx_tasks_context', 'bx_tasks_manage', 'bx_tasks_administration', 'bx_tasks_time_manage', 'bx_tasks_time_administration', 'bx_tasks_context_time', 'bx_tasks_context_time_administration');
 
 -- MENU
 DELETE FROM `sys_objects_menu` WHERE `module` = 'bx_tasks';
 DELETE FROM `sys_menu_sets` WHERE `module` = 'bx_tasks';
-DELETE FROM `sys_menu_items` WHERE `module` = 'bx_tasks' OR `set_name` IN('bx_tasks_create_task_attachments', 'bx_tasks_view', 'bx_tasks_view_actions', 'bx_tasks_view_submenu', 'bx_tasks_view_context_submenu');
+DELETE FROM `sys_menu_items` WHERE `module` = 'bx_tasks' OR `set_name` IN('bx_tasks_create_task_attachments', 'bx_tasks_view', 'bx_tasks_view_actions', 'bx_tasks_view_submenu', 'bx_tasks_view_context_submenu', 'bx_tasks_menu_manage_tools', 'bx_tasks_manage_tools_submenu');
 
 -- PRIVACY 
 DELETE FROM `sys_objects_privacy` WHERE `object` = 'bx_tasks_allow_view_to';

+ 141 - 22
modules/boonex/tasks/install/sql/enable.sql

@@ -91,7 +91,7 @@ INSERT INTO `sys_objects_page`(`object`, `uri`, `title_system`, `title`, `module
 
 INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title_system`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `active`, `order`) VALUES 
 ('bx_tasks_context_time', 2, 'bx_tasks', '_bx_tasks_page_block_title_sys_menu_in_context', '_bx_tasks_page_block_title_menu_in_context', 13, 2147483647, 'service', 'a:3:{s:6:"module";s:8:"bx_tasks";s:6:"method";s:22:"get_block_menu_context";s:6:"params";a:1:{i:0;s:12:"{profile_id}";}}', 0, 0, 1, 1),
-('bx_tasks_context_time', 3, 'bx_tasks', '_bx_tasks_page_block_title_sys_entries_time_in_context', '_bx_tasks_page_block_title_entries_time_in_context', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:8:"bx_tasks";s:6:"method";s:29:"get_block_manage_time_context";s:6:"params";a:1:{i:0;s:12:"{profile_id}";}}', 0, 0, 1, 1);
+('bx_tasks_context_time', 3, 'bx_tasks', '_bx_tasks_page_block_title_sys_entries_time_in_context', '_bx_tasks_page_block_title_entries_time_in_context', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:8:"bx_tasks";s:6:"method";s:21:"get_block_manage_time";s:6:"params";a:2:{i:0;s:6:"common";i:1;s:12:"{profile_id}";}}', 0, 0, 1, 1);
 
 -- PAGE: entries' time in context (all)
 INSERT INTO `sys_objects_page`(`object`, `uri`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
@@ -99,10 +99,44 @@ INSERT INTO `sys_objects_page`(`object`, `uri`, `title_system`, `title`, `module
 
 INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title_system`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `active`, `order`) VALUES 
 ('bx_tasks_context_time_administration', 2, 'bx_tasks', '_bx_tasks_page_block_title_sys_menu_in_context', '_bx_tasks_page_block_title_menu_in_context', 13, 2147483647, 'service', 'a:3:{s:6:"module";s:8:"bx_tasks";s:6:"method";s:22:"get_block_menu_context";s:6:"params";a:1:{i:0;s:12:"{profile_id}";}}', 0, 0, 1, 1),
-('bx_tasks_context_time_administration', 3, 'bx_tasks', '_bx_tasks_page_block_title_sys_entries_time_in_context_administration', '_bx_tasks_page_block_title_entries_time_in_context_administration', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:8:"bx_tasks";s:6:"method";s:35:"get_block_administrate_time_context";s:6:"params";a:1:{i:0;s:12:"{profile_id}";}}', 0, 0, 1, 1);
+('bx_tasks_context_time_administration', 3, 'bx_tasks', '_bx_tasks_page_block_title_sys_entries_time_in_context_administration', '_bx_tasks_page_block_title_entries_time_in_context_administration', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:8:"bx_tasks";s:6:"method";s:21:"get_block_manage_time";s:6:"params";a:2:{i:0;s:14:"administration";i:1;s:12:"{profile_id}";}}', 0, 0, 1, 1);
 
--- MENU: create task form attachments (link, photo, video, etc)
+-- PAGE: manage own entries
+INSERT INTO `sys_objects_page`(`object`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `uri`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_tasks_manage', '_bx_tasks_page_title_sys_manage', '_bx_tasks_page_title_manage', 'bx_tasks', 5, 2147483647, 1, 'tasks-manage', 'page.php?i=tasks-manage', '', '', '', 0, 1, 0, 'BxTasksPageBrowse', 'modules/boonex/tasks/classes/BxTasksPageBrowse.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title_system`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES 
+('bx_tasks_manage', 1, 'bx_tasks', '_bx_tasks_page_block_title_system_manage', '_bx_tasks_page_block_title_manage', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:8:"bx_tasks";s:6:"method";s:12:"manage_tools";}', 0, 1, 0);
+
+-- PAGE: manage all entries
+INSERT INTO `sys_objects_page`(`object`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `uri`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_tasks_administration', '_bx_tasks_page_title_sys_manage_administration', '_bx_tasks_page_title_manage', 'bx_tasks', 5, 192, 1, 'tasks-administration', 'page.php?i=tasks-administration', '', '', '', 0, 1, 0, 'BxTasksPageBrowse', 'modules/boonex/tasks/classes/BxTasksPageBrowse.php');
 
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title_system`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES 
+('bx_tasks_administration', 1, 'bx_tasks', '_bx_tasks_page_block_title_system_manage_administration', '_bx_tasks_page_block_title_manage', 11, 192, 'service', 'a:3:{s:6:"module";s:8:"bx_tasks";s:6:"method";s:12:"manage_tools";s:6:"params";a:1:{i:0;s:14:"administration";}}', 0, 1, 0);
+
+-- PAGE: manage own time
+INSERT INTO `sys_objects_page`(`object`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `uri`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_tasks_time_manage', '_bx_tasks_page_title_sys_time_manage', '_bx_tasks_page_title_time_manage', 'bx_tasks', 5, 2147483647, 1, 'tasks-time-manage', 'page.php?i=tasks-time-manage', '', '', '', 0, 1, 0, 'BxTasksPageBrowse', 'modules/boonex/tasks/classes/BxTasksPageBrowse.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title_system`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES 
+('bx_tasks_time_manage', 1, 'bx_tasks', '_bx_tasks_page_block_title_system_time_manage', '_bx_tasks_page_block_title_time_manage', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:8:"bx_tasks";s:6:"method";s:21:"get_block_manage_time";s:6:"params";a:1:{i:0;s:6:"common";}}', 0, 1, 0);
+
+-- PAGE: manage all time
+INSERT INTO `sys_objects_page`(`object`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `uri`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_tasks_time_administration', '_bx_tasks_page_title_sys_time_manage_administration', '_bx_tasks_page_title_time_manage', 'bx_tasks', 5, 192, 1, 'tasks-time-administration', 'page.php?i=tasks-time-administration', '', '', '', 0, 1, 0, 'BxTasksPageBrowse', 'modules/boonex/tasks/classes/BxTasksPageBrowse.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title_system`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES 
+('bx_tasks_time_administration', 1, 'bx_tasks', '_bx_tasks_page_block_title_system_time_manage_administration', '_bx_tasks_page_block_title_time_manage', 11, 192, 'service', 'a:3:{s:6:"module";s:8:"bx_tasks";s:6:"method";s:21:"get_block_manage_time";s:6:"params";a:1:{i:0;s:14:"administration";}}', 0, 1, 0);
+
+
+
+-- MENU: add to site menu
+SET @iSiteMenuOrder = (SELECT `order` FROM `sys_menu_items` WHERE `set_name` = 'sys_site' AND `active` = 1 AND `order` < 9999 ORDER BY `order` DESC LIMIT 1);
+INSERT INTO `sys_menu_items` (`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `submenu_object`, `visible_for_levels`, `active`, `copyable`, `order`) VALUES 
+('sys_site', 'bx_tasks', 'tasks-manage', '_bx_tasks_menu_item_title_system_entries_home', '_bx_tasks_menu_item_title_entries_home', 'page.php?i=tasks-manage', '', '', 'tasks col-red3', '', 2147483647, 1, 1, IFNULL(@iSiteMenuOrder, 0) + 1);
+
+-- MENU: create task form attachments (link, photo, video, etc)
 INSERT INTO `sys_objects_menu`(`object`, `title`, `set_name`, `module`, `template_id`, `deletable`, `active`, `override_class_name`, `override_class_file`) VALUES 
 ('bx_tasks_entry_attachments', '_bx_tasks_menu_title_entry_attachments', 'bx_tasks_entry_attachments', 'bx_tasks', 23, 0, 1, 'BxTasksMenuAttachments', 'modules/boonex/tasks/classes/BxTasksMenuAttachments.php');
 
@@ -186,6 +220,29 @@ INSERT INTO `sys_menu_items`(`set_name`, `module`, `name`, `title_system`, `titl
 ('bx_tasks_view_context_submenu', 'bx_tasks', 'tasks-context-time', '_bx_tasks_menu_item_title_system_view_context_time', '_bx_tasks_menu_item_title_view_context_time', 'page.php?i=tasks-context-time&profile_id={profile_id}', '', '', '', '', 2147483647, '', 1, 0, 2),
 ('bx_tasks_view_context_submenu', 'bx_tasks', 'tasks-context-time-administration', '_bx_tasks_menu_item_title_system_view_context_time_administration', '_bx_tasks_menu_item_title_view_context_time_administration', 'page.php?i=tasks-context-time-administration&profile_id={profile_id}', '', '', '', '', 2147483647, 'a:3:{s:6:"module";s:8:"bx_tasks";s:6:"method";s:31:"check_allowed_manage_in_context";s:6:"params";a:1:{i:0;s:12:"{profile_id}";}}', 1, 0, 3);
 
+-- MENU: manage tools submenu
+INSERT INTO `sys_objects_menu`(`object`, `title`, `set_name`, `module`, `template_id`, `deletable`, `active`, `override_class_name`, `override_class_file`) VALUES 
+('bx_tasks_manage_tools_submenu', '_bx_tasks_menu_title_manage_tools_submenu', 'bx_tasks_manage_tools_submenu', 'bx_tasks', 26, 0, 1, '', '');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_tasks_manage_tools_submenu', 'bx_tasks', '_bx_tasks_menu_set_title_manage_tools_submenu', 0);
+
+INSERT INTO `sys_menu_items`(`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `submenu_object`, `visible_for_levels`, `active`, `copyable`, `order`) VALUES 
+('bx_tasks_manage_tools_submenu', 'bx_tasks', 'tasks-manage', '', '_bx_tasks_menu_item_title_mt_submenu_entries_common', 'page.php?i=tasks-manage', '', '_self', '', '', 2147483647, 1, 0, 1),
+('bx_tasks_manage_tools_submenu', 'bx_tasks', 'tasks-administration', '', '_bx_tasks_menu_item_title_mt_submenu_entries_administration', 'page.php?i=tasks-administration', '', '_self', '', '', 128, 1, 0, 2),
+('bx_tasks_manage_tools_submenu', 'bx_tasks', 'tasks-time-manage', '', '_bx_tasks_menu_item_title_mt_submenu_time_common', 'page.php?i=tasks-time-manage', '', '_self', '', '', 2147483647, 1, 0, 3),
+('bx_tasks_manage_tools_submenu', 'bx_tasks', 'tasks-time-administration', '', '_bx_tasks_menu_item_title_mt_submenu_time_administration', 'page.php?i=tasks-time-administration', '', '_self', '', '', 128, 1, 0, 4);
+
+-- MENU: manage tools: item submenu
+INSERT INTO `sys_objects_menu`(`object`, `title`, `set_name`, `module`, `template_id`, `deletable`, `active`, `override_class_name`, `override_class_file`) VALUES 
+('bx_tasks_menu_manage_tools', '_bx_tasks_menu_title_manage_tools', 'bx_tasks_menu_manage_tools', 'bx_tasks', 6, 0, 1, 'BxTasksMenuManageTools', 'modules/boonex/tasks/classes/BxTasksMenuManageTools.php');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_tasks_menu_manage_tools', 'bx_tasks', '_bx_tasks_menu_set_title_manage_tools', 0);
+
+--INSERT INTO `sys_menu_items`(`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `submenu_object`, `visible_for_levels`, `active`, `copyable`, `order`) VALUES 
+--('bx_tasks_menu_manage_tools', 'bx_tasks', 'delete-with-content', '_bx_tasks_menu_item_title_system_delete_with_content', '_bx_tasks_menu_item_title_delete_with_content', 'javascript:void(0)', 'javascript:{js_object}.onClickDeleteWithContent({content_id});', '_self', 'far trash-alt', '', 128, 1, 0, 0);
+
 -- MENU: add menu item to profiles modules (trigger* menu sets are processed separately upon modules enable/disable)
 INSERT INTO `sys_menu_items`(`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `submenu_object`, `visible_for_levels`, `active`, `copyable`, `order`) VALUES 
 ('trigger_group_view_submenu', 'bx_tasks', 'tasks-context', '_bx_tasks_menu_item_title_system_view_entries_in_context', '_bx_tasks_menu_item_title_view_entries_in_context', 'page.php?i=tasks-context&profile_id={profile_id}', '', '', 'tasks col-red3', '', 510, 1, 0, 0);
@@ -297,35 +354,97 @@ INSERT INTO `sys_objects_chart` (`object`, `title`, `table`, `field_date_ts`, `f
 ('bx_tasks_growth', '_bx_tasks_chart_growth', 'bx_tasks_tasks', 'added', '', 'status,status_admin', '', 1, @iMaxOrderCharts + 1, 'BxDolChartGrowth', ''),
 ('bx_tasks_growth_speed', '_bx_tasks_chart_growth_speed', 'bx_tasks_tasks', 'added', '', 'status,status_admin', '', 1, @iMaxOrderCharts + 2, 'BxDolChartGrowthSpeed', '');
 
+-- GRIDS: moderation tools
+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`, `sorting_fields_translatable`, `visible_for_levels`, `override_class_name`, `override_class_file`) VALUES
+('bx_tasks_administration', 'Sql', 'SELECT `tt`.* FROM `bx_tasks_tasks` AS `tt` INNER JOIN `sys_profiles` AS `tp` ON ABS(`tt`.`allow_view_to`)=`tp`.`id` WHERE 1 ', 'bx_tasks_tasks', 'id', 'added', 'status_admin', '', 20, NULL, 'start', '', 'tt`.`title,tt`.`text', '', 'like', 'reports', '', 192, 'BxTasksGridAdministration', 'modules/boonex/tasks/classes/BxTasksGridAdministration.php'),
+('bx_tasks_common', 'Sql', 'SELECT `tt`.* FROM `bx_tasks_tasks` AS `tt` INNER JOIN `sys_profiles` AS `tp` ON ABS(`tt`.`allow_view_to`)=`tp`.`id` WHERE 1 ', 'bx_tasks_tasks', 'id', 'added', 'status', '', 20, NULL, 'start', '', 'tt`.`title,tt`.`text', '', 'like', '', '', 2147483647, 'BxTasksGridCommon', 'modules/boonex/tasks/classes/BxTasksGridCommon.php');
+
+INSERT INTO `sys_grid_fields` (`object`, `name`, `title`, `width`, `translatable`, `chars_limit`, `params`, `order`) VALUES
+('bx_tasks_administration', 'checkbox', '_sys_select', '2%', 0, '', '', 1),
+('bx_tasks_administration', 'switcher', '_bx_tasks_grid_column_title_adm_active', '8%', 0, '', '', 2),
+('bx_tasks_administration', 'reports', '_sys_txt_reports_title', '5%', 0, '', '', 3),
+('bx_tasks_administration', 'title', '_bx_tasks_grid_column_title_adm_title', '25%', 0, '25', '', 4),
+('bx_tasks_administration', 'added', '_bx_tasks_grid_column_title_adm_added', '20%', 1, '25', '', 5),
+('bx_tasks_administration', 'author', '_bx_tasks_grid_column_title_adm_author', '20%', 0, '25', '', 6),
+('bx_tasks_administration', 'actions', '', '20%', 0, '', '', 7),
+
+('bx_tasks_common', 'checkbox', '_sys_select', '2%', 0, '', '', 1),
+('bx_tasks_common', 'switcher', '_bx_tasks_grid_column_title_adm_active', '8%', 0, '', '', 2),
+('bx_tasks_common', 'title', '_bx_tasks_grid_column_title_adm_title', '40%', 0, '35', '', 3),
+('bx_tasks_common', 'added', '_bx_tasks_grid_column_title_adm_added', '15%', 1, '25', '', 4),
+('bx_tasks_common', 'status_admin', '_bx_tasks_grid_column_title_adm_status_admin', '15%', 0, '16', '', 5),
+('bx_tasks_common', 'actions', '', '20%', 0, '', '', 6);
+
+
+INSERT INTO `sys_grid_actions` (`object`, `type`, `name`, `title`, `icon`, `icon_only`, `confirm`, `order`) VALUES
+('bx_tasks_administration', 'bulk', 'delete', '_bx_tasks_grid_action_title_adm_delete', '', 0, 1, 1),
+('bx_tasks_administration', 'bulk', 'clear_reports', '_bx_tasks_grid_action_title_adm_clear_reports', '', 0, 1, 1),
+('bx_tasks_administration', 'single', 'edit', '_bx_tasks_grid_action_title_adm_edit', 'pencil-alt', 1, 0, 1),
+('bx_tasks_administration', 'single', 'delete', '_bx_tasks_grid_action_title_adm_delete', 'remove', 1, 1, 2),
+('bx_tasks_administration', 'single', 'settings', '_bx_tasks_grid_action_title_adm_more_actions', 'cog', 1, 0, 3),
+('bx_tasks_administration', 'single', 'audit_content', '_bx_tasks_grid_action_title_adm_audit_content', 'search', 1, 0, 4),
+('bx_tasks_administration', 'single', 'clear_reports', '_bx_tasks_grid_action_title_adm_clear_reports', 'eraser', 1, 0, 5),
+
+('bx_tasks_common', 'bulk', 'delete', '_bx_tasks_grid_action_title_adm_delete', '', 0, 1, 1),
+('bx_tasks_common', 'single', 'edit', '_bx_tasks_grid_action_title_adm_edit', 'pencil-alt', 1, 0, 1),
+('bx_tasks_common', 'single', 'delete', '_bx_tasks_grid_action_title_adm_delete', 'remove', 1, 1, 2),
+('bx_tasks_common', 'single', 'settings', '_bx_tasks_grid_action_title_adm_more_actions', 'cog', 1, 0, 3);
+
 -- GRIDS: moderation time tools
 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`, `sorting_fields_translatable`, `visible_for_levels`, `override_class_name`, `override_class_file`) VALUES
-('bx_tasks_time_administration', 'Sql', 'SELECT `ttt`.*, `tt`.`title` FROM `bx_tasks_time_track` AS `ttt` INNER JOIN `bx_tasks_tasks` AS `tt` ON `ttt`.`object_id`=`tt`.`id` WHERE 1 ', 'bx_tasks_time_track', 'id', 'value_date', '', '', 20, NULL, 'start', '', 'ttt`.`text,tt`.`title,tt`.`text', '', 'like', 'date', '', 192, 'BxTasksGridTimeAdministration', 'modules/boonex/tasks/classes/BxTasksGridTimeAdministration.php'),
-('bx_tasks_time', 'Sql', 'SELECT `ttt`.*, `tt`.`title` FROM `bx_tasks_time_track` AS `ttt` INNER JOIN `bx_tasks_tasks` AS `tt` ON `ttt`.`object_id`=`tt`.`id` WHERE 1 ', 'bx_tasks_time_track', 'id', 'value_date', '', '', 20, NULL, 'start', '', 'ttt`.`text,tt`.`title,tt`.`text', '', 'like', 'date', '', 2147483647, 'BxTasksGridTime', 'modules/boonex/tasks/classes/BxTasksGridTime.php');
+('bx_tasks_time_administration', 'Sql', 'SELECT `ttt`.*, `tt`.`title`, `tp`.`id` AS `context_id`, `tp`.`type` AS `context_module` FROM `bx_tasks_time_track` AS `ttt` INNER JOIN `bx_tasks_tasks` AS `tt` ON `ttt`.`object_id`=`tt`.`id` INNER JOIN `sys_profiles` AS `tp` ON ABS(`tt`.`allow_view_to`)=`tp`.`id` WHERE 1 ', 'bx_tasks_time_track', 'id', 'value_date', '', '', 20, NULL, 'start', '', 'ttt`.`text,tt`.`title,tt`.`text', '', 'like', 'date', '', 192, 'BxTasksGridTimeAdministration', 'modules/boonex/tasks/classes/BxTasksGridTimeAdministration.php'),
+('bx_tasks_time_common', 'Sql', 'SELECT `ttt`.*, `tt`.`title`, `tp`.`id` AS `context_id`, `tp`.`type` AS `context_module` FROM `bx_tasks_time_track` AS `ttt` INNER JOIN `bx_tasks_tasks` AS `tt` ON `ttt`.`object_id`=`tt`.`id` INNER JOIN `sys_profiles` AS `tp` ON ABS(`tt`.`allow_view_to`)=`tp`.`id` WHERE 1 ', 'bx_tasks_time_track', 'id', 'value_date', '', '', 20, NULL, 'start', '', 'ttt`.`text,tt`.`title,tt`.`text', '', 'like', 'date', '', 2147483647, 'BxTasksGridTimeCommon', 'modules/boonex/tasks/classes/BxTasksGridTimeCommon.php'),
+
+('bx_tasks_time_context_administration', 'Sql', 'SELECT `ttt`.*, `tt`.`title` FROM `bx_tasks_time_track` AS `ttt` INNER JOIN `bx_tasks_tasks` AS `tt` ON `ttt`.`object_id`=`tt`.`id` WHERE 1 ', 'bx_tasks_time_track', 'id', 'value_date', '', '', 20, NULL, 'start', '', 'ttt`.`text,tt`.`title,tt`.`text', '', 'like', 'date', '', 192, 'BxTasksGridTimeContextAdministration', 'modules/boonex/tasks/classes/BxTasksGridTimeContextAdministration.php'),
+('bx_tasks_time_context_common', 'Sql', 'SELECT `ttt`.*, `tt`.`title` FROM `bx_tasks_time_track` AS `ttt` INNER JOIN `bx_tasks_tasks` AS `tt` ON `ttt`.`object_id`=`tt`.`id` WHERE 1 ', 'bx_tasks_time_track', 'id', 'value_date', '', '', 20, NULL, 'start', '', 'ttt`.`text,tt`.`title,tt`.`text', '', 'like', 'date', '', 2147483647, 'BxTasksGridTimeContextCommon', 'modules/boonex/tasks/classes/BxTasksGridTimeContextCommon.php');
 
 INSERT INTO `sys_grid_fields` (`object`, `name`, `title`, `width`, `translatable`, `chars_limit`, `params`, `order`) VALUES
 ('bx_tasks_time_administration', 'checkbox', '_sys_select', '2%', 0, 0, '', 1),
-('bx_tasks_time_administration', 'author_id', '_bx_tasks_grid_column_title_tm_author_id', '28%', 0, 0, '', 2),
-('bx_tasks_time_administration', 'object_id', '_bx_tasks_grid_column_title_tm_object_id', '30%', 0, 0, '', 3),
-('bx_tasks_time_administration', 'text', '_bx_tasks_grid_column_title_tm_text', '15%', 0, 16, '', 4),
-('bx_tasks_time_administration', 'value', '_bx_tasks_grid_column_title_tm_value', '10%', 0, 0, '', 5),
-('bx_tasks_time_administration', 'value_date', '_bx_tasks_grid_column_title_tm_value_date', '15%', 0, 0, '', 6),
-
-('bx_tasks_time', 'checkbox', '_sys_select', '2%', 0, 0, '', 1),
-('bx_tasks_time', 'object_id', '_bx_tasks_grid_column_title_tm_object_id', '30%', 0, 0, '', 2),
-('bx_tasks_time', 'text', '_bx_tasks_grid_column_title_tm_text', '25%', 0, 32, '', 3),
-('bx_tasks_time', 'value', '_bx_tasks_grid_column_title_tm_value', '10%', 0, 0, '', 4),
-('bx_tasks_time', 'value_date', '_bx_tasks_grid_column_title_tm_value_date', '15%', 0, 0, '', 5),
-('bx_tasks_time', 'actions', '', '18%', 0, '', '', 6);
+('bx_tasks_time_administration', 'author_id', '_bx_tasks_grid_column_title_tm_author_id', '18%', 0, 0, '', 2),
+('bx_tasks_time_administration', 'context_module', '_bx_tasks_grid_column_title_tm_context_module', '10%', 0, 0, '', 3),
+('bx_tasks_time_administration', 'context_id', '_bx_tasks_grid_column_title_tm_context_id', '15%', 0, 0, '', 4),
+('bx_tasks_time_administration', 'object_id', '_bx_tasks_grid_column_title_tm_object_id', '15%', 0, 0, '', 5),
+('bx_tasks_time_administration', 'text', '_bx_tasks_grid_column_title_tm_text', '15%', 0, 16, '', 6),
+('bx_tasks_time_administration', 'value', '_bx_tasks_grid_column_title_tm_value', '10%', 0, 0, '', 7),
+('bx_tasks_time_administration', 'value_date', '_bx_tasks_grid_column_title_tm_value_date', '15%', 0, 0, '', 8),
+
+('bx_tasks_time_common', 'checkbox', '_sys_select', '2%', 0, 0, '', 1),
+('bx_tasks_time_common', 'context_module', '_bx_tasks_grid_column_title_tm_context_module', '10%', 0, 0, '', 2),
+('bx_tasks_time_common', 'context_id', '_bx_tasks_grid_column_title_tm_context_id', '20%', 0, 0, '', 3),
+('bx_tasks_time_common', 'object_id', '_bx_tasks_grid_column_title_tm_object_id', '23%', 0, 0, '', 4),
+('bx_tasks_time_common', 'text', '_bx_tasks_grid_column_title_tm_text', '20%', 0, 32, '', 5),
+('bx_tasks_time_common', 'value', '_bx_tasks_grid_column_title_tm_value', '10%', 0, 0, '', 6),
+('bx_tasks_time_common', 'value_date', '_bx_tasks_grid_column_title_tm_value_date', '15%', 0, 0, '', 7),
+
+('bx_tasks_time_context_administration', 'checkbox', '_sys_select', '2%', 0, 0, '', 1),
+('bx_tasks_time_context_administration', 'author_id', '_bx_tasks_grid_column_title_tm_author_id', '28%', 0, 0, '', 2),
+('bx_tasks_time_context_administration', 'object_id', '_bx_tasks_grid_column_title_tm_object_id', '30%', 0, 0, '', 3),
+('bx_tasks_time_context_administration', 'text', '_bx_tasks_grid_column_title_tm_text', '15%', 0, 16, '', 4),
+('bx_tasks_time_context_administration', 'value', '_bx_tasks_grid_column_title_tm_value', '10%', 0, 0, '', 5),
+('bx_tasks_time_context_administration', 'value_date', '_bx_tasks_grid_column_title_tm_value_date', '15%', 0, 0, '', 6),
+
+('bx_tasks_time_context_common', 'checkbox', '_sys_select', '2%', 0, 0, '', 1),
+('bx_tasks_time_context_common', 'object_id', '_bx_tasks_grid_column_title_tm_object_id', '30%', 0, 0, '', 2),
+('bx_tasks_time_context_common', 'text', '_bx_tasks_grid_column_title_tm_text', '25%', 0, 32, '', 3),
+('bx_tasks_time_context_common', 'value', '_bx_tasks_grid_column_title_tm_value', '10%', 0, 0, '', 4),
+('bx_tasks_time_context_common', 'value_date', '_bx_tasks_grid_column_title_tm_value_date', '15%', 0, 0, '', 5),
+('bx_tasks_time_context_common', 'actions', '', '18%', 0, '', '', 6);
 
 INSERT INTO `sys_grid_actions` (`object`, `type`, `name`, `title`, `icon`, `icon_only`, `confirm`, `order`) VALUES
 ('bx_tasks_time_administration', 'bulk', 'calculate', '_bx_tasks_grid_action_title_tm_calculate', '', 0, 0, 1),
 ('bx_tasks_time_administration', 'bulk', 'delete', '_bx_tasks_grid_action_title_tm_delete', '', 0, 1, 2),
 
-('bx_tasks_time', 'independent', 'add', '_bx_tasks_grid_action_title_tm_add', '', 0, 0, 1),
-('bx_tasks_time', 'bulk', 'calculate', '_bx_tasks_grid_action_title_tm_calculate', '', 0, 0, 1),
-('bx_tasks_time', 'bulk', 'delete', '_bx_tasks_grid_action_title_tm_delete', '', 0, 1, 2),
-('bx_tasks_time', 'single', 'edit', '_bx_tasks_grid_action_title_tm_edit', 'pencil-alt', 1, 0, 1),
-('bx_tasks_time', 'single', 'delete', '_bx_tasks_grid_action_title_tm_delete', 'remove', 1, 1, 2);
+('bx_tasks_time_common', 'bulk', 'calculate', '_bx_tasks_grid_action_title_tm_calculate', '', 0, 0, 1),
+('bx_tasks_time_common', 'bulk', 'delete', '_bx_tasks_grid_action_title_tm_delete', '', 0, 1, 2),
+
+('bx_tasks_time_context_administration', 'bulk', 'calculate', '_bx_tasks_grid_action_title_tm_calculate', '', 0, 0, 1),
+('bx_tasks_time_context_administration', 'bulk', 'delete', '_bx_tasks_grid_action_title_tm_delete', '', 0, 1, 2),
+
+('bx_tasks_time_context_common', 'independent', 'add', '_bx_tasks_grid_action_title_tm_add', '', 0, 0, 1),
+('bx_tasks_time_context_common', 'bulk', 'calculate', '_bx_tasks_grid_action_title_tm_calculate', '', 0, 0, 1),
+('bx_tasks_time_context_common', 'bulk', 'delete', '_bx_tasks_grid_action_title_tm_delete', '', 0, 1, 2),
+('bx_tasks_time_context_common', 'single', 'edit', '_bx_tasks_grid_action_title_tm_edit', 'pencil-alt', 1, 0, 1),
+('bx_tasks_time_context_common', 'single', 'delete', '_bx_tasks_grid_action_title_tm_delete', 'remove', 1, 1, 2);
 
 -- UPLOADERS
 

+ 22 - 0
modules/boonex/tasks/js/manage_tools.js

@@ -17,4 +17,26 @@ function BxTasksManageTools(oOptions)
 BxTasksManageTools.prototype = Object.create(BxBaseModTextManageTools.prototype);
 BxTasksManageTools.prototype.constructor = BxTasksManageTools;
 
+BxTasksManageTools.prototype.onChangeFilter = function(oFilter) {
+    var $this = this;
+    var oFilter1 = $('#bx-grid-filter1-' + this._sObjNameGrid);
+    var sValueFilter1 = oFilter1.length > 0 ? oFilter1.val() : '';
+
+    var oFilter2 = $('#bx-grid-filter2-' + this._sObjNameGrid);
+    var sValueFilter2 = oFilter2.length > 0 ? oFilter2.val() : '';
+    
+    var oFilter3 = $('#bx-grid-filter3-' + this._sObjNameGrid);
+    var sValueFilter3 = oFilter3.length > 0 ? oFilter3.val() : '';
+
+    var oSearch = $('#bx-grid-search-' + this._sObjNameGrid);
+    var sValueSearch = oSearch.length > 0 ? oSearch.val() : '';
+    if(sValueSearch == _t('_sys_grid_search'))
+        sValueSearch = '';
+
+    clearTimeout($this._iSearchTimeoutId);
+    $this._iSearchTimeoutId = setTimeout(function () {
+        glGrids[$this._sObjNameGrid].setFilter(sValueFilter1 + $this._sParamsDivider + sValueFilter2 + $this._sParamsDivider + sValueFilter3 + $this._sParamsDivider + sValueSearch, true);
+    }, 500);
+};
+
 /** @} */