From 84e231884ef3a974ceecd0378f477c04ecd71ff5 Mon Sep 17 00:00:00 2001
From: Thomas Steur <thomas.steur@googlemail.com>
Date: Thu, 20 Mar 2014 06:19:17 +0100
Subject: [PATCH] worked on the possibility to leave feedback easier and to
 place help urls / inline help

---
 lang/en.json                                  |   7 +-
 .../Actions/templates/indexSiteSearch.twig    |   8 +-
 plugins/CoreHome/CoreHome.php                 |   7 ++
 .../angularjs/common/directives/dialog.js     |  41 ++++++++++
 .../enrichedheadline-directive.js             |  64 +++++++++++++++
 .../enrichedheadline/enrichedheadline.html    |  29 +++++++
 .../enrichedheadline/enrichedheadline.less    |  42 ++++++++++
 .../angularjs/enrichedheadline/help.png       | Bin 0 -> 342 bytes
 .../siteselector/siteselector-model.js        |   6 ++
 plugins/CoreHome/javascripts/broadcast.js     |   2 +
 plugins/CoreHome/javascripts/dataTable.js     |   8 ++
 plugins/CoreHome/templates/_singleReport.twig |   2 +-
 .../templates/browsePlugins.twig              |   4 +-
 .../templates/browseThemes.twig               |   4 +-
 .../CorePluginsAdmin/templates/extend.twig    |   4 +-
 .../CorePluginsAdmin/templates/plugins.twig   |   2 +-
 .../CorePluginsAdmin/templates/themes.twig    |   2 +-
 plugins/CustomAlerts                          |   2 +-
 plugins/DevicesDetection/templates/index.twig |  10 +--
 plugins/Feedback/API.php                      |  73 ++++++++++++++++++
 plugins/Feedback/Feedback.php                 |  12 +++
 .../angularjs/ratefeature/icon_license        |   7 ++
 .../ratefeature/ratefeature-controller.js     |  22 ++++++
 .../ratefeature/ratefeature-directive.js      |  22 ++++++
 .../ratefeature/ratefeature-model.js          |  22 ++++++
 .../angularjs/ratefeature/ratefeature.html    |  31 ++++++++
 .../angularjs/ratefeature/ratefeature.less    |  31 ++++++++
 .../angularjs/ratefeature/thumbs-down.png     | Bin 0 -> 2188 bytes
 .../angularjs/ratefeature/thumbs-up.png       | Bin 0 -> 2202 bytes
 plugins/Goals/templates/_addEditGoal.twig     |   4 +-
 .../templates/_titleAndEvolutionGraph.twig    |   2 +-
 .../templates/systemCheckPage.twig            |   2 +-
 plugins/MobileMessaging/templates/index.twig  |   4 +-
 .../angularjs/dashboard/dashboard.html        |   4 +-
 .../templates/privacySettings.twig            |   3 +-
 .../getSearchEnginesAndKeywords.twig          |   4 +-
 plugins/Referrers/templates/index.twig        |   9 ++-
 .../Referrers/templates/indexWebsites.twig    |   4 +-
 plugins/ScheduledReports/templates/index.twig |   3 +-
 plugins/SecurityInfo                          |   2 +-
 .../SegmentEditor/javascripts/Segmentation.js |   1 +
 .../templates/_segmentSelector.twig           |   3 +-
 plugins/SitesManager/templates/index.twig     |   2 +-
 plugins/TasksTimetable                        |   2 +-
 plugins/TreemapVisualization                  |   2 +-
 plugins/UserCountry/templates/adminIndex.twig |   4 +-
 plugins/UserCountry/templates/index.twig      |   8 +-
 plugins/UserSettings/templates/index.twig     |  16 ++--
 plugins/UsersManager/templates/index.twig     |   3 +-
 .../UsersManager/templates/userSettings.twig  |   3 +-
 plugins/VisitFrequency/templates/index.twig   |   2 +-
 plugins/VisitTime/templates/index.twig        |   4 +-
 plugins/VisitorGenerator                      |   2 +-
 plugins/VisitorInterest/templates/index.twig  |   8 +-
 plugins/VisitsSummary/templates/index.twig    |   4 +-
 plugins/Zeitgeist/javascripts/piwikHelper.js  |  15 ++++
 56 files changed, 521 insertions(+), 63 deletions(-)
 create mode 100644 plugins/CoreHome/angularjs/common/directives/dialog.js
 create mode 100644 plugins/CoreHome/angularjs/enrichedheadline/enrichedheadline-directive.js
 create mode 100644 plugins/CoreHome/angularjs/enrichedheadline/enrichedheadline.html
 create mode 100644 plugins/CoreHome/angularjs/enrichedheadline/enrichedheadline.less
 create mode 100644 plugins/CoreHome/angularjs/enrichedheadline/help.png
 create mode 100644 plugins/Feedback/API.php
 create mode 100644 plugins/Feedback/angularjs/ratefeature/icon_license
 create mode 100644 plugins/Feedback/angularjs/ratefeature/ratefeature-controller.js
 create mode 100644 plugins/Feedback/angularjs/ratefeature/ratefeature-directive.js
 create mode 100644 plugins/Feedback/angularjs/ratefeature/ratefeature-model.js
 create mode 100644 plugins/Feedback/angularjs/ratefeature/ratefeature.html
 create mode 100644 plugins/Feedback/angularjs/ratefeature/ratefeature.less
 create mode 100644 plugins/Feedback/angularjs/ratefeature/thumbs-down.png
 create mode 100644 plugins/Feedback/angularjs/ratefeature/thumbs-up.png

diff --git a/lang/en.json b/lang/en.json
index 6033abdc4e..4b3ff4324f 100644
--- a/lang/en.json
+++ b/lang/en.json
@@ -650,7 +650,8 @@
         "ReportGeneratedOn": "Report generated on %s",
         "ReportGeneratedXAgo": "Report generated %s ago",
         "MakeOneTimeDonation": "Make a one time donation, instead.",
-        "TableNoData": "No data for this table."
+        "TableNoData": "No data for this table.",
+        "ExternalHelp": "Help (opens in new tab)"
     },
     "PrivacyManager": {
         "TeaserHeadline": "Privacy Settings",
@@ -945,6 +946,10 @@
         "ManuallySendEmailTo": "Please manually send your message to",
         "MessageSent": "Your message was sent to the Piwik team.",
         "ThankYou": "Thank you for helping us to make Piwik better!",
+        "RateFeatureTitle": "Do you like the '%s' feature? Please rate and leave a comment",
+        "RateFeatureThankYouTitle": "Thank you for rating the '%s' feature!",
+        "RateFeatureLeaveMessageLike": "We are glad you like it! Please let us know what you like the most or if you miss a feature.",
+        "RateFeatureLeaveMessageDislike": "We are sorry to hear! Please let us know what you don't like or which feature you miss so we can improve.",
         "ThePiwikTeam": "The Piwik Team",
         "ExceptionBodyLength": "Message must be at least %s characters long.",
         "ExceptionNoUrls": "The message cannot contain a URL, to avoid spam messages.",
diff --git a/plugins/Actions/templates/indexSiteSearch.twig b/plugins/Actions/templates/indexSiteSearch.twig
index 2b9ea3afbc..7d6093c6ac 100644
--- a/plugins/Actions/templates/indexSiteSearch.twig
+++ b/plugins/Actions/templates/indexSiteSearch.twig
@@ -1,17 +1,17 @@
 <div id='leftcolumn'>
-    <h2>{{ 'Actions_WidgetSearchKeywords'|translate }}</h2>
+    <h2 piwik-enriched-headline>{{ 'Actions_WidgetSearchKeywords'|translate }}</h2>
     {{ keywords|raw }}
 
-    <h2>{{ 'Actions_WidgetSearchNoResultKeywords'|translate }}</h2>
+    <h2 piwik-enriched-headline>{{ 'Actions_WidgetSearchNoResultKeywords'|translate }}</h2>
     {{ noResultKeywords|raw }}
 
     {% if categories is defined %}
-        <h2>{{ 'Actions_WidgetSearchCategories'|translate }}</h2>
+        <h2 piwik-enriched-headline>{{ 'Actions_WidgetSearchCategories'|translate }}</h2>
         {{ categories|raw }}
     {% endif %}
 </div>
 
 <div id='rightcolumn'>
-    <h2>{{ 'Actions_WidgetPageUrlsFollowingSearch'|translate }}</h2>
+    <h2 piwik-enriched-headline>{{ 'Actions_WidgetPageUrlsFollowingSearch'|translate }}</h2>
     {{ pagesUrlsFollowingSiteSearch|raw }}
 </div>
diff --git a/plugins/CoreHome/CoreHome.php b/plugins/CoreHome/CoreHome.php
index 5e0fa821ef..e2fd3b3062 100644
--- a/plugins/CoreHome/CoreHome.php
+++ b/plugins/CoreHome/CoreHome.php
@@ -54,6 +54,7 @@ class CoreHome extends \Piwik\Plugin
         $stylesheets[] = "plugins/CoreHome/stylesheets/color_manager.css";
         $stylesheets[] = "plugins/CoreHome/stylesheets/sparklineColors.less";
         $stylesheets[] = "plugins/CoreHome/stylesheets/notification.less";
+        $stylesheets[] = "plugins/CoreHome/angularjs/enrichedheadline/enrichedheadline.less";
     }
 
     public function getJsFiles(&$jsFiles)
@@ -109,6 +110,7 @@ class CoreHome extends \Piwik\Plugin
         $jsFiles[] = "plugins/CoreHome/angularjs/common/directives/ignore-click.js";
         $jsFiles[] = "plugins/CoreHome/angularjs/common/directives/onenter.js";
         $jsFiles[] = "plugins/CoreHome/angularjs/common/directives/focusif.js";
+        $jsFiles[] = "plugins/CoreHome/angularjs/common/directives/dialog.js";
 
         $jsFiles[] = "plugins/CoreHome/angularjs/piwikApp.js";
         $jsFiles[] = "plugins/CoreHome/angularjs/anchorLinkFix.js";
@@ -116,6 +118,8 @@ class CoreHome extends \Piwik\Plugin
         $jsFiles[] = "plugins/CoreHome/angularjs/siteselector/siteselector-model.js";
         $jsFiles[] = "plugins/CoreHome/angularjs/siteselector/siteselector-controller.js";
         $jsFiles[] = "plugins/CoreHome/angularjs/siteselector/siteselector-directive.js";
+
+        $jsFiles[] = "plugins/CoreHome/angularjs/enrichedheadline/enrichedheadline-directive.js";
     }
 
     public function getClientSideTranslationKeys(&$translationKeys)
@@ -135,6 +139,7 @@ class CoreHome extends \Piwik\Plugin
         $translationKeys[] = 'CoreHome_PageOf';
         $translationKeys[] = 'CoreHome_FlattenDataTable';
         $translationKeys[] = 'CoreHome_UnFlattenDataTable';
+        $translationKeys[] = 'CoreHome_ExternalHelp';
         $translationKeys[] = 'SitesManager_NotFound';
         $translationKeys[] = 'Annotations_ViewAndAddAnnotations';
         $translationKeys[] = 'General_RowEvolutionRowActionTooltipTitle';
@@ -190,5 +195,7 @@ class CoreHome extends \Piwik\Plugin
         $translationKeys[] = 'General_DaySa';
         $translationKeys[] = 'General_DaySu';
         $translationKeys[] = 'General_Search';
+        $translationKeys[] = 'General_MoreDetails';
+        $translationKeys[] = 'General_Help';
     }
 }
diff --git a/plugins/CoreHome/angularjs/common/directives/dialog.js b/plugins/CoreHome/angularjs/common/directives/dialog.js
new file mode 100644
index 0000000000..08d166a911
--- /dev/null
+++ b/plugins/CoreHome/angularjs/common/directives/dialog.js
@@ -0,0 +1,41 @@
+/*!
+ * Piwik - Web Analytics
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ */
+
+/**
+ * Usage:
+ * <div piwik-dialog="showDialog">...</div>
+ * Will show dialog once showDialog evaluates to true.
+ *
+ * <div piwik-dialog="showDialog" yes="executeMyFunction();">
+ * ... <input type="button" role="yes" value="button">
+ * </div>
+ * Will execute the "executeMyFunction" function in the current scope once the yes button is pressed.
+ */
+angular.module('piwikApp.directive').directive('piwikDialog', function(piwik) {
+
+    return {
+        restrict: 'A',
+        link: function(scope, element, attrs) {
+
+            element.css('display', 'none');
+
+            element.on( "dialogclose", function() {
+                scope.$eval(attrs.piwikDialog+'=false');
+            });
+
+            scope.$watch(attrs.piwikDialog, function(newValue, oldValue) {
+                if (newValue) {
+                    piwik.helper.modalConfirm(element, {yes: function() {
+                        if (attrs.yes) {
+                            scope.$eval(attrs.yes);
+                        }
+                    }});
+                }
+            });
+        }
+    }
+});
\ No newline at end of file
diff --git a/plugins/CoreHome/angularjs/enrichedheadline/enrichedheadline-directive.js b/plugins/CoreHome/angularjs/enrichedheadline/enrichedheadline-directive.js
new file mode 100644
index 0000000000..2444de9682
--- /dev/null
+++ b/plugins/CoreHome/angularjs/enrichedheadline/enrichedheadline-directive.js
@@ -0,0 +1,64 @@
+/*!
+ * Piwik - Web Analytics
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ */
+
+/**
+ * Usage:
+ *
+ * <h2 piwik-enriched-headline>All Websites Dashboard</h2>
+ * -> uses "All Websites Dashboard" as featurename
+ *
+ * <h2 piwik-enriched-headline feature-name="All Websites Dashboard">All Websites Dashboard (Total: 309 Visits)</h2>
+ * -> custom featurename
+ *
+ * <h2 piwik-enriched-headline help-url="http://piwik.org/guide">All Websites Dashboard</h2>
+ * -> shows help icon and links to external url
+ *
+ * <h2 piwik-enriched-headline>All Websites Dashboard
+ *     <div class="inlineHelp>My <strong>inline help</strong></div>
+ * </h2>
+ * -> shows help icon to display inline help on click. Note: You can combine inlinehelp and help-url
+ */
+angular.module('piwikApp').directive('piwikEnrichedHeadline', function($document, piwik, $filter){
+    var defaults = {
+        helpUrl: ''
+    };
+
+    return {
+        transclude: true,
+        restrict: 'A',
+        scope: {
+            helpUrl: '@',
+            featureName: '@'
+        },
+        templateUrl: 'plugins/CoreHome/angularjs/enrichedheadline/enrichedheadline.html?cb=' + piwik.cacheBuster,
+        compile: function (element, attrs) {
+
+            for (var index in defaults) {
+               if (!attrs[index]) { attrs[index] = defaults[index]; }
+            }
+
+            return function (scope, element, attrs) {
+
+                var helpNode = $('[ng-transclude] .inlineHelp', element);
+
+                if ((!helpNode || !helpNode.length) && element.next()) {
+                    // hack for reports :(
+                    helpNode = element.next().find('.reportDocumentation');
+                }
+
+                if (helpNode && helpNode.length) {
+                    scope.inlineHelp = helpNode.html();
+                    helpNode.remove();
+                }
+
+                if (!attrs.featureName) {
+                    attrs.featureName = $.trim(element.text());
+                }
+            }
+        }
+    }
+});
\ No newline at end of file
diff --git a/plugins/CoreHome/angularjs/enrichedheadline/enrichedheadline.html b/plugins/CoreHome/angularjs/enrichedheadline/enrichedheadline.html
new file mode 100644
index 0000000000..53f04ecac1
--- /dev/null
+++ b/plugins/CoreHome/angularjs/enrichedheadline/enrichedheadline.html
@@ -0,0 +1,29 @@
+<div class="enrichedHeadline"
+    ng-mouseenter="view.showIcons=true" ng-mouseleave="view.showIcons=false">
+    <span ng-transclude></span>
+
+    <span ng-show="view.showIcons">
+        <a ng-if="helpUrl && !inlineHelp"
+           target="_blank"
+           href="{{ helpUrl }}"
+           title="{{ 'CoreHome_ExternalHelp'|translate }}"
+           class="helpIcon"></a>
+
+        <a ng-if="inlineHelp"
+           title="{{ 'General_Help'|translate }}"
+           ng-click="view.showInlineHelp=!view.showInlineHelp"
+           class="helpIcon"></a>
+
+        <div class="ratingIcons"
+             piwik-rate-feature
+             title="{{ featureName }}"></div>
+    </span>
+
+    <div class="inlineHelp" ng-show="view.showIcons && view.showInlineHelp">
+        <div ng-bind-html="inlineHelp"></div>
+        <a ng-if="helpUrl"
+           target="_blank"
+           href="{{ helpUrl }}"
+           class="readMore">{{ 'General_MoreDetails'|translate }}</a>
+    </div>
+</div>
\ No newline at end of file
diff --git a/plugins/CoreHome/angularjs/enrichedheadline/enrichedheadline.less b/plugins/CoreHome/angularjs/enrichedheadline/enrichedheadline.less
new file mode 100644
index 0000000000..52fa7d0074
--- /dev/null
+++ b/plugins/CoreHome/angularjs/enrichedheadline/enrichedheadline.less
@@ -0,0 +1,42 @@
+.inlineHelp {
+  display: none;
+}
+
+.enrichedHeadline {
+  .inlineHelp {
+    display:block;
+    background: #F7F7F7;
+    font-size: 12px;
+    font-weight: normal;
+    border: 1px solid #E4E5E4;
+    margin: 10px 0 10px 0;
+    padding: 10px;
+    border-radius: 4px;
+    max-width: 500px;
+
+    .readMore {
+      margin-top: 10px;
+      display: inline-block;
+      font-weight: bold;
+    }
+  }
+
+  .ratingIcons {
+    display:inline-block;
+    vertical-align: bottom;
+  }
+
+  .helpIcon:hover {
+    opacity: 0.9;
+  }
+
+  .helpIcon {
+    cursor: pointer;
+    display:inline-block;
+    margin: 4px 0 0 4px;
+    width: 16px;
+    opacity: 0.3;
+    height: 16px;
+    background: url(plugins/CoreHome/angularjs/enrichedheadline/help.png) no-repeat;
+  }
+}
\ No newline at end of file
diff --git a/plugins/CoreHome/angularjs/enrichedheadline/help.png b/plugins/CoreHome/angularjs/enrichedheadline/help.png
new file mode 100644
index 0000000000000000000000000000000000000000..b18fa0aa61faec0fa0e67e4ccf02ce57e88031ef
GIT binary patch
literal 342
zcmV-c0jd6pP)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV0003UNkl<ZIE{VM
z!79X26vy$88Hp@xq`UxQ8axBBAs)cS&RWVFcm_KgWhG<7l!a$tiLx0BW=bh!Oo_$+
z&h&TvuV0<I|IYXKzvrHF%8E6MO&nnxLwH3y!S_`~9UXi}(ZLC3QsyPJ3XE~I0{csq
zP+lIq#y$>kALZJZ?wJR08Ug1R!6=3?j?0Lt2d^qVqvSdUaf_>PUW=GdR7+TubvdtH
zoM9?_e_<?QhOhz;|1|6ZlbFX{LB9Fl4_?Bpvv^K0&2o6(vcLMkJGL-akcYjJtmEAT
zFo}sou8RiQDCz~}H3GPiD8D~OvZaW(@C}E!DKNL>7OAI2JSA?+$0HUJ&r-p$tbwud
oBjhS6b6z#<$mZM(=UNf?0}-u-1?&~RMgRZ+07*qoM6N<$g8Ac<Qvd(}

literal 0
HcmV?d00001

diff --git a/plugins/CoreHome/angularjs/siteselector/siteselector-model.js b/plugins/CoreHome/angularjs/siteselector/siteselector-model.js
index d89d895c04..15db8e0770 100644
--- a/plugins/CoreHome/angularjs/siteselector/siteselector-model.js
+++ b/plugins/CoreHome/angularjs/siteselector/siteselector-model.js
@@ -1,3 +1,9 @@
+/*!
+ * Piwik - Web Analytics
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ */
 
 angular.module('piwikApp').factory('siteSelectorModel', function (piwikApi, $filter) {
 
diff --git a/plugins/CoreHome/javascripts/broadcast.js b/plugins/CoreHome/javascripts/broadcast.js
index 80fbf71e79..3e02f4f3e4 100644
--- a/plugins/CoreHome/javascripts/broadcast.js
+++ b/plugins/CoreHome/javascripts/broadcast.js
@@ -428,6 +428,8 @@ var broadcast = {
                 $(broadcast).trigger('locationChangeSuccess', {element: $('#content'), content: content});
                 piwikHelper.hideAjaxLoading();
                 broadcast.lastUrlRequested = null;
+
+                piwikHelper.compileAngularComponents('#content');
             }
 
             initTopControls();
diff --git a/plugins/CoreHome/javascripts/dataTable.js b/plugins/CoreHome/javascripts/dataTable.js
index 7bff4aad32..0c7cc5f104 100644
--- a/plugins/CoreHome/javascripts/dataTable.js
+++ b/plugins/CoreHome/javascripts/dataTable.js
@@ -1403,6 +1403,7 @@ $.extend(DataTable.prototype, UIControl.prototype, {
 
     // documentation for report
     handleReportDocumentation: function (domElem) {
+
         // don't display report documentation in dashboard
         if ($('#dashboard').size() > 0
             // or in Widgetize screen
@@ -1412,6 +1413,13 @@ $.extend(DataTable.prototype, UIControl.prototype, {
             ) {
             return;
         }
+
+        var prev = domElem.prev();
+        if (prev && prev.length && prev.attr('piwik-enriched-headline') === '') {
+            // help is covered by piwik-enriched-headline
+            return;
+        }
+
         domElem = $(domElem);
         var doc = domElem.find('.reportDocumentation');
 
diff --git a/plugins/CoreHome/templates/_singleReport.twig b/plugins/CoreHome/templates/_singleReport.twig
index f6ad622f21..6d6ab8a4e6 100644
--- a/plugins/CoreHome/templates/_singleReport.twig
+++ b/plugins/CoreHome/templates/_singleReport.twig
@@ -1,2 +1,2 @@
-<h2>{{ title }}</h2>
+<h2 piwik-enriched-headline>{{ title }}</h2>
 {{ report|raw }}
\ No newline at end of file
diff --git a/plugins/CorePluginsAdmin/templates/browsePlugins.twig b/plugins/CorePluginsAdmin/templates/browsePlugins.twig
index 2f543ed15d..63845bf73d 100644
--- a/plugins/CorePluginsAdmin/templates/browsePlugins.twig
+++ b/plugins/CorePluginsAdmin/templates/browsePlugins.twig
@@ -5,7 +5,9 @@
 
     <div class="pluginslistActionBar">
 
-        <h2>{{ 'CorePluginsAdmin_TeaserExtendPiwikByPlugin'|translate }}</h2>
+        <h2 piwik-enriched-headline
+            feature-name="{{ 'CorePluginsAdmin_Marketplace'|translate }}"
+            >{{ 'CorePluginsAdmin_TeaserExtendPiwikByPlugin'|translate }}</h2>
 
         <div class="infoBox">
             {{ 'CorePluginsAdmin_BeCarefulUsingPlugins'|translate }}
diff --git a/plugins/CorePluginsAdmin/templates/browseThemes.twig b/plugins/CorePluginsAdmin/templates/browseThemes.twig
index a445467a11..2f834247a0 100644
--- a/plugins/CorePluginsAdmin/templates/browseThemes.twig
+++ b/plugins/CorePluginsAdmin/templates/browseThemes.twig
@@ -4,7 +4,9 @@
 
     <div class="pluginslistActionBar">
 
-        <h2>{{ 'CorePluginsAdmin_TeaserExtendPiwikByTheme'|translate }}</h2>
+        <h2 piwik-enriched-headline
+            feature-name="{{ 'CorePluginsAdmin_Marketplace'|translate }}"
+            >{{ 'CorePluginsAdmin_TeaserExtendPiwikByTheme'|translate }}</h2>
 
         <div class="infoBox">
             {{ 'CorePluginsAdmin_BeCarefulUsingThemes'|translate }}
diff --git a/plugins/CorePluginsAdmin/templates/extend.twig b/plugins/CorePluginsAdmin/templates/extend.twig
index 4b04fa588f..b95b6018c8 100644
--- a/plugins/CorePluginsAdmin/templates/extend.twig
+++ b/plugins/CorePluginsAdmin/templates/extend.twig
@@ -22,7 +22,9 @@
 
         <div class="introduction">
 
-            <h2>{{ 'CorePluginsAdmin_TeaserExtendPiwik'|translate }}</h2>
+            <h2 piwik-enriched-headline
+                feature-name="{{ 'CorePluginsAdmin_Marketplace'|translate }}"
+                >{{ 'CorePluginsAdmin_TeaserExtendPiwik'|translate }}</h2>
 
             <p>{{ 'CorePluginsAdmin_DownloadAndInstallPluginsFromMarketplace'|translate("<a href='?module=Proxy&action=redirect&url=http://plugins.piwik.org/' target='_blank'>", "</a>")|raw }}</p>
 
diff --git a/plugins/CorePluginsAdmin/templates/plugins.twig b/plugins/CorePluginsAdmin/templates/plugins.twig
index 18732a7a5f..4eeb7ee032 100644
--- a/plugins/CorePluginsAdmin/templates/plugins.twig
+++ b/plugins/CorePluginsAdmin/templates/plugins.twig
@@ -13,7 +13,7 @@
         {{ plugins.tablePluginUpdates(pluginsHavingUpdate, updateNonce, activateNonce, 0) }}
     {% endif %}
 
-    <h2>{{ 'CorePluginsAdmin_PluginsManagement'|translate }}</h2>
+    <h2 piwik-enriched-headline>{{ 'CorePluginsAdmin_PluginsManagement'|translate }}</h2>
 
     <p>{{ 'CorePluginsAdmin_MainDescription'|translate }}
 
diff --git a/plugins/CorePluginsAdmin/templates/themes.twig b/plugins/CorePluginsAdmin/templates/themes.twig
index 2f117dfcf1..5ac8ff6d9a 100644
--- a/plugins/CorePluginsAdmin/templates/themes.twig
+++ b/plugins/CorePluginsAdmin/templates/themes.twig
@@ -13,7 +13,7 @@
         {{ plugins.tablePluginUpdates(pluginsHavingUpdate, updateNonce, true) }}
     {% endif %}
 
-    <h2>{{ 'CorePluginsAdmin_ThemesManagement'|translate }}</h2>
+    <h2 piwik-enriched-headline>{{ 'CorePluginsAdmin_ThemesManagement'|translate }}</h2>
 
     <p>{{ 'CorePluginsAdmin_ThemesDescription'|translate }}
     {% if otherUsersCount > 0 %}
diff --git a/plugins/CustomAlerts b/plugins/CustomAlerts
index 64842d4552..c9edd87900 160000
--- a/plugins/CustomAlerts
+++ b/plugins/CustomAlerts
@@ -1 +1 @@
-Subproject commit 64842d455200860bf6fb09183a165e691ea47c69
+Subproject commit c9edd879003ca7a9f75d81fe07ec6ff0c2340f91
diff --git a/plugins/DevicesDetection/templates/index.twig b/plugins/DevicesDetection/templates/index.twig
index 5c41f889a9..3391ed5f36 100644
--- a/plugins/DevicesDetection/templates/index.twig
+++ b/plugins/DevicesDetection/templates/index.twig
@@ -1,15 +1,15 @@
 <div id='leftcolumn'>
-    <h2>{{ "DevicesDetection_DeviceType"|translate }}</h2>
+    <h2 piwik-enriched-headline>{{ "DevicesDetection_DeviceType"|translate }}</h2>
     {{ deviceTypes  | raw}}
-    <h2>{{ "DevicesDetection_DeviceBrand"|translate }}</h2>
+    <h2 piwik-enriched-headline>{{ "DevicesDetection_DeviceBrand"|translate }}</h2>
     {{ deviceBrands | raw }}
-    <h2>{{ "DevicesDetection_DeviceModel"|translate }}</h2>
+    <h2 piwik-enriched-headline>{{ "DevicesDetection_DeviceModel"|translate }}</h2>
     {{ deviceModels | raw }}
 </div>
 
 <div id='rightcolumn'>
-    <h2>{{ "DevicesDetection_OperatingSystemFamilies"|translate }}</h2>
+    <h2 piwik-enriched-headline>{{ "DevicesDetection_OperatingSystemFamilies"|translate }}</h2>
     {{ osReport  | raw}}
-    <h2>{{ "UserSettings_BrowserFamilies"|translate }}</h2>
+    <h2 piwik-enriched-headline>{{ "UserSettings_BrowserFamilies"|translate }}</h2>
     {{ browserReport | raw }}
 </div>
diff --git a/plugins/Feedback/API.php b/plugins/Feedback/API.php
new file mode 100644
index 0000000000..96ae313d6d
--- /dev/null
+++ b/plugins/Feedback/API.php
@@ -0,0 +1,73 @@
+<?php
+/**
+ * Piwik - Open source web analytics
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ *
+ */
+namespace Piwik\Plugins\Feedback;
+use Piwik\Common;
+use Piwik\Config;
+use Piwik\IP;
+use Piwik\Mail;
+use Piwik\Piwik;
+use Piwik\Url;
+use Piwik\Version;
+
+/**
+ * API for plugin Feedback
+ *
+ * @method static \Piwik\Plugins\Feedback\API getInstance()
+ */
+class API extends \Piwik\Plugin\API
+{
+    public function sendFeedbackForFeature($featureName, $like, $message)
+    {
+        Piwik::checkUserIsNotAnonymous();
+        Piwik::checkUserHasSomeViewAccess();
+
+        $translationKeyForFeature = $this->findTranslationKeyForFeatureName($featureName);
+
+        if (empty($translationKeyForFeature)) {
+            $translationKeyForFeature = $featureName;
+        }
+
+        $likeText = 'Yes';
+        if (empty($like)) {
+            $likeText = 'No';
+        }
+
+        $body = sprintf("Feature: %s\nLike: %s\nFeedback:\n%s\n", $translationKeyForFeature, $likeText, $message);
+
+        $this->sendMail($featureName, $body);
+    }
+
+    private function sendMail($name, $body)
+    {
+        $feedbackEmailAddress = Config::getInstance()->General['feedback_email_address'];
+
+        $subject = '[ Feedback Feature - Piwik ] ' . $name;
+        $body    = Common::unsanitizeInputValue($body) . "\n"
+                 . 'Piwik ' . Version::VERSION . "\n"
+                 . 'IP: ' . IP::getIpFromHeader() . "\n"
+                 . 'URL: ' . Url::getReferrer() . "\n";
+
+        $mail = new Mail();
+        $mail->setFrom(Piwik::getCurrentUserEmail());
+        $mail->addTo($feedbackEmailAddress, 'Piwik Team');
+        $mail->setSubject($subject);
+        $mail->setBodyText($body);
+        @$mail->send();
+    }
+
+    private function findTranslationKeyForFeatureName($featureName)
+    {
+        foreach ($GLOBALS['Piwik_translations'] as $key => $translations) {
+            $possibleKey = array_search($featureName, $translations);
+            if (!empty($possibleKey)) {
+                return $key . '_' . $possibleKey;
+            }
+        }
+    }
+}
diff --git a/plugins/Feedback/Feedback.php b/plugins/Feedback/Feedback.php
index 82fa716d26..6d6969f548 100644
--- a/plugins/Feedback/Feedback.php
+++ b/plugins/Feedback/Feedback.php
@@ -45,15 +45,27 @@ class Feedback extends \Piwik\Plugin
     public function getStylesheetFiles(&$stylesheets)
     {
         $stylesheets[] = "plugins/Feedback/stylesheets/feedback.less";
+
+        $stylesheets[] = "plugins/Feedback/angularjs/ratefeature/ratefeature.less";
     }
 
     public function getJsFiles(&$jsFiles)
     {
         $jsFiles[] = "plugins/Feedback/javascripts/feedback.js";
+
+        $jsFiles[] = "plugins/Feedback/angularjs/ratefeature/ratefeature-model.js";
+        $jsFiles[] = "plugins/Feedback/angularjs/ratefeature/ratefeature-controller.js";
+        $jsFiles[] = "plugins/Feedback/angularjs/ratefeature/ratefeature-directive.js";
     }
 
     public function getClientSideTranslationKeys(&$translationKeys)
     {
         $translationKeys[] = 'General_Loading';
+        $translationKeys[] = 'Feedback_ThankYou';
+        $translationKeys[] = 'Feedback_RateFeatureTitle';
+        $translationKeys[] = 'Feedback_RateFeatureThankYouTitle';
+        $translationKeys[] = 'Feedback_RateFeatureLeaveMessageLike';
+        $translationKeys[] = 'Feedback_RateFeatureLeaveMessageDislike';
+        $translationKeys[] = 'Feedback_SendFeedback';
     }
 }
diff --git a/plugins/Feedback/angularjs/ratefeature/icon_license b/plugins/Feedback/angularjs/ratefeature/icon_license
new file mode 100644
index 0000000000..78a631917a
--- /dev/null
+++ b/plugins/Feedback/angularjs/ratefeature/icon_license
@@ -0,0 +1,7 @@
+thumbs-up.png
+https://www.iconfinder.com/icons/83403/thumbs_up_icon#size=32
+Creative Commons (Attribution-Share Alike 3.0 Unported)
+
+thumbs-down.png
+https://www.iconfinder.com/icons/83402/down_thumbs_icon#size=32
+Creative Commons (Attribution-Share Alike 3.0 Unported)
\ No newline at end of file
diff --git a/plugins/Feedback/angularjs/ratefeature/ratefeature-controller.js b/plugins/Feedback/angularjs/ratefeature/ratefeature-controller.js
new file mode 100644
index 0000000000..b68602fad7
--- /dev/null
+++ b/plugins/Feedback/angularjs/ratefeature/ratefeature-controller.js
@@ -0,0 +1,22 @@
+/*!
+ * 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('RateFeatureController', function($scope, rateFeatureModel, $filter){
+
+    $scope.dislikeFeature = function () {
+        $scope.like = false;
+    };
+
+    $scope.likeFeature = function () {
+        $scope.like = true;
+    };
+
+    $scope.sendFeedback = function (message) {
+        rateFeatureModel.sendFeedbackForFeature($scope.title, $scope.like, message);
+        alert($filter('translate')('Feedback_ThankYou'));
+    };
+});
diff --git a/plugins/Feedback/angularjs/ratefeature/ratefeature-directive.js b/plugins/Feedback/angularjs/ratefeature/ratefeature-directive.js
new file mode 100644
index 0000000000..0aa902bea6
--- /dev/null
+++ b/plugins/Feedback/angularjs/ratefeature/ratefeature-directive.js
@@ -0,0 +1,22 @@
+/*!
+ * Piwik - Web Analytics
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ */
+
+/**
+ * Usage:
+ * <div piwik-rate-feature title="My Feature Name">
+ */
+angular.module('piwikApp').directive('piwikRateFeature', function($document, piwik, $filter){
+
+    return {
+        restrict: 'A',
+        scope: {
+            title: '@'
+        },
+        templateUrl: 'plugins/Feedback/angularjs/ratefeature/ratefeature.html?cb=' + piwik.cacheBuster,
+        controller: 'RateFeatureController'
+    }
+});
\ No newline at end of file
diff --git a/plugins/Feedback/angularjs/ratefeature/ratefeature-model.js b/plugins/Feedback/angularjs/ratefeature/ratefeature-model.js
new file mode 100644
index 0000000000..c724cbc810
--- /dev/null
+++ b/plugins/Feedback/angularjs/ratefeature/ratefeature-model.js
@@ -0,0 +1,22 @@
+/*!
+ * Piwik - Web Analytics
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ */
+
+angular.module('piwikApp').factory('rateFeatureModel', function (piwikApi) {
+
+    var model = {};
+
+    model.sendFeedbackForFeature = function (featureName, like, message) {
+        return piwikApi.fetch({
+            method: 'Feedback.sendFeedbackForFeature',
+            featureName: featureName,
+            like: like ? '1' : '0',
+            message: message + ''
+        });
+    };
+
+    return model;
+});
diff --git a/plugins/Feedback/angularjs/ratefeature/ratefeature.html b/plugins/Feedback/angularjs/ratefeature/ratefeature.html
new file mode 100644
index 0000000000..bdfec8e301
--- /dev/null
+++ b/plugins/Feedback/angularjs/ratefeature/ratefeature.html
@@ -0,0 +1,31 @@
+<div title="{{ 'Feedback_RateFeatureTitle'|translate:title }}" class="ratefeature">
+
+    <div class="iconContainer"
+         ng-mouseenter="view.expanded=true;"
+         ng-mouseleave="view.expanded=false">
+
+        <img ng-click="likeFeature();view.showFeedbackForm=true;"
+             class="like-icon"
+             src="plugins/Feedback/angularjs/ratefeature/thumbs-up.png"/>
+
+        <img ng-click="dislikeFeature();view.showFeedbackForm=true;"
+             class="dislike-icon"
+             ng-show="view.expanded"
+             src="plugins/Feedback/angularjs/ratefeature/thumbs-down.png"/>
+    </div>
+
+    <div class="ratefeatureDialog" piwik-dialog="view.showFeedbackForm" yes="sendFeedback(view.feedbackMessage)">
+        <h1>{{ 'Feedback_RateFeatureThankYouTitle'|translate:title }}</h1>
+
+        <p ng-if="like">{{ 'Feedback_RateFeatureLeaveMessageLike'|translate }}</p>
+        <p ng-if="!like">{{ 'Feedback_RateFeatureLeaveMessageDislike'|translate }}</p>
+        <br />
+
+        <div class="messageContainer">
+            <textarea ng-model="view.feedbackMessage"></textarea>
+        </div>
+
+        <input type="button" value="{{ 'Feedback_SendFeedback'|translate }}" role="yes"/>
+    </div>
+
+</div>
\ No newline at end of file
diff --git a/plugins/Feedback/angularjs/ratefeature/ratefeature.less b/plugins/Feedback/angularjs/ratefeature/ratefeature.less
new file mode 100644
index 0000000000..4c55214456
--- /dev/null
+++ b/plugins/Feedback/angularjs/ratefeature/ratefeature.less
@@ -0,0 +1,31 @@
+.ratefeatureDialog {
+  .messageContainer {
+    text-align: center;
+  }
+
+  textarea {
+    width: 100%;
+    height: 80px;
+  }
+}
+
+.ratefeature {
+
+  font-size: 1px;
+
+  .iconContainer {
+    display: inline-block;
+  }
+
+  .dislike-icon,
+  .like-icon {
+    opacity: 0.2;
+    width:24px;
+    height:24px;
+    cursor: pointer;
+
+    &:hover {
+      opacity: 0.9;
+    }
+  }
+}
\ No newline at end of file
diff --git a/plugins/Feedback/angularjs/ratefeature/thumbs-down.png b/plugins/Feedback/angularjs/ratefeature/thumbs-down.png
new file mode 100644
index 0000000000000000000000000000000000000000..c9ce204822ebab188433a38b97c5effb3143b5be
GIT binary patch
literal 2188
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
MrdB3(Mws}20ePbmnE(I)

literal 0
HcmV?d00001

diff --git a/plugins/Feedback/angularjs/ratefeature/thumbs-up.png b/plugins/Feedback/angularjs/ratefeature/thumbs-up.png
new file mode 100644
index 0000000000000000000000000000000000000000..a94421bafe386fce2f4fda0de4a59f4e50648258
GIT binary patch
literal 2202
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

literal 0
HcmV?d00001

diff --git a/plugins/Goals/templates/_addEditGoal.twig b/plugins/Goals/templates/_addEditGoal.twig
index 41f094163f..c8feb87bc5 100644
--- a/plugins/Goals/templates/_addEditGoal.twig
+++ b/plugins/Goals/templates/_addEditGoal.twig
@@ -1,5 +1,5 @@
 {% if onlyShowAddNewGoal is defined %}
-    <h2>{{ 'Goals_AddNewGoal'|translate }}</h2>
+    <h2 piwik-enriched-headline>{{ 'Goals_AddNewGoal'|translate }}</h2>
     <p>{{ 'Goals_NewGoalIntro'|translate }}</p>
     <p>{{ 'Goals_NewGoalDescription'|translate }}
         {{ 'Goals_NewWhatDoYouWantUsersToDo'|translate }}
@@ -8,7 +8,7 @@
     </p>
 {% else %}
     <div class="clear"></div>
-    <h2>{{ 'Goals_GoalsManagement'|translate }}</h2>
+    <h2 piwik-enriched-headline>{{ 'Goals_GoalsManagement'|translate }}</h2>
     <div class="entityList">
         <ul class='listCircle'>
             <li><a onclick='' name='linkAddNewGoal'>{{ 'Goals_CreateNewGOal'|translate }}</a></li>
diff --git a/plugins/Goals/templates/_titleAndEvolutionGraph.twig b/plugins/Goals/templates/_titleAndEvolutionGraph.twig
index c19f253e4a..d3a1d304da 100644
--- a/plugins/Goals/templates/_titleAndEvolutionGraph.twig
+++ b/plugins/Goals/templates/_titleAndEvolutionGraph.twig
@@ -1,7 +1,7 @@
 <span data-graph-id="{{ nameGraphEvolution }}"></span>
 
 {% if displayFullReport %}
-    <h2>{% if goalName is defined %}{{ 'Goals_GoalX'|translate(goalName)|raw }}{% else %}{{ 'Goals_GoalsOverview'|translate }}{% endif %}</h2>
+    <h2 piwik-enriched-headline>{% if goalName is defined %}{{ 'Goals_GoalX'|translate(goalName)|raw }}{% else %}{{ 'Goals_GoalsOverview'|translate }}{% endif %}</h2>
 {% endif %}
 {{ graphEvolution|raw }}
 
diff --git a/plugins/Installation/templates/systemCheckPage.twig b/plugins/Installation/templates/systemCheckPage.twig
index eea9ca86b9..f6533496d0 100755
--- a/plugins/Installation/templates/systemCheckPage.twig
+++ b/plugins/Installation/templates/systemCheckPage.twig
@@ -2,7 +2,7 @@
 
 {% block content %}
 {% if isSuperUser %}
-    <h2>{{ 'Installation_SystemCheck'|translate }}</h2>
+    <h2 piwik-enriched-headline>{{ 'Installation_SystemCheck'|translate }}</h2>
     <p style="margin-left:1em;">
         {% if infos.has_errors %}
             <img src="plugins/Zeitgeist/images/error.png"/>
diff --git a/plugins/MobileMessaging/templates/index.twig b/plugins/MobileMessaging/templates/index.twig
index 082c9e4f3c..7b643b1d14 100644
--- a/plugins/MobileMessaging/templates/index.twig
+++ b/plugins/MobileMessaging/templates/index.twig
@@ -2,7 +2,9 @@
 
 {% block content %}
     {% if accountManagedByCurrentUser %}
-        <h2>{{ 'MobileMessaging_Settings_SMSAPIAccount'|translate }}</h2>
+        <h2 piwik-enriched-headline
+            feature-name="{{ 'MobileMessaging_SettingsMenu'|translate }}"
+                >{{ 'MobileMessaging_Settings_SMSAPIAccount'|translate }}</h2>
         {% if credentialSupplied %}
             {{ 'MobileMessaging_Settings_CredentialProvided'|translate(provider) }}
             {{ creditLeft }}
diff --git a/plugins/MultiSites/angularjs/dashboard/dashboard.html b/plugins/MultiSites/angularjs/dashboard/dashboard.html
index 0eba760b98..6c1074b336 100644
--- a/plugins/MultiSites/angularjs/dashboard/dashboard.html
+++ b/plugins/MultiSites/angularjs/dashboard/dashboard.html
@@ -1,5 +1,7 @@
 <div>
-    <h2>
+    <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)}}"
diff --git a/plugins/PrivacyManager/templates/privacySettings.twig b/plugins/PrivacyManager/templates/privacySettings.twig
index 89ed7c0d61..2fec22eb68 100644
--- a/plugins/PrivacyManager/templates/privacySettings.twig
+++ b/plugins/PrivacyManager/templates/privacySettings.twig
@@ -3,7 +3,8 @@
 {% block content %}
 {% import 'macros.twig' as piwik %}
 {% if isSuperUser %}
-    <h2>{{ 'PrivacyManager_TeaserHeadline'|translate }}</h2>
+    <h2 piwik-enriched-headline
+        help-url="http://piwik.org/docs/privacy/">{{ 'PrivacyManager_TeaserHeadline'|translate }}</h2>
     <p>{{ 'PrivacyManager_Teaser'|translate('<a href="#anonymizeIPAnchor">',"</a>",'<a href="#deleteLogsAnchor">',"</a>",'<a href="#optOutAnchor">',"</a>")|raw }}
         {{'PrivacyManager_SeeAlsoOurOfficialGuidePrivacy'|translate('<strong><a href="http://piwik.org/privacy/" target="_blank">','</a></strong>')|raw }}</p>
     <h2 id="anonymizeIPAnchor">{{ 'PrivacyManager_UseAnonymizeIp'|translate }}</h2>
diff --git a/plugins/Referrers/templates/getSearchEnginesAndKeywords.twig b/plugins/Referrers/templates/getSearchEnginesAndKeywords.twig
index c24463ba7d..ce2f5f2e8d 100644
--- a/plugins/Referrers/templates/getSearchEnginesAndKeywords.twig
+++ b/plugins/Referrers/templates/getSearchEnginesAndKeywords.twig
@@ -1,9 +1,9 @@
 <div id='leftcolumn'>
-    <h2>{{ 'Referrers_Keywords'|translate }}</h2>
+    <h2 piwik-enriched-headline>{{ 'Referrers_Keywords'|translate }}</h2>
     {{ keywords|raw }}
 </div>
 
 <div id='rightcolumn'>
-    <h2>{{ 'Referrers_SearchEngines'|translate }}</h2>
+    <h2 piwik-enriched-headline>{{ 'Referrers_SearchEngines'|translate }}</h2>
     {{ searchEngines|raw }}
 </div>
diff --git a/plugins/Referrers/templates/index.twig b/plugins/Referrers/templates/index.twig
index 8f0272fe58..6a5db26270 100644
--- a/plugins/Referrers/templates/index.twig
+++ b/plugins/Referrers/templates/index.twig
@@ -1,9 +1,10 @@
-<h2 data-graph-id="{{ nameGraphEvolutionReferrers }}">{{ 'General_EvolutionOverPeriod'|translate }}</h2>
+<h2 piwik-enriched-headline
+    data-graph-id="{{ nameGraphEvolutionReferrers }}">{{ 'General_EvolutionOverPeriod'|translate }}</h2>
 {{ graphEvolutionReferrers|raw }}
 
 <br/>
 <div id='leftcolumn' style="position:relative;">
-    <h2>{{ 'Referrers_Type'|translate }}</h2>
+    <h2 piwik-enriched-headline>{{ 'Referrers_Type'|translate }}</h2>
 
     <div id='leftcolumn'>
         <div class="sparkline">{{ sparkline(urlSparklineDirectEntry) }}
@@ -103,14 +104,14 @@
 </div>
 
 <div id='rightcolumn'>
-    <h2>{{ 'Referrers_DetailsByReferrerType'|translate }}</h2>
+    <h2 piwik-enriched-headline>{{ 'Referrers_DetailsByReferrerType'|translate }}</h2>
     {{ dataTableReferrerType|raw }}
 </div>
 
 <div style="clear:both;"></div>
 
 {% if totalVisits > 0 %}
-    <h2>{{ 'Referrers_ReferrersOverview'|translate }}</h2>
+    <h2 piwik-enriched-headline>{{ 'Referrers_ReferrersOverview'|translate }}</h2>
     {{ referrersReportsByDimension|raw }}
 {% endif %}
 
diff --git a/plugins/Referrers/templates/indexWebsites.twig b/plugins/Referrers/templates/indexWebsites.twig
index 10a844eeb5..adfea9d6e1 100644
--- a/plugins/Referrers/templates/indexWebsites.twig
+++ b/plugins/Referrers/templates/indexWebsites.twig
@@ -1,9 +1,9 @@
 <div id='leftcolumn'>
-    <h2>{{ 'Referrers_Websites'|translate }}</h2>
+    <h2 piwik-enriched-headline>{{ 'Referrers_Websites'|translate }}</h2>
     {{ websites|raw }}
 </div>
 
 <div id='rightcolumn'>
-    <h2>{{ 'Referrers_Socials'|translate }}</h2>
+    <h2 piwik-enriched-headline>{{ 'Referrers_Socials'|translate }}</h2>
     {{ socials|raw }}
 </div>
diff --git a/plugins/ScheduledReports/templates/index.twig b/plugins/ScheduledReports/templates/index.twig
index 3e41ac0147..b8ccecf53a 100644
--- a/plugins/ScheduledReports/templates/index.twig
+++ b/plugins/ScheduledReports/templates/index.twig
@@ -9,7 +9,8 @@
 </div>
 
 <div class="centerLargeDiv">
-    <h2>{{ 'ScheduledReports_ManageEmailReports'|translate }}</h2>
+    <h2 piwik-enriched-headline
+        help-url="http://piwik.org/docs/email-reports/">{{ 'ScheduledReports_ManageEmailReports'|translate }}</h2>
     <span id="reportSentSuccess"></span>
     <span id="reportUpdatedSuccess"></span>
 
diff --git a/plugins/SecurityInfo b/plugins/SecurityInfo
index f9aabdf4a4..cd98a60c78 160000
--- a/plugins/SecurityInfo
+++ b/plugins/SecurityInfo
@@ -1 +1 @@
-Subproject commit f9aabdf4a4112b3c0505257978435dcee4039471
+Subproject commit cd98a60c785ce56b45e4d142e9af3a470619a60b
diff --git a/plugins/SegmentEditor/javascripts/Segmentation.js b/plugins/SegmentEditor/javascripts/Segmentation.js
index 17f15637ff..5d843e6fcf 100644
--- a/plugins/SegmentEditor/javascripts/Segmentation.js
+++ b/plugins/SegmentEditor/javascripts/Segmentation.js
@@ -842,6 +842,7 @@ Segmentation = (function($) {
 
             self.target.closest('.segmentEditorPanel').addClass('editing');
 
+            piwikHelper.compileAngularComponents(self.target);
         };
 
         var closeForm = function () {
diff --git a/plugins/SegmentEditor/templates/_segmentSelector.twig b/plugins/SegmentEditor/templates/_segmentSelector.twig
index 22ebb8fd10..f83e738867 100644
--- a/plugins/SegmentEditor/templates/_segmentSelector.twig
+++ b/plugins/SegmentEditor/templates/_segmentSelector.twig
@@ -1,7 +1,6 @@
 <div class="SegmentEditor" style="display:none;">
     <div class="segmentationContainer listHtml">
         <span class="segmentationTitle"></span>
-
         <div class="dropdown-body">
             <ul class="submenu">
                 <li>{{ 'SegmentEditor_SelectSegmentOfVisitors'|translate }}
@@ -11,6 +10,7 @@
                     </div>
                 </li>
             </ul>
+
             {% if authorizedToCreateSegments %}
                 <a class="add_new_segment">{{ 'SegmentEditor_AddNewSegment'|translate }}</a>
             {% else %}
@@ -131,6 +131,7 @@
             <h3>{{ 'General_Name'|translate }}: <span  class="segmentName"></span> <a class="editSegmentName" href="#">{{ 'General_Edit'|translate|lower }}</a></h3>
         </div>
         <div class="segment-footer">
+            <div piwik-rate-feature title="'Segment Editor'" style="display:inline-block;float: left;margin-top: 2px;margin-right: 10px;"></div>
             <span class="segmentFooterNote">The Segment Editor was <a class='crowdfundingLink' href='http://crowdfunding.piwik.org/custom-segments-editor/' target='_blank'>crowdfunded</a> with the awesome support of 80 companies and Piwik users worldwide!</span>
             <a class="delete" href="#">{{ 'General_Delete'|translate }}</a>
             <a class="close" href="#">{{ 'General_Close'|translate }}</a>
diff --git a/plugins/SitesManager/templates/index.twig b/plugins/SitesManager/templates/index.twig
index 3298488964..dcf73012b3 100644
--- a/plugins/SitesManager/templates/index.twig
+++ b/plugins/SitesManager/templates/index.twig
@@ -104,7 +104,7 @@
         });
     </script>
 
-    <h2>{{ 'SitesManager_WebsitesManagement'|translate }}</h2>
+    <h2 piwik-enriched-headline>{{ 'SitesManager_WebsitesManagement'|translate }}</h2>
     <p>{{ 'SitesManager_MainDescription'|translate }}
         {{ 'SitesManager_YouCurrentlyHaveAccessToNWebsites'|translate("<strong>" ~ adminSitesCount ~ "</strong>")|raw }}
         {% if isSuperUser %}
diff --git a/plugins/TasksTimetable b/plugins/TasksTimetable
index 72dd8092a9..f6e252d5dc 160000
--- a/plugins/TasksTimetable
+++ b/plugins/TasksTimetable
@@ -1 +1 @@
-Subproject commit 72dd8092a95621026ad85d29b79c0283ed18fc04
+Subproject commit f6e252d5dc5e3cf004263f7450c2ca55bd2c5a71
diff --git a/plugins/TreemapVisualization b/plugins/TreemapVisualization
index 19978cb7cd..2cb15300a8 160000
--- a/plugins/TreemapVisualization
+++ b/plugins/TreemapVisualization
@@ -1 +1 @@
-Subproject commit 19978cb7cd926ec0fba111ce257b8f0450f34ce8
+Subproject commit 2cb15300a88f7ff2a1fc27ef633a1a1f4d5fef09
diff --git a/plugins/UserCountry/templates/adminIndex.twig b/plugins/UserCountry/templates/adminIndex.twig
index 2192f3fc91..5ea5459f7f 100755
--- a/plugins/UserCountry/templates/adminIndex.twig
+++ b/plugins/UserCountry/templates/adminIndex.twig
@@ -3,7 +3,9 @@
 {% block content %}
 {% import 'macros.twig' as piwik %}
 
-<h2 id="location-providers">{{ 'UserCountry_Geolocation'|translate }}</h2>
+<h2 piwik-enriched-headline
+    help-url="http://piwik.org/docs/geo-locate/"
+    id="location-providers">{{ 'UserCountry_Geolocation'|translate }}</h2>
 
 <div style="width:900px;">
 
diff --git a/plugins/UserCountry/templates/index.twig b/plugins/UserCountry/templates/index.twig
index c6e211de18..72d49613eb 100644
--- a/plugins/UserCountry/templates/index.twig
+++ b/plugins/UserCountry/templates/index.twig
@@ -1,7 +1,7 @@
 <div id="leftcolumn">
     {{ postEvent("Template.leftColumnUserCountry") }}
 
-    <h2>{{ 'UserCountry_Continent'|translate }}</h2>
+    <h2 piwik-enriched-headline>{{ 'UserCountry_Continent'|translate }}</h2>
     {{ dataTableContinent|raw }}
 
     <div class="sparkline">
@@ -14,13 +14,13 @@
 </div>
 
 <div id="rightcolumn">
-    <h2>{{ 'UserCountry_Country'|translate }}</h2>
+    <h2 piwik-enriched-headline>{{ 'UserCountry_Country'|translate }}</h2>
     {{ dataTableCountry|raw }}
 
-    <h2>{{ 'UserCountry_Region'|translate }}</h2>
+    <h2 piwik-enriched-headline>{{ 'UserCountry_Region'|translate }}</h2>
     {{ dataTableRegion|raw }}
 
-    <h2>{{ 'UserCountry_City'|translate }}</h2>
+    <h2 piwik-enriched-headline>{{ 'UserCountry_City'|translate }}</h2>
     {{ dataTableCity|raw }}
 </div>
 
diff --git a/plugins/UserSettings/templates/index.twig b/plugins/UserSettings/templates/index.twig
index ec55faccbc..7835908e5c 100644
--- a/plugins/UserSettings/templates/index.twig
+++ b/plugins/UserSettings/templates/index.twig
@@ -1,27 +1,27 @@
 <div id='leftcolumn'>
-    <h2>{{ 'UserSettings_BrowserFamilies'|translate }}</h2>
+    <h2 piwik-enriched-headline>{{ 'UserSettings_BrowserFamilies'|translate }}</h2>
     {{ dataTableBrowserType|raw }}
 
-    <h2>{{ 'UserSettings_Browsers'|translate }}</h2>
+    <h2 piwik-enriched-headline>{{ 'UserSettings_Browsers'|translate }}</h2>
     {{ dataTableBrowser|raw }}
 
-    <h2>{{ 'General_Plugins'|translate }}</h2>
+    <h2 piwik-enriched-headline>{{ 'General_Plugins'|translate }}</h2>
     {{ dataTablePlugin|raw }}
 </div>
 
 <div id='rightcolumn'>
-    <h2>{{ 'UserSettings_Configurations'|translate }}</h2>
+    <h2 piwik-enriched-headline>{{ 'UserSettings_Configurations'|translate }}</h2>
     {{ dataTableConfiguration|raw }}
 
-    <h2>{{ 'UserSettings_OperatingSystems'|translate }}</h2>
+    <h2 piwik-enriched-headline>{{ 'UserSettings_OperatingSystems'|translate }}</h2>
     {{ dataTableOS|raw }}
 
-    <h2>{{ 'UserSettings_Resolutions'|translate }}</h2>
+    <h2 piwik-enriched-headline>{{ 'UserSettings_Resolutions'|translate }}</h2>
     {{ dataTableResolution|raw }}
 
-    <h2>{{ 'UserSettings_MobileVsDesktop'|translate }}</h2>
+    <h2 piwik-enriched-headline>{{ 'UserSettings_MobileVsDesktop'|translate }}</h2>
     {{ dataTableMobileVsDesktop|raw }}
 
-    <h2>{{ 'UserSettings_BrowserLanguage'|translate }}</h2>
+    <h2 piwik-enriched-headline>{{ 'UserSettings_BrowserLanguage'|translate }}</h2>
     {{ dataTableBrowserLanguage|raw }}
 </div>
diff --git a/plugins/UsersManager/templates/index.twig b/plugins/UsersManager/templates/index.twig
index b97ff19647..45fdeeeb40 100644
--- a/plugins/UsersManager/templates/index.twig
+++ b/plugins/UsersManager/templates/index.twig
@@ -2,7 +2,8 @@
 
 {% block content %}
 
-<h2>{{ 'UsersManager_ManageAccess'|translate }}</h2>
+<h2 piwik-enriched-headline
+    help-url="http://piwik.org/docs/manage-users/">{{ 'UsersManager_ManageAccess'|translate }}</h2>
 <div id="sites" class="usersManager">
     <section class="sites_selector_container">
         <p>{{ 'UsersManager_MainDescription'|translate }}</p>
diff --git a/plugins/UsersManager/templates/userSettings.twig b/plugins/UsersManager/templates/userSettings.twig
index d98de49b94..397f31e46e 100644
--- a/plugins/UsersManager/templates/userSettings.twig
+++ b/plugins/UsersManager/templates/userSettings.twig
@@ -1,10 +1,9 @@
 {% extends 'admin.twig' %}
 
 {% block content %}
-<h2>{{ 'UsersManager_MenuUserSettings'|translate }}</h2>
+<h2 piwik-enriched-headline>{{ 'UsersManager_MenuUserSettings'|translate }}</h2>
 
 <br/>
-
 <div class="ui-confirm" id="confirmPasswordChange">
     <h2>{{ 'UsersManager_ChangePasswordConfirm'|translate }}</h2>
     <input role="yes" type="button" value="{{ 'General_Yes'|translate }}"/>
diff --git a/plugins/VisitFrequency/templates/index.twig b/plugins/VisitFrequency/templates/index.twig
index 52b70bb55a..6abd255b17 100644
--- a/plugins/VisitFrequency/templates/index.twig
+++ b/plugins/VisitFrequency/templates/index.twig
@@ -1,6 +1,6 @@
 {{ postEvent("Template.headerVisitsFrequency") }}
 
-<h2 data-graph-id="VisitFrequency.getEvolutionGraph">{{ 'VisitFrequency_ColumnReturningVisits'|translate }}</h2>
+<h2 piwik-enriched-headline data-graph-id="VisitFrequency.getEvolutionGraph">{{ 'VisitFrequency_ColumnReturningVisits'|translate }}</h2>
     {{ graphEvolutionVisitFrequency|raw }}
 <br/>
 
diff --git a/plugins/VisitTime/templates/index.twig b/plugins/VisitTime/templates/index.twig
index bb41160beb..c0c2a85feb 100644
--- a/plugins/VisitTime/templates/index.twig
+++ b/plugins/VisitTime/templates/index.twig
@@ -1,9 +1,9 @@
 <div id='leftcolumn'>
-    <h2>{{ 'VisitTime_LocalTime'|translate }}</h2>
+    <h2 piwik-enriched-headline>{{ 'VisitTime_LocalTime'|translate }}</h2>
     {{ dataTableVisitInformationPerLocalTime|raw }}
 </div>
 
 <div id='rightcolumn'>
-    <h2>{{ 'VisitTime_ServerTime'|translate }}</h2>
+    <h2 piwik-enriched-headline>{{ 'VisitTime_ServerTime'|translate }}</h2>
     {{ dataTableVisitInformationPerServerTime|raw }}
 </div>
diff --git a/plugins/VisitorGenerator b/plugins/VisitorGenerator
index db86db1894..29ccce979f 160000
--- a/plugins/VisitorGenerator
+++ b/plugins/VisitorGenerator
@@ -1 +1 @@
-Subproject commit db86db1894afdfead40dea154f8eb3a4295346d3
+Subproject commit 29ccce979f1bfc7df8595d1b2aac41157114144e
diff --git a/plugins/VisitorInterest/templates/index.twig b/plugins/VisitorInterest/templates/index.twig
index c2c143f135..359d43608f 100644
--- a/plugins/VisitorInterest/templates/index.twig
+++ b/plugins/VisitorInterest/templates/index.twig
@@ -1,11 +1,11 @@
-<h2>{{ 'VisitorInterest_VisitsPerDuration'|translate }}</h2>
+<h2 piwik-enriched-headline>{{ 'VisitorInterest_VisitsPerDuration'|translate }}</h2>
 {{ dataTableNumberOfVisitsPerVisitDuration|raw }}
 
-<h2>{{ 'VisitorInterest_VisitsPerNbOfPages'|translate }}</h2>
+<h2 piwik-enriched-headline>{{ 'VisitorInterest_VisitsPerNbOfPages'|translate }}</h2>
 {{ dataTableNumberOfVisitsPerPage|raw }}
 
-<h2>{{ 'VisitorInterest_visitsByVisitCount'|translate }}</h2>
+<h2 piwik-enriched-headline>{{ 'VisitorInterest_visitsByVisitCount'|translate }}</h2>
 {{ dataTableNumberOfVisitsByVisitNum|raw }}
 
-<h2>{{ 'VisitorInterest_VisitsByDaysSinceLast'|translate }}</h2>
+<h2 piwik-enriched-headline>{{ 'VisitorInterest_VisitsByDaysSinceLast'|translate }}</h2>
 {{ dataTableNumberOfVisitsByDaysSinceLast|raw }}
diff --git a/plugins/VisitsSummary/templates/index.twig b/plugins/VisitsSummary/templates/index.twig
index f1a6cb08ac..76fb54c4a9 100644
--- a/plugins/VisitsSummary/templates/index.twig
+++ b/plugins/VisitsSummary/templates/index.twig
@@ -1,5 +1,7 @@
 {# This graphId must be unique for this report #}
-<h2 data-graph-id="VisitsSummary.getEvolutionGraph">{{ 'General_EvolutionOverPeriod'|translate }}</h2>
+<h2 piwik-enriched-headline
+    data-graph-id="VisitsSummary.getEvolutionGraph"
+        >{{ 'General_EvolutionOverPeriod'|translate }}</h2>
 
 {{ graphEvolutionVisitsSummary|raw }}
 
diff --git a/plugins/Zeitgeist/javascripts/piwikHelper.js b/plugins/Zeitgeist/javascripts/piwikHelper.js
index cf65620566..0fc1f732af 100644
--- a/plugins/Zeitgeist/javascripts/piwikHelper.js
+++ b/plugins/Zeitgeist/javascripts/piwikHelper.js
@@ -110,6 +110,21 @@ var piwikHelper = {
 		return url;
 	},
 
+    /**
+     * As we still have a lot of old jQuery code and copy html from node to node we sometimes have to trigger the
+     * compiling of angular components manually.
+     *
+     * @param selector
+     */
+    compileAngularComponents: function (selector) {
+        var $element = $(selector);
+
+        angular.element(document).injector().invoke(function($compile) {
+            var scope = angular.element($element).scope();
+            $compile($element)(scope);
+        });
+    },
+
     /**
      * Displays a Modal dialog. Text will be taken from the DOM node domSelector.
      * Given callback handles will be mapped to the buttons having a role attriute
-- 
GitLab