diff --git a/core/DataTable/Filter/CalculateEvolutionFilter.php b/core/DataTable/Filter/CalculateEvolutionFilter.php index 7328245ab64..24c86121853 100755 --- a/core/DataTable/Filter/CalculateEvolutionFilter.php +++ b/core/DataTable/Filter/CalculateEvolutionFilter.php @@ -34,12 +34,12 @@ class CalculateEvolutionFilter extends ColumnCallbackAddColumnPercentage * * @var DataTable */ - private $pastDataTable; + protected $pastDataTable; /** * Tells if column being added is the revenue evolution column. */ - private $isRevenueEvolution = null; + protected $isRevenueEvolution = null; /** * Constructor. @@ -130,7 +130,7 @@ protected function formatValue($value, $divisor) * @param Row $row The row in the 'current' DataTable. * @return bool|Row */ - private function getPastRowFromCurrent($row) + protected function getPastRowFromCurrent($row) { return $this->pastDataTable->getRowFromLabel($row->getColumn('label')); } diff --git a/core/Period/Range.php b/core/Period/Range.php index a814db98f5d..ab542fe8386 100644 --- a/core/Period/Range.php +++ b/core/Period/Range.php @@ -365,6 +365,24 @@ protected function fillArraySubPeriods($startDate, $endDate, $period) * @api */ public static function getLastDate($date = false, $period = false) + { + return self::getDateXPeriodsAgo(1, $date, $period); + } + + /** + * Returns the date that is X periods before the supplied date. + * + * @param bool|string $date The date to get the last date of. + * @param bool|string $period The period to use (either 'day', 'week', 'month', 'year'); + * @param int $subXPeriods How many periods in the past the date should be, for instance 1 or 7. + * If sub period is 365 days and the current year is a leap year we assume you want to get the + * day one year ago and change the value to 366 days therefore. + * + * @return array An array with two elements, a string for the date before $date and + * a Period instance for the period before $date. + * @api + */ + public static function getDateXPeriodsAgo($subXPeriods, $date = false, $period = false) { if ($date === false) { $date = Common::getRequestVar('date'); @@ -374,20 +392,24 @@ public static function getLastDate($date = false, $period = false) $period = Common::getRequestVar('period'); } + if (365 == $subXPeriods && 'day' == $period && Date::today()->isLeapYear()) { + $subXPeriods = 366; + } + // can't get the last date for range periods & dates that use lastN/previousN $strLastDate = false; - $lastPeriod = false; + $lastPeriod = false; if ($period != 'range' && !preg_match('/(last|previous)([0-9]*)/', $date, $regs)) { if (strpos($date, ',')) // date in the form of 2011-01-01,2011-02-02 { $rangePeriod = new Range($period, $date); - $lastStartDate = $rangePeriod->getDateStart()->addPeriod(-1, $period); - $lastEndDate = $rangePeriod->getDateEnd()->addPeriod(-1, $period); + $lastStartDate = $rangePeriod->getDateStart()->subPeriod($subXPeriods, $period); + $lastEndDate = $rangePeriod->getDateEnd()->subPeriod($subXPeriods, $period); $strLastDate = "$lastStartDate,$lastEndDate"; } else { - $lastPeriod = Date::factory($date)->addPeriod(-1, $period); + $lastPeriod = Date::factory($date)->subPeriod($subXPeriods, $period); $strLastDate = $lastPeriod->toString(); } } diff --git a/core/Plugin/Visualization.php b/core/Plugin/Visualization.php index febe013b737..a8ab8292f49 100644 --- a/core/Plugin/Visualization.php +++ b/core/Plugin/Visualization.php @@ -255,7 +255,7 @@ public function assignTemplateVar($vars, $value = null) */ protected function isThereDataToDisplay() { - return true; + return !empty($this->dataTable) && 0 < $this->dataTable->getRowsCount(); } /** diff --git a/plugins/CoreHome/javascripts/dataTable.js b/plugins/CoreHome/javascripts/dataTable.js index 9c752de251c..b202199e71c 100644 --- a/plugins/CoreHome/javascripts/dataTable.js +++ b/plugins/CoreHome/javascripts/dataTable.js @@ -81,6 +81,10 @@ DataTable.getDataTableByReport = function (report) { $.extend(DataTable.prototype, UIControl.prototype, { + _init: function (domElem) { + // initialize your dataTable in your plugin + }, + //initialisation function init: function () { var domElem = this.$element; @@ -91,6 +95,7 @@ $.extend(DataTable.prototype, UIControl.prototype, { this.loadedSubDataTable = {}; this.isEmpty = $('.pk-emptyDataTable', domElem).length > 0; this.bindEventsAndApplyStyle(domElem); + this._init(domElem); this.initialized = true; }, diff --git a/plugins/CoreHome/templates/_dataTable.twig b/plugins/CoreHome/templates/_dataTable.twig index c024a8e9a46..234d90ea943 100644 --- a/plugins/CoreHome/templates/_dataTable.twig +++ b/plugins/CoreHome/templates/_dataTable.twig @@ -17,7 +17,7 @@ {% if error is defined %} {{ error.message }} {% else %} - {% if dataTable is empty or dataTable.getRowsCount() == 0 or dataTableHasNoData|default(false) %} + {% if dataTable is empty or dataTableHasNoData|default(false) %}
{% if showReportDataWasPurgedMessage is defined and showReportDataWasPurgedMessage %} {{ 'CoreHome_DataForThisReportHasBeenPurged'|translate(deleteReportsOlderThan) }} diff --git a/plugins/Insights/API.php b/plugins/Insights/API.php new file mode 100644 index 00000000000..ebfab42d321 --- /dev/null +++ b/plugins/Insights/API.php @@ -0,0 +1,212 @@ +getMoversAndShakers($idSite, $period, $date, 'Actions_getPageUrls', 4, 4), + $this->getMoversAndShakers($idSite, $period, $date, 'Actions_getPageTitles', 4, 4), + $this->getMoversAndShakers($idSite, $period, $date, 'Referrers_getKeywords', 4, 4), + $this->getMoversAndShakers($idSite, $period, $date, 'Referrers_getCampaigns', 4, 4), + $this->getMoversAndShakers($idSite, $period, $date, 'Referrers_getAll', 4, 4), + $this->getMoversAndShakers($idSite, $period, $date, 'MultiSites_getAll', 4, 4), + ); + + $map = new DataTable\Map(); + + foreach ($tables as $table) { + $map->addTable($table, $table->getMetadata('reportName')); + } + + return $map; + } + + // force $limitX and ignore minVisitsPercent, minGrowthPercent + // segment + public function getMoversAndShakers( + $idSite, $period, $date, $reportUniqueId = '', $limitIncreaser = 5, $limitDecreaser = 5, $basedOnTotalMetric = false, + $minVisitsPercent = 2, $minGrowthPercent = 20, $orderBy = 'absolute', + $comparedToXPeriods = 1, $filterBy = '') + { + $metric = 'nb_visits'; + + $processedReport = new ProcessedReport(); + $report = $processedReport->getReportMetadataByUniqueId($idSite, $reportUniqueId); + + $lastDate = Range::getDateXPeriodsAgo(abs($comparedToXPeriods), $date, $period); + + $currentReport = $this->requestReport($idSite, $period, $date, $report, $metric); + $lastReport = $this->requestReport($idSite, $period, $lastDate[0], $report, $metric); + + $totalValue = $this->getTotalValue($idSite, $period, $date, $basedOnTotalMetric, $currentReport, $metric); + $minVisits = $this->getMinVisits($totalValue, $minVisitsPercent); + + $considerMovers = false; + $considerNew = false; + $considerDisappeared = false; + + switch ($filterBy) { + case '': + $considerMovers = true; + $considerNew = true; + $considerDisappeared = true; + break; + case 'movers': + $considerMovers = true; + break; + case 'new': + $considerNew = true; + break; + case 'disappeared': + $considerDisappeared = true; + break; + } + + $dataTable = new DataTable(); + $dataTable->filter( + 'Piwik\Plugins\Insights\DataTable\Filter\Insight', + array( + $currentReport, + $lastReport, + $metric, + $totalValue, + $filterBy, + $considerMovers, + $considerNew, + $considerDisappeared + ) + ); + + $dataTable->filter( + 'Piwik\Plugins\Insights\DataTable\Filter\MinGrowth', + array( + 'growth_percent_numeric', + $minGrowthPercent + ) + ); + + $dataTable->filter( + 'Piwik\Plugins\Insights\DataTable\Filter\RemoveIrrelevant', + array( + $metric, + $minVisits + ) + ); + + $dataTable->filter( + 'Piwik\Plugins\Insights\DataTable\Filter\OrderBy', + array( + $this->getOrderByColumn($orderBy) + ) + ); + + $dataTable->filter( + 'Piwik\Plugins\Insights\DataTable\Filter\Limit', + array( + 'growth_percent_numeric', + $limitIncreaser, + $limitDecreaser + ) + ); + + $dataTable->setMetadataValues(array( + 'reportName' => $report['name'], + 'metricName' => $report['metrics'][$metric], + 'date' => $date, + 'lastDate' => $lastDate[0], + 'period' => $period, + 'report' => $report, + 'totalValue' => $totalValue, + 'minVisits' => $minVisits + )); + + return $dataTable; + } + + private function requestReport($idSite, $period, $date, $report, $metric) + { + $params = array( + 'method' => $report['module'] . '.' . $report['action'], + 'format' => 'original', + 'idSite' => $idSite, + 'period' => $period, + 'date' => $date, + 'flat' => 1, + 'filter_limit' => 10000, + 'showColumns' => $metric + ); + + if (!empty($report['parameters']) && is_array($report['parameters'])) { + $params = array_merge($params, $report['parameters']); + } + + $request = new ApiRequest($params); + $table = $request->process(); + + return $table; + } + + private function getMinVisits($totalValue, $minVisitsPercent) + { + $minVisits = (int) ceil(($totalValue / 100) * $minVisitsPercent); + + return $minVisits; + } + + private function getTotalValue($idSite, $period, $date, $basedOnTotalMetric, DataTable $currentReport, $metric) + { + if ($basedOnTotalMetric) { + $totals = $currentReport->getMetadata('totals'); + + if (!empty($totals[$metric])) { + $totalValue = $totals[$metric]; + } else { + $totalValue = 0; + } + + return $totalValue; + } + + $visits = VisitsSummaryAPI::getInstance()->get($idSite, $period, $date, false, array($metric)); + $totalValue = $visits->getFirstRow()->getColumn($metric); + + return $totalValue; + } + + private function getOrderByColumn($orderBy) + { + if ('relative' == $orderBy) { + $orderByColumn = 'growth_percent_numeric'; + } elseif ('absolute' == $orderBy) { + $orderByColumn = 'difference'; + } elseif ('importance' == $orderBy) { + $orderByColumn = 'importance'; + } else { + throw new \Exception('Unsupported orderBy'); + } + + return $orderByColumn; + } +} diff --git a/plugins/Insights/Controller.php b/plugins/Insights/Controller.php new file mode 100644 index 00000000000..ed67b9fada0 --- /dev/null +++ b/plugins/Insights/Controller.php @@ -0,0 +1,39 @@ +setBasicVariablesView($view); + + $view->moversAndShakers = API::getInstance()->getOverallMoversAndShakers($idSite, $period, $date); + $view->showNoDataMessage = false; + $view->showInsightsControls = false; + $view->properties = array( + 'show_increase' => true, + 'show_decrease' => true + ); + + return $view->render(); + } +} diff --git a/plugins/Insights/DataTable/Filter/Insight.php b/plugins/Insights/DataTable/Filter/Insight.php new file mode 100644 index 00000000000..4adabdb1236 --- /dev/null +++ b/plugins/Insights/DataTable/Filter/Insight.php @@ -0,0 +1,104 @@ +totalValue = $totalValue; + $this->filterBy = $filterBy; + $this->currentDataTable = $currentDataTable; + $this->considerMovers = $considerMovers; + $this->considerNew = $considerNew; + $this->considerDisappeared = $considerDisappeared; + } + + public function filter($table) + { + foreach ($this->currentDataTable->getRows() as $key => $row) { + $pastRow = $this->getPastRowFromCurrent($row); + $oldValue = 0; + + if (!$pastRow && !$this->considerNew) { + continue; + } + + if ($pastRow && $this->considerMovers) { + $oldValue = $pastRow->getColumn($this->columnValueToRead); + } elseif ($pastRow) { + continue; + } + + $difference = $this->getDividend($row); + if ($difference === false) { + continue; + } + + $newValue = $row->getColumn($this->columnValueToRead); + $divisor = $this->getDivisor($row); + + $growthPercentage = $this->formatValue($difference, $divisor); + + $this->addRow($table, $row, $growthPercentage, $newValue, $oldValue, $difference); + } + + if ($this->considerDisappeared) { + foreach ($this->pastDataTable->getRows() as $key => $row) { + + if (!$this->getRowFromTable($this->currentDataTable, $row)) { + continue; + } + + $newValue = 0; + $oldValue = $row->getColumn($this->columnValueToRead); + $difference = $newValue - $oldValue; + + $growthPercentage = '-100%'; + + $this->addRow($table, $row, $growthPercentage, $newValue, $oldValue, $difference); + } + } + } + + 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) + { + $columns = $row->getColumns(); + $columns['growth_percent'] = $growthPercentage; + $columns['growth_percent_numeric'] = str_replace('%', '', $growthPercentage); + $columns['grown'] = $newValue >= $oldValue; + $columns['value_old'] = $oldValue; + $columns['value_new'] = $newValue; + $columns['difference'] = $difference; + + if ($this->totalValue) { + $columns['importance'] = (abs($difference) / $this->totalValue) * 100; // magic formula here + } + + $table->addRowFromArray(array(DataTable\Row::COLUMNS => $columns)); + return $columns; + } +} \ No newline at end of file diff --git a/plugins/Insights/DataTable/Filter/Limit.php b/plugins/Insights/DataTable/Filter/Limit.php new file mode 100644 index 00000000000..9d39a39ff89 --- /dev/null +++ b/plugins/Insights/DataTable/Filter/Limit.php @@ -0,0 +1,48 @@ +columnToRead = $columnToRead; + $this->limitIncreaser = (int) $limitIncreaser; + $this->limitDecreaser = (int) $limitDecreaser; + } + + public function filter($table) + { + $countIncreaser = 0; + $countDecreaser = 0; + + foreach ($table->getRows() as $key => $row) { + + if ($row->getColumn($this->columnToRead) >= 0) { + $countIncreaser++; + + if ($countIncreaser > $this->limitIncreaser) { + $table->deleteRow($key); + } + + } else { + $countDecreaser++; + + if ($countDecreaser > $this->limitDecreaser) { + $table->deleteRow($key); + } + } + } + } +} \ No newline at end of file diff --git a/plugins/Insights/DataTable/Filter/MinGrowth.php b/plugins/Insights/DataTable/Filter/MinGrowth.php new file mode 100644 index 00000000000..244eebf9d9e --- /dev/null +++ b/plugins/Insights/DataTable/Filter/MinGrowth.php @@ -0,0 +1,44 @@ +growthColumn = $growthColumn; + $this->minGrowthPercent = $minGrowthPercent; + } + + public function filter($table) + { + if (!$this->minGrowthPercent) { + return; + } + + foreach ($table->getRows() as $key => $row) { + + $growthNumeric = $row->getColumn($this->growthColumn); + + if ($growthNumeric > $this->minGrowthPercent) { + continue; + } elseif ($growthNumeric < -$this->minGrowthPercent) { + continue; + } + + $table->deleteRow($key); + } + } +} \ No newline at end of file diff --git a/plugins/Insights/DataTable/Filter/OrderBy.php b/plugins/Insights/DataTable/Filter/OrderBy.php new file mode 100644 index 00000000000..abb5c6bc7c4 --- /dev/null +++ b/plugins/Insights/DataTable/Filter/OrderBy.php @@ -0,0 +1,67 @@ +columnToRead = $columnToRead; + } + + public function filter($table) + { + if (!$table->getRowsCount()) { + return; + } + + $table->sort(array($this, 'sort'), $this->columnToRead); + } + + public function sort(Row $a, Row $b) + { + $valA = $a->getColumn($this->columnToRead); + $valB = $b->getColumn($this->columnToRead); + + if (!isset($valA) && !isset($valB)) { + return 0; + } + + if (!isset($valA)) { + return 1; + } + + if (!isset($valB)) { + return -1; + } + + 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 strnatcasecmp( + $a->getColumn('nb_visits'), + $b->getColumn('nb_visits') + ); + } + +} \ No newline at end of file diff --git a/plugins/Insights/DataTable/Filter/RemoveIrrelevant.php b/plugins/Insights/DataTable/Filter/RemoveIrrelevant.php new file mode 100644 index 00000000000..7f82d1645d7 --- /dev/null +++ b/plugins/Insights/DataTable/Filter/RemoveIrrelevant.php @@ -0,0 +1,39 @@ +columnToRead = $columnToRead; + $this->minRequiredValue = $minRequiredValue; + } + + public function filter($table) + { + if (!$this->minRequiredValue) { + return; + } + + foreach ($table->getRows() as $key => $row) { + + $value = $row->getColumn($this->columnToRead); + + if ($this->minRequiredValue > $value) { + $table->deleteRow($key); + } + } + } +} \ No newline at end of file diff --git a/plugins/Insights/Insights.php b/plugins/Insights/Insights.php new file mode 100644 index 00000000000..b8c7a549d27 --- /dev/null +++ b/plugins/Insights/Insights.php @@ -0,0 +1,44 @@ + 'addWidgets', + 'AssetManager.getJavaScriptFiles' => 'getJsFiles', + 'ViewDataTable.addViewDataTable' => 'getAvailableVisualizations' + ); + } + + public function getAvailableVisualizations(&$visualizations) + { + $visualizations[] = __NAMESPACE__ . '\\Visualizations\\Insight'; + } + + public function addWidgets() + { + WidgetsList::add('Insights_Category', 'Insights_OverviewWidgetTitle', 'Insights', 'getOverviewMoversAndShakers'); + } + + public function getJsFiles(&$jsFiles) + { + $jsFiles[] = "plugins/Insights/javascripts/insightsDataTable.js"; + } + +} diff --git a/plugins/Insights/Visualizations/Insight.php b/plugins/Insights/Visualizations/Insight.php new file mode 100644 index 00000000000..4a235b22293 --- /dev/null +++ b/plugins/Insights/Visualizations/Insight.php @@ -0,0 +1,95 @@ +requestConfig->apiMethodToRequestDataTable; + $report = str_replace('.', '_', $report); + + $this->requestConfig->apiMethodToRequestDataTable = 'Insights.getMoversAndShakers'; + $this->requestConfig->request_parameters_to_modify = array( + 'reportUniqueId' => $report, + 'minVisitsPercent' => $this->requestConfig->min_visits_percent, + 'minGrowthPercent' => $this->requestConfig->min_growth_percent, + 'basedOnTotalMetric' => $this->requestConfig->based_on_total_metric, + 'comparedToXPeriods' => $this->requestConfig->compared_to_x_periods_ago, + 'orderBy' => $this->requestConfig->order_by, + 'filterBy' => $this->requestConfig->filter_by, + 'limitIncreaser' => $this->requestConfig->limit_increaser, + 'limitDecreaser' => $this->requestConfig->limit_decreaser, + ); + } + + public static function getDefaultConfig() + { + return new Insight\Config(); + } + + public static function getDefaultRequestConfig() + { + return new Insight\RequestConfig(); + } + + public function isThereDataToDisplay() + { + return true; + } + + public function afterAllFiltersAreApplied() + { + $this->assignTemplateVar('showNoDataMessage', true); + $this->assignTemplateVar('showInsightsControls', true); + $this->assignTemplateVar('period', Common::getRequestVar('period', null, 'string')); + } + + public function beforeRender() + { + $this->config->datatable_js_type = 'InsightsDataTable'; + $this->config->show_limit_control = false; + $this->config->show_pagination_control = false; + $this->config->show_offset_information = false; + $this->config->show_search = false; + $this->config->title = 'Insights of ' . $this->config->title; + } + + public static function canDisplayViewDataTable(ViewDataTable $view) + { + $period = Common::getRequestVar('period', null, 'string'); + $date = Common::getRequestVar('date', null, 'string'); + + $lastDate = Range::getDateXPeriodsAgo(1, $date, $period); + + if (empty($lastDate[0])) { + return false; + } + + return parent::canDisplayViewDataTable($view); + } +} diff --git a/plugins/Insights/Visualizations/Insight/Config.php b/plugins/Insights/Visualizations/Insight/Config.php new file mode 100644 index 00000000000..15c5f1cd2e3 --- /dev/null +++ b/plugins/Insights/Visualizations/Insight/Config.php @@ -0,0 +1,18 @@ +disable_generic_filters = true; + $this->disable_queued_filters = true; + + $properties = array( + 'min_growth_percent', + 'min_visits_percent', + 'based_on_total_metric', + 'order_by', + 'compared_to_x_periods_ago', + 'filter_by', + 'limit_increaser', + 'limit_decreaser' + ); + + $this->addPropertiesThatShouldBeAvailableClientSide($properties); + $this->addPropertiesThatCanBeOverwrittenByQueryParams($properties); + } + +} diff --git a/plugins/Insights/images/idea.png b/plugins/Insights/images/idea.png new file mode 100644 index 00000000000..05ecb8feb5a Binary files /dev/null and b/plugins/Insights/images/idea.png differ diff --git a/plugins/Insights/javascripts/insightsDataTable.js b/plugins/Insights/javascripts/insightsDataTable.js new file mode 100644 index 00000000000..400e50022ea --- /dev/null +++ b/plugins/Insights/javascripts/insightsDataTable.js @@ -0,0 +1,101 @@ +/*! + * 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; + + /** + * 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 + + DataTable.call(this, element); + }; + + $.extend(exports.InsightsDataTable.prototype, dataTablePrototype, { + + handleRowActions: function () {}, + + _init: function (domElem) { + this.initMinGrowthPercentage(domElem); + this.initMinVisitsPercent(domElem); + this.initBasedOnTotalMetric(domElem); + this.initShowIncreaseOrDecrease(domElem); + this.initOrderBy(domElem); + this.initComparedToXPeriodsAgo(domElem); + this.initFilterBy(domElem); + }, + + initShowIncreaseOrDecrease: function (domElem) { + var self = this; + $('[name=showIncreaseOrDecrease]', domElem).bind('change', function (event) { + var value = event.target.value; + + self.param.limit_increaser = (value == 'both' || value == 'increase') ? '5' : '0'; + self.param.limit_decreaser = (value == 'both' || value == 'decrease') ? '5' : '0'; + self.reloadAjaxDataTable(true); + }); + }, + + initMinGrowthPercentage: function (domElem) { + var self = this; + $('[name=minGrowthPercent]', domElem).bind('change', function (event) { + self.param.min_growth_percent = event.target.value; + self.reloadAjaxDataTable(true); + }); + }, + + initOrderBy: function (domElem) { + var self = this; + $('[name=orderBy]', domElem).bind('change', function (event) { + self.param.order_by = event.target.value; + self.reloadAjaxDataTable(true); + }); + }, + + initMinVisitsPercent: function (domElem) { + var self = this; + $('[name=minVisitsPercent]', domElem).bind('change', function (event) { + self.param.min_visits_percent = event.target.value; + self.reloadAjaxDataTable(true); + }); + }, + + initBasedOnTotalMetric: function (domElem) { + var self = this; + $('[name=basedOnTotalMetric]', domElem).bind('change', function (event) { + self.param.based_on_total_metric = event.target.value; + self.reloadAjaxDataTable(true); + }); + }, + + initComparedToXPeriodsAgo: function (domElem) { + var self = this; + $('[name=comparedToXPeriodsAgo]', domElem).bind('change', function (event) { + self.param.compared_to_x_periods_ago = event.target.value; + self.reloadAjaxDataTable(true); + }); + }, + + initFilterBy: function (domElem) { + var self = this; + $('[name=filterBy]', domElem).bind('change', function (event) { + self.param.filter_by = event.target.value; + self.reloadAjaxDataTable(true); + }); + } + }); + +})(jQuery, require); \ No newline at end of file diff --git a/plugins/Insights/lang/en.json b/plugins/Insights/lang/en.json new file mode 100644 index 00000000000..cde88325336 --- /dev/null +++ b/plugins/Insights/lang/en.json @@ -0,0 +1,6 @@ +{ + "Insights": { + "OverviewWidgetTitle": "Overview of movers and shakers", + "Category": "Insights" + } +} \ No newline at end of file diff --git a/plugins/Insights/plugin.json b/plugins/Insights/plugin.json new file mode 100644 index 00000000000..985eca4c6d7 --- /dev/null +++ b/plugins/Insights/plugin.json @@ -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" + } + ] +} \ No newline at end of file diff --git a/plugins/Insights/templates/index.twig b/plugins/Insights/templates/index.twig new file mode 100644 index 00000000000..fc91a813306 --- /dev/null +++ b/plugins/Insights/templates/index.twig @@ -0,0 +1,5 @@ +{% for dataTable in moversAndShakers.getDataTables() %} + + {% include "@Insights/insightVisualization.twig" %} + +{% endfor %} \ No newline at end of file diff --git a/plugins/Insights/templates/insightControls.twig b/plugins/Insights/templates/insightControls.twig new file mode 100644 index 00000000000..c0314bf0a4d --- /dev/null +++ b/plugins/Insights/templates/insightControls.twig @@ -0,0 +1,93 @@ +
+ Show only rows with a + + minimum impact of + + + {% if properties.show_based_on_total_metric %} + + {% endif %} + + and min growth of + + + {% if period == 'day' %} + + {% elseif period == 'month' %} + + {% endif %} + + Order them by + value + + and show + + {% if properties.show_filter_by %} + + {% endif %} + + if they + +
\ No newline at end of file diff --git a/plugins/Insights/templates/insightVisualization.twig b/plugins/Insights/templates/insightVisualization.twig new file mode 100644 index 00000000000..8ef6f7184fb --- /dev/null +++ b/plugins/Insights/templates/insightVisualization.twig @@ -0,0 +1,52 @@ +
+ {% if dataTable.getRowsCount > 0 %} + + + + + + + + + + + {% for row in dataTable.getRows %} + + + {% if row.getColumn('grown') %} + + + {% else %} + + + {% endif %} + + {% endfor %} + + +
+ {{ dataTable.getMetadata('reportName') }} + + {{ dataTable.getMetadata('metricName') }} + + Evolution +
+ + {{ row.getColumn('label') }} + + +{{ row.getColumn('difference') }} + +{{ row.getColumn('growth_percent') }} + {{ row.getColumn('difference') }} + {{ row.getColumn('growth_percent') }} +
+ {% elseif showNoDataMessage %} +
+ No rows match the criteria +
+ {% endif %} + + {% if showInsightsControls %} + {% include "@Insights/insightControls.twig" %} + {% endif %} +
\ No newline at end of file