PDF rausgenommen
This commit is contained in:
@ -0,0 +1,3 @@
|
||||
<div class="field">
|
||||
{{ field.myProperty }}
|
||||
</div>
|
@ -0,0 +1,170 @@
|
||||
/*!
|
||||
* Piwik - free/libre analytics platform
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
*/
|
||||
|
||||
/**
|
||||
* Usage:
|
||||
* <div piwik-field>
|
||||
*
|
||||
* eg <div piwik-field uicontrol="select"
|
||||
* title="{{ 'SitesManager_Timezone'|translate }}"
|
||||
* value="site.timezone"
|
||||
* options="timezones"
|
||||
* inline-help="test"
|
||||
* description=""
|
||||
* introduction=""
|
||||
* name=""
|
||||
* placeholder=""
|
||||
* rows="3"
|
||||
* autocomplete="off"
|
||||
* data-disabled="true"
|
||||
* full-width="true"
|
||||
* templateFile=""></div>
|
||||
*
|
||||
* templateFile allows to render a custom template
|
||||
* We do not use type= attribute here as it would match some CSS from input type=radio etc
|
||||
*/
|
||||
(function () {
|
||||
angular.module('piwikApp').directive('piwikField', piwikField);
|
||||
|
||||
piwikField.$inject = ['piwik', '$compile'];
|
||||
|
||||
function piwikField(piwik, $compile){
|
||||
|
||||
return {
|
||||
restrict: 'A',
|
||||
require: '?ngModel',
|
||||
scope: {
|
||||
uicontrol: '@',
|
||||
name: '@',
|
||||
value: '@',
|
||||
default: '@',
|
||||
options: '=',
|
||||
description: '@',
|
||||
introduction: '@',
|
||||
title: '@',
|
||||
inlineHelp: '@',
|
||||
disabled: '=',
|
||||
uiControlAttributes: '=',
|
||||
autocomplete: '@',
|
||||
condition: '@',
|
||||
varType: '@',
|
||||
autofocus: '@',
|
||||
tabindex: '@',
|
||||
templateFile: '@',
|
||||
fullWidth: '@',
|
||||
maxlength: '@',
|
||||
required: '@',
|
||||
placeholder: '@',
|
||||
rows: '@',
|
||||
min: '@',
|
||||
max: '@'
|
||||
},
|
||||
template: '<div piwik-form-field="field"></div>',
|
||||
link: function(scope, elm, attrs, ctrl) {
|
||||
if (!ctrl) {
|
||||
return;
|
||||
}
|
||||
|
||||
// load init value
|
||||
if (scope.field.value !== undefined && scope.field.value !== null) {
|
||||
ctrl.$setViewValue(scope.field.value);
|
||||
} else if (ctrl.$viewValue) {
|
||||
scope.field.value = ctrl.$viewValue;
|
||||
}
|
||||
|
||||
// view -> model
|
||||
scope.$watch('field.value', function (val, oldVal) {
|
||||
if (val !== oldVal && val !== ctrl.$viewValue) {
|
||||
ctrl.$setViewValue(val);
|
||||
}
|
||||
});
|
||||
|
||||
// model -> view
|
||||
ctrl.$render = function() {
|
||||
scope.field.value = ctrl.$viewValue;
|
||||
};
|
||||
|
||||
},
|
||||
controller: function ($scope) {
|
||||
var field = {};
|
||||
field.uiControl = $scope.uicontrol;
|
||||
if ($scope.varType) {
|
||||
field.type = $scope.varType;
|
||||
} else if (field.uiControl === 'multiselect') {
|
||||
field.type = 'array';
|
||||
} else if (field.uiControl === 'checkbox') {
|
||||
field.type = 'boolean';
|
||||
} else if (field.uiControl === 'site') {
|
||||
field.type = 'object';
|
||||
} else if (field.uiControl === 'number') {
|
||||
field.type = 'integer';
|
||||
} else {
|
||||
field.type = 'string';
|
||||
}
|
||||
|
||||
field.name = $scope.name;
|
||||
field.value = $scope.value;
|
||||
field.defaultValue = $scope.default;
|
||||
field.availableValues = $scope.options;
|
||||
field.description = $scope.description;
|
||||
field.introduction = $scope.introduction;
|
||||
field.inlineHelp = $scope.inlineHelp;
|
||||
field.templateFile = $scope.templateFile;
|
||||
field.title = $scope.title;
|
||||
field.uiControlAttributes = $scope.uiControlAttributes || {};
|
||||
field.fullWidth = !!$scope.fullWidth;
|
||||
|
||||
if (field.type === 'array' && angular.isString(field.value) && field.value) {
|
||||
field.value = JSON.parse(field.value);
|
||||
}
|
||||
|
||||
var i = 0, attribute;
|
||||
var attributes = ['disabled', 'autocomplete', 'tabindex', 'autofocus', 'rows', 'required', 'maxlength', 'placeholder', 'min', 'max'];
|
||||
for (i; i < attributes.length; i++) {
|
||||
attribute = attributes[i];
|
||||
if (!!$scope[attribute]) {
|
||||
field.uiControlAttributes[attribute] = $scope[attribute];
|
||||
}
|
||||
}
|
||||
|
||||
$scope.field = field;
|
||||
|
||||
$scope.$watch('options', function (val, oldVal) {
|
||||
if (val !== oldVal) {
|
||||
$scope.field.availableValues = val;
|
||||
}
|
||||
});
|
||||
|
||||
$scope.$watch('title', function (val, oldVal) {
|
||||
if (val !== oldVal) {
|
||||
$scope.field.title = val;
|
||||
}
|
||||
});
|
||||
|
||||
$scope.$watch('inlineHelp', function (val, oldVal) {
|
||||
if (val !== oldVal) {
|
||||
$scope.field.inlineHelp = val;
|
||||
}
|
||||
});
|
||||
|
||||
if ('undefined' !== typeof $scope.placeholder && $scope.placeholder !== null) {
|
||||
$scope.$watch('placeholder', function (val, oldVal) {
|
||||
if (val !== oldVal) {
|
||||
$scope.field.uiControlAttributes.placeholder = val;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
$scope.$watch('disabled', function (val, oldVal) {
|
||||
if (val !== oldVal) {
|
||||
$scope.field.uiControlAttributes.disabled = val;
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
})();
|
@ -0,0 +1,16 @@
|
||||
<div>
|
||||
<label class="fieldRadioTitle" ng-show="formField.title">{{ formField.title }}</label>
|
||||
<p ng-repeat="checkboxModel in formField.availableOptions"
|
||||
class="checkbox">
|
||||
<input ng-model="formField.checkboxkeys[$index.toString()]"
|
||||
value="{{ checkboxModel.key }}"
|
||||
ng-change="formField.updateCheckboxArrayValue()"
|
||||
piwik-attributes="{{formField.uiControlAttributes}}"
|
||||
type="checkbox"
|
||||
id="{{ formField.name + checkboxModel.key }}"
|
||||
name="{{ checkboxModel.name }}">
|
||||
|
||||
<label for="{{ formField.name + checkboxModel.key }}">{{ checkboxModel.value }}
|
||||
<span class="form-description" ng-show="checkboxModel.description">{{ checkboxModel.description }}</span></label>
|
||||
</p>
|
||||
</div>
|
@ -0,0 +1,10 @@
|
||||
<div class="checkbox">
|
||||
<input ng-model="formField.value"
|
||||
piwik-attributes="{{formField.uiControlAttributes}}"
|
||||
ng-value="1"
|
||||
type="checkbox"
|
||||
id="{{ formField.name }}"
|
||||
name="{{ formField.name }}">
|
||||
|
||||
<label for="{{ formField.name }}" ng-bind-html="formField.title"></label>
|
||||
</div>
|
@ -0,0 +1,24 @@
|
||||
<div class="expandableSelector" piwik-focus-anywhere-but-here="formField.showSelect = false">
|
||||
<div ng-click="formField.showSelect = !formField.showSelect" class="select-wrapper"
|
||||
><span class="caret">▼</span><input type="text" class="select-dropdown"
|
||||
readonly="true" value="{{ formField.title }}">
|
||||
</div>
|
||||
|
||||
<div ng-show="formField.showSelect" class="expandableList z-depth-2">
|
||||
|
||||
<div class="searchContainer">
|
||||
<input type="text" placeholder="Search"
|
||||
ng-model="formField.searchTerm" class="expandableSearch browser-default"
|
||||
piwik-focus-if="formField.showSelect">
|
||||
</div>
|
||||
<ul class="collection firstLevel">
|
||||
<li ng-repeat="options in formField.availableOptions" class="collection-item" ng-show="options.values|filter:formField.searchTerm|length">
|
||||
<h4 class="expandableListCategory" ng-click="formField.showCategory == options.group ? formField.showCategory = '' : formField.showCategory = options.group">{{ options.group }} <span class="secondary-content" ng-class='{"icon-arrow-right": formField.showCategory != options.group, "icon-arrow-bottom": formField.showCategory == options.group}'></span></h4>
|
||||
|
||||
<ul ng-show="formField.showCategory == options.group || formField.searchTerm" class="collection secondLevel">
|
||||
<li class="expandableListItem collection-item valign-wrapper" ng-repeat="children in options.values|filter:formField.searchTerm" ng-click="formField.value = children.key;formField.showSelect = false;"><span class="primary-content">{{ children.value }}</span> <span ng-show="children.tooltip" title="{{ children.tooltip }}" class="secondary-content icon-help"></span></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
@ -0,0 +1,88 @@
|
||||
.expandableSelector {
|
||||
|
||||
position: relative;
|
||||
|
||||
.secondary-content {
|
||||
font-size: 16px;
|
||||
margin-top: -3px;
|
||||
color: @theme-color-link;
|
||||
cursor: help;
|
||||
}
|
||||
|
||||
ul {
|
||||
min-width: 250px;
|
||||
|
||||
&.collection.firstLevel {
|
||||
border-top: 0;
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
font-size: 12px;
|
||||
|
||||
> li {
|
||||
padding: 0 !important;
|
||||
}
|
||||
}
|
||||
|
||||
.expandableListCategory {
|
||||
padding: 10px 20px;
|
||||
color: @theme-color-link;
|
||||
}
|
||||
|
||||
li {
|
||||
&:hover {
|
||||
background: #f2f2f2 !important;
|
||||
}
|
||||
|
||||
&.collection-item {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
ul {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
|
||||
.primary-content {
|
||||
width: 100%;
|
||||
}
|
||||
.secondary-content {
|
||||
margin-top: 3px;
|
||||
}
|
||||
|
||||
li {
|
||||
padding-top: 6px !important;
|
||||
padding-bottom: 6px !important;
|
||||
padding-left: 30px !important;
|
||||
min-width: 200px;
|
||||
|
||||
&:hover {
|
||||
background: #f2f2f2 !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.searchContainer {
|
||||
padding: 5px;
|
||||
border-left: 1px solid #e0e0e0;
|
||||
border-right: 1px solid #e0e0e0;
|
||||
border-top: 1px solid #e0e0e0;
|
||||
}
|
||||
|
||||
.expandableSearch {
|
||||
vertical-align: top;
|
||||
padding: 7px 6px !important;
|
||||
border: 1px solid #d0d0d0 !important;
|
||||
background: #fff !important;
|
||||
font-size: 11px !important;
|
||||
color: #454545 !important;
|
||||
width: 100% !important;
|
||||
}
|
||||
|
||||
.expandableList {
|
||||
position: absolute;
|
||||
z-index: 9999;
|
||||
margin-top: -48px;
|
||||
background: #fff;
|
||||
}
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
<div>
|
||||
<div matomo-field-array
|
||||
name="{{ formField.name }}"
|
||||
ng-model="formField.value"
|
||||
field="formField.uiControlAttributes.field">
|
||||
</div>
|
||||
<label for="{{ formField.name }}" ng-bind-html="formField.title"></label>
|
||||
</div>
|
@ -0,0 +1,10 @@
|
||||
<div>
|
||||
<div class="btn">
|
||||
<span for="{{ formField.name }}" ng-bind-html="formField.title"></span>
|
||||
<input name="{{ formField.name }}" type="file" id="{{ formField.name }}">
|
||||
</div>
|
||||
|
||||
<div class="file-path-wrapper">
|
||||
<input class="file-path validate" ng-model="formField.value" type="text">
|
||||
</div>
|
||||
</div>
|
@ -0,0 +1,6 @@
|
||||
<div>
|
||||
<input type="{{ formField.uiControl }}"
|
||||
name="{{ formField.name }}"
|
||||
ng-model="formField.value"
|
||||
>
|
||||
</div>
|
@ -0,0 +1,9 @@
|
||||
<div>
|
||||
<select multiple
|
||||
name="{{ formField.name }}"
|
||||
ng-model="formField.value"
|
||||
ng-options="t.key as t.value group by t.group for t in formField.availableOptions"
|
||||
piwik-attributes="{{formField.uiControlAttributes}}">
|
||||
</select>
|
||||
<label for="{{ formField.name }}" ng-bind-html="formField.title"></label>
|
||||
</div>
|
@ -0,0 +1,9 @@
|
||||
<div>
|
||||
<div matomo-multi-pair-field
|
||||
name="{{ formField.name }}"
|
||||
ng-model="formField.value"
|
||||
field1="formField.uiControlAttributes.field1"
|
||||
field2="formField.uiControlAttributes.field2">
|
||||
</div>
|
||||
<label for="{{ formField.name }}" ng-bind-html="formField.title"></label>
|
||||
</div>
|
@ -0,0 +1,13 @@
|
||||
<div>
|
||||
<input
|
||||
class="control_{{ formField.uiControl }}"
|
||||
type="{{ formField.uiControl }}"
|
||||
id="{{ formField.name }}"
|
||||
name="{{ formField.name }}"
|
||||
ng-model="formField.value"
|
||||
string-to-number
|
||||
ng-value="formField.value"
|
||||
piwik-attributes="{{formField.uiControlAttributes}}"
|
||||
>
|
||||
<label for="{{ formField.name }}" ng-bind-html="formField.title"></label>
|
||||
</div>
|
@ -0,0 +1,17 @@
|
||||
<div>
|
||||
<label class="fieldRadioTitle" ng-show="formField.title">{{ formField.title }}</label>
|
||||
|
||||
<p ng-repeat="radioModel in formField.availableOptions"
|
||||
class="radio">
|
||||
<input ng-model="formField.value"
|
||||
ng-value="radioModel.key"
|
||||
type="radio"
|
||||
id="{{ formField.name + radioModel.key }}"
|
||||
name="{{ formField.name }}"
|
||||
ng-disabled="radioModel.disabled || formField.disabled"
|
||||
piwik-attributes="{{formField.uiControlAttributes}}"
|
||||
>
|
||||
<label for="{{ formField.name + radioModel.key }}">{{ radioModel.value }}
|
||||
<span class="form-description" ng-show="radioModel.description">{{ radioModel.description }}</span></label>
|
||||
</p>
|
||||
</div>
|
@ -0,0 +1,10 @@
|
||||
<div>
|
||||
<select name="{{ formField.name }}"
|
||||
ng-model="formField.value"
|
||||
ng-options="t.key as t.value group by t.group disable when t.disabled for t in formField.availableOptions"
|
||||
piwik-attributes="{{formField.uiControlAttributes}}"
|
||||
ng-click="onShowSelect()"
|
||||
>
|
||||
</select>
|
||||
<label for="{{ formField.name }}" ng-bind-html="formField.title"></label>
|
||||
</div>
|
@ -0,0 +1,14 @@
|
||||
<div>
|
||||
<label for="{{ formField.name }}" class="siteSelectorLabel" ng-bind-html="formField.title"></label>
|
||||
<div piwik-siteselector
|
||||
class="sites_autocomplete"
|
||||
ng-model="formField.value"
|
||||
id="{{ formField.name }}"
|
||||
show-all-sites-item="formField.uiControlAttributes.showAllSitesItem || false"
|
||||
switch-site-on-select="false"
|
||||
show-selected-site="true"
|
||||
only-sites-with-admin-access="formField.uiControlAttributes.onlySitesWithAdminAccess || false"
|
||||
placeholder="{{ formField.uiControlAttributes.placeholder }}"
|
||||
piwik-attributes="{{formField.uiControlAttributes}}"
|
||||
></div>
|
||||
</div>
|
@ -0,0 +1,10 @@
|
||||
<div>
|
||||
<input class="control_{{ formField.uiControl }}"
|
||||
type="{{ formField.uiControl }}"
|
||||
name="{{ formField.name }}"
|
||||
ng-list
|
||||
ng-model="formField.value"
|
||||
piwik-attributes="{{formField.uiControlAttributes}}"
|
||||
>
|
||||
<label for="{{ formField.name }}" ng-bind-html="formField.title"></label>
|
||||
</div>
|
@ -0,0 +1,13 @@
|
||||
<div>
|
||||
<input
|
||||
class="control_{{ formField.uiControl }}"
|
||||
type="{{ formField.uiControl }}"
|
||||
id="{{ formField.name }}"
|
||||
name="{{ formField.name }}"
|
||||
ng-model="formField.value"
|
||||
ng-value="formField.value"
|
||||
ng-trim="false"
|
||||
piwik-attributes="{{formField.uiControlAttributes}}"
|
||||
>
|
||||
<label for="{{ formField.name }}" ng-bind-html="formField.title"></label>
|
||||
</div>
|
@ -0,0 +1,9 @@
|
||||
<div>
|
||||
<textarea name="{{ formField.name }}"
|
||||
ng-list=" " ng-trim="false"
|
||||
piwik-attributes="{{formField.uiControlAttributes}}"
|
||||
ng-model="formField.value"
|
||||
class="materialize-textarea"
|
||||
></textarea>
|
||||
<label for="{{ formField.name }}" ng-bind-html="formField.title"></label>
|
||||
</div>
|
@ -0,0 +1,9 @@
|
||||
<div>
|
||||
<textarea name="{{ formField.name }}"
|
||||
piwik-attributes="{{formField.uiControlAttributes}}"
|
||||
id="{{ formField.name }}"
|
||||
ng-model="formField.value"
|
||||
class="materialize-textarea"
|
||||
></textarea>
|
||||
<label for="{{ formField.name }}" ng-bind-html="formField.title"></label>
|
||||
</div>
|
@ -0,0 +1,28 @@
|
||||
<div class="form-group row" ng-show="formField.showField">
|
||||
|
||||
<h3 ng-if="formField.introduction" class="col s12">{{ formField.introduction }}</h3>
|
||||
|
||||
<div class="col s12"
|
||||
ng-class="{'input-field': formField.uiControl != 'checkbox' && formField.uiControl != 'radio', 'file-field': formField.uiControl == 'file', 'm6': !formField.fullWidth}"
|
||||
ng-include="formField.templateFile" onload="templateLoaded()"
|
||||
>
|
||||
|
||||
</div>
|
||||
<div class="col s12"
|
||||
ng-class="{'m6': !formField.fullWidth}">
|
||||
<div ng-if="formField.description || formField.inlineHelp || (formField.defaultValue && formField.uiControl != 'checkbox' && formField.uiControl != 'radio')"
|
||||
class="form-help">
|
||||
|
||||
<div ng-show="formField.description"
|
||||
class='form-description'>{{ formField.description }}</div>
|
||||
|
||||
<span class="inline-help" ng-bind-html="formField.inlineHelp"></span>
|
||||
|
||||
<span ng-show="formField.defaultValuePretty && formField.uiControl != 'checkbox' && formField.uiControl != 'radio'">
|
||||
<br />
|
||||
{{ 'General_Default'|translate }}:
|
||||
<span>{{formField.defaultValuePretty|limitTo:50}}</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@ -0,0 +1,451 @@
|
||||
/*!
|
||||
* Piwik - free/libre analytics platform
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
*/
|
||||
|
||||
/**
|
||||
* Usage:
|
||||
* <div piwik-form-field="{...}">
|
||||
*/
|
||||
(function () {
|
||||
angular.module('piwikApp').directive('piwikFormField', piwikFormField);
|
||||
|
||||
piwikFormField.$inject = ['piwik', '$timeout'];
|
||||
|
||||
function piwikFormField(piwik, $timeout){
|
||||
|
||||
function initMaterialSelect($select, placeholder) {
|
||||
$select.material_select();
|
||||
|
||||
// to prevent overlapping selects, when a select is opened, we set the z-index to a high value on focus & remove z-index for all others
|
||||
// NOTE: we can't remove it directly blur since the blur causes the select to overlap, aborting the select click. (a timeout is used
|
||||
// to make sure the z-index is removed however, in case a non-select dropdown is displayed over it)
|
||||
$select.closest('.select-wrapper').find('input.select-dropdown')
|
||||
.focus(function () {
|
||||
$('.select-wrapper').css('z-index', '');
|
||||
$(this).closest('.select-wrapper').css('z-index', 999);
|
||||
}).blur(function () {
|
||||
var self = this;
|
||||
setTimeout(function () {
|
||||
$(self).closest('.select-wrapper').css('z-index', '');
|
||||
}, 250);
|
||||
});
|
||||
|
||||
// add placeholder to input
|
||||
if (placeholder) {
|
||||
var $materialInput = $select.closest('.select-wrapper').find('input');
|
||||
$materialInput.attr('placeholder', placeholder);
|
||||
}
|
||||
}
|
||||
|
||||
function syncMultiCheckboxKeysWithFieldValue(field)
|
||||
{
|
||||
angular.forEach(field.availableOptions, function (option, index) {
|
||||
if (option && field.value.indexOf(option.key) !== -1) {
|
||||
field.checkboxkeys[index] = true;
|
||||
} else {
|
||||
field.checkboxkeys[index] = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function hasUiControl(field, uiControlType)
|
||||
{
|
||||
return field.uiControl === uiControlType;
|
||||
}
|
||||
|
||||
function isSelectControl(field)
|
||||
{
|
||||
return hasUiControl(field, 'select') || hasUiControl(field, 'multiselect');
|
||||
}
|
||||
|
||||
function isArrayCheckboxControl(field)
|
||||
{
|
||||
return field.type === 'array' && hasUiControl(field, 'checkbox');
|
||||
}
|
||||
|
||||
function hasGroupedValues(availableValues)
|
||||
{
|
||||
if (!angular.isObject(availableValues)
|
||||
|| angular.isArray(availableValues)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var key;
|
||||
for (key in availableValues) {
|
||||
if (Object.prototype.hasOwnProperty.call(availableValues, key)) {
|
||||
if (angular.isObject(availableValues[key])) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function whenRendered(scope, element, inlineHelpNode) {
|
||||
return function () {
|
||||
var field = scope.formField;
|
||||
|
||||
if (inlineHelpNode) {
|
||||
angular.element(inlineHelpNode).appendTo(element.find('.inline-help'));
|
||||
}
|
||||
|
||||
if (isSelectControl(field)) {
|
||||
var $select = element.find('select');
|
||||
initMaterialSelect($select, field.uiControlAttributes.placeholder);
|
||||
|
||||
scope.$watch('formField.value', function (val, oldVal) {
|
||||
if (val !== oldVal) {
|
||||
$timeout(function () {
|
||||
initMaterialSelect($select, field.uiControlAttributes.placeholder);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
scope.$watch('formField.uiControlAttributes.disabled', function (val, oldVal) {
|
||||
if (val !== oldVal) {
|
||||
$timeout(function () {
|
||||
initMaterialSelect($select, field.uiControlAttributes.placeholder);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
} else if (hasUiControl(field, 'textarea')) {
|
||||
element.find('textarea').trigger('autoresize');
|
||||
scope.$watch('formField.value', function (val, oldVal) {
|
||||
if (val !== oldVal) {
|
||||
$timeout(function () {
|
||||
element.find('textarea').trigger('autoresize');
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
} else if (hasUiControl(field, 'file')) {
|
||||
|
||||
// angular doesn't support file input type with ngModel. We implement our own "two way binding"
|
||||
var $file = element.find('[type=file]');
|
||||
|
||||
$file.on('change', function () {
|
||||
scope.formField.value = $(this).val();
|
||||
});
|
||||
|
||||
scope.$watch('formField.value', function (val, oldVal) {
|
||||
if (val !== oldVal && val === '') {
|
||||
$file.val('');
|
||||
}
|
||||
});
|
||||
|
||||
} else if (isArrayCheckboxControl(field)) {
|
||||
|
||||
Materialize.updateTextFields();
|
||||
|
||||
scope.$watch('formField.value', function (val, oldVal) {
|
||||
if (val !== oldVal && val && !oldVal && angular.isArray(val)) {
|
||||
// we do this only on initial check
|
||||
syncMultiCheckboxKeysWithFieldValue(field);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
} else if (hasUiControl(field, 'text')
|
||||
|| hasUiControl(field, 'textarea')
|
||||
|| hasUiControl(field, 'password')
|
||||
|| hasUiControl(field, 'email')
|
||||
|| hasUiControl(field, 'number')
|
||||
|| hasUiControl(field, 'url')
|
||||
|| hasUiControl(field, 'search')) {
|
||||
Materialize.updateTextFields();
|
||||
scope.$watch('formField.value', function (val, oldVal) {
|
||||
if (val !== oldVal) {
|
||||
$timeout(function () {
|
||||
Materialize.updateTextFields();
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
return {
|
||||
restrict: 'A',
|
||||
scope: {
|
||||
piwikFormField: '=',
|
||||
allSettings: '='
|
||||
},
|
||||
templateUrl: 'plugins/CorePluginsAdmin/angularjs/form-field/form-field.directive.html?cb=' + piwik.cacheBuster,
|
||||
compile: function (element, attrs) {
|
||||
|
||||
function evaluateConditionalExpression(scope, field)
|
||||
{
|
||||
if (!field.condition) {
|
||||
return;
|
||||
}
|
||||
|
||||
var values = {};
|
||||
angular.forEach(scope.allSettings, function (setting) {
|
||||
if (setting.value === '0') {
|
||||
values[setting.name] = 0;
|
||||
} else {
|
||||
values[setting.name] = setting.value;
|
||||
}
|
||||
});
|
||||
|
||||
field.showField = scope.$eval(field.condition, values);
|
||||
}
|
||||
|
||||
function formatAvailableValues(field)
|
||||
{
|
||||
if (!field.availableValues) {
|
||||
return;
|
||||
}
|
||||
|
||||
var flatValues = [];
|
||||
|
||||
if (hasUiControl(field, 'radio') || hasUiControl(field, 'checkbox')) {
|
||||
angular.forEach(field.availableValues, function (value, key) {
|
||||
|
||||
if (angular.isObject(value) && typeof value.key !== 'undefined'){
|
||||
flatValues.push(value);
|
||||
return;
|
||||
}
|
||||
|
||||
if (field.type === 'integer' && angular.isString(key)) {
|
||||
key = parseInt(key, 10);
|
||||
}
|
||||
|
||||
flatValues.push({key: key, value: value});
|
||||
});
|
||||
|
||||
return flatValues;
|
||||
}
|
||||
|
||||
if (hasUiControl(field, 'expandable-select')) {
|
||||
var availableValues = field.availableValues;
|
||||
var flatValues = [];
|
||||
|
||||
var groups = {};
|
||||
angular.forEach(availableValues, function (value) {
|
||||
|
||||
if (!value.group) {
|
||||
value.group = '';
|
||||
}
|
||||
|
||||
if (!(value.group in groups) || !groups[value.group]) {
|
||||
groups[value.group] = {values: [], group: value.group}
|
||||
}
|
||||
|
||||
var formatted = {key: value.key, value: value.value};
|
||||
|
||||
if ('tooltip' in value && value.tooltip) {
|
||||
formatted.tooltip = value.tooltip;
|
||||
}
|
||||
|
||||
groups[value.group].values.push(formatted);
|
||||
});
|
||||
|
||||
angular.forEach(groups, function (group) {
|
||||
if (group.values.length) {
|
||||
flatValues.push(group);
|
||||
}
|
||||
});
|
||||
|
||||
return flatValues;
|
||||
}
|
||||
|
||||
if (isSelectControl(field)) {
|
||||
var availableValues = field.availableValues;
|
||||
|
||||
if (!hasGroupedValues(availableValues)) {
|
||||
availableValues = {'': availableValues};
|
||||
}
|
||||
|
||||
var flatValues = [];
|
||||
angular.forEach(availableValues, function (values, group) {
|
||||
angular.forEach(values, function (value, key) {
|
||||
|
||||
if (angular.isObject(value) && typeof value.key !== 'undefined'){
|
||||
flatValues.push(value);
|
||||
return;
|
||||
}
|
||||
|
||||
if (field.type === 'integer' && angular.isString(key)) {
|
||||
key = parseInt(key, 10);
|
||||
}
|
||||
|
||||
flatValues.push({group: group, key: key, value: value});
|
||||
});
|
||||
});
|
||||
|
||||
return flatValues;
|
||||
}
|
||||
|
||||
return field.availableValues;
|
||||
}
|
||||
|
||||
function formatPrettyDefaultValue(defaultValue, availableOptions) {
|
||||
if (angular.isString(defaultValue) && defaultValue) {
|
||||
// eg default value for multi tuple
|
||||
var defaultParsed = null;
|
||||
try {
|
||||
defaultParsed = JSON.parse(defaultValue);
|
||||
} catch (e) {
|
||||
// invalid JSON
|
||||
}
|
||||
|
||||
if (angular.isObject(defaultParsed)) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
if (!angular.isArray(availableOptions)) {
|
||||
if (angular.isArray(defaultValue)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
var prettyValues = [];
|
||||
|
||||
if (!angular.isArray(defaultValue)) {
|
||||
defaultValue = [defaultValue];
|
||||
}
|
||||
|
||||
angular.forEach(availableOptions, function (value, key) {
|
||||
if (defaultValue.indexOf(value.key) !== -1 && typeof value.value !== 'undefined') {
|
||||
prettyValues.push(value.value);
|
||||
}
|
||||
});
|
||||
|
||||
return prettyValues.join(', ');
|
||||
}
|
||||
|
||||
return function (scope, element, attrs) {
|
||||
var field = scope.piwikFormField;
|
||||
var defaultValue = field.defaultValue;
|
||||
|
||||
|
||||
if (angular.isArray(field.defaultValue)) {
|
||||
field.defaultValue = defaultValue.join(',');
|
||||
}
|
||||
|
||||
// convert boolean values since angular 1.6 uses strict equals when determining if a model value
|
||||
// matches the ng-value of an input.
|
||||
if (field.type === 'boolean') {
|
||||
var valueIsTruthy = field.value && field.value > 0 && field.value !== '0';
|
||||
|
||||
// for checkboxes, the value MUST be either true or faluse
|
||||
if (field.uiControl === 'checkbox') {
|
||||
field.value = valueIsTruthy;
|
||||
} else if (field.uiControl === 'radio') {
|
||||
field.value = valueIsTruthy ? '1' : '0';
|
||||
}
|
||||
}
|
||||
|
||||
// we are setting availableOptions and not availableValues again. Otherwise when watching the scope
|
||||
// availableValues and in the watch change availableValues could trigger lots of more watch events
|
||||
field.availableOptions = formatAvailableValues(field);
|
||||
|
||||
// for selects w/ a placeholder, add an option to unset the select
|
||||
if (field.uiControl === 'select'
|
||||
&& field.uiControlAttributes.placeholder
|
||||
&& !hasOption('')
|
||||
) {
|
||||
field.availableOptions.splice(0, 0, { key: '', value: '' });
|
||||
}
|
||||
|
||||
field.defaultValuePretty = formatPrettyDefaultValue(defaultValue, field.availableOptions);
|
||||
|
||||
field.showField = true;
|
||||
|
||||
var inlineHelpNode;
|
||||
if (field.inlineHelp && field.inlineHelp.indexOf('#') === 0) {
|
||||
inlineHelpNode = field.inlineHelp;
|
||||
field.inlineHelp = ' '; // we make sure inline help will be shown
|
||||
}
|
||||
|
||||
if (isArrayCheckboxControl(field)) {
|
||||
field.updateCheckboxArrayValue = function () {
|
||||
var values = [];
|
||||
for (var x in field.checkboxkeys) {
|
||||
if (field.checkboxkeys[x]) {
|
||||
values.push(field.availableOptions[x].key);
|
||||
}
|
||||
}
|
||||
field.value = values;
|
||||
}
|
||||
field.checkboxkeys = new Array(field.availableOptions.length);
|
||||
|
||||
if (field.value && angular.isArray(field.value)) {
|
||||
syncMultiCheckboxKeysWithFieldValue(field);
|
||||
}
|
||||
}
|
||||
|
||||
if (field.condition && scope.allSettings) {
|
||||
evaluateConditionalExpression(scope, field);
|
||||
|
||||
for (var key in scope.allSettings) {
|
||||
if(scope.allSettings.hasOwnProperty(key)) {
|
||||
scope.$watchCollection('allSettings[' + key + '].value', function (val, oldVal) {
|
||||
if (val !== oldVal) {
|
||||
evaluateConditionalExpression(scope, field);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!field.templateFile) {
|
||||
field.templateFile = getTemplate(field);
|
||||
}
|
||||
|
||||
scope.formField = field;
|
||||
|
||||
scope.$watch('formField.availableValues', function (val, oldVal) {
|
||||
if (val !== oldVal) {
|
||||
scope.formField.availableOptions = formatAvailableValues(scope.formField);
|
||||
|
||||
if (isSelectControl(scope.formField)) {
|
||||
$timeout(function () {
|
||||
initMaterialSelect(element.find('select'), field.uiControlAttributes.placeholder);
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
scope.templateLoaded = function () {
|
||||
$timeout(whenRendered(scope, element, inlineHelpNode));
|
||||
};
|
||||
|
||||
function hasOption(key) {
|
||||
for (var i = 0; i !== field.availableOptions.length; ++i) {
|
||||
if (field.availableOptions[i].key === key) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
})();
|
@ -0,0 +1,39 @@
|
||||
/*!
|
||||
* Piwik - free/libre analytics platform
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
*/
|
||||
|
||||
/**
|
||||
* Usage:
|
||||
* <div piwik-form>
|
||||
*/
|
||||
(function () {
|
||||
angular.module('piwikApp').directive('piwikForm', piwikForm);
|
||||
|
||||
piwikForm.$inject = ['piwik', '$timeout'];
|
||||
|
||||
function piwikForm(piwik, $timeout){
|
||||
|
||||
return {
|
||||
restrict: 'A',
|
||||
priority: '10',
|
||||
compile: function (element, attrs) {
|
||||
|
||||
return function (scope, element, attrs) {
|
||||
|
||||
$timeout(function () {
|
||||
|
||||
element.find('input[type=text]').keypress(function (e) {
|
||||
var key = e.keyCode || e.which;
|
||||
if (key == 13) {
|
||||
element.find('[piwik-save-button] input').triggerHandler('click');
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
})();
|
@ -0,0 +1,74 @@
|
||||
/*!
|
||||
* Piwik - free/libre analytics platform
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
*/
|
||||
(function () {
|
||||
angular.module('piwikApp').controller('PluginSettingsController', PluginSettingsController);
|
||||
|
||||
PluginSettingsController.$inject = ['$scope', 'piwikApi'];
|
||||
|
||||
function PluginSettingsController($scope, piwikApi) {
|
||||
// remember to keep controller very simple. Create a service/factory (model) if needed
|
||||
|
||||
var self = this;
|
||||
|
||||
this.isLoading = true;
|
||||
this.isSaving = {};
|
||||
|
||||
var apiMethod = 'CorePluginsAdmin.getUserSettings';
|
||||
|
||||
if ($scope.mode === 'admin') {
|
||||
apiMethod = 'CorePluginsAdmin.getSystemSettings';
|
||||
}
|
||||
|
||||
piwikApi.fetch({method: apiMethod}).then(function (settings) {
|
||||
self.isLoading = false;
|
||||
self.settingsPerPlugin = settings;
|
||||
}, function () {
|
||||
self.isLoading = false;
|
||||
});
|
||||
|
||||
this.save = function (settings) {
|
||||
var apiMethod = 'CorePluginsAdmin.setUserSettings';
|
||||
if ($scope.mode === 'admin') {
|
||||
apiMethod = 'CorePluginsAdmin.setSystemSettings';
|
||||
}
|
||||
|
||||
this.isSaving[settings.pluginName] = true;
|
||||
|
||||
var values = {};
|
||||
if (!values[settings.pluginName]) {
|
||||
values[settings.pluginName] = [];
|
||||
}
|
||||
|
||||
angular.forEach(settings.settings, function (setting) {
|
||||
var value = setting.value;
|
||||
if (value === false) {
|
||||
value = '0';
|
||||
} else if (value === true) {
|
||||
value = '1';
|
||||
}
|
||||
values[settings.pluginName].push({
|
||||
name: setting.name,
|
||||
value: value
|
||||
});
|
||||
});
|
||||
|
||||
piwikApi.post({method: apiMethod}, {settingValues: values}).then(function (success) {
|
||||
self.isSaving[settings.pluginName] = false;
|
||||
|
||||
var UI = require('piwik/UI');
|
||||
var notification = new UI.Notification();
|
||||
notification.show(_pk_translate('CoreAdminHome_PluginSettingsSaveSuccess'), {
|
||||
id: 'generalSettings', context: 'success'
|
||||
});
|
||||
notification.scrollToNotification();
|
||||
|
||||
}, function () {
|
||||
self.isSaving[settings.pluginName] = false;
|
||||
});
|
||||
};
|
||||
}
|
||||
})();
|
@ -0,0 +1,25 @@
|
||||
<div class="pluginSettings">
|
||||
|
||||
<div ng-repeat="settings in pluginSettings.settingsPerPlugin"
|
||||
class="card"
|
||||
id="{{ settings.pluginName }}PluginSettings">
|
||||
|
||||
<div class="card-content">
|
||||
<h2 id="{{ settings.pluginName }}" class="card-title">{{ settings.title }}</h2>
|
||||
|
||||
<div ng-repeat="setting in settings.settings">
|
||||
<div piwik-form-field="setting" all-settings="settings.settings"></div>
|
||||
</div>
|
||||
|
||||
<input type="button" ng-click="pluginSettings.save(settings)"
|
||||
ng-disabled="pluginSettings.isLoading"
|
||||
value="{{ 'General_Save'|translate }}"
|
||||
class="pluginsSettingsSubmit btn"/>
|
||||
|
||||
<div piwik-activity-indicator loading="pluginSettings.isLoading || pluginSettings.isSaving[settings.pluginName]"></div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
@ -0,0 +1,44 @@
|
||||
/*!
|
||||
* Piwik - free/libre analytics platform
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
*/
|
||||
|
||||
/**
|
||||
* Usage:
|
||||
* <div piwik-plugin-settings>
|
||||
*/
|
||||
(function () {
|
||||
angular.module('piwikApp').directive('piwikPluginSettings', piwikPluginSettings);
|
||||
|
||||
piwikPluginSettings.$inject = ['piwik'];
|
||||
|
||||
function piwikPluginSettings(piwik){
|
||||
var defaults = {
|
||||
mode: ''
|
||||
};
|
||||
|
||||
return {
|
||||
restrict: 'A',
|
||||
scope: {
|
||||
mode: '@'
|
||||
},
|
||||
templateUrl: 'plugins/CorePluginsAdmin/angularjs/plugin-settings/plugin-settings.directive.html?cb=' + piwik.cacheBuster,
|
||||
controller: 'PluginSettingsController',
|
||||
controllerAs: 'pluginSettings',
|
||||
compile: function (element, attrs) {
|
||||
|
||||
for (var index in defaults) {
|
||||
if (defaults.hasOwnProperty(index) && attrs[index] === undefined) {
|
||||
attrs[index] = defaults[index];
|
||||
}
|
||||
}
|
||||
|
||||
return function (scope, element, attrs) {
|
||||
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
})();
|
@ -0,0 +1,9 @@
|
||||
.pluginSettings {
|
||||
textarea {
|
||||
width: 376px;
|
||||
height: 250px;
|
||||
}
|
||||
}
|
||||
.pluginsSettingsSubmit {
|
||||
margin-top: 30px;
|
||||
}
|
@ -0,0 +1,113 @@
|
||||
/*!
|
||||
* Piwik - free/libre analytics platform
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
*/
|
||||
|
||||
/**
|
||||
* Usage:
|
||||
* <div piwik-plugin-filter>
|
||||
*/
|
||||
(function () {
|
||||
angular.module('piwikApp').directive('piwikPluginFilter', piwikPluginFilter);
|
||||
|
||||
piwikPluginFilter.$inject = ['piwik'];
|
||||
|
||||
function piwikPluginFilter(piwik){
|
||||
|
||||
return {
|
||||
restrict: 'A',
|
||||
compile: function (element, attrs) {
|
||||
|
||||
return function (scope, element, attrs) {
|
||||
|
||||
updateAllNumbersOfMatchingPluginsInFilter();
|
||||
|
||||
function filterPlugins()
|
||||
{
|
||||
var filterOrigin = getCurrentFilterOrigin();
|
||||
var filterStatus = getCurrentFilterStatus();
|
||||
|
||||
var $nodesToEnable = getMatchingNodes(filterOrigin, filterStatus);
|
||||
|
||||
$('#plugins tr[data-filter-origin][data-filter-status]').css('display', 'none');
|
||||
$nodesToEnable.css('display', 'table-row');
|
||||
|
||||
updateAllNumbersOfMatchingPluginsInFilter();
|
||||
}
|
||||
|
||||
function updateAllNumbersOfMatchingPluginsInFilter()
|
||||
{
|
||||
var filterOrigin = getCurrentFilterOrigin();
|
||||
var filterStatus = getCurrentFilterStatus();
|
||||
|
||||
updateNumberOfMatchingPluginsInFilter('[data-filter-status="all"]', filterOrigin, 'all');
|
||||
updateNumberOfMatchingPluginsInFilter('[data-filter-status="active"]', filterOrigin, 'active');
|
||||
updateNumberOfMatchingPluginsInFilter('[data-filter-status="inactive"]', filterOrigin, 'inactive');
|
||||
|
||||
updateNumberOfMatchingPluginsInFilter('[data-filter-origin="all"]', 'all', filterStatus);
|
||||
updateNumberOfMatchingPluginsInFilter('[data-filter-origin="core"]', 'core', filterStatus);
|
||||
updateNumberOfMatchingPluginsInFilter('[data-filter-origin="official"]', 'official', filterStatus);
|
||||
updateNumberOfMatchingPluginsInFilter('[data-filter-origin="thirdparty"]', 'thirdparty', filterStatus);
|
||||
}
|
||||
|
||||
function updateNumberOfMatchingPluginsInFilter(selectorFilterToUpdate, filterOrigin, filterStatus)
|
||||
{
|
||||
var numMatchingNodes = getMatchingNodes(filterOrigin, filterStatus).length;
|
||||
var updatedCounterText = ' (' + numMatchingNodes + ')';
|
||||
|
||||
element.find(selectorFilterToUpdate + ' .counter').text(updatedCounterText);
|
||||
}
|
||||
|
||||
function getCurrentFilterOrigin()
|
||||
{
|
||||
return element.find('.origin a.active').data('filter-origin');
|
||||
}
|
||||
|
||||
function getCurrentFilterStatus()
|
||||
{
|
||||
return element.find('.status a.active').data('filter-status');
|
||||
}
|
||||
|
||||
function getMatchingNodes(filterOrigin, filterStatus)
|
||||
{
|
||||
var query = '#plugins tr';
|
||||
|
||||
if ('all' == filterOrigin) {
|
||||
query += '[data-filter-origin]';
|
||||
} else {
|
||||
query += '[data-filter-origin=' + filterOrigin + ']';
|
||||
}
|
||||
|
||||
if ('all' == filterStatus) {
|
||||
query += '[data-filter-status]';
|
||||
} else {
|
||||
query += '[data-filter-status=' + filterStatus + ']';
|
||||
}
|
||||
|
||||
return $(query);
|
||||
}
|
||||
|
||||
element.find('.status').on('click', 'a', function (event) {
|
||||
event.preventDefault();
|
||||
|
||||
$(this).siblings().removeClass('active');
|
||||
$(this).addClass('active');
|
||||
|
||||
filterPlugins();
|
||||
});
|
||||
|
||||
element.find('.origin').on('click', 'a', function (event) {
|
||||
event.preventDefault();
|
||||
|
||||
$(this).siblings().removeClass('active');
|
||||
$(this).addClass('active');
|
||||
|
||||
filterPlugins();
|
||||
});
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
})();
|
@ -0,0 +1,65 @@
|
||||
/*!
|
||||
* Piwik - free/libre analytics platform
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
*/
|
||||
|
||||
/**
|
||||
* Usage:
|
||||
* <div piwik-plugin-management>
|
||||
*/
|
||||
(function () {
|
||||
|
||||
angular.module('piwikApp').directive('piwikPluginManagement', piwikPluginManagement);
|
||||
|
||||
piwikPluginManagement.$inject = ['piwik'];
|
||||
|
||||
function piwikPluginManagement(piwik){
|
||||
|
||||
return {
|
||||
restrict: 'A',
|
||||
compile: function (element, attrs) {
|
||||
|
||||
return function (scope, element, attrs) {
|
||||
|
||||
var uninstallConfirmMessage = '';
|
||||
|
||||
element.find('.uninstall').click(function (event) {
|
||||
event.preventDefault();
|
||||
|
||||
var link = $(this).attr('href');
|
||||
var pluginName = $(this).attr('data-plugin-name');
|
||||
|
||||
if (!link || !pluginName) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!uninstallConfirmMessage) {
|
||||
uninstallConfirmMessage = $('#uninstallPluginConfirm').text();
|
||||
}
|
||||
|
||||
var messageToDisplay = uninstallConfirmMessage.replace('%s', pluginName);
|
||||
|
||||
$('#uninstallPluginConfirm').text(messageToDisplay);
|
||||
|
||||
piwikHelper.modalConfirm('#confirmUninstallPlugin', {
|
||||
yes: function () {
|
||||
window.location = link;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
element.find('.plugin-donation-link').click(function (event) {
|
||||
event.preventDefault();
|
||||
|
||||
var overlayId = $(this).data('overlay-id');
|
||||
|
||||
piwikHelper.modalConfirm('#'+overlayId, {});
|
||||
});
|
||||
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
})();
|
@ -0,0 +1,46 @@
|
||||
/*!
|
||||
* Piwik - free/libre analytics platform
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
*/
|
||||
|
||||
/**
|
||||
* Usage:
|
||||
* <div piwik-plugin-upload>
|
||||
*/
|
||||
(function () {
|
||||
|
||||
angular.module('piwikApp').directive('piwikPluginUpload', piwikPluginUpload);
|
||||
|
||||
piwikPluginUpload.$inject = ['piwik'];
|
||||
|
||||
function piwikPluginUpload(piwik){
|
||||
|
||||
return {
|
||||
restrict: 'A',
|
||||
compile: function (element, attrs) {
|
||||
|
||||
return function (scope, element, attrs) {
|
||||
|
||||
$('.uploadPlugin').click(function (event) {
|
||||
event.preventDefault();
|
||||
|
||||
piwikHelper.modalConfirm('#installPluginByUpload', {});
|
||||
});
|
||||
|
||||
$('#uploadPluginForm').submit(function (event) {
|
||||
|
||||
var $zipFile = $('[name=pluginZip]');
|
||||
var fileName = $zipFile.val();
|
||||
|
||||
if (!fileName || '.zip' != fileName.slice(-4)) {
|
||||
event.preventDefault();
|
||||
alert(_pk_translate('CorePluginsAdmin_NoZipFileSelected'));
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
})();
|
@ -0,0 +1,8 @@
|
||||
<div style="display:inline-block;">
|
||||
<input type="button"
|
||||
ng-click="onconfirm()"
|
||||
value="{{ value ? value : ('General_Save'|translate) }}"
|
||||
ng-disabled="saving || disabled"
|
||||
class="btn"/>
|
||||
<div piwik-activity-indicator loading="saving"></div>
|
||||
</div>
|
@ -0,0 +1,31 @@
|
||||
/*!
|
||||
* Piwik - free/libre analytics platform
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
*/
|
||||
|
||||
/**
|
||||
* Usage:
|
||||
* <div piwik-save-button>
|
||||
*/
|
||||
(function () {
|
||||
angular.module('piwikApp').directive('piwikSaveButton', piwikSaveButton);
|
||||
|
||||
piwikSaveButton.$inject = ['piwik'];
|
||||
|
||||
function piwikSaveButton(piwik){
|
||||
|
||||
return {
|
||||
restrict: 'A',
|
||||
replace: true,
|
||||
scope: {
|
||||
saving: '=?',
|
||||
value: '@?',
|
||||
disabled: '=?',
|
||||
onconfirm: '&?'
|
||||
},
|
||||
templateUrl: 'plugins/CorePluginsAdmin/angularjs/save-button/save-button.directive.html?cb=' + piwik.cacheBuster
|
||||
};
|
||||
}
|
||||
})();
|
Reference in New Issue
Block a user