Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/matomo-org/matomo.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Steur <thomas.steur@gmail.com>2015-07-03 03:54:27 +0300
committersgiehl <stefan@piwik.org>2015-10-06 18:25:13 +0300
commit9ba8f216fd7856ce5fef06bf82ecb8f8a2e7e630 (patch)
tree6ce07d18a85d00b39ab720abe042361c0775aead /plugins/Dashboard
parent8ccc9dc05da021325cdbf141a548637fa52f16b2 (diff)
generate pages instead of implementing them in each controller
Diffstat (limited to 'plugins/Dashboard')
-rw-r--r--plugins/Dashboard/API.php54
-rw-r--r--plugins/Dashboard/Categories/DashboardCategory.php17
-rw-r--r--plugins/Dashboard/Controller.php17
-rw-r--r--plugins/Dashboard/Dashboard.php64
-rw-r--r--plugins/Dashboard/Menu.php19
-rw-r--r--plugins/Dashboard/Model.php8
-rw-r--r--plugins/Dashboard/angularjs/common/services/dashboards-model.js68
-rw-r--r--plugins/Dashboard/angularjs/dashboard/dashboard.directive.js103
-rw-r--r--plugins/Dashboard/javascripts/dashboard.js106
-rw-r--r--plugins/Dashboard/javascripts/dashboardObject.js143
-rwxr-xr-xplugins/Dashboard/javascripts/dashboardWidget.js9
-rw-r--r--plugins/Dashboard/javascripts/widgetMenu.js102
-rw-r--r--plugins/Dashboard/templates/embeddedIndex.twig8
13 files changed, 478 insertions, 240 deletions
diff --git a/plugins/Dashboard/API.php b/plugins/Dashboard/API.php
index f4637e862a..7bd5bd73a5 100644
--- a/plugins/Dashboard/API.php
+++ b/plugins/Dashboard/API.php
@@ -8,7 +8,6 @@
namespace Piwik\Plugins\Dashboard;
use Piwik\Piwik;
-use Piwik\WidgetsList;
/**
* This API is the <a href='http://piwik.org/docs/analytics-api/reference/' rel='noreferrer' target='_blank'>Dashboard API</a>: it gives information about dashboards.
@@ -43,25 +42,22 @@ class API extends \Piwik\Plugin\API
/**
* Get the default dashboard.
- *
- * @return array[]
+ * @return \array[]
*/
private function getDefaultDashboard()
{
$defaultLayout = $this->dashboard->getDefaultLayout();
$defaultLayout = $this->dashboard->decodeLayout($defaultLayout);
+ $defaultDashboard = array('name' => Piwik::translate('Dashboard_Dashboard'), 'layout' => $defaultLayout, 'iddashboard' => 1);
- $defaultDashboard = array('name' => Piwik::translate('Dashboard_Dashboard'), 'layout' => $defaultLayout);
-
- $widgets = $this->getExistingWidgetsWithinDashboard($defaultDashboard);
+ $widgets = $this->getVisibleWidgetsWithinDashboard($defaultDashboard);
return $this->buildDashboard($defaultDashboard, $widgets);
}
/**
* Get all dashboards which a user has created.
- *
- * @return array[]
+ * @return \array[]
*/
private function getUserDashboards()
{
@@ -71,17 +67,14 @@ class API extends \Piwik\Plugin\API
$dashboards = array();
foreach ($userDashboards as $userDashboard) {
-
- if ($this->hasDashboardColumns($userDashboard)) {
- $widgets = $this->getExistingWidgetsWithinDashboard($userDashboard);
- $dashboards[] = $this->buildDashboard($userDashboard, $widgets);
- }
+ $widgets = $this->getVisibleWidgetsWithinDashboard($userDashboard);
+ $dashboards[] = $this->buildDashboard($userDashboard, $widgets);
}
return $dashboards;
}
- private function getExistingWidgetsWithinDashboard($dashboard)
+ private function getVisibleWidgetsWithinDashboard($dashboard)
{
$columns = $this->getColumnsFromDashboard($dashboard);
@@ -91,7 +84,7 @@ class API extends \Piwik\Plugin\API
foreach ($columns as $column) {
foreach ($column as $widget) {
- if ($this->widgetIsNotHidden($widget) && $this->widgetExists($widget)) {
+ if ($this->widgetIsNotHidden($widget) && !empty($widget->parameters->module)) {
$module = $widget->parameters->module;
$action = $widget->parameters->action;
@@ -105,39 +98,24 @@ class API extends \Piwik\Plugin\API
private function getColumnsFromDashboard($dashboard)
{
- if (is_array($dashboard['layout'])) {
-
- return $dashboard['layout'];
+ if (empty($dashboard['layout'])) {
+ return array();
}
- return $dashboard['layout']->columns;
- }
-
- private function hasDashboardColumns($dashboard)
- {
if (is_array($dashboard['layout'])) {
+ return $dashboard['layout'];
+ }
- return !empty($dashboard['layout']);
+ if (!empty($dashboard['layout']->columns)) {
+ return $dashboard['layout']->columns;
}
- return !empty($dashboard['layout']->columns);
+ return array();
}
private function buildDashboard($dashboard, $widgets)
{
- return array('name' => $dashboard['name'], 'widgets' => $widgets);
- }
-
- private function widgetExists($widget)
- {
- if (empty($widget->parameters->module)) {
- return false;
- }
-
- $module = $widget->parameters->module;
- $action = $widget->parameters->action;
-
- return WidgetsList::isDefined($module, $action);
+ return array('name' => $dashboard['name'], 'id' => $dashboard['iddashboard'], 'widgets' => $widgets);
}
private function widgetIsNotHidden($widget)
diff --git a/plugins/Dashboard/Categories/DashboardCategory.php b/plugins/Dashboard/Categories/DashboardCategory.php
new file mode 100644
index 0000000000..99a3785c84
--- /dev/null
+++ b/plugins/Dashboard/Categories/DashboardCategory.php
@@ -0,0 +1,17 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ *
+ */
+namespace Piwik\Plugins\Dashboard\Categories;
+
+use Piwik\Category\Category;
+
+class DashboardCategory extends Category
+{
+ protected $id = 'Dashboard_Dashboard';
+ protected $order = 0;
+}
diff --git a/plugins/Dashboard/Controller.php b/plugins/Dashboard/Controller.php
index d77c283273..bef5a89237 100644
--- a/plugins/Dashboard/Controller.php
+++ b/plugins/Dashboard/Controller.php
@@ -13,8 +13,6 @@ use Piwik\Db;
use Piwik\Piwik;
use Piwik\Session\SessionNamespace;
use Piwik\View;
-use Piwik\WidgetsList;
-use Piwik\FrontController;
/**
* Dashboard Controller
@@ -39,24 +37,21 @@ class Controller extends \Piwik\Plugin\Controller
$view = new View($template);
$this->setGeneralVariablesView($view);
- $view->availableWidgets = json_encode(WidgetsList::get());
$view->availableLayouts = $this->getAvailableLayouts();
$view->dashboardId = Common::getRequestVar('idDashboard', 1, 'int');
- // get the layout via FrontController so controller events are posted
- $view->dashboardLayout = FrontController::getInstance()->dispatch('Dashboard', 'getDashboardLayout',
- array($checkToken = false));
-
return $view;
}
+ // this
public function embeddedIndex()
{
$view = $this->_getDashboardView('@Dashboard/embeddedIndex');
return $view->render();
}
+ // this is the exported widget
public function index()
{
$view = $this->_getDashboardView('@Dashboard/index');
@@ -70,14 +65,6 @@ class Controller extends \Piwik\Plugin\Controller
return $view->render();
}
- public function getAvailableWidgets()
- {
- $this->checkTokenInUrl();
-
- Json::sendHeaderJSON();
- return json_encode(WidgetsList::get());
- }
-
public function getDashboardLayout($checkToken = true)
{
if ($checkToken) {
diff --git a/plugins/Dashboard/Dashboard.php b/plugins/Dashboard/Dashboard.php
index 9ccbb822e4..5a0a7cc0ec 100644
--- a/plugins/Dashboard/Dashboard.php
+++ b/plugins/Dashboard/Dashboard.php
@@ -11,7 +11,8 @@ namespace Piwik\Plugins\Dashboard;
use Piwik\Common;
use Piwik\Db;
use Piwik\Piwik;
-use Piwik\WidgetsList;
+use Piwik\Category\Subcategory;
+use Piwik\Widget\WidgetConfig;
/**
*/
@@ -26,10 +27,43 @@ class Dashboard extends \Piwik\Plugin
'AssetManager.getJavaScriptFiles' => 'getJsFiles',
'AssetManager.getStylesheetFiles' => 'getStylesheetFiles',
'UsersManager.deleteUser' => 'deleteDashboardLayout',
- 'Translate.getClientSideTranslationKeys' => 'getClientSideTranslationKeys'
+ 'Translate.getClientSideTranslationKeys' => 'getClientSideTranslationKeys',
+ 'Widget.addWidgetConfigs' => 'addWidgetConfigs',
+ 'Category.addSubcategories' => 'addSubcategories'
);
}
+ public function addWidgetConfigs(&$widgets)
+ {
+ $dashboards = API::getInstance()->getDashboards();
+
+ foreach ($dashboards as $dashboard) {
+ $config = new WidgetConfig();
+ $config->setIsNotWidgetizable();
+ $config->setModule('Dashboard');
+ $config->setAction('embeddedIndex');
+ $config->setCategoryId('Dashboard_Dashboard');
+ $config->setSubcategoryId($dashboard['id']);
+ $config->setParameters(array('idDashboard' => $dashboard['id']));
+ $widgets[] = $config;
+ }
+ }
+
+ public function addSubcategories(&$subcategories)
+ {
+ $dashboards = API::getInstance()->getDashboards();
+
+ $order = 0;
+ foreach ($dashboards as $dashboard) {
+ $subcategory = new Subcategory();
+ $subcategory->setName($dashboard['name']);
+ $subcategory->setCategoryId('Dashboard_Dashboard');
+ $subcategory->setId($dashboard['id']);
+ $subcategory->setOrder($order++);
+ $subcategories[] = $subcategory;
+ }
+ }
+
/**
* Returns the layout in the DB for the given user, or false if the layout has not been set yet.
* Parameters must be checked BEFORE this function call
@@ -70,14 +104,14 @@ class Dashboard extends \Piwik\Plugin
$defaultLayout = '[
[
- {"uniqueId":"widgetVisitsSummarygetEvolutionGraphcolumnsArray","parameters":{"module":"VisitsSummary","action":"getEvolutionGraph","columns":"nb_visits"}},
+ {"uniqueId":"widgetVisitsSummarygetEvolutionGraphforceView1viewDataTablegraphEvolution","parameters":{"forceView":"1","viewDataTable":"graphEvolution","module":"VisitsSummary","action":"getEvolutionGraph"}},
{"uniqueId":"widgetLivewidget","parameters":{"module":"Live","action":"widget"}},
- {"uniqueId":"widgetVisitorInterestgetNumberOfVisitsPerVisitDuration","parameters":{"module":"VisitorInterest","action":"getNumberOfVisitsPerVisitDuration"}}
+ {"uniqueId":"widgetVisitorInterestgetNumberOfVisitsPerVisitDurationviewDataTablecloud","parameters":{"viewDataTable":"cloud","module":"VisitorInterest","action":"getNumberOfVisitsPerVisitDuration"}}
],
[
' . $topWidget . '
{"uniqueId":"widgetReferrersgetWebsites","parameters":{"module":"Referrers","action":"getWebsites"}},
- {"uniqueId":"widgetVisitTimegetVisitInformationPerServerTime","parameters":{"module":"VisitTime","action":"getVisitInformationPerServerTime"}}
+ {"uniqueId":"widgetVisitTimegetVisitInformationPerServerTimeviewDataTablegraphVerticalBar","parameters":{"viewDataTable": "graphVerticalBar","module":"VisitTime","action":"getVisitInformationPerServerTime"}}
],
[
{"uniqueId":"widgetUserCountryMapvisitorMap","parameters":{"module":"UserCountryMap","action":"visitorMap"}},
@@ -160,24 +194,6 @@ class Dashboard extends \Piwik\Plugin
);
}
- foreach ($layoutObject->columns as &$row) {
- if (!is_array($row)) {
- $row = array();
- continue;
- }
-
- foreach ($row as $widgetId => $widget) {
- if (isset($widget->parameters->module)) {
- $controllerName = $widget->parameters->module;
- $controllerAction = $widget->parameters->action;
- if (!WidgetsList::isDefined($controllerName, $controllerAction)) {
- unset($row[$widgetId]);
- }
- } else {
- unset($row[$widgetId]);
- }
- }
- }
$layout = $this->encodeLayout($layoutObject);
return $layout;
}
@@ -202,11 +218,13 @@ class Dashboard extends \Piwik\Plugin
public function getJsFiles(&$jsFiles)
{
+ $jsFiles[] = "plugins/Dashboard/angularjs/common/services/dashboards-model.js";
$jsFiles[] = "plugins/Dashboard/javascripts/widgetMenu.js";
$jsFiles[] = "libs/javascript/json2.js";
$jsFiles[] = "plugins/Dashboard/javascripts/dashboardObject.js";
$jsFiles[] = "plugins/Dashboard/javascripts/dashboardWidget.js";
$jsFiles[] = "plugins/Dashboard/javascripts/dashboard.js";
+ $jsFiles[] = "plugins/Dashboard/angularjs/dashboard/dashboard.directive.js";
}
public function getStylesheetFiles(&$stylesheets)
diff --git a/plugins/Dashboard/Menu.php b/plugins/Dashboard/Menu.php
index f90c117e10..7967635f97 100644
--- a/plugins/Dashboard/Menu.php
+++ b/plugins/Dashboard/Menu.php
@@ -9,7 +9,6 @@
namespace Piwik\Plugins\Dashboard;
use Piwik\Db;
-use Piwik\Menu\MenuReporting;
use Piwik\Menu\MenuTop;
use Piwik\Piwik;
use Piwik\Plugins\UsersManager\UserPreferences;
@@ -19,24 +18,6 @@ use Piwik\Site;
*/
class Menu extends \Piwik\Plugin\Menu
{
- public function configureReportingMenu(MenuReporting $menu)
- {
- $menu->addItem('Dashboard_Dashboard', '', $this->urlForAction('embeddedIndex', array('idDashboard' => 1)), 5);
-
- if (!Piwik::isUserIsAnonymous()) {
- $login = Piwik::getCurrentUserLogin();
-
- $dashboard = new Dashboard();
- $dashboards = $dashboard->getAllDashboards($login);
-
- $pos = 0;
- foreach ($dashboards as $dashboard) {
- $menu->addItem('Dashboard_Dashboard', $dashboard['name'], $this->urlForAction('embeddedIndex', array('idDashboard' => $dashboard['iddashboard'])), $pos);
- $pos++;
- }
- }
- }
-
public function configureTopMenu(MenuTop $menu)
{
$userPreferences = new UserPreferences();
diff --git a/plugins/Dashboard/Model.php b/plugins/Dashboard/Model.php
index 790076c1a9..0ef02aeea9 100644
--- a/plugins/Dashboard/Model.php
+++ b/plugins/Dashboard/Model.php
@@ -10,7 +10,7 @@ namespace Piwik\Plugins\Dashboard;
use Piwik\Common;
use Piwik\Db;
use Piwik\DbHelper;
-use Piwik\WidgetsList;
+use Piwik\Widget\WidgetsList;
class Model
{
@@ -189,7 +189,11 @@ class Model
if ($widget->uniqueId == $oldWidgetId) {
- $newWidgetId = WidgetsList::getWidgetUniqueId($newWidget['module'], $newWidget['action'], $newWidget['params']);
+ if (!empty($newWidget['uniqueId'])) {
+ $newWidgetId = $newWidget['uniqueId'];
+ } else {
+ $newWidgetId = WidgetsList::getWidgetUniqueId($newWidget['module'], $newWidget['action'], $newWidget['params']);
+ }
// is new widget already is on dashboard just remove the old one
if (self::layoutContainsWidget($dashboardLayout, $newWidgetId)) {
diff --git a/plugins/Dashboard/angularjs/common/services/dashboards-model.js b/plugins/Dashboard/angularjs/common/services/dashboards-model.js
new file mode 100644
index 0000000000..e0d861c2ba
--- /dev/null
+++ b/plugins/Dashboard/angularjs/common/services/dashboards-model.js
@@ -0,0 +1,68 @@
+/*!
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ */
+(function () {
+ angular.module('piwikApp.service').factory('dashboardsModel', dashboardsModel);
+
+ dashboardsModel.$inject = ['piwikApi'];
+
+ function dashboardsModel (piwikApi) {
+
+ var dashboardsPromise = null;
+
+ var model = {
+ dashboards: [],
+ getAllDashboards: getAllDashboards,
+ reloadAllDashboards: reloadAllDashboards,
+ getDashboard: getDashboard,
+ getDashboardLayout: getDashboardLayout
+ };
+
+ return model;
+
+ function getDashboard(dashboardId)
+ {
+ return getAllDashboards().then(function (dashboards) {
+ var dashboard = null;
+ angular.forEach(dashboards, function (board) {
+ if (parseInt(board.id, 10) === parseInt(dashboardId, 10)) {
+ dashboard = board;
+ }
+ });
+ return dashboard;
+ });
+ }
+
+ function getDashboardLayout(dashboardId)
+ {
+ return piwikApi.fetch({module: 'Dashboard', action: 'getDashboardLayout', idDashboard: dashboardId});
+ }
+
+ function reloadAllDashboards()
+ {
+ if (dashboardsPromise) {
+ dashboardsPromise = null;
+ }
+
+ return getAllDashboards();
+ }
+
+ function getAllDashboards()
+ {
+ if (!dashboardsPromise) {
+ dashboardsPromise = piwikApi.fetch({method: 'Dashboard.getDashboards'}).then(function (response) {
+ if (response) {
+ model.dashboards = response;
+ }
+
+ return response;
+ });
+ }
+
+ return dashboardsPromise;
+ }
+ }
+})(); \ No newline at end of file
diff --git a/plugins/Dashboard/angularjs/dashboard/dashboard.directive.js b/plugins/Dashboard/angularjs/dashboard/dashboard.directive.js
new file mode 100644
index 0000000000..578737940c
--- /dev/null
+++ b/plugins/Dashboard/angularjs/dashboard/dashboard.directive.js
@@ -0,0 +1,103 @@
+/*!
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ */
+
+/**
+ * <div piwik-dashboard dashboardId="5" layout="10"></div>
+ */
+(function () {
+ angular.module('piwikApp').directive('piwikDashboard', piwikDashboard);
+
+ piwikDashboard.$inject = ['dashboardsModel', '$rootScope', '$q'];
+
+ function piwikDashboard(dashboardsModel, $rootScope, $q) {
+
+ function renderDashboard(dashboardId, dashboard, layout)
+ {
+ $('.dashboardSettings').show();
+ initTopControls();
+
+ // Embed dashboard
+ if (!$('#topBars').length) {
+ $('.dashboardSettings').after($('#Dashboard'));
+ $('#Dashboard_embeddedIndex_' + dashboardId).addClass('sfHover');
+ }
+
+ widgetsHelper.getAvailableWidgets();
+
+ $('#dashboardWidgetsArea')
+ .on('dashboardempty', showEmptyDashboardNotification)
+ .dashboard({
+ idDashboard: dashboardId,
+ layout: layout,
+ name: dashboard ? dashboard.name : ''
+ });
+
+ $('#columnPreview').find('>div').each(function () {
+ var width = [];
+ $('div', this).each(function () {
+ width.push(this.className.replace(/width-/, ''));
+ });
+ $(this).attr('layout', width.join('-'));
+ });
+
+ $('#columnPreview').find('>div').on('click', function () {
+ $('#columnPreview').find('>div').removeClass('choosen');
+ $(this).addClass('choosen');
+ });
+ }
+
+ function fetchDashboard(dashboardId) {
+ $('#dashboardWidgetsArea').innerHTML ='';
+
+ var getDashboard = dashboardsModel.getDashboard(dashboardId);
+ var getLayout = dashboardsModel.getDashboardLayout(dashboardId);
+
+ $q.all([getDashboard, getLayout]).then(function (response) {
+ var dashboard = response[0];
+ var layout = response[1];
+
+ $(function() {
+ renderDashboard(dashboardId, dashboard, layout);
+ });
+ });
+ }
+
+ function clearDashboard () {
+ $('.top_controls .dashboard-manager').hide();
+ $('#dashboardWidgetsArea').dashboard('destroy');
+ }
+
+ return {
+ restrict: 'A',
+ scope: {
+ dashboardid: '=',
+ layout: '='
+ },
+ link: function (scope, element, attrs) {
+
+ scope.$parent.fetchDashboard = function (dashboardId) {
+ scope.dashboardId = dashboardId;
+ fetchDashboard(dashboardId)
+ };
+
+ fetchDashboard(scope.dashboardid);
+
+ function onLocationChange(event, url1, url2)
+ {
+ if (url1 !== url2) {
+ clearDashboard();
+ }
+ }
+
+ // should be rather handled in route or so.
+ var unbind = $rootScope.$on('$locationChangeSuccess', onLocationChange);
+ scope.$on('$destroy', onLocationChange);
+ scope.$on('$destroy', unbind);
+ }
+ };
+ }
+})(); \ No newline at end of file
diff --git a/plugins/Dashboard/javascripts/dashboard.js b/plugins/Dashboard/javascripts/dashboard.js
index 238aca5197..f78814cdbb 100644
--- a/plugins/Dashboard/javascripts/dashboard.js
+++ b/plugins/Dashboard/javascripts/dashboard.js
@@ -5,45 +5,12 @@
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
*/
-function initDashboard(dashboardId, dashboardLayout) {
-
- $('.dashboardSettings').show();
- initTopControls();
-
- // Embed dashboard
- if (!$('#topBars').length) {
- $('.dashboardSettings').after($('#Dashboard'));
- $('#Dashboard_embeddedIndex_' + dashboardId).addClass('sfHover');
- }
-
- widgetsHelper.getAvailableWidgets();
-
- $('#dashboardWidgetsArea')
- .on('dashboardempty', showEmptyDashboardNotification)
- .dashboard({
- idDashboard: dashboardId,
- layout: dashboardLayout
- });
-
- $('#columnPreview').find('>div').each(function () {
- var width = [];
- $('div', this).each(function () {
- width.push(this.className.replace(/width-/, ''));
- });
- $(this).attr('layout', width.join('-'));
- });
-
- $('#columnPreview').find('>div').on('click', function () {
- $('#columnPreview').find('>div').removeClass('choosen');
- $(this).addClass('choosen');
- });
-}
-
function createDashboard() {
- $('#createDashboardName').val('');
- piwikHelper.modalConfirm('#createDashboardConfirm', {yes: function () {
- var dashboardName = $('#createDashboardName').val();
- var type = ($('#dashboard_type_empty:checked').length > 0) ? 'empty' : 'default';
+ $(makeSelectorLastId('createDashboardName')).val('');
+
+ piwikHelper.modalConfirm(makeSelectorLastId('createDashboardConfirm'), {yes: function () {
+ var dashboardName = $(makeSelectorLastId('createDashboardName')).val();
+ var type = ($('[id=dashboard_type_empty]:last:checked').length > 0) ? 'empty' : 'default';
var ajaxRequest = new ajaxHelper();
ajaxRequest.setLoadingElement();
@@ -57,50 +24,74 @@ function createDashboard() {
}, 'post');
ajaxRequest.setCallback(
function (id) {
- $('#dashboardWidgetsArea').dashboard('loadDashboard', id);
+ angular.element(document).injector().invoke(function ($location, reportingMenuModel, dashboardsModel) {
+ dashboardsModel.reloadAllDashboards().then(function () {
+ $('#dashboardWidgetsArea').dashboard('loadDashboard', id);
+ $('#dashboardWidgetsArea').dashboard('rebuildMenu');
+ });
+ });
}
);
ajaxRequest.send(true);
}});
}
+function makeSelectorLastId(domElementId)
+{
+ // there can be many elements with this id, we prefer the last one
+ return '[id=' + domElementId + ']:last';
+}
+
function resetDashboard() {
- piwikHelper.modalConfirm('#resetDashboardConfirm', {yes: function () { $('#dashboardWidgetsArea').dashboard('resetLayout'); }});
+ piwikHelper.modalConfirm(makeSelectorLastId('resetDashboardConfirm'), {yes:
+ function () { $('#dashboardWidgetsArea').dashboard('resetLayout');
+ }});
}
function renameDashboard() {
- $('#newDashboardName').val($('#dashboardWidgetsArea').dashboard('getDashboardName'));
- piwikHelper.modalConfirm('#renameDashboardConfirm', {yes: function () { $('#dashboardWidgetsArea').dashboard('setDashboardName', $('#newDashboardName').val()); }});
+ $(makeSelectorLastId('newDashboardName')).val($('#dashboardWidgetsArea').dashboard('getDashboardName'));
+
+ piwikHelper.modalConfirm(makeSelectorLastId('renameDashboardConfirm'), {yes: function () {
+ var newDashboardName = $(makeSelectorLastId('newDashboardName')).val();
+ $('#dashboardWidgetsArea').dashboard('setDashboardName', newDashboardName);
+ }});
}
function removeDashboard() {
- $('#removeDashboardConfirm').find('h2 span').text($('#dashboardWidgetsArea').dashboard('getDashboardName'));
- piwikHelper.modalConfirm('#removeDashboardConfirm', {yes: function () { $('#dashboardWidgetsArea').dashboard('removeDashboard'); }});
+ $(makeSelectorLastId('removeDashboardConfirm')).find('h2 span').text($('#dashboardWidgetsArea').dashboard('getDashboardName'));
+
+ piwikHelper.modalConfirm(makeSelectorLastId('removeDashboardConfirm'), {yes: function () {
+ $('#dashboardWidgetsArea').dashboard('removeDashboard');
+ }});
}
function showChangeDashboardLayoutDialog() {
$('#columnPreview').find('>div').removeClass('choosen');
$('#columnPreview').find('>div[layout=' + $('#dashboardWidgetsArea').dashboard('getColumnLayout') + ']').addClass('choosen');
- piwikHelper.modalConfirm('#changeDashboardLayout', {yes: function () {
- $('#dashboardWidgetsArea').dashboard('setColumnLayout', $('#changeDashboardLayout').find('.choosen').attr('layout'));
+
+ var id = makeSelectorLastId('changeDashboardLayout');
+ piwikHelper.modalConfirm(id, {yes: function () {
+ $('#dashboardWidgetsArea').dashboard('setColumnLayout', $(id).find('.choosen').attr('layout'));
}});
}
function showEmptyDashboardNotification() {
- piwikHelper.modalConfirm('#dashboardEmptyNotification', {
+ piwikHelper.modalConfirm(makeSelectorLastId('dashboardEmptyNotification'), {
resetDashboard: function () { $('#dashboardWidgetsArea').dashboard('resetLayout'); },
addWidget: function () { $('.dashboardSettings').trigger('click'); }
});
}
function setAsDefaultWidgets() {
- piwikHelper.modalConfirm('#setAsDefaultWidgetsConfirm', {
- yes: function () { $('#dashboardWidgetsArea').dashboard('saveLayoutAsDefaultWidgetLayout'); }
+ piwikHelper.modalConfirm(makeSelectorLastId('setAsDefaultWidgetsConfirm'), {
+ yes: function () {
+ $('#dashboardWidgetsArea').dashboard('saveLayoutAsDefaultWidgetLayout');
+ }
});
}
function copyDashboardToUser() {
- $('#copyDashboardName').val($('#dashboardWidgetsArea').dashboard('getDashboardName'));
+ $(makeSelectorLastId('copyDashboardName')).val($('#dashboardWidgetsArea').dashboard('getDashboardName'));
var ajaxRequest = new ajaxHelper();
ajaxRequest.addParams({
module: 'API',
@@ -109,13 +100,13 @@ function copyDashboardToUser() {
}, 'get');
ajaxRequest.setCallback(
function (availableUsers) {
- $('#copyDashboardUser').empty();
- $('#copyDashboardUser').append(
+ $(makeSelectorLastId('copyDashboardUser')).empty();
+ $(makeSelectorLastId('copyDashboardUser')).append(
$('<option></option>').val(piwik.userLogin).text(piwik.userLogin)
);
$.each(availableUsers, function (index, user) {
if (user.login != 'anonymous' && user.login != piwik.userLogin) {
- $('#copyDashboardUser').append(
+ $(makeSelectorLastId('copyDashboardUser')).append(
$('<option></option>').val(user.login).text(user.login + ' (' + user.alias + ')')
);
}
@@ -124,10 +115,10 @@ function copyDashboardToUser() {
);
ajaxRequest.send(true);
- piwikHelper.modalConfirm('#copyDashboardToUserConfirm', {
+ piwikHelper.modalConfirm(makeSelectorLastId('copyDashboardToUserConfirm'), {
yes: function () {
- var copyDashboardName = $('#copyDashboardName').val();
- var copyDashboardUser = $('#copyDashboardUser').val();
+ var copyDashboardName = $(makeSelectorLastId('copyDashboardName')).val();
+ var copyDashboardUser = $(makeSelectorLastId('copyDashboardUser')).val();
var ajaxRequest = new ajaxHelper();
ajaxRequest.addParams({
@@ -291,7 +282,7 @@ function copyDashboardToUser() {
},
isWidgetAvailable: function (widgetUniqueId) {
- return !$('#dashboardWidgetsArea').find('[widgetId=' + widgetUniqueId + ']').length;
+ return !$('#dashboardWidgetsArea').find('[widgetId="' + widgetUniqueId + '"]').length;
},
widgetSelected: function (widget) {
@@ -301,6 +292,7 @@ function copyDashboardToUser() {
DashboardManagerControl.initElements = function () {
UIControl.initElements(this, '.dashboard-manager');
+ $('.top_controls .dashboard-manager').hide(); // initially hide the manager
};
exports.DashboardManagerControl = DashboardManagerControl;
diff --git a/plugins/Dashboard/javascripts/dashboardObject.js b/plugins/Dashboard/javascripts/dashboardObject.js
index 7808d22c11..08bb36dd79 100644
--- a/plugins/Dashboard/javascripts/dashboardObject.js
+++ b/plugins/Dashboard/javascripts/dashboardObject.js
@@ -57,9 +57,6 @@
if (options.layout) {
generateLayout(options.layout);
- buildMenu();
- } else {
- methods.loadDashboard.apply(this, [dashboardId]);
}
return this;
@@ -89,11 +86,11 @@
dashboardName = '';
dashboardLayout = null;
dashboardId = dashboardIdToLoad;
- piwikHelper.showAjaxLoading();
- broadcast.updateHashOnly = true;
- broadcast.propagateAjax('?idDashboard=' + dashboardIdToLoad);
- fetchLayout(generateLayout);
- buildMenu();
+
+ var element = $('[piwik-dashboard]');
+ var scope = angular.element(element).scope();
+ scope.fetchDashboard(dashboardIdToLoad);
+
return this;
},
@@ -179,6 +176,8 @@
ajaxRequest.send(true);
},
+ rebuildMenu: rebuildMenu,
+
/**
* Removes the current dashboard
*/
@@ -201,6 +200,39 @@
}
};
+ function removeNonExistingWidgets(availableWidgets, layout)
+ {
+ var existingModuleAction = {};
+ $.each(availableWidgets, function (category, widgets) {
+ $.each(widgets, function (index, widget) {
+ existingModuleAction[widget.module + '.' + widget.action] = true;
+ });
+ });
+
+ var columns = [];
+ $.each(layout.columns, function (i, column) {
+ var widgets = [];
+
+ $.each(column, function (j, widget) {
+ if (!widget.parameters || !widget.parameters.module) {
+ return;
+ }
+
+ var method = widget.parameters.module + '.' + widget.parameters.action
+ if (existingModuleAction[method]) {
+ widgets.push(widget);
+ }
+
+ });
+
+ columns[i] = widgets;
+ });
+
+ layout.columns = columns;
+
+ return layout;
+ }
+
/**
* Generates the dashboard out of the given layout
*
@@ -209,46 +241,33 @@
function generateLayout(layout) {
dashboardLayout = parseLayout(layout);
- piwikHelper.hideAjaxLoading();
- adjustDashboardColumns(dashboardLayout.config.layout);
-
- var dashboardContainsWidgets = false;
- for (var column = 0; column < dashboardLayout.columns.length; column++) {
- for (var i in dashboardLayout.columns[column]) {
- if (typeof dashboardLayout.columns[column][i] != 'object') {
- // Fix IE8 bug: the "i in" loop contains i="indexOf", which would yield type function.
- // If we would continue with i="indexOf", an invalid widget would be created.
- continue;
+
+ widgetsHelper.getAvailableWidgets(function (availableWidgets) {
+ dashboardLayout = removeNonExistingWidgets(availableWidgets, dashboardLayout);
+
+ piwikHelper.hideAjaxLoading();
+ adjustDashboardColumns(dashboardLayout.config.layout);
+
+ var dashboardContainsWidgets = false;
+ for (var column = 0; column < dashboardLayout.columns.length; column++) {
+ for (var i in dashboardLayout.columns[column]) {
+ if (typeof dashboardLayout.columns[column][i] != 'object') {
+ // Fix IE8 bug: the "i in" loop contains i="indexOf", which would yield type function.
+ // If we would continue with i="indexOf", an invalid widget would be created.
+ continue;
+ }
+ var widget = dashboardLayout.columns[column][i];
+ dashboardContainsWidgets = true;
+ addWidgetTemplate(widget.uniqueId, column + 1, widget.parameters, false, widget.isHidden)
}
- var widget = dashboardLayout.columns[column][i];
- dashboardContainsWidgets = true;
- addWidgetTemplate(widget.uniqueId, column + 1, widget.parameters, false, widget.isHidden)
}
- }
-
- if (!dashboardContainsWidgets) {
- $(dashboardElement).trigger('dashboardempty');
- }
- makeWidgetsSortable();
- }
+ if (!dashboardContainsWidgets) {
+ $(dashboardElement).trigger('dashboardempty');
+ }
- /**
- * Fetches the layout for the currently set dashboard id
- * and passes the response to given callback function
- *
- * @param {function} callback
- */
- function fetchLayout(callback) {
- globalAjaxQueue.abort();
- var ajaxRequest = new ajaxHelper();
- ajaxRequest.addParams({
- module: 'Dashboard',
- action: 'getDashboardLayout',
- idDashboard: dashboardId
- }, 'get');
- ajaxRequest.setCallback(callback);
- ajaxRequest.send(false);
+ makeWidgetsSortable();
+ });
}
/**
@@ -388,7 +407,7 @@
* @param {String} uniqueId
*/
function reloadWidget(uniqueId) {
- $('[widgetId=' + uniqueId + ']', dashboardElement).dashboardWidget('reload', false, true);
+ $('[widgetId="' + uniqueId + '"]', dashboardElement).dashboardWidget('reload', false, true);
}
/**
@@ -417,7 +436,7 @@
$('.col:nth-child(' + columnNumber + ')', dashboardElement).append(widgetContent);
}
- $('[widgetId=' + uniqueId + ']', dashboardElement).dashboardWidget({
+ $('[widgetId="' + uniqueId + '"]', dashboardElement).dashboardWidget({
uniqueId: uniqueId,
widgetParameters: widgetParameters,
onChange: function () {
@@ -468,7 +487,19 @@
/**
* Handle clicks for menu items for choosing between available dashboards
*/
- function buildMenu() {
+ function rebuildMenu() {
+
+ if ($('[piwik-reporting-menu]').length) {
+ // dashboard in reporting page (regular Piwik UI)
+ angular.element(document).injector().invoke(function (reportingMenuModel) {
+ reportingMenuModel.reloadMenuItems();
+ });
+ return;
+ }
+
+ var _self = this;
+
+ // widgetized
var success = function (dashboards) {
var dashboardMenuList = $('#Dashboard').find('> ul');
var dashboardMenuListItems = dashboardMenuList.find('>li');
@@ -484,7 +515,7 @@
for (var i = 0; i < dashboards.length; i++) {
var $link = $('<a/>').attr('data-idDashboard', dashboards[i].iddashboard).text(dashboards[i].name);
var $li = $('<li/>').attr('id', 'Dashboard_embeddedIndex_' + dashboards[i].iddashboard)
- .addClass('dashboardMenuItem').append($link);
+ .addClass('dashboardMenuItem').append($link);
items.push($li);
if (dashboards[i].iddashboard == dashboardId) {
@@ -502,15 +533,10 @@
var idDashboard = $(this).attr('data-idDashboard');
- if (typeof piwikMenu != 'undefined') {
- piwikMenu.activateMenu('Dashboard', 'embeddedIndex');
- }
$('#Dashboard ul li').removeClass('sfHover');
- if ($(dashboardElement).length) {
- $(dashboardElement).dashboard('loadDashboard', idDashboard);
- } else {
- broadcast.propagateAjax('module=Dashboard&action=embeddedIndex&idDashboard=' + idDashboard);
- }
+
+ methods.loadDashboard.apply(_self, [idDashboard]);
+
$(this).closest('li').addClass('sfHover');
});
};
@@ -521,7 +547,7 @@
action: 'getAllDashboards'
}, 'get');
ajaxRequest.setCallback(success);
- ajaxRequest.send(false);
+ ajaxRequest.send();
}
/**
@@ -568,7 +594,7 @@
function () {
if (dashboardChanged) {
dashboardChanged = false;
- buildMenu();
+ rebuildMenu();
}
}
);
@@ -594,6 +620,7 @@
}, 'get');
ajaxRequest.setCallback(
function () {
+ rebuildMenu();
methods.loadDashboard.apply(this, [1]);
}
);
diff --git a/plugins/Dashboard/javascripts/dashboardWidget.js b/plugins/Dashboard/javascripts/dashboardWidget.js
index accd0aa2c2..969ed9db28 100755
--- a/plugins/Dashboard/javascripts/dashboardWidget.js
+++ b/plugins/Dashboard/javascripts/dashboardWidget.js
@@ -70,7 +70,7 @@
*/
destroy: function () {
if (this.isMaximised) {
- $('[widgetId=' + this.uniqueId + ']').dialog('destroy');
+ $('[widgetId="' + this.uniqueId + '"]').dialog('destroy');
}
$('*', this.element).off('.dashboardWidget'); // unbind all events
$('.widgetContent', this.element).trigger('widget:destroy');
@@ -197,7 +197,7 @@
var emptyWidgetContent = require('piwik/UI/Dashboard').WidgetFactory.make(uniqueId, title);
this.element.html(emptyWidgetContent);
- var widgetElement = $('#' + uniqueId, this.element);
+ var widgetElement = $('[id="' + uniqueId + '"]', this.element);
var self = this;
widgetElement
.on('mouseenter.dashboardWidget', function () {
@@ -312,7 +312,7 @@
}
$('body').off('.dashboardWidget');
$(this).dialog("destroy");
- $('#' + self.uniqueId + '-placeholder').replaceWith(this);
+ $('[id="' + self.uniqueId + '-placeholder"]').replaceWith(this);
$(this).removeAttr('style');
self.options.onChange();
$(this).find('div.piwik-graph').trigger('resizeGraph');
@@ -339,6 +339,9 @@
*/
detachWidget: function () {
this.element.before('<div id="' + this.uniqueId + '-placeholder" class="widgetPlaceholder widget"> </div>');
+ var placeholder = $('[id="' + self.uniqueId + '-placeholder"]')
+
+
$('#' + this.uniqueId + '-placeholder').height(this.element.height());
$('#' + this.uniqueId + '-placeholder').width(this.element.width() - 16);
diff --git a/plugins/Dashboard/javascripts/widgetMenu.js b/plugins/Dashboard/javascripts/widgetMenu.js
index 6d58415cb9..169768eb03 100644
--- a/plugins/Dashboard/javascripts/widgetMenu.js
+++ b/plugins/Dashboard/javascripts/widgetMenu.js
@@ -13,21 +13,82 @@ function widgetsHelper() {
*
* @return {object} object containing available widgets
*/
-widgetsHelper.getAvailableWidgets = function () {
+widgetsHelper.getAvailableWidgets = function (callback) {
+
+ function mergeCategoriesAndSubCategories(availableWidgets)
+ {
+ var categorized = {};
+
+ $.each(availableWidgets, function (index, widget) {
+ var category = widget.category.name;
+
+ if (!categorized[category]) {
+ categorized[category] = {'-': []};
+ }
+
+ var subcategory = '-';
+ if (widget.subcategory && widget.subcategory.name) {
+ subcategory = widget.subcategory.name;
+ }
+
+ if (!categorized[category][subcategory]) {
+ categorized[category][subcategory] = [];
+ }
+
+ categorized[category][subcategory].push(widget);
+ });
+
+ var moved = {};
+
+ $.each(categorized, function (category, widgets) {
+ $.each(widgets, function (subcategory, subwidgets) {
+
+ var categoryToUse = category;
+ if (subwidgets.length >= 3 && subcategory !== '-') {
+ categoryToUse = category + ' - ' + subcategory;
+ }
+
+ if (!moved[categoryToUse]) {
+ moved[categoryToUse] = [];
+ }
+
+ $.each(subwidgets, function (index, widget) {
+ moved[categoryToUse].push(widget);
+ });
+ });
+ });
+
+ return moved;
+ }
+
if (!widgetsHelper.availableWidgets) {
var ajaxRequest = new ajaxHelper();
+ ajaxRequest._mixinDefaultGetParams = function (params) {
+ return params;
+ };
ajaxRequest.addParams({
- module: 'Dashboard',
- action: 'getAvailableWidgets'
+ module: 'API',
+ method: 'API.getWidgetMetadata',
+ format: 'JSON',
+ deep: '1',
+ idSite: piwik.idSite || broadcast.getValueFromUrl('idSite')
}, 'get');
ajaxRequest.setCallback(
function (data) {
- widgetsHelper.availableWidgets = data;
+ widgetsHelper.availableWidgets = mergeCategoriesAndSubCategories(data);
+
+ if (callback) {
+ callback(widgetsHelper.availableWidgets);
+ }
}
);
ajaxRequest.send(true);
}
+ if (callback) {
+ callback(widgetsHelper.availableWidgets);
+ }
+
return widgetsHelper.availableWidgets;
};
@@ -191,6 +252,7 @@ widgetsHelper.loadWidgetAjax = function (widgetUniqueId, widgetParameters, onWid
* @return {$} category list element
*/
function createWidgetCategoryList(widgetPreview, availableWidgets) {
+
var settings = widgetPreview.settings;
if (!$('.' + settings.categorylistClass, widgetPreview).length) {
@@ -200,7 +262,6 @@ widgetsHelper.loadWidgetAjax = function (widgetUniqueId, widgetParameters, onWid
}
for (var widgetCategory in availableWidgets) {
-
$('.' + settings.categorylistClass, widgetPreview).append('<li>' + widgetCategory + '</li>');
}
@@ -257,6 +318,8 @@ widgetsHelper.loadWidgetAjax = function (widgetUniqueId, widgetParameters, onWid
widgetClass += ' ' + settings.unavailableClass;
}
+ widgetName = piwikHelper.escape(piwikHelper.htmlEntities(widgetName));
+
widgetList.append('<li class="' + widgetClass + '" uniqueid="' + widgetUniqueId + '">' + widgetName + '</li>');
}
@@ -278,7 +341,7 @@ widgetsHelper.loadWidgetAjax = function (widgetUniqueId, widgetParameters, onWid
clearTimeout(widgetPreview);
});
- $('li:not(.' + settings.unavailableClass + ')', widgetList).on('click', function () {
+ $('li', widgetList).on('click', function () {
if (!$('.widgetLoading', widgetPreview).length) {
settings.onSelect($(this).attr('uniqueid'));
if (settings.resetOnSelect) {
@@ -317,7 +380,7 @@ widgetsHelper.loadWidgetAjax = function (widgetUniqueId, widgetParameters, onWid
*/
function showPreview(widgetUniqueId, widgetPreview) {
// do not reload id widget already displayed
- if ($('#' + widgetUniqueId, widgetPreview).length) return;
+ if ($('[id="' + widgetUniqueId + '"]', widgetPreview).length) return;
var settings = widgetPreview.settings;
@@ -335,7 +398,8 @@ widgetsHelper.loadWidgetAjax = function (widgetUniqueId, widgetParameters, onWid
previewElement.html(emptyWidgetHtml);
var onWidgetLoadedCallback = function (response) {
- var widgetElement = $('#' + widgetUniqueId);
+ var widgetElement = $(document.getElementById(widgetUniqueId));
+ // document.getElementById needed for widgets with uniqueid like widgetOpens+Contact+Form
$('.widgetContent', widgetElement).html($(response));
$('.widgetContent', widgetElement).trigger('widget:create');
settings.onPreviewLoaded(widgetUniqueId, widgetElement);
@@ -398,19 +462,21 @@ widgetsHelper.loadWidgetAjax = function (widgetUniqueId, widgetParameters, onWid
this.onPreviewLoaded = this.settings.onPreviewLoaded;
}
- availableWidgets = widgetsHelper.getAvailableWidgets();
+ var self = this;
+ widgetsHelper.getAvailableWidgets(function (availableWidgets) {
- var categoryList = createWidgetCategoryList(this, availableWidgets);
+ var categoryList = createWidgetCategoryList(self, availableWidgets);
- var self = this;
- $('li', categoryList).on('mouseover', function () {
- var category = $(this).text();
- var widgets = availableWidgets[category];
- $('li', categoryList).removeClass(self.settings.choosenClass);
- $(this).addClass(self.settings.choosenClass);
- showWidgetList(widgets, self);
- createPreviewElement(self); // empty preview
+ $('li', categoryList).on('mouseover', function () {
+ var category = $(this).text();
+ var widgets = availableWidgets[category];
+ $('li', categoryList).removeClass(self.settings.choosenClass);
+ $(this).addClass(self.settings.choosenClass);
+ showWidgetList(widgets, self);
+ createPreviewElement(self); // empty preview
+ });
});
+
};
}
});
diff --git a/plugins/Dashboard/templates/embeddedIndex.twig b/plugins/Dashboard/templates/embeddedIndex.twig
index af1dbeb887..a7633ca193 100644
--- a/plugins/Dashboard/templates/embeddedIndex.twig
+++ b/plugins/Dashboard/templates/embeddedIndex.twig
@@ -1,10 +1,4 @@
-<script type="text/javascript">
- widgetsHelper.availableWidgets = {{ availableWidgets|raw }};
- $(function() {
- initDashboard({{ dashboardId }}, {{ dashboardLayout|raw }});
- });
-</script>
-<div id="dashboard">
+<div id="dashboard" piwik-dashboard dashboardid="{{ dashboardId }}">
<div class="ui-confirm" id="confirm">
<h2>{{ 'Dashboard_DeleteWidgetConfirm'|translate }}</h2>
<input role="yes" type="button" value="{{ 'General_Yes'|translate }}"/>