Skip to content
Extraits de code Groupes Projets
Valider 8c970d3e rédigé par Thomas Steur's avatar Thomas Steur
Parcourir les fichiers

changed look of custom variables screen, merge metadata when specified

parent 89eb98b2
Aucune branche associée trouvée
Aucune étiquette associée trouvée
Aucune requête de fusion associée trouvée
Affichage de
avec 161 ajouts et 67 suppressions
......@@ -479,7 +479,7 @@ class Row implements \ArrayAccess, \IteratorAggregate
}
if ($enableCopyMetadata) {
$this->sumRowMetadata($rowToSum);
$this->sumRowMetadata($rowToSum, $aggregationOperations);
}
}
......@@ -506,6 +506,19 @@ class Row implements \ArrayAccess, \IteratorAggregate
case 'sum':
$newValue = $this->sumRowArray($thisColumnValue, $columnToSumValue);
break;
case 'uniquearraymerge':
if (is_array($thisColumnValue) && is_array($columnToSumValue)) {
foreach ($columnToSumValue as $columnSum) {
if (!in_array($columnSum, $thisColumnValue)) {
$thisColumnValue[] = $columnSum;
}
}
} elseif (!is_array($thisColumnValue) && is_array($columnToSumValue)) {
$thisColumnValue = $columnToSumValue;
}
$newValue = $thisColumnValue;
break;
default:
throw new Exception("Unknown operation '$operation'.");
}
......@@ -516,12 +529,29 @@ class Row implements \ArrayAccess, \IteratorAggregate
* Sums the metadata in `$rowToSum` with the metadata in `$this` row.
*
* @param Row $rowToSum
* @param array $aggregationOperations
*/
public function sumRowMetadata($rowToSum)
public function sumRowMetadata($rowToSum, $aggregationOperations = array())
{
if (!empty($rowToSum->metadata)
&& !$this->isSummaryRow()
) {
$aggregatedMetadata = array();
if (is_array($aggregationOperations)) {
// we need to aggregate value before value is overwritten by maybe another row
foreach ($aggregationOperations as $columnn => $operation) {
$thisMetadata = $this->getMetadata($columnn);
$sumMetadata = $rowToSum->getMetadata($columnn);
if ($thisMetadata === false && $sumMetadata === false) {
continue;
}
$aggregatedMetadata[$columnn] = $this->getColumnValuesMerged($operation, $thisMetadata, $sumMetadata);
}
}
// We shall update metadata, and keep the metadata with the _most visits or pageviews_, rather than first or last seen
$visits = max($rowToSum->getColumn(Metrics::INDEX_PAGE_NB_HITS) || $rowToSum->getColumn(Metrics::INDEX_NB_VISITS),
// Old format pre-1.2, @see also method doSumVisitsMetrics()
......@@ -532,6 +562,11 @@ class Row implements \ArrayAccess, \IteratorAggregate
$this->maxVisitsSummed = $visits;
$this->metadata = $rowToSum->metadata;
}
foreach ($aggregatedMetadata as $column => $value) {
// we need to make sure aggregated value is used, and not metadata from $rowToSum
$this->setMetadata($column, $value);
}
}
}
......
......@@ -61,7 +61,7 @@ class Menu extends \Piwik\Plugin\Menu
if (!Piwik::isUserIsAnonymous()) {
$menu->addManageItem('CoreAdminHome_TrackingCode',
$this->urlForAction('trackingCodeGenerator'),
$order = 10);
$order = 20);
if (SettingsManager::hasUserPluginsSettingsForCurrentUser()) {
$menu->addPersonalItem('CoreAdminHome_PluginSettings',
......
......@@ -11,6 +11,7 @@ namespace Piwik\Plugins\CustomVariables;
use Piwik\Config;
use Piwik\DataAccess\LogAggregator;
use Piwik\DataArray;
use Piwik\DataTable;
use Piwik\Metrics;
use Piwik\Tracker\GoalManager;
use Piwik\Tracker;
......@@ -52,7 +53,7 @@ class Archiver extends \Piwik\Plugin\Archiver
public function aggregateMultipleReports()
{
$columnsAggregationOperation = null;
$columnsAggregationOperation = array('slots' => 'uniquearraymerge');
$this->getProcessor()->aggregateDataTableRecords(
self::CUSTOM_VARIABLE_RECORD_NAME,
......
......@@ -151,7 +151,7 @@ class CustomVariables extends \Piwik\Plugin
{
$translationKeys[] = 'CustomVariables_CustomVariables';
$translationKeys[] = 'CustomVariables_ManageDescription';
$translationKeys[] = 'CustomVariables_Scope';
$translationKeys[] = 'CustomVariables_ScopeX';
$translationKeys[] = 'CustomVariables_Index';
$translationKeys[] = 'CustomVariables_Usages';
$translationKeys[] = 'CustomVariables_Unused';
......
......@@ -27,7 +27,7 @@ class Menu extends \Piwik\Plugin\Menu
$idSite = Common::getRequestVar('idSite', $default, 'int');
if (Piwik::isUserHasAdminAccess($idSite)) {
$menu->addManageItem('Custom Variables', $this->urlForAction('manage'), $orderId = 30);
$menu->addManageItem('Custom Variables', $this->urlForAction('manage'), $orderId = 15);
}
}
}
......@@ -13,23 +13,7 @@
manageCustomVarsModel.fetchUsages();
this.model = manageCustomVarsModel;
this.createCustomVariableSlot = function () {
var highestIndex = 5;
angular.forEach(manageCustomVarsModel.customVariables, function (customVar) {
if (customVar.index > highestIndex) {
highestIndex = customVar.index;
}
});
var translate = $filter('translate');
var command = './console customvariables:set-max-custom-variables ' + (highestIndex + 1);
var text = translate('CustomVariables_CreatingCustomVariableTakesTime');
text += '<br /><br />' + translate('CustomVariables_CurrentAvailableCustomVariables', '<strong>' + highestIndex + '</strong>');
text += '<br /><br />' + translate('CustomVariables_ToCreateCustomVarExecute');
text += '<br /><br /><code>' + command + '</code>';
piwik.helper.modalConfirm('<div class="ui-confirm" title="' + translate('CustomVariables_CreateNewSlot') + '">' + text + '<br /><br /></div>');
}
this.siteName = piwik.siteName;
this.scopes = ['visit', 'page'];
}
})();
\ No newline at end of file
<div class="manageCustomVars">
<h2 piwik-enriched-headline>{{ 'CustomVariables_CustomVariables'|translate }}</h2>
<h2 piwik-enriched-headline help-url="http://piwik.org/docs/custom-variables/">{{ 'CustomVariables_CustomVariables'|translate }}</h2>
{{ 'CustomVariables_ManageDescription'|translate }}
<p>
<span ng-bind-html="'CustomVariables_ManageDescription'|translate:manageCustomVars.siteName"></span>
</p>
<br />
<div ng-repeat="scope in manageCustomVars.scopes">
<h2 class="secondary">{{ 'CustomVariables_ScopeX'|translate:(scope|ucfirst) }}</h2>
<table class="dataTable entityTable">
<thead>
<tr>
<th>{{'CustomVariables_Index'|translate }}</th>
<th>{{'CustomVariables_Usages'|translate }}</th>
</tr>
</thead>
<tbody>
<tr>
<td colspan="3" ng-show="manageCustomVars.model.isLoading">{{ 'General_Loading'|translate }}</td>
</tr>
<tr ng-repeat="customVariables in manageCustomVars.model.customVariables|filter:{scope: scope}">
<td class="index">{{ customVariables.index }}</td>
<td>
<span ng-show="(customVariables.usages|length) === 0"
class="unused">{{'CustomVariables_Unused'|translate }}</span>
<span ng-show="customVariables.usages|length" ng-repeat="cvar in customVariables.usages|orderBy:'-nb_actions'">
<span title="{{ 'CustomVariables_UsageDetails'|translate:(cvar.nb_visits ? cvar.nb_visits : 0):(cvar.nb_actions ? cvar.nb_actions : 0) }}">{{ cvar.name }}</span><span ng-show="!$last">, </span>
</span>
</td>
</tr>
</tbody>
</table>
</div>
<h3>{{ customVariables.scope }}</h3>
<table class="dataTable entityTable" style="max-width: 900px;">
<thead>
<tr>
<th>{{'CustomVariables_Scope'|translate }}</th>
<th>{{'CustomVariables_Index'|translate }}</th>
<th>{{'CustomVariables_Usages'|translate }}</th>
</tr>
</thead>
<tbody>
<tr>
<td colspan="3" ng-show="manageCustomVars.model.isLoading">{{ 'General_Loading'|translate }}</td>
</tr>
<tr ng-repeat="customVariables in manageCustomVars.model.customVariables">
<td class="scope">{{ customVariables.scope|ucfirst }}</td>
<td class="index">{{ customVariables.index }}</td>
<td>
<span ng-show="(customVariables.usages|length) === 0"
class="unused">{{'CustomVariables_Unused'|translate }}</span>
<span ng-show="customVariables.usages|length" ng-repeat="cvar in customVariables.usages|orderBy:'-nb_actions'">
<span title="{{ 'CustomVariables_UsageDetails'|translate:cvar.nb_visits:cvar.nb_actions }}">{{ cvar.name }}</span><span ng-show="!$last">, </span>
</span>
</td>
</tr>
</tbody>
</table>
<h2 class="secondary" ng-show="!manageCustomVars.model.isLoading">{{ 'CustomVariables_CreateNewSlot'|translate }}</h2>
<br/>
<a class="btn addCustomVar" ng-show="!manageCustomVars.model.isLoading" value=""
ng-click="manageCustomVars.createCustomVariableSlot()"
>{{ 'CustomVariables_CreateNewSlot'|translate }} <span class="icon-info"></span></a><br/>
<p ng-show="!manageCustomVars.model.isLoading">
{{ 'CustomVariables_CreatingCustomVariableTakesTime'|translate }}
<br /><br />
<span ng-bind-html="'CustomVariables_CurrentAvailableCustomVariables'|translate:('<strong>'+manageCustomVars.model.numSlotsAvailable+'</strong>')"></span>
<br />
<br />
{{ 'CustomVariables_ToCreateCustomVarExecute'|translate }}
<br />
<br />
<code>./console customvariables:set-max-custom-variables {{ manageCustomVars.model.numSlotsAvailable + 1 }}</code>
</p>
</div>
\ No newline at end of file
......@@ -3,6 +3,10 @@
color: @color-silver;
}
table, p {
width: 900px;
}
.scope, .index {
width: 90px;
max-width: 90px;
......
......@@ -15,7 +15,8 @@
customVariables : [],
extractions : [],
isLoading: false,
fetchUsages: fetchUsages
fetchUsages: fetchUsages,
numSlotsAvailable: 5,
};
return model;
......@@ -27,6 +28,13 @@
piwikApi.fetch({method: 'CustomVariables.getUsagesOfSlots'})
.then(function (customVariables) {
model.customVariables = customVariables;
angular.forEach(customVariables, function (customVar) {
if (customVar.index > model.numSlotsAvailable) {
model.numSlotsAvailable = customVar.index;
}
});
})['finally'](function () { // .finally() is not IE8 compatible see https://github.com/angular/angular.js/commit/f078762d48d0d5d9796dcdf2cb0241198677582c
model.isLoading = false;
});
......
......@@ -7,12 +7,12 @@
"PluginDescription": "Custom Variables are (name, value) pairs that you can assign using the Javascript API to visitors or any of their action. Piwik will then report how many visits, pages, conversions for each of these custom names and values. View the detailed Custom Variables for each user and action in the Visitor Log.<br />Required to use <a href=\"http://piwik.org/docs/ecommerce-analytics/\">Ecommerce Analytics</a> feature!",
"ScopePage": "scope page",
"ScopeVisit": "scope visit",
"ManageDescription": "This overview shows all custom variable slots and their usages. The names within each slot are ordered by how often they were used in total.",
"Scope": "Scope",
"ManageDescription": "This overview shows all custom variable slots and their usages for website '%s'. The names within each slot are ordered by how often they were used in total.",
"ScopeX": "Scope %s",
"Index": "Index",
"Usages": "Usages",
"Unused": "Unused",
"CreateNewSlot": "Create a new Custom Variable slot",
"CreateNewSlot": "Increase the number of available Custom Variables slots",
"UsageDetails": "%s visits and %s actions since creation of this website.",
"CreatingCustomVariableTakesTime": "Creating a new custom variable slot can take a long time depending on the size of your database. Therefore it is only possible to do this via a command which needs to be executed on the command line.",
"CurrentAvailableCustomVariables": "Currently you can use up to %s Custom Variables per site.",
......
......@@ -22,10 +22,4 @@ describe("CustomVariables", function () {
expect.screenshot('link_in_menu').to.be.captureSelector('li:contains(Manage)', function (page) {
}, done);
});
it('should show custom variable creation command in dialog', function (done) {
expect.screenshot('create').to.be.captureSelector('.ui-dialog', function (page) {
page.click('.manageCustomVars .addCustomVar')
}, done);
});
});
\ No newline at end of file
Le fichier a été supprimé par une entrée .gitattributes, ou son encodage n'est pas pris en charge.
Le fichier a été supprimé par une entrée .gitattributes, ou son encodage n'est pas pris en charge.
......@@ -362,6 +362,65 @@ class RowTest extends \PHPUnit_Framework_TestCase
$this->assertTrue($this->row->hasColumn('test'));
}
public function test_sumRowMetadata_shouldSumMetadataAccordingToAggregationOperations()
{
$this->row->setColumn('nb_visits', 10);
$this->row->setMetadata('my_sum', 5);
$this->row->setMetadata('my_max', 4);
$this->row->setMetadata('my_array', array(array('test' => 1, 'value' => 1), array('test' => 2, 'value' => 2)));
$row = $this->getTestRowWithNoSubDataTable();
$row->setColumn('nb_visits', 15);
$row->setMetadata('my_sum', 7);
$row->setMetadata('my_max', 2);
$row->setMetadata('my_array', array(array('test' => 3, 'value' => 3), array('test' => 2, 'value' => 2)));
$aggregations = array(
'nosuchcolumn' => 'max', // this metadata name does not exist and should be ignored
'my_sum' => 'sum',
'my_max' => 'max',
'my_array' => 'uniquearraymerge'
);
$this->row->sumRowMetadata($row, $aggregations);
$metadata = $this->row->getMetadata();
$expected = array(
'my_sum' => 12,
'my_max' => 4,
'my_array' => array(array('test' => 1, 'value' => 1), array('test' => 2, 'value' => 2), array('test' => 3, 'value' => 3))
);
$this->assertSame($expected, $metadata);
}
public function test_sumRowMetadata_uniquearraymergeShouldUseArrayFromOtherRow_IfNoMetadataForThisRowSpecified()
{
$row = $this->getTestRowWithNoSubDataTable();
$arrayValue = array(array('test' => 3, 'value' => 3), array('test' => 2, 'value' => 2));
$row->setMetadata('my_array', $arrayValue);
$aggregations = array('my_array' => 'uniquearraymerge');
$this->row->sumRowMetadata($row, $aggregations);
$this->assertSame(array('my_array' => $arrayValue), $this->row->getMetadata());
}
public function test_sumRowMetadata_uniquearraymergeShouldUseArrayFromThisRow_IfNoMetadataForOtherRowSpecified()
{
$row = $this->getTestRowWithNoSubDataTable();
$arrayValue = array(array('test' => 3, 'value' => 3), array('test' => 2, 'value' => 2));
$this->row->setMetadata('my_array', $arrayValue);
$aggregations = array('my_array' => 'uniquearraymerge');
$this->row->sumRowMetadata($row, $aggregations);
$this->assertSame(array('my_array' => $arrayValue), $this->row->getMetadata());
}
private function assertColumnSavesValue($expectedValue, $columnName, $valueToSet)
{
$this->row->setColumn($columnName, $valueToSet);
......
0% Chargement en cours ou .
You are about to add 0 people to the discussion. Proceed with caution.
Terminez d'abord l'édition de ce message.
Veuillez vous inscrire ou vous pour commenter