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:
authordizzy <diosmosis@users.noreply.github.com>2021-10-26 15:00:14 +0300
committerGitHub <noreply@github.com>2021-10-26 15:00:14 +0300
commit1023fb7d691ebf47c27aa8a1cab4702c55c2630d (patch)
tree849d9c373e89d9ceb346238fcd58430f661645f5 /plugins/Feedback
parent2b72bfe1648f25b76966adc93b6250ed239e0cbe (diff)
[Vue] Migrate content-block, enriched-headline, rate-feature + related (#18166)
* migrating RateFeature and ReviewLinks + adding AjaxHelper.fetch utility method (all untested) * get ratefeature component to work, modify matomodialog component to use v-model, add event parameters to createAngularAdapter, allow translate to use variadic args or one string array + rebuild * remove ratefeature angularjs files * rebuild + make vue mapping property optional in createANgularJsAdapter * migrate enrichedheadline and get to work * fix test * fix translate * fix another translate issue & migrate contentblock directive * fix anchor links, not including the "/" causes angularjs to fail (also on 4.x-dev) * update expected screenshots * fix ui test * fix some test failures * fix nested transclude issue * remove content block files * fix icon spacing that occurs due to angularjs inserting empty comments in between nodes while vue 3 does not * update some screenshots * update screenshot (actually fixes an alignment issue) * update screenshot * Update _dataTable.twig * fix order of operations issue * built vue files * fix variable reference * built vue files * make sure absolute paths are not used in polyfill source map * trigger build * trigger another build Co-authored-by: sgiehl <stefan@matomo.org>
Diffstat (limited to 'plugins/Feedback')
-rw-r--r--plugins/Feedback/Feedback.php5
-rw-r--r--plugins/Feedback/angularjs/ratefeature/ratefeature-model.service.js29
-rw-r--r--plugins/Feedback/angularjs/ratefeature/ratefeature.controller.js33
-rw-r--r--plugins/Feedback/angularjs/ratefeature/ratefeature.directive.html41
-rw-r--r--plugins/Feedback/angularjs/ratefeature/ratefeature.directive.js29
-rw-r--r--plugins/Feedback/vue/dist/Feedback.umd.js348
-rw-r--r--plugins/Feedback/vue/dist/Feedback.umd.js.map1
-rw-r--r--plugins/Feedback/vue/dist/Feedback.umd.min.js8
-rw-r--r--plugins/Feedback/vue/dist/Feedback.umd.min.js.map1
-rw-r--r--plugins/Feedback/vue/src/RateFeature/RateFeature.adapter.ts19
-rw-r--r--plugins/Feedback/vue/src/RateFeature/RateFeature.less (renamed from plugins/Feedback/angularjs/ratefeature/ratefeature.directive.less)0
-rw-r--r--plugins/Feedback/vue/src/RateFeature/RateFeature.vue118
-rw-r--r--plugins/Feedback/vue/src/RateFeature/icon_license (renamed from plugins/Feedback/angularjs/ratefeature/icon_license)0
-rw-r--r--plugins/Feedback/vue/src/RateFeature/thumbs-down.png (renamed from plugins/Feedback/angularjs/ratefeature/thumbs-down.png)bin2188 -> 2188 bytes
-rw-r--r--plugins/Feedback/vue/src/RateFeature/thumbs-up.png (renamed from plugins/Feedback/angularjs/ratefeature/thumbs-up.png)bin2202 -> 2202 bytes
-rw-r--r--plugins/Feedback/vue/src/ReviewLinks/ReviewLinks.vue90
-rw-r--r--plugins/Feedback/vue/src/index.ts11
17 files changed, 597 insertions, 136 deletions
diff --git a/plugins/Feedback/Feedback.php b/plugins/Feedback/Feedback.php
index 9ba74d2dac..8e6531b7af 100644
--- a/plugins/Feedback/Feedback.php
+++ b/plugins/Feedback/Feedback.php
@@ -38,16 +38,13 @@ class Feedback extends \Piwik\Plugin
public function getStylesheetFiles(&$stylesheets)
{
$stylesheets[] = "plugins/Feedback/stylesheets/feedback.less";
- $stylesheets[] = "plugins/Feedback/angularjs/ratefeature/ratefeature.directive.less";
+ $stylesheets[] = "plugins/Feedback/vue/src/RateFeature/RateFeature.less";
$stylesheets[] = "plugins/Feedback/angularjs/feedback-popup/feedback-popup.directive.less";
$stylesheets[] = "plugins/Feedback/angularjs/refer-banner/refer-banner.directive.less";
}
public function getJsFiles(&$jsFiles)
{
- $jsFiles[] = "plugins/Feedback/angularjs/ratefeature/ratefeature-model.service.js";
- $jsFiles[] = "plugins/Feedback/angularjs/ratefeature/ratefeature.controller.js";
- $jsFiles[] = "plugins/Feedback/angularjs/ratefeature/ratefeature.directive.js";
$jsFiles[] = "plugins/Feedback/angularjs/feedback-popup/feedback-popup.controller.js";
$jsFiles[] = "plugins/Feedback/angularjs/feedback-popup/feedback-popup.directive.js";
$jsFiles[] = "plugins/Feedback/angularjs/refer-banner/refer-banner.directive.js";
diff --git a/plugins/Feedback/angularjs/ratefeature/ratefeature-model.service.js b/plugins/Feedback/angularjs/ratefeature/ratefeature-model.service.js
deleted file mode 100644
index 6483282f4f..0000000000
--- a/plugins/Feedback/angularjs/ratefeature/ratefeature-model.service.js
+++ /dev/null
@@ -1,29 +0,0 @@
-/*!
- * Matomo - free/libre analytics platform
- *
- * @link https://matomo.org
- * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
- */
-
-(function () {
- angular.module('piwikApp').factory('rateFeatureModel', rateFeatureModel);
-
- rateFeatureModel.$inject = ['piwikApi'];
-
- function rateFeatureModel(piwikApi) {
-
- return {
- sendFeedbackForFeature: sendFeedbackForFeature
- };
-
- function sendFeedbackForFeature (featureName, like, message) {
- return piwikApi.fetch({
- method: 'Feedback.sendFeedbackForFeature',
- featureName: featureName,
- like: like ? '1' : '0',
- message: message + ''
- });
- }
-
- }
-})();
diff --git a/plugins/Feedback/angularjs/ratefeature/ratefeature.controller.js b/plugins/Feedback/angularjs/ratefeature/ratefeature.controller.js
deleted file mode 100644
index 15b6988a49..0000000000
--- a/plugins/Feedback/angularjs/ratefeature/ratefeature.controller.js
+++ /dev/null
@@ -1,33 +0,0 @@
-/*!
- * Matomo - free/libre analytics platform
- *
- * @link https://matomo.org
- * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
- */
-(function () {
- angular.module('piwikApp').controller('RateFeatureController', RateFeatureController);
-
- RateFeatureController.$inject = ['$scope', 'rateFeatureModel'];
-
- function RateFeatureController($scope, model){
-
- var vm = this;
- vm.title = $scope.title;
- vm.dislikeFeature = dislikeFeature;
- vm.likeFeature = likeFeature;
- vm.sendFeedback = sendFeedback;
-
- function dislikeFeature () {
- vm.like = false;
- }
-
- function likeFeature () {
- vm.like = true;
- }
-
- function sendFeedback (message) {
- model.sendFeedbackForFeature(vm.title, vm.like, message);
- vm.ratingDone = true;
- }
- }
-})();
diff --git a/plugins/Feedback/angularjs/ratefeature/ratefeature.directive.html b/plugins/Feedback/angularjs/ratefeature/ratefeature.directive.html
deleted file mode 100644
index 31ded8cf07..0000000000
--- a/plugins/Feedback/angularjs/ratefeature/ratefeature.directive.html
+++ /dev/null
@@ -1,41 +0,0 @@
-<div title="{{ 'Feedback_RateFeatureTitle'|translate:(rateFeature.title|escape) }}" class="ratefeature">
-
- <div class="iconContainer"
- ng-mouseenter="view.expanded=true;"
- ng-mouseleave="view.expanded=false">
-
- <img ng-click="rateFeature.likeFeature();view.showFeedbackForm=true;"
- class="like-icon"
- src="plugins/Feedback/angularjs/ratefeature/thumbs-up.png"/>
-
- <img ng-click="rateFeature.dislikeFeature();view.showFeedbackForm=true;"
- class="dislike-icon"
- ng-show="view.expanded"
- src="plugins/Feedback/angularjs/ratefeature/thumbs-down.png"/>
- </div>
-
- <div class="ui-confirm ratefeatureDialog" piwik-dialog="view.showFeedbackForm" yes="rateFeature.sendFeedback(view.feedbackMessage)">
- <h2>{{ 'Feedback_RateFeatureThankYouTitle'|translate:title }}</h2>
- <p ng-if="rateFeature.like">{{ 'Feedback_RateFeatureLeaveMessageLike'|translate }}</p>
- <p ng-if="!rateFeature.like">{{ 'Feedback_RateFeatureLeaveMessageDislike'|translate }}</p>
- <br />
-
- <div class="messageContainer">
- <textarea ng-model="view.feedbackMessage"></textarea>
- </div>
-
- <input type="button"
- title="{{ 'Feedback_RateFeatureSendFeedbackInformation'|translate }}"
- value="{{ 'Feedback_SendFeedback'|translate }}" role="yes"/>
- <input type="button" role="cancel" value="{{ 'General_Cancel'|translate }}"/>
- </div>
-
- <div class="ui-confirm ratefeatureDialog" piwik-dialog="rateFeature.ratingDone" yes="">
- <h2>{{ 'Feedback_ThankYou'|translate:rateFeature.title }}</h2>
-
- <div ng-if="rateFeature.like" ng-include src="'plugins/Feedback/angularjs/feedback-popup/review-links.directive.html'"></div>
-
- <input type="button" value="{{ 'General_Ok'|translate }}" role="yes"/>
- </div>
-
-</div> \ No newline at end of file
diff --git a/plugins/Feedback/angularjs/ratefeature/ratefeature.directive.js b/plugins/Feedback/angularjs/ratefeature/ratefeature.directive.js
deleted file mode 100644
index 8b4e5316fe..0000000000
--- a/plugins/Feedback/angularjs/ratefeature/ratefeature.directive.js
+++ /dev/null
@@ -1,29 +0,0 @@
-/*!
- * Matomo - free/libre analytics platform
- *
- * @link https://matomo.org
- * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
- */
-
-/**
- * Usage:
- * <div piwik-rate-feature title="My Feature Name">
- */
-(function () {
- angular.module('piwikApp').directive('piwikRateFeature', piwikRateFeature);
-
- piwikRateFeature.$inject = ['piwik'];
-
- function piwikRateFeature(piwik){
-
- return {
- restrict: 'A',
- scope: {
- title: '@'
- },
- templateUrl: 'plugins/Feedback/angularjs/ratefeature/ratefeature.directive.html?cb=' + piwik.cacheBuster,
- controller: 'RateFeatureController',
- controllerAs: 'rateFeature',
- };
- }
-})(); \ No newline at end of file
diff --git a/plugins/Feedback/vue/dist/Feedback.umd.js b/plugins/Feedback/vue/dist/Feedback.umd.js
new file mode 100644
index 0000000000..10d20f2a7f
--- /dev/null
+++ b/plugins/Feedback/vue/dist/Feedback.umd.js
@@ -0,0 +1,348 @@
+(function webpackUniversalModuleDefinition(root, factory) {
+ if(typeof exports === 'object' && typeof module === 'object')
+ module.exports = factory(require("CoreHome"), require("vue"));
+ else if(typeof define === 'function' && define.amd)
+ define(["CoreHome", ], factory);
+ else if(typeof exports === 'object')
+ exports["Feedback"] = factory(require("CoreHome"), require("vue"));
+ else
+ root["Feedback"] = factory(root["CoreHome"], root["Vue"]);
+})((typeof self !== 'undefined' ? self : this), function(__WEBPACK_EXTERNAL_MODULE__19dc__, __WEBPACK_EXTERNAL_MODULE__8bbf__) {
+return /******/ (function(modules) { // webpackBootstrap
+/******/ // The module cache
+/******/ var installedModules = {};
+/******/
+/******/ // The require function
+/******/ function __webpack_require__(moduleId) {
+/******/
+/******/ // Check if module is in cache
+/******/ if(installedModules[moduleId]) {
+/******/ return installedModules[moduleId].exports;
+/******/ }
+/******/ // Create a new module (and put it into the cache)
+/******/ var module = installedModules[moduleId] = {
+/******/ i: moduleId,
+/******/ l: false,
+/******/ exports: {}
+/******/ };
+/******/
+/******/ // Execute the module function
+/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
+/******/
+/******/ // Flag the module as loaded
+/******/ module.l = true;
+/******/
+/******/ // Return the exports of the module
+/******/ return module.exports;
+/******/ }
+/******/
+/******/
+/******/ // expose the modules object (__webpack_modules__)
+/******/ __webpack_require__.m = modules;
+/******/
+/******/ // expose the module cache
+/******/ __webpack_require__.c = installedModules;
+/******/
+/******/ // define getter function for harmony exports
+/******/ __webpack_require__.d = function(exports, name, getter) {
+/******/ if(!__webpack_require__.o(exports, name)) {
+/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter });
+/******/ }
+/******/ };
+/******/
+/******/ // define __esModule on exports
+/******/ __webpack_require__.r = function(exports) {
+/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
+/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
+/******/ }
+/******/ Object.defineProperty(exports, '__esModule', { value: true });
+/******/ };
+/******/
+/******/ // create a fake namespace object
+/******/ // mode & 1: value is a module id, require it
+/******/ // mode & 2: merge all properties of value into the ns
+/******/ // mode & 4: return value when already ns object
+/******/ // mode & 8|1: behave like require
+/******/ __webpack_require__.t = function(value, mode) {
+/******/ if(mode & 1) value = __webpack_require__(value);
+/******/ if(mode & 8) return value;
+/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
+/******/ var ns = Object.create(null);
+/******/ __webpack_require__.r(ns);
+/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value });
+/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
+/******/ return ns;
+/******/ };
+/******/
+/******/ // getDefaultExport function for compatibility with non-harmony modules
+/******/ __webpack_require__.n = function(module) {
+/******/ var getter = module && module.__esModule ?
+/******/ function getDefault() { return module['default']; } :
+/******/ function getModuleExports() { return module; };
+/******/ __webpack_require__.d(getter, 'a', getter);
+/******/ return getter;
+/******/ };
+/******/
+/******/ // Object.prototype.hasOwnProperty.call
+/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
+/******/
+/******/ // __webpack_public_path__
+/******/ __webpack_require__.p = "plugins/Feedback/vue/dist/";
+/******/
+/******/
+/******/ // Load entry module and return exports
+/******/ return __webpack_require__(__webpack_require__.s = "fae3");
+/******/ })
+/************************************************************************/
+/******/ ({
+
+/***/ "19dc":
+/***/ (function(module, exports) {
+
+module.exports = __WEBPACK_EXTERNAL_MODULE__19dc__;
+
+/***/ }),
+
+/***/ "8bbf":
+/***/ (function(module, exports) {
+
+module.exports = __WEBPACK_EXTERNAL_MODULE__8bbf__;
+
+/***/ }),
+
+/***/ "fae3":
+/***/ (function(module, __webpack_exports__, __webpack_require__) {
+
+"use strict";
+// ESM COMPAT FLAG
+__webpack_require__.r(__webpack_exports__);
+
+// EXPORTS
+__webpack_require__.d(__webpack_exports__, "ReviewLinks", function() { return /* reexport */ ReviewLinks; });
+__webpack_require__.d(__webpack_exports__, "RateFeature", function() { return /* reexport */ RateFeature; });
+
+// CONCATENATED MODULE: ./node_modules/@vue/cli-service/lib/commands/build/setPublicPath.js
+// This file is imported into lib/wc client bundles.
+
+if (typeof window !== 'undefined') {
+ var currentScript = window.document.currentScript
+ if (false) { var getCurrentScript; }
+
+ var src = currentScript && currentScript.src.match(/(.+\/)[^/]+\.js(\?.*)?$/)
+ if (src) {
+ __webpack_require__.p = src[1] // eslint-disable-line
+ }
+}
+
+// Indicate to webpack that this file can be concatenated
+/* harmony default export */ var setPublicPath = (null);
+
+// EXTERNAL MODULE: external "CoreHome"
+var external_CoreHome_ = __webpack_require__("19dc");
+
+// EXTERNAL MODULE: external {"commonjs":"vue","commonjs2":"vue","root":"Vue"}
+var external_commonjs_vue_commonjs2_vue_root_Vue_ = __webpack_require__("8bbf");
+
+// CONCATENATED MODULE: ./node_modules/@vue/cli-plugin-babel/node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/@vue/cli-plugin-babel/node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/templateLoader.js??ref--6!./node_modules/@vue/cli-service/node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist??ref--0-1!./plugins/Feedback/vue/src/RateFeature/RateFeature.vue?vue&type=template&id=65bd066a
+
+const _hoisted_1 = ["title"];
+const _hoisted_2 = {
+ class: "ui-confirm ratefeatureDialog"
+};
+const _hoisted_3 = {
+ key: 0
+};
+const _hoisted_4 = {
+ key: 1
+};
+
+const _hoisted_5 = /*#__PURE__*/Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("br", null, null, -1);
+
+const _hoisted_6 = {
+ class: "messageContainer"
+};
+const _hoisted_7 = ["title", "value"];
+const _hoisted_8 = ["value"];
+const _hoisted_9 = {
+ class: "ui-confirm ratefeatureDialog"
+};
+const _hoisted_10 = {
+ key: 0
+};
+const _hoisted_11 = ["value"];
+function render(_ctx, _cache, $props, $setup, $data, $options) {
+ const _component_MatomoDialog = Object(external_commonjs_vue_commonjs2_vue_root_Vue_["resolveComponent"])("MatomoDialog");
+
+ const _component_ReviewLinks = Object(external_commonjs_vue_commonjs2_vue_root_Vue_["resolveComponent"])("ReviewLinks");
+
+ return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", {
+ title: _ctx.translate('Feedback_RateFeatureTitle', _ctx.$sanitize(_ctx.title)),
+ class: "ratefeature"
+ }, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", {
+ class: "iconContainer",
+ onMouseenter: _cache[2] || (_cache[2] = $event => _ctx.expanded = true),
+ onMouseleave: _cache[3] || (_cache[3] = $event => _ctx.expanded = false)
+ }, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("img", {
+ onClick: _cache[0] || (_cache[0] = $event => {
+ _ctx.likeFeature();
+
+ _ctx.showFeedbackForm = true;
+ }),
+ class: "like-icon",
+ src: "plugins/Feedback/vue/src/RateFeature/thumbs-up.png"
+ }), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["withDirectives"])(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("img", {
+ onClick: _cache[1] || (_cache[1] = $event => {
+ _ctx.dislikeFeature();
+
+ _ctx.showFeedbackForm = true;
+ }),
+ class: "dislike-icon",
+ src: "plugins/Feedback/vue/src/RateFeature/thumbs-down.png"
+ }, null, 512), [[external_commonjs_vue_commonjs2_vue_root_Vue_["vShow"], _ctx.expanded]])], 32), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createVNode"])(_component_MatomoDialog, {
+ modelValue: _ctx.showFeedbackForm,
+ "onUpdate:modelValue": _cache[5] || (_cache[5] = $event => _ctx.showFeedbackForm = $event),
+ onYes: _cache[6] || (_cache[6] = $event => _ctx.sendFeedback())
+ }, {
+ default: Object(external_commonjs_vue_commonjs2_vue_root_Vue_["withCtx"])(() => [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", _hoisted_2, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("h2", null, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('Feedback_RateFeatureThankYouTitle', _ctx.title)), 1), _ctx.like ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("p", _hoisted_3, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('Feedback_RateFeatureLeaveMessageLike')), 1)) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true), !_ctx.like ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("p", _hoisted_4, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('Feedback_RateFeatureLeaveMessageDislike')), 1)) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true), _hoisted_5, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", _hoisted_6, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["withDirectives"])(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("textarea", {
+ "onUpdate:modelValue": _cache[4] || (_cache[4] = $event => _ctx.feedbackMessage = $event)
+ }, null, 512), [[external_commonjs_vue_commonjs2_vue_root_Vue_["vModelText"], _ctx.feedbackMessage]])]), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("input", {
+ type: "button",
+ title: _ctx.translate('Feedback_RateFeatureSendFeedbackInformation'),
+ value: _ctx.translate('Feedback_SendFeedback'),
+ role: "yes"
+ }, null, 8, _hoisted_7), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("input", {
+ type: "button",
+ role: "cancel",
+ value: _ctx.translate('General_Cancel')
+ }, null, 8, _hoisted_8)])]),
+ _: 1
+ }, 8, ["modelValue"]), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createVNode"])(_component_MatomoDialog, {
+ modelValue: _ctx.ratingDone,
+ "onUpdate:modelValue": _cache[7] || (_cache[7] = $event => _ctx.ratingDone = $event)
+ }, {
+ default: Object(external_commonjs_vue_commonjs2_vue_root_Vue_["withCtx"])(() => [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", _hoisted_9, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("h2", null, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('Feedback_ThankYou', _ctx.title)), 1), _ctx.like ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", _hoisted_10, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createVNode"])(_component_ReviewLinks)])) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("input", {
+ type: "button",
+ value: _ctx.translate('General_Ok'),
+ role: "yes"
+ }, null, 8, _hoisted_11)])]),
+ _: 1
+ }, 8, ["modelValue"])], 8, _hoisted_1);
+}
+// CONCATENATED MODULE: ./plugins/Feedback/vue/src/RateFeature/RateFeature.vue?vue&type=template&id=65bd066a
+
+// CONCATENATED MODULE: ./node_modules/@vue/cli-plugin-babel/node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/@vue/cli-plugin-babel/node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/templateLoader.js??ref--6!./node_modules/@vue/cli-service/node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist??ref--0-1!./plugins/Feedback/vue/src/ReviewLinks/ReviewLinks.vue?vue&type=template&id=4471fc41
+
+const ReviewLinksvue_type_template_id_4471fc41_hoisted_1 = {
+ class: "requestReview"
+};
+
+const ReviewLinksvue_type_template_id_4471fc41_hoisted_2 = /*#__PURE__*/Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createStaticVNode"])("<br><br><div class=\"review-links\"><div class=\"review-link\"><a href=\"https://www.capterra.com/p/182627/Matomo-Analytics/\" target=\"_blank\"><div class=\"image\"><img loading=\"lazy\" src=\"plugins/Feedback/images/capterra.svg\"></div><div class=\"link\">Capterra</div></a></div><div class=\"review-link\"><a href=\"https://www.g2crowd.com/products/matomo-formerly-piwik/details\" target=\"_blank\"><div class=\"image\"><img loading=\"lazy\" src=\"plugins/Feedback/images/g2crowd.svg\"></div><div class=\"link\">G2 Crowd</div></a></div><div class=\"review-link\"><a href=\"https://www.producthunt.com/posts/matomo-2\" target=\"_blank\"><div class=\"image\"><img loading=\"lazy\" src=\"plugins/Feedback/images/producthunt.svg\"></div><div class=\"link\">Product Hunt</div></a></div><div class=\"review-link\"><a href=\"https://www.saasworthy.com/product/matomo\" target=\"_blank\"><div class=\"image\"><img loading=\"lazy\" src=\"plugins/Feedback/images/saasworthy.png\"></div><div class=\"link\">SaaSworthy</div></a></div><div class=\"review-link\"><a href=\"https://www.trustradius.com/products/matomo/reviews\" target=\"_blank\"><div class=\"image\"><img loading=\"lazy\" src=\"plugins/Feedback/images/trustradius.svg\"></div><div class=\"link\">TrustRadius</div></a></div></div>", 3);
+
+function ReviewLinksvue_type_template_id_4471fc41_render(_ctx, _cache, $props, $setup, $data, $options) {
+ return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", ReviewLinksvue_type_template_id_4471fc41_hoisted_1, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("p", null, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('Feedback_PleaseLeaveExternalReviewForMatomo')), 1), ReviewLinksvue_type_template_id_4471fc41_hoisted_2]);
+}
+// CONCATENATED MODULE: ./plugins/Feedback/vue/src/ReviewLinks/ReviewLinks.vue?vue&type=template&id=4471fc41
+
+// CONCATENATED MODULE: ./node_modules/@vue/cli-plugin-typescript/node_modules/cache-loader/dist/cjs.js??ref--14-0!./node_modules/@vue/cli-plugin-typescript/node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib!./node_modules/@vue/cli-plugin-typescript/node_modules/ts-loader??ref--14-3!./node_modules/@vue/cli-service/node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist??ref--0-1!./plugins/Feedback/vue/src/ReviewLinks/ReviewLinks.vue?vue&type=script&lang=ts
+
+/* harmony default export */ var ReviewLinksvue_type_script_lang_ts = (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["defineComponent"])({}));
+// CONCATENATED MODULE: ./plugins/Feedback/vue/src/ReviewLinks/ReviewLinks.vue?vue&type=script&lang=ts
+
+// CONCATENATED MODULE: ./plugins/Feedback/vue/src/ReviewLinks/ReviewLinks.vue
+
+
+
+ReviewLinksvue_type_script_lang_ts.render = ReviewLinksvue_type_template_id_4471fc41_render
+
+/* harmony default export */ var ReviewLinks = (ReviewLinksvue_type_script_lang_ts);
+// CONCATENATED MODULE: ./node_modules/@vue/cli-plugin-typescript/node_modules/cache-loader/dist/cjs.js??ref--14-0!./node_modules/@vue/cli-plugin-typescript/node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib!./node_modules/@vue/cli-plugin-typescript/node_modules/ts-loader??ref--14-3!./node_modules/@vue/cli-service/node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist??ref--0-1!./plugins/Feedback/vue/src/RateFeature/RateFeature.vue?vue&type=script&lang=ts
+
+
+
+/* harmony default export */ var RateFeaturevue_type_script_lang_ts = (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["defineComponent"])({
+ props: {
+ title: String
+ },
+ components: {
+ MatomoDialog: external_CoreHome_["MatomoDialog"],
+ ReviewLinks: ReviewLinks
+ },
+
+ data() {
+ return {
+ like: false,
+ ratingDone: false,
+ expanded: false,
+ showFeedbackForm: false,
+ feedbackMessage: ''
+ };
+ },
+
+ methods: {
+ dislikeFeature() {
+ this.like = false;
+ },
+
+ likeFeature() {
+ this.like = true;
+ },
+
+ sendFeedback() {
+ external_CoreHome_["AjaxHelper"].fetch({
+ method: 'Feedback.sendFeedbackForFeature',
+ featureName: this.title,
+ like: this.like ? '1' : '0',
+ message: this.feedbackMessage
+ });
+ this.ratingDone = true;
+ }
+
+ }
+}));
+// CONCATENATED MODULE: ./plugins/Feedback/vue/src/RateFeature/RateFeature.vue?vue&type=script&lang=ts
+
+// CONCATENATED MODULE: ./plugins/Feedback/vue/src/RateFeature/RateFeature.vue
+
+
+
+RateFeaturevue_type_script_lang_ts.render = render
+
+/* harmony default export */ var RateFeature = (RateFeaturevue_type_script_lang_ts);
+// CONCATENATED MODULE: ./plugins/Feedback/vue/src/RateFeature/RateFeature.adapter.ts
+/*!
+ * Matomo - free/libre analytics platform
+ *
+ * @link https://matomo.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ */
+
+
+/* harmony default export */ var RateFeature_adapter = (Object(external_CoreHome_["createAngularJsAdapter"])({
+ component: RateFeature,
+ scope: {
+ title: {
+ angularJsBind: '@'
+ }
+ },
+ directiveName: 'piwikRateFeature'
+}));
+// CONCATENATED MODULE: ./plugins/Feedback/vue/src/index.ts
+/*!
+ * Matomo - free/libre analytics platform
+ *
+ * @link https://matomo.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ */
+
+
+
+// CONCATENATED MODULE: ./node_modules/@vue/cli-service/lib/commands/build/entry-lib-no-default.js
+
+
+
+
+/***/ })
+
+/******/ });
+});
+//# sourceMappingURL=Feedback.umd.js.map \ No newline at end of file
diff --git a/plugins/Feedback/vue/dist/Feedback.umd.js.map b/plugins/Feedback/vue/dist/Feedback.umd.js.map
new file mode 100644
index 0000000000..a9475a0398
--- /dev/null
+++ b/plugins/Feedback/vue/dist/Feedback.umd.js.map
@@ -0,0 +1 @@
+{"version":3,"sources":["webpack://Feedback/webpack/universalModuleDefinition","webpack://Feedback/webpack/bootstrap","webpack://Feedback/external \"CoreHome\"","webpack://Feedback/external {\"commonjs\":\"vue\",\"commonjs2\":\"vue\",\"root\":\"Vue\"}","webpack://Feedback/./node_modules/@vue/cli-service/lib/commands/build/setPublicPath.js","webpack://Feedback/./plugins/Feedback/vue/src/RateFeature/RateFeature.vue","webpack://Feedback/./plugins/Feedback/vue/src/ReviewLinks/ReviewLinks.vue","webpack://Feedback/./plugins/Feedback/vue/src/ReviewLinks/ReviewLinks.vue?afec","webpack://Feedback/./plugins/Feedback/vue/src/ReviewLinks/ReviewLinks.vue?8b81","webpack://Feedback/./plugins/Feedback/vue/src/ReviewLinks/ReviewLinks.vue?1770","webpack://Feedback/./plugins/Feedback/vue/src/RateFeature/RateFeature.vue?7d7b","webpack://Feedback/./plugins/Feedback/vue/src/RateFeature/RateFeature.vue?09a5","webpack://Feedback/./plugins/Feedback/vue/src/RateFeature/RateFeature.vue?c2c1","webpack://Feedback/./plugins/Feedback/vue/src/RateFeature/RateFeature.adapter.ts","webpack://Feedback/./plugins/Feedback/vue/src/index.ts","webpack://Feedback/./node_modules/@vue/cli-service/lib/commands/build/entry-lib-no-default.js"],"names":[],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,CAAC;AACD,O;QCVA;QACA;;QAEA;QACA;;QAEA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;;QAEA;QACA;;QAEA;QACA;;QAEA;QACA;QACA;;;QAGA;QACA;;QAEA;QACA;;QAEA;QACA;QACA;QACA,0CAA0C,gCAAgC;QAC1E;QACA;;QAEA;QACA;QACA;QACA,wDAAwD,kBAAkB;QAC1E;QACA,iDAAiD,cAAc;QAC/D;;QAEA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA,yCAAyC,iCAAiC;QAC1E,gHAAgH,mBAAmB,EAAE;QACrI;QACA;;QAEA;QACA;QACA;QACA,2BAA2B,0BAA0B,EAAE;QACvD,iCAAiC,eAAe;QAChD;QACA;QACA;;QAEA;QACA,sDAAsD,+DAA+D;;QAErH;QACA;;;QAGA;QACA;;;;;;;;AClFA,mD;;;;;;;ACAA,mD;;;;;;;;;;;;;;;;ACAA;;AAEA;AACA;AACA,MAAM,KAAuC,EAAE,yBAQ5C;;AAEH;AACA;AACA,IAAI,qBAAuB;AAC3B;AACA;;AAEA;AACe,sDAAI;;;;;;;;;;;;ACYX,OAAK,EAAC;;;;;;;;;gCAKN,4EAAM,IAAN,EAAM,IAAN,EAAM,IAAN,EAAM,EAAN,C;;;AACK,OAAK,EAAC;;;;;AAoBX,OAAK,EAAC;;;;;;;;;;;+EApDZ,4EAmEM,KAnEN,EAmEM;AAlEH,SAAK,EAAE,eAAS,2BAAT,EAAuC,eAAU,UAAV,CAAvC,CAkEJ;AAjEJ,SAAK,EAAC;AAiEF,GAnEN,E,CAIE,4EAgBM,KAhBN,EAgBM;AAfJ,SAAK,EAAC,eAeF;AAdC,gBAAU,sCAAE,gBAAQ,IAAV,CAcX;AAbC,gBAAU,sCAAE,gBAAQ,KAAV;AAaX,GAhBN,E,CAKE,4EAIE,KAJF,EAIE;AAHK,WAAK;AAAE;;AAAc,8BAAgB,IAAhB;AAAgB,KAAhC,CAGV;AAFA,SAAK,EAAC,WAEN;AADA,OAAG,EAAC;AACJ,GAJF,C,0EAKA,4EAKE,KALF,EAKE;AAJK,WAAK;AAAE;;AAAiB,8BAAgB,IAAhB;AAAgB,KAAnC,CAIV;AAHA,SAAK,EAAC,cAGN;AADA,OAAG,EAAC;AACJ,GALF,E,IAAA,E,GAAA,C,4DAGU,a,IAbZ,E,EAAA,C,EAiBA,qEA0Be,uBA1Bf,EA0Be;gBAzBJ,qBAyBI;+DAzBJ,wBAAgB,M,CAyBZ;AAxBZ,SAAG,sCAAE,mBAAF;AAwBS,GA1Bf,E;8EAIE,MAqBM,CArBN,4EAqBM,KArBN,cAqBM,CAlBJ,4EAAoE,IAApE,EAAoE,IAApE,EAAoE,yEAA7D,eAAS,mCAAT,EAA+C,UAA/C,CAA6D,CAApE,EAA2D,CAA3D,CAkBI,EAjBK,S,0EAAT,4EAA0E,GAA1E,EAA0E,UAA1E,EAA0E,yEAAxD,eAAS,sCAAT,CAAwD,CAA1E,EAA2B,CAA3B,C,yFAiBI,E,CAhBM,S,0EAAV,4EAA8E,GAA9E,EAA8E,UAA9E,EAA8E,yEAA3D,eAAS,yCAAT,CAA2D,CAA9E,EAA4B,CAA5B,C,yFAgBI,EAfJ,UAeI,EAdJ,4EAEM,KAFN,cAEM,C,wEADJ,4EAAsC,UAAtC,EAAsC;iEAAnB,uBAAe,M;AAAI,KAAtC,E,IAAA,E,GAAA,C,iEAAmB,oB,GACf,CAFN,CAcI,EAXJ,4EAKE,OALF,EAKE;AAJA,UAAI,EAAC,QAIL;AAHC,WAAK,EAAE,eAAS,6CAAT,CAGR;AAFC,WAAK,EAAE,eAAS,uBAAT,CAER;AADA,UAAI,EAAC;AACL,KALF,E,IAAA,E,CAAA,E,UAAA,CAWI,EALJ,4EAIE,OAJF,EAIE;AAHA,UAAI,EAAC,QAGL;AAFA,UAAI,EAAC,QAEL;AADC,WAAK,EAAE,eAAS,gBAAT;AACR,KAJF,E,IAAA,E,CAAA,E,UAAA,CAKI,CArBN,CAqBM,C;;GAzBR,E,CAAA,E,cAAA,C,EA2BA,qEAkBe,uBAlBf,EAkBe;gBAjBJ,eAiBI;+DAjBJ,kBAAU,M;AAiBN,GAlBf,E;8EAGE,MAcM,CAdN,4EAcM,KAdN,cAcM,CAXJ,4EAAoD,IAApD,EAAoD,IAApD,EAAoD,yEAA7C,eAAS,mBAAT,EAA+B,UAA/B,CAA6C,CAApD,EAA2C,CAA3C,CAWI,EATI,S,0EADR,4EAIM,KAJN,EAIM,WAJN,EAIM,CADJ,qEAAe,sBAAf,CACI,CAJN,C,yFAUI,EALJ,4EAIE,OAJF,EAIE;AAHA,UAAI,EAAC,QAGL;AAFC,WAAK,EAAE,eAAS,YAAT,CAER;AADA,UAAI,EAAC;AACL,KAJF,E,IAAA,E,CAAA,E,WAAA,CAKI,CAdN,CAcM,C;;GAjBR,E,CAAA,E,cAAA,C,CAhDF,E,CAAA,E,UAAA,C;;;;;;;ACCK,OAAK,EAAC;;;;;;+EAAX,4EA0EM,KA1EN,sDA0EM,CAzEJ,4EAAqE,GAArE,EAAqE,IAArE,EAAqE,yEAA/D,eAAS,6CAAT,CAA+D,CAArE,EAAe,CAAf,CAyEI,EAzEiE,kDAyEjE,CA1EN,C;;;;;ACPF;AAEe,+IAAe,CAAC,EAAD,CAA9B,E;;ACHkmB,C;;ACA1hB;AACV;AACL;AACzD,kCAAM,UAAU,+CAAM;;AAEP,kF;;ACJf;AACA;AACA;AAEe,+IAAe,CAAC;AAC7B,OAAK,EAAE;AACL,SAAK,EAAE;AADF,GADsB;AAI7B,YAAU,EAAE;AACV,oDADU;AAEV,4BAAW;AAFD,GAJiB;;AAQ7B,MAAI;AACF,WAAO;AACL,UAAI,EAAE,KADD;AAEL,gBAAU,EAAE,KAFP;AAGL,cAAQ,EAAE,KAHL;AAIL,sBAAgB,EAAE,KAJb;AAKL,qBAAe,EAAE;AALZ,KAAP;AAOD,GAhB4B;;AAiB7B,SAAO,EAAE;AACP,kBAAc;AACZ,WAAK,IAAL,GAAY,KAAZ;AACD,KAHM;;AAIP,eAAW;AACT,WAAK,IAAL,GAAY,IAAZ;AACD,KANM;;AAOP,gBAAY;AACV,sCAAU,CAAC,KAAX,CAAiB;AACf,cAAM,EAAE,iCADO;AAEf,mBAAW,EAAE,KAAK,KAFH;AAGf,YAAI,EAAE,KAAK,IAAL,GAAY,GAAZ,GAAkB,GAHT;AAIf,eAAO,EAAE,KAAK;AAJC,OAAjB;AAMA,WAAK,UAAL,GAAkB,IAAlB;AACD;;AAfM;AAjBoB,CAAD,CAA9B,E;;ACLkmB,C;;ACA1hB;AACV;AACL;AACzD,kCAAM,UAAU,MAAM;;AAEP,kF;;ACLf;;;;;AAKG;AAEH;AACA;AAEe,4GAAsB,CAAC;AACpC,WAAS,EAAE,WADyB;AAEpC,OAAK,EAAE;AACL,SAAK,EAAE;AACL,mBAAa,EAAE;AADV;AADF,GAF6B;AAOpC,eAAa,EAAE;AAPqB,CAAD,CAArC,E;;ACVA;;;;;AAKG;AAEH;AAEA;;;ACTwB;AACF","file":"Feedback.umd.js","sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory(require(\"CoreHome\"), require(\"vue\"));\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine([\"CoreHome\", ], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"Feedback\"] = factory(require(\"CoreHome\"), require(\"vue\"));\n\telse\n\t\troot[\"Feedback\"] = factory(root[\"CoreHome\"], root[\"Vue\"]);\n})((typeof self !== 'undefined' ? self : this), function(__WEBPACK_EXTERNAL_MODULE__19dc__, __WEBPACK_EXTERNAL_MODULE__8bbf__) {\nreturn "," \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"plugins/Feedback/vue/dist/\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = \"fae3\");\n","module.exports = __WEBPACK_EXTERNAL_MODULE__19dc__;","module.exports = __WEBPACK_EXTERNAL_MODULE__8bbf__;","// This file is imported into lib/wc client bundles.\n\nif (typeof window !== 'undefined') {\n var currentScript = window.document.currentScript\n if (process.env.NEED_CURRENTSCRIPT_POLYFILL) {\n var getCurrentScript = require('@soda/get-current-script')\n currentScript = getCurrentScript()\n\n // for backward compatibility, because previously we directly included the polyfill\n if (!('currentScript' in document)) {\n Object.defineProperty(document, 'currentScript', { get: getCurrentScript })\n }\n }\n\n var src = currentScript && currentScript.src.match(/(.+\\/)[^/]+\\.js(\\?.*)?$/)\n if (src) {\n __webpack_public_path__ = src[1] // eslint-disable-line\n }\n}\n\n// Indicate to webpack that this file can be concatenated\nexport default null\n","<!--\n Matomo - free/libre analytics platform\n @link https://matomo.org\n @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later\n-->\n\n<template>\n <div\n :title=\"translate('Feedback_RateFeatureTitle', $sanitize(title))\"\n class=\"ratefeature\"\n >\n <div\n class=\"iconContainer\"\n v-on:mouseenter=\"expanded = true\"\n v-on:mouseleave=\"expanded = false\"\n >\n <img\n v-on:click=\"likeFeature();showFeedbackForm=true\"\n class=\"like-icon\"\n src=\"plugins/Feedback/vue/src/RateFeature/thumbs-up.png\"\n />\n <img\n v-on:click=\"dislikeFeature();showFeedbackForm=true\"\n class=\"dislike-icon\"\n v-show=\"expanded\"\n src=\"plugins/Feedback/vue/src/RateFeature/thumbs-down.png\"\n />\n </div>\n <MatomoDialog\n v-model=\"showFeedbackForm\"\n @yes=\"sendFeedback()\"\n >\n <div\n class=\"ui-confirm ratefeatureDialog\"\n >\n <h2>{{ translate('Feedback_RateFeatureThankYouTitle', title) }}</h2>\n <p v-if=\"like\">{{ translate('Feedback_RateFeatureLeaveMessageLike') }}</p>\n <p v-if=\"!like\">{{ translate('Feedback_RateFeatureLeaveMessageDislike') }}</p>\n <br />\n <div class=\"messageContainer\">\n <textarea v-model=\"feedbackMessage\" />\n </div>\n <input\n type=\"button\"\n :title=\"translate('Feedback_RateFeatureSendFeedbackInformation')\"\n :value=\"translate('Feedback_SendFeedback')\"\n role=\"yes\"\n />\n <input\n type=\"button\"\n role=\"cancel\"\n :value=\"translate('General_Cancel')\"\n />\n </div>\n </MatomoDialog>\n <MatomoDialog\n v-model=\"ratingDone\"\n >\n <div\n class=\"ui-confirm ratefeatureDialog\"\n >\n <h2>{{ translate('Feedback_ThankYou', title) }}</h2>\n <div\n v-if=\"like\"\n >\n <ReviewLinks />\n </div>\n <input\n type=\"button\"\n :value=\"translate('General_Ok')\"\n role=\"yes\"\n />\n </div>\n </MatomoDialog>\n </div>\n</template>\n\n<script lang=\"ts\">\nimport { defineComponent } from 'vue';\nimport { MatomoDialog, AjaxHelper } from 'CoreHome';\nimport ReviewLinks from '../ReviewLinks/ReviewLinks.vue';\n\nexport default defineComponent({\n props: {\n title: String,\n },\n components: {\n MatomoDialog,\n ReviewLinks,\n },\n data() {\n return {\n like: false,\n ratingDone: false,\n expanded: false,\n showFeedbackForm: false,\n feedbackMessage: '',\n };\n },\n methods: {\n dislikeFeature() {\n this.like = false;\n },\n likeFeature() {\n this.like = true;\n },\n sendFeedback() {\n AjaxHelper.fetch({\n method: 'Feedback.sendFeedbackForFeature',\n featureName: this.title,\n like: this.like ? '1' : '0',\n message: this.feedbackMessage,\n });\n this.ratingDone = true;\n },\n },\n});\n</script>\n","<!--\n Matomo - free/libre analytics platform\n\n @link https://matomo.org\n @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later\n-->\n\n<template>\n <div class=\"requestReview\">\n <p>{{ translate('Feedback_PleaseLeaveExternalReviewForMatomo') }}</p><br><br>\n <div class=\"review-links\">\n <div class=\"review-link\">\n <a\n href=\"https://www.capterra.com/p/182627/Matomo-Analytics/\"\n target=\"_blank\"\n >\n <div class=\"image\">\n <img\n loading=\"lazy\"\n src=\"plugins/Feedback/images/capterra.svg\"\n />\n </div>\n <div class=\"link\">Capterra</div>\n </a>\n </div>\n <div class=\"review-link\">\n <a\n href=\"https://www.g2crowd.com/products/matomo-formerly-piwik/details\"\n target=\"_blank\"\n >\n <div class=\"image\">\n <img\n loading=\"lazy\"\n src=\"plugins/Feedback/images/g2crowd.svg\"\n />\n </div>\n <div class=\"link\">G2 Crowd</div>\n </a>\n </div>\n <div class=\"review-link\">\n <a\n href=\"https://www.producthunt.com/posts/matomo-2\"\n target=\"_blank\"\n >\n <div class=\"image\">\n <img\n loading=\"lazy\"\n src=\"plugins/Feedback/images/producthunt.svg\"\n />\n </div>\n <div class=\"link\">Product Hunt</div>\n </a>\n </div>\n <div class=\"review-link\">\n <a\n href=\"https://www.saasworthy.com/product/matomo\"\n target=\"_blank\"\n >\n <div class=\"image\">\n <img\n loading=\"lazy\"\n src=\"plugins/Feedback/images/saasworthy.png\"\n />\n </div>\n <div class=\"link\">SaaSworthy</div>\n </a>\n </div>\n <div class=\"review-link\">\n <a\n href=\"https://www.trustradius.com/products/matomo/reviews\"\n target=\"_blank\"\n >\n <div class=\"image\">\n <img\n loading=\"lazy\"\n src=\"plugins/Feedback/images/trustradius.svg\"\n />\n </div>\n <div class=\"link\">TrustRadius</div>\n </a>\n </div>\n </div>\n </div>\n</template>\n\n<script lang=\"ts\">\nimport { defineComponent } from 'vue';\n\nexport default defineComponent({});\n</script>\n","\nimport { defineComponent } from 'vue';\n\nexport default defineComponent({});\n","export { default } from \"-!../../../../../node_modules/@vue/cli-plugin-typescript/node_modules/cache-loader/dist/cjs.js??ref--14-0!../../../../../node_modules/@vue/cli-plugin-typescript/node_modules/thread-loader/dist/cjs.js!../../../../../node_modules/babel-loader/lib/index.js!../../../../../node_modules/@vue/cli-plugin-typescript/node_modules/ts-loader/index.js??ref--14-3!../../../../../node_modules/@vue/cli-service/node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/index.js??ref--0-1!./ReviewLinks.vue?vue&type=script&lang=ts\"; export * from \"-!../../../../../node_modules/@vue/cli-plugin-typescript/node_modules/cache-loader/dist/cjs.js??ref--14-0!../../../../../node_modules/@vue/cli-plugin-typescript/node_modules/thread-loader/dist/cjs.js!../../../../../node_modules/babel-loader/lib/index.js!../../../../../node_modules/@vue/cli-plugin-typescript/node_modules/ts-loader/index.js??ref--14-3!../../../../../node_modules/@vue/cli-service/node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/index.js??ref--0-1!./ReviewLinks.vue?vue&type=script&lang=ts\"","import { render } from \"./ReviewLinks.vue?vue&type=template&id=4471fc41\"\nimport script from \"./ReviewLinks.vue?vue&type=script&lang=ts\"\nexport * from \"./ReviewLinks.vue?vue&type=script&lang=ts\"\nscript.render = render\n\nexport default script","\nimport { defineComponent } from 'vue';\nimport { MatomoDialog, AjaxHelper } from 'CoreHome';\nimport ReviewLinks from '../ReviewLinks/ReviewLinks.vue';\n\nexport default defineComponent({\n props: {\n title: String,\n },\n components: {\n MatomoDialog,\n ReviewLinks,\n },\n data() {\n return {\n like: false,\n ratingDone: false,\n expanded: false,\n showFeedbackForm: false,\n feedbackMessage: '',\n };\n },\n methods: {\n dislikeFeature() {\n this.like = false;\n },\n likeFeature() {\n this.like = true;\n },\n sendFeedback() {\n AjaxHelper.fetch({\n method: 'Feedback.sendFeedbackForFeature',\n featureName: this.title,\n like: this.like ? '1' : '0',\n message: this.feedbackMessage,\n });\n this.ratingDone = true;\n },\n },\n});\n","export { default } from \"-!../../../../../node_modules/@vue/cli-plugin-typescript/node_modules/cache-loader/dist/cjs.js??ref--14-0!../../../../../node_modules/@vue/cli-plugin-typescript/node_modules/thread-loader/dist/cjs.js!../../../../../node_modules/babel-loader/lib/index.js!../../../../../node_modules/@vue/cli-plugin-typescript/node_modules/ts-loader/index.js??ref--14-3!../../../../../node_modules/@vue/cli-service/node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/index.js??ref--0-1!./RateFeature.vue?vue&type=script&lang=ts\"; export * from \"-!../../../../../node_modules/@vue/cli-plugin-typescript/node_modules/cache-loader/dist/cjs.js??ref--14-0!../../../../../node_modules/@vue/cli-plugin-typescript/node_modules/thread-loader/dist/cjs.js!../../../../../node_modules/babel-loader/lib/index.js!../../../../../node_modules/@vue/cli-plugin-typescript/node_modules/ts-loader/index.js??ref--14-3!../../../../../node_modules/@vue/cli-service/node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../../node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/index.js??ref--0-1!./RateFeature.vue?vue&type=script&lang=ts\"","import { render } from \"./RateFeature.vue?vue&type=template&id=65bd066a\"\nimport script from \"./RateFeature.vue?vue&type=script&lang=ts\"\nexport * from \"./RateFeature.vue?vue&type=script&lang=ts\"\nscript.render = render\n\nexport default script","/*!\n * Matomo - free/libre analytics platform\n *\n * @link https://matomo.org\n * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later\n */\n\nimport { createAngularJsAdapter } from 'CoreHome';\nimport RateFeature from './RateFeature.vue';\n\nexport default createAngularJsAdapter({\n component: RateFeature,\n scope: {\n title: {\n angularJsBind: '@',\n },\n },\n directiveName: 'piwikRateFeature',\n});\n","/*!\n * Matomo - free/libre analytics platform\n *\n * @link https://matomo.org\n * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later\n */\n\nimport './RateFeature/RateFeature.adapter';\n\nexport { default as ReviewLinks } from './ReviewLinks/ReviewLinks.vue';\nexport { default as RateFeature } from './RateFeature/RateFeature.vue';\n","import './setPublicPath'\nexport * from '~entry'\n"],"sourceRoot":""} \ No newline at end of file
diff --git a/plugins/Feedback/vue/dist/Feedback.umd.min.js b/plugins/Feedback/vue/dist/Feedback.umd.min.js
new file mode 100644
index 0000000000..2c4e753504
--- /dev/null
+++ b/plugins/Feedback/vue/dist/Feedback.umd.min.js
@@ -0,0 +1,8 @@
+(function(e,t){"object"===typeof exports&&"object"===typeof module?module.exports=t(require("CoreHome"),require("vue")):"function"===typeof define&&define.amd?define(["CoreHome"],t):"object"===typeof exports?exports["Feedback"]=t(require("CoreHome"),require("vue")):e["Feedback"]=t(e["CoreHome"],e["Vue"])})("undefined"!==typeof self?self:this,(function(e,t){return function(e){var t={};function a(n){if(t[n])return t[n].exports;var r=t[n]={i:n,l:!1,exports:{}};return e[n].call(r.exports,r,r.exports,a),r.l=!0,r.exports}return a.m=e,a.c=t,a.d=function(e,t,n){a.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},a.r=function(e){"undefined"!==typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},a.t=function(e,t){if(1&t&&(e=a(e)),8&t)return e;if(4&t&&"object"===typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(a.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var r in e)a.d(n,r,function(t){return e[t]}.bind(null,r));return n},a.n=function(e){var t=e&&e.__esModule?function(){return e["default"]}:function(){return e};return a.d(t,"a",t),t},a.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},a.p="plugins/Feedback/vue/dist/",a(a.s="fae3")}({"19dc":function(t,a){t.exports=e},"8bbf":function(e,a){e.exports=t},fae3:function(e,t,a){"use strict";if(a.r(t),a.d(t,"ReviewLinks",(function(){return h})),a.d(t,"RateFeature",(function(){return V})),"undefined"!==typeof window){var n=window.document.currentScript,r=n&&n.src.match(/(.+\/)[^/]+\.js(\?.*)?$/);r&&(a.p=r[1])}var i=a("19dc"),o=a("8bbf");const c=["title"],l={class:"ui-confirm ratefeatureDialog"},s={key:0},d={key:1},u=Object(o["createElementVNode"])("br",null,null,-1),b={class:"messageContainer"},m=["title","value"],p=["value"],v={class:"ui-confirm ratefeatureDialog"},k={key:0},f=["value"];function g(e,t,a,n,r,i){const g=Object(o["resolveComponent"])("MatomoDialog"),j=Object(o["resolveComponent"])("ReviewLinks");return Object(o["openBlock"])(),Object(o["createElementBlock"])("div",{title:e.translate("Feedback_RateFeatureTitle",e.$sanitize(e.title)),class:"ratefeature"},[Object(o["createElementVNode"])("div",{class:"iconContainer",onMouseenter:t[2]||(t[2]=t=>e.expanded=!0),onMouseleave:t[3]||(t[3]=t=>e.expanded=!1)},[Object(o["createElementVNode"])("img",{onClick:t[0]||(t[0]=t=>{e.likeFeature(),e.showFeedbackForm=!0}),class:"like-icon",src:"plugins/Feedback/vue/src/RateFeature/thumbs-up.png"}),Object(o["withDirectives"])(Object(o["createElementVNode"])("img",{onClick:t[1]||(t[1]=t=>{e.dislikeFeature(),e.showFeedbackForm=!0}),class:"dislike-icon",src:"plugins/Feedback/vue/src/RateFeature/thumbs-down.png"},null,512),[[o["vShow"],e.expanded]])],32),Object(o["createVNode"])(g,{modelValue:e.showFeedbackForm,"onUpdate:modelValue":t[5]||(t[5]=t=>e.showFeedbackForm=t),onYes:t[6]||(t[6]=t=>e.sendFeedback())},{default:Object(o["withCtx"])(()=>[Object(o["createElementVNode"])("div",l,[Object(o["createElementVNode"])("h2",null,Object(o["toDisplayString"])(e.translate("Feedback_RateFeatureThankYouTitle",e.title)),1),e.like?(Object(o["openBlock"])(),Object(o["createElementBlock"])("p",s,Object(o["toDisplayString"])(e.translate("Feedback_RateFeatureLeaveMessageLike")),1)):Object(o["createCommentVNode"])("",!0),e.like?Object(o["createCommentVNode"])("",!0):(Object(o["openBlock"])(),Object(o["createElementBlock"])("p",d,Object(o["toDisplayString"])(e.translate("Feedback_RateFeatureLeaveMessageDislike")),1)),u,Object(o["createElementVNode"])("div",b,[Object(o["withDirectives"])(Object(o["createElementVNode"])("textarea",{"onUpdate:modelValue":t[4]||(t[4]=t=>e.feedbackMessage=t)},null,512),[[o["vModelText"],e.feedbackMessage]])]),Object(o["createElementVNode"])("input",{type:"button",title:e.translate("Feedback_RateFeatureSendFeedbackInformation"),value:e.translate("Feedback_SendFeedback"),role:"yes"},null,8,m),Object(o["createElementVNode"])("input",{type:"button",role:"cancel",value:e.translate("General_Cancel")},null,8,p)])]),_:1},8,["modelValue"]),Object(o["createVNode"])(g,{modelValue:e.ratingDone,"onUpdate:modelValue":t[7]||(t[7]=t=>e.ratingDone=t)},{default:Object(o["withCtx"])(()=>[Object(o["createElementVNode"])("div",v,[Object(o["createElementVNode"])("h2",null,Object(o["toDisplayString"])(e.translate("Feedback_ThankYou",e.title)),1),e.like?(Object(o["openBlock"])(),Object(o["createElementBlock"])("div",k,[Object(o["createVNode"])(j)])):Object(o["createCommentVNode"])("",!0),Object(o["createElementVNode"])("input",{type:"button",value:e.translate("General_Ok"),role:"yes"},null,8,f)])]),_:1},8,["modelValue"])],8,c)}const j={class:"requestReview"},O=Object(o["createStaticVNode"])('<br><br><div class="review-links"><div class="review-link"><a href="https://www.capterra.com/p/182627/Matomo-Analytics/" target="_blank"><div class="image"><img loading="lazy" src="plugins/Feedback/images/capterra.svg"></div><div class="link">Capterra</div></a></div><div class="review-link"><a href="https://www.g2crowd.com/products/matomo-formerly-piwik/details" target="_blank"><div class="image"><img loading="lazy" src="plugins/Feedback/images/g2crowd.svg"></div><div class="link">G2 Crowd</div></a></div><div class="review-link"><a href="https://www.producthunt.com/posts/matomo-2" target="_blank"><div class="image"><img loading="lazy" src="plugins/Feedback/images/producthunt.svg"></div><div class="link">Product Hunt</div></a></div><div class="review-link"><a href="https://www.saasworthy.com/product/matomo" target="_blank"><div class="image"><img loading="lazy" src="plugins/Feedback/images/saasworthy.png"></div><div class="link">SaaSworthy</div></a></div><div class="review-link"><a href="https://www.trustradius.com/products/matomo/reviews" target="_blank"><div class="image"><img loading="lazy" src="plugins/Feedback/images/trustradius.svg"></div><div class="link">TrustRadius</div></a></div></div>',3);function w(e,t,a,n,r,i){return Object(o["openBlock"])(),Object(o["createElementBlock"])("div",j,[Object(o["createElementVNode"])("p",null,Object(o["toDisplayString"])(e.translate("Feedback_PleaseLeaveExternalReviewForMatomo")),1),O])}var F=Object(o["defineComponent"])({});F.render=w;var h=F,y=Object(o["defineComponent"])({props:{title:String},components:{MatomoDialog:i["MatomoDialog"],ReviewLinks:h},data(){return{like:!1,ratingDone:!1,expanded:!1,showFeedbackForm:!1,feedbackMessage:""}},methods:{dislikeFeature(){this.like=!1},likeFeature(){this.like=!0},sendFeedback(){i["AjaxHelper"].fetch({method:"Feedback.sendFeedbackForFeature",featureName:this.title,like:this.like?"1":"0",message:this.feedbackMessage}),this.ratingDone=!0}}});y.render=g;var V=y;
+/*!
+ * Matomo - free/libre analytics platform
+ *
+ * @link https://matomo.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ */Object(i["createAngularJsAdapter"])({component:V,scope:{title:{angularJsBind:"@"}},directiveName:"piwikRateFeature"})}})}));
+//# sourceMappingURL=Feedback.umd.min.js.map \ No newline at end of file
diff --git a/plugins/Feedback/vue/dist/Feedback.umd.min.js.map b/plugins/Feedback/vue/dist/Feedback.umd.min.js.map
new file mode 100644
index 0000000000..c84386e2fe
--- /dev/null
+++ b/plugins/Feedback/vue/dist/Feedback.umd.min.js.map
@@ -0,0 +1 @@
+{"version":3,"sources":["webpack://Feedback/webpack/universalModuleDefinition","webpack://Feedback/webpack/bootstrap","webpack://Feedback/external \"CoreHome\"","webpack://Feedback/external {\"commonjs\":\"vue\",\"commonjs2\":\"vue\",\"root\":\"Vue\"}","webpack://Feedback/./node_modules/@vue/cli-service/lib/commands/build/setPublicPath.js","webpack://Feedback/./plugins/Feedback/vue/src/RateFeature/RateFeature.vue","webpack://Feedback/./plugins/Feedback/vue/src/ReviewLinks/ReviewLinks.vue","webpack://Feedback/./plugins/Feedback/vue/src/ReviewLinks/ReviewLinks.vue?afec","webpack://Feedback/./plugins/Feedback/vue/src/ReviewLinks/ReviewLinks.vue?1770","webpack://Feedback/./plugins/Feedback/vue/src/RateFeature/RateFeature.vue?7d7b","webpack://Feedback/./plugins/Feedback/vue/src/RateFeature/RateFeature.vue?c2c1","webpack://Feedback/./plugins/Feedback/vue/src/RateFeature/RateFeature.adapter.ts"],"names":["root","factory","exports","module","require","define","amd","self","this","__WEBPACK_EXTERNAL_MODULE__19dc__","__WEBPACK_EXTERNAL_MODULE__8bbf__","installedModules","__webpack_require__","moduleId","i","l","modules","call","m","c","d","name","getter","o","Object","defineProperty","enumerable","get","r","Symbol","toStringTag","value","t","mode","__esModule","ns","create","key","bind","n","object","property","prototype","hasOwnProperty","p","s","window","currentScript","document","src","match","class","title","translate","$sanitize","expanded","likeFeature","showFeedbackForm","dislikeFeature","sendFeedback","like","feedbackMessage","type","role","ratingDone","render","props","String","components","MatomoDialog","ReviewLinks","methods","fetch","method","featureName","message","component","RateFeature","scope","angularJsBind","directiveName"],"mappings":"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","file":"Feedback.umd.min.js","sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory(require(\"CoreHome\"), require(\"vue\"));\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine([\"CoreHome\", ], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"Feedback\"] = factory(require(\"CoreHome\"), require(\"vue\"));\n\telse\n\t\troot[\"Feedback\"] = factory(root[\"CoreHome\"], root[\"Vue\"]);\n})((typeof self !== 'undefined' ? self : this), function(__WEBPACK_EXTERNAL_MODULE__19dc__, __WEBPACK_EXTERNAL_MODULE__8bbf__) {\nreturn "," \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"plugins/Feedback/vue/dist/\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = \"fae3\");\n","module.exports = __WEBPACK_EXTERNAL_MODULE__19dc__;","module.exports = __WEBPACK_EXTERNAL_MODULE__8bbf__;","// This file is imported into lib/wc client bundles.\n\nif (typeof window !== 'undefined') {\n var currentScript = window.document.currentScript\n if (process.env.NEED_CURRENTSCRIPT_POLYFILL) {\n var getCurrentScript = require('@soda/get-current-script')\n currentScript = getCurrentScript()\n\n // for backward compatibility, because previously we directly included the polyfill\n if (!('currentScript' in document)) {\n Object.defineProperty(document, 'currentScript', { get: getCurrentScript })\n }\n }\n\n var src = currentScript && currentScript.src.match(/(.+\\/)[^/]+\\.js(\\?.*)?$/)\n if (src) {\n __webpack_public_path__ = src[1] // eslint-disable-line\n }\n}\n\n// Indicate to webpack that this file can be concatenated\nexport default null\n","<!--\n Matomo - free/libre analytics platform\n @link https://matomo.org\n @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later\n-->\n\n<template>\n <div\n :title=\"translate('Feedback_RateFeatureTitle', $sanitize(title))\"\n class=\"ratefeature\"\n >\n <div\n class=\"iconContainer\"\n v-on:mouseenter=\"expanded = true\"\n v-on:mouseleave=\"expanded = false\"\n >\n <img\n v-on:click=\"likeFeature();showFeedbackForm=true\"\n class=\"like-icon\"\n src=\"plugins/Feedback/vue/src/RateFeature/thumbs-up.png\"\n />\n <img\n v-on:click=\"dislikeFeature();showFeedbackForm=true\"\n class=\"dislike-icon\"\n v-show=\"expanded\"\n src=\"plugins/Feedback/vue/src/RateFeature/thumbs-down.png\"\n />\n </div>\n <MatomoDialog\n v-model=\"showFeedbackForm\"\n @yes=\"sendFeedback()\"\n >\n <div\n class=\"ui-confirm ratefeatureDialog\"\n >\n <h2>{{ translate('Feedback_RateFeatureThankYouTitle', title) }}</h2>\n <p v-if=\"like\">{{ translate('Feedback_RateFeatureLeaveMessageLike') }}</p>\n <p v-if=\"!like\">{{ translate('Feedback_RateFeatureLeaveMessageDislike') }}</p>\n <br />\n <div class=\"messageContainer\">\n <textarea v-model=\"feedbackMessage\" />\n </div>\n <input\n type=\"button\"\n :title=\"translate('Feedback_RateFeatureSendFeedbackInformation')\"\n :value=\"translate('Feedback_SendFeedback')\"\n role=\"yes\"\n />\n <input\n type=\"button\"\n role=\"cancel\"\n :value=\"translate('General_Cancel')\"\n />\n </div>\n </MatomoDialog>\n <MatomoDialog\n v-model=\"ratingDone\"\n >\n <div\n class=\"ui-confirm ratefeatureDialog\"\n >\n <h2>{{ translate('Feedback_ThankYou', title) }}</h2>\n <div\n v-if=\"like\"\n >\n <ReviewLinks />\n </div>\n <input\n type=\"button\"\n :value=\"translate('General_Ok')\"\n role=\"yes\"\n />\n </div>\n </MatomoDialog>\n </div>\n</template>\n\n<script lang=\"ts\">\nimport { defineComponent } from 'vue';\nimport { MatomoDialog, AjaxHelper } from 'CoreHome';\nimport ReviewLinks from '../ReviewLinks/ReviewLinks.vue';\n\nexport default defineComponent({\n props: {\n title: String,\n },\n components: {\n MatomoDialog,\n ReviewLinks,\n },\n data() {\n return {\n like: false,\n ratingDone: false,\n expanded: false,\n showFeedbackForm: false,\n feedbackMessage: '',\n };\n },\n methods: {\n dislikeFeature() {\n this.like = false;\n },\n likeFeature() {\n this.like = true;\n },\n sendFeedback() {\n AjaxHelper.fetch({\n method: 'Feedback.sendFeedbackForFeature',\n featureName: this.title,\n like: this.like ? '1' : '0',\n message: this.feedbackMessage,\n });\n this.ratingDone = true;\n },\n },\n});\n</script>\n","<!--\n Matomo - free/libre analytics platform\n\n @link https://matomo.org\n @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later\n-->\n\n<template>\n <div class=\"requestReview\">\n <p>{{ translate('Feedback_PleaseLeaveExternalReviewForMatomo') }}</p><br><br>\n <div class=\"review-links\">\n <div class=\"review-link\">\n <a\n href=\"https://www.capterra.com/p/182627/Matomo-Analytics/\"\n target=\"_blank\"\n >\n <div class=\"image\">\n <img\n loading=\"lazy\"\n src=\"plugins/Feedback/images/capterra.svg\"\n />\n </div>\n <div class=\"link\">Capterra</div>\n </a>\n </div>\n <div class=\"review-link\">\n <a\n href=\"https://www.g2crowd.com/products/matomo-formerly-piwik/details\"\n target=\"_blank\"\n >\n <div class=\"image\">\n <img\n loading=\"lazy\"\n src=\"plugins/Feedback/images/g2crowd.svg\"\n />\n </div>\n <div class=\"link\">G2 Crowd</div>\n </a>\n </div>\n <div class=\"review-link\">\n <a\n href=\"https://www.producthunt.com/posts/matomo-2\"\n target=\"_blank\"\n >\n <div class=\"image\">\n <img\n loading=\"lazy\"\n src=\"plugins/Feedback/images/producthunt.svg\"\n />\n </div>\n <div class=\"link\">Product Hunt</div>\n </a>\n </div>\n <div class=\"review-link\">\n <a\n href=\"https://www.saasworthy.com/product/matomo\"\n target=\"_blank\"\n >\n <div class=\"image\">\n <img\n loading=\"lazy\"\n src=\"plugins/Feedback/images/saasworthy.png\"\n />\n </div>\n <div class=\"link\">SaaSworthy</div>\n </a>\n </div>\n <div class=\"review-link\">\n <a\n href=\"https://www.trustradius.com/products/matomo/reviews\"\n target=\"_blank\"\n >\n <div class=\"image\">\n <img\n loading=\"lazy\"\n src=\"plugins/Feedback/images/trustradius.svg\"\n />\n </div>\n <div class=\"link\">TrustRadius</div>\n </a>\n </div>\n </div>\n </div>\n</template>\n\n<script lang=\"ts\">\nimport { defineComponent } from 'vue';\n\nexport default defineComponent({});\n</script>\n","\nimport { defineComponent } from 'vue';\n\nexport default defineComponent({});\n","import { render } from \"./ReviewLinks.vue?vue&type=template&id=4471fc41\"\nimport script from \"./ReviewLinks.vue?vue&type=script&lang=ts\"\nexport * from \"./ReviewLinks.vue?vue&type=script&lang=ts\"\nscript.render = render\n\nexport default script","\nimport { defineComponent } from 'vue';\nimport { MatomoDialog, AjaxHelper } from 'CoreHome';\nimport ReviewLinks from '../ReviewLinks/ReviewLinks.vue';\n\nexport default defineComponent({\n props: {\n title: String,\n },\n components: {\n MatomoDialog,\n ReviewLinks,\n },\n data() {\n return {\n like: false,\n ratingDone: false,\n expanded: false,\n showFeedbackForm: false,\n feedbackMessage: '',\n };\n },\n methods: {\n dislikeFeature() {\n this.like = false;\n },\n likeFeature() {\n this.like = true;\n },\n sendFeedback() {\n AjaxHelper.fetch({\n method: 'Feedback.sendFeedbackForFeature',\n featureName: this.title,\n like: this.like ? '1' : '0',\n message: this.feedbackMessage,\n });\n this.ratingDone = true;\n },\n },\n});\n","import { render } from \"./RateFeature.vue?vue&type=template&id=65bd066a\"\nimport script from \"./RateFeature.vue?vue&type=script&lang=ts\"\nexport * from \"./RateFeature.vue?vue&type=script&lang=ts\"\nscript.render = render\n\nexport default script","/*!\n * Matomo - free/libre analytics platform\n *\n * @link https://matomo.org\n * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later\n */\n\nimport { createAngularJsAdapter } from 'CoreHome';\nimport RateFeature from './RateFeature.vue';\n\nexport default createAngularJsAdapter({\n component: RateFeature,\n scope: {\n title: {\n angularJsBind: '@',\n },\n },\n directiveName: 'piwikRateFeature',\n});\n"],"sourceRoot":""} \ No newline at end of file
diff --git a/plugins/Feedback/vue/src/RateFeature/RateFeature.adapter.ts b/plugins/Feedback/vue/src/RateFeature/RateFeature.adapter.ts
new file mode 100644
index 0000000000..2af13ffc21
--- /dev/null
+++ b/plugins/Feedback/vue/src/RateFeature/RateFeature.adapter.ts
@@ -0,0 +1,19 @@
+/*!
+ * Matomo - free/libre analytics platform
+ *
+ * @link https://matomo.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ */
+
+import { createAngularJsAdapter } from 'CoreHome';
+import RateFeature from './RateFeature.vue';
+
+export default createAngularJsAdapter({
+ component: RateFeature,
+ scope: {
+ title: {
+ angularJsBind: '@',
+ },
+ },
+ directiveName: 'piwikRateFeature',
+});
diff --git a/plugins/Feedback/angularjs/ratefeature/ratefeature.directive.less b/plugins/Feedback/vue/src/RateFeature/RateFeature.less
index 83abd8970b..83abd8970b 100644
--- a/plugins/Feedback/angularjs/ratefeature/ratefeature.directive.less
+++ b/plugins/Feedback/vue/src/RateFeature/RateFeature.less
diff --git a/plugins/Feedback/vue/src/RateFeature/RateFeature.vue b/plugins/Feedback/vue/src/RateFeature/RateFeature.vue
new file mode 100644
index 0000000000..324142273f
--- /dev/null
+++ b/plugins/Feedback/vue/src/RateFeature/RateFeature.vue
@@ -0,0 +1,118 @@
+<!--
+ Matomo - free/libre analytics platform
+ @link https://matomo.org
+ @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+-->
+
+<template>
+ <div
+ :title="translate('Feedback_RateFeatureTitle', $sanitize(title))"
+ class="ratefeature"
+ >
+ <div
+ class="iconContainer"
+ v-on:mouseenter="expanded = true"
+ v-on:mouseleave="expanded = false"
+ >
+ <img
+ v-on:click="likeFeature();showFeedbackForm=true"
+ class="like-icon"
+ src="plugins/Feedback/vue/src/RateFeature/thumbs-up.png"
+ />
+ <img
+ v-on:click="dislikeFeature();showFeedbackForm=true"
+ class="dislike-icon"
+ v-show="expanded"
+ src="plugins/Feedback/vue/src/RateFeature/thumbs-down.png"
+ />
+ </div>
+ <MatomoDialog
+ v-model="showFeedbackForm"
+ @yes="sendFeedback()"
+ >
+ <div
+ class="ui-confirm ratefeatureDialog"
+ >
+ <h2>{{ translate('Feedback_RateFeatureThankYouTitle', title) }}</h2>
+ <p v-if="like">{{ translate('Feedback_RateFeatureLeaveMessageLike') }}</p>
+ <p v-if="!like">{{ translate('Feedback_RateFeatureLeaveMessageDislike') }}</p>
+ <br />
+ <div class="messageContainer">
+ <textarea v-model="feedbackMessage" />
+ </div>
+ <input
+ type="button"
+ :title="translate('Feedback_RateFeatureSendFeedbackInformation')"
+ :value="translate('Feedback_SendFeedback')"
+ role="yes"
+ />
+ <input
+ type="button"
+ role="cancel"
+ :value="translate('General_Cancel')"
+ />
+ </div>
+ </MatomoDialog>
+ <MatomoDialog
+ v-model="ratingDone"
+ >
+ <div
+ class="ui-confirm ratefeatureDialog"
+ >
+ <h2>{{ translate('Feedback_ThankYou', title) }}</h2>
+ <div
+ v-if="like"
+ >
+ <ReviewLinks />
+ </div>
+ <input
+ type="button"
+ :value="translate('General_Ok')"
+ role="yes"
+ />
+ </div>
+ </MatomoDialog>
+ </div>
+</template>
+
+<script lang="ts">
+import { defineComponent } from 'vue';
+import { MatomoDialog, AjaxHelper } from 'CoreHome';
+import ReviewLinks from '../ReviewLinks/ReviewLinks.vue';
+
+export default defineComponent({
+ props: {
+ title: String,
+ },
+ components: {
+ MatomoDialog,
+ ReviewLinks,
+ },
+ data() {
+ return {
+ like: false,
+ ratingDone: false,
+ expanded: false,
+ showFeedbackForm: false,
+ feedbackMessage: '',
+ };
+ },
+ methods: {
+ dislikeFeature() {
+ this.like = false;
+ },
+ likeFeature() {
+ this.like = true;
+ },
+ sendFeedback() {
+ AjaxHelper.fetch({
+ method: 'Feedback.sendFeedbackForFeature',
+ featureName: this.title,
+ like: this.like ? '1' : '0',
+ message: this.feedbackMessage,
+ });
+ this.ratingDone = true;
+ },
+ },
+});
+</script>
diff --git a/plugins/Feedback/angularjs/ratefeature/icon_license b/plugins/Feedback/vue/src/RateFeature/icon_license
index 78a631917a..78a631917a 100644
--- a/plugins/Feedback/angularjs/ratefeature/icon_license
+++ b/plugins/Feedback/vue/src/RateFeature/icon_license
diff --git a/plugins/Feedback/angularjs/ratefeature/thumbs-down.png b/plugins/Feedback/vue/src/RateFeature/thumbs-down.png
index c9ce204822..c9ce204822 100644
--- a/plugins/Feedback/angularjs/ratefeature/thumbs-down.png
+++ b/plugins/Feedback/vue/src/RateFeature/thumbs-down.png
Binary files differ
diff --git a/plugins/Feedback/angularjs/ratefeature/thumbs-up.png b/plugins/Feedback/vue/src/RateFeature/thumbs-up.png
index a94421bafe..a94421bafe 100644
--- a/plugins/Feedback/angularjs/ratefeature/thumbs-up.png
+++ b/plugins/Feedback/vue/src/RateFeature/thumbs-up.png
Binary files differ
diff --git a/plugins/Feedback/vue/src/ReviewLinks/ReviewLinks.vue b/plugins/Feedback/vue/src/ReviewLinks/ReviewLinks.vue
new file mode 100644
index 0000000000..fa65f8569f
--- /dev/null
+++ b/plugins/Feedback/vue/src/ReviewLinks/ReviewLinks.vue
@@ -0,0 +1,90 @@
+<!--
+ Matomo - free/libre analytics platform
+
+ @link https://matomo.org
+ @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+-->
+
+<template>
+ <div class="requestReview">
+ <p>{{ translate('Feedback_PleaseLeaveExternalReviewForMatomo') }}</p><br><br>
+ <div class="review-links">
+ <div class="review-link">
+ <a
+ href="https://www.capterra.com/p/182627/Matomo-Analytics/"
+ target="_blank"
+ >
+ <div class="image">
+ <img
+ loading="lazy"
+ src="plugins/Feedback/images/capterra.svg"
+ />
+ </div>
+ <div class="link">Capterra</div>
+ </a>
+ </div>
+ <div class="review-link">
+ <a
+ href="https://www.g2crowd.com/products/matomo-formerly-piwik/details"
+ target="_blank"
+ >
+ <div class="image">
+ <img
+ loading="lazy"
+ src="plugins/Feedback/images/g2crowd.svg"
+ />
+ </div>
+ <div class="link">G2 Crowd</div>
+ </a>
+ </div>
+ <div class="review-link">
+ <a
+ href="https://www.producthunt.com/posts/matomo-2"
+ target="_blank"
+ >
+ <div class="image">
+ <img
+ loading="lazy"
+ src="plugins/Feedback/images/producthunt.svg"
+ />
+ </div>
+ <div class="link">Product Hunt</div>
+ </a>
+ </div>
+ <div class="review-link">
+ <a
+ href="https://www.saasworthy.com/product/matomo"
+ target="_blank"
+ >
+ <div class="image">
+ <img
+ loading="lazy"
+ src="plugins/Feedback/images/saasworthy.png"
+ />
+ </div>
+ <div class="link">SaaSworthy</div>
+ </a>
+ </div>
+ <div class="review-link">
+ <a
+ href="https://www.trustradius.com/products/matomo/reviews"
+ target="_blank"
+ >
+ <div class="image">
+ <img
+ loading="lazy"
+ src="plugins/Feedback/images/trustradius.svg"
+ />
+ </div>
+ <div class="link">TrustRadius</div>
+ </a>
+ </div>
+ </div>
+ </div>
+</template>
+
+<script lang="ts">
+import { defineComponent } from 'vue';
+
+export default defineComponent({});
+</script>
diff --git a/plugins/Feedback/vue/src/index.ts b/plugins/Feedback/vue/src/index.ts
new file mode 100644
index 0000000000..5f37c3b890
--- /dev/null
+++ b/plugins/Feedback/vue/src/index.ts
@@ -0,0 +1,11 @@
+/*!
+ * Matomo - free/libre analytics platform
+ *
+ * @link https://matomo.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ */
+
+import './RateFeature/RateFeature.adapter';
+
+export { default as ReviewLinks } from './ReviewLinks/ReviewLinks.vue';
+export { default as RateFeature } from './RateFeature/RateFeature.vue';