mirror of
https://github.com/grafana/grafana.git
synced 2024-11-27 19:30:36 -06:00
36e4a871f2
* UI/ClipboardButton: Remove ClipboardJS in favor of native Clipboard API Closes #42365 * Add backwards compatibility
189 lines
5.4 KiB
TypeScript
189 lines
5.4 KiB
TypeScript
import angular from 'angular';
|
|
import coreModule from './core_module';
|
|
|
|
/** @ngInject */
|
|
function tip($compile: any) {
|
|
return {
|
|
restrict: 'E',
|
|
link: (scope: any, elem: any, attrs: any) => {
|
|
let _t =
|
|
'<i class="grafana-tip fa fa-' +
|
|
(attrs.icon || 'question-circle') +
|
|
'" bs-tooltip="\'' +
|
|
// here we double-html-encode any special characters in the source string
|
|
// this is needed so that the final html contains the encoded entities as they
|
|
// will be decoded when _t is parsed by angular
|
|
elem.text().replace(/[\'\"\\{}<>&]/g, (m: string) => '&#' + m.charCodeAt(0) + ';') +
|
|
'\'"></i>';
|
|
elem.replaceWith($compile(angular.element(_t))(scope));
|
|
},
|
|
};
|
|
}
|
|
|
|
/** @ngInject */
|
|
function compile($compile: any) {
|
|
return {
|
|
restrict: 'A',
|
|
link: (scope: any, element: any, attrs: any) => {
|
|
scope.$watch(
|
|
(scope: any) => {
|
|
return scope.$eval(attrs.compile);
|
|
},
|
|
(value: any) => {
|
|
element.html(value);
|
|
$compile(element.contents())(scope);
|
|
}
|
|
);
|
|
},
|
|
};
|
|
}
|
|
|
|
function watchChange() {
|
|
return {
|
|
scope: { onchange: '&watchChange' },
|
|
link: (scope: any, element: any) => {
|
|
element.on('input', () => {
|
|
scope.$apply(() => {
|
|
scope.onchange({ inputValue: element.val() });
|
|
});
|
|
});
|
|
},
|
|
};
|
|
}
|
|
|
|
/** @ngInject */
|
|
function editorOptBool($compile: any) {
|
|
return {
|
|
restrict: 'E',
|
|
link: (scope: any, elem: any, attrs: any) => {
|
|
const ngchange = attrs.change ? ' ng-change="' + attrs.change + '"' : '';
|
|
const tip = attrs.tip ? ' <tip>' + attrs.tip + '</tip>' : '';
|
|
const showIf = attrs.showIf ? ' ng-show="' + attrs.showIf + '" ' : '';
|
|
|
|
const template =
|
|
'<div class="editor-option gf-form-checkbox text-center"' +
|
|
showIf +
|
|
'>' +
|
|
' <label for="' +
|
|
attrs.model +
|
|
'" class="small">' +
|
|
attrs.text +
|
|
tip +
|
|
'</label>' +
|
|
'<input class="cr1" id="' +
|
|
attrs.model +
|
|
'" type="checkbox" ' +
|
|
' ng-model="' +
|
|
attrs.model +
|
|
'"' +
|
|
ngchange +
|
|
' ng-checked="' +
|
|
attrs.model +
|
|
'"></input>' +
|
|
' <label for="' +
|
|
attrs.model +
|
|
'" class="cr1"></label>';
|
|
elem.replaceWith($compile(angular.element(template))(scope));
|
|
},
|
|
};
|
|
}
|
|
|
|
/** @ngInject */
|
|
function editorCheckbox($compile: any, $interpolate: any) {
|
|
return {
|
|
restrict: 'E',
|
|
link: (scope: any, elem: any, attrs: any) => {
|
|
const text = $interpolate(attrs.text)(scope);
|
|
const model = $interpolate(attrs.model)(scope);
|
|
const ngchange = attrs.change ? ' ng-change="' + attrs.change + '"' : '';
|
|
const tip = attrs.tip ? ' <tip>' + attrs.tip + '</tip>' : '';
|
|
const label = '<label for="' + scope.$id + model + '" class="checkbox-label">' + text + tip + '</label>';
|
|
|
|
let template =
|
|
'<input class="cr1" id="' +
|
|
scope.$id +
|
|
model +
|
|
'" type="checkbox" ' +
|
|
' ng-model="' +
|
|
model +
|
|
'"' +
|
|
ngchange +
|
|
' ng-checked="' +
|
|
model +
|
|
'"></input>' +
|
|
' <label for="' +
|
|
scope.$id +
|
|
model +
|
|
'" class="cr1"></label>';
|
|
|
|
template = template + label;
|
|
elem.addClass('gf-form-checkbox');
|
|
elem.html($compile(angular.element(template))(scope));
|
|
},
|
|
};
|
|
}
|
|
|
|
/** @ngInject */
|
|
function gfDropdown($parse: any, $compile: any, $timeout: any) {
|
|
function buildTemplate(items: any, placement?: any) {
|
|
const upclass = placement === 'top' ? 'dropup' : '';
|
|
const ul = ['<ul class="dropdown-menu ' + upclass + '" role="menu" aria-labelledby="drop1">', '</ul>'];
|
|
|
|
for (let index = 0; index < items.length; index++) {
|
|
const item = items[index];
|
|
|
|
if (item.divider) {
|
|
ul.splice(index + 1, 0, '<li class="divider"></li>');
|
|
continue;
|
|
}
|
|
|
|
let li =
|
|
'<li' +
|
|
(item.submenu && item.submenu.length ? ' class="dropdown-submenu"' : '') +
|
|
'>' +
|
|
'<a tabindex="-1" ng-href="' +
|
|
(item.href || '') +
|
|
'"' +
|
|
(item.click ? ' ng-click="' + item.click + '"' : '') +
|
|
(item.target ? ' target="' + item.target + '"' : '') +
|
|
(item.method ? ' data-method="' + item.method + '"' : '') +
|
|
'>' +
|
|
(item.text || '') +
|
|
'</a>';
|
|
|
|
if (item.submenu && item.submenu.length) {
|
|
li += buildTemplate(item.submenu).join('\n');
|
|
}
|
|
|
|
li += '</li>';
|
|
ul.splice(index + 1, 0, li);
|
|
}
|
|
|
|
return ul;
|
|
}
|
|
|
|
return {
|
|
restrict: 'EA',
|
|
scope: true,
|
|
link: function postLink(scope: any, iElement: any, iAttrs: any) {
|
|
const getter = $parse(iAttrs.gfDropdown),
|
|
items = getter(scope);
|
|
$timeout(() => {
|
|
const placement = iElement.data('placement');
|
|
const dropdown = angular.element(buildTemplate(items, placement).join(''));
|
|
dropdown.insertAfter(iElement);
|
|
$compile(iElement.next('ul.dropdown-menu'))(scope);
|
|
});
|
|
|
|
iElement.addClass('dropdown-toggle').attr('data-toggle', 'dropdown');
|
|
},
|
|
};
|
|
}
|
|
|
|
coreModule.directive('tip', tip);
|
|
coreModule.directive('compile', compile);
|
|
coreModule.directive('watchChange', watchChange);
|
|
coreModule.directive('editorOptBool', editorOptBool);
|
|
coreModule.directive('editorCheckbox', editorCheckbox);
|
|
coreModule.directive('gfDropdown', gfDropdown);
|