@tsteur opened this Issue on November 30th 2022 Member

Currently, when viewing a sparkline over a longer data range, then we're visualising the data of every single day in that range. When you fetch a period of one year, it means Matomo has to select 365 different archives and plot each single dot on the sparkline.

Example:

image

To improve performance, and also to see trends better, we want to change the period used to plot the sparkline depending on the selected date range.

Expected outcomes:

  • If a range of 24+ months is selected, then in the UI show the sparklines for the selected range for months.
    • For example, if a date range of 2018-06-21,2022-04-19 is selected, then we show the sparklines for the months from June 2018 to April 2022.
  • If a range of 6+ months is selected, then in the UI show the sparklines for the selected range for weeks.
    • For example, if a date range of 2022-02-21,2022-10-19 is selected, then we show the sparklines for the week of 2022-02-21 to the week of 2022-10-19.
  • If a range of less than 6 months is selected, then we keep showing it as before.
  • In the user interface, when hovering a sparkline, we should show a tooltip which data/period is shown in the sparkline graphs. Meaning which period and which dates. Like in the case of a selected date range 2022-02-21,2022-10-19 we would say something like "This sparklines shows the evolution over time from $periodStart to $periodEnd. Each data point represents a $period."
  • When comparison different dates feature is used, then people might be comparing different ranges. This means we can maybe only convert to week/month if both the original range and the comparison range is of a certain length. When comparing only different periods then we can still easily use the same period.

Technical note:
We don't need to change the Sparkline visualisation itself but could simply change the Sparklines visualisation in above cases to not use range but week or month when needed. This way can then also more easily adjust the tooltip.

Example diff below (not taking into account yet the comparison feature)

diff --git a/plugins/CoreVisualizations/Visualizations/Sparklines.php b/plugins/CoreVisualizations/Visualizations/Sparklines.php
index 6ed99cea4f..e6e81c8979 100644
--- a/plugins/CoreVisualizations/Visualizations/Sparklines.php
+++ b/plugins/CoreVisualizations/Visualizations/Sparklines.php
@@ -13,6 +13,7 @@ namespace Piwik\Plugins\CoreVisualizations\Visualizations;
 use Piwik\API\Request;
 use Piwik\Common;
 use Piwik\DataTable;
+use Piwik\Date;
 use Piwik\Metrics;
 use Piwik\Metrics\Formatter as MetricFormatter;
 use Piwik\Period\Factory;
@@ -174,7 +175,8 @@ class Sparklines extends ViewDataTable
         $originalDate = Common::getRequestVar('date');
         $originalPeriod = Common::getRequestVar('period');

-        if ($this->isComparing() && !empty($comparisons)) {
+        $isComparing = $this->isComparing() && !empty($comparisons); 
+        if ($isComparing) {
             $comparisonRows = [];
             foreach ($comparisons->getRows() as $comparisonRow) {
                 $segment = $comparisonRow->getMetadata('compareSegment');
@@ -227,7 +229,23 @@ class Sparklines extends ViewDataTable
                 'action'  => $this->requestConfig->getApiMethodToRequest()
             ]);

-            if ($this->isComparing() && !empty($comparisons)) {
+            if ($originalPeriod === 'range' && !$isComparing) { // todo check for comparing segments it would still work to select different period but problem when comparing different periods
+                // when comparing, we have to fallback to a range because different periods might be selected.
+                // when not comparing and a longer range is selected, then we select a higher period for improved
+                // performance and also to see trends better
+                $periodObj = Factory::build($originalPeriod, $originalDate);
+                $numDaysInRange = $this->getNumDaysDifference($periodObj->getDateStart(), $periodObj->getDateEnd());
+                if ($numDaysInRange >= 730) {
+                    $sparklineUrlParams['period'] = 'month';
+                    $sparklineUrlParams['date'] = $originalDate;
+                } elseif ($numDaysInRange >= 180) {
+                    $sparklineUrlParams['period'] = 'week';
+                    $sparklineUrlParams['date'] = $originalDate;
+                }
+            }
+
+
+            if ($isComparing) {
                 $periodObj = Factory::build($originalPeriod, $originalDate);

                 $sparklineUrlParams['compareSegments'] = [];
@@ -285,6 +303,7 @@ class Sparklines extends ViewDataTable
                         'period' => $periodObj->getLabel(),
                         'date' => $periodObj->getLabel() === 'range' ? $periodObj->getRangeString() : $periodObj->getDateEnd(),
                     ]);
+
                     $this->config->addSparkline($params, $metrics, $desc = null, null, ($order * 100) + $segmentIndex, $title, $sparklineMetricIndex, $seriesIndices, $graphParams);
                 }
             } else {
@@ -322,6 +341,12 @@ class Sparklines extends ViewDataTable
         }
     }

+    private function getNumDaysDifference(Date $date1, Date $date2)
+    {
+        $days = (abs($date1->getTimestamp() - $date2->getTimestamp())) / 60 / 60 / 24;
+        return (int) round($days);
+    }
+
     private function applyFilters(DataTable\DataTableInterface $table)
     {
         foreach ($this->config->getPriorityFilters() as $filter) {
diff --git a/plugins/CoreVisualizations/Visualizations/Sparklines/Config.php b/plugins/CoreVisualizations/Visualizations/Sparklines/Config.php
index caf77a7b11..6cd87f6e7f 100644
--- a/plugins/CoreVisualizations/Visualizations/Sparklines/Config.php
+++ b/plugins/CoreVisualizations/Visualizations/Sparklines/Config.php
@@ -13,6 +13,7 @@ use Piwik\DataTable\Filter\CalculateEvolutionFilter;
 use Piwik\Metrics;
 use Piwik\NoAccessException;
 use Piwik\Period\Range;
+use Piwik\Piwik;
 use Piwik\Site;
 use Piwik\Url;

@@ -284,8 +285,15 @@ class Config extends \Piwik\ViewDataTable\Config
             $groupedMetrics[$metricGroup][] = $metricInfo;
         }

+        $tooltip = '';
+        if (!empty($requestParamsForSparkline['period'])) {
+            $tooltip = Piwik::translate('Each data point in the sparkline represents a %s.',
+                $requestParamsForSparkline['period'] === 'range' ? 'day' : $requestParamsForSparkline['period']);
+        }
+
         $sparkline = array(
             'url' => $this->getUrlSparkline($requestParamsForSparkline),
+            'tooltip' => $tooltip,
             'metrics' => $groupedMetrics,
             'order' => $this->getSparklineOrder($order),
             'title' => $title,
diff --git a/plugins/CoreVisualizations/templates/macros.twig b/plugins/CoreVisualizations/templates/macros.twig
index ea80c087bb..1c748b3bff 100644
--- a/plugins/CoreVisualizations/templates/macros.twig
+++ b/plugins/CoreVisualizations/templates/macros.twig
@@ -25,7 +25,9 @@
          {% if sparkline.seriesIndices|default is not empty %}data-series-indices="{{ sparkline.seriesIndices|json_encode|e('html_attr') }}"{% endif %}
          {% if sparkline.graphParams|default is not empty %}data-graph-params="{{ sparkline.graphParams|json_encode|e('html_attr') }}"{% endif %}
     >
-        <div>
+        <div
+            {% if sparkline.tooltip|default %}title="{{ sparkline.tooltip|e('html_attr') }}"{% endif %}
+        >
             {% if sparkline.title|default is not empty %}<h6 class="sparkline-title" title="{{ sparkline.title|rawSafeDecoded|e('html_attr') }}">{{ sparkline.title }}</h6>{% endif %}
             {% if sparkline.url %}{{ sparkline(sparkline.url)|raw }}{% endif %}

@mattab can you check out this one?

This Issue was closed on December 12th 2022
Powered by GitHub Issue Mirror