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

github.com/matomo-org/matomo.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordizzy <diosmosis@users.noreply.github.com>2021-12-01 20:19:20 +0300
committerGitHub <noreply@github.com>2021-12-01 20:19:20 +0300
commit43c21c99ef0451772a52a449729f832bfad8e82e (patch)
treeca4fe64af15b932887fad8ec7d5bb14194d81932 /plugins/CoreHome/angularjs
parenteede069c84a97729d62689dcf0447d60b2056665 (diff)
[Vue] migrate piwik-field and related directives (#18352)
* forgot to remove old files * built vue files * first pass at migrating notification directive, notification service and parts of UI.Notification to Vue * rewrite URL handling to use computed properties in a URL store + do the same for other dependent data in the comparison store to allow vues to subscribe to the properties for changes to global state * fix some tests * some more fixes * more fixes + disallow modifications to MatomoUrl state * get angularjs unit tests to pass + fix a couple more issues * another fix * fix bad merge * self review + fixes * remove old fix as it may not be needed anymore * empty string is not a valid date + do not report invalid date exception just rethrow * update screenshots and try to fix random failure * use jquery $destroy event instead of scope one since the scope one is broadcasted * rangeChange event must be triggered once on mount * initialize startDateText/endDateText correctly * use jquery $destroy event instead of angularjs one * built vue files * fix menudropdown.directive.js reference * load vue in installation/updater & correctly make focusanywherebuthere stateful * correctly implement stateful directives for ExpandOnClick/ExpandOnHover * less tweak (angularjs comment removal) * fix submenu check * quick type fix * load vue in installation workflow * add broadcast.js to Installation workflow + do not fail in pk_translate if no translations are loaded * update expected screenshots (spacing of arrow changed because of angularjs comment no longer being there) * start moving Notification class code to notifications store * fix prop type * fix html escaping * built vue files * get toast and other transitions to work + fix broken toast * move all of notification.js to NotificationStore * wait for angular to be initialized to post events to avoid loading race condition * get scroll to notification to work + get initialization of notification groups to work * correct unmount + remove notifications service file * fix some test failures * re add accidentally removed (?) file * remove no longer needed file * Add CoreHome UMD in CoreUpdater/Installation. * self review * fix type + add default value * remove file from JS list * fix test * fix UI tests * set correct type in users manager notification and allow scope values to be transformed in createAngularAdapter * start converting form field directives * start migrating siteselector * small addition * migrate rest of site selector code + make some breaking changes to function signatures in createAngularJsAdapter * disable webpack asset size hints/warnings + get siteselector code to build * fixing some bugs * fix some more issues (allow specifing require in createAngularJsAdapter and make AjaxHelper promises abortable) * get npm test to pass * a couple more fixes * remove existing files * convert quick-access directive and use shared code/state with site selector * remove site selector model * fix more issues and get UI tests to pass for quickaccess * remove debugging code / todo * fix initial value * add back a $timeout() * fixing tests, the post blur scope.$apply()s are apparently required for angularjs to function properly * migrate field-array * fixing more UI test failures * rebuild * start converting multipairfield * fix vue build * why were these deleted? * remove debug code * first pass migrate multipairfield.vue * move form-field code relevant to selects to FieldSelect.vue * fix css class issue + update expected screenshots * rebuild CoreHome * move more of form-field.directive.js to new vue classes * revert styling change * finish converting last of form-field.directive.js code (completely untested) * built vue files * get focus-if to work and remove debugging return; * rebuilt vue * should not need to specify type there * built CoreHome * built vue files * Fix for misaligned evolution trend icons (#18323) * Aligned evolution trend icons, text tweak * Update plugins/MultiSites/angularjs/dashboard/dashboard.directive.less Co-authored-by: Stefan Giehl <stefan@matomo.org> * apply review feedback * Hide feedback banner in zen mode (#18329) * [Vue] 4.6.0 fixes (#18334) * feedback plugin may not be loaded * fix copy paste * async/await not supported * built UMDs * get local files to build * built files * get auto clearing behavior to work in site selector * fix a couple more bugs * use jQuery click for expand on click * undo submodule change * rebuild vue * get vue files to run * missing element * more fixes * get more fields working properly * rebuild * fix even more issues * [Vue] use jQuery click for expand on click (#18341) * use jQuery click for expand on click * undo submodule change * migrate piwik-field directive and fix some issues * forgot to add migrated directive files and get demo.twig to work * use event target * make sure angularjs and vue do not share data * fix ng model mapping * fix a couple more issues * fix a couple more bugs * more fixes * mimic existing behavior where an empty value will result in an extra field appearing in a select option list, but only at first * another fix * built vue files * more fixes * do not use UMD if vue/src is not present * use non-minified angularjs if in development mode * deprecate custom template file property * remove angularjs properties in scope properties (ie, $$hashKey) otherwise vue will fail when it tries to process them * fixing some more issues from ui tests * more fixes * fix form field issue + patch jquery so .trigger() will also trigger events added via addEventHandler() * true bc fix * get the jquery patch to work * ignore polyfill map * fix ng-model issue in report limit in report export directive * full width property was not handled properly before in angularjs * do not try and parseInt null values * fix several more issues for tests * fix some tests * fix data binding * fix css class * fixing more ui test issues * do not decode model value of site name in site selector, so it is always the same as what is in the DB * 4.6.0-rc2 * more ng-model fixes * rebuild * html tweaks * add timeout to test * rebuild * fix another UI test * rebuild vue files * update some expected screenshots * fix more issues * Revert "[Vue] do not decode model value of site name in site selector, so it is always matches the DB value (#18356)" This reverts commit 8c7539f073e7a49311cbe6dc2474eb1bbfb8718d. * update screenshots * more fixes * another fix + screenshot update * more screenshot updates * more fixes * even more fixes * another ui test fix * more type fixes * rebuilt vue JS * couple more fixes * undo debugging * do not convert undefined to bool * update screenshot * another bool checking fix * rebuild vue files * more fixes * initial site value in field is assumed to be encoded * file headers and custom field component support * get custom component field code to work * rebuild vue * allow using angularjs templateFile for custom field (for BC) * get angularjs template embedding to work for rollupreporting at least * deal with some in source TODO items * fix a couple more issues * Use separate div in modals to display notifications otherwise Vue will erase modal content when initializing NotificationGroup component. * build again * refactor some code and fix an issue with checkbox array field handling in angularjs * more fixes * another fix * even more fixes * remove more todo * hopefully the last changes * update vue files * update submodule * revert debugging change + fix issue * built vue files * fix another select issue * rebuild vue files * fix broken refactor * update two screenshots * add some more timeouts and update screenshots * fix site selector model binding * rebuild vue * fix field array title * apply some pr feedback * apply more pr feedback * another fix * tweak * fix ng-change not executed before ng-model * fix another set of issues * fix another issue * rebuild vue * better ng-change/ng-model fix * initiate initial ng-change ONLY for site selectors where this behavior applies * update screenshots and try to fix random failure * undo submodule change * fix test Co-authored-by: sgiehl <stefan@matomo.org> Co-authored-by: Ben Burgess <88810029+bx80@users.noreply.github.com> Co-authored-by: Matthieu Aubry <mattab@users.noreply.github.com>
Diffstat (limited to 'plugins/CoreHome/angularjs')
-rw-r--r--plugins/CoreHome/angularjs/field-array/field-array.controller.js71
-rw-r--r--plugins/CoreHome/angularjs/field-array/field-array.directive.html23
-rw-r--r--plugins/CoreHome/angularjs/field-array/field-array.directive.js61
-rw-r--r--plugins/CoreHome/angularjs/field-array/field-array.directive.less17
-rw-r--r--plugins/CoreHome/angularjs/multipairfield/multipairfield.controller.js129
-rw-r--r--plugins/CoreHome/angularjs/multipairfield/multipairfield.directive.html61
-rw-r--r--plugins/CoreHome/angularjs/multipairfield/multipairfield.directive.js64
-rw-r--r--plugins/CoreHome/angularjs/multipairfield/multipairfield.directive.less60
-rw-r--r--plugins/CoreHome/angularjs/report-export/reportexport.directive.js7
-rw-r--r--plugins/CoreHome/angularjs/report-export/reportexport.popover.html19
-rw-r--r--plugins/CoreHome/angularjs/siteselector/siteselector-model.service.js140
11 files changed, 156 insertions, 496 deletions
diff --git a/plugins/CoreHome/angularjs/field-array/field-array.controller.js b/plugins/CoreHome/angularjs/field-array/field-array.controller.js
deleted file mode 100644
index 02aa7a2215..0000000000
--- a/plugins/CoreHome/angularjs/field-array/field-array.controller.js
+++ /dev/null
@@ -1,71 +0,0 @@
-/*!
- * Matomo - free/libre analytics platform
- *
- * @link https://matomo.org
- * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
- */
-(function () {
- angular.module('piwikApp').controller('FieldArrayController', FieldArrayController);
-
- FieldArrayController.$inject = ['$scope'];
-
- function FieldArrayController($scope){
-
- function getTemplate(field) {
- var control = field.uiControl;
- if (control === 'password' || control === 'url' || control === 'search' || control === 'email') {
- control = 'text'; // we use same template for text and password both
- }
-
- var file = 'field-' + control;
- var fieldsSupportingArrays = ['textarea', 'checkbox', 'text'];
- if (field.type === 'array' && fieldsSupportingArrays.indexOf(control) !== -1) {
- file += '-array';
- }
-
- return 'plugins/CorePluginsAdmin/angularjs/form-field/' + file + '.html?cb=' + piwik.cacheBuster;
- }
-
- if ($scope.field && !$scope.field.templateFile) {
- $scope.field.templateFile = getTemplate($scope.field);
- }
-
- var self = this;
- $scope.$watch('formValue', function () {
- if (!$scope.formValue || !$scope.formValue.length) {
- self.addEntry();
- } else {
- self.onEntryChange();
- }
- }, true);
-
- this.onEntryChange = function () {
- var hasAny = true;
- angular.forEach($scope.formValue, function (entry) {
- if (!entry) {
- hasAny = false;
- }
- });
- if (hasAny) {
- this.addEntry();
- }
- };
-
- this.addEntry = function () {
- if (angular.isArray($scope.formValue)) {
- $scope.formValue.push('');
- }
- };
-
- this.removeEntry = function (index) {
- if (index > -1) {
- $scope.formValue.splice(index, 1);
- }
- };
-
- if (!$scope.formValue || !$scope.formValue.length) {
- this.addEntry();
- }
- }
-
-})();
diff --git a/plugins/CoreHome/angularjs/field-array/field-array.directive.html b/plugins/CoreHome/angularjs/field-array/field-array.directive.html
deleted file mode 100644
index 1ce3fcaecc..0000000000
--- a/plugins/CoreHome/angularjs/field-array/field-array.directive.html
+++ /dev/null
@@ -1,23 +0,0 @@
-<div class="fieldArray form-group">
- <div ng-repeat="item in formValue track by $index"
- class="fieldArrayTable fieldArrayTable{{ $index }} multiple valign-wrapper">
-
- <div piwik-field uicontrol="{{ field.uiControl }}"
- data-title="{{ field.title }}"
- name="{{ name + '-' + $index }}"
- full-width="true"
- ng-if="field.templateFile"
- template-file="{{ field.templateFile }}"
- class="fieldUiControl"
- ng-model="formValue[$index]"
- options="field.availableValues"
- ng-change="fieldArray.onEntryChange()"
- placeholder=" ">
- </div>
-
- <span ng-click="fieldArray.removeEntry($index)"
- title="{{ 'General_Remove'|translate }}"
- ng-hide="($index + 1) == (formValue|length)"
- class="icon-minus valign"></span>
- </div>
-</div> \ No newline at end of file
diff --git a/plugins/CoreHome/angularjs/field-array/field-array.directive.js b/plugins/CoreHome/angularjs/field-array/field-array.directive.js
deleted file mode 100644
index 000f16caa9..0000000000
--- a/plugins/CoreHome/angularjs/field-array/field-array.directive.js
+++ /dev/null
@@ -1,61 +0,0 @@
-/*!
- * Matomo - free/libre analytics platform
- *
- * @link https://matomo.org
- * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
- */
-
-/**
- * Usage:
- * <div matomo-field-array field=".." ng-model="...">
- */
-(function () {
- angular.module('piwikApp').directive('matomoFieldArray', matomoFieldArray);
-
- matomoFieldArray.$inject = ['$document', 'piwik', '$filter'];
-
- function matomoFieldArray($document, piwik, $filter){
- return {
- restrict: 'A',
- scope: {
- name: '=',
- field: '='
- },
- require: "?ngModel",
- templateUrl: 'plugins/CoreHome/angularjs/field-array/field-array.directive.html?cb=' + piwik.cacheBuster,
- controller: 'FieldArrayController',
- controllerAs: 'fieldArray',
- compile: function (element, attrs) {
-
- return function (scope, element, attrs, ngModel) {
-
- if (ngModel) {
- ngModel.$setViewValue(scope.formValue);
- }
-
- scope.$watch('formValue', function (newValue, oldValue) {
- if (newValue != oldValue) {
- element.trigger('change', newValue);
- }
- }, true);
-
- if (ngModel) {
- ngModel.$render = function() {
- if (angular.isString(ngModel.$viewValue)) {
- scope.formValue = JSON.parse(ngModel.$viewValue);
- } else {
- scope.formValue = ngModel.$viewValue;
- }
- };
- }
-
- scope.$watch('formValue', function (newValue, oldValue) {
- if (ngModel) {
- ngModel.$setViewValue(newValue);
- }
- }, true);
- };
- }
- };
- }
-})(); \ No newline at end of file
diff --git a/plugins/CoreHome/angularjs/field-array/field-array.directive.less b/plugins/CoreHome/angularjs/field-array/field-array.directive.less
deleted file mode 100644
index 29f63392d7..0000000000
--- a/plugins/CoreHome/angularjs/field-array/field-array.directive.less
+++ /dev/null
@@ -1,17 +0,0 @@
-.fieldArray {
- margin-top: 40px !important;
-
- .form-group.row {
- margin-top: 2px;
- margin-bottom: 2px;
- }
-
- .fieldUiControl {
- width: ~"calc(100% - 60px)";
- padding-right: 0.75rem;
- }
-
- .icon-minus {
- cursor: pointer;
- }
-} \ No newline at end of file
diff --git a/plugins/CoreHome/angularjs/multipairfield/multipairfield.controller.js b/plugins/CoreHome/angularjs/multipairfield/multipairfield.controller.js
deleted file mode 100644
index 737bdbf94f..0000000000
--- a/plugins/CoreHome/angularjs/multipairfield/multipairfield.controller.js
+++ /dev/null
@@ -1,129 +0,0 @@
-/*!
- * Matomo - free/libre analytics platform
- *
- * @link https://matomo.org
- * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
- */
-(function () {
- angular.module('piwikApp').controller('MultiPairFieldController', MultiPairFieldController);
-
- MultiPairFieldController.$inject = ['$scope'];
-
- function MultiPairFieldController($scope){
-
- function getTemplate(field) {
- var control = field.uiControl;
- if (control === 'password' || control === 'url' || control === 'search' || control === 'email') {
- control = 'text'; // we use same template for text and password both
- }
-
- var file = 'field-' + control;
- var fieldsSupportingArrays = ['textarea', 'checkbox', 'text'];
- if (field.type === 'array' && fieldsSupportingArrays.indexOf(control) !== -1) {
- file += '-array';
- }
-
- return 'plugins/CorePluginsAdmin/angularjs/form-field/' + file + '.html?cb=' + piwik.cacheBuster;
- }
-
- if ($scope.field1 && !$scope.field1.templateFile) {
- $scope.field1.templateFile = getTemplate($scope.field1);
- }
-
- if ($scope.field2 && !$scope.field2.templateFile) {
- $scope.field2.templateFile = getTemplate($scope.field2);
- }
-
- if ($scope.field3 && !$scope.field3.templateFile) {
- $scope.field3.templateFile = getTemplate($scope.field3);
- }
-
- if ($scope.field4 && !$scope.field4.templateFile) {
- $scope.field4.templateFile = getTemplate($scope.field4);
- }
-
- var self = this;
- $scope.$watch('formValue', function () {
- if (!$scope.formValue || !$scope.formValue.length) {
- self.addEntry();
- } else {
- self.onEntryChange();
- }
- }, true);
-
- this.onEntryChange = function () {
- var hasAny = true;
- angular.forEach($scope.formValue, function (table) {
- if (!table) {
- hasAny = false;
- return;
- }
-
- var fieldCount = 0;
- if ($scope.field1 && $scope.field2 && $scope.field3 && $scope.field4) {
- fieldCount = 4;
- } else if ($scope.field1 && $scope.field2 && $scope.field3) {
- fieldCount = 3;
- } else if ($scope.field1 && $scope.field2) {
- fieldCount = 2;
- } else if ($scope.field1) {
- fieldCount = 1;
- }
- table.fieldCount = fieldCount;
-
- if (fieldCount === 4) {
- if (!table[$scope.field1.key] && !table[$scope.field2.key] && !table[$scope.field3.key] && !table[$scope.field4.key]) {
- hasAny = false;
- }
- } else if (fieldCount === 3) {
- if (!table[$scope.field1.key] && !table[$scope.field2.key] && !table[$scope.field3.key]) {
- hasAny = false;
- }
- } else if (fieldCount === 2) {
- if (!table[$scope.field1.key] && !table[$scope.field2.key]) {
- hasAny = false;
- }
- } else if (fieldCount === 1) {
- if (!table[$scope.field1.key]) {
- hasAny = false;
- }
- }
-
-
- });
- if (hasAny) {
- this.addEntry();
- }
- };
-
- this.addEntry = function () {
- if (angular.isArray($scope.formValue)) {
- var obj = {};
- if ($scope.field1 && $scope.field1.key) {
- obj[$scope.field1.key] = '';
- }
- if ($scope.field2 && $scope.field2.key) {
- obj[$scope.field2.key] = '';
- }
- if ($scope.field3 && $scope.field3.key) {
- obj[$scope.field3.key] = '';
- }
- if ($scope.field4 && $scope.field4.key) {
- obj[$scope.field4.key] = '';
- }
- $scope.formValue.push(obj);
- }
- };
-
- this.removeEntry = function (index) {
- if (index > -1) {
- $scope.formValue.splice(index, 1);
- }
- };
-
- if (!$scope.formValue || !$scope.formValue.length) {
- this.addEntry();
- }
- }
-
-})();
diff --git a/plugins/CoreHome/angularjs/multipairfield/multipairfield.directive.html b/plugins/CoreHome/angularjs/multipairfield/multipairfield.directive.html
deleted file mode 100644
index a14cc99c36..0000000000
--- a/plugins/CoreHome/angularjs/multipairfield/multipairfield.directive.html
+++ /dev/null
@@ -1,61 +0,0 @@
-<div class="multiPairField form-group">
- <div ng-repeat="(index, item) in formValue"
- class="multiPairFieldTable multiPairFieldTable{{ index }} has{{ item.fieldCount }}Fields multiple valign-wrapper">
-
- <div piwik-field uicontrol="{{ field1.uiControl }}"
- name="{{ name + '-p1-' + $index }}"
- data-title="{{ field1.title }}"
- full-width="true"
- ng-if="field1.templateFile"
- template-file="{{ field1.templateFile }}"
- class="fieldUiControl fieldUiControl1"
- ng-class="{'hasMultiFields': (field1.templateFile && field2.templateFile)}"
- ng-model="formValue[index][field1.key]"
- options="field1.availableValues"
- ng-change="multiPairField.onEntryChange()"
- placeholder=" ">
- </div>
-
- <div piwik-field uicontrol="{{ field2.uiControl }}"
- name="{{ name + '-p2-' + $index }}"
- data-title="{{ field2.title }}"
- full-width="true"
- ng-if="field2.templateFile"
- class="fieldUiControl fieldUiControl2"
- template-file="{{ field2.templateFile }}"
- options="field2.availableValues"
- ng-change="multiPairField.onEntryChange()"
- ng-model="formValue[index][field2.key]"
- placeholder=" ">
- </div>
-
- <div piwik-field uicontrol="{{ field3.uiControl }}"
- data-title="{{ field3.title }}"
- full-width="true"
- ng-if="field3.templateFile"
- class="fieldUiControl fieldUiControl3"
- template-file="{{ field3.templateFile }}"
- options="field3.availableValues"
- ng-change="multiPairField.onEntryChange()"
- ng-model="formValue[index][field3.key]"
- placeholder=" ">
- </div>
-
- <div piwik-field uicontrol="{{ field4.uiControl }}"
- data-title="{{ field4.title }}"
- full-width="true"
- ng-if="field4.templateFile"
- class="fieldUiControl fieldUiControl4"
- template-file="{{ field4.templateFile }}"
- options="field4.availableValues"
- ng-change="multiPairField.onEntryChange()"
- ng-model="formValue[index][field4.key]"
- placeholder=" ">
- </div>
-
- <span ng-click="multiPairField.removeEntry(index)"
- title="{{ 'General_Remove'|translate }}"
- ng-hide="(index + 1) == (formValue|length)"
- class="icon-minus valign"></span>
- </div>
-</div> \ No newline at end of file
diff --git a/plugins/CoreHome/angularjs/multipairfield/multipairfield.directive.js b/plugins/CoreHome/angularjs/multipairfield/multipairfield.directive.js
deleted file mode 100644
index d877c05609..0000000000
--- a/plugins/CoreHome/angularjs/multipairfield/multipairfield.directive.js
+++ /dev/null
@@ -1,64 +0,0 @@
-/*!
- * Matomo - free/libre analytics platform
- *
- * @link https://matomo.org
- * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
- */
-
-/**
- * Usage:
- * <div matomo-multi-pair-field field1=".." field2="" ng-model="...">
- */
-(function () {
- angular.module('piwikApp').directive('matomoMultiPairField', matomoMultiPairField);
-
- matomoMultiPairField.$inject = ['$document', 'piwik', '$filter'];
-
- function matomoMultiPairField($document, piwik, $filter){
- return {
- restrict: 'A',
- scope: {
- name: '=',
- field1: '=',
- field2: '=',
- field3: '=',
- field4: '='
- },
- require: "?ngModel",
- templateUrl: 'plugins/CoreHome/angularjs/multipairfield/multipairfield.directive.html?cb=' + piwik.cacheBuster,
- controller: 'MultiPairFieldController',
- controllerAs: 'multiPairField',
- compile: function (element, attrs) {
-
- return function (scope, element, attrs, ngModel) {
-
- if (ngModel) {
- ngModel.$setViewValue(scope.formValue);
- }
-
- scope.$watch('formValue', function (newValue, oldValue) {
- if (newValue != oldValue) {
- element.trigger('change', newValue);
- }
- }, true);
-
- if (ngModel) {
- ngModel.$render = function() {
- if (angular.isString(ngModel.$viewValue)) {
- scope.formValue = JSON.parse(ngModel.$viewValue);
- } else {
- scope.formValue = ngModel.$viewValue;
- }
- };
- }
-
- scope.$watch('formValue', function (newValue, oldValue) {
- if (ngModel) {
- ngModel.$setViewValue(newValue);
- }
- }, true);
- };
- }
- };
- }
-})(); \ No newline at end of file
diff --git a/plugins/CoreHome/angularjs/multipairfield/multipairfield.directive.less b/plugins/CoreHome/angularjs/multipairfield/multipairfield.directive.less
deleted file mode 100644
index 3a2f34c736..0000000000
--- a/plugins/CoreHome/angularjs/multipairfield/multipairfield.directive.less
+++ /dev/null
@@ -1,60 +0,0 @@
-.multiPairField {
- margin-top: 40px !important;
-
- .form-group.row {
- margin-top: 2px;
- margin-bottom: 2px;
- }
-
- .multiPairFieldTable {
-
- &.has1Fields {
- .fieldUiControl1{
- width: ~"calc(100% - 60px)";
- padding-right: 0.75rem;
- }
- }
-
- &:not(.has1Fields) {
- .fieldUiControl {
- display: inline-block;
- padding-right: 0.75rem;
- }
- }
-
- &.has2Fields {
- .fieldUiControl1 {
- width: 160px;
- }
- .fieldUiControl2 {
- width: ~"calc(100% - 190px)";
- padding: 0.75rem;
- }
- }
-
- &.has3Fields {
- .fieldUiControl1 {
- width: 120px;
- }
- .fieldUiControl2,
- .fieldUiControl3 {
- width: 220px;
- }
- }
-
- &.has4Fields {
- .fieldUiControl1 {
- width: 120px;
- }
- .fieldUiControl2,
- .fieldUiControl3,
- .fieldUiControl4 {
- width: 148px;
- }
- }
- }
-
- .icon-minus {
- cursor: pointer;
- }
-} \ No newline at end of file
diff --git a/plugins/CoreHome/angularjs/report-export/reportexport.directive.js b/plugins/CoreHome/angularjs/report-export/reportexport.directive.js
index a0edb62b11..2967c90ab4 100644
--- a/plugins/CoreHome/angularjs/report-export/reportexport.directive.js
+++ b/plugins/CoreHome/angularjs/report-export/reportexport.directive.js
@@ -45,7 +45,7 @@
}
var method = scope.apiMethod;
- var limit = scope.reportLimitAll == 'yes' ? -1 : scope.reportLimit;
+ var limit = scope.reportLimitAll == 'yes' ? -1 : scope.limitContainer.reportLimit;
var type = scope.reportType;
var params = scope.requestParams;
@@ -222,6 +222,9 @@
reportLimit = Math.min(reportLimit, scope.maxFilterLimit);
}
scope.reportLimit = reportLimit > 0 ? reportLimit : 100;
+ // ng-model seems to have trouble setting $parent.reportLimit, so this was changed
+ // to use a property in a new object, limitContainer. it works. i'm not sure why.
+ scope.limitContainer = { reportLimit: reportLimit };
scope.reportLimitAll = reportLimit == -1 ? 'yes' : 'no';
scope.optionFlat = dataTable.param.flat === true || dataTable.param.flat === 1 || dataTable.param.flat === "1";
scope.optionExpanded = true;
@@ -253,7 +256,7 @@
if (scope.maxFilterLimit > 0) {
scope.$watch('reportLimit', function (newVal, oldVal) {
if (parseInt(newVal, 10) > parseInt(scope.maxFilterLimit, 10)) {
- scope.reportLimit = oldVal;
+ scope.limitContainer.reportLimit = oldVal;
}
}, true);
}
diff --git a/plugins/CoreHome/angularjs/report-export/reportexport.popover.html b/plugins/CoreHome/angularjs/report-export/reportexport.popover.html
index f206424602..24bbf7065f 100644
--- a/plugins/CoreHome/angularjs/report-export/reportexport.popover.html
+++ b/plugins/CoreHome/angularjs/report-export/reportexport.popover.html
@@ -38,24 +38,27 @@
data-title="{{ 'CoreHome_RowLimit'|translate }}"
ng-model="$parent.reportLimitAll"
ng-hide="maxFilterLimit > 0"
- full-width="false"
+ full-width="true"
options="limitAllOptions">
</div>
+
<div piwik-field uicontrol="number" name="filter_limit"
min="1"
- ng-model="$parent.reportLimit"
- full-width="false"
- ng-show="$parent.reportLimitAll == 'no' && maxFilterLimit <= 0">
+ ng-model="limitContainer.reportLimit"
+ value="{{ $parent.reportLimit }}"
+ full-width="true"
+ ng-if="$parent.reportLimitAll == 'no' && maxFilterLimit <= 0">
</div>
<div piwik-field uicontrol="number" name="filter_limit"
min="1"
- max="{{ scope.reportLimit }}"
- ng-model="$parent.reportLimit"
+ max="{{ scope.maxFilterLimit }}"
+ ng-model="limitContainer.reportLimit"
+ value="{{ $parent.reportLimit }}"
ng-keypress="scope.checkNumberForLimit"
- full-width="false"
+ full-width="true"
data-title="{{ 'CoreHome_RowLimit'|translate }} ({{ 'General_ComputedMetricMax'|translate:maxFilterLimit }})"
- ng-show="$parent.reportLimitAll == 'no' && maxFilterLimit > 0">
+ ng-if="$parent.reportLimitAll == 'no' && maxFilterLimit > 0">
</div>
</div>
</div>
diff --git a/plugins/CoreHome/angularjs/siteselector/siteselector-model.service.js b/plugins/CoreHome/angularjs/siteselector/siteselector-model.service.js
new file mode 100644
index 0000000000..eb10cd4235
--- /dev/null
+++ b/plugins/CoreHome/angularjs/siteselector/siteselector-model.service.js
@@ -0,0 +1,140 @@
+/*!
+ * Matomo - free/libre analytics platform
+ *
+ * @link https://matomo.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ */
+(function () {
+ angular.module('piwikApp').factory('siteSelectorModel', siteSelectorModel);
+
+ siteSelectorModel.$inject = ['piwikApi', '$filter', 'piwik', '$q'];
+
+ /**
+ * @deprecated kept for angularjs code that uses it.
+ */
+ function siteSelectorModel(piwikApi, $filter, piwik, $q) {
+
+ var initialSites = null;
+ var limitPromise = null;
+
+ var model = {
+ sites : [],
+ hasMultipleWebsites : false,
+ isLoading : false,
+ firstSiteName : '',
+ onlySitesWithAdminAccess: false,
+ updateWebsitesList: updateWebsitesList,
+ searchSite: searchSite,
+ loadSite: loadSite,
+ loadInitialSites: loadInitialSites,
+ hasMultipleSites: hasMultipleSites
+ };
+
+ return model;
+
+ function updateWebsitesList(sites) {
+
+ if (!sites || !sites.length) {
+ model.sites = [];
+ return [];
+ }
+
+ angular.forEach(sites, function (site) {
+ if (site.group) site.name = '[' + site.group + '] ' + site.name;
+ });
+
+ model.sites = sortSites(sites);
+
+ if (!model.firstSiteName) {
+ model.firstSiteName = model.sites[0].name;
+ }
+
+ model.hasMultipleWebsites = model.hasMultipleWebsites || sites.length > 1;
+
+ return model.sites;
+ }
+
+ function searchSite(term) {
+
+ if (!term) {
+ loadInitialSites();
+ return;
+ }
+
+ if (model.isLoading) {
+ if (model.currentRequest) {
+ model.currentRequest.abort();
+ } else if (limitPromise) {
+ limitPromise.abort();
+ limitPromise = null;
+ }
+ }
+
+ model.isLoading = true;
+
+ if (!limitPromise) {
+ limitPromise = piwikApi.fetch({method: 'SitesManager.getNumWebsitesToDisplayPerPage'});
+ }
+
+ return limitPromise.then(function (response) {
+ var limit = response.value;
+
+ var methodToCall = 'SitesManager.getPatternMatchSites';
+ if (model.onlySitesWithAdminAccess) {
+ methodToCall = 'SitesManager.getSitesWithAdminAccess';
+ }
+
+ model.currentRequest = piwikApi.fetch({
+ method: methodToCall,
+ limit: limit,
+ pattern: term
+ });
+
+ return model.currentRequest;
+ }).then(function (response) {
+ if (angular.isDefined(response)) {
+ return updateWebsitesList(response);
+ }
+ }).finally(function () {
+ model.isLoading = false;
+ model.currentRequest = null;
+ });
+ }
+
+ function loadSite(idsite) {
+ if (idsite == 'all') {
+ document.location.href = piwikHelper.getCurrentQueryStringWithParametersModified(piwikHelper.getQueryStringFromParameters({
+ module: 'MultiSites',
+ action: 'index',
+ date: piwik.currentDateString,
+ period: piwik.period
+ }));
+ } else {
+ piwik.broadcast.propagateNewPage('segment=&idSite=' + idsite, false);
+ }
+ }
+
+ function sortSites(websites)
+ {
+ return $filter('orderBy')(websites, '+name');
+ }
+
+ function loadInitialSites() {
+ if (initialSites) {
+ model.sites = initialSites;
+ var deferred = $q.defer();
+ deferred.resolve();
+ return deferred.promise;
+ }
+
+ return searchSite('%').then(function () {
+ initialSites = model.sites;
+ model.isInitialized = true
+ });
+ }
+
+ function hasMultipleSites() {
+ return initialSites && initialSites.length > 1;
+ }
+ }
+})();