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>2022-03-23 03:06:42 +0300
committerGitHub <noreply@github.com>2022-03-23 03:06:42 +0300
commit1a3d0de2d7a7b287de0acc04df7c586fe9f6a53d (patch)
treec891a1419dbf61fbc3f1cdc70c1fd764c50d23d0
parentbc5175b483a5c88b389761624f5b65dfbfc85978 (diff)
[Vue] Migrate sms-provider-credentials directive and ManageMobilePhoneNumbersController controller (#18972)
* start migrating sms provider credentials and ManageSmsProviderController * finish migrating code, get to build * get to work in the UI * fix UI test * Fix ui test selector. * fix UI test wait * add missing change * update expected screenshots
-rw-r--r--plugins/CoreHome/vue/dist/CoreHome.umd.js4
-rw-r--r--plugins/CoreHome/vue/dist/CoreHome.umd.min.js2
-rw-r--r--plugins/CoreHome/vue/src/AjaxHelper/AjaxHelper.ts4
-rw-r--r--plugins/MobileMessaging/Controller.php8
-rw-r--r--plugins/MobileMessaging/MobileMessaging.php10
-rw-r--r--plugins/MobileMessaging/angularjs/sms-provider-credentials.directive.js2
-rw-r--r--plugins/MobileMessaging/templates/macros.twig63
-rw-r--r--plugins/MobileMessaging/vue/dist/MobileMessaging.umd.js546
-rw-r--r--plugins/MobileMessaging/vue/dist/MobileMessaging.umd.min.js14
-rw-r--r--plugins/MobileMessaging/vue/dist/umd.metadata.json6
-rw-r--r--plugins/MobileMessaging/vue/src/ManageSmsProvider/ManageSmsProvider.vue208
-rw-r--r--plugins/MobileMessaging/vue/src/SmsProviderCredentials/SmsProviderCredentials.adapter.ts69
-rw-r--r--plugins/MobileMessaging/vue/src/SmsProviderCredentials/SmsProviderCredentials.vue82
-rw-r--r--plugins/MobileMessaging/vue/src/index.ts11
-rw-r--r--plugins/Morpheus/javascripts/piwikHelper.js3
-rw-r--r--tests/UI/expected-screenshots/UIIntegrationTest_admin_settings_mobilemessaging_provider.png4
-rw-r--r--tests/UI/specs/UIIntegration_spec.js5
17 files changed, 973 insertions, 68 deletions
diff --git a/plugins/CoreHome/vue/dist/CoreHome.umd.js b/plugins/CoreHome/vue/dist/CoreHome.umd.js
index e0eb58fd6d..8dcae0bb73 100644
--- a/plugins/CoreHome/vue/dist/CoreHome.umd.js
+++ b/plugins/CoreHome/vue/dist/CoreHome.umd.js
@@ -2041,6 +2041,10 @@ var AjaxHelper_AjaxHelper = /*#__PURE__*/function () {
helper.withTokenInUrl();
}
+ if (options.errorElement) {
+ helper.setErrorElement(options.errorElement);
+ }
+
helper.setFormat(options.format || 'json');
if (Array.isArray(params)) {
diff --git a/plugins/CoreHome/vue/dist/CoreHome.umd.min.js b/plugins/CoreHome/vue/dist/CoreHome.umd.min.js
index 4365bf08ec..7764c289ce 100644
--- a/plugins/CoreHome/vue/dist/CoreHome.umd.min.js
+++ b/plugins/CoreHome/vue/dist/CoreHome.umd.min.js
@@ -99,7 +99,7 @@ function De(){return S}function Pe(e,t){t.$oldEmit=t.$emit,t.$emit=function(e){f
*
* @link https://matomo.org
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
- */function Qe(e,t){if("abort"!==t)if("undefined"!==typeof Piwik_Popover){var n=$("#loadingError");Piwik_Popover.isOpen()&&e&&500===e.status?e&&500===e.status&&$(document.body).html(piwikHelper.escape(e.responseText)):n.show()}else console.log("Request failed: ".concat(e.responseText))}we.updatePeriodParamsFromUrl=Se.updatePeriodParamsFromUrl.bind(Se),window.angular.module("piwikApp.service").service("piwikUrl",Ee),window.angular.module("piwikApp.service").run(["$location",function(){return null}]),window.angular.module("piwikApp.service").service("piwik",De),Pe.$inject=["piwik","$rootScope"],window.angular.module("piwikApp.service").run(Pe),window.globalAjaxQueue=[],window.globalAjaxQueue.active=0,window.globalAjaxQueue.clean=function(){for(var e=this.length;e>=0;e-=1)this[e]&&4!==this[e].readyState||this.splice(e,1)},window.globalAjaxQueue.push=function(){for(var e,t=arguments.length,n=new Array(t),r=0;r<t;r++)n[r]=arguments[r];return this.active+=n.length,this.clean(),(e=Array.prototype.push).call.apply(e,[this].concat(n))},window.globalAjaxQueue.abort=function(){this.forEach((function(e){return e&&e.abort&&e.abort()})),this.splice(0,this.length),this.active=0};var Ke=function(e){_e(n,e);var t=$e(n);function n(){return Re(this,n),t.apply(this,arguments)}return n}(qe(Error)),Xe=function(){function e(){Re(this,e),Fe(this,"format","json"),Fe(this,"timeout",null),Fe(this,"callback",null),Fe(this,"useRegularCallbackInCaseOfError",!1),Fe(this,"errorCallback",void 0),Fe(this,"withToken",!1),Fe(this,"completeCallback",void 0),Fe(this,"getParams",{}),Fe(this,"getUrl","?"),Fe(this,"postParams",{}),Fe(this,"loadingElement",null),Fe(this,"errorElement","#ajaxError"),Fe(this,"headers",void 0),Fe(this,"requestHandle",null),Fe(this,"abortController",null),Fe(this,"defaultParams",["idSite","period","date","segment"]),Fe(this,"resolveWithHelper",!1),this.errorCallback=Qe}return Le(e,[{key:"addParams",value:function(e,t){var n=this,r="string"===typeof e?window.broadcast.getValuesFromUrl(e):e,i=["compareSegments","comparePeriods","compareDates"];Object.keys(r).forEach((function(e){var a=r[e];(-1===i.indexOf(e)||a)&&("get"===t.toLowerCase()?n.getParams[e]=a:"post"===t.toLowerCase()&&(n.postParams[e]=a))}))}},{key:"withTokenInUrl",value:function(){this.withToken=!0}},{key:"setUrl",value:function(e){this.addParams(broadcast.getValuesFromUrl(e),"GET")}},{key:"setBulkRequests",value:function(){for(var e=arguments.length,t=new Array(e),n=0;n<e;n++)t[n]=arguments[n];var r=t.map((function(e){return"string"===typeof e?e:$.param(e)}));this.addParams({module:"API",method:"API.getBulkRequest",urls:r,format:"json"},"post")}},{key:"setTimeout",value:function(e){this.timeout=e}},{key:"setCallback",value:function(e){this.callback=e}},{key:"useCallbackInCaseOfError",value:function(){this.useRegularCallbackInCaseOfError=!0}},{key:"redirectOnSuccess",value:function(e){this.setCallback((function(){piwikHelper.redirect(e)}))}},{key:"setErrorCallback",value:function(e){this.errorCallback=e}},{key:"setCompleteCallback",value:function(e){this.completeCallback=e}},{key:"setFormat",value:function(e){this.format=e}},{key:"setLoadingElement",value:function(e){this.loadingElement=e||"#ajaxLoadingDiv"}},{key:"setErrorElement",value:function(e){e&&(this.errorElement=e)}},{key:"useGETDefaultParameter",value:function(e){if(e&&this.defaultParams)for(var t=0;t<this.defaultParams.length;t+=1)if(this.defaultParams[t]===e)return!0;return!1}},{key:"removeDefaultParameter",value:function(e){if(e&&this.defaultParams)for(var t=0;t<this.defaultParams.length;t+=1)this.defaultParams[t]===e&&this.defaultParams.splice(t,1)}},{key:"send",value:function(){var e=this;$(this.errorElement).length&&$(this.errorElement).hide(),this.loadingElement&&$(this.loadingElement).fadeIn(),this.requestHandle=this.buildAjaxCall(),window.globalAjaxQueue.push(this.requestHandle);var t=null;try{t=S.helper.getAngularDependency("$timeout")}catch(r){}this.abortController&&this.abortController.signal.addEventListener("abort",(function(){e.requestHandle&&e.requestHandle.abort()}));var n=new Promise((function(n,r){e.requestHandle.then((function(t){e.resolveWithHelper?n(e):n(t)})).fail((function(t){"abort"!==t.statusText&&(console.log("Warning: the ".concat($.param(e.getParams)," request failed!")),r(t))})).done((function(){t&&t()}))}));return n}},{key:"abort",value:function(){this.requestHandle&&"function"===typeof this.requestHandle.abort&&(this.requestHandle.abort(),this.requestHandle=null)}},{key:"buildAjaxCall",value:function(){var e=this,t=this,n=this.mixinDefaultGetParams(this.getParams),r=this.getUrl;"?"!==r[r.length-1]&&(r+="&"),n.segment&&(r="".concat(r,"segment=").concat(n.segment,"&"),delete n.segment),n.date&&(r="".concat(r,"date=").concat(decodeURIComponent(n.date.toString()),"&"),delete n.date),r+=$.param(n);var i={type:"POST",async:!0,url:r,dataType:this.format||"json",complete:this.completeCallback,headers:this.headers?this.headers:void 0,error:function(){if(window.globalAjaxQueue.active-=1,t.errorCallback){for(var e=arguments.length,n=new Array(e),r=0;r<e;r++)n[r]=arguments[r];t.errorCallback.apply(this,n)}},success:function(t,n,r){if(e.loadingElement&&$(e.loadingElement).hide(),t&&"error"===t.result&&!e.useRegularCallbackInCaseOfError){var i=null,a="toast";$(e.errorElement).length&&t.message&&($(e.errorElement).show(),i=e.errorElement,a=null);var o=!document.querySelector("#login_form");if(t.message&&o){var l=window["require"]("piwik/UI"),c=new l.Notification;c.show(t.message,{placeat:i,context:"error",type:a,id:"ajaxHelper"}),c.scrollToNotification()}}else e.callback&&e.callback(t,n,r);window.globalAjaxQueue.active-=1,S.ajaxRequestFinished&&S.ajaxRequestFinished()},data:this.mixinDefaultPostParams(this.postParams),timeout:null!==this.timeout?this.timeout:void 0};return $.ajax(i)}},{key:"isRequestToApiMethod",value:function(){return this.getParams&&"API"===this.getParams.module&&this.getParams.method||this.postParams&&"API"===this.postParams.module&&this.postParams.method}},{key:"isWidgetizedRequest",value:function(){return"Widgetize"===broadcast.getValueFromUrl("module")}},{key:"getDefaultPostParams",value:function(){return this.withToken||this.isRequestToApiMethod()||S.shouldPropagateTokenAuth?{token_auth:S.token_auth,force_api_session:broadcast.isWidgetizeRequestWithoutSession()?0:1}:{}}},{key:"mixinDefaultPostParams",value:function(e){var t=this.getDefaultPostParams(),n=Object.assign(Object.assign({},t),e);return n}},{key:"mixinDefaultGetParams",value:function(e){var t=this,n=Ce.getSearchParam("segment"),r={idSite:S.idSite?S.idSite.toString():broadcast.getValueFromUrl("idSite"),period:S.period||broadcast.getValueFromUrl("period"),segment:n},i=e;return i.token_auth&&(i.token_auth=null,delete i.token_auth),Object.keys(r).forEach((function(e){t.useGETDefaultParameter(e)&&!i[e]&&!t.postParams[e]&&r[e]&&(i[e]=r[e])})),!this.useGETDefaultParameter("date")||i.date||this.postParams.date||(i.date=S.currentDateString),i}},{key:"getRequestHandle",value:function(){return this.requestHandle}}],[{key:"fetch",value:function(t){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},r=new e;return n.withTokenInUrl&&r.withTokenInUrl(),r.setFormat(n.format||"json"),Array.isArray(t)?r.setBulkRequests.apply(r,Ne(t)):r.addParams(Object.assign(Object.assign({module:"API",format:n.format||"json"},t),{},{segment:t.segment?encodeURIComponent(t.segment):void 0}),"get"),n.postParams&&r.addParams(n.postParams,"post"),n.headers&&(r.headers=n.headers),"undefined"===typeof n.createErrorNotification||n.createErrorNotification||r.useCallbackInCaseOfError(),n.abortController&&(r.abortController=n.abortController),n.returnResponseObject&&(r.resolveWithHelper=!0),r.send().then((function(t){var n=t instanceof e?t.requestHandle.responseJSON:t;if("error"===n.result)throw new Ke(n.message);return t}))}},{key:"post",value:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{};return this.fetch(e,Object.assign(Object.assign({},n),{},{postParams:t}))}}]),e}();function Ze(){return window.globalAjaxQueue}function et(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function tt(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}function nt(e,t,n){return t&&tt(e.prototype,t),n&&tt(e,n),e}
+ */function Qe(e,t){if("abort"!==t)if("undefined"!==typeof Piwik_Popover){var n=$("#loadingError");Piwik_Popover.isOpen()&&e&&500===e.status?e&&500===e.status&&$(document.body).html(piwikHelper.escape(e.responseText)):n.show()}else console.log("Request failed: ".concat(e.responseText))}we.updatePeriodParamsFromUrl=Se.updatePeriodParamsFromUrl.bind(Se),window.angular.module("piwikApp.service").service("piwikUrl",Ee),window.angular.module("piwikApp.service").run(["$location",function(){return null}]),window.angular.module("piwikApp.service").service("piwik",De),Pe.$inject=["piwik","$rootScope"],window.angular.module("piwikApp.service").run(Pe),window.globalAjaxQueue=[],window.globalAjaxQueue.active=0,window.globalAjaxQueue.clean=function(){for(var e=this.length;e>=0;e-=1)this[e]&&4!==this[e].readyState||this.splice(e,1)},window.globalAjaxQueue.push=function(){for(var e,t=arguments.length,n=new Array(t),r=0;r<t;r++)n[r]=arguments[r];return this.active+=n.length,this.clean(),(e=Array.prototype.push).call.apply(e,[this].concat(n))},window.globalAjaxQueue.abort=function(){this.forEach((function(e){return e&&e.abort&&e.abort()})),this.splice(0,this.length),this.active=0};var Ke=function(e){_e(n,e);var t=$e(n);function n(){return Re(this,n),t.apply(this,arguments)}return n}(qe(Error)),Xe=function(){function e(){Re(this,e),Fe(this,"format","json"),Fe(this,"timeout",null),Fe(this,"callback",null),Fe(this,"useRegularCallbackInCaseOfError",!1),Fe(this,"errorCallback",void 0),Fe(this,"withToken",!1),Fe(this,"completeCallback",void 0),Fe(this,"getParams",{}),Fe(this,"getUrl","?"),Fe(this,"postParams",{}),Fe(this,"loadingElement",null),Fe(this,"errorElement","#ajaxError"),Fe(this,"headers",void 0),Fe(this,"requestHandle",null),Fe(this,"abortController",null),Fe(this,"defaultParams",["idSite","period","date","segment"]),Fe(this,"resolveWithHelper",!1),this.errorCallback=Qe}return Le(e,[{key:"addParams",value:function(e,t){var n=this,r="string"===typeof e?window.broadcast.getValuesFromUrl(e):e,i=["compareSegments","comparePeriods","compareDates"];Object.keys(r).forEach((function(e){var a=r[e];(-1===i.indexOf(e)||a)&&("get"===t.toLowerCase()?n.getParams[e]=a:"post"===t.toLowerCase()&&(n.postParams[e]=a))}))}},{key:"withTokenInUrl",value:function(){this.withToken=!0}},{key:"setUrl",value:function(e){this.addParams(broadcast.getValuesFromUrl(e),"GET")}},{key:"setBulkRequests",value:function(){for(var e=arguments.length,t=new Array(e),n=0;n<e;n++)t[n]=arguments[n];var r=t.map((function(e){return"string"===typeof e?e:$.param(e)}));this.addParams({module:"API",method:"API.getBulkRequest",urls:r,format:"json"},"post")}},{key:"setTimeout",value:function(e){this.timeout=e}},{key:"setCallback",value:function(e){this.callback=e}},{key:"useCallbackInCaseOfError",value:function(){this.useRegularCallbackInCaseOfError=!0}},{key:"redirectOnSuccess",value:function(e){this.setCallback((function(){piwikHelper.redirect(e)}))}},{key:"setErrorCallback",value:function(e){this.errorCallback=e}},{key:"setCompleteCallback",value:function(e){this.completeCallback=e}},{key:"setFormat",value:function(e){this.format=e}},{key:"setLoadingElement",value:function(e){this.loadingElement=e||"#ajaxLoadingDiv"}},{key:"setErrorElement",value:function(e){e&&(this.errorElement=e)}},{key:"useGETDefaultParameter",value:function(e){if(e&&this.defaultParams)for(var t=0;t<this.defaultParams.length;t+=1)if(this.defaultParams[t]===e)return!0;return!1}},{key:"removeDefaultParameter",value:function(e){if(e&&this.defaultParams)for(var t=0;t<this.defaultParams.length;t+=1)this.defaultParams[t]===e&&this.defaultParams.splice(t,1)}},{key:"send",value:function(){var e=this;$(this.errorElement).length&&$(this.errorElement).hide(),this.loadingElement&&$(this.loadingElement).fadeIn(),this.requestHandle=this.buildAjaxCall(),window.globalAjaxQueue.push(this.requestHandle);var t=null;try{t=S.helper.getAngularDependency("$timeout")}catch(r){}this.abortController&&this.abortController.signal.addEventListener("abort",(function(){e.requestHandle&&e.requestHandle.abort()}));var n=new Promise((function(n,r){e.requestHandle.then((function(t){e.resolveWithHelper?n(e):n(t)})).fail((function(t){"abort"!==t.statusText&&(console.log("Warning: the ".concat($.param(e.getParams)," request failed!")),r(t))})).done((function(){t&&t()}))}));return n}},{key:"abort",value:function(){this.requestHandle&&"function"===typeof this.requestHandle.abort&&(this.requestHandle.abort(),this.requestHandle=null)}},{key:"buildAjaxCall",value:function(){var e=this,t=this,n=this.mixinDefaultGetParams(this.getParams),r=this.getUrl;"?"!==r[r.length-1]&&(r+="&"),n.segment&&(r="".concat(r,"segment=").concat(n.segment,"&"),delete n.segment),n.date&&(r="".concat(r,"date=").concat(decodeURIComponent(n.date.toString()),"&"),delete n.date),r+=$.param(n);var i={type:"POST",async:!0,url:r,dataType:this.format||"json",complete:this.completeCallback,headers:this.headers?this.headers:void 0,error:function(){if(window.globalAjaxQueue.active-=1,t.errorCallback){for(var e=arguments.length,n=new Array(e),r=0;r<e;r++)n[r]=arguments[r];t.errorCallback.apply(this,n)}},success:function(t,n,r){if(e.loadingElement&&$(e.loadingElement).hide(),t&&"error"===t.result&&!e.useRegularCallbackInCaseOfError){var i=null,a="toast";$(e.errorElement).length&&t.message&&($(e.errorElement).show(),i=e.errorElement,a=null);var o=!document.querySelector("#login_form");if(t.message&&o){var l=window["require"]("piwik/UI"),c=new l.Notification;c.show(t.message,{placeat:i,context:"error",type:a,id:"ajaxHelper"}),c.scrollToNotification()}}else e.callback&&e.callback(t,n,r);window.globalAjaxQueue.active-=1,S.ajaxRequestFinished&&S.ajaxRequestFinished()},data:this.mixinDefaultPostParams(this.postParams),timeout:null!==this.timeout?this.timeout:void 0};return $.ajax(i)}},{key:"isRequestToApiMethod",value:function(){return this.getParams&&"API"===this.getParams.module&&this.getParams.method||this.postParams&&"API"===this.postParams.module&&this.postParams.method}},{key:"isWidgetizedRequest",value:function(){return"Widgetize"===broadcast.getValueFromUrl("module")}},{key:"getDefaultPostParams",value:function(){return this.withToken||this.isRequestToApiMethod()||S.shouldPropagateTokenAuth?{token_auth:S.token_auth,force_api_session:broadcast.isWidgetizeRequestWithoutSession()?0:1}:{}}},{key:"mixinDefaultPostParams",value:function(e){var t=this.getDefaultPostParams(),n=Object.assign(Object.assign({},t),e);return n}},{key:"mixinDefaultGetParams",value:function(e){var t=this,n=Ce.getSearchParam("segment"),r={idSite:S.idSite?S.idSite.toString():broadcast.getValueFromUrl("idSite"),period:S.period||broadcast.getValueFromUrl("period"),segment:n},i=e;return i.token_auth&&(i.token_auth=null,delete i.token_auth),Object.keys(r).forEach((function(e){t.useGETDefaultParameter(e)&&!i[e]&&!t.postParams[e]&&r[e]&&(i[e]=r[e])})),!this.useGETDefaultParameter("date")||i.date||this.postParams.date||(i.date=S.currentDateString),i}},{key:"getRequestHandle",value:function(){return this.requestHandle}}],[{key:"fetch",value:function(t){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},r=new e;return n.withTokenInUrl&&r.withTokenInUrl(),n.errorElement&&r.setErrorElement(n.errorElement),r.setFormat(n.format||"json"),Array.isArray(t)?r.setBulkRequests.apply(r,Ne(t)):r.addParams(Object.assign(Object.assign({module:"API",format:n.format||"json"},t),{},{segment:t.segment?encodeURIComponent(t.segment):void 0}),"get"),n.postParams&&r.addParams(n.postParams,"post"),n.headers&&(r.headers=n.headers),"undefined"===typeof n.createErrorNotification||n.createErrorNotification||r.useCallbackInCaseOfError(),n.abortController&&(r.abortController=n.abortController),n.returnResponseObject&&(r.resolveWithHelper=!0),r.send().then((function(t){var n=t instanceof e?t.requestHandle.responseJSON:t;if("error"===n.result)throw new Ke(n.message);return t}))}},{key:"post",value:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{};return this.fetch(e,Object.assign(Object.assign({},n),{},{postParams:t}))}}]),e}();function Ze(){return window.globalAjaxQueue}function et(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function tt(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}function nt(e,t,n){return t&&tt(e.prototype,t),n&&tt(e,n),e}
/*!
* Matomo - free/libre analytics platform
*
diff --git a/plugins/CoreHome/vue/src/AjaxHelper/AjaxHelper.ts b/plugins/CoreHome/vue/src/AjaxHelper/AjaxHelper.ts
index 2a3ee021dc..560bab3c1e 100644
--- a/plugins/CoreHome/vue/src/AjaxHelper/AjaxHelper.ts
+++ b/plugins/CoreHome/vue/src/AjaxHelper/AjaxHelper.ts
@@ -20,6 +20,7 @@ export interface AjaxOptions {
createErrorNotification?: boolean;
abortController?: AbortController;
returnResponseObject?: boolean;
+ errorElement?: HTMLElement|JQuery|JQLite|string;
}
interface ErrorResponse {
@@ -185,6 +186,9 @@ export default class AjaxHelper<T = any> { // eslint-disable-line
if (options.withTokenInUrl) {
helper.withTokenInUrl();
}
+ if (options.errorElement) {
+ helper.setErrorElement(options.errorElement);
+ }
helper.setFormat(options.format || 'json');
if (Array.isArray(params)) {
helper.setBulkRequests(...(params as QueryParameters[]));
diff --git a/plugins/MobileMessaging/Controller.php b/plugins/MobileMessaging/Controller.php
index 42cff6ca12..831f524872 100644
--- a/plugins/MobileMessaging/Controller.php
+++ b/plugins/MobileMessaging/Controller.php
@@ -10,6 +10,7 @@
namespace Piwik\Plugins\MobileMessaging;
use Piwik\Common;
+use Piwik\DataTable\Renderer\Json;
use Piwik\Intl\Data\Provider\RegionDataProvider;
use Piwik\IP;
use Piwik\Piwik;
@@ -150,10 +151,7 @@ class Controller extends ControllerAdmin
}
}
- $view = new View('@MobileMessaging/credentials');
-
- $view->credentialfields = $credentialFields;
-
- return $view->render();
+ Json::sendHeaderJSON();
+ return json_encode($credentialFields);
}
}
diff --git a/plugins/MobileMessaging/MobileMessaging.php b/plugins/MobileMessaging/MobileMessaging.php
index 240ab55fb9..9be6bf8a45 100644
--- a/plugins/MobileMessaging/MobileMessaging.php
+++ b/plugins/MobileMessaging/MobileMessaging.php
@@ -92,9 +92,7 @@ class MobileMessaging extends \Piwik\Plugin
public function getJsFiles(&$jsFiles)
{
$jsFiles[] = "plugins/MobileMessaging/angularjs/delegate-mobile-messaging-settings.controller.js";
- $jsFiles[] = "plugins/MobileMessaging/angularjs/manage-sms-provider.controller.js";
$jsFiles[] = "plugins/MobileMessaging/angularjs/manage-mobile-phone-numbers.controller.js";
- $jsFiles[] = "plugins/MobileMessaging/angularjs/sms-provider-credentials.directive.js";
}
public function getStylesheetFiles(&$stylesheets)
@@ -107,6 +105,14 @@ class MobileMessaging extends \Piwik\Plugin
$translationKeys[] = 'CoreAdminHome_SettingsSaveSuccess';
$translationKeys[] = 'MobileMessaging_Settings_InvalidActivationCode';
$translationKeys[] = 'MobileMessaging_Settings_PhoneActivated';
+ $translationKeys[] = 'MobileMessaging_Settings_SMSProvider';
+ $translationKeys[] = 'MobileMessaging_Settings_PleaseSignUp';
+ $translationKeys[] = 'MobileMessaging_Settings_CredentialInvalid';
+ $translationKeys[] = 'MobileMessaging_Settings_CredentialProvided';
+ $translationKeys[] = 'MobileMessaging_Settings_UpdateOrDeleteAccount';
+ $translationKeys[] = 'MobileMessaging_UserKey';
+ $translationKeys[] = 'General_Password';
+ $translationKeys[] = 'MobileMessaging_Settings_APIKey';
}
public function validateReportParameters(&$parameters, $reportType)
diff --git a/plugins/MobileMessaging/angularjs/sms-provider-credentials.directive.js b/plugins/MobileMessaging/angularjs/sms-provider-credentials.directive.js
index d09e0b88ec..58fde7ddd8 100644
--- a/plugins/MobileMessaging/angularjs/sms-provider-credentials.directive.js
+++ b/plugins/MobileMessaging/angularjs/sms-provider-credentials.directive.js
@@ -48,4 +48,4 @@
}
};
}
-})(); \ No newline at end of file
+})();
diff --git a/plugins/MobileMessaging/templates/macros.twig b/plugins/MobileMessaging/templates/macros.twig
index 4d40ba46b7..a21f2f3be3 100644
--- a/plugins/MobileMessaging/templates/macros.twig
+++ b/plugins/MobileMessaging/templates/macros.twig
@@ -1,58 +1,13 @@
{% macro manageSmsApi(credentialSupplied, credentialError, creditLeft, smsProviderOptions, smsProviders, provider) %}
-<div ng-controller="ManageSmsProviderController as manageProvider">
-
- <div piwik-activity-indicator loading="manageProvider.isDeletingAccount"></div>
- <div id="ajaxErrorManageSmsProviderSettings"></div>
-
- {% if credentialSupplied %}
- <p>
- {% if credentialError %}
- {{ 'MobileMessaging_Settings_CredentialInvalid'|translate(provider) }}<br />
- {{ credentialError }}
- {% else %}
- {{ 'MobileMessaging_Settings_CredentialProvided'|translate(provider) }}
- {{ creditLeft }}
- {% endif %}
- <br/>
- {{ 'MobileMessaging_Settings_UpdateOrDeleteAccount'|translate('<a ng-click="manageProvider.showUpdateAccount()" id="displayAccountForm">',"</a>",'<a ng-click="manageProvider.deleteAccount()" id="deleteAccount">',"</a>")|raw }}
- </p>
- {% else %}
- <p>{{ 'MobileMessaging_Settings_PleaseSignUp'|translate }}</p>
- {% endif %}
-
- <div piwik-form id='accountForm' {% if credentialSupplied %}ng-show="manageProvider.showAccountForm"{% endif %}>
-
- <div piwik-field uicontrol="select" name="smsProviders"
- options="{{ smsProviderOptions|json_encode }}"
- ng-model="manageProvider.smsProvider"
- ng-change="manageProvider.isUpdateAccountPossible()"
- data-title="{{ 'MobileMessaging_Settings_SMSProvider'|translate|e('html_attr') }}"
- value="{{ provider }}">
- </div>
-
- <div sms-provider-credentials
- provider="manageProvider.smsProvider"
- ng-model="manageProvider.credentials"
- value="{}"
- ng-init="manageProvider.isUpdateAccountPossible()"
- ng-change="manageProvider.isUpdateAccountPossible()"
- ></div>
-
- <div piwik-save-button id='apiAccountSubmit'
- data-disabled="!manageProvider.canBeUpdated"
- saving="manageProvider.isUpdatingAccount"
- onconfirm="manageProvider.updateAccount()"></div>
-
- {% for smsProvider, description in smsProviders %}
- <div class='providerDescription'
- ng-show="manageProvider.smsProvider == '{{ smsProvider|e('js') }}'"
- id='{{ smsProvider }}'>
- {{ description|raw }}
- </div>
- {% endfor %}
-
- </div>
-</div>
+<div
+ vue-entry="MobileMessaging.ManageSmsProvider"
+ credential-supplied="{{ credentialSupplied|default(null)|json_encode|e('html_attr') }}"
+ credential-error="{{ credentialError|default(null)|json_encode|e('html_attr') }}"
+ provider="{{ provider|default(null)|json_encode|e('html_attr') }}"
+ credit-left="{{ creditLeft|default(null)|json_encode|e('html_attr') }}"
+ sms-provider-options="{{ smsProviderOptions|default(null)|json_encode|e('html_attr') }}"
+ sms-providers="{{ smsProviders|default(null)|json_encode|e('html_attr') }}"
+></div>
{% endmacro %}
{% macro selectPhoneNumbers(phoneNumbers, angularContext, value, withIntroduction) %}
diff --git a/plugins/MobileMessaging/vue/dist/MobileMessaging.umd.js b/plugins/MobileMessaging/vue/dist/MobileMessaging.umd.js
new file mode 100644
index 0000000000..259a4a972c
--- /dev/null
+++ b/plugins/MobileMessaging/vue/dist/MobileMessaging.umd.js
@@ -0,0 +1,546 @@
+(function webpackUniversalModuleDefinition(root, factory) {
+ if(typeof exports === 'object' && typeof module === 'object')
+ module.exports = factory(require("CoreHome"), require("vue"), require("CorePluginsAdmin"));
+ else if(typeof define === 'function' && define.amd)
+ define(["CoreHome", , "CorePluginsAdmin"], factory);
+ else if(typeof exports === 'object')
+ exports["MobileMessaging"] = factory(require("CoreHome"), require("vue"), require("CorePluginsAdmin"));
+ else
+ root["MobileMessaging"] = factory(root["CoreHome"], root["Vue"], root["CorePluginsAdmin"]);
+})((typeof self !== 'undefined' ? self : this), function(__WEBPACK_EXTERNAL_MODULE__19dc__, __WEBPACK_EXTERNAL_MODULE__8bbf__, __WEBPACK_EXTERNAL_MODULE_a5a2__) {
+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/MobileMessaging/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__;
+
+/***/ }),
+
+/***/ "a5a2":
+/***/ (function(module, exports) {
+
+module.exports = __WEBPACK_EXTERNAL_MODULE_a5a2__;
+
+/***/ }),
+
+/***/ "fae3":
+/***/ (function(module, __webpack_exports__, __webpack_require__) {
+
+"use strict";
+// ESM COMPAT FLAG
+__webpack_require__.r(__webpack_exports__);
+
+// EXPORTS
+__webpack_require__.d(__webpack_exports__, "ManageSmsProvider", function() { return /* reexport */ ManageSmsProvider; });
+__webpack_require__.d(__webpack_exports__, "SmsProviderCredentials", function() { return /* reexport */ SmsProviderCredentials; });
+
+// 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 {"commonjs":"vue","commonjs2":"vue","root":"Vue"}
+var external_commonjs_vue_commonjs2_vue_root_Vue_ = __webpack_require__("8bbf");
+
+// EXTERNAL MODULE: external "CoreHome"
+var external_CoreHome_ = __webpack_require__("19dc");
+
+// 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/MobileMessaging/vue/src/SmsProviderCredentials/SmsProviderCredentials.vue?vue&type=template&id=71256e6a
+function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
+
+
+var _hoisted_1 = {
+ key: 0
+};
+function render(_ctx, _cache, $props, $setup, $data, $options) {
+ var _component_Field = Object(external_commonjs_vue_commonjs2_vue_root_Vue_["resolveComponent"])("Field");
+
+ return _ctx.fields ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", _hoisted_1, [(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(true), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])(external_commonjs_vue_commonjs2_vue_root_Vue_["Fragment"], null, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["renderList"])(_ctx.fields, function (field) {
+ var _ctx$modelValue;
+
+ return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createBlock"])(_component_Field, {
+ key: field.name,
+ uicontrol: field.type,
+ name: field.name,
+ "model-value": (_ctx$modelValue = _ctx.modelValue) === null || _ctx$modelValue === void 0 ? void 0 : _ctx$modelValue[field.name],
+ "onUpdate:modelValue": function onUpdateModelValue($event) {
+ return _ctx.$emit('update:modelValue', Object.assign(Object.assign({}, _ctx.modelValue), {}, _defineProperty({}, field.name, $event)));
+ },
+ title: _ctx.translate(field.title)
+ }, null, 8, ["uicontrol", "name", "model-value", "onUpdate:modelValue", "title"]);
+ }), 128))])) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true);
+}
+// CONCATENATED MODULE: ./plugins/MobileMessaging/vue/src/SmsProviderCredentials/SmsProviderCredentials.vue?vue&type=template&id=71256e6a
+
+// EXTERNAL MODULE: external "CorePluginsAdmin"
+var external_CorePluginsAdmin_ = __webpack_require__("a5a2");
+
+// CONCATENATED MODULE: ./node_modules/@vue/cli-plugin-typescript/node_modules/cache-loader/dist/cjs.js??ref--14-0!./node_modules/babel-loader/lib!./node_modules/@vue/cli-plugin-typescript/node_modules/ts-loader??ref--14-2!./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/MobileMessaging/vue/src/SmsProviderCredentials/SmsProviderCredentials.vue?vue&type=script&lang=ts
+
+
+
+var allFieldsByProvider = Object(external_commonjs_vue_commonjs2_vue_root_Vue_["reactive"])({});
+/* harmony default export */ var SmsProviderCredentialsvue_type_script_lang_ts = (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["defineComponent"])({
+ props: {
+ provider: {
+ type: String,
+ required: true
+ },
+ modelValue: {
+ type: Object,
+ required: true
+ }
+ },
+ emits: ['update:modelValue'],
+ components: {
+ Field: external_CorePluginsAdmin_["Field"]
+ },
+ watch: {
+ provider: function provider() {
+ // unset credentials when new provider is chosen
+ this.$emit('update:modelValue', {}); // fetch fields for provider
+
+ this.getCredentialFields();
+ }
+ },
+ created: function created() {
+ this.getCredentialFields();
+ },
+ methods: {
+ getCredentialFields: function getCredentialFields() {
+ var _this = this;
+
+ if (allFieldsByProvider[this.provider]) {
+ return;
+ }
+
+ external_CoreHome_["AjaxHelper"].fetch({
+ module: 'MobileMessaging',
+ action: 'getCredentialFields',
+ provider: this.provider
+ }).then(function (fields) {
+ allFieldsByProvider[_this.provider] = fields;
+ });
+ }
+ },
+ computed: {
+ fields: function fields() {
+ return allFieldsByProvider[this.provider];
+ }
+ }
+}));
+// CONCATENATED MODULE: ./plugins/MobileMessaging/vue/src/SmsProviderCredentials/SmsProviderCredentials.vue?vue&type=script&lang=ts
+
+// CONCATENATED MODULE: ./plugins/MobileMessaging/vue/src/SmsProviderCredentials/SmsProviderCredentials.vue
+
+
+
+SmsProviderCredentialsvue_type_script_lang_ts.render = render
+
+/* harmony default export */ var SmsProviderCredentials = (SmsProviderCredentialsvue_type_script_lang_ts);
+// CONCATENATED MODULE: ./plugins/MobileMessaging/vue/src/SmsProviderCredentials/SmsProviderCredentials.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 SmsProviderCredentials_adapter = (Object(external_CoreHome_["createAngularJsAdapter"])({
+ component: SmsProviderCredentials,
+ scope: {
+ provider: {
+ angularJsBind: '='
+ },
+ credentials: {
+ angularJsBind: '=value'
+ }
+ },
+ directiveName: 'smsProviderCredentials',
+ transclude: true,
+ events: {
+ 'update:modelValue': function updateModelValue(newValue, vm, scope, element, attrs, ngModel, $timeout) {
+ var currentValue = ngModel ? ngModel.$viewValue : scope.value;
+
+ if (newValue !== currentValue) {
+ $timeout(function () {
+ if (!ngModel) {
+ scope.value = newValue;
+ return;
+ } // ngModel being used
+
+
+ ngModel.$setViewValue(newValue);
+ ngModel.$render(); // not detected by the watch for some reason
+ });
+ }
+ }
+ },
+ postCreate: function postCreate(vm, scope, element, attrs, controller) {
+ var ngModel = controller;
+
+ if (!ngModel) {
+ scope.$watch('value', function (newVal) {
+ if (newVal !== vm.modelValue) {
+ Object(external_commonjs_vue_commonjs2_vue_root_Vue_["nextTick"])(function () {
+ vm.modelValue = newVal;
+ });
+ }
+ });
+ return;
+ } // ngModel being used
+
+
+ ngModel.$render = function () {
+ Object(external_commonjs_vue_commonjs2_vue_root_Vue_["nextTick"])(function () {
+ vm.modelValue = Object(external_CoreHome_["removeAngularJsSpecificProperties"])(ngModel.$viewValue);
+ });
+ };
+
+ if (typeof scope.value !== 'undefined') {
+ ngModel.$setViewValue(scope.value);
+ } else {
+ ngModel.$setViewValue(vm.modelValue);
+ }
+ }
+}));
+// 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/MobileMessaging/vue/src/ManageSmsProvider/ManageSmsProvider.vue?vue&type=template&id=e42e6e40
+
+
+var ManageSmsProvidervue_type_template_id_e42e6e40_hoisted_1 = /*#__PURE__*/Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", {
+ id: "ajaxErrorManageSmsProviderSettings"
+}, null, -1);
+
+var _hoisted_2 = {
+ key: 0
+};
+var _hoisted_3 = {
+ key: 0
+};
+
+var _hoisted_4 = /*#__PURE__*/Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("br", null, null, -1);
+
+var _hoisted_5 = {
+ key: 1
+};
+
+var _hoisted_6 = /*#__PURE__*/Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("br", null, null, -1);
+
+var _hoisted_7 = ["innerHTML"];
+var _hoisted_8 = {
+ key: 1
+};
+var _hoisted_9 = {
+ id: "accountForm"
+};
+var _hoisted_10 = ["innerHTML"];
+function ManageSmsProvidervue_type_template_id_e42e6e40_render(_ctx, _cache, $props, $setup, $data, $options) {
+ var _component_ActivityIndicator = Object(external_commonjs_vue_commonjs2_vue_root_Vue_["resolveComponent"])("ActivityIndicator");
+
+ var _component_Field = Object(external_commonjs_vue_commonjs2_vue_root_Vue_["resolveComponent"])("Field");
+
+ var _component_SmsProviderCredentials = Object(external_commonjs_vue_commonjs2_vue_root_Vue_["resolveComponent"])("SmsProviderCredentials");
+
+ var _component_SaveButton = Object(external_commonjs_vue_commonjs2_vue_root_Vue_["resolveComponent"])("SaveButton");
+
+ var _directive_form = Object(external_commonjs_vue_commonjs2_vue_root_Vue_["resolveDirective"])("form");
+
+ return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", null, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createVNode"])(_component_ActivityIndicator, {
+ loading: _ctx.isDeletingAccount
+ }, null, 8, ["loading"]), ManageSmsProvidervue_type_template_id_e42e6e40_hoisted_1, _ctx.credentialSupplied ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("p", _hoisted_2, [_ctx.credentialError ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("span", _hoisted_3, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createTextVNode"])(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('MobileMessaging_Settings_CredentialInvalid', _ctx.provider)), 1), _hoisted_4, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createTextVNode"])(" " + Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.credentialError), 1)])) : (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("span", _hoisted_5, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('MobileMessaging_Settings_CredentialProvided', _ctx.provider)) + " " + Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.creditLeft), 1)), _hoisted_6, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("span", {
+ innerHTML: _ctx.updateOrDeleteAccountText,
+ onClick: _cache[0] || (_cache[0] = function ($event) {
+ return _ctx.onUpdateOrDeleteClick($event);
+ })
+ }, null, 8, _hoisted_7)])) : (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("p", _hoisted_8, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('MobileMessaging_Settings_PleaseSignUp')), 1)), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["withDirectives"])(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", _hoisted_9, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", null, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createVNode"])(_component_Field, {
+ uicontrol: "select",
+ name: "smsProviders",
+ modelValue: _ctx.smsProvider,
+ "onUpdate:modelValue": _cache[1] || (_cache[1] = function ($event) {
+ return _ctx.smsProvider = $event;
+ }),
+ title: _ctx.translate('MobileMessaging_Settings_SMSProvider'),
+ options: _ctx.smsProviderOptions,
+ value: _ctx.provider
+ }, null, 8, ["modelValue", "title", "options", "value"])]), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createVNode"])(_component_SmsProviderCredentials, {
+ provider: _ctx.smsProvider,
+ modelValue: _ctx.credentials,
+ "onUpdate:modelValue": [_cache[2] || (_cache[2] = function ($event) {
+ return _ctx.credentials = $event;
+ }), _cache[3] || (_cache[3] = function ($event) {
+ _ctx.credentials = $event;
+ })],
+ "model-value": _ctx.credentials
+ }, null, 8, ["provider", "modelValue", "model-value"]), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createVNode"])(_component_SaveButton, {
+ id: "apiAccountSubmit",
+ disabled: !_ctx.isUpdateAccountPossible,
+ saving: _ctx.isUpdatingAccount,
+ onConfirm: _cache[4] || (_cache[4] = function ($event) {
+ return _ctx.updateAccount();
+ })
+ }, null, 8, ["disabled", "saving"]), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", {
+ class: "providerDescription",
+ innerHTML: _ctx.$sanitize(_ctx.currentProviderDescription)
+ }, null, 8, _hoisted_10)], 512), [[external_commonjs_vue_commonjs2_vue_root_Vue_["vShow"], !_ctx.credentialSupplied || _ctx.showAccountForm], [_directive_form]])]);
+}
+// CONCATENATED MODULE: ./plugins/MobileMessaging/vue/src/ManageSmsProvider/ManageSmsProvider.vue?vue&type=template&id=e42e6e40
+
+// CONCATENATED MODULE: ./node_modules/@vue/cli-plugin-typescript/node_modules/cache-loader/dist/cjs.js??ref--14-0!./node_modules/babel-loader/lib!./node_modules/@vue/cli-plugin-typescript/node_modules/ts-loader??ref--14-2!./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/MobileMessaging/vue/src/ManageSmsProvider/ManageSmsProvider.vue?vue&type=script&lang=ts
+
+
+
+
+/* harmony default export */ var ManageSmsProvidervue_type_script_lang_ts = (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["defineComponent"])({
+ props: {
+ credentialSupplied: Boolean,
+ credentialError: String,
+ provider: String,
+ creditLeft: [Number, String],
+ smsProviderOptions: {
+ type: Object,
+ required: true
+ },
+ smsProviders: {
+ type: Object,
+ required: true
+ }
+ },
+ components: {
+ ActivityIndicator: external_CoreHome_["ActivityIndicator"],
+ Field: external_CorePluginsAdmin_["Field"],
+ SaveButton: external_CorePluginsAdmin_["SaveButton"],
+ SmsProviderCredentials: SmsProviderCredentials
+ },
+ directives: {
+ Form: external_CorePluginsAdmin_["Form"]
+ },
+ data: function data() {
+ return {
+ isDeletingAccount: false,
+ isUpdatingAccount: false,
+ showAccountForm: false,
+ credentials: {},
+ smsProvider: this.provider
+ };
+ },
+ methods: {
+ deleteApiAccount: function deleteApiAccount() {
+ var _this = this;
+
+ this.isDeletingAccount = true;
+ external_CoreHome_["AjaxHelper"].fetch({
+ method: 'MobileMessaging.deleteSMSAPICredential'
+ }, {
+ errorElement: '#ajaxErrorManageSmsProviderSettings'
+ }).then(function () {
+ external_CoreHome_["Matomo"].helper.redirect();
+ }).finally(function () {
+ _this.isDeletingAccount = false;
+ });
+ },
+ showUpdateAccount: function showUpdateAccount() {
+ this.showAccountForm = true;
+ },
+ updateAccount: function updateAccount() {
+ var _this2 = this;
+
+ if (this.isUpdateAccountPossible) {
+ this.isUpdatingAccount = true;
+ external_CoreHome_["AjaxHelper"].post({
+ method: 'MobileMessaging.setSMSAPICredential'
+ }, {
+ provider: this.smsProvider,
+ credentials: this.credentials
+ }, {
+ errorElement: '#ajaxErrorManageSmsProviderSettings'
+ }).then(function () {
+ external_CoreHome_["Matomo"].helper.redirect();
+ }).finally(function () {
+ _this2.isUpdatingAccount = false;
+ });
+ }
+ },
+ deleteAccount: function deleteAccount() {
+ var _this3 = this;
+
+ external_CoreHome_["Matomo"].helper.modalConfirm('#confirmDeleteAccount', {
+ yes: function yes() {
+ _this3.isDeletingAccount = true;
+ external_CoreHome_["AjaxHelper"].fetch({
+ method: 'MobileMessaging.deleteSMSAPICredential'
+ }, {
+ errorElement: '#ajaxErrorManageSmsProviderSettings'
+ }).then(function () {
+ _this3.isDeletingAccount = false;
+ external_CoreHome_["Matomo"].helper.redirect();
+ }).finally(function () {
+ _this3.isDeletingAccount = false;
+ });
+ }
+ });
+ },
+ onUpdateOrDeleteClick: function onUpdateOrDeleteClick(event) {
+ var target = event.target;
+
+ if (target.id === 'displayAccountForm') {
+ this.showUpdateAccount();
+ } else if (target.id === 'deleteAccount') {
+ this.deleteAccount();
+ }
+ }
+ },
+ computed: {
+ isUpdateAccountPossible: function isUpdateAccountPossible() {
+ // possible if smsProvider is set and all credential field values are set to something
+ return !!this.smsProvider && Object.keys(this.credentials).length > 0 && Object.values(this.credentials).every(function (v) {
+ return !!v;
+ });
+ },
+ updateOrDeleteAccountText: function updateOrDeleteAccountText() {
+ return Object(external_CoreHome_["translate"])('MobileMessaging_Settings_UpdateOrDeleteAccount', '<a id="displayAccountForm">', '</a>', '<a id="deleteAccount">', '</a>');
+ },
+ currentProviderDescription: function currentProviderDescription() {
+ if (!this.smsProvider || !this.smsProviders) {
+ return '';
+ }
+
+ return this.smsProviders[this.smsProvider];
+ }
+ }
+}));
+// CONCATENATED MODULE: ./plugins/MobileMessaging/vue/src/ManageSmsProvider/ManageSmsProvider.vue?vue&type=script&lang=ts
+
+// CONCATENATED MODULE: ./plugins/MobileMessaging/vue/src/ManageSmsProvider/ManageSmsProvider.vue
+
+
+
+ManageSmsProvidervue_type_script_lang_ts.render = ManageSmsProvidervue_type_template_id_e42e6e40_render
+
+/* harmony default export */ var ManageSmsProvider = (ManageSmsProvidervue_type_script_lang_ts);
+// CONCATENATED MODULE: ./plugins/MobileMessaging/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=MobileMessaging.umd.js.map \ No newline at end of file
diff --git a/plugins/MobileMessaging/vue/dist/MobileMessaging.umd.min.js b/plugins/MobileMessaging/vue/dist/MobileMessaging.umd.min.js
new file mode 100644
index 0000000000..a9ba483777
--- /dev/null
+++ b/plugins/MobileMessaging/vue/dist/MobileMessaging.umd.min.js
@@ -0,0 +1,14 @@
+(function(e,t){"object"===typeof exports&&"object"===typeof module?module.exports=t(require("CoreHome"),require("vue"),require("CorePluginsAdmin")):"function"===typeof define&&define.amd?define(["CoreHome",,"CorePluginsAdmin"],t):"object"===typeof exports?exports["MobileMessaging"]=t(require("CoreHome"),require("vue"),require("CorePluginsAdmin")):e["MobileMessaging"]=t(e["CoreHome"],e["Vue"],e["CorePluginsAdmin"])})("undefined"!==typeof self?self:this,(function(e,t,n){return function(e){var t={};function n(r){if(t[r])return t[r].exports;var i=t[r]={i:r,l:!1,exports:{}};return e[r].call(i.exports,i,i.exports,n),i.l=!0,i.exports}return n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!==typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"===typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var i in e)n.d(r,i,function(t){return e[t]}.bind(null,i));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e["default"]}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="plugins/MobileMessaging/vue/dist/",n(n.s="fae3")}({"19dc":function(t,n){t.exports=e},"8bbf":function(e,n){e.exports=t},a5a2:function(e,t){e.exports=n},fae3:function(e,t,n){"use strict";if(n.r(t),n.d(t,"ManageSmsProvider",(function(){return V})),n.d(t,"SmsProviderCredentials",(function(){return m})),"undefined"!==typeof window){var r=window.document.currentScript,i=r&&r.src.match(/(.+\/)[^/]+\.js(\?.*)?$/);i&&(n.p=i[1])}var o=n("8bbf"),c=n("19dc");function l(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var a={key:0};function d(e,t,n,r,i,c){var d=Object(o["resolveComponent"])("Field");return e.fields?(Object(o["openBlock"])(),Object(o["createElementBlock"])("div",a,[(Object(o["openBlock"])(!0),Object(o["createElementBlock"])(o["Fragment"],null,Object(o["renderList"])(e.fields,(function(t){var n;return Object(o["openBlock"])(),Object(o["createBlock"])(d,{key:t.name,uicontrol:t.type,name:t.name,"model-value":null===(n=e.modelValue)||void 0===n?void 0:n[t.name],"onUpdate:modelValue":function(n){return e.$emit("update:modelValue",Object.assign(Object.assign({},e.modelValue),{},l({},t.name,n)))},title:e.translate(t.title)},null,8,["uicontrol","name","model-value","onUpdate:modelValue","title"])})),128))])):Object(o["createCommentVNode"])("",!0)}var s=n("a5a2"),u=Object(o["reactive"])({}),p=Object(o["defineComponent"])({props:{provider:{type:String,required:!0},modelValue:{type:Object,required:!0}},emits:["update:modelValue"],components:{Field:s["Field"]},watch:{provider:function(){this.$emit("update:modelValue",{}),this.getCredentialFields()}},created:function(){this.getCredentialFields()},methods:{getCredentialFields:function(){var e=this;u[this.provider]||c["AjaxHelper"].fetch({module:"MobileMessaging",action:"getCredentialFields",provider:this.provider}).then((function(t){u[e.provider]=t}))}},computed:{fields:function(){return u[this.provider]}}});p.render=d;var m=p,v=(Object(c["createAngularJsAdapter"])({component:m,scope:{provider:{angularJsBind:"="},credentials:{angularJsBind:"=value"}},directiveName:"smsProviderCredentials",transclude:!0,events:{"update:modelValue":function(e,t,n,r,i,o,c){var l=o?o.$viewValue:n.value;e!==l&&c((function(){o?(o.$setViewValue(e),o.$render()):n.value=e}))}},postCreate:function(e,t,n,r,i){var l=i;l?(l.$render=function(){Object(o["nextTick"])((function(){e.modelValue=Object(c["removeAngularJsSpecificProperties"])(l.$viewValue)}))},"undefined"!==typeof t.value?l.$setViewValue(t.value):l.$setViewValue(e.modelValue)):t.$watch("value",(function(t){t!==e.modelValue&&Object(o["nextTick"])((function(){e.modelValue=t}))}))}}),Object(o["createElementVNode"])("div",{id:"ajaxErrorManageSmsProviderSettings"},null,-1)),f={key:0},b={key:0},g=Object(o["createElementVNode"])("br",null,null,-1),j={key:1},O=Object(o["createElementVNode"])("br",null,null,-1),h=["innerHTML"],A={key:1},S={id:"accountForm"},y=["innerHTML"];
+/*!
+ * Matomo - free/libre analytics platform
+ *
+ * @link https://matomo.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ */function M(e,t,n,r,i,c){var l=Object(o["resolveComponent"])("ActivityIndicator"),a=Object(o["resolveComponent"])("Field"),d=Object(o["resolveComponent"])("SmsProviderCredentials"),s=Object(o["resolveComponent"])("SaveButton"),u=Object(o["resolveDirective"])("form");return Object(o["openBlock"])(),Object(o["createElementBlock"])("div",null,[Object(o["createVNode"])(l,{loading:e.isDeletingAccount},null,8,["loading"]),v,e.credentialSupplied?(Object(o["openBlock"])(),Object(o["createElementBlock"])("p",f,[e.credentialError?(Object(o["openBlock"])(),Object(o["createElementBlock"])("span",b,[Object(o["createTextVNode"])(Object(o["toDisplayString"])(e.translate("MobileMessaging_Settings_CredentialInvalid",e.provider)),1),g,Object(o["createTextVNode"])(" "+Object(o["toDisplayString"])(e.credentialError),1)])):(Object(o["openBlock"])(),Object(o["createElementBlock"])("span",j,Object(o["toDisplayString"])(e.translate("MobileMessaging_Settings_CredentialProvided",e.provider))+" "+Object(o["toDisplayString"])(e.creditLeft),1)),O,Object(o["createElementVNode"])("span",{innerHTML:e.updateOrDeleteAccountText,onClick:t[0]||(t[0]=function(t){return e.onUpdateOrDeleteClick(t)})},null,8,h)])):(Object(o["openBlock"])(),Object(o["createElementBlock"])("p",A,Object(o["toDisplayString"])(e.translate("MobileMessaging_Settings_PleaseSignUp")),1)),Object(o["withDirectives"])(Object(o["createElementVNode"])("div",S,[Object(o["createElementVNode"])("div",null,[Object(o["createVNode"])(a,{uicontrol:"select",name:"smsProviders",modelValue:e.smsProvider,"onUpdate:modelValue":t[1]||(t[1]=function(t){return e.smsProvider=t}),title:e.translate("MobileMessaging_Settings_SMSProvider"),options:e.smsProviderOptions,value:e.provider},null,8,["modelValue","title","options","value"])]),Object(o["createVNode"])(d,{provider:e.smsProvider,modelValue:e.credentials,"onUpdate:modelValue":[t[2]||(t[2]=function(t){return e.credentials=t}),t[3]||(t[3]=function(t){e.credentials=t})],"model-value":e.credentials},null,8,["provider","modelValue","model-value"]),Object(o["createVNode"])(s,{id:"apiAccountSubmit",disabled:!e.isUpdateAccountPossible,saving:e.isUpdatingAccount,onConfirm:t[4]||(t[4]=function(t){return e.updateAccount()})},null,8,["disabled","saving"]),Object(o["createElementVNode"])("div",{class:"providerDescription",innerHTML:e.$sanitize(e.currentProviderDescription)},null,8,y)],512),[[o["vShow"],!e.credentialSupplied||e.showAccountForm],[u]])])}var P=Object(o["defineComponent"])({props:{credentialSupplied:Boolean,credentialError:String,provider:String,creditLeft:[Number,String],smsProviderOptions:{type:Object,required:!0},smsProviders:{type:Object,required:!0}},components:{ActivityIndicator:c["ActivityIndicator"],Field:s["Field"],SaveButton:s["SaveButton"],SmsProviderCredentials:m},directives:{Form:s["Form"]},data:function(){return{isDeletingAccount:!1,isUpdatingAccount:!1,showAccountForm:!1,credentials:{},smsProvider:this.provider}},methods:{deleteApiAccount:function(){var e=this;this.isDeletingAccount=!0,c["AjaxHelper"].fetch({method:"MobileMessaging.deleteSMSAPICredential"},{errorElement:"#ajaxErrorManageSmsProviderSettings"}).then((function(){c["Matomo"].helper.redirect()})).finally((function(){e.isDeletingAccount=!1}))},showUpdateAccount:function(){this.showAccountForm=!0},updateAccount:function(){var e=this;this.isUpdateAccountPossible&&(this.isUpdatingAccount=!0,c["AjaxHelper"].post({method:"MobileMessaging.setSMSAPICredential"},{provider:this.smsProvider,credentials:this.credentials},{errorElement:"#ajaxErrorManageSmsProviderSettings"}).then((function(){c["Matomo"].helper.redirect()})).finally((function(){e.isUpdatingAccount=!1})))},deleteAccount:function(){var e=this;c["Matomo"].helper.modalConfirm("#confirmDeleteAccount",{yes:function(){e.isDeletingAccount=!0,c["AjaxHelper"].fetch({method:"MobileMessaging.deleteSMSAPICredential"},{errorElement:"#ajaxErrorManageSmsProviderSettings"}).then((function(){e.isDeletingAccount=!1,c["Matomo"].helper.redirect()})).finally((function(){e.isDeletingAccount=!1}))}})},onUpdateOrDeleteClick:function(e){var t=e.target;"displayAccountForm"===t.id?this.showUpdateAccount():"deleteAccount"===t.id&&this.deleteAccount()}},computed:{isUpdateAccountPossible:function(){return!!this.smsProvider&&Object.keys(this.credentials).length>0&&Object.values(this.credentials).every((function(e){return!!e}))},updateOrDeleteAccountText:function(){return Object(c["translate"])("MobileMessaging_Settings_UpdateOrDeleteAccount",'<a id="displayAccountForm">',"</a>",'<a id="deleteAccount">',"</a>")},currentProviderDescription:function(){return this.smsProvider&&this.smsProviders?this.smsProviders[this.smsProvider]:""}}});P.render=M;var V=P;
+/*!
+ * Matomo - free/libre analytics platform
+ *
+ * @link https://matomo.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ */}})}));
+//# sourceMappingURL=MobileMessaging.umd.min.js.map \ No newline at end of file
diff --git a/plugins/MobileMessaging/vue/dist/umd.metadata.json b/plugins/MobileMessaging/vue/dist/umd.metadata.json
new file mode 100644
index 0000000000..dce4477a3c
--- /dev/null
+++ b/plugins/MobileMessaging/vue/dist/umd.metadata.json
@@ -0,0 +1,6 @@
+{
+ "dependsOn": [
+ "CoreHome",
+ "CorePluginsAdmin"
+ ]
+} \ No newline at end of file
diff --git a/plugins/MobileMessaging/vue/src/ManageSmsProvider/ManageSmsProvider.vue b/plugins/MobileMessaging/vue/src/ManageSmsProvider/ManageSmsProvider.vue
new file mode 100644
index 0000000000..cdca5e1603
--- /dev/null
+++ b/plugins/MobileMessaging/vue/src/ManageSmsProvider/ManageSmsProvider.vue
@@ -0,0 +1,208 @@
+<!--
+ 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>
+ <ActivityIndicator :loading="isDeletingAccount" />
+ <div id="ajaxErrorManageSmsProviderSettings" />
+ <p v-if="credentialSupplied">
+ <span v-if="credentialError">
+ {{ translate('MobileMessaging_Settings_CredentialInvalid', provider) }}<br />
+ {{ credentialError }}
+ </span>
+ <span v-else>
+ {{ translate('MobileMessaging_Settings_CredentialProvided', provider) }}
+ {{ creditLeft }}
+ </span>
+ <br />
+ <span v-html="updateOrDeleteAccountText" @click="onUpdateOrDeleteClick($event)"></span>
+ </p>
+ <p v-else>{{ translate('MobileMessaging_Settings_PleaseSignUp') }}</p>
+ <div
+ id="accountForm"
+ v-show="!credentialSupplied || showAccountForm"
+ v-form
+ >
+ <div>
+ <Field
+ uicontrol="select"
+ name="smsProviders"
+ v-model="smsProvider"
+ :title="translate('MobileMessaging_Settings_SMSProvider')"
+ :options="smsProviderOptions"
+ :value="provider"
+ >
+ </Field>
+ </div>
+ <SmsProviderCredentials
+ :provider="smsProvider"
+ v-model="credentials"
+ :model-value="credentials"
+ @update:model-value="credentials = $event;"
+ />
+ <SaveButton
+ id="apiAccountSubmit"
+ :disabled="!isUpdateAccountPossible"
+ :saving="isUpdatingAccount"
+ @confirm="updateAccount()"
+ />
+ <div
+ class="providerDescription"
+ v-html="$sanitize(currentProviderDescription)"
+ >
+ </div>
+ </div>
+ </div>
+</template>
+
+<script lang="ts">
+import { defineComponent } from 'vue';
+import {
+ translate,
+ AjaxHelper,
+ Matomo,
+ ActivityIndicator,
+} from 'CoreHome';
+import { Form, Field, SaveButton } from 'CorePluginsAdmin';
+import SmsProviderCredentials from '../SmsProviderCredentials/SmsProviderCredentials';
+
+interface ManageSmsProviderState {
+ isDeletingAccount: boolean;
+ isUpdatingAccount: boolean;
+ showAccountForm: boolean;
+ credentials: Record<string, unknown>;
+ smsProvider?: string;
+}
+
+export default defineComponent({
+ props: {
+ credentialSupplied: Boolean,
+ credentialError: String,
+ provider: String,
+ creditLeft: [Number, String],
+ smsProviderOptions: {
+ type: Object,
+ required: true,
+ },
+ smsProviders: {
+ type: Object,
+ required: true,
+ },
+ },
+ components: {
+ ActivityIndicator,
+ Field,
+ SaveButton,
+ SmsProviderCredentials,
+ },
+ directives: {
+ Form,
+ },
+ data(): ManageSmsProviderState {
+ return {
+ isDeletingAccount: false,
+ isUpdatingAccount: false,
+ showAccountForm: false,
+ credentials: {},
+ smsProvider: this.provider,
+ };
+ },
+ methods: {
+ deleteApiAccount() {
+ this.isDeletingAccount = true;
+ AjaxHelper.fetch(
+ {
+ method: 'MobileMessaging.deleteSMSAPICredential',
+ },
+ {
+ errorElement: '#ajaxErrorManageSmsProviderSettings',
+ },
+ ).then(() => {
+ Matomo.helper.redirect();
+ }).finally(() => {
+ this.isDeletingAccount = false;
+ });
+ },
+ showUpdateAccount() {
+ this.showAccountForm = true;
+ },
+ updateAccount() {
+ if (this.isUpdateAccountPossible) {
+ this.isUpdatingAccount = true;
+ AjaxHelper.post(
+ {
+ method: 'MobileMessaging.setSMSAPICredential',
+ },
+ {
+ provider: this.smsProvider,
+ credentials: this.credentials,
+ },
+ {
+ errorElement: '#ajaxErrorManageSmsProviderSettings',
+ },
+ ).then(() => {
+ Matomo.helper.redirect();
+ }).finally(() => {
+ this.isUpdatingAccount = false;
+ });
+ }
+ },
+ deleteAccount() {
+ Matomo.helper.modalConfirm('#confirmDeleteAccount', {
+ yes: () => {
+ this.isDeletingAccount = true;
+
+ AjaxHelper.fetch(
+ {
+ method: 'MobileMessaging.deleteSMSAPICredential',
+ },
+ {
+ errorElement: '#ajaxErrorManageSmsProviderSettings',
+ },
+ ).then(() => {
+ this.isDeletingAccount = false;
+ Matomo.helper.redirect();
+ }).finally(() => {
+ this.isDeletingAccount = false;
+ });
+ },
+ });
+ },
+ onUpdateOrDeleteClick(event: Event) {
+ const target = event.target as HTMLElement;
+ if (target.id === 'displayAccountForm') {
+ this.showUpdateAccount();
+ } else if (target.id === 'deleteAccount') {
+ this.deleteAccount();
+ }
+ },
+ },
+ computed: {
+ isUpdateAccountPossible() {
+ // possible if smsProvider is set and all credential field values are set to something
+ return !!this.smsProvider
+ && Object.keys(this.credentials).length > 0
+ && Object.values(this.credentials as Record<string, string>).every((v) => !!v);
+ },
+ updateOrDeleteAccountText() {
+ return translate(
+ 'MobileMessaging_Settings_UpdateOrDeleteAccount',
+ '<a id="displayAccountForm">',
+ '</a>',
+ '<a id="deleteAccount">',
+ '</a>',
+ );
+ },
+ currentProviderDescription() {
+ if (!this.smsProvider || !this.smsProviders) {
+ return '';
+ }
+
+ return this.smsProviders[this.smsProvider];
+ },
+ },
+});
+</script>
diff --git a/plugins/MobileMessaging/vue/src/SmsProviderCredentials/SmsProviderCredentials.adapter.ts b/plugins/MobileMessaging/vue/src/SmsProviderCredentials/SmsProviderCredentials.adapter.ts
new file mode 100644
index 0000000000..a25b626d77
--- /dev/null
+++ b/plugins/MobileMessaging/vue/src/SmsProviderCredentials/SmsProviderCredentials.adapter.ts
@@ -0,0 +1,69 @@
+/*!
+ * Matomo - free/libre analytics platform
+ *
+ * @link https://matomo.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ */
+
+import { nextTick } from 'vue';
+import { createAngularJsAdapter, removeAngularJsSpecificProperties } from 'CoreHome';
+import { INgModelController, ITimeoutService } from 'angular';
+import SmsProviderCredentials from './SmsProviderCredentials.vue';
+
+export default createAngularJsAdapter<[ITimeoutService]>({
+ component: SmsProviderCredentials,
+ scope: {
+ provider: {
+ angularJsBind: '=',
+ },
+ credentials: {
+ angularJsBind: '=value',
+ },
+ },
+ directiveName: 'smsProviderCredentials',
+ transclude: true,
+ events: {
+ 'update:modelValue': (newValue, vm, scope, element, attrs, ngModel, $timeout) => {
+ const currentValue = ngModel ? ngModel.$viewValue : scope.value;
+ if (newValue !== currentValue) {
+ $timeout(() => {
+ if (!ngModel) {
+ scope.value = newValue;
+ return;
+ }
+
+ // ngModel being used
+ (ngModel as INgModelController).$setViewValue(newValue);
+ (ngModel as INgModelController).$render(); // not detected by the watch for some reason
+ });
+ }
+ },
+ },
+ postCreate(vm, scope, element, attrs, controller) {
+ const ngModel = controller as INgModelController;
+
+ if (!ngModel) {
+ scope.$watch('value', (newVal: unknown) => {
+ if (newVal !== vm.modelValue) {
+ nextTick(() => {
+ vm.modelValue = newVal;
+ });
+ }
+ });
+ return;
+ }
+
+ // ngModel being used
+ ngModel.$render = () => {
+ nextTick(() => {
+ vm.modelValue = removeAngularJsSpecificProperties(ngModel.$viewValue);
+ });
+ };
+
+ if (typeof scope.value !== 'undefined') {
+ (ngModel as INgModelController).$setViewValue(scope.value);
+ } else {
+ ngModel.$setViewValue(vm.modelValue);
+ }
+ },
+});
diff --git a/plugins/MobileMessaging/vue/src/SmsProviderCredentials/SmsProviderCredentials.vue b/plugins/MobileMessaging/vue/src/SmsProviderCredentials/SmsProviderCredentials.vue
new file mode 100644
index 0000000000..34a6d8b8ff
--- /dev/null
+++ b/plugins/MobileMessaging/vue/src/SmsProviderCredentials/SmsProviderCredentials.vue
@@ -0,0 +1,82 @@
+<!--
+ 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 v-if="fields">
+ <Field
+ v-for="field in fields"
+ :key="field.name"
+ :uicontrol="field.type"
+ :name="field.name"
+ :model-value="modelValue?.[field.name]"
+ @update:model-value="$emit('update:modelValue', { ...modelValue, [field.name]: $event })"
+ :title="translate(field.title)"
+ />
+ </div>
+</template>
+
+<script lang="ts">
+import { defineComponent, reactive } from 'vue';
+import { AjaxHelper } from 'CoreHome';
+import { Field } from 'CorePluginsAdmin';
+
+interface FieldInfo {
+ name: string;
+ type: string;
+ title: string;
+}
+
+const allFieldsByProvider = reactive<Record<string, FieldInfo[]>>({});
+
+export default defineComponent({
+ props: {
+ provider: {
+ type: String,
+ required: true,
+ },
+ modelValue: {
+ type: Object,
+ required: true,
+ },
+ },
+ emits: ['update:modelValue'],
+ components: {
+ Field,
+ },
+ watch: {
+ provider() {
+ // unset credentials when new provider is chosen
+ this.$emit('update:modelValue', {});
+
+ // fetch fields for provider
+ this.getCredentialFields();
+ },
+ },
+ created() {
+ this.getCredentialFields();
+ },
+ methods: {
+ getCredentialFields() {
+ if (allFieldsByProvider[this.provider]) {
+ return;
+ }
+
+ AjaxHelper.fetch({
+ module: 'MobileMessaging',
+ action: 'getCredentialFields',
+ provider: this.provider,
+ }).then((fields) => {
+ allFieldsByProvider[this.provider] = fields;
+ });
+ },
+ },
+ computed: {
+ fields() {
+ return allFieldsByProvider[this.provider];
+ },
+ },
+});
+</script>
diff --git a/plugins/MobileMessaging/vue/src/index.ts b/plugins/MobileMessaging/vue/src/index.ts
new file mode 100644
index 0000000000..2bddb6f845
--- /dev/null
+++ b/plugins/MobileMessaging/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 './SmsProviderCredentials/SmsProviderCredentials.adapter';
+
+export { default as ManageSmsProvider } from './ManageSmsProvider/ManageSmsProvider.vue';
+export { default as SmsProviderCredentials } from './SmsProviderCredentials/SmsProviderCredentials.vue';
diff --git a/plugins/Morpheus/javascripts/piwikHelper.js b/plugins/Morpheus/javascripts/piwikHelper.js
index 165a24d7b6..7fc4c9ddb9 100644
--- a/plugins/Morpheus/javascripts/piwikHelper.js
+++ b/plugins/Morpheus/javascripts/piwikHelper.js
@@ -195,7 +195,8 @@ window.piwikHelper = {
return;
}
- var camelName = toCamelCase(this.name);
+ // append with underscore so reserved javascripy keywords aren't accidentally used
+ var camelName = toCamelCase(this.name) + '_';
paramsStr += ':' + this.name + '=' + JSON.stringify(camelName) + ' ';
var value = this.value;
diff --git a/tests/UI/expected-screenshots/UIIntegrationTest_admin_settings_mobilemessaging_provider.png b/tests/UI/expected-screenshots/UIIntegrationTest_admin_settings_mobilemessaging_provider.png
index a47ee9174b..22c2d630b4 100644
--- a/tests/UI/expected-screenshots/UIIntegrationTest_admin_settings_mobilemessaging_provider.png
+++ b/tests/UI/expected-screenshots/UIIntegrationTest_admin_settings_mobilemessaging_provider.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:a210ad533741772461a36c3b1b1379d6e27e4e18c7399f2131bc953fc839281b
-size 120233
+oid sha256:02a6d7124ce7acf2fbfadb6c306f934abaacfe625514b49a6c7db25f41c086a7
+size 117157
diff --git a/tests/UI/specs/UIIntegration_spec.js b/tests/UI/specs/UIIntegration_spec.js
index 67758c3f04..e635ff0c3e 100644
--- a/tests/UI/specs/UIIntegration_spec.js
+++ b/tests/UI/specs/UIIntegration_spec.js
@@ -814,12 +814,13 @@ describe("UIIntegrationTest", function () { // TODO: Rename to Piwik?
pageWrap = await page.$('.pageWrap');
expect(await pageWrap.screenshot()).to.matchImage('admin_settings_mobilemessaging');
- });
+ })
it('should switch the SMS provider correctly', async function () {
await page.evaluate(function () {
- $('[name=smsProviders] ul li:nth-child(2)').click();
+ $('[name=smsProviders]').val('string:Clockwork').trigger('change');
});
+ await page.waitForNetworkIdle();
pageWrap = await page.$('.pageWrap');
expect(await pageWrap.screenshot()).to.matchImage('admin_settings_mobilemessaging_provider');