Commit 5545cdbf by Torkel Ödegaard

refactor: improving structure, moving things into a core module

parent 9dec5083
...@@ -73,7 +73,6 @@ function (angular, $, _, appLevelRequire) { ...@@ -73,7 +73,6 @@ function (angular, $, _, appLevelRequire) {
'services/all', 'services/all',
'features/all', 'features/all',
'controllers/all', 'controllers/all',
'directives/all',
'components/partials', 'components/partials',
'routes/all', 'routes/all',
]; ];
......
///<amd-dependency path="./directives/annotation_tooltip" />
///<amd-dependency path="./directives/body_class" />
///<amd-dependency path="./directives/config_modal" />
///<amd-dependency path="./directives/confirm_click" />
///<amd-dependency path="./directives/dash_edit_link" />
///<amd-dependency path="./directives/dash_upload" />
///<amd-dependency path="./directives/dropdown_typeahead" />
///<amd-dependency path="./directives/grafana_version_check" />
///<amd-dependency path="./directives/metric_segment" />
///<amd-dependency path="./directives/misc" />
///<amd-dependency path="./directives/ng_model_on_blur" />
///<amd-dependency path="./directives/password_strenght" />
///<amd-dependency path="./directives/spectrum_picker" />
///<amd-dependency path="./directives/tags" />
///<amd-dependency path="./directives/topnav" />
///<amd-dependency path="./directives/value_select_dropdown" />
export * from './directives/array_join' export * from './directives/array_join'
export * from './directives/giveFocus' export * from './directives/give_focus'
export * from './routes/module_loader' export * from './routes/module_loader'
export * from './filters/filters' export * from './filters/filters'
......
...@@ -2,4 +2,4 @@ ...@@ -2,4 +2,4 @@
import angular = require('angular'); import angular = require('angular');
export default angular.module('grafana.core', []); export = angular.module('grafana.core', []);
define([ define([
'angular',
'jquery', 'jquery',
'lodash' 'lodash',
'../core_module',
], ],
function (angular, $, _) { function ($, _, coreModule) {
'use strict'; 'use strict';
angular coreModule.directive('annotationTooltip', function($sanitize, dashboardSrv, $compile) {
.module('grafana.directives')
.directive('annotationTooltip', function($sanitize, dashboardSrv, $compile) {
function sanitizeString(str) { function sanitizeString(str) {
try { try {
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
import angular = require('angular'); import angular = require('angular');
import _ = require('lodash'); import _ = require('lodash');
import coreModule from '../core_module'; import coreModule = require('../core_module');
export function arrayJoin() { export function arrayJoin() {
'use strict'; 'use strict';
......
define([ define([
'angular',
'lodash', 'lodash',
'jquery' 'jquery',
'../core_module',
], ],
function (angular, _, $) { function (_, $, coreModule) {
'use strict'; 'use strict';
angular coreModule.directive('bodyClass', function() {
.module('grafana.directives') return {
.directive('bodyClass', function() { link: function($scope, elem) {
return {
link: function($scope, elem) { var lastHideControlsVal;
var lastHideControlsVal; // tooltip removal fix
$scope.$on("$routeChangeSuccess", function() {
// tooltip removal fix $("#tooltip, .tooltip").remove();
$scope.$on("$routeChangeSuccess", function() { });
$("#tooltip, .tooltip").remove();
}); $scope.$watch('submenuEnabled', function() {
if (!$scope.dashboard) {
$scope.$watch('submenuEnabled', function() { return;
if (!$scope.dashboard) { }
return;
} elem.toggleClass('submenu-controls-visible', $scope.submenuEnabled);
});
elem.toggleClass('submenu-controls-visible', $scope.submenuEnabled);
}); $scope.$watch('dashboard.hideControls', function() {
if (!$scope.dashboard) {
$scope.$watch('dashboard.hideControls', function() { return;
if (!$scope.dashboard) { }
return;
} var hideControls = $scope.dashboard.hideControls || $scope.playlist_active;
var hideControls = $scope.dashboard.hideControls || $scope.playlist_active; if (lastHideControlsVal !== hideControls) {
elem.toggleClass('hide-controls', hideControls);
if (lastHideControlsVal !== hideControls) { lastHideControlsVal = hideControls;
elem.toggleClass('hide-controls', hideControls); }
lastHideControlsVal = hideControls; });
}
}); $scope.$watch('playlistSrv', function(newValue) {
elem.toggleClass('playlist-active', _.isObject(newValue));
$scope.$watch('playlistSrv', function(newValue) { });
elem.toggleClass('playlist-active', _.isObject(newValue)); }
}); };
} });
};
});
}); });
define([ define([
'angular',
'lodash', 'lodash',
'jquery' 'jquery',
'../core_module',
], ],
function (angular, _, $) { function (_, $, coreModule) {
'use strict'; 'use strict';
angular coreModule.directive('configModal', function($modal, $q, $timeout) {
.module('grafana.directives') return {
.directive('configModal', function($modal, $q, $timeout) { restrict: 'A',
return { link: function(scope, elem, attrs) {
restrict: 'A', var partial = attrs.configModal;
link: function(scope, elem, attrs) { var id = '#' + partial.replace('.html', '').replace(/[\/|\.|:]/g, '-') + '-' + scope.$id;
var partial = attrs.configModal;
var id = '#' + partial.replace('.html', '').replace(/[\/|\.|:]/g, '-') + '-' + scope.$id;
elem.bind('click',function() { elem.bind('click',function() {
if ($(id).length) { if ($(id).length) {
elem.attr('data-target', id).attr('data-toggle', 'modal'); elem.attr('data-target', id).attr('data-toggle', 'modal');
scope.$apply(function() { scope.$broadcast('modal-opened'); }); scope.$apply(function() { scope.$broadcast('modal-opened'); });
return; return;
} }
var panelModal = $modal({ var panelModal = $modal({
template: partial, template: partial,
persist: false, persist: false,
show: false, show: false,
scope: scope.$new(), scope: scope.$new(),
keyboard: false keyboard: false
}); });
$q.when(panelModal).then(function(modalEl) {
elem.attr('data-target', id).attr('data-toggle', 'modal');
$timeout(function () { $q.when(panelModal).then(function(modalEl) {
if (!modalEl.data('modal').isShown) { elem.attr('data-target', id).attr('data-toggle', 'modal');
modalEl.modal('show');
}
}, 50);
});
scope.$apply(); $timeout(function () {
if (!modalEl.data('modal').isShown) {
modalEl.modal('show');
}
}, 50);
}); });
}
}; scope.$apply();
}); });
}
};
});
}); });
define([ define([
'angular', '../core_module',
'kbn'
], ],
function (angular) { function (coreModule) {
'use strict'; 'use strict';
var module = angular.module('grafana.directives'); coreModule.directive('confirmClick', function() {
module.directive('confirmClick', function() {
return { return {
restrict: 'A', restrict: 'A',
link: function(scope, elem, attrs) { link: function(scope, elem, attrs) {
...@@ -23,4 +20,4 @@ function (angular) { ...@@ -23,4 +20,4 @@ function (angular) {
}, },
}; };
}); });
}); });
\ No newline at end of file
define([ define([
'angular', 'jquery',
'jquery' '../core_module',
], ],
function (angular, $) { function ($, coreModule) {
'use strict'; 'use strict';
var editViewMap = { var editViewMap = {
...@@ -11,97 +11,93 @@ function (angular, $) { ...@@ -11,97 +11,93 @@ function (angular, $) {
'templating': { src: 'app/features/templating/partials/editor.html', title: "Templating" } 'templating': { src: 'app/features/templating/partials/editor.html', title: "Templating" }
}; };
angular coreModule.directive('dashEditorLink', function($timeout) {
.module('grafana.directives') return {
.directive('dashEditorLink', function($timeout) { restrict: 'A',
return { link: function(scope, elem, attrs) {
restrict: 'A', var partial = attrs.dashEditorLink;
link: function(scope, elem, attrs) {
var partial = attrs.dashEditorLink; elem.bind('click',function() {
$timeout(function() {
elem.bind('click',function() { var editorScope = attrs.editorScope === 'isolated' ? null : scope;
$timeout(function() { scope.appEvent('show-dash-editor', { src: partial, scope: editorScope });
var editorScope = attrs.editorScope === 'isolated' ? null : scope;
scope.appEvent('show-dash-editor', { src: partial, scope: editorScope });
});
}); });
});
}
};
});
coreModule.directive('dashEditorView', function($compile, $location) {
return {
restrict: 'A',
link: function(scope, elem) {
var editorScope;
var lastEditor;
function hideEditorPane() {
if (editorScope) { editorScope.dismiss(); }
} }
};
});
angular
.module('grafana.directives')
.directive('dashEditorView', function($compile, $location) {
return {
restrict: 'A',
link: function(scope, elem) {
var editorScope;
var lastEditor;
function hideEditorPane() {
if (editorScope) { editorScope.dismiss(); }
}
function showEditorPane(evt, payload, editview) {
if (editview) {
scope.contextSrv.editview = editViewMap[editview];
payload.src = scope.contextSrv.editview.src;
}
if (lastEditor === payload.src) { function showEditorPane(evt, payload, editview) {
hideEditorPane(); if (editview) {
return; scope.contextSrv.editview = editViewMap[editview];
} payload.src = scope.contextSrv.editview.src;
}
if (lastEditor === payload.src) {
hideEditorPane(); hideEditorPane();
return;
}
scope.exitFullscreen(); hideEditorPane();
lastEditor = payload.src;
editorScope = payload.scope ? payload.scope.$new() : scope.$new();
editorScope.dismiss = function() { scope.exitFullscreen();
editorScope.$destroy();
elem.empty();
lastEditor = null;
editorScope = null;
if (editview) { lastEditor = payload.src;
var urlParams = $location.search(); editorScope = payload.scope ? payload.scope.$new() : scope.$new();
if (editview === urlParams.editview) {
delete urlParams.editview;
$location.search(urlParams);
}
}
};
var src = "'" + payload.src + "'"; editorScope.dismiss = function() {
var view = $('<div class="gf-box" ng-include="' + src + '"></div>'); editorScope.$destroy();
elem.empty();
lastEditor = null;
editorScope = null;
if (payload.cssClass) { if (editview) {
view.addClass(payload.cssClass); var urlParams = $location.search();
if (editview === urlParams.editview) {
delete urlParams.editview;
$location.search(urlParams);
}
} }
};
elem.append(view); var src = "'" + payload.src + "'";
$compile(elem.contents())(editorScope); var view = $('<div class="gf-box" ng-include="' + src + '"></div>');
}
scope.$watch("dashboardViewState.state.editview", function(newValue, oldValue) { if (payload.cssClass) {
if (newValue) { view.addClass(payload.cssClass);
showEditorPane(null, {}, newValue); }
} else if (oldValue) {
scope.contextSrv.editview = null;
if (lastEditor === editViewMap[oldValue]) {
hideEditorPane();
}
}
});
scope.contextSrv.editview = null; elem.append(view);
scope.$on("$destroy", hideEditorPane); $compile(elem.contents())(editorScope);
scope.onAppEvent('hide-dash-editor', hideEditorPane);
scope.onAppEvent('show-dash-editor', showEditorPane);
} }
};
}); scope.$watch("dashboardViewState.state.editview", function(newValue, oldValue) {
if (newValue) {
showEditorPane(null, {}, newValue);
} else if (oldValue) {
scope.contextSrv.editview = null;
if (lastEditor === editViewMap[oldValue]) {
hideEditorPane();
}
}
});
scope.contextSrv.editview = null;
scope.$on("$destroy", hideEditorPane);
scope.onAppEvent('hide-dash-editor', hideEditorPane);
scope.onAppEvent('show-dash-editor', showEditorPane);
}
};
});
}); });
define([ define([
'angular', 'kbn',
'kbn' '../core_module',
], ],
function (angular, kbn) { function (kbn, coreModule) {
'use strict'; 'use strict';
var module = angular.module('grafana.directives'); coreModule.directive('dashUpload', function(timer, alertSrv, $location) {
module.directive('dashUpload', function(timer, alertSrv, $location) {
return { return {
restrict: 'A', restrict: 'A',
link: function(scope) { link: function(scope) {
......
define([ define([
'angular',
'lodash', 'lodash',
'jquery', 'jquery',
'../core_module',
], ],
function (angular, _, $) { function (_, $, coreModule) {
'use strict'; 'use strict';
angular coreModule.directive('dropdownTypeahead', function($compile) {
.module('grafana.directives')
.directive('dropdownTypeahead', function($compile) {
var inputTemplate = '<input type="text"'+ var inputTemplate = '<input type="text"'+
' class="tight-form-input input-medium tight-form-input"' + ' class="tight-form-input input-medium tight-form-input"' +
' spellcheck="false" style="display:none"></input>'; ' spellcheck="false" style="display:none"></input>';
var buttonTemplate = '<a class="tight-form-item tight-form-func dropdown-toggle"' + var buttonTemplate = '<a class="tight-form-item tight-form-func dropdown-toggle"' +
' tabindex="1" gf-dropdown="menuItems" data-toggle="dropdown"' + ' tabindex="1" gf-dropdown="menuItems" data-toggle="dropdown"' +
' data-placement="top"><i class="fa fa-plus"></i></a>'; ' data-placement="top"><i class="fa fa-plus"></i></a>';
return { return {
scope: { scope: {
menuItems: "=dropdownTypeahead", menuItems: "=dropdownTypeahead",
dropdownTypeaheadOnSelect: "&dropdownTypeaheadOnSelect", dropdownTypeaheadOnSelect: "&dropdownTypeaheadOnSelect",
model: '=ngModel' model: '=ngModel'
}, },
link: function($scope, elem, attrs) { link: function($scope, elem, attrs) {
var $input = $(inputTemplate); var $input = $(inputTemplate);
var $button = $(buttonTemplate); var $button = $(buttonTemplate);
$input.appendTo(elem); $input.appendTo(elem);
$button.appendTo(elem); $button.appendTo(elem);
if (attrs.linkText) { if (attrs.linkText) {
$button.html(attrs.linkText); $button.html(attrs.linkText);
} }
if (attrs.ngModel) { if (attrs.ngModel) {
$scope.$watch('model', function(newValue) { $scope.$watch('model', function(newValue) {
_.each($scope.menuItems, function(item) { _.each($scope.menuItems, function(item) {
_.each(item.submenu, function(subItem) { _.each(item.submenu, function(subItem) {
if (subItem.value === newValue) { if (subItem.value === newValue) {
$button.html(subItem.text); $button.html(subItem.text);
} }
});
}); });
}); });
} });
}
var typeaheadValues = _.reduce($scope.menuItems, function(memo, value, index) { var typeaheadValues = _.reduce($scope.menuItems, function(memo, value, index) {
_.each(value.submenu, function(item, subIndex) { _.each(value.submenu, function(item, subIndex) {
item.click = 'menuItemSelected(' + index + ',' + subIndex + ')'; item.click = 'menuItemSelected(' + index + ',' + subIndex + ')';
memo.push(value.text + ' ' + item.text); memo.push(value.text + ' ' + item.text);
}); });
return memo; return memo;
}, []); }, []);
$scope.menuItemSelected = function(index, subIndex) { $scope.menuItemSelected = function(index, subIndex) {
var item = $scope.menuItems[index]; var item = $scope.menuItems[index];
$scope.dropdownTypeaheadOnSelect({$item: item, $subItem: item.submenu[subIndex]}); $scope.dropdownTypeaheadOnSelect({$item: item, $subItem: item.submenu[subIndex]});
}; };
$input.attr('data-provide', 'typeahead'); $input.attr('data-provide', 'typeahead');
$input.typeahead({ $input.typeahead({
source: typeaheadValues, source: typeaheadValues,
minLength: 1, minLength: 1,
items: 10, items: 10,
updater: function (value) { updater: function (value) {
var result = {}; var result = {};
_.each($scope.menuItems, function(menuItem) { _.each($scope.menuItems, function(menuItem) {
_.each(menuItem.submenu, function(submenuItem) { _.each(menuItem.submenu, function(submenuItem) {
if (value === (menuItem.text + ' ' + submenuItem.text)) { if (value === (menuItem.text + ' ' + submenuItem.text)) {
result.$item = menuItem; result.$item = menuItem;
result.$subItem = submenuItem; result.$subItem = submenuItem;
} }
});
}); });
});
if (result.$item) { if (result.$item) {
$scope.$apply(function() { $scope.$apply(function() {
$scope.dropdownTypeaheadOnSelect(result); $scope.dropdownTypeaheadOnSelect(result);
}); });
}
$input.trigger('blur');
return '';
} }
});
$button.click(function() { $input.trigger('blur');
$button.hide(); return '';
$input.show(); }
$input.focus(); });
});
$input.keyup(function() { $button.click(function() {
elem.toggleClass('open', $input.val() === ''); $button.hide();
}); $input.show();
$input.focus();
});
$input.blur(function() { $input.keyup(function() {
$input.hide(); elem.toggleClass('open', $input.val() === '');
$input.val(''); });
$button.show();
$button.focus();
// clicking the function dropdown menu wont
// work if you remove class at once
setTimeout(function() {
elem.removeClass('open');
}, 200);
});
$compile(elem.contents())($scope); $input.blur(function() {
} $input.hide();
}; $input.val('');
}); $button.show();
$button.focus();
// clicking the function dropdown menu wont
// work if you remove class at once
setTimeout(function() {
elem.removeClass('open');
}, 200);
});
$compile(elem.contents())($scope);
}
};
});
}); });
///<reference path="../../headers/common.d.ts" /> ///<reference path="../../headers/common.d.ts" />
import angular = require('angular'); import angular = require('angular');
import coreModule from '../core_module'; import coreModule = require('../core_module');
coreModule.directive('giveFocus', function() { coreModule.directive('giveFocus', function() {
return function(scope, element, attrs) { return function(scope, element, attrs) {
......
define([ define([
'angular' '../core_module',
], ],
function (angular) { function (coreModule) {
'use strict'; 'use strict';
angular coreModule.directive('grafanaVersionCheck', function($http, contextSrv) {
.module('grafana.directives') return {
.directive('grafanaVersionCheck', function($http, contextSrv) { restrict: 'A',
return { link: function(scope, elem) {
restrict: 'A', if (contextSrv.version === 'master') {
link: function(scope, elem) { return;
if (contextSrv.version === 'master') { }
$http({ method: 'GET', url: 'https://grafanarel.s3.amazonaws.com/latest.json' })
.then(function(response) {
if (!response.data || !response.data.version) {
return; return;
} }
$http({ method: 'GET', url: 'https://grafanarel.s3.amazonaws.com/latest.json' }) if (contextSrv.version !== response.data.version) {
.then(function(response) { elem.append('<i class="icon-info-sign"></i> ' +
if (!response.data || !response.data.version) { '<a href="http://grafana.org/download" target="_blank"> ' +
return; 'New version available: ' + response.data.version +
} '</a>');
}
if (contextSrv.version !== response.data.version) { });
elem.append('<i class="icon-info-sign"></i> ' + }
'<a href="http://grafana.org/download" target="_blank"> ' + };
'New version available: ' + response.data.version + });
'</a>');
}
});
}
};
});
}); });
define([ define([
'angular', 'angular',
'kbn' 'kbn',
'../core_module',
], ],
function (angular, kbn) { function (angular, kbn, coreModule) {
'use strict'; 'use strict';
angular coreModule.directive('tip', function($compile) {
.module('grafana.directives') return {
.directive('tip', function($compile) { restrict: 'E',
return { link: function(scope, elem, attrs) {
restrict: 'E', var _t = '<i class="grafana-tip fa fa-'+(attrs.icon||'question-circle')+'" bs-tooltip="\''+
link: function(scope, elem, attrs) { kbn.addslashes(elem.text())+'\'"></i>';
var _t = '<i class="grafana-tip fa fa-'+(attrs.icon||'question-circle')+'" bs-tooltip="\''+ _t = _t.replace(/{/g, '\\{').replace(/}/g, '\\}');
kbn.addslashes(elem.text())+'\'"></i>'; elem.replaceWith($compile(angular.element(_t))(scope));
_t = _t.replace(/{/g, '\\{').replace(/}/g, '\\}'); }
elem.replaceWith($compile(angular.element(_t))(scope)); };
} });
};
}); coreModule.directive('watchChange', function() {
return {
angular scope: { onchange: '&watchChange' },
.module('grafana.directives') link: function(scope, element) {
.directive('watchChange', function() { element.on('input', function() {
return { scope.$apply(function () {
scope: { onchange: '&watchChange' }, scope.onchange({ inputValue: element.val() });
link: function(scope, element) {
element.on('input', function() {
scope.$apply(function () {
scope.onchange({ inputValue: element.val() });
});
}); });
});
}
};
});
coreModule.directive('editorOptBool', function($compile) {
return {
restrict: 'E',
link: function(scope, elem, attrs) {
var ngchange = attrs.change ? (' ng-change="' + attrs.change + '"') : '';
var tip = attrs.tip ? (' <tip>' + attrs.tip + '</tip>') : '';
var showIf = attrs.showIf ? (' ng-show="' + attrs.showIf + '" ') : '';
var template = '<div class="editor-option 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));
}
};
});
coreModule.directive('editorCheckbox', function($compile, $interpolate) {
return {
restrict: 'E',
link: function(scope, elem, attrs) {
var text = $interpolate(attrs.text)(scope);
var model = $interpolate(attrs.model)(scope);
var ngchange = attrs.change ? (' ng-change="' + attrs.change + '"') : '';
var tip = attrs.tip ? (' <tip>' + attrs.tip + '</tip>') : '';
var label = '<label for="' + scope.$id + model + '" class="checkbox-label">' +
text + tip + '</label>';
var 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 = label + template;
elem.replaceWith($compile(angular.element(template))(scope));
}
};
});
coreModule.directive('gfDropdown', function ($parse, $compile, $timeout) {
function buildTemplate(items, placement) {
var upclass = placement === 'top' ? 'dropup' : '';
var ul = [
'<ul class="dropdown-menu ' + upclass + '" role="menu" aria-labelledby="drop1">',
'</ul>'
];
angular.forEach(items, function (item, index) {
if (item.divider) {
return ul.splice(index + 1, 0, '<li class="divider"></li>');
} }
};
});
angular
.module('grafana.directives')
.directive('editorOptBool', function($compile) {
return {
restrict: 'E',
link: function(scope, elem, attrs) {
var ngchange = attrs.change ? (' ng-change="' + attrs.change + '"') : '';
var tip = attrs.tip ? (' <tip>' + attrs.tip + '</tip>') : '';
var showIf = attrs.showIf ? (' ng-show="' + attrs.showIf + '" ') : '';
var template = '<div class="editor-option 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));
}
};
});
angular
.module('grafana.directives')
.directive('editorCheckbox', function($compile, $interpolate) {
return {
restrict: 'E',
link: function(scope, elem, attrs) {
var text = $interpolate(attrs.text)(scope);
var model = $interpolate(attrs.model)(scope);
var ngchange = attrs.change ? (' ng-change="' + attrs.change + '"') : '';
var tip = attrs.tip ? (' <tip>' + attrs.tip + '</tip>') : '';
var label = '<label for="' + scope.$id + model + '" class="checkbox-label">' +
text + tip + '</label>';
var template = '<input class="cr1" id="' + scope.$id + model + '" type="checkbox" ' + var li = '<li' + (item.submenu && item.submenu.length ? ' class="dropdown-submenu"' : '') + '>' +
' ng-model="' + model + '"' + ngchange + '<a tabindex="-1" ng-href="' + (item.href || '') + '"' + (item.click ? ' ng-click="' + item.click + '"' : '') +
' ng-checked="' + model + '"></input>' + (item.target ? ' target="' + item.target + '"' : '') + (item.method ? ' data-method="' + item.method + '"' : '') +
' <label for="' + scope.$id + model + '" class="cr1"></label>'; (item.configModal ? ' dash-editor-link="' + item.configModal + '"' : "") +
'>' + (item.text || '') + '</a>';
template = label + template; if (item.submenu && item.submenu.length) {
elem.replaceWith($compile(angular.element(template))(scope)); li += buildTemplate(item.submenu).join('\n');
} }
};
});
angular li += '</li>';
.module('grafana.directives') ul.splice(index + 1, 0, li);
.directive('gfDropdown', function ($parse, $compile, $timeout) { });
return ul;
function buildTemplate(items, placement) { }
var upclass = placement === 'top' ? 'dropup' : '';
var ul = [ return {
'<ul class="dropdown-menu ' + upclass + '" role="menu" aria-labelledby="drop1">', restrict: 'EA',
'</ul>' scope: true,
]; link: function postLink(scope, iElement, iAttrs) {
var getter = $parse(iAttrs.gfDropdown), items = getter(scope);
angular.forEach(items, function (item, index) { $timeout(function () {
if (item.divider) { var placement = iElement.data('placement');
return ul.splice(index + 1, 0, '<li class="divider"></li>'); var dropdown = angular.element(buildTemplate(items, placement).join(''));
} dropdown.insertAfter(iElement);
$compile(iElement.next('ul.dropdown-menu'))(scope);
var 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.configModal ? ' dash-editor-link="' + item.configModal + '"' : "") +
'>' + (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, iElement, iAttrs) {
var getter = $parse(iAttrs.gfDropdown), items = getter(scope);
$timeout(function () {
var placement = iElement.data('placement');
var 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'); iElement.addClass('dropdown-toggle').attr('data-toggle', 'dropdown');
} }
}; };
}); });
}); });
define([ define([
'angular', 'kbn',
'kbn' '../core_module',
], ],
function (angular, kbn) { function (kbn, coreModule) {
'use strict'; 'use strict';
angular coreModule.directive('ngModelOnblur', function() {
.module('grafana.directives') return {
.directive('ngModelOnblur', function() { restrict: 'A',
return { priority: 1,
restrict: 'A', require: 'ngModel',
priority: 1, link: function(scope, elm, attr, ngModelCtrl) {
require: 'ngModel', if (attr.type === 'radio' || attr.type === 'checkbox') {
link: function(scope, elm, attr, ngModelCtrl) { return;
if (attr.type === 'radio' || attr.type === 'checkbox') {
return;
}
elm.off('input keydown change');
elm.bind('blur', function() {
scope.$apply(function() {
ngModelCtrl.$setViewValue(elm.val());
});
});
} }
};
}) elm.off('input keydown change');
.directive('emptyToNull', function () { elm.bind('blur', function() {
return { scope.$apply(function() {
restrict: 'A', ngModelCtrl.$setViewValue(elm.val());
require: 'ngModel',
link: function (scope, elm, attrs, ctrl) {
ctrl.$parsers.push(function (viewValue) {
if(viewValue === "") { return null; }
return viewValue;
}); });
} });
}; }
}) };
.directive('validTimeSpan', function() { });
return {
require: 'ngModel', coreModule.directive('emptyToNull', function () {
link: function(scope, elm, attrs, ctrl) { return {
ctrl.$validators.integer = function(modelValue, viewValue) { restrict: 'A',
if (ctrl.$isEmpty(modelValue)) { require: 'ngModel',
return true; link: function (scope, elm, attrs, ctrl) {
} ctrl.$parsers.push(function (viewValue) {
return kbn.isValidTimeSpan(viewValue); if(viewValue === "") { return null; }
}; return viewValue;
} });
}; }
}); };
});
coreModule.directive('validTimeSpan', function() {
return {
require: 'ngModel',
link: function(scope, elm, attrs, ctrl) {
ctrl.$validators.integer = function(modelValue, viewValue) {
if (ctrl.$isEmpty(modelValue)) {
return true;
}
return kbn.isValidTimeSpan(viewValue);
};
}
};
});
}); });
define([ define([
'angular', '../core_module',
], ],
function (angular) { function (coreModule) {
'use strict'; 'use strict';
angular coreModule.directive('passwordStrength', function() {
.module('grafana.directives') var template = '<div class="password-strength small" ng-if="!loginMode" ng-class="strengthClass">' +
.directive('passwordStrength', function() { '<em>{{strengthText}}</em>' +
var template = '<div class="password-strength small" ng-if="!loginMode" ng-class="strengthClass">' + '</div>';
'<em>{{strengthText}}</em>' + return {
'</div>'; template: template,
return { scope: {
template: template, password: "=",
scope: { },
password: "=", link: function($scope) {
},
link: function($scope) {
$scope.strengthClass = ''; $scope.strengthClass = '';
function passwordChanged(newValue) { function passwordChanged(newValue) {
if (!newValue) { if (!newValue) {
$scope.strengthText = ""; $scope.strengthText = "";
$scope.strengthClass = "hidden"; $scope.strengthClass = "hidden";
return; return;
} }
if (newValue.length < 4) { if (newValue.length < 4) {
$scope.strengthText = "strength: weak sauce."; $scope.strengthText = "strength: weak sauce.";
$scope.strengthClass = "password-strength-bad"; $scope.strengthClass = "password-strength-bad";
return; return;
} }
if (newValue.length <= 8) { if (newValue.length <= 8) {
$scope.strengthText = "strength: you can do better."; $scope.strengthText = "strength: you can do better.";
$scope.strengthClass = "password-strength-ok"; $scope.strengthClass = "password-strength-ok";
return; return;
}
$scope.strengthText = "strength: strong like a bull.";
$scope.strengthClass = "password-strength-good";
} }
$scope.$watch("password", passwordChanged); $scope.strengthText = "strength: strong like a bull.";
$scope.strengthClass = "password-strength-good";
} }
};
}); $scope.$watch("password", passwordChanged);
}
};
});
}); });
define([ define([
'angular', 'angular',
'spectrum' '../core_module',
'spectrum',
], ],
function (angular) { function (angular, coreModule) {
'use strict'; 'use strict';
angular coreModule.directive('spectrumPicker', function() {
.module('grafana.directives') return {
.directive('spectrumPicker', function() { restrict: 'E',
return { require: 'ngModel',
restrict: 'E', scope: false,
require: 'ngModel', replace: true,
scope: false, template: "<span><input class='input-small' /></span>",
replace: true, link: function(scope, element, attrs, ngModel) {
template: "<span><input class='input-small' /></span>", var input = element.find('input');
link: function(scope, element, attrs, ngModel) { var options = angular.extend({
var input = element.find('input'); showAlpha: true,
var options = angular.extend({ showButtons: false,
showAlpha: true, color: ngModel.$viewValue,
showButtons: false, change: function(color) {
color: ngModel.$viewValue, scope.$apply(function() {
change: function(color) { ngModel.$setViewValue(color.toRgbString());
scope.$apply(function() { });
ngModel.$setViewValue(color.toRgbString()); }
}); }, scope.$eval(attrs.options));
}
}, scope.$eval(attrs.options));
ngModel.$render = function() { ngModel.$render = function() {
input.spectrum('set', ngModel.$viewValue || ''); input.spectrum('set', ngModel.$viewValue || '');
}; };
input.spectrum(options); input.spectrum(options);
scope.$on('$destroy', function() { scope.$on('$destroy', function() {
input.spectrum('destroy'); input.spectrum('destroy');
}); });
} }
}; };
}); });
}); });
define([ define([
'angular', 'angular',
'jquery', 'jquery',
'bootstrap-tagsinput' '../core_module',
'bootstrap-tagsinput',
], ],
function (angular, $) { function (angular, $, coreModule) {
'use strict'; 'use strict';
function djb2(str) { function djb2(str) {
...@@ -38,9 +39,7 @@ function (angular, $) { ...@@ -38,9 +39,7 @@ function (angular, $) {
element.css("border-color", borderColor); element.css("border-color", borderColor);
} }
angular coreModule.directive('tagColorFromName', function() {
.module('grafana.directives')
.directive('tagColorFromName', function() {
return { return {
scope: { tagColorFromName: "=" }, scope: { tagColorFromName: "=" },
link: function (scope, element) { link: function (scope, element) {
...@@ -49,9 +48,7 @@ function (angular, $) { ...@@ -49,9 +48,7 @@ function (angular, $) {
}; };
}); });
angular coreModule.directive('bootstrapTagsinput', function() {
.module('grafana.directives')
.directive('bootstrapTagsinput', function() {
function getItemProperty(scope, property) { function getItemProperty(scope, property) {
if (!property) { if (!property) {
......
define([ define([
'angular', '../core_module',
'kbn'
], ],
function (angular) { function (coreModule) {
'use strict'; 'use strict';
angular coreModule.directive('topnav', function($rootScope, contextSrv) {
.module('grafana.directives') return {
.directive('topnav', function($rootScope, contextSrv) { restrict: 'E',
return { transclude: true,
restrict: 'E', scope: {
transclude: true, title: "@",
scope: { section: "@",
title: "@", titleAction: "&",
section: "@", subnav: "=",
titleAction: "&", },
subnav: "=", template:
}, '<div class="navbar navbar-static-top"><div class="navbar-inner"><div class="container-fluid">' +
template: '<div class="top-nav">' +
'<div class="navbar navbar-static-top"><div class="navbar-inner"><div class="container-fluid">' + '<a class="top-nav-menu-btn pointer" ng-if="!contextSrv.sidemenu" ng-click="toggle()">' +
'<div class="top-nav">' + '<img class="logo-icon" src="img/fav32.png"></img> ' +
'<a class="top-nav-menu-btn pointer" ng-if="!contextSrv.sidemenu" ng-click="toggle()">' + '<i class="fa fa-bars"></i>' +
'<img class="logo-icon" src="img/fav32.png"></img> ' + '</a>' +
'<i class="fa fa-bars"></i>' +
'</a>' +
'<span class="icon-circle top-nav-icon">' + '<span class="icon-circle top-nav-icon">' +
'<i ng-class="icon"></i>' + '<i ng-class="icon"></i>' +
'</span>' + '</span>' +
'<span ng-show="section">' + '<span ng-show="section">' +
'<span class="top-nav-title">{{section}}</span>' + '<span class="top-nav-title">{{section}}</span>' +
'<i class="top-nav-breadcrumb-icon fa fa-angle-right"></i>' + '<i class="top-nav-breadcrumb-icon fa fa-angle-right"></i>' +
'</span>' + '</span>' +
'<a ng-click="titleAction()" class="top-nav-title">' + '<a ng-click="titleAction()" class="top-nav-title">' +
'{{title}}' + '{{title}}' +
'</a>' + '</a>' +
'<i ng-show="subnav" class="top-nav-breadcrumb-icon fa fa-angle-right"></i>' + '<i ng-show="subnav" class="top-nav-breadcrumb-icon fa fa-angle-right"></i>' +
'</div><div ng-transclude></div></div></div></div>', '</div><div ng-transclude></div></div></div></div>',
link: function(scope, elem, attrs) { link: function(scope, elem, attrs) {
scope.icon = attrs.icon; scope.icon = attrs.icon;
scope.contextSrv = contextSrv; scope.contextSrv = contextSrv;
scope.toggle = function() { scope.toggle = function() {
$rootScope.appEvent('toggle-sidemenu'); $rootScope.appEvent('toggle-sidemenu');
}; };
} }
}; };
}); });
}); });
...@@ -4,7 +4,7 @@ import angular = require('angular'); ...@@ -4,7 +4,7 @@ import angular = require('angular');
import jquery = require('jquery'); import jquery = require('jquery');
import moment = require('moment'); import moment = require('moment');
import _ = require('lodash'); import _ = require('lodash');
import coreModule from '../core_module'; import coreModule = require('../core_module');
coreModule.filter('stringSort', function() { coreModule.filter('stringSort', function() {
return function(input) { return function(input) {
......
define([
'./dashUpload',
'./dashEditLink',
'./ngModelOnBlur',
'./misc',
'./confirmClick',
'./configModal',
'./spectrumPicker',
'./tags',
'./bodyClass',
'./valueSelectDropdown',
'./metric.segment',
'./grafanaVersionCheck',
'./dropdown.typeahead',
'./topnav',
'./annotationTooltip',
'./passwordStrenght',
], function () {});
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
</div> </div>
<form name="loginForm" class="login-form" style="margin-top: 25px;"> <form name="loginForm" class="login-form" style="margin-top: 25px;">
<div class="tight-from-container"> <div class="tight-form-container">
<div class="tight-form" ng-if="loginMode"> <div class="tight-form" ng-if="loginMode">
<ul class="tight-form-list"> <ul class="tight-form-list">
<li class="tight-form-item" style="width: 78px"> <li class="tight-form-item" style="width: 78px">
...@@ -41,7 +41,7 @@ ...@@ -41,7 +41,7 @@
<div class="clearfix"></div> <div class="clearfix"></div>
</div> </div>
<div class="tight-form" ng-if="!loginMode" style="margin: 20px 0 57px 0"> <div class="tight-form" ng-if="!loginMode">
<ul class="tight-form-list"> <ul class="tight-form-list">
<li class="tight-form-item" style="width: 79px"> <li class="tight-form-item" style="width: 79px">
<strong>Email</strong> <strong>Email</strong>
......
...@@ -36,7 +36,7 @@ ...@@ -36,7 +36,7 @@
</div> </div>
</div> </div>
<div class="tight-from-container"> <div class="tight-form-container">
<div class="tight-form" ng-if="!autoAssignOrg"> <div class="tight-form" ng-if="!autoAssignOrg">
<ul class="tight-form-list"> <ul class="tight-form-list">
<li class="tight-form-item" style="width: 128px"> <li class="tight-form-item" style="width: 128px">
......
define([ define([
'directives/valueSelectDropdown', 'core/directives/value_select_dropdown',
], ],
function () { function () {
'use strict'; 'use strict';
describe("SelectDropdownCtrl", function() { describe("SelectDropdownCtrl", function() {
var scope; var scope;
var ctrl; var ctrl;
var tagValuesMap = {}; var tagValuesMap = {};
var rootScope; var rootScope;
beforeEach(module('grafana.controllers')); beforeEach(module('grafana.core'));
beforeEach(inject(function($controller, $rootScope, $q) { beforeEach(inject(function($controller, $rootScope, $q) {
rootScope = $rootScope; rootScope = $rootScope;
scope = $rootScope.$new(); scope = $rootScope.$new();
......
...@@ -149,7 +149,7 @@ require([ ...@@ -149,7 +149,7 @@ require([
'specs/singlestat-specs', 'specs/singlestat-specs',
'specs/dynamicDashboardSrv-specs', 'specs/dynamicDashboardSrv-specs',
'specs/unsavedChangesSrv-specs', 'specs/unsavedChangesSrv-specs',
'specs/valueSelectDropdown-specs', 'specs/value_select_dropdown_specs',
'specs/opentsdbDatasource-specs', 'specs/opentsdbDatasource-specs',
'specs/cloudwatch-datasource-specs', 'specs/cloudwatch-datasource-specs',
'specs/elasticsearch-specs', 'specs/elasticsearch-specs',
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment