diff options
author | Ben Burgess <88810029+bx80@users.noreply.github.com> | 2022-05-24 10:51:06 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-05-24 10:51:06 +0300 |
commit | fdbcb562ef9e200c860fa3d40f664cac873ea8e8 (patch) | |
tree | 303d03c08977daa3603b443b637ba50c331a76fc /plugins/Goals | |
parent | 72f3d296d2b7dc6bb4348f401fa427262d72b374 (diff) |
Show sparkline evolution figures for visits, goals and ecommerce overviews (#19057)
* Add evolution to sparklines on the visits overview and the goals overview
* Add evolution to sparklines on the ecommerce overview
* Updated UI test screenshots
* Update submodule
* Fix for tooltip date formatting, improved translation lookup and callback method extra parameter documentation
* Sparklines API calls modified to return unformatted values, formatting added to the sparkline visualization and overview reports
* update submodule
* Updated inherited method signature
* Code improvements, added forcedParams parameter to ViewDataTable / Visualization loadDataTableFromAPI methods
* Revert change to loadDataTableFromAPI method signature in ViewDataTable and Visualization classes
* Remove incorrectly added file
* Improve international handling of plus symbol in ecommerce overview template
* Always use gigabytes when formatting byte values for evolution charts
* update sumbodule
* built vue files
* System test updates
* UI test screenshot updates
* Update submodule
* Test fix
* Test fixes
* Update system tests
* Rerun tests
* Fix for unformatted metrics when comparing
* Update UI test screenshots for sparkline comparisons
* apply some fixes
* Update submodule
Co-authored-by: sgiehl <stefan@matomo.org>
Co-authored-by: sgiehl <sgiehl@users.noreply.github.com>
Diffstat (limited to 'plugins/Goals')
6 files changed, 97 insertions, 40 deletions
diff --git a/plugins/Goals/Controller.php b/plugins/Goals/Controller.php index 045d177e4d..450b5648a8 100644 --- a/plugins/Goals/Controller.php +++ b/plugins/Goals/Controller.php @@ -358,11 +358,13 @@ class Controller extends \Piwik\Plugin\Controller return $topDimensions; } - protected function getMetricsForGoal($idGoal) + protected function getMetricsForGoal($idGoal, $dataRow = null) { - $request = new Request("method=Goals.get&format=original&idGoal=$idGoal"); - $datatable = $request->process(); - $dataRow = $datatable->getFirstRow(); + if (!$dataRow) { + $request = new Request("method=Goals.get&format=original&idGoal=$idGoal"); + $datatable = $request->process(); + $dataRow = $datatable->getFirstRow(); + } $nbConversions = $dataRow->getColumn('nb_conversions'); $nbVisitsConverted = $dataRow->getColumn('nb_visits_converted'); // Backward compatibility before 1.3, this value was not processed diff --git a/plugins/Goals/Reports/Get.php b/plugins/Goals/Reports/Get.php index 5d0f3b1411..ba5f9850d9 100644 --- a/plugins/Goals/Reports/Get.php +++ b/plugins/Goals/Reports/Get.php @@ -1,4 +1,5 @@ <?php + /** * Matomo - free/libre analytics platform * @@ -6,13 +7,20 @@ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later * */ + namespace Piwik\Plugins\Goals\Reports; use Piwik\API\Request; use Piwik\Common; use Piwik\DataTable; +use Piwik\DataTable\Filter\CalculateEvolutionFilter; +use Piwik\Metrics; +use Piwik\Metrics\Formatter as MetricFormatter; use Piwik\NumberFormatter; +use Piwik\Period\Month; +use Piwik\Period\Range; use Piwik\Piwik; +use Piwik\Period\Factory as PeriodFactory; use Piwik\Plugin; use Piwik\Plugin\ViewDataTable; use Piwik\Plugins\CoreVisualizations\Visualizations\JqplotGraph\Evolution; @@ -32,11 +40,11 @@ class Get extends Base parent::init(); $this->name = Piwik::translate('Goals_Goals'); - $this->processedMetrics = array('conversion_rate'); + $this->processedMetrics = ['conversion_rate']; $this->documentation = Piwik::translate('Goals_OverviewReportDocumentation'); $this->order = 1; $this->orderGoal = 50; - $this->metrics = array('nb_conversions', 'nb_visits_converted', 'revenue'); + $this->metrics = ['nb_conversions', 'nb_visits_converted', 'revenue']; $this->parameters = null; } @@ -52,7 +60,6 @@ class Get extends Base $goals = $this->getGoals(); if (!empty($goals[$goalId])) { - return $goals[$goalId]; } } @@ -111,7 +118,7 @@ class Get extends Base if ($onlySummary && !empty($idGoal)) { if (is_numeric($idGoal)) { - $view->config->title_attributes = array('goal-page-link' => $idGoal); + $view->config->title_attributes = ['goal-page-link' => $idGoal]; } // in Goals overview summary we show proper title for a goal @@ -123,63 +130,111 @@ class Get extends Base $view->config->title = ''; } - $numberFormatter = NumberFormatter::getInstance(); - $view->config->filters[] = function (DataTable $table) use ($numberFormatter, $idSite) { - $firstRow = $table->getFirstRow(); - if ($firstRow) { - $revenue = $firstRow->getColumn('revenue'); - $currencySymbol = Site::getCurrencySymbolFor($idSite); - $revenue = $numberFormatter->formatCurrency($revenue, $currencySymbol, GoalManager::REVENUE_PRECISION); - $firstRow->setColumn('revenue', $revenue); - } - }; - - $view->config->addTranslations(array( + $view->config->addTranslations([ 'nb_visits' => Piwik::translate('VisitsSummary_NbVisitsDescription'), 'nb_conversions' => Piwik::translate('Goals_ConversionsDescription'), 'nb_visits_converted' => Piwik::translate('General_NVisits'), 'conversion_rate' => Piwik::translate('Goals_OverallConversionRate'), 'revenue' => Piwik::translate('Goals_OverallRevenue'), - )); + ]); $allowMultiple = Common::getRequestVar('allow_multiple', 0, 'int'); if ($allowMultiple) { - $view->config->addSparklineMetric(array('nb_conversions', 'nb_visits_converted'), $order = 10); + $view->config->addSparklineMetric(['nb_conversions', 'nb_visits_converted'], $order = 10); } else { - $view->config->addSparklineMetric(array('nb_conversions'), $order = 10); + $view->config->addSparklineMetric(['nb_conversions'], $order = 10); } - $view->config->addSparklineMetric(array('conversion_rate'), $order = 20); + $view->config->addSparklineMetric(['conversion_rate'], $order = 20); if (empty($idGoal)) { // goals overview sparklines below evolution graph if ($isEcommerceEnabled) { // this would be ideally done in Ecommerce plugin but then it is hard to keep same order - $view->config->addSparklineMetric(array('revenue'), $order = 30); + $view->config->addSparklineMetric(['revenue'], $order = 30); } - } else { if ($onlySummary) { // in Goals Overview we list an overview for each goal.... $view->config->addTranslation('conversion_rate', Piwik::translate('Goals_ConversionRate')); - } elseif ($isEcommerceEnabled) { // in Goals detail page... - $view->config->addSparklineMetric(array('revenue'), $order = 30); + $view->config->addSparklineMetric(['revenue'], $order = 30); } } - } else if ($view->isViewDataTableId(Evolution::ID)) { + + // Add evolution values to sparklines + [$lastPeriodDate, $ignore] = Range::getLastDate(); + if ($lastPeriodDate !== false) { + + /** @var DataTable $previousData */ + $previousData = Request::processRequest('Goals.get', ['date' => $lastPeriodDate, 'format_metrics' => '0']); + $previousDataRow = $previousData->getFirstRow(); + + $currentPeriod = PeriodFactory::build(Piwik::getPeriod(), Common::getRequestVar('date')); + $currentPrettyDate = ($currentPeriod instanceof Month ? $currentPeriod->getLocalizedLongString() : $currentPeriod->getPrettyString()); + $lastPeriod = PeriodFactory::build(Piwik::getPeriod(), $lastPeriodDate); + $lastPrettyDate = ($currentPeriod instanceof Month ? $lastPeriod->getLocalizedLongString() : $lastPeriod->getPrettyString()); + + $view->config->compute_evolution = function ($columns, $metrics) use ($currentPrettyDate, $lastPrettyDate, $previousDataRow, $idSite) { + + $value = reset($columns); + $columnName = key($columns); + $pastValue = $previousDataRow->getColumn($columnName); + + if (!is_numeric($value)) { + return; + } + + // Format + $formatter = new MetricFormatter(); + $currentValueFormatted = $value; + $pastValueFormatted = $pastValue; + foreach ($metrics as $metric) { + if ($metric->getName() === $columnName) { + $pastValueFormatted = $metric->format($pastValue, $formatter); + $currentValueFormatted = $metric->format($value, $formatter); + break; + } + } + + if (strpos($columnName, 'revenue') !== false) { + $currencySymbol = Site::getCurrencySymbolFor($idSite); + $pastValueFormatted = NumberFormatter::getInstance()->formatCurrency($pastValue, $currencySymbol, GoalManager::REVENUE_PRECISION); + $currentValueFormatted = NumberFormatter::getInstance()->formatCurrency($value, $currencySymbol, GoalManager::REVENUE_PRECISION); + } + + $columnTranslations = Metrics::getDefaultMetricTranslations(); + $columnTranslation = ''; + if (array_key_exists($columnName, $columnTranslations)) { + $columnTranslation = $columnTranslations[$columnName]; + } + + return [ + 'currentValue' => $value, + 'pastValue' => $pastValue, + 'tooltip' => Piwik::translate('General_EvolutionSummaryGeneric', [ + $currentValueFormatted . ' ' . $columnTranslation, + $currentPrettyDate, + $pastValueFormatted . ' ' . $columnTranslation, + $lastPrettyDate, + CalculateEvolutionFilter::calculate($value, $pastValue, $precision = 1) + ]), + ]; + }; + } + } elseif ($view->isViewDataTableId(Evolution::ID)) { if (!empty($idSite) && Piwik::isUserHasWriteAccess($idSite)) { - $view->config->title_edit_entity_url = 'index.php' . Url::getCurrentQueryStringWithParametersModified(array( + $view->config->title_edit_entity_url = 'index.php' . Url::getCurrentQueryStringWithParametersModified([ 'module' => 'Goals', 'action' => 'manage', 'forceView' => null, 'viewDataTable' => null, 'showtitle' => null, 'random' => null - )); + ]); } $goal = $this->getGoal($idGoal); @@ -193,7 +248,7 @@ class Get extends Base } if (empty($view->config->columns_to_display)) { - $view->config->columns_to_display = array('nb_conversions'); + $view->config->columns_to_display = ['nb_conversions']; } } } diff --git a/plugins/Goals/tests/UI/expected-screenshots/GoalsPages_ecommerce.png b/plugins/Goals/tests/UI/expected-screenshots/GoalsPages_ecommerce.png index 0d2e28a482..6a66904b4f 100644 --- a/plugins/Goals/tests/UI/expected-screenshots/GoalsPages_ecommerce.png +++ b/plugins/Goals/tests/UI/expected-screenshots/GoalsPages_ecommerce.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:33a3afeb3540e24a1eb929c022114c6d9ea1fe1c9f271d74b908d55861b3fe4b -size 76261 +oid sha256:b8cc5d0a442b27bdb6498f85ce0eeebb475d736a91a6bfd242f358805a62623a +size 81709 diff --git a/plugins/Goals/tests/UI/expected-screenshots/GoalsPages_individual_goal.png b/plugins/Goals/tests/UI/expected-screenshots/GoalsPages_individual_goal.png index afe451f5df..a3288fe939 100644 --- a/plugins/Goals/tests/UI/expected-screenshots/GoalsPages_individual_goal.png +++ b/plugins/Goals/tests/UI/expected-screenshots/GoalsPages_individual_goal.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0ac52a11e25e786fcf4d15067f1732b8ecac7058876ea79e72ed57874cc94974 -size 200161 +oid sha256:95c851c648cf543352e78f63a6e80b425dca08d7e1c3715baf4e0c425d4b74fb +size 201716 diff --git a/plugins/Goals/tests/UI/expected-screenshots/GoalsPages_individual_goal_updated.png b/plugins/Goals/tests/UI/expected-screenshots/GoalsPages_individual_goal_updated.png index d4e72bb065..d4787789b0 100644 --- a/plugins/Goals/tests/UI/expected-screenshots/GoalsPages_individual_goal_updated.png +++ b/plugins/Goals/tests/UI/expected-screenshots/GoalsPages_individual_goal_updated.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:72e576d64c1732bdf480747a17f92511b57588c643ed5dce1217daf618fc202f -size 201041 +oid sha256:2cf473eef5935fecea595337e53099e721c8090dbdbd99ebf1907d1b22aeaf7d +size 206484 diff --git a/plugins/Goals/tests/UI/expected-screenshots/GoalsPages_overview.png b/plugins/Goals/tests/UI/expected-screenshots/GoalsPages_overview.png index 3bb51b9f70..43b2aeba83 100644 --- a/plugins/Goals/tests/UI/expected-screenshots/GoalsPages_overview.png +++ b/plugins/Goals/tests/UI/expected-screenshots/GoalsPages_overview.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:601a598d35e2914b002510549c090229ee8d676b996531debcb42f2c1180f476 -size 165909 +oid sha256:6c06b4c92247abb95c0263b9b371c91a3e5beec4029ee079edcf397dc969bbde +size 175144 |