RomanL před 8 roky
rodič
revize
d7ce553be8

+ 62 - 61
modules/boonex/analytics/classes/BxAnalyticsDb.php

@@ -1,68 +1,69 @@
 <?php defined('BX_DOL') or die('hack attempt');
-      /**
-       * Copyright (c) UNA, Inc - https://una.io
-       * MIT License - https://opensource.org/licenses/MIT
-       *
-       * @defgroup    Analytics Analytics
-       * @ingroup     UnaModules
-       *
-       * @{
-       */
+/**
+* Copyright (c) UNA, Inc - https://una.io
+* MIT License - https://opensource.org/licenses/MIT
+*
+* @defgroup    Analytics Analytics
+* @ingroup     UnaModules
+*
+* @{
+*/
 
-      bx_import('BxDolModuleDb');
-
-      class BxAnalyticsDb extends BxBaseModGeneralDb
-      {
-          public function getGrowth($sTableName, $sColumnAdded, $iDateFrom, $iDateTo)
-          {
-              $aBindings = array(
-                  'datefrom' => $iDateFrom,
-                  'dateto' => $iDateTo
-              );
-              $sQuery = "SELECT DATE(FROM_UNIXTIME(`" . $sColumnAdded . "`))  AS `period`, YEAR(FROM_UNIXTIME(`" . $sColumnAdded . "`))  AS `year`,  COUNT(*) AS `count` FROM " . $sTableName . " WHERE `" . $sColumnAdded . "` >= :datefrom AND `" . $sColumnAdded . "` <= :dateto   GROUP BY `period`, `year` ORDER BY `year`, `period` ASC";
-              return $this->getAll($sQuery, $aBindings);
-          }
+/*
+ * Module database queries
+ */
+class BxAnalyticsDb extends BxBaseModGeneralDb
+{
+    public function getGrowth($sTableName, $sColumnAdded, $iDateFrom, $iDateTo)
+    {
+        $aBindings = array(
+            'datefrom' => $iDateFrom,
+            'dateto' => $iDateTo
+        );
+        $sQuery = "SELECT DATE(FROM_UNIXTIME(`" . $sColumnAdded . "`))  AS `period`, YEAR(FROM_UNIXTIME(`" . $sColumnAdded . "`))  AS `year`,  COUNT(*) AS `count` FROM " . $sTableName . " WHERE `" . $sColumnAdded . "` >= :datefrom AND `" . $sColumnAdded . "` <= :dateto   GROUP BY `period`, `year` ORDER BY `year`, `period` ASC";
+        return $this->getAll($sQuery, $aBindings);
+    }
           
-          public function getGrowthInitValue($sTableName, $sColumnAdded, $iDateFrom)
-          {
-              $aBindings = array(
-                  'datefrom' => $iDateFrom
-              );
-              $sQuery = "SELECT  COUNT(*) AS `count` FROM " . $sTableName . " WHERE `" . $sColumnAdded . "` < :datefrom ";
-              return $this->getOne($sQuery, $aBindings);
-          }
+    public function getGrowthInitValue($sTableName, $sColumnAdded, $iDateFrom)
+    {
+        $aBindings = array(
+            'datefrom' => $iDateFrom
+        );
+        $sQuery = "SELECT  COUNT(*) AS `count` FROM " . $sTableName . " WHERE `" . $sColumnAdded . "` < :datefrom ";
+        return $this->getOne($sQuery, $aBindings);
+    }
           
-          public function getTopContentByLikes($sModuleName, $sTableName, $iDateFrom, $iDateTo)
-          {
-              $aBindings = array(
-                  'datefrom' => $iDateFrom,
-                  'dateto' => $iDateTo
-              );
-              $sQuery = "SELECT `object_id`,'" . $sModuleName . "' AS `module`, COUNT(*) AS `value` FROM `" . $sTableName . "` WHERE `date` >= :datefrom  AND `date` <= :dateto GROUP BY `object_id` ORDER BY  COUNT(*) DESC LIMIT 0, " . intval(getParam('bx_analytics_items_count'));
-              return $this->getAll($sQuery, $aBindings);
-          }
+    public function getTopContentByLikes($sModuleName, $sTableName, $iDateFrom, $iDateTo)
+    {
+        $aBindings = array(
+            'datefrom' => $iDateFrom,
+            'dateto' => $iDateTo
+        );
+        $sQuery = "SELECT `object_id`,'" . $sModuleName . "' AS `module`, COUNT(*) AS `value` FROM `" . $sTableName . "` WHERE `date` >= :datefrom  AND `date` <= :dateto GROUP BY `object_id` ORDER BY  COUNT(*) DESC LIMIT 0, " . intval(getParam('bx_analytics_items_count'));
+        return $this->getAll($sQuery, $aBindings);
+    }
           
-          public function getMostFollowedProfiles($sModuleName, $iDateFrom, $iDateTo)
-          {
-              $aBindings = array(
-                  'datefrom' => $iDateFrom,
-                  'dateto' => $iDateTo
-              );
-              $sQuery = "SELECT `sys_profiles`.`content_id` AS `object_id`, `sys_profiles`.`type` , COUNT(`sys_profiles_conn_subscriptions`.`id`) AS `value` FROM `sys_profiles_conn_subscriptions`
-  INNER JOIN `sys_profiles`  ON `sys_profiles`.`id` = `sys_profiles_conn_subscriptions`.`content` WHERE sys_profiles.type='" . $sModuleName . "' AND  `sys_profiles_conn_subscriptions`.`added` >= :datefrom AND  `sys_profiles_conn_subscriptions`.`added` <= :dateto GROUP BY `sys_profiles`.`content_id`, `sys_profiles`.`type` ORDER BY COUNT(`sys_profiles_conn_subscriptions`.`id`) DESC LIMIT 0," . intval(getParam('bx_analytics_items_count'));
-              return $this->getAll($sQuery, $aBindings);
-          }
+    public function getMostFollowedProfiles($sModuleName, $iDateFrom, $iDateTo)
+    {
+        $aBindings = array(
+            'datefrom' => $iDateFrom,
+            'dateto' => $iDateTo
+        );
+        $sQuery = "SELECT `sys_profiles`.`content_id` AS `object_id`, `sys_profiles`.`type` , COUNT(`sys_profiles_conn_subscriptions`.`id`) AS `value` FROM `sys_profiles_conn_subscriptions`
+INNER JOIN `sys_profiles`  ON `sys_profiles`.`id` = `sys_profiles_conn_subscriptions`.`content` WHERE sys_profiles.type='" . $sModuleName . "' AND  `sys_profiles_conn_subscriptions`.`added` >= :datefrom AND  `sys_profiles_conn_subscriptions`.`added` <= :dateto GROUP BY `sys_profiles`.`content_id`, `sys_profiles`.`type` ORDER BY COUNT(`sys_profiles_conn_subscriptions`.`id`) DESC LIMIT 0," . intval(getParam('bx_analytics_items_count'));
+        return $this->getAll($sQuery, $aBindings);
+    }
           
-          public function getMostActiveProfiles($sModuleName, $sContentModuleName, $sTableName, $sColumnAuthor, $sColumnAdded, $iDateFrom, $iDateTo)
-          {
-              $aBindings = array(
-                  'datefrom' => $iDateFrom,
-                  'dateto' => $iDateTo
-              );
-              $sQuery = "SELECT `sys_profiles`.`content_id`  AS `object_id`, `sys_profiles`.`type`, '" . $sContentModuleName . "' , COUNT(`" . $sTableName . "`.`id`) AS `value` FROM `" . $sTableName . "`
-  INNER JOIN `sys_profiles`  ON `sys_profiles`.`id` = `" . $sTableName . "`.`" . $sColumnAuthor . "` WHERE sys_profiles.type='" . $sModuleName . "' AND  `" . $sTableName . "`.`" . $sColumnAdded . "` >= :datefrom AND `" . $sTableName . "`.`" . $sColumnAdded . "` <= :dateto GROUP BY `sys_profiles`.`content_id`, `sys_profiles`.`type` ORDER BY COUNT(`" . $sTableName . "`.`id`) DESC LIMIT 0," . intval(getParam('bx_analytics_items_count'));
-              return $this->getAll($sQuery, $aBindings);
-          }
-      }
+    public function getMostActiveProfiles($sModuleName, $sContentModuleName, $sTableName, $sColumnAuthor, $sColumnAdded, $iDateFrom, $iDateTo)
+    {
+        $aBindings = array(
+            'datefrom' => $iDateFrom,
+            'dateto' => $iDateTo
+        );
+        $sQuery = "SELECT `sys_profiles`.`content_id`  AS `object_id`, `sys_profiles`.`type`, '" . $sContentModuleName . "' , COUNT(`" . $sTableName . "`.`id`) AS `value` FROM `" . $sTableName . "`
+INNER JOIN `sys_profiles`  ON `sys_profiles`.`id` = `" . $sTableName . "`.`" . $sColumnAuthor . "` WHERE sys_profiles.type='" . $sModuleName . "' AND  `" . $sTableName . "`.`" . $sColumnAdded . "` >= :datefrom AND `" . $sTableName . "`.`" . $sColumnAdded . "` <= :dateto GROUP BY `sys_profiles`.`content_id`, `sys_profiles`.`type` ORDER BY COUNT(`" . $sTableName . "`.`id`) DESC LIMIT 0," . intval(getParam('bx_analytics_items_count'));
+        return $this->getAll($sQuery, $aBindings);
+    }
+}
 
-      /** @} */
+/** @} */

+ 407 - 321
modules/boonex/analytics/classes/BxAnalyticsModule.php

@@ -1,352 +1,438 @@
 <?php defined('BX_DOL') or die('hack attempt');
-      /**
-       * Copyright (c) UNA, Inc - https://una.io
-       * MIT License - https://opensource.org/licenses/MIT
-       *
-       * @defgroup    Analytics Analytics
-       * @ingroup     UnaModules
-       *
-       * @{
-       */
-      
-      define('BX_ANALYTICS_SYSTEM', 'system');
-      define('BX_ANALYTICS_TOP_BY_LIKES', 'top_by_likes');
-      define('BX_ANALYTICS_TOP_BY_VIEWS', 'top_by_views');
-      define('BX_ANALYTICS_CONTENT_TOTAL', 'content_total');
-      define('BX_ANALYTICS_CONTENT_SPEED', 'content_speed');
-      define('BX_ANALYTICS_MOST_FOLLOWED_PROFILES', 'top_by_followers');
-      define('BX_ANALYTICS_MOST_ACTIVE_PROFILES', 'top_by_activity');
+/**
+* Copyright (c) UNA, Inc - https://una.io
+* MIT License - https://opensource.org/licenses/MIT
+*
+* @defgroup    Analytics Analytics
+* @ingroup     UnaModules
+*
+* @{
+*/
 
-      class BxAnalyticsModule extends BxDolModule
-      {
-          protected $aColors = array('#3366CC', '#DC3912', '#FF9900', '#109618', '#990099');
+/**
+ * Analytics module
+ */     
+define('BX_ANALYTICS_SYSTEM', 'system');
+define('BX_ANALYTICS_TOP_BY_LIKES', 'top_by_likes');
+define('BX_ANALYTICS_TOP_BY_VIEWS', 'top_by_views');
+define('BX_ANALYTICS_CONTENT_TOTAL', 'content_total');
+define('BX_ANALYTICS_CONTENT_SPEED', 'content_speed');
+define('BX_ANALYTICS_MOST_FOLLOWED_PROFILES', 'top_by_followers');
+define('BX_ANALYTICS_MOST_ACTIVE_PROFILES', 'top_by_activity');
+class BxAnalyticsModule extends BxDolModule
+{
+    protected $aColors = array('#3366CC', '#DC3912', '#FF9900', '#109618', '#990099');
           
-          function __construct(&$aModule)
-          {
-              parent::__construct($aModule);
-          }
+    function __construct(&$aModule)
+    {
+        parent::__construct($aModule);
+    }
           
-          /**
-           * Service methods
-           */
+    /**
+    * Service methods
+    */
           
-          /**
-           * @page service Service Calls
-           * @section bx_analytics Analytics
-           * @subsection bx_analytics-other Other
-           * @subsubsection bx_analytics get_canvas
-           * 
-           * @code bx_srv('bx_analytics', 'get_canvas', [...]); @endcode
-           * 
-           * Get canvas  
-           * 
-           * @return an html. 
-           * 
-           * @see BxAnalyticsModule::serviceGetCanvas
-           */
-          /** 
-           * @ref bx_analytics-get_canvas "get_canvas"
-           */
-          public function serviceGetCanvas()
-          {
-              return $this->_oTemplate->getCanvas();
-          }
+    /**
+    * @page service Service Calls
+    * @section bx_analytics Analytics
+    * @subsection bx_analytics-other Other
+    * @subsubsection bx_analytics get_canvas
+    * 
+    * @code bx_srv('bx_analytics', 'get_canvas', [...]); @endcode
+    * 
+    * Get canvas  
+    * 
+    * @return an html. 
+    * 
+    * @see BxAnalyticsModule::serviceGetCanvas
+    */
+    /** 
+    * @ref bx_analytics-get_canvas "get_canvas"
+    */
+    public function serviceGetCanvas()
+    {
+        return $this->_oTemplate->getCanvas();
+    }
           
-          /**
-           * @page service Service Calls
-           * @section bx_analytics Analytics
-           * @subsection bx_analytics-other Other
-           * @subsubsection bx_analytics get_modules
-           * 
-           * @code bx_srv('bx_analytics', 'get_modules', [...]); @endcode
-           * 
-           * Get modules list  
-           * 
-           * @return an html. 
-           * 
-           * @see BxAnalyticsModule::serviceGetModules
-           */
-          /** 
-           * @ref bx_analytics-get_modules "get_modules"
-           */
-          public function serviceGetModules()
-          {
-              $aResult = array();
-              $aResult2 = array();
-              $aResult[BX_ANALYTICS_SYSTEM] = _t('_bx_analytics_system_text');
-              $BxDolModuleQuery = BxDolModuleQuery::getInstance();
-              $aModules = $BxDolModuleQuery->getModulesBy(array('type' => 'modules', 'active' => 1));
-              foreach($aModules as $aModule){
-                  $oModule = BxDolModule::getInstance($aModule['name']);
-                  if($oModule instanceof iBxDolContentInfoService){
-                      $aResult[$aModule['name']] = $aModule['title'];
-                  }
-              }
-              return array_merge($aResult, $aResult2);
-          }
+    /**
+    * @page service Service Calls
+    * @section bx_analytics Analytics
+    * @subsection bx_analytics-other Other
+    * @subsubsection bx_analytics get_modules
+    * 
+    * @code bx_srv('bx_analytics', 'get_modules', [...]); @endcode
+    * 
+    * Get modules list  
+    * 
+    * @return an html. 
+    * 
+    * @see BxAnalyticsModule::serviceGetModules
+    */
+    /** 
+    * @ref bx_analytics-get_modules "get_modules"
+    */
+    public function serviceGetModules()
+    {
+        $aResult = array();
+        $aResult2 = array();
+        $aResult[BX_ANALYTICS_SYSTEM] = _t('_bx_analytics_system_text');
+        $BxDolModuleQuery = BxDolModuleQuery::getInstance();
+        $aModules = $BxDolModuleQuery->getModulesBy(array('type' => 'modules', 'active' => 1));
+        foreach($aModules as $aModule){
+            $oModule = BxDolModule::getInstance($aModule['name']);
+            if($oModule instanceof iBxDolContentInfoService){
+                $aResult[$aModule['name']] = $aModule['title'];
+            }
+        }
+        return array_merge($aResult, $aResult2);
+    }
           
-           /**
-           * Action methods
-           */
+    /**
+    * Action methods
+    */
           
-          public function actionGetReports($sModuleName)
-          {
-              header('Content-Type: application/json');
+    public function actionGetReports($sModuleName)
+    {
+        if(!BxDolAcl::getInstance()->isMemberLevelInSet(192))
+            return '';
+            
+        header('Content-Type: application/json');
              
-              $aSystemsVote = BxDolVote::getSystems();
-              $aRv = array();
-              if ($sModuleName == BX_ANALYTICS_SYSTEM){
-                  $aRv[BX_ANALYTICS_TOP_BY_LIKES] = _t('_bx_analytics_type_top_contents_by_likes');
-                  $aRv[BX_ANALYTICS_TOP_BY_VIEWS] = _t('_bx_analytics_type_top_by_views');
-                  $aRv[BX_ANALYTICS_CONTENT_TOTAL] = _t('_bx_analytics_type_accounts_growth');
-                  $aRv[BX_ANALYTICS_CONTENT_SPEED] = _t('_bx_analytics_type_accounts_speed');
-              }
-              else{
-                  $oModule = BxDolModule::getInstance($sModuleName);
+        $aSystemsVote = BxDolVote::getSystems();
+        $aRv = array();
+        if ($sModuleName == BX_ANALYTICS_SYSTEM){
+            $aRv[BX_ANALYTICS_TOP_BY_LIKES] = _t('_bx_analytics_type_top_contents_by_likes');
+            $aRv[BX_ANALYTICS_TOP_BY_VIEWS] = _t('_bx_analytics_type_top_by_views');
+            $aRv[BX_ANALYTICS_CONTENT_TOTAL] = _t('_bx_analytics_type_accounts_growth');
+            $aRv[BX_ANALYTICS_CONTENT_SPEED] = _t('_bx_analytics_type_accounts_speed');
+        }
+        else{
+            $oModule = BxDolModule::getInstance($sModuleName);
                   
-                  if(BxDolRequest::serviceExists($sModuleName, 'act_as_profile') && BxDolService::call($sModuleName, 'act_as_profile') == true){
-                      $aRv[BX_ANALYTICS_MOST_FOLLOWED_PROFILES] = _t('_bx_analytics_type_most_followed_profiles');
-                      $aRv[BX_ANALYTICS_MOST_ACTIVE_PROFILES] = _t('_bx_analytics_type_most_active_profiles');
-                  }
+            if(BxDolRequest::serviceExists($sModuleName, 'act_as_profile') && BxDolService::call($sModuleName, 'act_as_profile') == true){
+                $aRv[BX_ANALYTICS_MOST_FOLLOWED_PROFILES] = _t('_bx_analytics_type_most_followed_profiles');
+                $aRv[BX_ANALYTICS_MOST_ACTIVE_PROFILES] = _t('_bx_analytics_type_most_active_profiles');
+            }
                   
-                  if(isset($oModule->_oConfig->CNF['OBJECT_VOTES']) && isset($aSystemsVote[$oModule->_oConfig->CNF['OBJECT_VOTES']])){
-                      $aRv[BX_ANALYTICS_TOP_BY_LIKES] = _t('_bx_analytics_type_top_contents_by_likes');
-                  }
+            if(isset($oModule->_oConfig->CNF['OBJECT_VOTES']) && isset($aSystemsVote[$oModule->_oConfig->CNF['OBJECT_VOTES']])){
+                $aRv[BX_ANALYTICS_TOP_BY_LIKES] = _t('_bx_analytics_type_top_contents_by_likes');
+            }
                   
-                  if(isset($oModule->_oConfig->CNF['OBJECT_VIEWS'])){
-                      $aRv[BX_ANALYTICS_TOP_BY_VIEWS] = _t('_bx_analytics_type_top_by_views');
-                  }
+            if(isset($oModule->_oConfig->CNF['OBJECT_VIEWS'])){
+                $aRv[BX_ANALYTICS_TOP_BY_VIEWS] = _t('_bx_analytics_type_top_by_views');
+            }
                   
-                  $aRv[BX_ANALYTICS_CONTENT_TOTAL] = _t('_bx_analytics_type_content_growth');
-                  $aRv[BX_ANALYTICS_CONTENT_SPEED] = _t('_bx_analytics_type_content_speed');
-              }
-              echo json_encode($aRv);
-          }
+            $aRv[BX_ANALYTICS_CONTENT_TOTAL] = _t('_bx_analytics_type_content_growth');
+            $aRv[BX_ANALYTICS_CONTENT_SPEED] = _t('_bx_analytics_type_content_speed');
+        }
+        echo json_encode($aRv);
+    }
           
-          public function actionGetReportsData($sModuleName, $sReportName, $sDateFrom, $sDateTo)
-          {
-              header('Content-Type: application/json');
+    public function actionGetReportsData($sModuleName, $sReportName, $sDateFrom, $sDateTo)
+    {
+        if(!BxDolAcl::getInstance()->isMemberLevelInSet(192))
+            return '';
+        
+        header('Content-Type: application/json');
               
-              $iDateFrom = strtotime($sDateFrom);
-              $iDateTo = strtotime($sDateTo);
-              $sType = "bar";
-              $bIsTimeX = false;
-              $iMinValueY = 0;
-              $iMaxValueY = 0;
-              $bDefaultFillData = true;
-              $aValues = array('labels' => array(), 'values' => array(array('legend' => '', 'data' => array())), 'links' => array(), 'strings' => array(0 => _t('_bx_analytics_txt_item'), 1 => _t('_bx_analytics_txt_value')));
+        $iDateFrom = strtotime($sDateFrom);
+        $iDateTo = strtotime($sDateTo);
+        $sType = "bar";
+        $bIsTimeX = false;
+        $iMinValueY = 0;
+        $iMaxValueY = 0;
+        $bDefaultFillData = true;
+        $aValues = array('labels' => array(), 'values' => array(array('legend' => '', 'data' => array())), 'links' => array(), 'strings' => array(0 => _t('_bx_analytics_txt_item'), 1 => _t('_bx_analytics_txt_value')));
    
-              if ($sModuleName != BX_ANALYTICS_SYSTEM){
-                  $oModule = BxDolModule::getInstance($sModuleName);
-                  $aValues['strings'][0] = $oModule->_aModule['title'];
-                  $aValues['strings'][1] = _t('_bx_analytics_type_' . $sReportName . '_label');
-              }
-              else{
-                  $aValues['strings'][0] = _t('_bx_analytics_txt_total_content');
-                  $aValues['strings'][1] = _t('_bx_analytics_type_' . $sReportName . '_label');
-              }
+        if ($sModuleName != BX_ANALYTICS_SYSTEM){
+            $oModule = BxDolModule::getInstance($sModuleName);
+            $aValues['strings'][0] = $oModule->_aModule['title'];
+            $aValues['strings'][1] = _t('_bx_analytics_type_' . $sReportName . '_label');
+        }
+        else{
+            $aValues['strings'][0] = _t('_bx_analytics_txt_total_content');
+            $aValues['strings'][1] = _t('_bx_analytics_type_' . $sReportName . '_label');
+        }
               
-              switch ($sReportName) {
-                  case BX_ANALYTICS_CONTENT_TOTAL:
-                  case BX_ANALYTICS_CONTENT_SPEED:
-                      $sType = "line";
-                      $bIsTimeX = true;
-                      $sTableName = '';
-                      $aValues['strings'][0] = _t('_bx_analytics_txt_date');
-                      $bDefaultFillData = false;
-                      if ($sModuleName != BX_ANALYTICS_SYSTEM){
-                          $oModule = BxDolModule::getInstance($sModuleName);
-                          if (isset($oModule->_oConfig->CNF['TABLE_ENTRIES']))
-                              $sTableName = $oModule->_oConfig->CNF['TABLE_ENTRIES'];
-                          $aValues['strings'][1] = $oModule->_aModule['title'] . ($sReportName == BX_ANALYTICS_CONTENT_TOTAL ? _t('_bx_analytics_txt_total_count') : _t('_bx_analytics_txt_count'));
-                      }
-                      else{
-                          $sTableName = 'sys_accounts';
-                          $aValues['strings'][1] = _t('_bx_analytics_txt_accounts') . ($sReportName == BX_ANALYTICS_CONTENT_TOTAL ? _t('_bx_analytics_txt_total_count') : _t('_bx_analytics_txt_count'));
-                      }
-                      if (isset($oModule) && isset($oModule->_oConfig->CNF['FIELD_ADDED']))
-                          $sColumnAdded = $oModule->_oConfig->CNF['FIELD_ADDED'];
-                      else
-                          $sColumnAdded = 'added';
-                      if ($sColumnAdded != ''){
-                          $aData = $this->_oDb->getGrowth($sTableName, $sColumnAdded, $iDateFrom, $iDateTo);
-                          $iValuePrev = $this->_oDb->getGrowthInitValue($sTableName, $sColumnAdded, $iDateFrom);
-                          $aTmpDates = array();
-                          foreach ($aData as $aValue) {
-                              $sX = $aValue['period'];
-                              $aTmpDates[$sX] = $aValue['count'];
-                          }
-                          for ($i = $iDateFrom; $i < $iDateTo ; $i = $i + 86400 ){
-                              $sX = date('Y-m-d', $i);
-                              if (!array_key_exists($sX, $aTmpDates)){
-                                array_push($aValues['values'][0]['data'], array('x' => $sX, 'y' => $sReportName == BX_ANALYTICS_CONTENT_TOTAL ? $iValuePrev : 0));
-                              }
-                              else{
-                                  array_push($aValues['values'][0]['data'], array('x' => $sX, 'y' => $sReportName == BX_ANALYTICS_CONTENT_TOTAL ? $iValuePrev : $aTmpDates[$sX]));
-                                  $iValuePrev += $aTmpDates[$sX];
-                              }
-                              if ($sReportName == BX_ANALYTICS_CONTENT_TOTAL){
-                                  if ($iValuePrev > $iMaxValueY)
-                                      $iMaxValueY = $iValuePrev;
-                              }
-                              else{
-                                  if (array_key_exists($sX, $aTmpDates) && $aTmpDates[$sX] > $iMaxValueY)
-                                      $iMaxValueY = $aTmpDates[$sX];
-                              }
-                          }
-                      }
-                      break;
+        switch ($sReportName) {
+            case BX_ANALYTICS_CONTENT_TOTAL:
+            case BX_ANALYTICS_CONTENT_SPEED:
+                $sType = "line";
+                $bIsTimeX = true;
+                $sTableName = '';
+                $aValues['strings'][0] = _t('_bx_analytics_txt_date');
+                $bDefaultFillData = false;
+                if ($sModuleName != BX_ANALYTICS_SYSTEM){
+                    $oModule = BxDolModule::getInstance($sModuleName);
+                    if (isset($oModule->_oConfig->CNF['TABLE_ENTRIES']))
+                        $sTableName = $oModule->_oConfig->CNF['TABLE_ENTRIES'];
+                    $aValues['strings'][1] = ($sReportName == BX_ANALYTICS_CONTENT_TOTAL ? _t('_bx_analytics_txt_total_count', $oModule->_aModule['title']) : _t('_bx_analytics_txt_count', $oModule->_aModule['title']));
+                }
+                else{
+                    $sTableName = 'sys_accounts';
+                    $aValues['strings'][1] = ($sReportName == BX_ANALYTICS_CONTENT_TOTAL ? _t('_bx_analytics_txt_total_count', _t('_bx_analytics_txt_accounts')) : _t('_bx_analytics_txt_count', _t('_bx_analytics_txt_accounts')));
+                }
+                if (isset($oModule) && isset($oModule->_oConfig->CNF['FIELD_ADDED']))
+                    $sColumnAdded = $oModule->_oConfig->CNF['FIELD_ADDED'];
+                else
+                    $sColumnAdded = 'added';
+                if ($sColumnAdded != ''){
+                    $aData = $this->_oDb->getGrowth($sTableName, $sColumnAdded, $iDateFrom, $iDateTo);
+                    $iValuePrev = $this->_oDb->getGrowthInitValue($sTableName, $sColumnAdded, $iDateFrom);
+                    $aTmpDates = array();
+                    foreach ($aData as $aValue) {
+                        $sX = $aValue['period'];
+                        $aTmpDates[$sX] = $aValue['count'];
+                    }
+                    for ($i = $iDateFrom; $i < $iDateTo ; $i = $i + 86400 ){
+                        $sX = date('Y-m-d', $i);
+                        if (!array_key_exists($sX, $aTmpDates)){
+                        array_push($aValues['values'][0]['data'], array('x' => $sX, 'y' => $sReportName == BX_ANALYTICS_CONTENT_TOTAL ? $iValuePrev : 0));
+                        }
+                        else{
+                            array_push($aValues['values'][0]['data'], array('x' => $sX, 'y' => $sReportName == BX_ANALYTICS_CONTENT_TOTAL ? $iValuePrev : $aTmpDates[$sX]));
+                            $iValuePrev += $aTmpDates[$sX];
+                        }
+                        if ($sReportName == BX_ANALYTICS_CONTENT_TOTAL){
+                            if ($iValuePrev > $iMaxValueY)
+                                $iMaxValueY = $iValuePrev;
+                        }
+                        else{
+                            if (array_key_exists($sX, $aTmpDates) && $aTmpDates[$sX] > $iMaxValueY)
+                                $iMaxValueY = $aTmpDates[$sX];
+                        }
+                    }
+                }
+                break;
                   
-                  case BX_ANALYTICS_TOP_BY_LIKES:
-                      $bDefaultFillData = false;
-                      $sRv = $this->getViewsOrVotes(BxDolVote::getSystems(), 'OBJECT_VOTES', $sModuleName, $iDateFrom, $iDateTo, $aValues, $iMaxValueY, $iMinValueY);
-                      break;
+            case BX_ANALYTICS_TOP_BY_LIKES:
+                $bDefaultFillData = false;
+                $sRv = $this->getViewsOrVotes(BxDolVote::getSystems(), 'OBJECT_VOTES', $sModuleName, $iDateFrom, $iDateTo, $aValues, $iMaxValueY, $iMinValueY);
+                break;
                   
-                  case BX_ANALYTICS_TOP_BY_VIEWS:
-                      $bDefaultFillData = false;
-                      $sRv = $this->getViewsOrVotes(BxDolView::getSystems(), 'OBJECT_VIEWS', $sModuleName, $iDateFrom, $iDateTo, $aValues, $iMaxValueY, $iMinValueY);
-                      break;
+            case BX_ANALYTICS_TOP_BY_VIEWS:
+                $bDefaultFillData = false;
+                $sRv = $this->getViewsOrVotes(BxDolView::getSystems(), 'OBJECT_VIEWS', $sModuleName, $iDateFrom, $iDateTo, $aValues, $iMaxValueY, $iMinValueY);
+                break;
                   
-                  case BX_ANALYTICS_MOST_FOLLOWED_PROFILES:
-                      $oModule = BxDolModule::getInstance($sModuleName);
-                      $aData = $this->_oDb->getMostFollowedProfiles($sModuleName, $iDateFrom, $iDateTo);
-                      break;
+            case BX_ANALYTICS_MOST_FOLLOWED_PROFILES:
+                $oModule = BxDolModule::getInstance($sModuleName);
+                $aData = $this->_oDb->getMostFollowedProfiles($sModuleName, $iDateFrom, $iDateTo);
+                break;
                   
-                  case BX_ANALYTICS_MOST_ACTIVE_PROFILES:
-                      $aData = array();
-                      $oModule = BxDolModule::getInstance($sModuleName);
-                      $aTmp = $this->getSelectedModules();
-                      foreach($aTmp[0] as $sContentModule){
-                          $oContentModule = BxDolModule::getInstance($sContentModule);
-                          if ($oContentModule && isset($oContentModule->_oConfig->CNF['TABLE_ENTRIES']) && isset($oContentModule->_oConfig->CNF['FIELD_AUTHOR'])){
-                              $sContentTable = $oContentModule->_oConfig->CNF['TABLE_ENTRIES'];
-                              $sColumnAuthor = $oContentModule->_oConfig->CNF['FIELD_AUTHOR'];
-                              $sColumnAdded = $oContentModule->_oConfig->CNF['FIELD_ADDED'];
-                              if (!empty($sContentTable) && !empty($sColumnAuthor) && !empty($sColumnAdded) && (!BxDolRequest::serviceExists($sContentModule, 'act_as_profile') || BxDolService::call($sContentModule, 'act_as_profile') == false)){
-                                  $aData1 = $this->_oDb->getMostActiveProfiles($sModuleName, $sContentModule, $sContentTable, $sColumnAuthor, $sColumnAuthor, $sColumnAdded, $iDateFrom, $iDateTo);
-                                  foreach($aData1 as $aTmp3){
-                                      if (array_key_exists($aTmp3['object_id'], $aData))
-                                          $aData[$aTmp3['object_id']]['value'] += $aTmp3['value'];
-                                      else
-                                          $aData[$aTmp3['object_id']] = $aTmp3;
-                                  }
-                              }
-                          }
-                      }
-                      $aData = $this->sortArrayOfArraysAndSlice($aData, 'value', intval(getParam('bx_analytics_items_count')));
-                      break;
-              }
+            case BX_ANALYTICS_MOST_ACTIVE_PROFILES:
+                $aData = array();
+                $oModule = BxDolModule::getInstance($sModuleName);
+                $aTmp = $this->getSelectedModules();
+                foreach($aTmp[0] as $sContentModule){
+                    $oContentModule = BxDolModule::getInstance($sContentModule);
+                    if ($oContentModule && isset($oContentModule->_oConfig->CNF['TABLE_ENTRIES']) && isset($oContentModule->_oConfig->CNF['FIELD_AUTHOR'])){
+                        $sContentTable = $oContentModule->_oConfig->CNF['TABLE_ENTRIES'];
+                        $sColumnAuthor = $oContentModule->_oConfig->CNF['FIELD_AUTHOR'];
+                        $sColumnAdded = $oContentModule->_oConfig->CNF['FIELD_ADDED'];
+                        if (!empty($sContentTable) && !empty($sColumnAuthor) && !empty($sColumnAdded) && (!BxDolRequest::serviceExists($sContentModule, 'act_as_profile') || BxDolService::call($sContentModule, 'act_as_profile') == false)){
+                            $aData1 = $this->_oDb->getMostActiveProfiles($sModuleName, $sContentModule, $sContentTable, $sColumnAuthor, $sColumnAuthor, $sColumnAdded, $iDateFrom, $iDateTo);
+                            foreach($aData1 as $aTmp3){
+                                if (array_key_exists($aTmp3['object_id'], $aData))
+                                    $aData[$aTmp3['object_id']]['value'] += $aTmp3['value'];
+                                else
+                                    $aData[$aTmp3['object_id']] = $aTmp3;
+                            }
+                        }
+                    }
+                }
+                $aData = $this->sortArrayOfArraysAndSlice($aData, 'value', intval(getParam('bx_analytics_items_count')));
+                break;
+        }
               
-              if ($bDefaultFillData){
-                  foreach ($aData as $aValue) {
-                      array_push($aValues['labels'], $this->getItemName($oModule->serviceGetTitle($aValue['object_id'])));
-                      array_push($aValues['values'][0]['data'], $aValue['value']);
-                      array_push($aValues['links'], $oModule->serviceGetLink($aValue['object_id']));
-                      if ($aValue['value'] > $iMaxValueY)
-                          $iMaxValueY = $aValue['value'];
-                  }
-              }
-              
-              $sRv = '{"type": "' . $sType . '", "data": {"labels":' . json_encode($aValues['labels']) . ',"datasets": [';
-              for($i = 0; $i < count($aValues['values']); $i++){
-                  $sRv .= '{"label": "' . $aValues['values'][$i]['legend'] . '", "fill": false, "backgroundColor": "' . $this->aColors[$i] . '","borderColor": "' . $this->aColors[$i] . '","borderWidth": 1,"data": ' . json_encode($aValues['values'][$i]['data']) . '}';
-                  if ($i != count($aValues['values']) - 1)
-                      $sRv .= ',';
-              }
-              $sRv .= ']}, "options": {"legend": {"position": "bottom" ' . (count($aValues['values']) == 1 ? ', "display": false' : '') . '}, "scales": {';
+        if ($bDefaultFillData){
+            foreach ($aData as $aValue) {
+                array_push($aValues['labels'], $this->getItemName($oModule->serviceGetTitle($aValue['object_id'])));
+                array_push($aValues['values'][0]['data'], $aValue['value']);
+                array_push($aValues['links'], $oModule->serviceGetLink($aValue['object_id']));
+                if ($aValue['value'] > $iMaxValueY)
+                    $iMaxValueY = $aValue['value'];
+            }
+        }
+        $iMaxValueY = ceil($iMaxValueY * 1.1);
+        
+        $aDataForChartXAxes = array();
+        if ($bIsTimeX){
+            $sUnit = 'day';
+            $iInterval = ($iDateTo - $iDateFrom) / 86400;
+            if ($iInterval > 50)
+                $sUnit = 'week';
+            if ($iInterval > 100)
+                $sUnit = 'month';
+            
+            $aDataForChartXAxes = array(
+                'type' => 'time',
+                'time' => array(
+                    'tooltipFormat' => 'DD.MM.YYYY',
+                    'unit' => $sUnit,
+                 ),
+                'display' => true,
+                'distribution' => 'linear',
+                'ticks' =>  array(
+                    'display' => true, 
+                    'autoSkip' => true, 
+                )
+            );
+        }
+        else{
+            $aDataForChartXAxes = array(
+                'ticks' =>  array(
+                    'autoSkip' => false
+                ),
+                'display' => true
+            );
+        }
+       
+        $aDataForChartDatasets = array();    
+        for($i = 0; $i < count($aValues['values']); $i++){
+            $aDataForChartDatasets[] = array(
+                'label' => $aValues['values'][$i]['legend'],
+                'fill' => false,
+                'backgroundColor' =>  $this->aColors[$i],
+                'borderColor' => $this->aColors[$i],
+                'borderWidth' => 1,
+                'data' => $aValues['values'][$i]['data']
+            );
+        }
+            
+        $aDataForChart = array(
+            'type' =>  $sType,
+            'data' =>  array(
+                'labels' => $aValues['labels'], 
+                'datasets' => $aDataForChartDatasets
+            ),
+            'options' => array(
+                'legend' => array(
+                    'position' => 'bottom', 
+                    'display' => count($aValues['values']) == 1 ? false :true
+                ),
+                'scales' => array(
+                    'yAxes' =>  array(
+                        array(
+                            'ticks' =>  array(
+                                'max' => $iMaxValueY, 
+                                'min' => $iMinValueY, 
+                                'stepSize' => $this->getStep($iMinValueY, $iMaxValueY), 
+                                'autoSkip' => true
+                            )
+                        )
+                    ),
+                    'xAxes' =>  array($aDataForChartXAxes)
+                )
+            ),
+            'links' => $aValues['links'],
+            'strings' => $aValues['strings'],
+        );
+        
+
+        echo json_encode($aDataForChart);
+        return;
+        
+        $sRv = '{"type": "' . $sType . '", "data": {"labels":' . json_encode($aValues['labels']) . ',"datasets": [';
+        for($i = 0; $i < count($aValues['values']); $i++){
+            $sRv .= '{"label": "' . $aValues['values'][$i]['legend'] . '", "fill": false, "backgroundColor": "' . $this->aColors[$i] . '","borderColor": "' . $this->aColors[$i] . '","borderWidth": 1,"data": ' . json_encode($aValues['values'][$i]['data']) . '}';
+            if ($i != count($aValues['values']) - 1)
+                $sRv .= ',';
+        }
+        $sRv .= ']}, "options": {"legend": {"position": "bottom" ' . (count($aValues['values']) == 1 ? ', "display": false' : '') . '}, "scales": {';
               
-              $iMaxValueY = ceil($iMaxValueY * 1.1);
-              $sRv .= '"yAxes": [{"ticks": { "max": ' . $iMaxValueY . ',"min": ' . $iMinValueY . ', "stepSize": ' . $this->getStep($iMinValueY, $iMaxValueY) . ', "autoSkip": true }}]';
+        
+        $sRv .= '"yAxes": [{"ticks": { "max": ' . $iMaxValueY . ',"min": ' . $iMinValueY . ', "stepSize": ' . $this->getStep($iMinValueY, $iMaxValueY) . ', "autoSkip": true }}]';
               
-              if ($bIsTimeX){
-                  $sUnit = 'day';
-                  $iInterval = ($iDateTo - $iDateFrom) / 86400;
-                  if ($iInterval > 50)
-                      $sUnit = 'week';
-                  if ($iInterval > 100)
-                      $sUnit = 'month';
-                  $sRv .= ', "xAxes": [{"type": "time", "time": {"tooltipFormat": "DD.MM.YYYY", "unit" : "' . $sUnit . '"}, "ticks": {"autoSkip": true}, "display": "true", "distribution": "linear" }]';
-              }
-              else{
-                  $sRv .= ', "xAxes": [{"ticks": {"autoSkip": false}, "display": "true" }]';
-              }
-              $sRv .= '}}';
+        if ($bIsTimeX){
+            $sUnit = 'day';
+            $iInterval = ($iDateTo - $iDateFrom) / 86400;
+            if ($iInterval > 50)
+                $sUnit = 'week';
+            if ($iInterval > 100)
+                $sUnit = 'month';
+            $sRv .= ', "xAxes": [{"type": "time", "time": {"tooltipFormat": "DD.MM.YYYY", "unit" : "' . $sUnit . '"}, "ticks": {"autoSkip": true}, "display": "true", "distribution": "linear" }]';
+        }
+        else{
+            $sRv .= ', "xAxes": [{"ticks": {"autoSkip": false}, "display": "true" }]';
+        }
+        $sRv .= '}}';
 
-              if (count($aValues['links']) > 0)
-                  $sRv .= ', "links": ' . json_encode($aValues['links']);
-              $sRv .= ', "strings": ' . json_encode($aValues['strings']);
-              $sRv .= '}';
-              echo $sRv;
-          }
+        if (count($aValues['links']) > 0)
+            $sRv .= ', "links": ' . json_encode($aValues['links']);
+        $sRv .= ', "strings": ' . json_encode($aValues['strings']);
+        $sRv .= '}';
+        echo $sRv;
+    }
           
-          public function getSelectedModules()
-          {
-              $aModulesList = $this->serviceGetModules();
-              $aModules = array_keys($aModulesList);
-              $sModulesDisabled = explode(',', getParam('bx_analytics_modules_disabled'));
-              return array(array_diff($aModules, $sModulesDisabled), $aModulesList);
-          }
+    public function getSelectedModules()
+    {
+        $aModulesList = $this->serviceGetModules();
+        $aModules = array_keys($aModulesList);
+        $sModulesDisabled = explode(',', getParam('bx_analytics_modules_disabled'));
+        return array(array_diff($aModules, $sModulesDisabled), $aModulesList);
+    }
 
-          private function getViewsOrVotes($aSystems, $sSystem, $sModuleName, $iDateFrom, $iDateTo, &$aValues, &$iMaxValueY, &$iMinValueY)
-          {
-              $aData = array();
-              if ($sModuleName != BX_ANALYTICS_SYSTEM){
-                  $oModule = BxDolModule::getInstance($sModuleName);
-                  $sSystem = $oModule->_oConfig->CNF['OBJECT_VIEWS'];
-                  if(isset($aSystems[$sSystem]))
-                      $aData = $this->_oDb->getTopContentByLikes($sModuleName, $aSystems[$sSystem]['table_track'], $iDateFrom, $iDateTo);
-              }
-              else{
-                  $aTmp = $this->getSelectedModules();
-                  foreach ($aTmp[0] as $sModule) {
-                      if ($sModule != BX_ANALYTICS_SYSTEM){
-                          $oModule = BxDolModule::getInstance($sModule);
-                          if (isset($oModule->_oConfig->CNF['OBJECT_VIEWS'])){
-                              $sSystem = $oModule->_oConfig->CNF['OBJECT_VIEWS'];
-                              if(isset($aSystems[$sSystem])){
-                                  $aData1 = $this->_oDb->getTopContentByLikes($sModule, $aSystems[$sSystem]['table_track'], $iDateFrom, $iDateTo);
-                                  $aData = array_merge($aData, $aData1);
-                              }
-                          }
-                      }
-                  }
-                  $aData = $this->sortArrayOfArraysAndSlice($aData, 'value', intval(getParam('bx_analytics_items_count')));
-              }
-              foreach ($aData as $aValue) {
-                  $oModule = BxDolModule::getInstance($aValue['module']);
-                  array_push($aValues['labels'], $this->getItemName($oModule->serviceGetTitle($aValue['object_id'])));
-                  array_push($aValues['values'][0]['data'], $aValue['value']);
-                  array_push($aValues['links'], $oModule->serviceGetLink($aValue['object_id']));
-                  if ($aValue['value'] > $iMaxValueY)
-                      $iMaxValueY = $aValue['value'];
-              }
-          }
+    private function getViewsOrVotes($aSystems, $sSystem, $sModuleName, $iDateFrom, $iDateTo, &$aValues, &$iMaxValueY, &$iMinValueY)
+    {
+        $aData = array();
+        if ($sModuleName != BX_ANALYTICS_SYSTEM){
+            $oModule = BxDolModule::getInstance($sModuleName);
+            $sSystem = $oModule->_oConfig->CNF['OBJECT_VIEWS'];
+            if(isset($aSystems[$sSystem]))
+                $aData = $this->_oDb->getTopContentByLikes($sModuleName, $aSystems[$sSystem]['table_track'], $iDateFrom, $iDateTo);
+        }
+        else{
+            $aTmp = $this->getSelectedModules();
+            foreach ($aTmp[0] as $sModule) {
+                if ($sModule != BX_ANALYTICS_SYSTEM){
+                    $oModule = BxDolModule::getInstance($sModule);
+                    if (isset($oModule->_oConfig->CNF['OBJECT_VIEWS'])){
+                        $sSystem = $oModule->_oConfig->CNF['OBJECT_VIEWS'];
+                        if(isset($aSystems[$sSystem])){
+                            $aData1 = $this->_oDb->getTopContentByLikes($sModule, $aSystems[$sSystem]['table_track'], $iDateFrom, $iDateTo);
+                            $aData = array_merge($aData, $aData1);
+                        }
+                    }
+                }
+            }
+            $aData = $this->sortArrayOfArraysAndSlice($aData, 'value', intval(getParam('bx_analytics_items_count')));
+        }
+        foreach ($aData as $aValue) {
+            $oModule = BxDolModule::getInstance($aValue['module']);
+            array_push($aValues['labels'], $this->getItemName($oModule->serviceGetTitle($aValue['object_id'])));
+            array_push($aValues['values'][0]['data'], $aValue['value']);
+            array_push($aValues['links'], $oModule->serviceGetLink($aValue['object_id']));
+            if ($aValue['value'] > $iMaxValueY)
+                $iMaxValueY = $aValue['value'];
+        }
+    }
           
-          private function getStep($iMin, $iMax)
-          {
-              $iCount = 10;
-              return ceil(($iMax - $iMin) / $iCount);
-          }
+    private function getStep($iMin, $iMax)
+    {
+        $iCount = 10;
+        return ceil(($iMax - $iMin) / $iCount);
+    }
           
-          private function sortArrayOfArraysAndSlice($aArr, $sFld, $Count)
-          {
-              $aDataSort = array();
-              foreach ($aArr as $sKey => $oRow)
-              {
-                  $aDataSort[$sKey] = $oRow[$sFld];
-              }
-              array_multisort($aDataSort, SORT_DESC, $aArr);
-              return array_slice($aArr, 0, $Count);
-          }
+    private function sortArrayOfArraysAndSlice($aArr, $sFld, $Count)
+    {
+        $aDataSort = array();
+        foreach ($aArr as $sKey => $oRow)
+        {
+            $aDataSort[$sKey] = $oRow[$sFld];
+        }
+        array_multisort($aDataSort, SORT_DESC, $aArr);
+        return array_slice($aArr, 0, $Count);
+    }
           
-          private function getItemName($sString)
-          {
-              $sString = strip_tags($sString);
-              if ($sString == ''){
-                  $sString = _t('_bx_analytics_txt_empty_title_item');
-              }
-              return $sString;
-          }
-      }
+    private function getItemName($sString)
+    {
+        $sString = strip_tags($sString);
+        if ($sString == ''){
+            $sString = _t('_bx_analytics_txt_empty_title_item');
+        }
+        return $sString;
+    }
+}
 
-      /** @} */
+/** @} */

+ 29 - 29
modules/boonex/analytics/classes/BxAnalyticsPageLicenses.php → modules/boonex/analytics/classes/BxAnalyticsPage.php

@@ -1,29 +1,29 @@
-<?php defined('BX_DOL') or die('hack attempt');
-/**
- * Copyright (c) UNA, Inc - https://una.io
- * MIT License - https://opensource.org/licenses/MIT
- *
- * @defgroup    Analytics Analytics
- * @ingroup     UnaModules
- *
- * @{
- */
-
-class BxAnalyticsPageLicenses extends BxBaseModTextPageAuthor
-{
-    protected $MODULE;
-
-    public function __construct($aObject, $oTemplate = false)
-    {
-        $this->MODULE = 'bx_analytics';
-        parent::__construct($aObject, $oTemplate);
-        $oMenuSubmenu = BxDolMenu::getObjectInstance('sys_site_submenu');
-        if($oMenuSubmenu) {
-            $sMenuSubmenu = 'sys_account_dashboard';
-            $oMenuSubmenu->setObjectSubmenu($sMenuSubmenu, array('title' => _t('_sys_menu_item_title_account_dashboard'), 'link' => '', 'icon' => ''));
-            BxDolMenu::getObjectInstance($sMenuSubmenu)->setSelected($this->MODULE, 'analytics');
-        }
-    }
-}
-
-/** @} */
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Analytics Analytics
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+class BxAnalyticsPage extends BxTemplPage
+{
+    protected $MODULE;
+
+    public function __construct($aObject, $oTemplate = false)
+    {
+        $this->MODULE = 'bx_analytics';
+        parent::__construct($aObject, $oTemplate);
+        $oMenuSubmenu = BxDolMenu::getObjectInstance('sys_site_submenu');
+        if($oMenuSubmenu) {
+            $sMenuSubmenu = 'sys_account_dashboard';
+            $oMenuSubmenu->setObjectSubmenu($sMenuSubmenu, array('title' => _t('_sys_menu_item_title_account_dashboard'), 'link' => '', 'icon' => ''));
+            BxDolMenu::getObjectInstance($sMenuSubmenu)->setSelected($this->MODULE, 'analytics');
+        }
+    }
+}
+
+/** @} */

+ 2 - 3
modules/boonex/analytics/classes/BxAnalyticsTemplate.php

@@ -32,9 +32,8 @@ class BxAnalyticsTemplate extends BxBaseModGeneralTemplate
         
         $iDaysBefore = getParam('bx_analytics_default_interval_day');
         $sDate = date('d/m/Y', time() - $iDaysBefore * 86400) . ' - ' . date('d/m/Y');
-        
-        $this->addJs(array('chart.min.js', 'analytics.js', 'moment-with-locales.min.js', 'daterangepicker.js', 'datatables.min.js'));
-        $this->addCss(array('daterangepicker.css', 'datatables.min.css'));
+        $this->addJs(array('chart.min.js', 'analytics.js', BX_DIRECTORY_PATH_MODULES . 'boonex/analytics/plugins/daterangepicker/|daterangepicker.js', BX_DIRECTORY_PATH_MODULES . 'boonex/analytics/plugins/datatables/|datatables.min.js'));
+        $this->addCss(array(BX_DIRECTORY_PATH_MODULES . 'boonex/analytics/plugins/daterangepicker/|daterangepicker.css', BX_DIRECTORY_PATH_MODULES . 'boonex/analytics/plugins/datatables/|datatables.min.css'));
         return $this->getJsCode('analytics') . $this->parseHtmlByName('canvas.html', array(
              'bx_repeat:items' => $aModulesList2,
              'interval' => $sDate

+ 2 - 2
modules/boonex/analytics/install/langs/en.xml

@@ -27,8 +27,8 @@
   <string name="_bx_analytics_txt_item"><![CDATA[Item]]></string>
   <string name="_bx_analytics_txt_date"><![CDATA[Date]]></string>
   <string name="_bx_analytics_txt_value"><![CDATA[Value]]></string>
-  <string name="_bx_analytics_txt_total_count"><![CDATA[ - total number]]></string>
-  <string name="_bx_analytics_txt_count"><![CDATA[ - number]]></string>
+  <string name="_bx_analytics_txt_total_count"><![CDATA[{0} - total number]]></string>
+  <string name="_bx_analytics_txt_count"><![CDATA[{0} - number]]></string>
   <string name="_bx_analytics_txt_accounts"><![CDATA[Accounts]]></string>
   <string name="_bx_analytics_txt_total_content"><![CDATA[All content]]></string>
   <string name="_bx_analytics_type_top_by_views_label"><![CDATA[Number of views]]></string>

+ 1 - 2
modules/boonex/analytics/install/sql/enable.sql

@@ -18,9 +18,8 @@ INSERT INTO `sys_options` (`category_id`, `name`, `caption`, `value`, `type`, `e
 
 -- PAGES & BLOCKS
 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_analytics_page', '_bx_analytics_page_title_sys_page', '_bx_analytics_page_title_page', @sName, 5, 2147483647, 1, 'analytics', '', '', '', '', 0, 1, 0, 'BxAnalyticsPageLicenses', 'modules/boonex/analytics/classes/BxAnalyticsPageLicenses.php');
+('bx_analytics_page', '_bx_analytics_page_title_sys_page', '_bx_analytics_page_title_page', @sName, 5, 2147483647, 1, 'analytics', '', '', '', '', 0, 1, 0, 'BxAnalyticsPage', 'modules/boonex/analytics/classes/BxAnalyticsPage.php');
 
--- PAGES: add page block on dashboard
 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_analytics_page', 1,  @sName, '_bx_analytics_page_block_title_system_canvas', '_bx_analytics_page_block_title_canvas', 11, 192, 'service', 'a:2:{s:6:"module";s:12:"bx_analytics";s:6:"method";s:10:"get_canvas";}', 0, 1, 1, 0);
 

+ 2 - 2
modules/boonex/analytics/js/analytics.js

@@ -9,7 +9,7 @@
  */
 
 function BxAnalytics(oOptions) {
-    this._sContainerId = 'BxAnalyticsContainer';
+    this._sContainerId = 'bx_analytics_container';
     this._sModuleSelector = '#' + this._sContainerId + ' .bx_analytics_module_selector';
     this._sReportSelector = '#' + this._sContainerId + " .bx_analytics_report_selector";
     this._sContainerDataSelector = '#' + this._sContainerId + " .bx_analytics_data";
@@ -119,7 +119,7 @@ BxAnalytics.prototype.dataToTable = function (oDataIn) {
         else{
             sTxt = oData.datasets[0].data[iDx].x;
         }
-        if (oDataIn.links) {
+        if (oDataIn.links && count(oDataIn.links) > 0) {
             sTxt = "<a href='" + oDataIn.links[iDx] + "'>" + sTxt + "</a>"
         }
         sHtml += '<tr><td>&nbsp;'+  sTxt + '</td>';

Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 0 - 12
modules/boonex/analytics/plugins/datatables/datatables.min.css


+ 2 - 2
modules/boonex/analytics/js/datatables.min.js → modules/boonex/analytics/plugins/datatables/datatables.min.js

@@ -59,7 +59,7 @@ h._aFilterData=j;h._sFilterRow=j.join("  ");c=!0}return c}function Ab(a){return{
 b+"_info"));return d[0]}function Cb(a){var b=a.aanFeatures.i;if(0!==b.length){var c=a.oLanguage,d=a._iDisplayStart+1,e=a.fnDisplayEnd(),f=a.fnRecordsTotal(),g=a.fnRecordsDisplay(),j=g?c.sInfo:c.sInfoEmpty;g!==f&&(j+=" "+c.sInfoFiltered);j+=c.sInfoPostFix;j=Db(a,j);c=c.fnInfoCallback;null!==c&&(j=c.call(a.oInstance,a,d,e,f,g,j));h(b).html(j)}}function Db(a,b){var c=a.fnFormatNumber,d=a._iDisplayStart+1,e=a._iDisplayLength,f=a.fnRecordsDisplay(),g=-1===e;return b.replace(/_START_/g,c.call(a,d)).replace(/_END_/g,
 c.call(a,a.fnDisplayEnd())).replace(/_MAX_/g,c.call(a,a.fnRecordsTotal())).replace(/_TOTAL_/g,c.call(a,f)).replace(/_PAGE_/g,c.call(a,g?1:Math.ceil(d/e))).replace(/_PAGES_/g,c.call(a,g?1:Math.ceil(f/e)))}function ha(a){var b,c,d=a.iInitDisplayStart,e=a.aoColumns,f;c=a.oFeatures;var g=a.bDeferLoading;if(a.bInitialised){nb(a);kb(a);fa(a,a.aoHeader);fa(a,a.aoFooter);C(a,!0);c.bAutoWidth&&Fa(a);b=0;for(c=e.length;b<c;b++)f=e[b],f.sWidth&&(f.nTh.style.width=v(f.sWidth));r(a,null,"preInit",[a]);T(a);e=
 y(a);if("ssp"!=e||g)"ajax"==e?sa(a,[],function(c){var f=ta(a,c);for(b=0;b<f.length;b++)O(a,f[b]);a.iInitDisplayStart=d;T(a);C(a,!1);ua(a,c)},a):(C(a,!1),ua(a))}else setTimeout(function(){ha(a)},200)}function ua(a,b){a._bInitComplete=!0;(b||a.oInit.aaData)&&$(a);r(a,null,"plugin-init",[a,b]);r(a,"aoInitComplete","init",[a,b])}function Ra(a,b){var c=parseInt(b,10);a._iDisplayLength=c;Sa(a);r(a,null,"length",[a,c])}function ob(a){for(var b=a.oClasses,c=a.sTableId,d=a.aLengthMenu,e=h.isArray(d[0]),f=
-e ? d[0] : d, d = e ? d[1] : d, e = h("<select/>", { name: c + "_length", "aria-controls": c, "class": b.sLengthSelect + 'bx-def-font-inputs bx-form-input-select' }), g = 0, j = f.length; g < j; g++) e[0][g] = new Option("number" === typeof d[g] ? a.fnFormatNumber(d[g]) : d[g], f[g]); var i = h("<div><label/></div>").addClass(b.sLength); a.aanFeatures.l || (i[0].id = c + "_length"); i.children().append(a.oLanguage.sLengthMenu.replace("_MENU_", e[0].outerHTML)); h("select", i).val(a._iDisplayLength).on("change.DT", function () { Ra(a, h(this).val()); P(a) }); h(a.nTable).on("length.dt.DT", function (b, c, d) {
+e ? d[0] : d, d = e ? d[1] : d, e = h("<select/>", { name: c + "_length", "aria-controls": c, "class": b.sLengthSelect + 'bx-def-font-inputs bx-form-input-select' }), g = 0, j = f.length; g < j; g++) e[0][g] = new Option("number" === typeof d[g] ? a.fnFormatNumber(d[g]) : d[g], f[g]); var i = h("<div><label/></div>").addClass(b.sLength); a.aanFeatures.l || (i[0].id = c + "_length"); i.children().append(a.oLanguage.sLengthMenu.replace("_MENU_", e[0].outerHTML)); h("select", i).val(a._iDisplayLength).on("change.DT", function () { Ra(a, h(this).val()); P(a) }); h(a.nTable).on("length.dt.DT", function (b, c, d) {
     a ===
 c&&h("select",i).val(d)});return i[0]}function tb(a){var b=a.sPaginationType,c=n.ext.pager[b],d="function"===typeof c,e=function(a){P(a)},b=h("<div/>").addClass(a.oClasses.sPaging+b)[0],f=a.aanFeatures;d||c.fnInit(a,b,e);f.p||(b.id=a.sTableId+"_paginate",a.aoDrawCallback.push({fn:function(a){if(d){var b=a._iDisplayStart,i=a._iDisplayLength,h=a.fnRecordsDisplay(),l=-1===i,b=l?0:Math.ceil(b/i),i=l?1:Math.ceil(h/i),h=c(b,i),k,l=0;for(k=f.p.length;l<k;l++)Na(a,"pageButton")(a,f.p[l],l,h,b,i)}else c.fnUpdate(a,
 e)},sName:"pagination"}));return b}function Ta(a,b,c){var d=a._iDisplayStart,e=a._iDisplayLength,f=a.fnRecordsDisplay();0===f||-1===e?d=0:"number"===typeof b?(d=b*e,d>f&&(d=0)):"first"==b?d=0:"previous"==b?(d=0<=e?d-e:0,0>d&&(d=0)):"next"==b?d+e<f&&(d+=e):"last"==b?d=Math.floor((f-1)/e)*e:K(a,0,"Unknown paging action: "+b,5);b=a._iDisplayStart!==d;a._iDisplayStart=d;b&&(r(a,null,"page",[a]),c&&P(a));return b}function qb(a){return h("<div/>",{id:!a.aanFeatures.r?a.sTableId+"_processing":null,"class":a.oClasses.sProcessing}).html(a.oLanguage.sProcessing).insertBefore(a.nTable)[0]}
@@ -155,7 +155,7 @@ a._);return a.replace("%d",c)});n.version="1.10.18";n.settings=[];n.models={};n.
 sClass:null,sContentPadding:null,sDefaultContent:null,sName:null,sSortDataType:"std",sSortingClass:null,sSortingClassJUI:null,sTitle:null,sType:null,sWidth:null,sWidthOrig:null};n.defaults={aaData:null,aaSorting:[[0,"asc"]],aaSortingFixed:[],ajax:null,aLengthMenu:[10,25,50,100],aoColumns:null,aoColumnDefs:null,aoSearchCols:[],asStripeClasses:null,bAutoWidth:!0,bDeferRender:!1,bDestroy:!1,bFilter:!0,bInfo:!0,bLengthChange:!0,bPaginate:!0,bProcessing:!1,bRetrieve:!1,bScrollCollapse:!1,bServerSide:!1,
 bSort:!0,bSortMulti:!0,bSortCellsTop:!1,bSortClasses:!0,bStateSave:!1,fnCreatedRow:null,fnDrawCallback:null,fnFooterCallback:null,fnFormatNumber:function(a){return a.toString().replace(/\B(?=(\d{3})+(?!\d))/g,this.oLanguage.sThousands)},fnHeaderCallback:null,fnInfoCallback:null,fnInitComplete:null,fnPreDrawCallback:null,fnRowCallback:null,fnServerData:null,fnServerParams:null,fnStateLoadCallback:function(a){try{return JSON.parse((-1===a.iStateDuration?sessionStorage:localStorage).getItem("DataTables_"+
 a.sInstance+"_"+location.pathname))}catch(b){}},fnStateLoadParams:null,fnStateLoaded:null,fnStateSaveCallback:function(a,b){try{(-1===a.iStateDuration?sessionStorage:localStorage).setItem("DataTables_"+a.sInstance+"_"+location.pathname,JSON.stringify(b))}catch(c){}},fnStateSaveParams:null,iStateDuration:7200,iDeferLoading:null,iDisplayLength:10,iDisplayStart:0,iTabIndex:0,oClasses:{},oLanguage:{oAria:{sSortAscending:": activate to sort column ascending",sSortDescending:": activate to sort column descending"},
-    oPaginate: { sFirst: "First", sLast: "Last", sNext: "&raquo;", sPrevious: "&laquo;" }, sEmptyTable: "No data available in table", sInfo: "Showing _START_ to _END_ of _TOTAL_ entries", sInfoEmpty: "Showing 0 to 0 of 0 entries", sInfoFiltered: "(filtered from _MAX_ total entries)", sInfoPostFix: "", sDecimal: "", sThousands: ",", sLengthMenu: "_MENU_", sLoadingRecords: "Loading...", sProcessing: "Processing...", sSearch: "Search:", sSearchPlaceholder: "", sUrl: "", sZeroRecords: "No matching records found"
+    oPaginate: { sFirst: "First", sLast: "Last", sNext: "&raquo;", sPrevious: "&laquo;" }, sEmptyTable: "No data available in table", sInfo: "Showing _START_ to _END_ of _TOTAL_ entries", sInfoEmpty: "Showing 0 to 0 of 0 entries", sInfoFiltered: "(filtered from _MAX_ total entries)", sInfoPostFix: "", sDecimal: "", sThousands: ",", sLengthMenu: "_MENU_", sLoadingRecords: "Loading...", sProcessing: "Processing...", sSearch: "Search:", sSearchPlaceholder: "", sUrl: "", sZeroRecords: "No matching records found"
 }, oSearch: h.extend({},
 n.models.oSearch),sAjaxDataProp:"data",sAjaxSource:null,sDom:"lfrtip",searchDelay:null,sPaginationType:"simple_numbers",sScrollX:"",sScrollXInner:"",sScrollY:"",sServerMethod:"GET",renderer:null,rowId:"DT_RowId"};Z(n.defaults);n.defaults.column={aDataSort:null,iDataSort:-1,asSorting:["asc","desc"],bSearchable:!0,bSortable:!0,bVisible:!0,fnCreatedCell:null,mData:null,mRender:null,sCellType:"td",sClass:"",sContentPadding:"",sDefaultContent:null,sName:"",sSortDataType:"std",sTitle:null,sType:null,sWidth:null};
 Z(n.defaults.column);n.models.oSettings={oFeatures:{bAutoWidth:null,bDeferRender:null,bFilter:null,bInfo:null,bLengthChange:null,bPaginate:null,bProcessing:null,bServerSide:null,bSort:null,bSortMulti:null,bSortClasses:null,bStateSave:null},oScroll:{bCollapse:null,iBarWidth:0,sX:null,sXInner:null,sY:null},oLanguage:{fnInfoCallback:null},oBrowser:{bScrollOversize:!1,bScrollbarLeft:!1,bBounding:!1,barWidth:0},ajax:null,aanFeatures:[],aoData:[],aiDisplay:[],aiDisplayMaster:[],aIds:{},aoColumns:[],aoHeader:[],

+ 392 - 392
modules/boonex/analytics/template/css/daterangepicker.css → modules/boonex/analytics/plugins/daterangepicker/daterangepicker.css

@@ -1,392 +1,392 @@
-body
-{
-	background:red;
-}
-.daterangepicker {
-  position: absolute;
-  color: inherit;
-  background-color: #fff;
-  border-radius: 4px;
-  border: 1px solid #ddd;
-  width: 278px;
-  max-width: none;
-  padding: 0;
-  margin-top: 7px;
-  top: 100px;
-  left: 20px;
-  z-index: 3001;
-  display: none;
-  font-family: arial;
-  font-size: 15px;
-  line-height: 1em;
-}
-
-.daterangepicker:before, .daterangepicker:after {
-  position: absolute;
-  display: inline-block;
-  border-bottom-color: rgba(0, 0, 0, 0.2);
-  content: '';
-}
-
-.daterangepicker:before {
-  top: -7px;
-  border-right: 7px solid transparent;
-  border-left: 7px solid transparent;
-  border-bottom: 7px solid #ccc;
-}
-
-.daterangepicker:after {
-  top: -6px;
-  border-right: 6px solid transparent;
-  border-bottom: 6px solid #fff;
-  border-left: 6px solid transparent;
-}
-
-.daterangepicker.opensleft:before {
-  right: 9px;
-}
-
-.daterangepicker.opensleft:after {
-  right: 10px;
-}
-
-.daterangepicker.openscenter:before {
-  left: 0;
-  right: 0;
-  width: 0;
-  margin-left: auto;
-  margin-right: auto;
-}
-
-.daterangepicker.openscenter:after {
-  left: 0;
-  right: 0;
-  width: 0;
-  margin-left: auto;
-  margin-right: auto;
-}
-
-.daterangepicker.opensright:before {
-  left: 9px;
-}
-
-.daterangepicker.opensright:after {
-  left: 10px;
-}
-
-.daterangepicker.drop-up {
-  margin-top: -7px;
-}
-
-.daterangepicker.drop-up:before {
-  top: initial;
-  bottom: -7px;
-  border-bottom: initial;
-  border-top: 7px solid #ccc;
-}
-
-.daterangepicker.drop-up:after {
-  top: initial;
-  bottom: -6px;
-  border-bottom: initial;
-  border-top: 6px solid #fff;
-}
-
-.daterangepicker.single .daterangepicker .ranges, .daterangepicker.single .drp-calendar {
-  float: none;
-}
-
-.daterangepicker.single .drp-selected {
-  display: none;
-}
-
-.daterangepicker.show-calendar .drp-calendar {
-  display: block;
-}
-
-.daterangepicker.show-calendar .drp-buttons {
-  display: block;
-}
-
-.daterangepicker.auto-apply .drp-buttons {
-  display: none;
-}
-
-.daterangepicker .drp-calendar {
-  display: none;
-  max-width: 270px;
-}
-
-.daterangepicker .drp-calendar.left {
-  padding: 8px 0 8px 8px;
-}
-
-.daterangepicker .drp-calendar.right {
-  padding: 8px;
-}
-
-.daterangepicker .drp-calendar.single .calendar-table {
-  border: none;
-}
-
-.daterangepicker .calendar-table .next span, .daterangepicker .calendar-table .prev span {
-  color: #fff;
-  border: solid black;
-  border-width: 0 2px 2px 0;
-  border-radius: 0;
-  display: inline-block;
-  padding: 3px;
-}
-
-.daterangepicker .calendar-table .next span {
-  transform: rotate(-45deg);
-  -webkit-transform: rotate(-45deg);
-}
-
-.daterangepicker .calendar-table .prev span {
-  transform: rotate(135deg);
-  -webkit-transform: rotate(135deg);
-}
-
-.daterangepicker .calendar-table th, .daterangepicker .calendar-table td {
-  white-space: nowrap;
-  text-align: center;
-  vertical-align: middle;
-  min-width: 32px;
-  width: 32px;
-  height: 24px;
-  line-height: 24px;
-  font-size: 12px;
-  border-radius: 4px;
-  border: 1px solid transparent;
-  white-space: nowrap;
-  cursor: pointer;
-}
-
-.daterangepicker .calendar-table {
-  border: 1px solid #fff;
-  border-radius: 4px;
-  background-color: #fff;
-}
-
-.daterangepicker .calendar-table table {
-  width: 100%;
-  margin: 0;
-  border-spacing: 0;
-  border-collapse: collapse;
-}
-
-.daterangepicker td.available:hover, .daterangepicker th.available:hover {
-  background-color: #eee;
-  border-color: transparent;
-  color: inherit;
-}
-
-.daterangepicker td.week, .daterangepicker th.week {
-  font-size: 80%;
-  color: #ccc;
-}
-
-.daterangepicker td.off, .daterangepicker td.off.in-range, .daterangepicker td.off.start-date, .daterangepicker td.off.end-date {
-  background-color: #fff;
-  border-color: transparent;
-  color: #999;
-}
-
-.daterangepicker td.in-range {
-  background-color: #ebf4f8;
-  border-color: transparent;
-  color: #000;
-  border-radius: 0;
-}
-
-.daterangepicker td.start-date {
-  border-radius: 4px 0 0 4px;
-}
-
-.daterangepicker td.end-date {
-  border-radius: 0 4px 4px 0;
-}
-
-.daterangepicker td.start-date.end-date {
-  border-radius: 4px;
-}
-
-.daterangepicker td.active, .daterangepicker td.active:hover {
-  background-color: #357ebd;
-  border-color: transparent;
-  color: #fff;
-}
-
-.daterangepicker th.month {
-  width: auto;
-}
-
-.daterangepicker td.disabled, .daterangepicker option.disabled {
-  color: #999;
-  cursor: not-allowed;
-  text-decoration: line-through;
-}
-
-.daterangepicker select.monthselect, .daterangepicker select.yearselect {
-  font-size: 12px;
-  padding: 1px;
-  height: auto;
-  margin: 0;
-  cursor: default;
-}
-
-.daterangepicker select.monthselect {
-  margin-right: 2%;
-  width: 56%;
-}
-
-.daterangepicker select.yearselect {
-  width: 40%;
-}
-
-.daterangepicker select.hourselect, .daterangepicker select.minuteselect, .daterangepicker select.secondselect, .daterangepicker select.ampmselect {
-  width: 50px;
-  margin: 0 auto;
-  background: #eee;
-  border: 1px solid #eee;
-  padding: 2px;
-  outline: 0;
-  font-size: 12px;
-}
-
-.daterangepicker .calendar-time {
-  text-align: center;
-  margin: 4px auto 0 auto;
-  line-height: 30px;
-  position: relative;
-}
-
-.daterangepicker .calendar-time select.disabled {
-  color: #ccc;
-  cursor: not-allowed;
-}
-
-.daterangepicker .drp-buttons {
-  clear: both;
-  text-align: right;
-  padding: 8px;
-  border-top: 1px solid #ddd;
-  display: none;
-  line-height: 12px;
-  vertical-align: middle;
-}
-
-.daterangepicker .drp-selected {
-  display: inline-block;
-  font-size: 12px;
-  padding-right: 8px;
-}
-
-.daterangepicker .drp-buttons .btn {
-  margin-left: 8px;
-  font-size: 12px;
-  font-weight: bold;
-  padding: 4px 8px;
-}
-
-.daterangepicker.show-ranges .drp-calendar.left {
-  border-left: 1px solid #ddd;
-}
-
-.daterangepicker .ranges {
-  float: none;
-  text-align: left;
-  margin: 0;
-}
-
-.daterangepicker.show-calendar .ranges {
-  margin-top: 8px;
-}
-
-.daterangepicker .ranges ul {
-  list-style: none;
-  margin: 0 auto;
-  padding: 0;
-  width: 100%;
-}
-
-.daterangepicker .ranges li {
-  font-size: 12px;
-  padding: 8px 12px;
-  cursor: pointer;
-}
-
-.daterangepicker .ranges li:hover {
-  background-color: #eee;
-}
-
-.daterangepicker .ranges li.active {
-  background-color: #08c;
-  color: #fff;
-}
-
-/*  Larger Screen Styling */
-@media (min-width: 564px) {
-  .daterangepicker {
-    width: auto; }
-    .daterangepicker .ranges ul {
-      width: 140px; }
-    .daterangepicker.single .ranges ul {
-      width: 100%; }
-    .daterangepicker.single .drp-calendar.left {
-      clear: none; }
-    .daterangepicker.single.ltr .ranges, .daterangepicker.single.ltr .drp-calendar {
-      float: left; }
-    .daterangepicker.single.rtl .ranges, .daterangepicker.single.rtl .drp-calendar {
-      float: right; }
-    .daterangepicker.ltr {
-      direction: ltr;
-      text-align: left; }
-      .daterangepicker.ltr .drp-calendar.left {
-        clear: left;
-        margin-right: 0; }
-        .daterangepicker.ltr .drp-calendar.left .calendar-table {
-          border-right: none;
-          border-top-right-radius: 0;
-          border-bottom-right-radius: 0; }
-      .daterangepicker.ltr .drp-calendar.right {
-        margin-left: 0; }
-        .daterangepicker.ltr .drp-calendar.right .calendar-table {
-          border-left: none;
-          border-top-left-radius: 0;
-          border-bottom-left-radius: 0; }
-      .daterangepicker.ltr .drp-calendar.left .calendar-table {
-        padding-right: 8px; }
-      .daterangepicker.ltr .ranges, .daterangepicker.ltr .drp-calendar {
-        float: left; }
-    .daterangepicker.rtl {
-      direction: rtl;
-      text-align: right; }
-      .daterangepicker.rtl .drp-calendar.left {
-        clear: right;
-        margin-left: 0; }
-        .daterangepicker.rtl .drp-calendar.left .calendar-table {
-          border-left: none;
-          border-top-left-radius: 0;
-          border-bottom-left-radius: 0; }
-      .daterangepicker.rtl .drp-calendar.right {
-        margin-right: 0; }
-        .daterangepicker.rtl .drp-calendar.right .calendar-table {
-          border-right: none;
-          border-top-right-radius: 0;
-          border-bottom-right-radius: 0; }
-      .daterangepicker.rtl .drp-calendar.left .calendar-table {
-        padding-left: 12px; }
-      .daterangepicker.rtl .ranges, .daterangepicker.rtl .drp-calendar {
-        text-align: right;
-        float: right; } }
-@media (min-width: 730px) {
-  .daterangepicker .ranges {
-    width: auto; }
-  .daterangepicker.ltr .ranges {
-    float: left; }
-  .daterangepicker.rtl .ranges {
-    float: right; }
-  .daterangepicker .drp-calendar.left {
-    clear: none !important; } }
+body
+{
+	background:red;
+}
+.daterangepicker {
+  position: absolute;
+  color: inherit;
+  background-color: #fff;
+  border-radius: 4px;
+  border: 1px solid #ddd;
+  width: 278px;
+  max-width: none;
+  padding: 0;
+  margin-top: 7px;
+  top: 100px;
+  left: 20px;
+  z-index: 3001;
+  display: none;
+  font-family: arial;
+  font-size: 15px;
+  line-height: 1em;
+}
+
+.daterangepicker:before, .daterangepicker:after {
+  position: absolute;
+  display: inline-block;
+  border-bottom-color: rgba(0, 0, 0, 0.2);
+  content: '';
+}
+
+.daterangepicker:before {
+  top: -7px;
+  border-right: 7px solid transparent;
+  border-left: 7px solid transparent;
+  border-bottom: 7px solid #ccc;
+}
+
+.daterangepicker:after {
+  top: -6px;
+  border-right: 6px solid transparent;
+  border-bottom: 6px solid #fff;
+  border-left: 6px solid transparent;
+}
+
+.daterangepicker.opensleft:before {
+  right: 9px;
+}
+
+.daterangepicker.opensleft:after {
+  right: 10px;
+}
+
+.daterangepicker.openscenter:before {
+  left: 0;
+  right: 0;
+  width: 0;
+  margin-left: auto;
+  margin-right: auto;
+}
+
+.daterangepicker.openscenter:after {
+  left: 0;
+  right: 0;
+  width: 0;
+  margin-left: auto;
+  margin-right: auto;
+}
+
+.daterangepicker.opensright:before {
+  left: 9px;
+}
+
+.daterangepicker.opensright:after {
+  left: 10px;
+}
+
+.daterangepicker.drop-up {
+  margin-top: -7px;
+}
+
+.daterangepicker.drop-up:before {
+  top: initial;
+  bottom: -7px;
+  border-bottom: initial;
+  border-top: 7px solid #ccc;
+}
+
+.daterangepicker.drop-up:after {
+  top: initial;
+  bottom: -6px;
+  border-bottom: initial;
+  border-top: 6px solid #fff;
+}
+
+.daterangepicker.single .daterangepicker .ranges, .daterangepicker.single .drp-calendar {
+  float: none;
+}
+
+.daterangepicker.single .drp-selected {
+  display: none;
+}
+
+.daterangepicker.show-calendar .drp-calendar {
+  display: block;
+}
+
+.daterangepicker.show-calendar .drp-buttons {
+  display: block;
+}
+
+.daterangepicker.auto-apply .drp-buttons {
+  display: none;
+}
+
+.daterangepicker .drp-calendar {
+  display: none;
+  max-width: 270px;
+}
+
+.daterangepicker .drp-calendar.left {
+  padding: 8px 0 8px 8px;
+}
+
+.daterangepicker .drp-calendar.right {
+  padding: 8px;
+}
+
+.daterangepicker .drp-calendar.single .calendar-table {
+  border: none;
+}
+
+.daterangepicker .calendar-table .next span, .daterangepicker .calendar-table .prev span {
+  color: #fff;
+  border: solid black;
+  border-width: 0 2px 2px 0;
+  border-radius: 0;
+  display: inline-block;
+  padding: 3px;
+}
+
+.daterangepicker .calendar-table .next span {
+  transform: rotate(-45deg);
+  -webkit-transform: rotate(-45deg);
+}
+
+.daterangepicker .calendar-table .prev span {
+  transform: rotate(135deg);
+  -webkit-transform: rotate(135deg);
+}
+
+.daterangepicker .calendar-table th, .daterangepicker .calendar-table td {
+  white-space: nowrap;
+  text-align: center;
+  vertical-align: middle;
+  min-width: 32px;
+  width: 32px;
+  height: 24px;
+  line-height: 24px;
+  font-size: 12px;
+  border-radius: 4px;
+  border: 1px solid transparent;
+  white-space: nowrap;
+  cursor: pointer;
+}
+
+.daterangepicker .calendar-table {
+  border: 1px solid #fff;
+  border-radius: 4px;
+  background-color: #fff;
+}
+
+.daterangepicker .calendar-table table {
+  width: 100%;
+  margin: 0;
+  border-spacing: 0;
+  border-collapse: collapse;
+}
+
+.daterangepicker td.available:hover, .daterangepicker th.available:hover {
+  background-color: #eee;
+  border-color: transparent;
+  color: inherit;
+}
+
+.daterangepicker td.week, .daterangepicker th.week {
+  font-size: 80%;
+  color: #ccc;
+}
+
+.daterangepicker td.off, .daterangepicker td.off.in-range, .daterangepicker td.off.start-date, .daterangepicker td.off.end-date {
+  background-color: #fff;
+  border-color: transparent;
+  color: #999;
+}
+
+.daterangepicker td.in-range {
+  background-color: #ebf4f8;
+  border-color: transparent;
+  color: #000;
+  border-radius: 0;
+}
+
+.daterangepicker td.start-date {
+  border-radius: 4px 0 0 4px;
+}
+
+.daterangepicker td.end-date {
+  border-radius: 0 4px 4px 0;
+}
+
+.daterangepicker td.start-date.end-date {
+  border-radius: 4px;
+}
+
+.daterangepicker td.active, .daterangepicker td.active:hover {
+  background-color: #357ebd;
+  border-color: transparent;
+  color: #fff;
+}
+
+.daterangepicker th.month {
+  width: auto;
+}
+
+.daterangepicker td.disabled, .daterangepicker option.disabled {
+  color: #999;
+  cursor: not-allowed;
+  text-decoration: line-through;
+}
+
+.daterangepicker select.monthselect, .daterangepicker select.yearselect {
+  font-size: 12px;
+  padding: 1px;
+  height: auto;
+  margin: 0;
+  cursor: default;
+}
+
+.daterangepicker select.monthselect {
+  margin-right: 2%;
+  width: 56%;
+}
+
+.daterangepicker select.yearselect {
+  width: 40%;
+}
+
+.daterangepicker select.hourselect, .daterangepicker select.minuteselect, .daterangepicker select.secondselect, .daterangepicker select.ampmselect {
+  width: 50px;
+  margin: 0 auto;
+  background: #eee;
+  border: 1px solid #eee;
+  padding: 2px;
+  outline: 0;
+  font-size: 12px;
+}
+
+.daterangepicker .calendar-time {
+  text-align: center;
+  margin: 4px auto 0 auto;
+  line-height: 30px;
+  position: relative;
+}
+
+.daterangepicker .calendar-time select.disabled {
+  color: #ccc;
+  cursor: not-allowed;
+}
+
+.daterangepicker .drp-buttons {
+  clear: both;
+  text-align: right;
+  padding: 8px;
+  border-top: 1px solid #ddd;
+  display: none;
+  line-height: 12px;
+  vertical-align: middle;
+}
+
+.daterangepicker .drp-selected {
+  display: inline-block;
+  font-size: 12px;
+  padding-right: 8px;
+}
+
+.daterangepicker .drp-buttons .btn {
+  margin-left: 8px;
+  font-size: 12px;
+  font-weight: bold;
+  padding: 4px 8px;
+}
+
+.daterangepicker.show-ranges .drp-calendar.left {
+  border-left: 1px solid #ddd;
+}
+
+.daterangepicker .ranges {
+  float: none;
+  text-align: left;
+  margin: 0;
+}
+
+.daterangepicker.show-calendar .ranges {
+  margin-top: 8px;
+}
+
+.daterangepicker .ranges ul {
+  list-style: none;
+  margin: 0 auto;
+  padding: 0;
+  width: 100%;
+}
+
+.daterangepicker .ranges li {
+  font-size: 12px;
+  padding: 8px 12px;
+  cursor: pointer;
+}
+
+.daterangepicker .ranges li:hover {
+  background-color: #eee;
+}
+
+.daterangepicker .ranges li.active {
+  background-color: #08c;
+  color: #fff;
+}
+
+/*  Larger Screen Styling */
+@media (min-width: 564px) {
+  .daterangepicker {
+    width: auto; }
+    .daterangepicker .ranges ul {
+      width: 140px; }
+    .daterangepicker.single .ranges ul {
+      width: 100%; }
+    .daterangepicker.single .drp-calendar.left {
+      clear: none; }
+    .daterangepicker.single.ltr .ranges, .daterangepicker.single.ltr .drp-calendar {
+      float: left; }
+    .daterangepicker.single.rtl .ranges, .daterangepicker.single.rtl .drp-calendar {
+      float: right; }
+    .daterangepicker.ltr {
+      direction: ltr;
+      text-align: left; }
+      .daterangepicker.ltr .drp-calendar.left {
+        clear: left;
+        margin-right: 0; }
+        .daterangepicker.ltr .drp-calendar.left .calendar-table {
+          border-right: none;
+          border-top-right-radius: 0;
+          border-bottom-right-radius: 0; }
+      .daterangepicker.ltr .drp-calendar.right {
+        margin-left: 0; }
+        .daterangepicker.ltr .drp-calendar.right .calendar-table {
+          border-left: none;
+          border-top-left-radius: 0;
+          border-bottom-left-radius: 0; }
+      .daterangepicker.ltr .drp-calendar.left .calendar-table {
+        padding-right: 8px; }
+      .daterangepicker.ltr .ranges, .daterangepicker.ltr .drp-calendar {
+        float: left; }
+    .daterangepicker.rtl {
+      direction: rtl;
+      text-align: right; }
+      .daterangepicker.rtl .drp-calendar.left {
+        clear: right;
+        margin-left: 0; }
+        .daterangepicker.rtl .drp-calendar.left .calendar-table {
+          border-left: none;
+          border-top-left-radius: 0;
+          border-bottom-left-radius: 0; }
+      .daterangepicker.rtl .drp-calendar.right {
+        margin-right: 0; }
+        .daterangepicker.rtl .drp-calendar.right .calendar-table {
+          border-right: none;
+          border-top-right-radius: 0;
+          border-bottom-right-radius: 0; }
+      .daterangepicker.rtl .drp-calendar.left .calendar-table {
+        padding-left: 12px; }
+      .daterangepicker.rtl .ranges, .daterangepicker.rtl .drp-calendar {
+        text-align: right;
+        float: right; } }
+@media (min-width: 730px) {
+  .daterangepicker .ranges {
+    width: auto; }
+  .daterangepicker.ltr .ranges {
+    float: left; }
+  .daterangepicker.rtl .ranges {
+    float: right; }
+  .daterangepicker .drp-calendar.left {
+    clear: none !important; } }

+ 0 - 0
modules/boonex/analytics/js/daterangepicker.js → modules/boonex/analytics/plugins/daterangepicker/daterangepicker.js


+ 1 - 1
modules/boonex/analytics/request.php

@@ -3,7 +3,7 @@
 * Copyright (c) UNA, Inc - https://una.io
 * MIT License - https://opensource.org/licenses/MIT
 *
- * @defgroup    Analytics Analytics
+* @defgroup    Analytics Analytics
 * @ingroup     UnaModules
 *
 * @{

+ 1 - 1
modules/boonex/analytics/template/canvas.html

@@ -1,5 +1,5 @@
 <script type="text/javascript" src="https://cdn.jsdelivr.net/momentjs/latest/moment.min.js"></script>
-<div id="BxAnalyticsContainer">
+<div id="bx_analytics_container">
     <div class="bx_analytics_filters">
         <select class="bx-def-font-inputs bx-form-input-select bx_analytics_module_selector">
             <bx_repeat:items>

Některé soubory nejsou zobrazeny, neboť je v těchto rozdílových datech změněno mnoho souborů