diff options
author | dizzy <diosmosis@users.noreply.github.com> | 2021-12-01 20:19:20 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-12-01 20:19:20 +0300 |
commit | 43c21c99ef0451772a52a449729f832bfad8e82e (patch) | |
tree | ca4fe64af15b932887fad8ec7d5bb14194d81932 /plugins/CoreHome/angularjs | |
parent | eede069c84a97729d62689dcf0447d60b2056665 (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')
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; + } + } +})(); |