Questtype ?Textinput?: add support for field sizes (Issue #252) and general improvements
This commit is contained in:
commit
8d903135a5
3476 changed files with 599099 additions and 0 deletions
34
www/analytics/plugins/MultiSites/angularjs/dashboard/dashboard-controller.js
vendored
Normal file
34
www/analytics/plugins/MultiSites/angularjs/dashboard/dashboard-controller.js
vendored
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
/*!
|
||||
* Piwik - Web Analytics
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
*/
|
||||
|
||||
angular.module('piwikApp').controller('MultiSitesDashboardController', function($scope, piwik, multisitesDashboardModel){
|
||||
|
||||
$scope.model = multisitesDashboardModel;
|
||||
|
||||
$scope.reverse = true;
|
||||
$scope.predicate = 'nb_visits';
|
||||
$scope.evolutionSelector = 'visits_evolution';
|
||||
$scope.hasSuperUserAccess = piwik.hasSuperUserAccess;
|
||||
$scope.date = piwik.broadcast.getValueFromUrl('date');
|
||||
$scope.url = piwik.piwik_url;
|
||||
$scope.period = piwik.period;
|
||||
|
||||
$scope.sortBy = function (metric) {
|
||||
|
||||
var reverse = $scope.reverse;
|
||||
if ($scope.predicate == metric) {
|
||||
reverse = !reverse;
|
||||
}
|
||||
|
||||
$scope.predicate = metric;
|
||||
$scope.reverse = reverse;
|
||||
};
|
||||
|
||||
this.refresh = function (interval) {
|
||||
multisitesDashboardModel.fetchAllSites(interval);
|
||||
};
|
||||
});
|
||||
40
www/analytics/plugins/MultiSites/angularjs/dashboard/dashboard-directive.js
vendored
Normal file
40
www/analytics/plugins/MultiSites/angularjs/dashboard/dashboard-directive.js
vendored
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
/*!
|
||||
* Piwik - Web Analytics
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
*/
|
||||
|
||||
/**
|
||||
* Renders the multisites dashboard
|
||||
* Example usage:
|
||||
*
|
||||
* <div piwik-multisites-dashboard
|
||||
* display-revenue-column="true"
|
||||
* show-sparklines="true"
|
||||
* date-sparkline="true"
|
||||
* page-size="50"
|
||||
* auto-refresh-today-report="500" // or 0 to disable
|
||||
* ></div>
|
||||
*/
|
||||
angular.module('piwikApp').directive('piwikMultisitesDashboard', function($document, piwik, $filter){
|
||||
|
||||
return {
|
||||
restrict: 'A',
|
||||
scope: {
|
||||
displayRevenueColumn: '@',
|
||||
showSparklines: '@',
|
||||
dateSparkline: '@'
|
||||
},
|
||||
templateUrl: 'plugins/MultiSites/angularjs/dashboard/dashboard.html?cb=' + piwik.cacheBuster,
|
||||
controller: 'MultiSitesDashboardController',
|
||||
link: function (scope, element, attrs, controller) {
|
||||
|
||||
if (attrs.pageSize) {
|
||||
scope.model.pageSize = attrs.pageSize;
|
||||
}
|
||||
|
||||
controller.refresh(attrs.autoRefreshTodayReport);
|
||||
}
|
||||
};
|
||||
});
|
||||
63
www/analytics/plugins/MultiSites/angularjs/dashboard/dashboard-filter.js
vendored
Normal file
63
www/analytics/plugins/MultiSites/angularjs/dashboard/dashboard-filter.js
vendored
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
/*!
|
||||
* Piwik - Web Analytics
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
*/
|
||||
|
||||
/**
|
||||
* Filters a given list of websites and groups and makes sure only the websites within a given offset and limit are
|
||||
* displayed. It also makes sure sites are displayed under the groups. That means it flattens a structure like this:
|
||||
*
|
||||
* - website1
|
||||
* - website2
|
||||
* - website3.sites // this is a group
|
||||
* - website4
|
||||
* - website5
|
||||
* - website6
|
||||
*
|
||||
* to the following structure
|
||||
* - website1
|
||||
* - website2
|
||||
* - website3.sites // this is a group
|
||||
* - website4
|
||||
* - website5
|
||||
* - website6
|
||||
*/
|
||||
angular.module('piwikApp').filter('multiSitesGroupFilter', function() {
|
||||
return function(websites, from, to) {
|
||||
var offsetEnd = parseInt(from, 10) + parseInt(to, 10);
|
||||
var groups = {};
|
||||
|
||||
var sites = [];
|
||||
for (var index = 0; index < websites.length; index++) {
|
||||
var website = websites[index];
|
||||
|
||||
sites.push(website);
|
||||
if (website.sites && website.sites.length) {
|
||||
groups[website.label] = website;
|
||||
for (var innerIndex = 0; innerIndex < website.sites.length; innerIndex++) {
|
||||
sites.push(website.sites[innerIndex]);
|
||||
}
|
||||
}
|
||||
|
||||
if (sites.length >= offsetEnd) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// if the first site is a website having a group, then try to find the related group and prepend it to the list
|
||||
// of sites to make sure we always display the name of the group that belongs to a website.
|
||||
var filteredSites = sites.slice(from, offsetEnd);
|
||||
|
||||
if (filteredSites.length && filteredSites[0] && filteredSites[0].group) {
|
||||
var groupName = filteredSites[0].group;
|
||||
if (groups[groupName]) {
|
||||
filteredSites.unshift(groups[groupName]);
|
||||
}
|
||||
}
|
||||
|
||||
return filteredSites;
|
||||
};
|
||||
});
|
||||
|
||||
273
www/analytics/plugins/MultiSites/angularjs/dashboard/dashboard-model.js
vendored
Normal file
273
www/analytics/plugins/MultiSites/angularjs/dashboard/dashboard-model.js
vendored
Normal file
|
|
@ -0,0 +1,273 @@
|
|||
/**
|
||||
* Model for Multisites Dashboard aka All Websites Dashboard.
|
||||
*
|
||||
*/
|
||||
angular.module('piwikApp').factory('multisitesDashboardModel', function (piwikApi, $filter, $timeout) {
|
||||
/**
|
||||
*
|
||||
* this is the list of all available sites. For performance reason this list is different to model.sites. ngRepeat
|
||||
* won't operate on the whole list this way. The allSites array contains websites and groups in the following
|
||||
* structure
|
||||
*
|
||||
* - website1
|
||||
* - website2
|
||||
* - website3.sites = [ // this is a group
|
||||
* - website4
|
||||
* - website5
|
||||
* ]
|
||||
* - website6
|
||||
*
|
||||
* This structure allows us to display the sites within a group directly under the group without big logic and also
|
||||
* allows us to calculate the summary for each group easily
|
||||
*/
|
||||
var allSitesByGroup = [];
|
||||
|
||||
var model = {};
|
||||
// those sites are going to be displayed
|
||||
model.sites = [];
|
||||
model.isLoading = false;
|
||||
model.pageSize = 5;
|
||||
model.currentPage = 0;
|
||||
model.totalVisits = '?';
|
||||
model.totalActions = '?';
|
||||
model.totalRevenue = '?';
|
||||
model.searchTerm = '';
|
||||
model.lastVisits = '?';
|
||||
model.lastVisitsDate = '?';
|
||||
|
||||
fetchPreviousSummary();
|
||||
|
||||
// create a new group object which has similar structure than a website
|
||||
function createGroup(name){
|
||||
return {
|
||||
label: name,
|
||||
sites: [],
|
||||
nb_visits: 0,
|
||||
nb_pageviews: 0,
|
||||
revenue: 0,
|
||||
isGroup: true
|
||||
};
|
||||
}
|
||||
|
||||
// create a new group with empty site to make sure we do not change the original group in $allSites
|
||||
function copyGroup(group)
|
||||
{
|
||||
return {
|
||||
label: group.label,
|
||||
sites: [],
|
||||
nb_visits: group.nb_visits,
|
||||
nb_pageviews: group.nb_pageviews,
|
||||
revenue: group.revenue,
|
||||
isGroup: true
|
||||
};
|
||||
}
|
||||
|
||||
function onError () {
|
||||
model.errorLoadingSites = true;
|
||||
model.sites = [];
|
||||
allSitesByGroup = [];
|
||||
}
|
||||
|
||||
function calculateMetricsForEachGroup(groups)
|
||||
{
|
||||
angular.forEach(groups, function (group) {
|
||||
angular.forEach(group.sites, function (site) {
|
||||
var revenue = (site.revenue+'').match(/(\d+\.?\d*)/); // convert $ 0.00 to 0.00 or 5€ to 5
|
||||
group.nb_visits += parseInt(site.nb_visits, 10);
|
||||
group.nb_pageviews += parseInt(site.nb_pageviews, 10);
|
||||
if (revenue.length) {
|
||||
group.revenue += parseInt(revenue[0], 10);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function createGroupsAndMoveSitesIntoRelatedGroup(allSitesUnordered, reportMetadata)
|
||||
{
|
||||
var sitesByGroup = [];
|
||||
var groups = {};
|
||||
|
||||
// we do 3 things (complete site information, create groups, move sites into group) in one step for
|
||||
// performance reason, there can be > 20k sites
|
||||
angular.forEach(allSitesUnordered, function (site, index) {
|
||||
site.idsite = reportMetadata[index].idsite;
|
||||
site.group = reportMetadata[index].group;
|
||||
site.main_url = reportMetadata[index].main_url;
|
||||
|
||||
if (site.group) {
|
||||
|
||||
if (!groups[site.group]) {
|
||||
var group = createGroup(site.group);
|
||||
|
||||
groups[site.group] = group;
|
||||
sitesByGroup.push(group);
|
||||
}
|
||||
|
||||
groups[site.group].sites.push(site);
|
||||
|
||||
} else {
|
||||
sitesByGroup.push(site);
|
||||
}
|
||||
});
|
||||
|
||||
calculateMetricsForEachGroup(groups);
|
||||
|
||||
return sitesByGroup;
|
||||
}
|
||||
|
||||
model.updateWebsitesList = function (processedReport) {
|
||||
if (!processedReport) {
|
||||
onError();
|
||||
return;
|
||||
}
|
||||
|
||||
var allSitesUnordered = processedReport.reportData;
|
||||
model.totalVisits = processedReport.reportTotal.nb_visits;
|
||||
model.totalActions = processedReport.reportTotal.nb_actions;
|
||||
model.totalRevenue = processedReport.reportTotal.revenue;
|
||||
|
||||
allSitesByGroup = createGroupsAndMoveSitesIntoRelatedGroup(allSitesUnordered, processedReport.reportMetadata);
|
||||
|
||||
if (!allSitesByGroup.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (model.searchTerm) {
|
||||
model.searchSite(model.searchTerm);
|
||||
} else {
|
||||
model.sites = allSitesByGroup;
|
||||
}
|
||||
};
|
||||
|
||||
model.getNumberOfFilteredSites = function () {
|
||||
var numSites = model.sites.length;
|
||||
|
||||
var groupNames = {};
|
||||
|
||||
for (var index = 0; index < model.sites.length; index++) {
|
||||
var site = model.sites[index];
|
||||
if (site && site.isGroup) {
|
||||
numSites += site.sites.length;
|
||||
}
|
||||
}
|
||||
|
||||
return numSites;
|
||||
};
|
||||
|
||||
model.getNumberOfPages = function () {
|
||||
return Math.ceil(model.getNumberOfFilteredSites() / model.pageSize - 1);
|
||||
};
|
||||
|
||||
model.getCurrentPagingOffsetStart = function() {
|
||||
return Math.ceil(model.currentPage * model.pageSize);
|
||||
};
|
||||
|
||||
model.getCurrentPagingOffsetEnd = function() {
|
||||
var end = model.getCurrentPagingOffsetStart() + parseInt(model.pageSize, 10);
|
||||
var max = model.getNumberOfFilteredSites();
|
||||
if (end > max) {
|
||||
end = max;
|
||||
}
|
||||
return parseInt(end, 10);
|
||||
};
|
||||
|
||||
model.previousPage = function () {
|
||||
model.currentPage = model.currentPage - 1;
|
||||
};
|
||||
|
||||
model.nextPage = function () {
|
||||
model.currentPage = model.currentPage + 1;
|
||||
};
|
||||
|
||||
function nestedSearch(sitesByGroup, term)
|
||||
{
|
||||
var filteredSites = [];
|
||||
|
||||
for (var index in sitesByGroup) {
|
||||
var site = sitesByGroup[index];
|
||||
if (site.isGroup) {
|
||||
var matchingSites = nestedSearch(site.sites, term);
|
||||
if (matchingSites.length || (''+site.label).toLowerCase().indexOf(term) > -1) {
|
||||
var clonedGroup = copyGroup(site);
|
||||
clonedGroup.sites = matchingSites;
|
||||
filteredSites.push(clonedGroup);
|
||||
}
|
||||
} else if ((''+site.label).toLowerCase().indexOf(term) > -1) {
|
||||
filteredSites.push(site);
|
||||
} else if (site.group && (''+site.group).toLowerCase().indexOf(term) > -1) {
|
||||
filteredSites.push(site);
|
||||
}
|
||||
}
|
||||
|
||||
return filteredSites;
|
||||
}
|
||||
|
||||
model.searchSite = function (term) {
|
||||
model.searchTerm = term;
|
||||
model.currentPage = 0;
|
||||
model.sites = nestedSearch(allSitesByGroup, term);
|
||||
};
|
||||
|
||||
function fetchPreviousSummary () {
|
||||
piwikApi.fetch({
|
||||
method: 'API.getLastDate'
|
||||
}).then(function (response) {
|
||||
if (response && response.value) {
|
||||
return response.value;
|
||||
}
|
||||
}).then(function (lastDate) {
|
||||
if (!lastDate) {
|
||||
return;
|
||||
}
|
||||
|
||||
model.lastVisitsDate = lastDate;
|
||||
|
||||
return piwikApi.fetch({
|
||||
method: 'API.getProcessedReport',
|
||||
apiModule: 'MultiSites',
|
||||
apiAction: 'getAll',
|
||||
hideMetricsDoc: '1',
|
||||
filter_limit: '0',
|
||||
showColumns: 'label,nb_visits',
|
||||
enhanced: 1,
|
||||
date: lastDate
|
||||
});
|
||||
}).then(function (response) {
|
||||
if (response && response.reportTotal) {
|
||||
model.lastVisits = response.reportTotal.nb_visits;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
model.fetchAllSites = function (refreshInterval) {
|
||||
|
||||
if (model.isLoading) {
|
||||
piwikApi.abort();
|
||||
}
|
||||
|
||||
model.isLoading = true;
|
||||
model.errorLoadingSites = false;
|
||||
|
||||
return piwikApi.fetch({
|
||||
method: 'API.getProcessedReport',
|
||||
apiModule: 'MultiSites',
|
||||
apiAction: 'getAll',
|
||||
hideMetricsDoc: '1',
|
||||
filter_limit: '-1',
|
||||
showColumns: 'label,nb_visits,nb_pageviews,visits_evolution,pageviews_evolution,revenue_evolution,nb_actions,revenue',
|
||||
enhanced: 1
|
||||
}).then(function (response) {
|
||||
model.updateWebsitesList(response);
|
||||
}, onError)['finally'](function () {
|
||||
model.isLoading = false;
|
||||
|
||||
if (refreshInterval && refreshInterval > 0) {
|
||||
$timeout(function () {
|
||||
model.fetchAllSites(refreshInterval);
|
||||
}, refreshInterval * 1000);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
return model;
|
||||
});
|
||||
|
|
@ -0,0 +1,128 @@
|
|||
<div>
|
||||
<h2 piwik-enriched-headline
|
||||
help-url="http://piwik.org/docs/manage-websites/#all-websites-dashboard"
|
||||
feature-name="{{ 'General_AllWebsitesDashboard'|translate }}">
|
||||
{{ 'General_AllWebsitesDashboard'|translate }}
|
||||
<span class='smallTitle'
|
||||
title="{{ 'General_EvolutionSummaryGeneric'|translate:('General_NVisits'|translate:model.totalVisits):date:model.lastVisits:model.lastVisitsDate:(model.totalVisits|evolution:model.lastVisits)}}"
|
||||
ng-bind-html="'General_TotalVisitsPageviewsRevenue' | translate:('<strong>'+model.totalVisits+'</strong>'):('<strong>'+model.totalActions+'</strong>'):('<strong>' + model.totalRevenue + '</strong>')">
|
||||
</span>
|
||||
</h2>
|
||||
|
||||
<table id="mt" class="dataTable" cellspacing="0">
|
||||
<thead>
|
||||
<tr>
|
||||
<th id="names" class="label" ng-click="sortBy('label')" ng-class="{columnSorted: 'label' == predicate}">
|
||||
<span class="heading">{{ 'General_Website'|translate }}</span>
|
||||
<span ng-class="{multisites_asc: !reverse && 'label' == predicate, multisites_desc: reverse && 'label' == predicate}" class="arrow"></span>
|
||||
</th>
|
||||
<th id="visits" class="multisites-column" ng-click="sortBy('nb_visits')" ng-class="{columnSorted: 'nb_visits' == predicate}">
|
||||
<span class="heading">{{ 'General_ColumnNbVisits'|translate }}</span>
|
||||
<span ng-class="{multisites_asc: !reverse && 'nb_visits' == predicate, multisites_desc: reverse && 'nb_visits' == predicate}" class="arrow"></span>
|
||||
</th>
|
||||
<th id="pageviews" class="multisites-column" ng-click="sortBy('nb_pageviews')" ng-class="{columnSorted: 'nb_pageviews' == predicate}">
|
||||
<span class="heading">{{ 'General_ColumnPageviews'|translate }}</span>
|
||||
<span ng-class="{multisites_asc: !reverse && 'nb_pageviews' == predicate, multisites_desc: reverse && 'nb_pageviews' == predicate}" class="arrow"></span>
|
||||
</th>
|
||||
|
||||
<th ng-if="displayRevenueColumn" id="revenue" class="multisites-column" ng-click="sortBy('revenue')" ng-class="{columnSorted: 'revenue' == predicate}">
|
||||
<span class="heading">{{ 'General_ColumnRevenue'|translate }}</span>
|
||||
<span ng-class="{multisites_asc: !reverse && 'revenue' == predicate, multisites_desc: reverse && 'revenue' == predicate}" class="arrow"></span>
|
||||
</th>
|
||||
|
||||
<th id="evolution" colspan="{{ showSparklines ? 2 : 1 }}" ng-class="{columnSorted: evolutionSelector == predicate}">
|
||||
<span class="arrow" ng-class="{multisites_asc: !reverse && evolutionSelector == predicate, multisites_desc: reverse && evolutionSelector == predicate}"></span>
|
||||
<span class="evolution"
|
||||
ng-click="sortBy(evolutionSelector)"> {{ 'MultiSites_Evolution'|translate }}</span>
|
||||
<select class="selector" id="evolution_selector" ng-model="evolutionSelector"
|
||||
ng-change="predicate = evolutionSelector">
|
||||
<option value="visits_evolution">{{ 'General_ColumnNbVisits'|translate }}</option>
|
||||
<option value="pageviews_evolution">{{ 'General_ColumnPageviews'|translate }}</option>
|
||||
<option ng-if="displayRevenueColumn" value="revenue_evolution">{{ 'General_ColumnRevenue'|translate }}</option>
|
||||
</select>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody id="tb" ng-if="model.isLoading">
|
||||
<tr>
|
||||
<td colspan="7" class="allWebsitesLoading">
|
||||
{{ 'MultiSites_LoadingWebsites' | translate }}
|
||||
<span class="allWebsitesLoadingIndicator"> </span>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
<tbody id="tb" ng-if="!model.isLoading">
|
||||
|
||||
<tr ng-if="model.errorLoadingSites">
|
||||
<td colspan="7">
|
||||
<div class="notification system notification-error">
|
||||
{{ 'General_ErrorRequest'|translate }}
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr website="website"
|
||||
evolution-metric="evolutionSelector"
|
||||
piwik-multisites-site
|
||||
date-sparkline="dateSparkline"
|
||||
show-sparklines="showSparklines"
|
||||
metric="predicate"
|
||||
ng-class-odd="'columnodd'"
|
||||
display-revenue-column="displayRevenueColumn"
|
||||
ng-repeat="website in model.sites | orderBy:predicate:reverse | multiSitesGroupFilter:model.getCurrentPagingOffsetStart():model.pageSize">
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
<tfoot>
|
||||
|
||||
<tr ng-if="hasSuperUserAccess">
|
||||
<td colspan="8" class="add_new_site">
|
||||
<a href="{{ url }}?module=SitesManager&action=index&showaddsite=1&period={{ period }}&date={{ date }}">
|
||||
<img src='plugins/UsersManager/images/add.png' alt=""/> {{ 'SitesManager_AddSite'|translate }}
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr ng-if="!hasSuperUserAccess">
|
||||
<td colspan="8">
|
||||
<br/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="8" class="site_search">
|
||||
<input type="text"
|
||||
ng-change="model.searchSite(searchTerm)"
|
||||
ng-model="searchTerm"
|
||||
placeholder="{{ 'Actions_SubmenuSitesearch' | translate }}">
|
||||
<img title="Search"
|
||||
ng-show="!searchTerm"
|
||||
class="search_ico"
|
||||
src="plugins/Zeitgeist/images/search_ico.png"/>
|
||||
<img title="Clear"
|
||||
ng-show="searchTerm"
|
||||
ng-click="searchTerm='';model.searchSite('')"
|
||||
class="reset"
|
||||
src="plugins/CoreHome/images/reset_search.png"/>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr row_id="last">
|
||||
<td colspan="8" class="paging" ng-hide="model.numberOfPages() <= 1">
|
||||
<span id="prev" class="previous" ng-hide="model.currentPage == 0" ng-click="model.previousPage()">
|
||||
<span style="cursor:pointer;">« {{ 'General_Previous'|translate }}</span>
|
||||
</span>
|
||||
<span class="dataTablePages">
|
||||
<span id="counter">
|
||||
{{ model.getCurrentPagingOffsetStart() }} - {{ model.getCurrentPagingOffsetEnd() }} of {{ model.getNumberOfFilteredSites() }}
|
||||
</span>
|
||||
</span>
|
||||
<span id="next" class="next" ng-hide="model.currentPage >= model.getNumberOfPages()" ng-click="model.nextPage()">
|
||||
<span style="cursor:pointer;" class="pointer">{{ 'General_Next'|translate }} »</span>
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
</div>
|
||||
|
|
@ -0,0 +1,185 @@
|
|||
|
||||
.smallTitle {
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
#multisites {
|
||||
border: 0;
|
||||
padding: 0 15px;
|
||||
font-size: 14px;
|
||||
|
||||
.notification-error {
|
||||
margin-top: 15px;
|
||||
}
|
||||
|
||||
.add_new_site,
|
||||
.clean {
|
||||
border: 0 !important;
|
||||
text-align: right; padding-top: 15px;padding-right:10px;
|
||||
}
|
||||
|
||||
.add_new_site {
|
||||
img {
|
||||
margin: 0px;
|
||||
}
|
||||
}
|
||||
|
||||
.site_search {
|
||||
padding: 0px;
|
||||
text-align: center;
|
||||
border: 0 !important;
|
||||
}
|
||||
|
||||
td, tr, .sparkline {
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
padding: 1px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.indicator {
|
||||
background: url(plugins/MultiSites/images/loading-blue.gif) no-repeat center;
|
||||
height: 20px;
|
||||
width: 60px;
|
||||
margin: auto;
|
||||
border: 0 !important;
|
||||
}
|
||||
|
||||
.paging {
|
||||
padding: 20px;
|
||||
|
||||
.previous {
|
||||
padding-right: 20px;
|
||||
}
|
||||
.next {
|
||||
padding-left: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
.top_controls {
|
||||
height: 10px;
|
||||
}
|
||||
|
||||
th {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.site_search input {
|
||||
margin-right: 0px;
|
||||
margin-left: 25px;
|
||||
}
|
||||
|
||||
.search_ico {
|
||||
position: relative;
|
||||
left: -25px;
|
||||
margin-right: 0px;
|
||||
}
|
||||
.reset {
|
||||
position: relative;
|
||||
left: -25px;
|
||||
cursor: pointer;
|
||||
margin-right: 0px;
|
||||
}
|
||||
|
||||
tr.columnodd:hover td, tr.columnodd td {
|
||||
background: #F2F2F2 !important;
|
||||
}
|
||||
|
||||
tr:hover td {
|
||||
background: #FFF !important;
|
||||
}
|
||||
|
||||
tr.group {
|
||||
font-weight: bold;
|
||||
height: 30px;
|
||||
}
|
||||
tr.groupedWebsite .label {
|
||||
padding-left: 50px;
|
||||
}
|
||||
td.multisites-label {
|
||||
padding-left: 15px;
|
||||
text-align: left;
|
||||
width: 250px;
|
||||
}
|
||||
td.multisites-label a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
td.multisites-column,
|
||||
th.multisites-column {
|
||||
width: 70px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
td.multisites-column-evolution,
|
||||
th.multisites-column-evolution {
|
||||
width: 70px;
|
||||
}
|
||||
|
||||
th#evolution {
|
||||
width:350px;
|
||||
}
|
||||
|
||||
th#visits {
|
||||
width: 100px;
|
||||
}
|
||||
|
||||
th#pageviews {
|
||||
width: 110px;
|
||||
}
|
||||
|
||||
th#revenue {
|
||||
width: 110px;
|
||||
}
|
||||
|
||||
.evolution {
|
||||
cursor:pointer;
|
||||
}
|
||||
|
||||
.allWebsitesLoading {
|
||||
padding:20px
|
||||
}
|
||||
|
||||
.allWebsitesLoadingIndicator {
|
||||
background: url(plugins/Zeitgeist/images/loading-blue.gif) no-repeat right 3px;
|
||||
display: inline-block;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
.heading {
|
||||
display: inline-block;
|
||||
margin-top: 4px;
|
||||
}
|
||||
.multisites_desc {
|
||||
width: 16px;
|
||||
height: 13px;
|
||||
display: inline-block;
|
||||
background-image: url(plugins/Zeitgeist/images/sortdesc.png);
|
||||
}
|
||||
.multisites_asc {
|
||||
width: 16px;
|
||||
height: 13px;
|
||||
display: inline-block;
|
||||
background-image: url(plugins/Zeitgeist/images/sortasc.png);
|
||||
}
|
||||
div.sparkline {
|
||||
float:none;
|
||||
}
|
||||
|
||||
tfoot td {
|
||||
border-bottom: 0px;
|
||||
}
|
||||
}
|
||||
|
||||
#mt thead {
|
||||
line-height: 2.5em;
|
||||
}
|
||||
|
||||
#mt thead *:first-child {
|
||||
border-top-left-radius: 7px
|
||||
}
|
||||
|
||||
#mt thead *:last-child {
|
||||
border-top-right-radius: 7px;
|
||||
}
|
||||
55
www/analytics/plugins/MultiSites/angularjs/site/site-directive.js
vendored
Normal file
55
www/analytics/plugins/MultiSites/angularjs/site/site-directive.js
vendored
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
/*!
|
||||
* Piwik - Web Analytics
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
*/
|
||||
|
||||
/**
|
||||
* Renders a single website row, for instance to be used within the MultiSites Dashboard.
|
||||
*
|
||||
* Usage:
|
||||
* <div piwik-multisites-site>
|
||||
* website="{label: 'Name', main_url: 'http://...', idsite: '...'}"
|
||||
* evolution-metric="visits_evolution"
|
||||
* show-sparklines="true"
|
||||
* date-sparkline="2014-01-01,2014-02-02"
|
||||
* display-revenue-column="true"
|
||||
* </div>
|
||||
*/
|
||||
angular.module('piwikApp').directive('piwikMultisitesSite', function($document, piwik, $filter){
|
||||
|
||||
return {
|
||||
restrict: 'AC',
|
||||
replace: true,
|
||||
scope: {
|
||||
website: '=',
|
||||
evolutionMetric: '=',
|
||||
showSparklines: '=',
|
||||
dateSparkline: '=',
|
||||
displayRevenueColumn: '=',
|
||||
metric: '='
|
||||
},
|
||||
templateUrl: 'plugins/MultiSites/angularjs/site/site.html?cb=' + piwik.cacheBuster,
|
||||
controller: function ($scope) {
|
||||
|
||||
$scope.period = piwik.period;
|
||||
$scope.date = piwik.broadcast.getValueFromUrl('date');
|
||||
$scope.parseInt = parseInt;
|
||||
|
||||
this.getWebsite = function () {
|
||||
return $scope.website;
|
||||
};
|
||||
|
||||
$scope.sparklineImage = function(website){
|
||||
var append = '';
|
||||
var token_auth = piwik.broadcast.getValueFromUrl('token_auth');
|
||||
if (token_auth.length) {
|
||||
append = '&token_auth=' + token_auth;
|
||||
}
|
||||
|
||||
return piwik.piwik_url + '?module=MultiSites&action=getEvolutionGraph&period=' + $scope.period + '&date=' + $scope.dateSparkline + '&evolutionBy=' +$scope.metric + '&columns=' + $scope.metric + '&idSite=' + website.idsite + '&idsite=' + website.idsite + '&viewDataTable=sparkline' + append + '&colors=' + encodeURIComponent(JSON.stringify(piwik.getSparklineColors()));
|
||||
};
|
||||
}
|
||||
};
|
||||
});
|
||||
39
www/analytics/plugins/MultiSites/angularjs/site/site.html
Normal file
39
www/analytics/plugins/MultiSites/angularjs/site/site.html
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
<tr ng-class="{'groupedWebsite': website.group, 'website': !website.group, 'group': website.isGroup}">
|
||||
<td ng-if="!website.isGroup" class="multisites-label label">
|
||||
<a title="View reports" ng-href="index.php?module=CoreHome&action=index&date={{ date }}&period={{ period }}&idSite={{ website.idsite }}">{{ website.label }}</a>
|
||||
|
||||
<span style="width: 10px; margin-left:3px;">
|
||||
<a target="_blank" title="{{ 'General_GoTo'|translate:website.main_url }}" ng-href="{{ website.main_url }}">
|
||||
<img src="plugins/MultiSites/images/link.gif"/></a>
|
||||
</span>
|
||||
</td>
|
||||
<td ng-if="website.isGroup" class="multisites-label label">
|
||||
{{ website.label }}
|
||||
</td>
|
||||
<td class="multisites-column">
|
||||
{{ website.nb_visits }}
|
||||
</td>
|
||||
<td class="multisites-column">
|
||||
{{ website.nb_pageviews }}
|
||||
</td>
|
||||
<td ng-if="displayRevenueColumn" class="multisites-column">
|
||||
{{ website.revenue }}
|
||||
</td>
|
||||
|
||||
<td ng-if="period != 'range'" style="width:170px;">
|
||||
<div class="visits" ng-if="!website.isGroup">
|
||||
<span ng-show="parseInt(website[evolutionMetric]) > 0"><img src="plugins/MultiSites/images/arrow_up.png" alt="" /> <span style="color: green;">{{ website[evolutionMetric] }} </span></span>
|
||||
<span ng-show="parseInt(website[evolutionMetric]) == 0"><img src="plugins/MultiSites/images/stop.png" alt="" /> <span>{{ website[evolutionMetric] }}</span></span>
|
||||
<span ng-show="parseInt(website[evolutionMetric]) < 0"><img src="plugins/MultiSites/images/arrow_down.png" alt="" /> <span style="color: red;">{{ website[evolutionMetric] }} </span></span>
|
||||
</div>
|
||||
</td>
|
||||
|
||||
<td ng-if="showSparklines" style="width:180px;">
|
||||
<div ng-if="!website.isGroup" class="sparkline" style="width: 100px; margin: auto;">
|
||||
<a target="_blank" ng-href="index.php?module=CoreHome&action=index&date={{ date }}&period={{ period }}&idSite={{ website.idsite }}"
|
||||
title="{{ 'General_GoTo'|translate:('Dashboard_DashboardOf'|translate:website.label) }}">
|
||||
<img alt="" ng-src="{{ sparklineImage(website) }}" width="100" height="25" />
|
||||
</a>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
Loading…
Add table
Add a link
Reference in a new issue