mirror of
https://github.com/Icinga/icingaweb2.git
synced 2025-07-23 05:44:36 +02:00
Add javascript autoloading
the js/modules/%modulename%/%file% is now mapped to the module path (if existing). To prevent name clashing, the modules folder has been renamed to components.
This commit is contained in:
parent
3a5a4bf273
commit
d94d89e1cf
@ -9,6 +9,7 @@ use Icinga\Web\ActionController;
|
|||||||
use Icinga\Application\Icinga;
|
use Icinga\Application\Icinga;
|
||||||
use Zend_Controller_Action_Exception as ActionException;
|
use Zend_Controller_Action_Exception as ActionException;
|
||||||
|
|
||||||
|
use Icinga\Application\Benchmark;
|
||||||
/**
|
/**
|
||||||
* Class StaticController
|
* Class StaticController
|
||||||
* @package Icinga\Web\Form
|
* @package Icinga\Web\Form
|
||||||
@ -69,7 +70,7 @@ class StaticController extends ActionController
|
|||||||
*/
|
*/
|
||||||
public function javascriptAction()
|
public function javascriptAction()
|
||||||
{
|
{
|
||||||
$module = $this->_getParam('moduleName');
|
$module = $this->_getParam('module_name');
|
||||||
$file = $this->_getParam('file');
|
$file = $this->_getParam('file');
|
||||||
$basedir = Icinga::app()->getModule($module)->getBaseDir();
|
$basedir = Icinga::app()->getModule($module)->getBaseDir();
|
||||||
|
|
||||||
@ -96,15 +97,16 @@ class StaticController extends ActionController
|
|||||||
) . ' GMT'
|
) . ' GMT'
|
||||||
);
|
);
|
||||||
|
|
||||||
|
$hash = md5_file($filePath);
|
||||||
|
|
||||||
if ($hash === $this->getRequest()->getHeader('If-None-Match')) {
|
if ($hash === $this->getRequest()->getHeader('If-None-Match')) {
|
||||||
$response->setHttpResponseCode(304);
|
$response->setHttpResponseCode(304);
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
readfile($filePath);
|
readfile($filePath);
|
||||||
}
|
}
|
||||||
// TODO: get rid of exit:
|
return;
|
||||||
exit;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// @codingStandardsIgnoreEnd
|
// @codingStandardsIgnoreEnd
|
||||||
|
@ -59,6 +59,17 @@ class Web extends ApplicationBootstrap
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
$this->frontController->getRouter()->addRoute(
|
||||||
|
'module_javascript',
|
||||||
|
new Route(
|
||||||
|
'js/modules/:module_name/:file',
|
||||||
|
array(
|
||||||
|
'controller' => 'static',
|
||||||
|
'action' => 'javascript'
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -162,6 +173,7 @@ class Web extends ApplicationBootstrap
|
|||||||
*/
|
*/
|
||||||
protected function configurePagination()
|
protected function configurePagination()
|
||||||
{
|
{
|
||||||
|
|
||||||
Paginator::addScrollingStylePrefixPath(
|
Paginator::addScrollingStylePrefixPath(
|
||||||
'Icinga_Web_Paginator_ScrollingStyle',
|
'Icinga_Web_Paginator_ScrollingStyle',
|
||||||
'Icinga/Web/Paginator/ScrollingStyle'
|
'Icinga/Web/Paginator/ScrollingStyle'
|
||||||
|
118
public/js/icinga/components/actionTable.js
Normal file
118
public/js/icinga/components/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();
|
||||||
|
|
||||||
|
});
|
99
public/js/icinga/components/mainDetail.js
Executable file
99
public/js/icinga/components/mainDetail.js
Executable file
@ -0,0 +1,99 @@
|
|||||||
|
/*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) {
|
||||||
|
log.debug("Parent is detail, loading into detail");
|
||||||
|
async.loadToTarget("icinga-detail",href);
|
||||||
|
} else {
|
||||||
|
log.debug("Parent is not detail, loading into main");
|
||||||
|
async.loadToTarget("icinga-main",href);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
switch(target) {
|
||||||
|
case "body":
|
||||||
|
async.loadToTarget("body", href);
|
||||||
|
break;
|
||||||
|
case "main":
|
||||||
|
async.loadToTarget("icinga-main",href);
|
||||||
|
collapseDetailView();
|
||||||
|
break;
|
||||||
|
case "detail":
|
||||||
|
log.debug("Target: detail");
|
||||||
|
async.loadToTarget("icinga-detail",href);
|
||||||
|
break;
|
||||||
|
case "popup":
|
||||||
|
log.debug("No target");
|
||||||
|
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();
|
||||||
|
});
|
@ -5,7 +5,7 @@
|
|||||||
var containerMgrInstance = null;
|
var containerMgrInstance = null;
|
||||||
var async;
|
var async;
|
||||||
|
|
||||||
var ContainerMgr = function($,log,Widgets,SubTable,holder) {
|
var ContainerMgr = function($,log,Widgets,SubTable) {
|
||||||
|
|
||||||
|
|
||||||
var enhanceDetachLinks = function() {
|
var enhanceDetachLinks = function() {
|
||||||
@ -34,14 +34,12 @@
|
|||||||
}
|
}
|
||||||
target.focus();
|
target.focus();
|
||||||
this.initializeContainers(target);
|
this.initializeContainers(target);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
this.updateControlTargets = function(ctrl, req) {
|
this.updateControlTargets = function(ctrl, req) {
|
||||||
$('a',ctrl).each(function() {
|
$('a',ctrl).each(function() {
|
||||||
$(this).attr("href",req.url);
|
$(this).attr("href",req.url);
|
||||||
});
|
});
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
this.initControlBehaviour = function(root) {
|
this.initControlBehaviour = function(root) {
|
||||||
@ -86,7 +84,6 @@
|
|||||||
this.initExpandables(root);
|
this.initExpandables(root);
|
||||||
this.drawImplicitWidgets(root);
|
this.drawImplicitWidgets(root);
|
||||||
this.loadAsyncContainers(root);
|
this.loadAsyncContainers(root);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
this.createPopupContainer = function(content,req) {
|
this.createPopupContainer = function(content,req) {
|
||||||
@ -96,7 +93,6 @@
|
|||||||
.append($("<div>").addClass('modal-body').html(content)).appendTo(document.body);
|
.append($("<div>").addClass('modal-body').html(content)).appendTo(document.body);
|
||||||
|
|
||||||
closeButton.on("click",function() {container.remove();});
|
closeButton.on("click",function() {container.remove();});
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
this.getContainer = function(id) {
|
this.getContainer = function(id) {
|
||||||
@ -107,7 +103,7 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
};
|
};
|
||||||
define(['jquery','logging','icinga/widgets/checkIcons','icinga/widgets/subTable'], function($,log,widgets,subTable) {
|
define(['jquery','logging','icinga/widgets/checkIcons','icinga/widgets/subTable'],function($,log,widgets,subTable) {
|
||||||
if (containerMgrInstance === null) {
|
if (containerMgrInstance === null) {
|
||||||
containerMgrInstance = new ContainerMgr($,log,widgets,subTable);
|
containerMgrInstance = new ContainerMgr($,log,widgets,subTable);
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,7 @@ define([
|
|||||||
* Icinga prototype
|
* Icinga prototype
|
||||||
*/
|
*/
|
||||||
var Icinga = function() {
|
var Icinga = function() {
|
||||||
var internalModules = ['icinga/modules/actionTable','icinga/modules/mainDetail'];
|
var internalModules = ['icinga/components/actionTable','icinga/components/mainDetail'];
|
||||||
|
|
||||||
this.modules = {};
|
this.modules = {};
|
||||||
var failedModules = [];
|
var failedModules = [];
|
||||||
@ -37,7 +37,7 @@ define([
|
|||||||
};
|
};
|
||||||
|
|
||||||
var loadModuleScript = function(name) {
|
var loadModuleScript = function(name) {
|
||||||
moduleMgr.enableModule("modules/"+name, function(error) {
|
moduleMgr.enableModule("modules/"+name+"/"+name, function(error) {
|
||||||
failedModules.push({
|
failedModules.push({
|
||||||
name: name,
|
name: name,
|
||||||
errorMessage: error
|
errorMessage: error
|
||||||
|
Loading…
x
Reference in New Issue
Block a user