diff options
24 files changed, 1102 insertions, 322 deletions
diff --git a/plugins/UsersManager/UsersManager.php b/plugins/UsersManager/UsersManager.php index e5620260ef..d45083b1f2 100644 --- a/plugins/UsersManager/UsersManager.php +++ b/plugins/UsersManager/UsersManager.php @@ -134,8 +134,6 @@ class UsersManager extends \Piwik\Plugin $jsFiles[] = "plugins/UsersManager/angularjs/user-permissions-edit/user-permissions-edit.component.js"; $jsFiles[] = "plugins/UsersManager/angularjs/personal-settings/personal-settings.controller.js"; $jsFiles[] = "plugins/UsersManager/angularjs/personal-settings/anonymous-settings.controller.js"; - $jsFiles[] = "plugins/UsersManager/angularjs/permissions-metadata/permissions-metadata.service.js"; - $jsFiles[] = "plugins/UsersManager/angularjs/capabilities-edit/capabilities-edit.component.js"; } /** @@ -149,7 +147,7 @@ class UsersManager extends \Piwik\Plugin $stylesheets[] = "plugins/UsersManager/angularjs/paged-users-list/paged-users-list.component.less"; $stylesheets[] = "plugins/UsersManager/angularjs/user-edit-form/user-edit-form.component.less"; $stylesheets[] = "plugins/UsersManager/angularjs/user-permissions-edit/user-permissions-edit.component.less"; - $stylesheets[] = "plugins/UsersManager/angularjs/capabilities-edit/capabilities-edit.component.less"; + $stylesheets[] = "plugins/UsersManager/vue/src/CapabilitiesEdit/CapabilitiesEdit.less"; } /** diff --git a/plugins/UsersManager/angularjs/capabilities-edit/capabilities-edit.component.html b/plugins/UsersManager/angularjs/capabilities-edit/capabilities-edit.component.html deleted file mode 100644 index 4eee7fe20e..0000000000 --- a/plugins/UsersManager/angularjs/capabilities-edit/capabilities-edit.component.html +++ /dev/null @@ -1,48 +0,0 @@ -<div class="capabilitiesEdit" ng-class="{ busy: $ctrl.isBusy }"> - <div - class="chip" - ng-repeat="capability in $ctrl.availableCapabilities" - ng-if="$ctrl.capabilitiesSet[capability.id]" - > - <span - class="capability-name" - title="{{ capability.description }} {{ ($ctrl.isIncludedInRole(capability) ? ('<br/><br/>' + ('UsersManager_IncludedInUsersRole'|translate)): '') }}" - > - {{ capability.category }}: {{ capability.name }} - </span> - <span - class="icon-close" - ng-if="!$ctrl.isIncludedInRole(capability)" - ng-click="$ctrl.capabilityToAddOrRemoveId = capability.id; $ctrl.onToggleCapability(false)" - ></span> - </div> - - <div piwik-field uicontrol="expandable-select" - name="add_capability" - full-width="true" - ng-change="$ctrl.onToggleCapability(true)" - ng-model="$ctrl.capabilityToAddOrRemoveId" - options="$ctrl.availableCapabilitiesGrouped" - data-disabled="$ctrl.isBusy" - ng-if="$ctrl.availableCapabilitiesGrouped.length" - class="addCapability" - > - </div> - - <div class="ui-confirm confirmCapabilityToggle modal"> - <div class="modal-content"> - <h2 ng-if="$ctrl.isAddingCapability" piwik-translate="UsersManager_AreYouSureAddCapability"> - <strong>{{ $ctrl.userLogin }}</strong>::<strong>{{ $ctrl.capabilityToAddOrRemove.name }}</strong>::<strong>{{ $ctrl.siteName }}</strong> - </h2> - <h2 ng-if="!$ctrl.isAddingCapability" piwik-translate="UsersManager_AreYouSureRemoveCapability"> - <strong>{{ $ctrl.capabilityToAddOrRemove.name }}</strong>::<strong>{{ $ctrl.userLogin }}</strong>::<strong>{{ $ctrl.siteName }}</strong> - </h2> - </div> - <div class="modal-footer"> - <a href="" class="modal-action modal-close btn" ng-click="$ctrl.toggleCapability()">{{:: 'General_Yes'|translate }}</a> - <a href="" class="modal-action modal-close modal-no" ng-click="$ctrl.capabilityToAddOrRemove = null; $ctrl.capabilityToAddOrRemoveId = null"> - {{:: 'General_No'|translate }} - </a> - </div> - </div> -</div> diff --git a/plugins/UsersManager/angularjs/capabilities-edit/capabilities-edit.component.js b/plugins/UsersManager/angularjs/capabilities-edit/capabilities-edit.component.js deleted file mode 100644 index 6efe3129a0..0000000000 --- a/plugins/UsersManager/angularjs/capabilities-edit/capabilities-edit.component.js +++ /dev/null @@ -1,214 +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: - * <piwik-capabilities-edit> - */ -(function () { - angular.module('piwikApp').component('piwikCapabilitiesEdit', { - templateUrl: 'plugins/UsersManager/angularjs/capabilities-edit/capabilities-edit.component.html?cb=' + piwik.cacheBuster, - bindings: { - idsite: '<', - siteName: '<', - userLogin: '<', - userRole: '<', - capabilities: '<', - onCapabilitiesChange: '&', - }, - controller: CapabilitiesEditController - }); - - CapabilitiesEditController.$inject = ['piwikApi', 'permissionsMetadataService', 'piwik', '$element']; - - function CapabilitiesEditController(piwikApi, permissionsMetadataService, piwik, $element) { - var vm = this; - - vm.isBusy = false; - vm.availableCapabilities = []; - vm.availableCapabilitiesGrouped = []; - vm.capabilitiesSet = {}; - - // intermediate state - vm.isAddingCapability = false; - vm.capabilityToAddOrRemoveId = null; - vm.capabilityToAddOrRemove = null; - - vm.$onInit = $onInit; - vm.$onChanges = $onChanges; - vm.onToggleCapability = onToggleCapability; - vm.toggleCapability = toggleCapability; - vm.isIncludedInRole = isIncludedInRole; - - function $onInit() { - fetchAvailableCapabilities(); - - if (typeof vm.capabilities === 'undefined') { - fetchCapabilities(); - } - } - - function $onChanges() { - setCapabilitiesSet(); - } - - function isIncludedInRole(capability) { - return capability.includedInRoles.indexOf(vm.userRole) !== -1; - } - - function fetchAvailableCapabilities() { - permissionsMetadataService.getAllCapabilities() - .then(function (capabilities) { - vm.availableCapabilities = capabilities; - setCapabilitiesSet(); - setAvailableCapabilitiesDropdown(); - }); - } - - function fetchCapabilities() { - vm.isBusy = true; - piwikApi.fetch({ - method: 'UsersManager.getUsersPlusRole', - limit: '1', - filter_search: vm.userLogin, - }).then(function (user) { - if (!user || !user.capabilities) { - return []; - } - - return user.capabilities; - }).then(function (capabilities) { - vm.capabilities = capabilities; - setCapabilitiesSet(); - setAvailableCapabilitiesDropdown(); - })['finally'](function () { - vm.isBusy = false; - }); - } - - function setCapabilitiesSet() { - vm.capabilitiesSet = {}; - (vm.capabilities || []).forEach(function (capability) { - vm.capabilitiesSet[capability] = true; - }); - (vm.availableCapabilities || []).forEach(function (capability) { - if (vm.isIncludedInRole(capability)) { - vm.capabilitiesSet[capability.id] = true; - } - }); - } - - function setAvailableCapabilitiesDropdown() { - var availableCapabilitiesGrouped = []; - vm.availableCapabilities.forEach(function (capability) { - if (vm.capabilitiesSet[capability.id]) { - return; - } - - availableCapabilitiesGrouped.push({ - group: capability.category, - key: capability.id, - value: capability.name, - tooltip: capability.description, - }); - }); - vm.availableCapabilitiesGrouped = availableCapabilitiesGrouped; - vm.availableCapabilitiesGrouped.sort(function (lhs, rhs) { - if (lhs.group === rhs.group) { - if (lhs.value === rhs.value) { - return 0; - } - return lhs.value < rhs.value ? -1 : 1; - } - return lhs.group < rhs.group ? -1 : 1; - }); - } - - function onToggleCapability(isAdd) { - vm.isAddingCapability = isAdd; - - vm.capabilityToAddOrRemove = null; - vm.availableCapabilities.forEach(function (capability) { - if (capability.id === vm.capabilityToAddOrRemoveId) { - vm.capabilityToAddOrRemove = capability; - } - }); - - $element.find('.confirmCapabilityToggle').modal({ - dismissible: false, - yes: function () { - }, - }).modal('open'); - } - - function toggleCapability() { - if (vm.isAddingCapability) { - addCapability(vm.capabilityToAddOrRemove); - } else { - removeCapability(vm.capabilityToAddOrRemove); - } - } - - function addCapability(capability) { - vm.isBusy = true; - piwikApi.post({ - method: 'UsersManager.addCapabilities', - }, { - userLogin: vm.userLogin, - capabilities: capability.id, - idSites: vm.idsite - }).then(function () { - vm.onCapabilitiesChange.call({ - capabilities: getCapabilitiesList(), - }); - - setCapabilitiesSet(); - setAvailableCapabilitiesDropdown(); - })['finally'](function () { - vm.isBusy = false; - vm.capabilityToAddOrRemove = null; - vm.capabilityToAddOrRemoveId = null; - }); - } - - function removeCapability(capability) { - vm.isBusy = true; - piwikApi.post({ - method: 'UsersManager.removeCapabilities', - }, { - userLogin: vm.userLogin, - capabilities: capability.id, - idSites: vm.idsite - }).then(function () { - vm.onCapabilitiesChange.call({ - capabilities: getCapabilitiesList(), - }); - - setCapabilitiesSet(); - setAvailableCapabilitiesDropdown(); - })['finally'](function () { - vm.isBusy = false; - vm.capabilityToAddOrRemove = null; - vm.capabilityToAddOrRemoveId = null; - }); - } - - function getCapabilitiesList() { - var result = []; - vm.availableCapabilities.forEach(function (capability) { - if (vm.isIncludedInRole(capability)) { - return; - } - - if (vm.capabilitiesSet[capability.id]) { - result.push(capability.id); - } - }); - return result; - } - } -})(); diff --git a/plugins/UsersManager/angularjs/capability-edit/capability-edit.component.html b/plugins/UsersManager/angularjs/capability-edit/capability-edit.component.html deleted file mode 100644 index e20609a83b..0000000000 --- a/plugins/UsersManager/angularjs/capability-edit/capability-edit.component.html +++ /dev/null @@ -1,3 +0,0 @@ -<div class="capabilityEdit"> - {{ capabilityEdit.myProperty }} -</div>
\ No newline at end of file diff --git a/plugins/UsersManager/angularjs/capability-edit/capability-edit.component.less b/plugins/UsersManager/angularjs/capability-edit/capability-edit.component.less deleted file mode 100644 index a59690b170..0000000000 --- a/plugins/UsersManager/angularjs/capability-edit/capability-edit.component.less +++ /dev/null @@ -1,3 +0,0 @@ -.capabilityEdit { - // ... -}
\ No newline at end of file diff --git a/plugins/UsersManager/angularjs/permissions-metadata/permissions-metadata.service.js b/plugins/UsersManager/angularjs/permissions-metadata/permissions-metadata.service.js deleted file mode 100644 index 1728041412..0000000000 --- a/plugins/UsersManager/angularjs/permissions-metadata/permissions-metadata.service.js +++ /dev/null @@ -1,35 +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: - * <piwik-capabilities-edit> - */ -(function () { - angular.module('piwikApp').factory('permissionsMetadataService', PermissionsMetadataService); - - PermissionsMetadataService.$inject = ['piwikApi', '$q']; - - function PermissionsMetadataService(piwikApi, $q) { - var allCapabilities; - - return { - getAllCapabilities: function () { - if (allCapabilities) { - return $q.when(allCapabilities); - } - - return piwikApi.fetch({ - method: 'UsersManager.getAvailableCapabilities', - }).then(function (capabilities) { - allCapabilities = capabilities; - return allCapabilities; - }); - }, - }; - } -})(); diff --git a/plugins/UsersManager/tests/UI/UsersManager_spec.js b/plugins/UsersManager/tests/UI/UsersManager_spec.js index e53e654cd3..475bba3d8c 100644 --- a/plugins/UsersManager/tests/UI/UsersManager_spec.js +++ b/plugins/UsersManager/tests/UI/UsersManager_spec.js @@ -332,6 +332,7 @@ describe("UsersManager", function () { it('should select all displayed rows when the select all checkbox is clicked', async function () { await page.click('.userPermissionsEdit th.select-cell input + span'); await page.waitForTimeout(250); // for checkbox animations + await page.mouse.move(-10, -10); expect(await page.screenshotSelector('.usersManager')).to.matchImage({ imageName: 'permissions_select_all', diff --git a/plugins/UsersManager/tests/UI/expected-screenshots/UsersManager_permissions_all_sites_access.png b/plugins/UsersManager/tests/UI/expected-screenshots/UsersManager_permissions_all_sites_access.png index ca5768d6ef..3ce1307b10 100644 --- a/plugins/UsersManager/tests/UI/expected-screenshots/UsersManager_permissions_all_sites_access.png +++ b/plugins/UsersManager/tests/UI/expected-screenshots/UsersManager_permissions_all_sites_access.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d508ef919076c7de2aca6ef361ca5d8c508d340b1bc6d2a3e60e3ca6314bb34e -size 102083 +oid sha256:1187cff49198d1ec7784bcf8ef9c57813b4325c0e6778117dd32b30d777c4594 +size 100480 diff --git a/plugins/UsersManager/tests/UI/expected-screenshots/UsersManager_permissions_bulk_access_set_all.png b/plugins/UsersManager/tests/UI/expected-screenshots/UsersManager_permissions_bulk_access_set_all.png index 19208deb3b..f6531a6194 100644 --- a/plugins/UsersManager/tests/UI/expected-screenshots/UsersManager_permissions_bulk_access_set_all.png +++ b/plugins/UsersManager/tests/UI/expected-screenshots/UsersManager_permissions_bulk_access_set_all.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:990108c86e38681e565ccd517fb02369ad98f43a80e7892fe33a940781176596 -size 80978 +oid sha256:aaffd292e9b45fe77a6985984a20507d4ac198078074139c4b83eeab1fc0b2b7 +size 80848 diff --git a/plugins/UsersManager/tests/UI/expected-screenshots/UsersManager_permissions_capability_single_site.png b/plugins/UsersManager/tests/UI/expected-screenshots/UsersManager_permissions_capability_single_site.png index 50f12fb58a..9365527f47 100644 --- a/plugins/UsersManager/tests/UI/expected-screenshots/UsersManager_permissions_capability_single_site.png +++ b/plugins/UsersManager/tests/UI/expected-screenshots/UsersManager_permissions_capability_single_site.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9484fcaf803922946c6cdbddfcfce0908fed6e77619655022d2454ed595f3f4d -size 92451 +oid sha256:7245e5f4269836c8e2cde0c44de8ddb12423eb63f2e36d1ddb72c2926225ea5d +size 92457 diff --git a/plugins/UsersManager/tests/UI/expected-screenshots/UsersManager_permissions_next.png b/plugins/UsersManager/tests/UI/expected-screenshots/UsersManager_permissions_next.png index b655bd93ca..f22b6b6284 100644 --- a/plugins/UsersManager/tests/UI/expected-screenshots/UsersManager_permissions_next.png +++ b/plugins/UsersManager/tests/UI/expected-screenshots/UsersManager_permissions_next.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:846991e7dfd320e07e82212bc46bd7bef663289c17863a81f6881aef5df58698 -size 92113 +oid sha256:2ec58a4d3d51a8b13bad20f858453cba578e68b5a946ecede4d2b0174a76d83f +size 92466 diff --git a/plugins/UsersManager/tests/UI/expected-screenshots/UsersManager_permissions_remove_single.png b/plugins/UsersManager/tests/UI/expected-screenshots/UsersManager_permissions_remove_single.png index efeb7da210..367f2c5b10 100644 --- a/plugins/UsersManager/tests/UI/expected-screenshots/UsersManager_permissions_remove_single.png +++ b/plugins/UsersManager/tests/UI/expected-screenshots/UsersManager_permissions_remove_single.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5b1ac3c0fba9928c19cb39b56cc13ce064f9a8359e2fe91ee887269efd7b64e1 -size 90338 +oid sha256:86efc969c58f87ddfe9df3451d585cfe3710d851354e71f4d45b52225b03c320 +size 90565 diff --git a/plugins/UsersManager/tests/UI/expected-screenshots/UsersManager_permissions_select_multiple.png b/plugins/UsersManager/tests/UI/expected-screenshots/UsersManager_permissions_select_multiple.png index 0436cb04b7..69215c0e74 100644 --- a/plugins/UsersManager/tests/UI/expected-screenshots/UsersManager_permissions_select_multiple.png +++ b/plugins/UsersManager/tests/UI/expected-screenshots/UsersManager_permissions_select_multiple.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4b68f0989997324e8575cfaa9ad1ba67bdc62aad3673626a1af495f74749bcba -size 92270 +oid sha256:bb5d14dcd6075e80cdbf488ad9e03dc6a830dbfb8b31b3f0a172c9396697c82b +size 92579 diff --git a/plugins/UsersManager/tests/UI/expected-screenshots/UsersManager_permissions_single_site_access.png b/plugins/UsersManager/tests/UI/expected-screenshots/UsersManager_permissions_single_site_access.png index 52d4c428fb..ab419ee5f9 100644 --- a/plugins/UsersManager/tests/UI/expected-screenshots/UsersManager_permissions_single_site_access.png +++ b/plugins/UsersManager/tests/UI/expected-screenshots/UsersManager_permissions_single_site_access.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c69e778f61c9697067eea1cf4da7293161b3e19fd5d20d8523a7cb87cc36a0e2 -size 89089 +oid sha256:cec452b68a9801e37be4050f2454d5656844c5ccdd31af643d1e0583dbf8df08 +size 89100 diff --git a/plugins/UsersManager/vue/dist/UsersManager.umd.js b/plugins/UsersManager/vue/dist/UsersManager.umd.js new file mode 100644 index 0000000000..ae145d094b --- /dev/null +++ b/plugins/UsersManager/vue/dist/UsersManager.umd.js @@ -0,0 +1,596 @@ +(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["UsersManager"] = factory(require("CoreHome"), require("vue"), require("CorePluginsAdmin")); + else + root["UsersManager"] = 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/UsersManager/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__, "CapabilitiesEdit", function() { return /* reexport */ CapabilitiesEdit; }); + +// 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/UsersManager/vue/src/CapabilitiesEdit/CapabilitiesEdit.vue?vue&type=template&id=259d8ccf + +var _hoisted_1 = ["title"]; +var _hoisted_2 = ["onClick"]; +var _hoisted_3 = { + key: 0, + class: "addCapability" +}; +var _hoisted_4 = { + class: "ui-confirm confirmCapabilityToggle modal", + ref: "confirmCapabilityToggleModal" +}; +var _hoisted_5 = { + class: "modal-content" +}; +var _hoisted_6 = ["innerHTML"]; +var _hoisted_7 = ["innerHTML"]; +var _hoisted_8 = { + class: "modal-footer" +}; +function render(_ctx, _cache, $props, $setup, $data, $options) { + var _component_Field = Object(external_commonjs_vue_commonjs2_vue_root_Vue_["resolveComponent"])("Field"); + + return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", { + class: Object(external_commonjs_vue_commonjs2_vue_root_Vue_["normalizeClass"])(["capabilitiesEdit", { + busy: _ctx.isBusy + }]) + }, [(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.actualCapabilities, function (capability) { + return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", { + key: capability.id, + class: "chip" + }, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("span", { + class: "capability-name", + title: "".concat(capability.description, " ").concat(_ctx.isIncludedInRole(capability) ? "<br/><br/>".concat(_ctx.translate('UsersManager_IncludedInUsersRole')) : '') + }, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(capability.category) + ": " + Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(capability.name), 9, _hoisted_1), !_ctx.isIncludedInRole(capability) ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("span", { + key: 0, + class: "icon-close", + onClick: function onClick($event) { + _ctx.capabilityToRemoveId = capability.id; + + _ctx.onToggleCapability(false); + } + }, null, 8, _hoisted_2)) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true)]); + }), 128)), _ctx.availableCapabilitiesGrouped.length ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", _hoisted_3, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createVNode"])(_component_Field, { + "model-value": _ctx.capabilityToAddId, + "onUpdate:modelValue": _cache[0] || (_cache[0] = function ($event) { + _ctx.capabilityToAddId = $event; + + _ctx.onToggleCapability(true); + }), + disabled: _ctx.isBusy, + uicontrol: "expandable-select", + name: "add_capability", + "full-width": true, + options: _ctx.availableCapabilitiesGrouped + }, null, 8, ["model-value", "disabled", "options"])])) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", _hoisted_4, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", _hoisted_5, [_ctx.isAddingCapability ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("h2", { + key: 0, + innerHTML: _ctx.$sanitize(_ctx.confirmAddCapabilityToggleContent) + }, null, 8, _hoisted_6)) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true), !_ctx.isAddingCapability ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("h2", { + key: 1, + innerHTML: _ctx.$sanitize(_ctx.confirmCapabilityToggleContent) + }, null, 8, _hoisted_7)) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true)]), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", _hoisted_8, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("a", { + href: "", + class: "modal-action modal-close btn", + onClick: _cache[1] || (_cache[1] = Object(external_commonjs_vue_commonjs2_vue_root_Vue_["withModifiers"])(function ($event) { + return _ctx.toggleCapability(); + }, ["prevent"])) + }, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('General_Yes')), 1), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("a", { + href: "", + class: "modal-action modal-close modal-no", + onClick: _cache[2] || (_cache[2] = Object(external_commonjs_vue_commonjs2_vue_root_Vue_["withModifiers"])(function ($event) { + _ctx.capabilityToAddOrRemove = null; + _ctx.capabilityToAddId = null; + _ctx.capabilityToRemoveId = null; + }, ["prevent"])) + }, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('General_No')), 1)])], 512)], 2); +} +// CONCATENATED MODULE: ./plugins/UsersManager/vue/src/CapabilitiesEdit/CapabilitiesEdit.vue?vue&type=template&id=259d8ccf + +// EXTERNAL MODULE: external "CorePluginsAdmin" +var external_CorePluginsAdmin_ = __webpack_require__("a5a2"); + +// CONCATENATED MODULE: ./plugins/UsersManager/vue/src/CapabilitiesStore/CapabilitiesStore.ts +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } + +function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } + +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; } + +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + + + +var CapabilitiesStore_CapabilitiesStore = /*#__PURE__*/function () { + function CapabilitiesStore() { + var _this = this; + + _classCallCheck(this, CapabilitiesStore); + + _defineProperty(this, "privateState", Object(external_commonjs_vue_commonjs2_vue_root_Vue_["reactive"])({ + isLoading: false, + capabilities: [] + })); + + _defineProperty(this, "state", Object(external_commonjs_vue_commonjs2_vue_root_Vue_["computed"])(function () { + return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["readonly"])(_this.privateState); + })); + + _defineProperty(this, "capabilities", Object(external_commonjs_vue_commonjs2_vue_root_Vue_["computed"])(function () { + return _this.state.value.capabilities; + })); + + _defineProperty(this, "isLoading", Object(external_commonjs_vue_commonjs2_vue_root_Vue_["computed"])(function () { + return _this.state.value.isLoading; + })); + + _defineProperty(this, "fetchPromise", void 0); + + this.fetchCapabilities(); + } + + _createClass(CapabilitiesStore, [{ + key: "fetchCapabilities", + value: function fetchCapabilities() { + var _this2 = this; + + if (!this.fetchPromise) { + this.privateState.isLoading = true; + this.fetchPromise = external_CoreHome_["AjaxHelper"].fetch({ + method: 'UsersManager.getAvailableCapabilities' + }).then(function (capabilities) { + _this2.privateState.capabilities = capabilities; + return _this2.capabilities.value; + }).finally(function () { + _this2.privateState.isLoading = false; + }); + } + + return this.fetchPromise; + } + }]); + + return CapabilitiesStore; +}(); + +/* harmony default export */ var src_CapabilitiesStore_CapabilitiesStore = (Object(external_CoreHome_["lazyInitSingleton"])(CapabilitiesStore_CapabilitiesStore)); +// 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/UsersManager/vue/src/CapabilitiesEdit/CapabilitiesEdit.vue?vue&type=script&lang=ts + + + + +var _window = window, + $ = _window.$; +/* harmony default export */ var CapabilitiesEditvue_type_script_lang_ts = (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["defineComponent"])({ + props: { + idsite: [String, Number], + siteName: { + type: String, + required: true + }, + userLogin: { + type: String, + required: true + }, + userRole: { + type: String, + required: true + }, + capabilities: Array + }, + components: { + Field: external_CorePluginsAdmin_["Field"] + }, + data: function data() { + return { + theCapabilities: this.capabilities || [], + isBusy: false, + isAddingCapability: false, + capabilityToAddId: null, + capabilityToRemoveId: null, + capabilityToAddOrRemove: null + }; + }, + emits: ['change'], + watch: { + capabilities: function capabilities(newValue) { + if (newValue) { + this.theCapabilities = newValue; + } + } + }, + created: function created() { + var _this = this; + + if (!this.capabilities) { + this.isBusy = true; + external_CoreHome_["AjaxHelper"].fetch({ + method: 'UsersManager.getUsersPlusRole', + limit: '1', + filter_search: this.userLogin + }).then(function (user) { + if (!user || !user.capabilities) { + return []; + } + + return user.capabilities; + }).then(function (capabilities) { + _this.theCapabilities = capabilities; + }).finally(function () { + _this.isBusy = false; + }); + } else { + this.theCapabilities = this.capabilities; + } + }, + methods: { + onToggleCapability: function onToggleCapability(isAdd) { + var _this2 = this; + + this.isAddingCapability = isAdd; + var capabilityToAddOrRemoveId = isAdd ? this.capabilityToAddId : this.capabilityToRemoveId; + this.capabilityToAddOrRemove = null; + this.availableCapabilities.forEach(function (capability) { + if (capability.id === capabilityToAddOrRemoveId) { + _this2.capabilityToAddOrRemove = capability; + } + }); + + if (this.$refs.confirmCapabilityToggleModal) { + $(this.$refs.confirmCapabilityToggleModal).modal({ + dismissible: false, + yes: function yes() { + return null; + } + }).modal('open'); + } + }, + toggleCapability: function toggleCapability() { + if (this.isAddingCapability) { + this.addCapability(this.capabilityToAddOrRemove); + } else { + this.removeCapability(this.capabilityToAddOrRemove); + } + }, + isIncludedInRole: function isIncludedInRole(capability) { + return (capability.includedInRoles || []).indexOf(this.userRole) !== -1; + }, + getCapabilitiesList: function getCapabilitiesList() { + var _this3 = this; + + var result = []; + this.availableCapabilities.forEach(function (capability) { + if (_this3.isIncludedInRole(capability)) { + return; + } + + if (_this3.capabilitiesSet[capability.id]) { + result.push(capability.id); + } + }); + return result; + }, + addCapability: function addCapability(capability) { + var _this4 = this; + + this.isBusy = true; + external_CoreHome_["AjaxHelper"].post({ + method: 'UsersManager.addCapabilities' + }, { + userLogin: this.userLogin, + capabilities: capability.id, + idSites: this.idsite + }).then(function () { + _this4.$emit('change', _this4.getCapabilitiesList()); + }).finally(function () { + _this4.isBusy = false; + _this4.capabilityToAddOrRemove = null; + _this4.capabilityToAddId = null; + _this4.capabilityToRemoveId = null; + }); + }, + removeCapability: function removeCapability(capability) { + var _this5 = this; + + this.isBusy = true; + external_CoreHome_["AjaxHelper"].post({ + method: 'UsersManager.removeCapabilities' + }, { + userLogin: this.userLogin, + capabilities: capability.id, + idSites: this.idsite + }).then(function () { + _this5.$emit('change', _this5.getCapabilitiesList()); + }).finally(function () { + _this5.isBusy = false; + _this5.capabilityToAddOrRemove = null; + _this5.capabilityToAddId = null; + _this5.capabilityToRemoveId = null; + }); + } + }, + computed: { + availableCapabilities: function availableCapabilities() { + return src_CapabilitiesStore_CapabilitiesStore.capabilities.value; + }, + confirmAddCapabilityToggleContent: function confirmAddCapabilityToggleContent() { + return Object(external_CoreHome_["translate"])('UsersManager_AreYouSureAddCapability', "<strong>".concat(this.userLogin, "</strong>"), "<strong>".concat(this.capabilityToAddOrRemove ? this.capabilityToAddOrRemove.name : '', "</strong>"), "<strong>".concat(this.siteNameText, "</strong>")); + }, + confirmCapabilityToggleContent: function confirmCapabilityToggleContent() { + return Object(external_CoreHome_["translate"])('UsersManager_AreYouSureRemoveCapability', "<strong>".concat(this.capabilityToAddOrRemove ? this.capabilityToAddOrRemove.name : '', "</strong>"), "<strong>".concat(this.userLogin, "</strong>"), "<strong>".concat(this.siteNameText, "</strong>")); + }, + siteNameText: function siteNameText() { + return external_CoreHome_["Matomo"].helper.htmlEntities(this.siteName); + }, + availableCapabilitiesGrouped: function availableCapabilitiesGrouped() { + var _this6 = this; + + var availableCapabilitiesGrouped = this.availableCapabilities.filter(function (c) { + return !_this6.capabilitiesSet[c.id]; + }).map(function (c) { + return { + group: c.category, + key: c.id, + value: c.name, + tooltip: c.description + }; + }); + availableCapabilitiesGrouped.sort(function (lhs, rhs) { + if (lhs.group === rhs.group) { + if (lhs.value === rhs.value) { + return 0; + } + + return lhs.value < rhs.value ? -1 : 1; + } + + return lhs.group < rhs.group ? -1 : 1; + }); + return availableCapabilitiesGrouped; + }, + capabilitiesSet: function capabilitiesSet() { + var _this7 = this; + + var capabilitiesSet = {}; + var capabilities = this.theCapabilities; + (capabilities || []).forEach(function (capability) { + capabilitiesSet[capability] = true; + }); + (this.availableCapabilities || []).forEach(function (capability) { + if (_this7.isIncludedInRole(capability)) { + capabilitiesSet[capability.id] = true; + } + }); + return capabilitiesSet; + }, + actualCapabilities: function actualCapabilities() { + var capabilitiesSet = this.capabilitiesSet; + return this.availableCapabilities.filter(function (c) { + return !!capabilitiesSet[c.id]; + }); + } + } +})); +// CONCATENATED MODULE: ./plugins/UsersManager/vue/src/CapabilitiesEdit/CapabilitiesEdit.vue?vue&type=script&lang=ts + +// CONCATENATED MODULE: ./plugins/UsersManager/vue/src/CapabilitiesEdit/CapabilitiesEdit.vue + + + +CapabilitiesEditvue_type_script_lang_ts.render = render + +/* harmony default export */ var CapabilitiesEdit = (CapabilitiesEditvue_type_script_lang_ts); +// CONCATENATED MODULE: ./plugins/UsersManager/vue/src/CapabilitiesEdit/CapabilitiesEdit.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 CapabilitiesEdit_adapter = (Object(external_CoreHome_["createAngularJsAdapter"])({ + component: CapabilitiesEdit, + scope: { + idsite: { + angularJsBind: '<' + }, + siteName: { + angularJsBind: '<' + }, + userLogin: { + angularJsBind: '<' + }, + userRole: { + angularJsBind: '<' + }, + capabilities: { + angularJsBind: '<' + }, + onCapabilitiesChange: { + angularJsBind: '&', + vue: 'change' + } + }, + directiveName: 'piwikCapabilitiesEdit', + restrict: 'E', + $inject: ['$timeout'], + events: { + change: function change(caps, vm, scope, element, attrs, controller, $timeout) { + $timeout(function () { + if (scope.onCapabilitiesChange) { + scope.onCapabilitiesChange.call({ + capabilities: caps + }); + } + }); + } + } +})); +// CONCATENATED MODULE: ./plugins/UsersManager/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=UsersManager.umd.js.map
\ No newline at end of file diff --git a/plugins/UsersManager/vue/dist/UsersManager.umd.min.js b/plugins/UsersManager/vue/dist/UsersManager.umd.min.js new file mode 100644 index 0000000000..2a1f272e0c --- /dev/null +++ b/plugins/UsersManager/vue/dist/UsersManager.umd.min.js @@ -0,0 +1,14 @@ +(function(e,i){"object"===typeof exports&&"object"===typeof module?module.exports=i(require("CoreHome"),require("vue"),require("CorePluginsAdmin")):"function"===typeof define&&define.amd?define(["CoreHome",,"CorePluginsAdmin"],i):"object"===typeof exports?exports["UsersManager"]=i(require("CoreHome"),require("vue"),require("CorePluginsAdmin")):e["UsersManager"]=i(e["CoreHome"],e["Vue"],e["CorePluginsAdmin"])})("undefined"!==typeof self?self:this,(function(e,i,t){return function(e){var i={};function t(a){if(i[a])return i[a].exports;var n=i[a]={i:a,l:!1,exports:{}};return e[a].call(n.exports,n,n.exports,t),n.l=!0,n.exports}return t.m=e,t.c=i,t.d=function(e,i,a){t.o(e,i)||Object.defineProperty(e,i,{enumerable:!0,get:a})},t.r=function(e){"undefined"!==typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},t.t=function(e,i){if(1&i&&(e=t(e)),8&i)return e;if(4&i&&"object"===typeof e&&e&&e.__esModule)return e;var a=Object.create(null);if(t.r(a),Object.defineProperty(a,"default",{enumerable:!0,value:e}),2&i&&"string"!=typeof e)for(var n in e)t.d(a,n,function(i){return e[i]}.bind(null,n));return a},t.n=function(e){var i=e&&e.__esModule?function(){return e["default"]}:function(){return e};return t.d(i,"a",i),i},t.o=function(e,i){return Object.prototype.hasOwnProperty.call(e,i)},t.p="plugins/UsersManager/vue/dist/",t(t.s="fae3")}({"19dc":function(i,t){i.exports=e},"8bbf":function(e,t){e.exports=i},a5a2:function(e,i){e.exports=t},fae3:function(e,i,t){"use strict";if(t.r(i),t.d(i,"CapabilitiesEdit",(function(){return B})),"undefined"!==typeof window){var a=window.document.currentScript,n=a&&a.src.match(/(.+\/)[^/]+\.js(\?.*)?$/);n&&(t.p=n[1])}var o=t("19dc"),l=t("8bbf"),r=["title"],s=["onClick"],c={key:0,class:"addCapability"},u={class:"ui-confirm confirmCapabilityToggle modal",ref:"confirmCapabilityToggleModal"},d={class:"modal-content"},p=["innerHTML"],b=["innerHTML"],f={class:"modal-footer"};function m(e,i,t,a,n,o){var m=Object(l["resolveComponent"])("Field");return Object(l["openBlock"])(),Object(l["createElementBlock"])("div",{class:Object(l["normalizeClass"])(["capabilitiesEdit",{busy:e.isBusy}])},[(Object(l["openBlock"])(!0),Object(l["createElementBlock"])(l["Fragment"],null,Object(l["renderList"])(e.actualCapabilities,(function(i){return Object(l["openBlock"])(),Object(l["createElementBlock"])("div",{key:i.id,class:"chip"},[Object(l["createElementVNode"])("span",{class:"capability-name",title:"".concat(i.description," ").concat(e.isIncludedInRole(i)?"<br/><br/>".concat(e.translate("UsersManager_IncludedInUsersRole")):"")},Object(l["toDisplayString"])(i.category)+": "+Object(l["toDisplayString"])(i.name),9,r),e.isIncludedInRole(i)?Object(l["createCommentVNode"])("",!0):(Object(l["openBlock"])(),Object(l["createElementBlock"])("span",{key:0,class:"icon-close",onClick:function(t){e.capabilityToRemoveId=i.id,e.onToggleCapability(!1)}},null,8,s))])})),128)),e.availableCapabilitiesGrouped.length?(Object(l["openBlock"])(),Object(l["createElementBlock"])("div",c,[Object(l["createVNode"])(m,{"model-value":e.capabilityToAddId,"onUpdate:modelValue":i[0]||(i[0]=function(i){e.capabilityToAddId=i,e.onToggleCapability(!0)}),disabled:e.isBusy,uicontrol:"expandable-select",name:"add_capability","full-width":!0,options:e.availableCapabilitiesGrouped},null,8,["model-value","disabled","options"])])):Object(l["createCommentVNode"])("",!0),Object(l["createElementVNode"])("div",u,[Object(l["createElementVNode"])("div",d,[e.isAddingCapability?(Object(l["openBlock"])(),Object(l["createElementBlock"])("h2",{key:0,innerHTML:e.$sanitize(e.confirmAddCapabilityToggleContent)},null,8,p)):Object(l["createCommentVNode"])("",!0),e.isAddingCapability?Object(l["createCommentVNode"])("",!0):(Object(l["openBlock"])(),Object(l["createElementBlock"])("h2",{key:1,innerHTML:e.$sanitize(e.confirmCapabilityToggleContent)},null,8,b))]),Object(l["createElementVNode"])("div",f,[Object(l["createElementVNode"])("a",{href:"",class:"modal-action modal-close btn",onClick:i[1]||(i[1]=Object(l["withModifiers"])((function(i){return e.toggleCapability()}),["prevent"]))},Object(l["toDisplayString"])(e.translate("General_Yes")),1),Object(l["createElementVNode"])("a",{href:"",class:"modal-action modal-close modal-no",onClick:i[2]||(i[2]=Object(l["withModifiers"])((function(i){e.capabilityToAddOrRemove=null,e.capabilityToAddId=null,e.capabilityToRemoveId=null}),["prevent"]))},Object(l["toDisplayString"])(e.translate("General_No")),1)])],512)],2)}var g=t("a5a2");function h(e,i){if(!(e instanceof i))throw new TypeError("Cannot call a class as a function")}function y(e,i){for(var t=0;t<i.length;t++){var a=i[t];a.enumerable=a.enumerable||!1,a.configurable=!0,"value"in a&&(a.writable=!0),Object.defineProperty(e,a.key,a)}}function v(e,i,t){return i&&y(e.prototype,i),t&&y(e,t),e}function C(e,i,t){return i in e?Object.defineProperty(e,i,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[i]=t,e} +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */var O=function(){function e(){var i=this;h(this,e),C(this,"privateState",Object(l["reactive"])({isLoading:!1,capabilities:[]})),C(this,"state",Object(l["computed"])((function(){return Object(l["readonly"])(i.privateState)}))),C(this,"capabilities",Object(l["computed"])((function(){return i.state.value.capabilities}))),C(this,"isLoading",Object(l["computed"])((function(){return i.state.value.isLoading}))),C(this,"fetchPromise",void 0),this.fetchCapabilities()}return v(e,[{key:"fetchCapabilities",value:function(){var e=this;return this.fetchPromise||(this.privateState.isLoading=!0,this.fetchPromise=o["AjaxHelper"].fetch({method:"UsersManager.getAvailableCapabilities"}).then((function(i){return e.privateState.capabilities=i,e.capabilities.value})).finally((function(){e.privateState.isLoading=!1}))),this.fetchPromise}}]),e}(),j=Object(o["lazyInitSingleton"])(O),T=window,A=T.$,R=Object(l["defineComponent"])({props:{idsite:[String,Number],siteName:{type:String,required:!0},userLogin:{type:String,required:!0},userRole:{type:String,required:!0},capabilities:Array},components:{Field:g["Field"]},data:function(){return{theCapabilities:this.capabilities||[],isBusy:!1,isAddingCapability:!1,capabilityToAddId:null,capabilityToRemoveId:null,capabilityToAddOrRemove:null}},emits:["change"],watch:{capabilities:function(e){e&&(this.theCapabilities=e)}},created:function(){var e=this;this.capabilities?this.theCapabilities=this.capabilities:(this.isBusy=!0,o["AjaxHelper"].fetch({method:"UsersManager.getUsersPlusRole",limit:"1",filter_search:this.userLogin}).then((function(e){return e&&e.capabilities?e.capabilities:[]})).then((function(i){e.theCapabilities=i})).finally((function(){e.isBusy=!1})))},methods:{onToggleCapability:function(e){var i=this;this.isAddingCapability=e;var t=e?this.capabilityToAddId:this.capabilityToRemoveId;this.capabilityToAddOrRemove=null,this.availableCapabilities.forEach((function(e){e.id===t&&(i.capabilityToAddOrRemove=e)})),this.$refs.confirmCapabilityToggleModal&&A(this.$refs.confirmCapabilityToggleModal).modal({dismissible:!1,yes:function(){return null}}).modal("open")},toggleCapability:function(){this.isAddingCapability?this.addCapability(this.capabilityToAddOrRemove):this.removeCapability(this.capabilityToAddOrRemove)},isIncludedInRole:function(e){return-1!==(e.includedInRoles||[]).indexOf(this.userRole)},getCapabilitiesList:function(){var e=this,i=[];return this.availableCapabilities.forEach((function(t){e.isIncludedInRole(t)||e.capabilitiesSet[t.id]&&i.push(t.id)})),i},addCapability:function(e){var i=this;this.isBusy=!0,o["AjaxHelper"].post({method:"UsersManager.addCapabilities"},{userLogin:this.userLogin,capabilities:e.id,idSites:this.idsite}).then((function(){i.$emit("change",i.getCapabilitiesList())})).finally((function(){i.isBusy=!1,i.capabilityToAddOrRemove=null,i.capabilityToAddId=null,i.capabilityToRemoveId=null}))},removeCapability:function(e){var i=this;this.isBusy=!0,o["AjaxHelper"].post({method:"UsersManager.removeCapabilities"},{userLogin:this.userLogin,capabilities:e.id,idSites:this.idsite}).then((function(){i.$emit("change",i.getCapabilitiesList())})).finally((function(){i.isBusy=!1,i.capabilityToAddOrRemove=null,i.capabilityToAddId=null,i.capabilityToRemoveId=null}))}},computed:{availableCapabilities:function(){return j.capabilities.value},confirmAddCapabilityToggleContent:function(){return Object(o["translate"])("UsersManager_AreYouSureAddCapability","<strong>".concat(this.userLogin,"</strong>"),"<strong>".concat(this.capabilityToAddOrRemove?this.capabilityToAddOrRemove.name:"","</strong>"),"<strong>".concat(this.siteNameText,"</strong>"))},confirmCapabilityToggleContent:function(){return Object(o["translate"])("UsersManager_AreYouSureRemoveCapability","<strong>".concat(this.capabilityToAddOrRemove?this.capabilityToAddOrRemove.name:"","</strong>"),"<strong>".concat(this.userLogin,"</strong>"),"<strong>".concat(this.siteNameText,"</strong>"))},siteNameText:function(){return o["Matomo"].helper.htmlEntities(this.siteName)},availableCapabilitiesGrouped:function(){var e=this,i=this.availableCapabilities.filter((function(i){return!e.capabilitiesSet[i.id]})).map((function(e){return{group:e.category,key:e.id,value:e.name,tooltip:e.description}}));return i.sort((function(e,i){return e.group===i.group?e.value===i.value?0:e.value<i.value?-1:1:e.group<i.group?-1:1})),i},capabilitiesSet:function(){var e=this,i={},t=this.theCapabilities;return(t||[]).forEach((function(e){i[e]=!0})),(this.availableCapabilities||[]).forEach((function(t){e.isIncludedInRole(t)&&(i[t.id]=!0)})),i},actualCapabilities:function(){var e=this.capabilitiesSet;return this.availableCapabilities.filter((function(i){return!!e[i.id]}))}}});R.render=m;var B=R; +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */Object(o["createAngularJsAdapter"])({component:B,scope:{idsite:{angularJsBind:"<"},siteName:{angularJsBind:"<"},userLogin:{angularJsBind:"<"},userRole:{angularJsBind:"<"},capabilities:{angularJsBind:"<"},onCapabilitiesChange:{angularJsBind:"&",vue:"change"}},directiveName:"piwikCapabilitiesEdit",restrict:"E",$inject:["$timeout"],events:{change:function(e,i,t,a,n,o,l){l((function(){t.onCapabilitiesChange&&t.onCapabilitiesChange.call({capabilities:e})}))}}})}})})); +//# sourceMappingURL=UsersManager.umd.min.js.map
\ No newline at end of file diff --git a/plugins/UsersManager/vue/dist/umd.metadata.json b/plugins/UsersManager/vue/dist/umd.metadata.json new file mode 100644 index 0000000000..dce4477a3c --- /dev/null +++ b/plugins/UsersManager/vue/dist/umd.metadata.json @@ -0,0 +1,6 @@ +{ + "dependsOn": [ + "CoreHome", + "CorePluginsAdmin" + ] +}
\ No newline at end of file diff --git a/plugins/UsersManager/vue/src/CapabilitiesEdit/CapabilitiesEdit.adapter.ts b/plugins/UsersManager/vue/src/CapabilitiesEdit/CapabilitiesEdit.adapter.ts new file mode 100644 index 0000000000..ca522d10db --- /dev/null +++ b/plugins/UsersManager/vue/src/CapabilitiesEdit/CapabilitiesEdit.adapter.ts @@ -0,0 +1,50 @@ +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + +import { ITimeoutService } from 'angular'; +import { createAngularJsAdapter } from 'CoreHome'; +import CapabilitiesEdit from './CapabilitiesEdit.vue'; +import Capability from '../CapabilitiesStore/Capability'; + +export default createAngularJsAdapter<[ITimeoutService]>({ + component: CapabilitiesEdit, + scope: { + idsite: { + angularJsBind: '<', + }, + siteName: { + angularJsBind: '<', + }, + userLogin: { + angularJsBind: '<', + }, + userRole: { + angularJsBind: '<', + }, + capabilities: { + angularJsBind: '<', + }, + onCapabilitiesChange: { + angularJsBind: '&', + vue: 'change', + }, + }, + directiveName: 'piwikCapabilitiesEdit', + restrict: 'E', + $inject: ['$timeout'], + events: { + change(caps: Capability[], vm, scope, element, attrs, controller, $timeout) { + $timeout(() => { + if (scope.onCapabilitiesChange) { + scope.onCapabilitiesChange.call({ + capabilities: caps, + }); + } + }); + }, + }, +}); diff --git a/plugins/UsersManager/angularjs/capabilities-edit/capabilities-edit.component.less b/plugins/UsersManager/vue/src/CapabilitiesEdit/CapabilitiesEdit.less index 8a0305bfcd..3d4cf06b95 100644 --- a/plugins/UsersManager/angularjs/capabilities-edit/capabilities-edit.component.less +++ b/plugins/UsersManager/vue/src/CapabilitiesEdit/CapabilitiesEdit.less @@ -2,7 +2,7 @@ display: inline-block; margin-bottom: -8px; - > div.chip { + div.chip { margin-right: 8px; display: inline-block; margin-bottom: 8px; @@ -11,7 +11,7 @@ padding-right: .4rem; } - > span.icon-close { + span.icon-close { font-size: .6rem; float: right; margin-top: 1.4em; diff --git a/plugins/UsersManager/vue/src/CapabilitiesEdit/CapabilitiesEdit.vue b/plugins/UsersManager/vue/src/CapabilitiesEdit/CapabilitiesEdit.vue new file mode 100644 index 0000000000..e1c226b56e --- /dev/null +++ b/plugins/UsersManager/vue/src/CapabilitiesEdit/CapabilitiesEdit.vue @@ -0,0 +1,311 @@ +<!-- + 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="capabilitiesEdit" + :class="{busy: isBusy}" + > + <div + v-for="capability in actualCapabilities" + :key="capability.id" + class="chip" + > + <span + class="capability-name" + :title="`${capability.description} ${ + isIncludedInRole(capability) + ? `<br/><br/>${translate('UsersManager_IncludedInUsersRole')}` + : '' + }`" + > + {{ capability.category }}: {{ capability.name }} + </span> + <span + class="icon-close" + v-if="!isIncludedInRole(capability)" + @click="capabilityToRemoveId = capability.id; onToggleCapability(false)" + /> + </div> + <div + class="addCapability" + v-if="availableCapabilitiesGrouped.length" + > + <Field + :model-value="capabilityToAddId" + @update:model-value="capabilityToAddId = $event; onToggleCapability(true)" + :disabled="isBusy" + uicontrol="expandable-select" + name="add_capability" + :full-width="true" + :options="availableCapabilitiesGrouped" + > + </Field> + </div> + <div class="ui-confirm confirmCapabilityToggle modal" ref="confirmCapabilityToggleModal"> + <div class="modal-content"> + <h2 + v-if="isAddingCapability" + v-html="$sanitize(confirmAddCapabilityToggleContent)" + ></h2> + <h2 + v-if="!isAddingCapability" + v-html="$sanitize(confirmCapabilityToggleContent)" + ></h2> + </div> + <div class="modal-footer"> + <a + href="" + class="modal-action modal-close btn" + @click.prevent="toggleCapability()" + >{{ translate('General_Yes') }}</a> + <a + href="" + class="modal-action modal-close modal-no" + @click.prevent=" + capabilityToAddOrRemove = null; + capabilityToAddId = null; + capabilityToRemoveId = null;" + > + {{ translate('General_No') }} + </a> + </div> + </div> + </div> +</template> + +<script lang="ts"> +import { defineComponent, DeepReadonly } from 'vue'; +import { translate, AjaxHelper, Matomo } from 'CoreHome'; +import { Field } from 'CorePluginsAdmin'; +import CapabilitiesStore from '../CapabilitiesStore/CapabilitiesStore'; +import Capability from '../CapabilitiesStore/Capability'; +import ModalOptions = M.ModalOptions; + +interface CapabilitiesEditState { + isBusy: boolean; + theCapabilities: string[]; + isAddingCapability: boolean; + capabilityToAddId: string|null; + capabilityToRemoveId: string|null; + capabilityToAddOrRemove: DeepReadonly<Capability>|null; +} + +const { $ } = window; + +export default defineComponent({ + props: { + idsite: [String, Number], + siteName: { + type: String, + required: true, + }, + userLogin: { + type: String, + required: true, + }, + userRole: { + type: String, + required: true, + }, + capabilities: Array, + }, + components: { + Field, + }, + data(): CapabilitiesEditState { + return { + theCapabilities: (this.capabilities as string[]) || [], + isBusy: false, + isAddingCapability: false, + capabilityToAddId: null, + capabilityToRemoveId: null, + capabilityToAddOrRemove: null, + }; + }, + emits: ['change'], + watch: { + capabilities(newValue) { + if (newValue) { + this.theCapabilities = newValue as string[]; + } + }, + }, + created() { + if (!this.capabilities) { + this.isBusy = true; + + AjaxHelper.fetch<{ capabilities: string[] }>({ + method: 'UsersManager.getUsersPlusRole', + limit: '1', + filter_search: this.userLogin, + }).then((user) => { + if (!user || !user.capabilities) { + return []; + } + + return user.capabilities; + }).then((capabilities) => { + this.theCapabilities = capabilities; + }).finally(() => { + this.isBusy = false; + }); + } else { + this.theCapabilities = this.capabilities as string[]; + } + }, + methods: { + onToggleCapability(isAdd: boolean) { + this.isAddingCapability = isAdd; + + const capabilityToAddOrRemoveId = isAdd ? this.capabilityToAddId : this.capabilityToRemoveId; + + this.capabilityToAddOrRemove = null; + this.availableCapabilities.forEach((capability) => { + if (capability.id === capabilityToAddOrRemoveId) { + this.capabilityToAddOrRemove = capability; + } + }); + + if (this.$refs.confirmCapabilityToggleModal) { + $(this.$refs.confirmCapabilityToggleModal as HTMLElement).modal({ + dismissible: false, + yes: () => null, + } as unknown as ModalOptions).modal('open'); + } + }, + toggleCapability() { + if (this.isAddingCapability) { + this.addCapability(this.capabilityToAddOrRemove!); + } else { + this.removeCapability(this.capabilityToAddOrRemove!); + } + }, + isIncludedInRole(capability: DeepReadonly<Capability>) { + return (capability.includedInRoles || []).indexOf(this.userRole) !== -1; + }, + getCapabilitiesList() { + const result: string[] = []; + this.availableCapabilities.forEach((capability) => { + if (this.isIncludedInRole(capability)) { + return; + } + + if (this.capabilitiesSet[capability.id]) { + result.push(capability.id); + } + }); + return result; + }, + addCapability(capability: DeepReadonly<Capability>) { + this.isBusy = true; + AjaxHelper.post( + { + method: 'UsersManager.addCapabilities', + }, + { + userLogin: this.userLogin, + capabilities: capability.id, + idSites: this.idsite, + }, + ).then(() => { + this.$emit('change', this.getCapabilitiesList()); + }).finally(() => { + this.isBusy = false; + this.capabilityToAddOrRemove = null; + this.capabilityToAddId = null; + this.capabilityToRemoveId = null; + }); + }, + removeCapability(capability: DeepReadonly<Capability>) { + this.isBusy = true; + AjaxHelper.post( + { + method: 'UsersManager.removeCapabilities', + }, + { + userLogin: this.userLogin, + capabilities: capability.id, + idSites: this.idsite, + }, + ).then(() => { + this.$emit('change', this.getCapabilitiesList()); + }).finally(() => { + this.isBusy = false; + this.capabilityToAddOrRemove = null; + this.capabilityToAddId = null; + this.capabilityToRemoveId = null; + }); + }, + }, + computed: { + availableCapabilities() { + return CapabilitiesStore.capabilities.value; + }, + confirmAddCapabilityToggleContent() { + return translate( + 'UsersManager_AreYouSureAddCapability', + `<strong>${this.userLogin}</strong>`, + `<strong>${this.capabilityToAddOrRemove ? this.capabilityToAddOrRemove.name : ''}</strong>`, + `<strong>${this.siteNameText}</strong>`, + ); + }, + confirmCapabilityToggleContent() { + return translate( + 'UsersManager_AreYouSureRemoveCapability', + `<strong>${this.capabilityToAddOrRemove ? this.capabilityToAddOrRemove.name : ''}</strong>`, + `<strong>${this.userLogin}</strong>`, + `<strong>${this.siteNameText}</strong>`, + ); + }, + siteNameText() { + return Matomo.helper.htmlEntities(this.siteName); + }, + availableCapabilitiesGrouped() { + const availableCapabilitiesGrouped = this.availableCapabilities.filter( + (c) => !this.capabilitiesSet[c.id], + ).map((c) => ({ + group: c.category, + key: c.id, + value: c.name, + tooltip: c.description, + })); + + availableCapabilitiesGrouped.sort((lhs, rhs) => { + if (lhs.group === rhs.group) { + if (lhs.value === rhs.value) { + return 0; + } + return lhs.value < rhs.value ? -1 : 1; + } + return lhs.group < rhs.group ? -1 : 1; + }); + + return availableCapabilitiesGrouped; + }, + capabilitiesSet() { + const capabilitiesSet: Record<string, boolean> = {}; + const capabilities = this.theCapabilities as string[]; + + (capabilities || []).forEach((capability) => { + capabilitiesSet[capability] = true; + }); + + (this.availableCapabilities || []).forEach((capability) => { + if (this.isIncludedInRole(capability)) { + capabilitiesSet[capability.id] = true; + } + }); + + return capabilitiesSet; + }, + actualCapabilities() { + const { capabilitiesSet } = this; + return this.availableCapabilities.filter((c) => !!capabilitiesSet[c.id]); + }, + }, +}); +</script> diff --git a/plugins/UsersManager/vue/src/CapabilitiesStore/CapabilitiesStore.adapter.ts b/plugins/UsersManager/vue/src/CapabilitiesStore/CapabilitiesStore.adapter.ts new file mode 100644 index 0000000000..dc3f08419f --- /dev/null +++ b/plugins/UsersManager/vue/src/CapabilitiesStore/CapabilitiesStore.adapter.ts @@ -0,0 +1,23 @@ +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + +import { DeepReadonly } from 'vue'; +import Capability from './Capability'; +import CapabilitiesStore from "./CapabilitiesStore"; + +function permissionsMetadataServiceAdapter() { + return { + getAllCapabilities(): Promise<DeepReadonly<Capability[]>> { + return CapabilitiesStore.fetchCapabilities(); + }, + }; +} + +window.angular.module('piwikApp.service').factory( + 'permissionsMetadataService', + permissionsMetadataServiceAdapter, +); diff --git a/plugins/UsersManager/vue/src/CapabilitiesStore/CapabilitiesStore.ts b/plugins/UsersManager/vue/src/CapabilitiesStore/CapabilitiesStore.ts new file mode 100644 index 0000000000..36b3c8113f --- /dev/null +++ b/plugins/UsersManager/vue/src/CapabilitiesStore/CapabilitiesStore.ts @@ -0,0 +1,57 @@ +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + +import { + reactive, + readonly, + computed, + DeepReadonly, +} from 'vue'; +import { AjaxHelper, lazyInitSingleton } from 'CoreHome'; +import Capability from './Capability'; + +interface CapabilitiesStoreState { + isLoading: boolean; + capabilities: Capability[]; +} + +class CapabilitiesStore { + private privateState = reactive<CapabilitiesStoreState>({ + isLoading: false, + capabilities: [], + }); + + private readonly state = computed(() => readonly(this.privateState)); + + readonly capabilities = computed(() => this.state.value.capabilities); + + readonly isLoading = computed(() => this.state.value.isLoading); + + private fetchPromise?: Promise<DeepReadonly<Capability[]>>; + + constructor() { + this.fetchCapabilities(); + } + + public fetchCapabilities(): Promise<DeepReadonly<Capability[]>> { + if (!this.fetchPromise) { + this.privateState.isLoading = true; + this.fetchPromise = AjaxHelper.fetch<Capability[]>({ + method: 'UsersManager.getAvailableCapabilities', + }).then((capabilities) => { + this.privateState.capabilities = capabilities; + return this.capabilities.value; + }).finally(() => { + this.privateState.isLoading = false; + }); + } + + return this.fetchPromise!; + } +} + +export default lazyInitSingleton(CapabilitiesStore) as CapabilitiesStore; diff --git a/plugins/UsersManager/vue/src/CapabilitiesStore/Capability.ts b/plugins/UsersManager/vue/src/CapabilitiesStore/Capability.ts new file mode 100644 index 0000000000..0f099b8a32 --- /dev/null +++ b/plugins/UsersManager/vue/src/CapabilitiesStore/Capability.ts @@ -0,0 +1,17 @@ +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + +interface Capability { + id: string; + name: string; + description: string; + helpUrl: string; + includedInRoles: string[]; + category: string; +} + +export default Capability; diff --git a/plugins/UsersManager/vue/src/index.ts b/plugins/UsersManager/vue/src/index.ts new file mode 100644 index 0000000000..7411497560 --- /dev/null +++ b/plugins/UsersManager/vue/src/index.ts @@ -0,0 +1,10 @@ +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ +import './CapabilitiesEdit/CapabilitiesEdit.adapter'; + +export { default as CapabilitiesEdit } from './CapabilitiesEdit/CapabilitiesEdit.vue'; +export { default as Capability } from './CapabilitiesStore/Capability'; |