mirror of
https://github.com/Icinga/icingaweb2.git
synced 2025-07-29 08:44:10 +02:00
Test and icinga.js module setup procedure
Behaviours are now modules and icinga.js automatically requests module/list (which should be served by the application and is non static) and retrieves a list of modules to request and enable. refs #3753
This commit is contained in:
parent
63f7b8016e
commit
0d0db281f7
@ -1,27 +1,25 @@
|
|||||||
/*global Icinga:false, document: false, define:false require:false base_url:false console:false */
|
/*global Icinga:false, document: false, define:false require:false base_url:false console:false */
|
||||||
define([
|
define([
|
||||||
'jquery',
|
'jquery',
|
||||||
'vendor/jquery.sparkline.min',
|
|
||||||
'logging',
|
'logging',
|
||||||
'icinga/behaviour',
|
'icinga/module',
|
||||||
'icinga/util/async',
|
'icinga/util/async',
|
||||||
'icinga/container',
|
'icinga/container',
|
||||||
'modules/list'
|
'modules/list'
|
||||||
], function ($,sparkline,log,behaviour,async,containerMgr, modules) {
|
], function ($, log, moduleMgr, async, containerMgr, modules) {
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Icinga prototype
|
* Icinga prototype
|
||||||
*/
|
*/
|
||||||
var Icinga = function() {
|
var Icinga = function() {
|
||||||
var internalBehaviours = ['icinga/behaviour/actionTable','icinga/behaviour/mainDetail'];
|
var internalModules = ['icinga/modules/actionTable','icinga/modules/mainDetail'];
|
||||||
|
|
||||||
this.modules = {};
|
this.modules = {};
|
||||||
var failedModules = [];
|
var failedModules = [];
|
||||||
|
|
||||||
var initialize = function () {
|
var initialize = function () {
|
||||||
require(['modules/list']);
|
enableInternalModules();
|
||||||
enableDefaultBehaviour();
|
|
||||||
|
|
||||||
containerMgr.registerAsyncMgr(async);
|
containerMgr.registerAsyncMgr(async);
|
||||||
containerMgr.initializeContainers(document);
|
containerMgr.initializeContainers(document);
|
||||||
@ -30,9 +28,20 @@ define([
|
|||||||
enableModules();
|
enableModules();
|
||||||
};
|
};
|
||||||
|
|
||||||
var enableDefaultBehaviour = function() {
|
|
||||||
$.each(internalBehaviours,function(idx,behaviourImpl) {
|
|
||||||
behaviour.enableBehaviour(behaviourImpl,log.error);
|
var enableInternalModules = function() {
|
||||||
|
$.each(internalModules,function(idx,module) {
|
||||||
|
moduleMgr.enableModule(module, log.error);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
var loadModuleScript = function(name) {
|
||||||
|
moduleMgr.enableModule("modules/"+name, function(error) {
|
||||||
|
failedModules.push({
|
||||||
|
name: name,
|
||||||
|
errorMessage: error
|
||||||
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -40,17 +49,10 @@ define([
|
|||||||
moduleList = moduleList || modules;
|
moduleList = moduleList || modules;
|
||||||
|
|
||||||
$.each(modules,function(idx,module) {
|
$.each(modules,function(idx,module) {
|
||||||
if(module.behaviour) {
|
loadModuleScript(module.name);
|
||||||
behaviour.enableBehaviour(module.name+"/"+module.name,function(error) {
|
|
||||||
failedModules.push({name: module.name,errorMessage: error});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
var enableCb = function(behaviour) {
|
|
||||||
behaviour.enable();
|
|
||||||
};
|
|
||||||
|
|
||||||
$(document).ready(initialize.bind(this));
|
$(document).ready(initialize.bind(this));
|
||||||
|
|
||||||
@ -64,6 +66,10 @@ define([
|
|||||||
|
|
||||||
loadIntoContainer: function(ctr) {
|
loadIntoContainer: function(ctr) {
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
getFailedModules: function() {
|
||||||
|
return failedModules;
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
118
public/js/icinga/modules/actionTable.js
Normal file
118
public/js/icinga/modules/actionTable.js
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
/*global Icinga:false, document: false, define:false require:false base_url:false console:false */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ActionTable behaviour as described in
|
||||||
|
* https://wiki.icinga.org/display/cranberry/Frontend+Components#FrontendComponents-ActionTable
|
||||||
|
*
|
||||||
|
* @TODO: Row selection
|
||||||
|
*/
|
||||||
|
define(['jquery','logging','icinga/util/async'],function($,log,async) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
var ActionTableBehaviour = function() {
|
||||||
|
var onTableHeaderClick;
|
||||||
|
|
||||||
|
var TABLE_BASE_MATCHER = '.icinga-container table.action';
|
||||||
|
var linksInActionTable = TABLE_BASE_MATCHER+" tbody tr > a";
|
||||||
|
var actionTableRow = TABLE_BASE_MATCHER+" tbody tr";
|
||||||
|
var headerRow = TABLE_BASE_MATCHER+" > th a";
|
||||||
|
var searchField = ".icinga-container .actiontable.controls input[type=search]";
|
||||||
|
|
||||||
|
|
||||||
|
onTableHeaderClick = function (ev) {
|
||||||
|
var target = ev.currentTarget,
|
||||||
|
href = $(target).attr('href'),
|
||||||
|
destination;
|
||||||
|
if ($(target).parents('.layout-main-detail').length) {
|
||||||
|
if ($(target).parents("#icinga-main").length) {
|
||||||
|
destination = 'icinga-main';
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
destination = 'icinga-detail';
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
destination = 'icinga-main';
|
||||||
|
}
|
||||||
|
async.loadToTarget(destination, href);
|
||||||
|
ev.preventDefault();
|
||||||
|
ev.stopImmediatePropagation();
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
var onLinkTagClick = function(ev) {
|
||||||
|
|
||||||
|
var target = ev.currentTarget,
|
||||||
|
href = $(target).attr('href'),
|
||||||
|
destination;
|
||||||
|
if ($(target).parents('.layout-main-detail').length) {
|
||||||
|
destination = 'icinga-detail';
|
||||||
|
} else {
|
||||||
|
destination = 'icinga-main';
|
||||||
|
}
|
||||||
|
async.loadToTarget(destination,href);
|
||||||
|
ev.preventDefault();
|
||||||
|
ev.stopImmediatePropagation();
|
||||||
|
return false;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
var onTableRowClick = function(ev) {
|
||||||
|
ev.stopImmediatePropagation();
|
||||||
|
|
||||||
|
var target = $(ev.currentTarget),
|
||||||
|
href = target.attr('href'),
|
||||||
|
destination;
|
||||||
|
$('tr.active',target.parent('tbody').first()).removeClass("active");
|
||||||
|
target.addClass('active');
|
||||||
|
|
||||||
|
// When the tr has a href, act like it is a link
|
||||||
|
if(href) {
|
||||||
|
ev.currentTarget = target.first();
|
||||||
|
return onLinkTagClick(ev);
|
||||||
|
}
|
||||||
|
// Try to find a designated row action
|
||||||
|
var links = $("a.row-action",target);
|
||||||
|
if(links.length) {
|
||||||
|
ev.currentTarget = links.first();
|
||||||
|
return onLinkTagClick(ev);
|
||||||
|
}
|
||||||
|
|
||||||
|
// otherwise use the first anchor tag
|
||||||
|
links = $("a",target);
|
||||||
|
if(links.length) {
|
||||||
|
ev.currentTarget = links.first();
|
||||||
|
return onLinkTagClick(ev);
|
||||||
|
}
|
||||||
|
|
||||||
|
log.debug("No target for this table row found");
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
var onSearchInput = function(ev) {
|
||||||
|
ev.stopImmediatePropagation();
|
||||||
|
var txt = $(this).val();
|
||||||
|
};
|
||||||
|
|
||||||
|
this.eventHandler = {};
|
||||||
|
this.eventHandler[linksInActionTable] = {
|
||||||
|
'click' : onLinkTagClick
|
||||||
|
};
|
||||||
|
this.eventHandler[actionTableRow] = {
|
||||||
|
'click' : onTableRowClick
|
||||||
|
};
|
||||||
|
this.eventHandler[headerRow] = {
|
||||||
|
'click' : onTableHeaderClick
|
||||||
|
};
|
||||||
|
this.eventHandler[searchField] = {
|
||||||
|
'keyup' : onSearchInput
|
||||||
|
};
|
||||||
|
|
||||||
|
this.enable = function() {
|
||||||
|
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
return new ActionTableBehaviour();
|
||||||
|
|
||||||
|
});
|
94
public/js/icinga/modules/mainDetail.js
Executable file
94
public/js/icinga/modules/mainDetail.js
Executable file
@ -0,0 +1,94 @@
|
|||||||
|
/*global Icinga:false, document: false, define:false require:false base_url:false console:false */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Main-Detail layout behaviour as described in
|
||||||
|
* https://wiki.icinga.org/display/cranberry/Frontend+Components#FrontendComponents-Behaviour
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
define(['jquery','logging','icinga/util/async'],function($,log,async) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
var MainDetailBehaviour = function() {
|
||||||
|
|
||||||
|
var onOuterLinkClick = function(ev) {
|
||||||
|
var a = $(ev.currentTarget),
|
||||||
|
target = a.attr("target"),
|
||||||
|
href = a.attr("href");
|
||||||
|
ev.stopImmediatePropagation();
|
||||||
|
collapseDetailView();
|
||||||
|
async.loadToTarget("icinga-main",href);
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
var onLinkTagClick = function(ev) {
|
||||||
|
|
||||||
|
var a = $(ev.currentTarget),
|
||||||
|
target = a.attr("target"),
|
||||||
|
href = a.attr("href");
|
||||||
|
|
||||||
|
// check for protocol://
|
||||||
|
if(/^[A-Z]{2,10}\:\/\//i.test(href)) {
|
||||||
|
window.open(href);
|
||||||
|
ev.stopImmediatePropagation();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check for link in table header
|
||||||
|
if(a.parents('th').length > 0) {
|
||||||
|
ev.stopImmediatePropagation();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(typeof target === "undefined") {
|
||||||
|
if(a.parents("#icinga-detail").length) {
|
||||||
|
async.loadToTarget("icinga-detail",href);
|
||||||
|
} else {
|
||||||
|
async.loadToTarget("icinga-main",href);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
switch(target) {
|
||||||
|
case "main":
|
||||||
|
async.loadToTarget("icinga-main",href);
|
||||||
|
collapseDetailView();
|
||||||
|
break;
|
||||||
|
case "detail":
|
||||||
|
async.loadToTarget("icinga-detail",href);
|
||||||
|
break;
|
||||||
|
case "popup":
|
||||||
|
async.loadToTarget(null,href);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ev.stopImmediatePropagation();
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
var expandDetailView = function() {
|
||||||
|
$("#icinga-detail").parents(".collapsed").removeClass('collapsed');
|
||||||
|
};
|
||||||
|
|
||||||
|
var collapseDetailView = function(elementInDetailView) {
|
||||||
|
$("#icinga-detail").parents(".layout-main-detail").addClass('collapsed');
|
||||||
|
};
|
||||||
|
|
||||||
|
this.expandDetailView = expandDetailView;
|
||||||
|
this.collapseDetailView = collapseDetailView;
|
||||||
|
|
||||||
|
this.eventHandler = {
|
||||||
|
'.layout-main-detail * a' : {
|
||||||
|
'click' : onLinkTagClick
|
||||||
|
},
|
||||||
|
'a' : {
|
||||||
|
'click' : onOuterLinkClick
|
||||||
|
},
|
||||||
|
'.layout-main-detail .icinga-container#icinga-detail' : {
|
||||||
|
'focus' : expandDetailView
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
return new MainDetailBehaviour();
|
||||||
|
});
|
||||||
|
|
@ -14,7 +14,7 @@ var BASE = "../../../../public/js/";
|
|||||||
require(BASE+"icinga/module.js");
|
require(BASE+"icinga/module.js");
|
||||||
|
|
||||||
var module = rjsmock.getDefine();
|
var module = rjsmock.getDefine();
|
||||||
|
GLOBAL.document = $('body');
|
||||||
/**
|
/**
|
||||||
* Test module that only uses eventhandlers and
|
* Test module that only uses eventhandlers and
|
||||||
* no custom logic
|
* no custom logic
|
||||||
@ -186,5 +186,41 @@ describe('Module loader', function() {
|
|||||||
tearDownTestDOM();
|
tearDownTestDOM();
|
||||||
$('body').unbind();
|
$('body').unbind();
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
describe('The icinga module bootstrap', function() {
|
||||||
|
it("Should automatically load all enabled modules", function() {
|
||||||
|
rjsmock.purgeDependencies();
|
||||||
|
var testClick = false;
|
||||||
|
rjsmock.registerDependencies({
|
||||||
|
"icinga/module": module,
|
||||||
|
"modules/test" : {
|
||||||
|
eventHandler: {
|
||||||
|
"a.test" : {
|
||||||
|
click : function() {
|
||||||
|
testClick = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"icinga/container" : {
|
||||||
|
registerAsyncMgr: function() {},
|
||||||
|
initializeContainers: function() {}
|
||||||
|
},
|
||||||
|
"modules/list" : [
|
||||||
|
{ name: 'test' },
|
||||||
|
{ name: 'test2'} // this one fails
|
||||||
|
]
|
||||||
|
});
|
||||||
|
tearDownTestDOM();
|
||||||
|
require(BASE+"icinga/icinga.js");
|
||||||
|
var icinga = rjsmock.getDefine();
|
||||||
|
$('body').append($("<a class='test'></a>"));
|
||||||
|
$('a.test').click();
|
||||||
|
should.equal(testClick, true, "Module wasn't automatically loaded!");
|
||||||
|
icinga.getFailedModules().should.have.length(1);
|
||||||
|
should.equal(icinga.getFailedModules()[0].name, "test2");
|
||||||
|
tearDownTestDOM();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user