add icons for Character groups

This commit is contained in:
coderkun 2014-04-29 14:18:04 +02:00
commit 2d9a41a5fe
3461 changed files with 594457 additions and 0 deletions

View file

@ -0,0 +1,350 @@
<?php
/**
* Piwik - Open source web analytics
*
* @link http://piwik.org
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
*
*/
namespace Piwik\Plugins\Insights;
use Piwik\DataTable;
use Piwik\Date;
use Piwik\Log;
use Piwik\Period\Range;
use Piwik\Piwik;
use Piwik\Plugins\API\ProcessedReport;
use Piwik\API\Request as ApiRequest;
use Piwik\Plugins\VisitsSummary\API as VisitsSummaryAPI;
/**
* API for plugin Insights
*
* @method static \Piwik\Plugins\Insights\API getInstance()
*/
class API extends \Piwik\Plugin\API
{
/**
* Include only 'movers' which are existing in the current and past report.
*/
const FILTER_BY_MOVERS = 'movers';
/**
* Include only 'new' rows which were not existing in the past report.
*/
const FILTER_BY_NEW = 'new';
/**
* Include only 'disappeared' rows which were existing in the past report but no longer in the current report.
*/
const FILTER_BY_DISAPPEARED = 'disappeared';
/**
* @var Model
*/
private $model;
protected function __construct()
{
parent::__construct();
$this->model = new Model();
}
private function getOverviewReports()
{
$reports = array();
/**
* Triggered to gather all reports to be displayed in the "Insight" and "Movers And Shakers" overview reports.
* Plugins that want to add new reports to the overview should subscribe to this event and add reports to the
* incoming array. API parameters can be configured as an array optionally.
*
* **Example**
*
* public function addReportToInsightsOverview(&$reports)
* {
* $reports['Actions_getPageUrls'] = array();
* $reports['Actions_getDownloads'] = array('flat' => 1, 'minGrowthPercent' => 60);
* }
*
* @param array &$reports An array containing a report unique id as key and an array of API parameters as
* values.
*/
Piwik::postEvent('Insights.addReportToOverview', array(&$reports));
return $reports;
}
/**
* Detects whether insights can be generated for this date/period combination or not.
* @param string $date eg 'today', '2012-12-12'
* @param string $period eg 'day' or 'week'
*
* @return bool
*/
public function canGenerateInsights($date, $period)
{
Piwik::checkUserHasSomeViewAccess();
try {
$model = new Model();
$lastDate = $model->getLastDate($date, $period, 1);
} catch (\Exception $e) {
return false;
}
if (empty($lastDate)) {
return false;
}
return true;
}
/**
* Generates insights for a set of reports. Plugins can add their own reports to be included in the insights
* overview by listening to the {@hook Insights.addReportToOverview} event.
*
* @param int $idSite
* @param string $period
* @param string $date
* @param bool|string $segment
*
* @return DataTable\Map A map containing a dataTable for each insight report. See {@link getInsights()} for more
* information
*/
public function getInsightsOverview($idSite, $period, $date, $segment = false)
{
Piwik::checkUserHasViewAccess($idSite);
$defaultParams = array(
'limitIncreaser' => 3,
'limitDecreaser' => 3,
'minImpactPercent' => 1,
'minGrowthPercent' => 25,
);
$map = $this->generateOverviewReport('getInsights', $idSite, $period, $date, $segment, $defaultParams);
return $map;
}
/**
* Detects the movers and shakers for a set of reports. Plugins can add their own reports to be included in this
* overview by listening to the {@hook Insights.addReportToOverview} event.
*
* @param int $idSite
* @param string $period
* @param string $date
* @param bool|string $segment
*
* @return DataTable\Map A map containing a dataTable for each movers and shakers report. See
* {@link getMoversAndShakers()} for more information
*/
public function getMoversAndShakersOverview($idSite, $period, $date, $segment = false)
{
Piwik::checkUserHasViewAccess($idSite);
$defaultParams = array(
'limitIncreaser' => 4,
'limitDecreaser' => 4
);
$map = $this->generateOverviewReport('getMoversAndShakers', $idSite, $period, $date, $segment, $defaultParams);
return $map;
}
private function generateOverviewReport($method, $idSite, $period, $date, $segment, array $defaultParams)
{
$tableManager = DataTable\Manager::getInstance();
/** @var DataTable[] $tables */
$tables = array();
foreach ($this->getOverviewReports() as $reportId => $reportParams) {
if (!empty($reportParams)) {
foreach ($defaultParams as $key => $defaultParam) {
if (!array_key_exists($key, $reportParams)) {
$reportParams[$key] = $defaultParam;
}
}
}
$firstTableId = $tableManager->getMostRecentTableId();
$table = $this->requestApiMethod($method, $idSite, $period, $date, $reportId, $segment, $reportParams);
$reportTableIds[] = $table->getId();
$tableManager->deleteTablesExceptIgnored($reportTableIds, $firstTableId);
$tables[] = $table;
}
$map = new DataTable\Map();
foreach ($tables as $table) {
$map->addTable($table, $table->getMetadata('reportName'));
}
return $map;
}
/**
* Detects the movers and shakers of a given date / report combination. A mover and shakers has an higher impact
* than other rows on average. For instance if a sites pageviews increase by 10% a page that increased by 40% at the
* same time contributed significantly more to the success than the average of 10%.
*
* @param int $idSite
* @param string $period
* @param string $date
* @param string $reportUniqueId eg 'Actions_getPageUrls'. An id like 'Goals_getVisitsUntilConversion_idGoal--4' works as well.
* @param bool|string $segment
* @param int $comparedToXPeriods
* @param int $limitIncreaser Value '0' ignores all increasers
* @param int $limitDecreaser Value '0' ignores all decreasers
*
* @return DataTable
*
* @throws \Exception In case a report having the given ID does not exist
* @throws \Exception In case the report exists but does not return a dataTable
*/
public function getMoversAndShakers($idSite, $period, $date, $reportUniqueId, $segment = false,
$comparedToXPeriods = 1, $limitIncreaser = 4, $limitDecreaser = 4)
{
Piwik::checkUserHasViewAccess(array($idSite));
$metric = 'nb_visits';
$orderBy = InsightReport::ORDER_BY_ABSOLUTE;
$reportMetadata = $this->model->getReportByUniqueId($idSite, $reportUniqueId);
if (empty($reportMetadata)) {
throw new \Exception('A report having the ID ' . $reportUniqueId . ' does not exist');
}
$totalValue = $this->model->getTotalValue($idSite, $period, $date, $metric);
$currentReport = $this->model->requestReport($idSite, $period, $date, $reportUniqueId, $metric, $segment);
$this->checkReportIsValid($currentReport);
$lastDate = $this->model->getLastDate($date, $period, $comparedToXPeriods);
$lastTotalValue = $this->model->getTotalValue($idSite, $period, $lastDate, $metric);
$lastReport = $this->model->requestReport($idSite, $period, $lastDate, $reportUniqueId, $metric, $segment);
$this->checkReportIsValid($lastReport);
$insight = new InsightReport();
return $insight->generateMoverAndShaker($reportMetadata, $period, $date, $lastDate, $metric, $currentReport, $lastReport, $totalValue, $lastTotalValue, $orderBy, $limitIncreaser, $limitDecreaser);
}
/**
* Generates insights by comparing the report for a given date/period with a different date and calculating the
* difference. The API can exclude rows which growth is not good enough or did not have enough impact.
*
* @param int $idSite
* @param string $period
* @param string $date
* @param string $reportUniqueId eg 'Actions_getPageUrls'. An id like 'Goals_getVisitsUntilConversion_idGoal--4' works as well.
* @param bool|string $segment
* @param int $limitIncreaser Value '0' ignores all increasers
* @param int $limitDecreaser Value '0' ignores all decreasers
* @param string $filterBy By default all rows will be ignored. If given only 'movers', 'new' or 'disappeared' will be returned.
* @param int $minImpactPercent The minimum impact in percent. Eg '2%' of 1000 visits means the change /
* increase / decrease has to be at least 20 visits. Usually the '2%' are based on the total
* amount of visits but for reports having way less visits the metric total is used. Eg A page
* has 1000 visits but only 100 visits having keywords. In this case a minimum impact of '2%' evaluates to 2 and not 20.
* @param int $minGrowthPercent The amount of percent a row has to increase or decrease at least compared to the previous period.
* If value is '20' the growth has to be either at least '+20%' or '-20%' and lower.
* @param int $comparedToXPeriods The report will be compared to X periods before.
* @param string $orderBy Orders the rows by 'absolute', 'relative' or 'importance'.
*
* @return DataTable
*
* @throws \Exception In case a report having the given ID does not exist
* @throws \Exception In case the report exists but does not return a dataTable
*/
public function getInsights(
$idSite, $period, $date, $reportUniqueId, $segment = false, $limitIncreaser = 5, $limitDecreaser = 5,
$filterBy = '', $minImpactPercent = 2, $minGrowthPercent = 20,
$comparedToXPeriods = 1, $orderBy = 'absolute')
{
Piwik::checkUserHasViewAccess(array($idSite));
$metric = 'nb_visits';
$reportMetadata = $this->model->getReportByUniqueId($idSite, $reportUniqueId);
if (empty($reportMetadata)) {
throw new \Exception('A report having the ID ' . $reportUniqueId . ' does not exist');
}
$totalValue = $this->model->getTotalValue($idSite, $period, $date, $metric);
$currentReport = $this->model->requestReport($idSite, $period, $date, $reportUniqueId, $metric, $segment);
$this->checkReportIsValid($currentReport);
$lastDate = $this->model->getLastDate($date, $period, $comparedToXPeriods);
$lastTotalValue = $this->model->getTotalValue($idSite, $period, $lastDate, $metric);
$lastReport = $this->model->requestReport($idSite, $period, $lastDate, $reportUniqueId, $metric, $segment);
$this->checkReportIsValid($lastReport);
$minGrowthPercentPositive = abs($minGrowthPercent);
$minGrowthPercentNegative = -1 * $minGrowthPercentPositive;
$relevantTotal = $this->model->getRelevantTotalValue($currentReport, $metric, $totalValue);
$minMoversPercent = -1;
$minNewPercent = -1;
$minDisappearedPercent = -1;
switch ($filterBy) {
case self::FILTER_BY_MOVERS:
$minMoversPercent = $minImpactPercent;
break;
case self::FILTER_BY_NEW:
$minNewPercent = $minImpactPercent;
break;
case self::FILTER_BY_DISAPPEARED:
$minDisappearedPercent = $minImpactPercent;
break;
default:
$minMoversPercent = $minImpactPercent;
$minNewPercent = $minImpactPercent;
$minDisappearedPercent = $minImpactPercent;
}
$insight = new InsightReport();
$table = $insight->generateInsight($reportMetadata, $period, $date, $lastDate, $metric, $currentReport, $lastReport, $relevantTotal, $minMoversPercent, $minNewPercent, $minDisappearedPercent, $minGrowthPercentPositive, $minGrowthPercentNegative, $orderBy, $limitIncreaser, $limitDecreaser);
$insight->markMoversAndShakers($table, $currentReport, $lastReport, $totalValue, $lastTotalValue);
return $table;
}
private function checkReportIsValid($report)
{
if (!($report instanceof DataTable)) {
throw new \Exception('Insight can be only generated for reports returning a dataTable');
}
}
private function requestApiMethod($method, $idSite, $period, $date, $reportId, $segment, $additionalParams)
{
$params = array(
'method' => 'Insights.' . $method,
'idSite' => $idSite,
'date' => $date,
'period' => $period,
'format' => 'original',
'reportUniqueId' => $reportId,
);
if (!empty($segment)) {
$params['segment'] = $segment;
}
if (!empty($additionalParams)) {
foreach ($additionalParams as $key => $value) {
$params[$key] = $value;
}
}
$request = new ApiRequest($params);
return $request->process();
}
}

View file

@ -0,0 +1,84 @@
<?php
/**
* Piwik - Open source web analytics
*
* @link http://piwik.org
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
*
*/
namespace Piwik\Plugins\Insights;
use Piwik\Common;
use Piwik\Piwik;
use Piwik\Plugins\Insights\Visualizations\Insight;
use Piwik\View;
/**
* Insights Controller
*/
class Controller extends \Piwik\Plugin\Controller
{
public function __construct()
{
$idSite = Common::getRequestVar('idSite', null, 'int');
Piwik::checkUserHasViewAccess($idSite);
}
public function getInsightsOverview()
{
$view = $this->prepareWidgetView('insightsOverviewWidget.twig');
$view->reports = $this->requestApiReport('getInsightsOverview');
return $view->render();
}
public function getOverallMoversAndShakers()
{
$view = $this->prepareWidgetView('moversAndShakersOverviewWidget.twig');
$view->reports = $this->requestApiReport('getMoversAndShakersOverview');
return $view->render();
}
private function prepareWidgetView($template)
{
if (!$this->canGenerateInsights()) {
$view = new View('@Insights/cannotDisplayReport.twig');
$this->setBasicVariablesView($view);
return $view;
}
$view = new View('@Insights/' . $template);
$this->setBasicVariablesView($view);
$view->properties = array(
'order_by' => InsightReport::ORDER_BY_ABSOLUTE
);
return $view;
}
private function requestApiReport($apiReport)
{
if (!$this->canGenerateInsights()) {
return;
}
$idSite = Common::getRequestVar('idSite', null, 'int');
$period = Common::getRequestVar('period', null, 'string');
$date = Common::getRequestVar('date', null, 'string');
return API::getInstance()->$apiReport($idSite, $period, $date);
}
private function canGenerateInsights()
{
$period = Common::getRequestVar('period', null, 'string');
$date = Common::getRequestVar('date', null, 'string');
return API::getInstance()->canGenerateInsights($date, $period);
}
}

View file

@ -0,0 +1,56 @@
<?php
/**
* Piwik - Open source web analytics
*
* @link http://piwik.org
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
*
*/
namespace Piwik\Plugins\Insights\DataTable\Filter;
use Piwik\DataTable;
/**
* Removes all rows whose value is too low.
*/
class ExcludeLowValue extends DataTable\BaseFilter
{
private $minimumValue;
private $columnToRead;
private $columnToCheckToBeTrue;
/**
* @param DataTable $table
* @param string $columnToRead
* @param int $minimumValue
* @param string $columnToCheckToBeTrue if set, we will delete a row only if this column evaluates to true. If
* column does not evaluate to true we will not delete the row even if
* the value is lower than the minimumValue.
*/
public function __construct($table, $columnToRead, $minimumValue, $columnToCheckToBeTrue = '')
{
$this->columnToRead = $columnToRead;
$this->minimumValue = $minimumValue;
$this->columnToCheckToBeTrue = $columnToCheckToBeTrue;
}
public function filter($table)
{
if (!$this->minimumValue) {
return;
}
foreach ($table->getRows() as $key => $row) {
if ($this->columnToCheckToBeTrue && !$row->getColumn($this->columnToCheckToBeTrue)) {
continue;
}
$value = $row->getColumn($this->columnToRead);
if ($this->minimumValue > abs($value)) {
$table->deleteRow($key);
}
}
}
}

View file

@ -0,0 +1,119 @@
<?php
/**
* Piwik - Open source web analytics
*
* @link http://piwik.org
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
*
*/
namespace Piwik\Plugins\Insights\DataTable\Filter;
use Piwik\DataTable;
class Insight extends DataTable\Filter\CalculateEvolutionFilter
{
private $considerMovers;
private $considerNew;
private $considerDisappeared;
private $currentDataTable;
public function __construct($table, $currentDataTable, $pastDataTable, $columnToRead,
$considerMovers, $considerNew, $considerDisappeared)
{
parent::__construct($table, $pastDataTable, 'growth', $columnToRead, $quotientPrecision = 1);
$this->currentDataTable = $currentDataTable;
$this->considerMovers = $considerMovers;
$this->considerNew = $considerNew;
$this->considerDisappeared = $considerDisappeared;
}
public function filter($table)
{
foreach ($this->currentDataTable->getRows() as $row) {
$this->addRowIfNewOrMover($table, $row);
}
if ($this->considerDisappeared) {
foreach ($this->pastDataTable->getRows() as $row) {
$this->addRowIfDisappeared($table, $row);
}
}
}
private function addRowIfDisappeared(DataTable $table, DataTable\Row $row)
{
if ($this->getRowFromTable($this->currentDataTable, $row)) {
return;
}
$newValue = 0;
$oldValue = $row->getColumn($this->columnValueToRead);
$difference = $newValue - $oldValue;
if ($oldValue == 0 && $newValue == 0) {
$growthPercentage = '0%';
} else {
$growthPercentage = '-100%';
}
$this->addRow($table, $row, $growthPercentage, $newValue, $oldValue, $difference, $isDisappeared = true);
}
private function addRowIfNewOrMover(DataTable $table, DataTable\Row $row)
{
$pastRow = $this->getPastRowFromCurrent($row);
if (!$pastRow && !$this->considerNew) {
return;
} elseif ($pastRow && !$this->considerMovers) {
return;
}
$isNew = false;
$isMover = false;
$isDisappeared = false;
if (!$pastRow) {
$isNew = true;
$oldValue = 0;
} else {
$isMover = true;
$oldValue = $pastRow->getColumn($this->columnValueToRead);
}
$difference = $this->getDividend($row);
if ($difference === false) {
return;
}
$newValue = $row->getColumn($this->columnValueToRead);
$divisor = $this->getDivisor($row);
$growthPercentage = $this->formatValue($difference, $divisor);
$this->addRow($table, $row, $growthPercentage, $newValue, $oldValue, $difference, $isDisappeared, $isNew, $isMover);
}
private function getRowFromTable(DataTable $table, DataTable\Row $row)
{
return $table->getRowFromLabel($row->getColumn('label'));
}
private function addRow(DataTable $table, DataTable\Row $row, $growthPercentage, $newValue, $oldValue, $difference, $disappeared = false, $isNew = false, $isMover = false)
{
$columns = $row->getColumns();
$columns['growth_percent'] = $growthPercentage;
$columns['growth_percent_numeric'] = str_replace('%', '', $growthPercentage);
$columns['grown'] = '-' != substr($growthPercentage, 0 , 1);
$columns['value_old'] = $oldValue;
$columns['value_new'] = $newValue;
$columns['difference'] = $difference;
$columns['importance'] = abs($difference);
$columns['isDisappeared'] = $disappeared;
$columns['isNew'] = $isNew;
$columns['isMover'] = $isMover;
$table->addRowFromArray(array(DataTable\Row::COLUMNS => $columns));
}
}

View file

@ -0,0 +1,54 @@
<?php
/**
* Piwik - Open source web analytics
*
* @link http://piwik.org
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
*
*/
namespace Piwik\Plugins\Insights\DataTable\Filter;
use Piwik\DataTable\BaseFilter;
/**
* Limits the number of positive and negative values. A value is considered as positive if the value of $columnToRead
* is 0 or higher. A value is considered as negative in all other cases (< 0).
*/
class Limit extends BaseFilter
{
private $limitPositive;
private $limitNegative;
private $columnToRead;
public function __construct($table, $columnToRead, $limitPositiveValues, $limitNegativeValues)
{
$this->columnToRead = $columnToRead;
$this->limitPositive = (int) $limitPositiveValues;
$this->limitNegative = (int) $limitNegativeValues;
}
public function filter($table)
{
$countIncreaser = 0;
$countDecreaser = 0;
foreach ($table->getRows() as $key => $row) {
if ($row->getColumn($this->columnToRead) >= 0) {
$countIncreaser++;
if ($countIncreaser > $this->limitPositive) {
$table->deleteRow($key);
}
} else {
$countDecreaser++;
if ($countDecreaser > $this->limitNegative) {
$table->deleteRow($key);
}
}
}
}
}

View file

@ -0,0 +1,51 @@
<?php
/**
* Piwik - Open source web analytics
*
* @link http://piwik.org
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
*
*/
namespace Piwik\Plugins\Insights\DataTable\Filter;
use Piwik\DataTable\BaseFilter;
use Piwik\DataTable;
/**
* A row will be deleted if a positive value of $columnToRead is lower than the $minPositiveValue or if the negative
* value of $columnToRead is higher than the $minNegativeValue.
* That means a row will be deleted if the value is between $minNegativeValue and $minPositiveValue.
*/
class MinGrowth extends BaseFilter
{
private $minPositiveValue;
private $minNegativeValue;
private $columnToRead;
public function __construct($table, $columnToRead, $minPositiveValue, $minNegativeValue)
{
$this->columnToRead = $columnToRead;
$this->minPositiveValue = $minPositiveValue;
$this->minNegativeValue = $minNegativeValue;
}
public function filter($table)
{
if (!$this->minPositiveValue && !$this->minNegativeValue) {
return;
}
foreach ($table->getRows() as $key => $row) {
$growthNumeric = $row->getColumn($this->columnToRead);
if ($growthNumeric >= $this->minPositiveValue && $growthNumeric >= 0) {
continue;
} elseif ($growthNumeric <= $this->minNegativeValue && $growthNumeric < 0) {
continue;
}
$table->deleteRow($key);
}
}
}

View file

@ -0,0 +1,92 @@
<?php
/**
* Piwik - Open source web analytics
*
* @link http://piwik.org
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
*
*/
namespace Piwik\Plugins\Insights\DataTable\Filter;
use Piwik\DataTable\BaseFilter;
use Piwik\DataTable\Row;
/**
* Goal is to list all positive values first (the higher the better) and then all negative values (the lower the better).
*
* 40%
* 20%
* 0%
* -40%
* -20%
*/
class OrderBy extends BaseFilter
{
private $columnsToCheck;
public function __construct($table, $columnToRead, $columnSecondOrder, $columnThirdOrder = '')
{
$this->columnsToCheck = array($columnToRead, $columnSecondOrder, $columnThirdOrder);
}
public function filter($table)
{
if (!$table->getRowsCount()) {
return;
}
$table->sort(array($this, 'sort'), $this->columnsToCheck[0]);
}
public function sort(Row $a, Row $b)
{
foreach ($this->columnsToCheck as $column) {
if ($column) {
$valA = $a->getColumn($column);
$valB = $b->getColumn($column);
$sort = $this->sortVal($valA, $valB);
if (isset($sort)) {
return $sort;
}
}
}
return 0;
}
private function sortVal($valA, $valB)
{
if ((!isset($valA) || $valA === false) && (!isset($valB) || $valB === false)) {
return 0;
}
if (!isset($valA) || $valA === false) {
return 1;
}
if (!isset($valB) || $valB === false) {
return -1;
}
if ($valA === $valB) {
return null;
}
if ($valA >= 0 && $valB < 0) {
return -1;
}
if ($valA < 0 && $valB < 0) {
return $valA < $valB ? -1 : 1;
}
if ($valA != $valB) {
return $valA < $valB ? 1 : -1;
}
return null;
}
}

View file

@ -0,0 +1,288 @@
<?php
/**
* Piwik - Open source web analytics
*
* @link http://piwik.org
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
*
*/
namespace Piwik\Plugins\Insights;
use Piwik\DataTable;
use Piwik\Piwik;
/**
* Insight report generator
*/
class InsightReport
{
const ORDER_BY_RELATIVE = 'relative';
const ORDER_BY_ABSOLUTE = 'absolute';
const ORDER_BY_IMPORTANCE = 'importance';
/**
* @param array $reportMetadata
* @param string $period
* @param string $date
* @param string $lastDate
* @param string $metric
* @param DataTable $currentReport
* @param DataTable $lastReport
* @param int $totalValue
* @param int $lastTotalValue
* @param string $orderBy
* @param int $limitIncreaser
* @param int $limitDecreaser
* @return DataTable
*/
public function generateMoverAndShaker($reportMetadata, $period, $date, $lastDate, $metric, $currentReport, $lastReport, $totalValue, $lastTotalValue, $orderBy, $limitIncreaser, $limitDecreaser)
{
$totalEvolution = $this->getTotalEvolution($totalValue, $lastTotalValue);
$minMoversPercent = 1;
if ($totalEvolution >= 100) {
// eg change from 50 to 150 = 200%
$factor = (int) ceil($totalEvolution / 500);
$minGrowthPercentPositive = $totalEvolution + ($factor * 40); // min +240%
$minGrowthPercentNegative = -70; // min -70%
$minDisappearedPercent = 8; // min 12
$minNewPercent = min(($totalEvolution / 100) * 3, 10); // min 6% = min 10 of total visits up to max 10%
} elseif ($totalEvolution >= 0) {
// eg change from 50 to 75 = 50%
$minGrowthPercentPositive = $totalEvolution + 20; // min 70%
$minGrowthPercentNegative = -1 * $minGrowthPercentPositive; // min -70%
$minDisappearedPercent = 7;
$minNewPercent = 5;
} else {
// eg change from 50 to 25 = -50%
$minGrowthPercentNegative = $totalEvolution - 20; // min -70%
$minGrowthPercentPositive = abs($minGrowthPercentNegative); // min 70%
$minDisappearedPercent = 7;
$minNewPercent = 5;
}
if ($totalValue < 200 && $totalValue != 0) {
// force at least a change of 2 visits
$minMoversPercent = (int) ceil(2 / ($totalValue / 100));
$minNewPercent = max($minNewPercent, $minMoversPercent);
$minDisappearedPercent = max($minDisappearedPercent, $minMoversPercent);
}
$dataTable = $this->generateInsight($reportMetadata, $period, $date, $lastDate, $metric, $currentReport, $lastReport, $totalValue, $minMoversPercent, $minNewPercent, $minDisappearedPercent, $minGrowthPercentPositive, $minGrowthPercentNegative, $orderBy, $limitIncreaser, $limitDecreaser);
$this->addMoversAndShakersMetadata($dataTable, $totalValue, $lastTotalValue);
return $dataTable;
}
/**
* Extends an already generated insight report by adding a column "isMoverAndShaker" whether a row is also a
* "Mover and Shaker" or not.
*
* Avoids the need to fetch all reports again when we already have the currentReport/lastReport
*/
public function markMoversAndShakers(DataTable $insight, $currentReport, $lastReport, $totalValue, $lastTotalValue)
{
if (!$insight->getRowsCount()) {
return;
}
$limitIncreaser = max($insight->getRowsCount(), 3);
$limitDecreaser = max($insight->getRowsCount(), 3);
$lastDate = $insight->getMetadata('lastDate');
$date = $insight->getMetadata('date');
$period = $insight->getMetadata('period');
$metric = $insight->getMetadata('metric');
$orderBy = $insight->getMetadata('orderBy');
$reportMetadata = $insight->getMetadata('report');
$shakers = $this->generateMoverAndShaker($reportMetadata, $period, $date, $lastDate, $metric, $currentReport, $lastReport, $totalValue, $lastTotalValue, $orderBy, $limitIncreaser, $limitDecreaser);
foreach ($insight->getRows() as $row) {
$label = $row->getColumn('label');
if ($shakers->getRowFromLabel($label)) {
$row->setColumn('isMoverAndShaker', true);
} else {
$row->setColumn('isMoverAndShaker', false);
}
}
$this->addMoversAndShakersMetadata($insight, $totalValue, $lastTotalValue);
}
/**
* @param array $reportMetadata
* @param string $period
* @param string $date
* @param string $lastDate
* @param string $metric
* @param DataTable $currentReport
* @param DataTable $lastReport
* @param int $totalValue
* @param int $minMoversPercent Exclude rows who moved and the difference is not at least min percent
* visits of totalVisits. -1 excludes movers.
* @param int $minNewPercent Exclude rows who are new and the difference is not at least min percent
* visits of totalVisits. -1 excludes all new.
* @param int $minDisappearedPercent Exclude rows who are disappeared and the difference is not at least min
* percent visits of totalVisits. -1 excludes all disappeared.
* @param int $minGrowthPercentPositive The actual growth of a row must be at least percent compared to the
* previous value (not total value)
* @param int $minGrowthPercentNegative The actual growth of a row must be lower percent compared to the
* previous value (not total value)
* @param string $orderBy Order by absolute, relative, importance
* @param int $limitIncreaser
* @param int $limitDecreaser
*
* @return DataTable
*/
public function generateInsight($reportMetadata, $period, $date, $lastDate, $metric, $currentReport, $lastReport, $totalValue, $minMoversPercent, $minNewPercent, $minDisappearedPercent, $minGrowthPercentPositive, $minGrowthPercentNegative, $orderBy, $limitIncreaser, $limitDecreaser)
{
$minChangeMovers = $this->getMinVisits($totalValue, $minMoversPercent);
$minIncreaseNew = $this->getMinVisits($totalValue, $minNewPercent);
$minDecreaseDisappeared = $this->getMinVisits($totalValue, $minDisappearedPercent);
$dataTable = new DataTable();
$dataTable->filter(
'Piwik\Plugins\Insights\DataTable\Filter\Insight',
array(
$currentReport,
$lastReport,
$metric,
$considerMovers = (-1 !== $minMoversPercent),
$considerNew = (-1 !== $minNewPercent),
$considerDisappeared = (-1 !== $minDisappearedPercent)
)
);
$dataTable->filter(
'Piwik\Plugins\Insights\DataTable\Filter\MinGrowth',
array(
'growth_percent_numeric',
$minGrowthPercentPositive,
$minGrowthPercentNegative
)
);
if ($minIncreaseNew) {
$dataTable->filter(
'Piwik\Plugins\Insights\DataTable\Filter\ExcludeLowValue',
array(
'difference',
$minIncreaseNew,
'isNew'
)
);
}
if ($minChangeMovers) {
$dataTable->filter(
'Piwik\Plugins\Insights\DataTable\Filter\ExcludeLowValue',
array(
'difference',
$minChangeMovers,
'isMover'
)
);
}
if ($minDecreaseDisappeared) {
$dataTable->filter(
'Piwik\Plugins\Insights\DataTable\Filter\ExcludeLowValue',
array(
'difference',
$minDecreaseDisappeared,
'isDisappeared'
)
);
}
$dataTable->filter(
'Piwik\Plugins\Insights\DataTable\Filter\OrderBy',
array(
$this->getOrderByColumn($orderBy),
$orderBy === self::ORDER_BY_RELATIVE ? $this->getOrderByColumn(self::ORDER_BY_ABSOLUTE) : $this->getOrderByColumn(self::ORDER_BY_RELATIVE),
$metric
)
);
$dataTable->filter(
'Piwik\Plugins\Insights\DataTable\Filter\Limit',
array(
'growth_percent_numeric',
$limitIncreaser,
$limitDecreaser
)
);
$metricName = $metric;
if (!empty($reportMetadata['metrics'][$metric])) {
$metricName = $reportMetadata['metrics'][$metric];
}
$dataTable->setMetadataValues(array(
'reportName' => $reportMetadata['name'],
'metricName' => $metricName,
'date' => $date,
'lastDate' => $lastDate,
'period' => $period,
'report' => $reportMetadata,
'totalValue' => $totalValue,
'orderBy' => $orderBy,
'metric' => $metric,
'minChangeMovers' => $minChangeMovers,
'minIncreaseNew' => $minIncreaseNew,
'minDecreaseDisappeared' => $minDecreaseDisappeared,
'minGrowthPercentPositive' => $minGrowthPercentPositive,
'minGrowthPercentNegative' => $minGrowthPercentNegative,
'minMoversPercent' => $minMoversPercent,
'minNewPercent' => $minNewPercent,
'minDisappearedPercent' => $minDisappearedPercent
));
return $dataTable;
}
private function getOrderByColumn($orderBy)
{
if (self::ORDER_BY_RELATIVE == $orderBy) {
$orderByColumn = 'growth_percent_numeric';
} elseif (self::ORDER_BY_ABSOLUTE == $orderBy) {
$orderByColumn = 'difference';
} elseif (self::ORDER_BY_IMPORTANCE == $orderBy) {
$orderByColumn = 'importance';
} else {
throw new \Exception('Unsupported orderBy');
}
return $orderByColumn;
}
private function getMinVisits($totalValue, $percent)
{
if ($percent <= 0) {
return 0;
}
$minVisits = ceil(($totalValue / 100) * $percent);
return (int) $minVisits;
}
private function addMoversAndShakersMetadata(DataTable $dataTable, $totalValue, $lastTotalValue)
{
$totalEvolution = $this->getTotalEvolution($totalValue, $lastTotalValue);
$dataTable->setMetadata('lastTotalValue', $lastTotalValue);
$dataTable->setMetadata('evolutionTotal', $totalEvolution);
$dataTable->setMetadata('evolutionDifference', $totalValue - $lastTotalValue);
}
private function getTotalEvolution($totalValue, $lastTotalValue)
{
return Piwik::getPercentageSafe($totalValue - $lastTotalValue, $lastTotalValue, 1);
}
}

View file

@ -0,0 +1,51 @@
<?php
/**
* Piwik - Open source web analytics
*
* @link http://piwik.org
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
*
*/
namespace Piwik\Plugins\Insights;
use Piwik\WidgetsList;
/**
*/
class Insights extends \Piwik\Plugin
{
/**
* @see Piwik\Plugin::getListHooksRegistered
*/
public function getListHooksRegistered()
{
return array(
'WidgetsList.addWidgets' => 'addWidgets',
'AssetManager.getJavaScriptFiles' => 'getJsFiles',
'AssetManager.getStylesheetFiles' => 'getStylesheetFiles',
'ViewDataTable.addViewDataTable' => 'getAvailableVisualizations'
);
}
public function getAvailableVisualizations(&$visualizations)
{
$visualizations[] = __NAMESPACE__ . '\\Visualizations\\Insight';
}
public function addWidgets()
{
WidgetsList::add('Insights_WidgetCategory', 'Insights_OverviewWidgetTitle', 'Insights', 'getInsightsOverview');
WidgetsList::add('Insights_WidgetCategory', 'Insights_MoversAndShakersWidgetTitle', 'Insights', 'getOverallMoversAndShakers');
}
public function getStylesheetFiles(&$stylesheets)
{
$stylesheets[] = "plugins/Insights/stylesheets/insightVisualization.less";
}
public function getJsFiles(&$jsFiles)
{
$jsFiles[] = "plugins/Insights/javascripts/insightsDataTable.js";
}
}

View file

@ -0,0 +1,120 @@
<?php
/**
* Piwik - Open source web analytics
*
* @link http://piwik.org
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
*
*/
namespace Piwik\Plugins\Insights;
use Piwik\DataTable;
use Piwik\Period\Range;
use Piwik\Plugins\API\ProcessedReport;
use Piwik\API\Request as ApiRequest;
use Piwik\Plugins\VisitsSummary\API as VisitsSummaryAPI;
/**
* API for plugin Insights
*
* @method static \Piwik\Plugins\Insights\API getInstance()
*/
class Model
{
public function requestReport($idSite, $period, $date, $reportUniqueId, $metric, $segment)
{
$report = $this->getReportByUniqueId($idSite, $reportUniqueId);
$params = array(
'method' => $report['module'] . '.' . $report['action'],
'format' => 'original',
'idSite' => $idSite,
'period' => $period,
'date' => $date,
'filter_limit' => 1000,
'showColumns' => $metric
);
if (!empty($segment)) {
$params['segment'] = $segment;
}
if (!empty($report['parameters']) && is_array($report['parameters'])) {
$params = array_merge($params, $report['parameters']);
}
$request = new ApiRequest($params);
$table = $request->process();
return $table;
}
public function getLastDate($date, $period, $comparedToXPeriods)
{
$pastDate = Range::getDateXPeriodsAgo(abs($comparedToXPeriods), $date, $period);
if (empty($pastDate[0])) {
throw new \Exception('Not possible to compare this date/period combination');
}
return $pastDate[0];
}
/**
* Returns either the $totalValue (eg 5500 visits) or the total value of the report
* (eg 2500 visits of 5500 total visits as for instance only 2500 visits came to the website using a search engine).
*
* If the metric total (2500) is much lower than $totalValue, the metric total will be returned, otherwise the
* $totalValue
*/
public function getRelevantTotalValue(DataTable $currentReport, $metric, $totalValue)
{
$totalMetric = $this->getMetricTotalValue($currentReport, $metric);
if ($totalMetric > $totalValue) {
return $totalMetric;
}
if (($totalMetric * 2) < $totalValue) {
return $totalMetric;
}
return $totalValue;
}
public function getTotalValue($idSite, $period, $date, $metric)
{
$visits = VisitsSummaryAPI::getInstance()->get($idSite, $period, $date, false, array($metric));
$firstRow = $visits->getFirstRow();
if (empty($firstRow)) {
return 0;
}
$totalValue = $firstRow->getColumn($metric);
return (int) $totalValue;
}
public function getMetricTotalValue(DataTable $currentReport, $metric)
{
$totals = $currentReport->getMetadata('totals');
if (!empty($totals[$metric])) {
$totalValue = (int) $totals[$metric];
} else {
$totalValue = 0;
}
return $totalValue;
}
public function getReportByUniqueId($idSite, $reportUniqueId)
{
$processedReport = new ProcessedReport();
$report = $processedReport->getReportMetadataByUniqueId($idSite, $reportUniqueId);
return $report;
}
}

View file

@ -0,0 +1,121 @@
<?php
/**
* Piwik - Open source web analytics
*
* @link http://piwik.org
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
*
*/
namespace Piwik\Plugins\Insights\Visualizations;
use Piwik\Common;
use Piwik\DataTable;
use Piwik\Period\Range;
use Piwik\Plugin\ViewDataTable;
use Piwik\Plugin\Visualization;
use Piwik\Plugins\Insights\API;
use Piwik\Plugins\Insights\Model;
/**
* InsightsVisualization Visualization.
*
* @property Insight\RequestConfig $requestConfig
*/
class Insight extends Visualization
{
const ID = 'insightsVisualization';
const TEMPLATE_FILE = '@Insights/insightVisualization.twig';
const FOOTER_ICON_TITLE = 'Insights';
const FOOTER_ICON = 'plugins/Insights/images/idea.png';
public function beforeLoadDataTable()
{
if (!self::canDisplayViewDataTable($this)) {
return;
}
if (!$this->requestConfig->filter_limit) {
$this->requestConfig->filter_limit = 10;
}
$report = $this->requestConfig->apiMethodToRequestDataTable;
$report = str_replace('.', '_', $report);
$this->requestConfig->apiMethodToRequestDataTable = 'Insights.getInsights';
$this->requestConfig->request_parameters_to_modify = array(
'reportUniqueId' => $report,
'minImpactPercent' => $this->requestConfig->min_impact_percent,
'minGrowthPercent' => $this->requestConfig->min_growth_percent,
'comparedToXPeriods' => $this->requestConfig->compared_to_x_periods_ago,
'orderBy' => $this->requestConfig->order_by,
'filterBy' => $this->requestConfig->filter_by,
'limitIncreaser' => $this->getLimitIncrease(),
'limitDecreaser' => $this->getLimitDecrease(),
);
}
private function getLimitIncrease()
{
$filterLimit = $this->requestConfig->filter_limit;
$limitIncrease = 0;
if ($this->requestConfig->limit_increaser && !$this->requestConfig->limit_decreaser) {
$limitIncrease = $filterLimit;
} elseif ($this->requestConfig->limit_increaser && $this->requestConfig->limit_decreaser) {
$limitIncrease = round($filterLimit / 2);
}
return $limitIncrease;
}
private function getLimitDecrease()
{
$filterLimit = $this->requestConfig->filter_limit;
$limitDecrease = $filterLimit - $this->getLimitIncrease();
return abs($limitDecrease);
}
public static function getDefaultRequestConfig()
{
return new Insight\RequestConfig();
}
public function isThereDataToDisplay()
{
return true;
}
public function beforeRender()
{
$this->config->datatable_js_type = 'InsightsDataTable';
$this->config->show_limit_control = true;
$this->config->show_pagination_control = false;
$this->config->show_offset_information = false;
$this->config->show_search = false;
if (!self::canDisplayViewDataTable($this)) {
$this->assignTemplateVar('cannotDisplayReport', true);
return;
}
$period = Common::getRequestVar('period', null, 'string');
$this->assignTemplateVar('period', $period);
}
public static function canDisplayViewDataTable(ViewDataTable $view)
{
$period = Common::getRequestVar('period', null, 'string');
$date = Common::getRequestVar('date', null, 'string');
$canGenerateInsights = API::getInstance()->canGenerateInsights($date, $period);
if (!$canGenerateInsights) {
return false;
}
return parent::canDisplayViewDataTable($view);
}
}

View file

@ -0,0 +1,45 @@
<?php
/**
* Piwik - Open source web analytics
*
* @link http://piwik.org
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
*
*/
namespace Piwik\Plugins\Insights\Visualizations\Insight;
use Piwik\Plugins\Insights\InsightReport;
use Piwik\Plugins\Insights\Visualizations\Insight;
use Piwik\ViewDataTable\RequestConfig as VisualizationRequestConfig;
class RequestConfig extends VisualizationRequestConfig
{
public $min_impact_percent = '0.1';
public $min_growth_percent = 1;
public $compared_to_x_periods_ago = 1;
public $order_by = InsightReport::ORDER_BY_ABSOLUTE;
public $filter_by = '';
public $limit_increaser = '5';
public $limit_decreaser = '5';
public function __construct()
{
$this->disable_generic_filters = true;
$this->disable_queued_filters = true;
$properties = array(
'min_growth_percent',
'order_by',
'compared_to_x_periods_ago',
'filter_by',
'limit_increaser',
'limit_decreaser',
'filter_limit'
);
$this->addPropertiesThatShouldBeAvailableClientSide($properties);
$this->addPropertiesThatCanBeOverwrittenByQueryParams($properties);
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 364 B

View file

@ -0,0 +1,118 @@
/*!
* Piwik - Web Analytics
*
* @link http://piwik.org
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
*/
(function ($, require) {
var exports = require('piwik/UI'),
DataTable = exports.DataTable,
dataTablePrototype = DataTable.prototype;
var UIControl = exports.UIControl;
function getValueFromEvent(event)
{
return event.target.value ? event.target.value : $(event.target).attr('value');
}
/**
* UI control that handles extra functionality for Actions datatables.
*
* @constructor
*/
exports.InsightsDataTable = function (element) {
this.parentAttributeParent = '';
this.parentId = '';
this.disabledRowDom = {}; // to handle double click on '+' row
if ($(element).attr('data-table-onlyinsightsinit')) {
// overview-widget
UIControl.call(this, element);
this._init($(element));
this.workingDivId = this._createDivId();
$(element).attr('id', this.workingDivId);
} else {
DataTable.call(this, element);
}
};
$.extend(exports.InsightsDataTable.prototype, dataTablePrototype, {
handleRowActions: function () {},
_init: function (domElem) {
this.initShowIncreaseOrDecrease(domElem);
this.initOrderBy(domElem);
this.initComparedToXPeriodsAgo(domElem);
this.initFilterBy(domElem);
this.setFixWidthToMakeEllipsisWork(domElem);
},
setFixWidthToMakeEllipsisWork: function (domElem) {
var width = domElem.width();
if (width) {
$('td.label', domElem).width(parseInt(width * 0.50, 10));
}
},
_changeParameter: function (params) {
var widgetParams = {};
for (var index in params) {
if (params.hasOwnProperty(index)) {
this.param[index] = params[index];
widgetParams[index] = params[index];
}
}
this.notifyWidgetParametersChange(this.$element, widgetParams);
},
_changeParameterAndReload: function (params) {
this._changeParameter(params);
this.reloadAjaxDataTable(true);
},
initShowIncreaseOrDecrease: function (domElem) {
var self = this;
$('[name=showIncreaseOrDecrease]', domElem).bind('change', function (event) {
var value = getValueFromEvent(event);
self._changeParameterAndReload({
limit_increaser: (value == 'both' || value == 'increase') ? '5' : '0',
limit_decreaser: (value == 'both' || value == 'decrease') ? '5' : '0'
});
});
},
initOrderBy: function (domElem) {
var self = this;
$('[name=orderBy]', domElem).bind('change', function (event) {
self._changeParameterAndReload({order_by: getValueFromEvent(event)});
});
$('th[name=orderBy]', domElem).bind('click', function (event) {
self._changeParameterAndReload({order_by: getValueFromEvent(event)});
});
},
initComparedToXPeriodsAgo: function (domElem) {
var self = this;
$('[name=comparedToXPeriodsAgo]', domElem).bind('change', function (event) {
self._changeParameterAndReload({compared_to_x_periods_ago: getValueFromEvent(event)});
});
},
initFilterBy: function (domElem) {
var self = this;
$('[name=filterBy]', domElem).bind('change', function (event) {
self._changeParameterAndReload({filter_by: getValueFromEvent(event)});
});
}
});
})(jQuery, require);

View file

@ -0,0 +1,15 @@
{
"name": "Insights",
"version": "0.1.0",
"description": "Get insights",
"theme": false,
"license": "GPL v3+",
"homepage": "http://piwik.org",
"authors": [
{
"name": "Piwik",
"email": "hello@piwik.org",
"homepage": "http://piwik.org"
}
]
}

View file

@ -0,0 +1,49 @@
.dataTableVizInsight {
th.orderBy {
cursor:pointer;
}
}
.dataTableVizInsight .dataTableFeatures,
.insightsDataTable {
.controls {
padding: 10px;
padding-bottom: 0px;
}
.controlSeparator {
height: 1px;
border: 0px;
background-color: #cccccc;
}
th.orderBy {
width: 20%;
}
th.orderBy.active {
font-weight:bold;
}
.title {
word-break: break-all;
overflow: hidden;
text-overflow: ellipsis;
width: inherit;
display: block;
}
.grown {
color:green;
}
.notGrown {
color:red;
}
.isMoverAndShaker {
font-weight:bold;
}
}

View file

@ -0,0 +1,3 @@
<div class="pk-emptyDataTable">
{{ 'Insights_DatePeriodCombinationNotSupported'|translate }}
</div>

View file

@ -0,0 +1,65 @@
<div class="controls">
{% if period != 'range' %}
{{ 'Insights_ControlComparedToDescription'|translate }}
{% if period == 'day' %}
<select size="1" name="comparedToXPeriodsAgo">
<option value="1" {% if properties.compared_to_x_periods_ago == 1 %}selected{% endif %}>
{{ 'Insights_DayComparedToPreviousDay'|translate }}
</option>
<option value="7" {% if properties.compared_to_x_periods_ago == 7 %}selected{% endif %}>
{{ 'Insights_DayComparedToPreviousWeek'|translate }}
</option>
<option value="365" {% if properties.compared_to_x_periods_ago == 365 %}selected{% endif %}>
{{ 'Insights_DayComparedToPreviousYear'|translate }}
</option>
</select>
{% elseif period == 'month' %}
<select size="1" name="comparedToXPeriodsAgo">
<option value="1" {% if properties.compared_to_x_periods_ago == 1 %}selected{% endif %}>
{{ 'Insights_MonthComparedToPreviousMonth'|translate }}
</option>
<option value="12" {% if properties.compared_to_x_periods_ago == 12 %}selected{% endif %}>
{{ 'Insights_MonthComparedToPreviousYear'|translate }}
</option>
</select>
{% elseif period == 'week' %}
{{ 'Insights_WeekComparedToPreviousWeek'|translate }}
{% elseif period == 'year' %}
{{ 'Insights_YearComparedToPreviousYear'|translate }}
{% endif %}
{% endif %}
<hr class="controlSeparator" />
{{ 'Insights_Filter'|translate }}
<select size="1" name="filterBy" title="{{ 'Insights_ControlFilterByDescription'|translate|e('html_attr') }}">
<option {% if not properties.filter_by %}selected{% endif %} value="">
{{ 'General_All'|translate }}
</option>
<option {% if properties.filter_by == 'movers' %}selected{% endif %} value="movers">
{{ 'Insights_FilterOnlyMovers'|translate }}
</option>
<option {% if properties.filter_by == 'new' %}selected{% endif %} value="new">
{{ 'Insights_FilterOnlyNew'|translate }}
</option>
<option {% if properties.filter_by == 'disappeared' %}selected{% endif %} value="disappeared">
{{ 'Insights_FilterOnlyDisappeared'|translate }}
</option>
</select>
<select size="1" name="showIncreaseOrDecrease" title="Show increaser and/or decreaser">
<option value="both" {% if properties.limit_increaser and properties.limit_decreaser %}selected{%endif%}>
{{ 'Insights_FilterIncreaserAndDecreaser'|translate }}
</option>
<option value="increase" {% if properties.limit_increaser and not properties.limit_decreaser %}selected{%endif%}>
{{ 'Insights_FilterOnlyIncreaser'|translate }}
</option>
<option value="decrease" {% if not properties.limit_increaser and properties.limit_decreaser %}selected{%endif%}>
{{ 'Insights_FilterOnlyDecreaser'|translate }}
</option>
</select>
</div>

View file

@ -0,0 +1,34 @@
{% if cannotDisplayReport is defined and cannotDisplayReport %}
{% include "@Insights/cannotDisplayReport.twig" %}
{% else %}
{% set metadata = dataTable.getAllTableMetadata%}
{% set consideredGrowth = 'Insights_TitleConsideredInsightsGrowth'|translate(metadata.minGrowthPercentPositive, metadata.lastDate|prettyDate(metadata.period)) %}
{% set consideredChanges = '' %}
{% if metadata.minChangeMovers and metadata.minChangeMovers > 1 %}
{% set consideredChanges = 'Insights_IgnoredChanges'|translate(metadata.minChangeMovers) %}
{% endif %}
<div class="insightsDataTable" title="{{ consideredGrowth|e('html_attr') }} {{ consideredChanges|e('html_attr') }}">
{% if dataTable.getRowsCount %}
<table class="dataTable">
<thead>
{% include "@Insights/table_header.twig" %}
</thead>
<tbody>
{% for row in dataTable.getRows %}
{% include "@Insights/table_row.twig" %}
{% endfor %}
</tbody>
</table>
{% else %}
<div class="pk-emptyDataTable">
{{ 'Insights_NoResultMatchesCriteria'|translate }}
</div>
{% endif %}
{% include "@Insights/insightControls.twig" %}
</div>
{% endif %}

View file

@ -0,0 +1,5 @@
{% set allMetadata = reports.getFirstRow.getAllTableMetadata %}
{% set consideredGrowth = 'Insights_TitleConsideredInsightsGrowth'|translate(allMetadata.minGrowthPercentPositive, allMetadata.lastDate|prettyDate(allMetadata.period)) %}
{% set consideredChanges = '' %}
{% include "@Insights/overviewWidget.twig" %}

View file

@ -0,0 +1,6 @@
{% set allMetadata = reports.getFirstRow.getAllTableMetadata %}
{% set consideredGrowth = 'Insights_TitleConsideredMoversAndShakersGrowth'|translate(allMetadata.metricName, allMetadata.lastTotalValue, allMetadata.totalValue, allMetadata.lastDate|prettyDate(allMetadata.period), allMetadata.evolutionTotal) %}
{% set consideredChanges = 'Insights_TitleConsideredMoversAndShakersChanges'|translate(allMetadata.minGrowthPercentPositive, allMetadata.minGrowthPercentNegative, allMetadata.minNewPercent, allMetadata.minIncreaseNew, allMetadata.minDisappearedPercent, allMetadata.minDecreaseDisappeared, allMetadata.totalValue) %}
{% include "@Insights/overviewWidget.twig" %}

View file

@ -0,0 +1,38 @@
<div class="insightsDataTable dataTable"
data-table-type="InsightsDataTable"
data-table-onlyinsightsinit="1">
{% if reports.getColumns|length > 0 %}
<table class="dataTable"
title="{{ consideredGrowth|e('html_attr') }} {{ consideredChanges|e('html_attr') }}">
{% for dataTable in reports.getDataTables() if dataTable.getRowsCount > 0 %}
{% set metadata = dataTable.getAllTableMetadata %}
<thead>
{% include "@Insights/table_header.twig" %}
</thead>
<tbody>
{% for row in dataTable.getRows %}
{% include "@Insights/table_row.twig" %}
{% endfor %}
</tbody>
{% endfor %}
</table>
<script type="text/javascript" defer="defer">
$(document).ready(function () {
require('piwik/UI/DataTable').initNewDataTables();
});
</script>
{% else %}
<div class="pk-emptyDataTable"
title="{{ consideredGrowth|e('html_attr') }} {{ consideredChanges|e('html_attr') }}">
{{ 'Insights_NoResultMatchesCriteria'|translate }}
</div>
{% endif %}
</div>

View file

@ -0,0 +1,13 @@
<tr>
<th class="label">
{{ metadata.reportName }}
</th>
<th class="label orderBy {% if 'absolute' == properties.order_by %}active{% endif %}"
name="orderBy" value="absolute">
{{ metadata.metricName }}
</th>
<th class="label orderBy {% if 'relative' == properties.order_by %}active{% endif %}"
name="orderBy" value="relative">
{{ 'MultiSites_Evolution'|translate }}
</th>
</tr>

View file

@ -0,0 +1,29 @@
{% if row.getColumn('isDisappeared') %}
{% set rowTitle = 'Insights_TitleRowDisappearedDetails'|translate(row.getColumn('label'), row.getColumn('value_old'), metadata.date|prettyDate(metadata.period), metadata.lastDate|prettyDate(metadata.period)) %}
{% elseif row.getColumn('isNew') %}
{% set rowTitle = 'Insights_TitleRowNewDetails'|translate(row.getColumn('label'), row.getColumn('value_new'), metadata.lastDate|prettyDate(metadata.period)) %}
{% else %}
{% set rowTitle = 'Insights_TitleRowChangeDetails'|translate(row.getColumn('label'), row.getColumn('value_old'), metadata.lastDate|prettyDate(metadata.period), row.getColumn('value_new'), metadata.date|prettyDate(metadata.period), metadata.metricName) %}
{% endif %}
{% set rowTitleShaker = '' %}
{% if row.getColumn('isMoverAndShaker') %}
{% set rowTitleShaker = 'Insights_TitleRowMoverAndShaker'|translate %}
{% endif %}
<tr title="{{ rowTitle|e('html_attr') }} {{ rowTitleShaker|e('html_attr') }}"
class="{% if row.getColumn('isMoverAndShaker') %}isMoverAndShaker{% endif %}">
<td class="label">
<span class="title">
{{ row.getColumn('label') }}
</span>
</td>
{% if row.getColumn('grown') %}
<td>+{{ row.getColumn('difference') }}</td>
<td class="grown">+{{ row.getColumn('growth_percent') }}</td>
{% else %}
<td>{{ row.getColumn('difference') }}</td>
<td class="notGrown">{{ row.getColumn('growth_percent') }}</td>
{% endif %}
</tr>