diff --git a/src/sunstone/public/js/plugins/dashboard-tab.js b/src/sunstone/public/js/plugins/dashboard-tab.js
index edb303c51f..b6bc6fb2ac 100644
--- a/src/sunstone/public/js/plugins/dashboard-tab.js
+++ b/src/sunstone/public/js/plugins/dashboard-tab.js
@@ -149,7 +149,13 @@ var dashboard_tab_content =
';
-Sunstone.addMainTab('dashboard_tab','Dashboard',dashboard_tab_content,null);
+var dashboard_tab = {
+ title: 'Dashboard',
+ content: dashboard_tab_content,
+ condition : True
+}
+
+Sunstone.addMainTab('dashboard_tab',dashboard_tab);
$(document).ready(function(){
//Dashboard link listener
diff --git a/src/sunstone/public/js/plugins/hosts-tab.js b/src/sunstone/public/js/plugins/hosts-tab.js
index dd1c937765..21c45e5e0d 100644
--- a/src/sunstone/public/js/plugins/hosts-tab.js
+++ b/src/sunstone/public/js/plugins/hosts-tab.js
@@ -322,12 +322,17 @@ var host_info_panel = {
content: ""
}
};
-
+
+
+var hosts_tab = {
+ title: 'Hosts & Clusters',
+ content: hosts_tab_content,
+ buttons: host_buttons,
+ condition: True
+}
Sunstone.addActions(host_actions);
-
-// title, content, buttons, id
-Sunstone.addMainTab('hosts_tab','Hosts & Clusters',hosts_tab_content,host_buttons);
+Sunstone.addMainTab('hosts_tab',hosts_tab);
Sunstone.addInfoPanel("host_info_panel",host_info_panel);
diff --git a/src/sunstone/public/js/plugins/images-tab.js b/src/sunstone/public/js/plugins/images-tab.js
index ea6eef4c36..de4ab5a5cd 100644
--- a/src/sunstone/public/js/plugins/images-tab.js
+++ b/src/sunstone/public/js/plugins/images-tab.js
@@ -422,8 +422,15 @@ var image_info_panel = {
}
+var images_tab = {
+ title: "Images",
+ content: images_tab_content,
+ buttons: image_buttons,
+ condition: True
+}
+
Sunstone.addActions(image_actions);
-Sunstone.addMainTab('images_tab',"Images",images_tab_content,image_buttons);
+Sunstone.addMainTab('images_tab',images_tab);
Sunstone.addInfoPanel('image_info_panel',image_info_panel);
diff --git a/src/sunstone/public/js/plugins/users-tab.js b/src/sunstone/public/js/plugins/users-tab.js
index e9f1411f12..1c9f2039a6 100644
--- a/src/sunstone/public/js/plugins/users-tab.js
+++ b/src/sunstone/public/js/plugins/users-tab.js
@@ -119,8 +119,15 @@ var user_buttons = {
}
}
+var users_tab = {
+ title: "Users",
+ content: users_tab_content,
+ buttons: user_buttons,
+ condition: function(){ return uid == 0; }
+}
+
Sunstone.addActions(user_actions);
-Sunstone.addMainTab('users_tab',"Users",users_tab_content,user_buttons,false,function(){return uid==0;});
+Sunstone.addMainTab('users_tab',users_tab);
function userElementArray(user_json){
diff --git a/src/sunstone/public/js/plugins/vms-tab.js b/src/sunstone/public/js/plugins/vms-tab.js
index 9c149e43ae..3fd1622da0 100644
--- a/src/sunstone/public/js/plugins/vms-tab.js
+++ b/src/sunstone/public/js/plugins/vms-tab.js
@@ -805,8 +805,15 @@ var vm_info_panel = {
}
}
+var vms_tab = {
+ title: "Virtual Machines",
+ content: vms_tab_content,
+ buttons: vm_buttons,
+ condition: True
+}
+
Sunstone.addActions(vm_actions);
-Sunstone.addMainTab('vms_tab',"Virtual Machines",vms_tab_content,vm_buttons);
+Sunstone.addMainTab('vms_tab',vms_tab);
Sunstone.addInfoPanel('vm_info_panel',vm_info_panel);
diff --git a/src/sunstone/public/js/plugins/vnets-tab.js b/src/sunstone/public/js/plugins/vnets-tab.js
index 08845611d7..030202981c 100644
--- a/src/sunstone/public/js/plugins/vnets-tab.js
+++ b/src/sunstone/public/js/plugins/vnets-tab.js
@@ -259,8 +259,15 @@ var vnet_info_panel = {
}
}
+var vnets_tab = {
+ title: "Virtual Networks",
+ content: vnets_tab_content,
+ buttons: vnet_buttons,
+ condition: True
+}
+
Sunstone.addActions(vnet_actions);
-Sunstone.addMainTab('vnets_tab',"Virtual Networks",vnets_tab_content, vnet_buttons);
+Sunstone.addMainTab('vnets_tab',vnets_tab);
Sunstone.addInfoPanel('vnet_info_panel',vnet_info_panel);
diff --git a/src/sunstone/public/js/sunstone.js b/src/sunstone/public/js/sunstone.js
index 1473526406..e425a3a308 100644
--- a/src/sunstone/public/js/sunstone.js
+++ b/src/sunstone/public/js/sunstone.js
@@ -14,69 +14,64 @@
/* limitations under the License. */
/* -------------------------------------------------------------------------- */
-
-//TODOs: handle confirm and confirm with select dialogs
-
var cookie = {};
var username = '';
var uid = '';
var spinner = '';
+
+//Sunstone configuration is formed by predifined "actions", main tabs
+//and "info_panels". Each tab has "content" and "buttons". Each
+//"info_panel" has "tabs" with "content".
var SunstoneCfg = {
- "actions" : {
-
-
- },
-
- "tabs" : {
-
- },
-
- "info_panels" : {
-
- }
+ "actions" : {},
+ "tabs" : {},
+ "info_panels" : {}
};
+/* Public plugin interface */
var Sunstone = {
-
+ //Adds a predifined action
"addAction" : function (name,action_obj) {
SunstoneCfg["actions"][name] = action_obj;
},
+ //Replaces a predefined action
"updateAction" : function(name,action_obj) {
SunstoneCfg["actions"][name] = action_obj;
},
+ //Deletes a predefined action.
"removeAction" : function(action) {
- SunstoneCfg["actions"][action] = null;
+ delete SunstoneCfg["actions"][action];
},
+ //Adds several actions encapsulated in an js object.
"addActions" : function(actions) {
for (action in actions){
Sunstone.addAction(action,actions[action]);
}
},
- "addMainTab" : function(tab_id,title_arg,content_arg, buttons_arg,refresh,condition_f) {
- SunstoneCfg["tabs"][tab_id] = {title: title_arg,
- content: content_arg,
- buttons: buttons_arg,
- condition: condition_f
- };
+ //Adds a new main tab. Refreshes the dom if wanted.
+ "addMainTab" : function(tab_id,tab_obj,refresh) {
+ SunstoneCfg["tabs"][tab_id] = tab_obj;
if (refresh){
-
+ insertTab(tab_id);
}
},
+ //Updates the content of an info tab and refreshes the DOM if wanted.
"updateMainTabContent" : function(tab_id,content_arg,refresh){
SunstoneCfg["tabs"][tab_id]["content"]=content_arg;
- if (refresh){
+ if (refresh){ //if not present it won't be updated
$('div#'+tab).html(tab_info.content);
}
},
+ //Replaces the buttons of an info tab and regenerates them if wanted.
"updateMainTabButtons" : function(tab_id,buttons_arg,refresh){
SunstoneCfg["tabs"][tab_id]["buttons"]=buttons_arg;
if (refresh){
@@ -85,13 +80,16 @@ var Sunstone = {
}
},
+ //Removes a tab and refreshes the DOM
"removeMainTab" : function(tab_id,refresh) {
- SunstoneCfg["tabs"][tab_id]=null;
+ delete SunstoneCfg["tabs"][tab_id];
if (refresh) {
$('div#'+tab_name).remove();
}
},
+ //Generates and returns the HTML div element for an info panel, with
+ //Jquery tabs.
"getInfoPanelHTML" : function(name,selected_tab){
var info_panel = $('
');
var tabs = SunstoneCfg["info_panels"][name];
@@ -108,26 +106,32 @@ var Sunstone = {
},
+ //Adds a new info panel
"addInfoPanel" : function(name, info_panel){
SunstoneCfg["info_panels"][name]=info_panel;
},
+ //Replaces an existing info panel
"updateInfoPanel" : function(name, info_panel){
SunstoneCfg["info_panels"][name]=info_panel;
},
+ //Removes an info panel
"removeInfoPanel" : function(name){
- SunstoneCfg["info_panels"][name] = null;
+ delete SunstoneCfg["info_panels"][name];
},
+ //Makes an info panel content pop up in the screen.
"popUpInfoPanel" : function(name, selected_tab){
popDialog(Sunstone.getInfoPanelHTML(name, selected_tab));
},
+ //adds a tab to an info panel.
"addInfoPanelTab" : function(info_panel, tab_name, tab){
SunstoneCfg["info_panels"][info_panel][tab_name] = tab;
},
+ //Replaces a tab from an info panel. Refreshes the DOM if wanted.
"updateInfoPanelTab" : function(info_panel, tab_name, tab, refresh){
SunstoneCfg["info_panels"][info_panel][tab_name] = tab;
if (refresh){
@@ -135,11 +139,14 @@ var Sunstone = {
}
},
-
+ //Removes a tab from an info panel configuration.
"removeInfoPanelTab" : function(info_panel,tab_name){
- SunstoneCfg["info_panels"][info_panel][tab_name] = null;
+ delete SunstoneCfg["info_panels"][info_panel][tab_name];
},
+ //Runs a predefined action. Wraps the calls to opennebula.js and
+ //can be use to run action depending on conditions and notify them
+ //if desired.
"runAction" : function(action, data_arg, extra_param){
var actions = SunstoneCfg["actions"];
@@ -152,9 +159,13 @@ var Sunstone = {
var notify = action_cfg.notify;
var condition = action_cfg["condition"];
- if (condition && !condition() && notify){
- //we do not meet the condition to run this action
+
+ //Is the condition to run the action met?
+ //Should we inform if it is not met?
+ if (condition && !condition()){
+ if (notify) {
notifyError("This action cannot be run");
+ }
return;
}
@@ -163,19 +174,23 @@ var Sunstone = {
var err = action_cfg["error"];
-
+ //Time to close any confirmation dialogs, as the execution may have
+ //come from them.
$('div#confirm_with_select_dialog').dialog("close");
$('div#confirm_dialog').dialog("close");
//We ease the use of:
- // * Create call
- // * Confirm and confirm with select calls
- // * Calls on multiple elements
- // * Other calls
+ // * "create" calls to opennebula.js
+ // * "single" element calls to opennebula.js
+ // * "list" (get the pool of elements) calls to opennebula.js
+ // * "multiple" - actions to be run on a given list of elements
+ // (with maybe an extra parameter).
+ // * The default actions. Simple call the the pre-defined "call"
+ // function with an extraparam if defined.
switch (action_cfg.type){
- case "create":
+ case "create","register":
call({data:data_arg, success: callback, error:err});
break;
case "single":
@@ -195,8 +210,8 @@ var Sunstone = {
});
break;
default:
- //we have supposedly altered an action and we want it to do
- //something completely different
+ //This action is complemente handled by the "call" function.
+ //we pass any data if present.
if (data_arg && extra_param) {call(data_arg,extra_param);}
else if (data_arg) {call(data_arg);}
else {call();}
@@ -204,6 +219,9 @@ var Sunstone = {
},
+ //Runs a predefined action on the selected nodes of a datatable.
+ //Optionally they are run with an extra_parameter.
+ //If no datatable is provided, it simply runs the action.
"runActionOnDatatableNodes": function(action,dataTable,extra_param){
if (dataTable != null){
@@ -219,11 +237,14 @@ var Sunstone = {
Sunstone.runAction(action,extra_param);
};
},
+
+ //returns a button object from the desired tab
"getButton" : function(tab_name,button_name){
var button = null;
var buttons = SunstoneCfg["tabs"][tab_name]["buttons"];
button = buttons[button_name];
- if (!button && buttons["action_list"]) //not found, is it in the list then?
+ //not found, is it in the list then?
+ if (!button && buttons["action_list"])
{
button = buttons["action_list"]["actions"][button_name];
}
@@ -236,17 +257,25 @@ var Sunstone = {
-//plugins have done their jobs when we execute this
+//Plugins have done their pre-ready jobs when we execute this. That means
+//all startup configuration is in place regarding tabs, info panels etc.
$(document).ready(function(){
readCookie();
setLogin();
+
+ //Insert the tabs in the DOM and their buttons.
insertTabs();
insertButtons();
+ //Enhace the look of select buttons
initListButtons();
- setupCreateDialogs(); //listener for create
+
+ //Prepare the standard confirmation dialogs
setupConfirmDialogs();
+ //Listen for .action_buttons
+ //An action buttons runs a predefined action. If it has type
+ //"multiple" it runs that action on the elements of a datatable.
$('.action_button').live("click",function(){
var table = null;
@@ -264,32 +293,35 @@ $(document).ready(function(){
return false;
});
+
+ //Listen .confirm_buttons. These buttons show a confirmation dialog
+ //before running the action.
$('.confirm_button').live("click",function(){
popUpConfirmDialog(this);
return false;
});
+ //Listen .confirm_buttons. These buttons show a confirmation dialog
+ //with a select box before running the action.
$('.confirm_with_select_button').live("click",function(){
popUpConfirmWithSelectDialog(this);
return false;
});
-
+ //Jquery-enhace the buttons in the DOM
$('button').button();
- $('div#select_helpers').hide();
-
- $(".ui-widget-overlay").live("click", function (){
- $("div:ui-dialog:visible").dialog("close");
+ //Close overlay dialogs when clicking outside of them.
+ $(".ui-widget-overlay").live("click", function (){
+ $("div:ui-dialog:visible").dialog("close");
});
-
-
- //Close select lists...
+ //Close select lists when clicking somewhere else.
$('*:not(.action_list,.list_button)').click(function(){
$('.action_list:visible').hide();
});
+ //Start with the dashboard (supposing we have one).
showTab('#dashboard_tab');
});
@@ -307,8 +339,10 @@ function readCookie(){
});
}
-//sets the user info in the top bar and creates a listner in the signout button
+//sets the user info in the top bar and creates a listner in the
+//signout button
function setLogin(){
+ //This two variables can be used anywhere
username = cookie["one-user"];
uid = cookie["one-user_id"];
@@ -322,128 +356,114 @@ function setLogin(){
});
}
-
+//Inserts all main tabs in the DOM
function insertTabs(){
var tab_info;
for (tab in SunstoneCfg["tabs"]){
- tab_info = SunstoneCfg["tabs"][tab];
-
- //skip this tab if we do not meet the condition
- if (tab_info.condition && !tab_info.condition()) {continue;}
- $("div.inner-center").append('');
- $('div#'+tab).html(tab_info.content);
-
- $('ul#navigation').append('
');
-
+ insertTab(tab);
}
}
+//Inserts a main tab in the DOM. This is done by
+//adding the content to the proper div and by adding a list item
+//link to the navigation menu
+function insertTab(tab_name){
+ var tab_info = SunstoneCfg["tabs"][tab_name];
+ var condition = tab_info["condition"];
+ //skip this tab if we do not meet the condition
+ if (condition && !condition()) {return;}
+ $("div.inner-center").append('');
+ $('div#'+tab_name).html(tab_info.content);
+
+ $('ul#navigation').append('
');
+}
+
+
+//Inserts the buttons of all tabs.
function insertButtons(){
for (tab in SunstoneCfg["tabs"]){
insertButtonsInTab(tab)
}
}
+//If we have defined a block of action buttons in a tab,
+//this function takes care of inserting them in the DOM.
function insertButtonsInTab(tab_name){
var buttons = SunstoneCfg["tabs"][tab_name]["buttons"];
var button_code="";
var sel_obj=null;
+ var condition=null;
- if ($('div#'+tab_name+' .action_blocks').length){
+ //Check if we have included an appropiate space our tab to
+ //insert them (an .action_blocks div)
+ if ($('div#'+tab_name+' div.action_blocks').length){
+
+ //for every button defined for this tab...
for (button_name in buttons){
button_code = "";
button = buttons[button_name];
- if (button.condition()) {
- switch (button.type) {
- case "select":
- button_code = '';
- break;
- case "image":
- button_code = '';
- break;
- case "create_dialog":
- button_code = '';
- break;
- default:
- button_code = '';
+ condition = button.condition;
+ //if we meet the condition we proceed. Otherwise we skip it.
+ if (condition && !condition()) { continue; }
- }
+ //depending on the type of button we generate different
+ //code. There are 4 possible types:
+ /*
+ * select: We need to create a select element with actions inside.
+ * image: a button consisting of a link with an image inside.
+ * create: we make sure they have the "action_button" class.
+ * default: generally buttons have the "_button" class.
+ */
+ switch (button.type) {
+ case "select":
+ button_code = '';
+ break;
+ case "image":
+ button_code = '';
+ break;
+ case "create_dialog":
+ button_code = '';
+ break;
+ default:
+ button_code = '';
+
}
+
$('div#'+tab_name+' .action_blocks').append(button_code);
}//for each button in tab
}//if tab exists
}
-// We do not insert info panels code, we generate it dynamicly when
-// we need it with getInfoPanelHTML()
-//~ function insertInfoPanels(){
- //~ var panels = SunstoneCfg["info_panels"];
- //~ tabs = null;
- //~ //For each defined dialog
- //~ for (panel in panels) {
- //~ addInfoPanel(panel);
- //~ }
-//~ }
-//~
-//~ function addInfoPanel(name){
- //~ var tabs = SunstoneCfg["info_panels"][name];
- //~ $('#info_panels').append('');
- //~ for (tab in tabs){
- //~ addInfoPanelTab(name,tab);
- //~ }
- //~ //at this point jquery tabs structure is ready, so we enable it
- //~ $('div#'+name).tabs();
-//~ }
-//~
-//~ function refreshInfoPanel(name){
- //~ $('#info_panels div#'+name).tabs("destroy");
- //~ $('#info_panels div#'+name).remove();
- //~ $('#info_panels').append('');
- //~ var tabs = SunstoneCfg["info_panels"][name];
- //~ for (tab in tabs){
- //~ addInfoPanelTab(name,tab);
- //~ }
- //~ //at this point jquery tabs structure is ready, so we enable it
- //~ $('div#'+name).tabs();
-//~ }
-//~
-//~ function addInfoPanelTab(panel_name,tab_name){
- //~ var tab = SunstoneCfg["info_panels"][panel_name][tab_name];
- //~ if ( !$('div#'+panel_name+' ul').length ) {
- //~ $('div#'+panel_name).prepend('
');
-//~ }
-//~
-
-
//Tries to refresh a tab content if it is somewhere in the DOM
+//Useful for plugins wanting to update certain information.
function refreshInfoPanelTab(panel_name,tab_name){
- var tab = SunstoneCfg["info_panels"][panel_name][tab_name];
- $('div#'+panel_name+' div#'+tab_name).html(tab.content);
+ var tab_content = SunstoneCfg["info_panels"][panel_name][tab_name].content;
+ $('div#'+panel_name+' div#'+tab_name).html(tab_content);
}
-//Converts selects into buttons which show a of actions when clicked
+//Converts selects into buttons which show a list of actions when
+//clicked. This lists have two parts, one for the last action run, and
+//another containing a list of actions that can be folded/unfolded.
function initListButtons(){
//for each multi_action select
$('.multi_action_slct').each(function(){
//prepare replacement buttons
- buttonset = $('Previous action').button();
+ var buttonset = $('Previous action').button();
button1.attr("disabled","disabled");
- button2 = $('').button({
+ var button2 = $('').button({
text:false,
icons: { primary: "ui-icon-triangle-1-s" }
});
@@ -452,12 +472,12 @@ function initListButtons(){
buttonset.buttonset();
//prepare list
- options = $('option', $(this));
- list = $('
');
+ var options = $('option', $(this));
+ var list = $('
');
$.each(options,function(){
- classes = $(this).attr("class");
- item = $('');
- a = $(''+$(this).text()+'');
+ var classes = $(this).attr("class");
+ var item = $('');
+ var a = $(''+$(this).text()+'');
a.val($(this).val());
item.html(a);
list.append(item);
@@ -476,12 +496,12 @@ function initListButtons(){
});
- //listen for events on this buttons and list
+ //below the listeners for events on these buttons and list
//enable run the last action button
$('.action_list li a').click(function(){
//enable run last action button
- prev_action_button = $('.last_action_button',$(this).parents('.action_blocks'));
+ var prev_action_button = $('.last_action_button',$(this).parents('.action_blocks'));
prev_action_button.val($(this).val());
prev_action_button.removeClass("confirm_with_select_button");
prev_action_button.removeClass("confirm_button");
@@ -506,26 +526,15 @@ function initListButtons(){
});
}
-//Sets up all the "+ New Thing" dialogs.
-function setupCreateDialogs(){
-// createHostDialog();
-// createClusterDialog();
-// createVMachineDialog();
-// createVNetworkDialog();
-// createUserDialog();
-// createImageDialog();
-
- //Todo listener on "create" class to trigger the right dialog.
-}
-
-//Adds the dialogs bodies
+//Prepares the standard confirm dialogs
function setupConfirmDialogs(){
- //confirm
+ //add div to the main body if it isn't present.
if (!($('div#confirm_dialog').length)){
$('div#dialogs').append('');
};
+ //add the HTML with the standard question and buttons.
$('div#confirm_dialog').html(
'');
- //prepare the jquery dialog
+
+ //prepare the jquery dialog
$('div#confirm_with_select_dialog').dialog({
resizable:false,
modal:true,
@@ -575,12 +587,16 @@ function setupConfirmDialogs(){
$('div#confirm_with_select_dialog button').button();
+ //if a cancel button is pressed, we close the dialog.
$('button.confirm_cancel').click(function(){
$('div#confirm_with_select_dialog').dialog("close");
$('div#confirm_dialog').dialog("close");
return false;
});
+ //when we proceed with a "confirm with select" we need to
+ //find out if we are running an action with a parametre on a datatable
+ //items or if its just an action
$('button#confirm_with_select_proceed').click(function(){
var value = $(this).val();
var action = SunstoneCfg["actions"][value];
@@ -588,7 +604,7 @@ function setupConfirmDialogs(){
if (!action) { notifyError("Action "+value+" not defined."); return false;};
switch (action.type){
case "multiple": //find the datatable
- table = SunstoneCfg["actions"][value].dataTable();
+ var table = SunstoneCfg["actions"][value].dataTable();
Sunstone.runActionOnDatatableNodes(value,table,param);
break;
default:
@@ -601,6 +617,11 @@ function setupConfirmDialogs(){
}
+//Popup a confirmation dialog.
+//In order to find out the dialog action and
+//tip for the user we need to access the clicked button
+//configuration. We do this by discovering the name of the parent tab
+//and with the value of the clicked element.
function popUpConfirmDialog(target_elem){
var value = $(target_elem).val();
var tab_id = $(target_elem).parents('.tab').attr('id');
@@ -611,6 +632,9 @@ function popUpConfirmDialog(target_elem){
$('div#confirm_dialog').dialog("open");
}
+//Same as previous. This time we need as well to access the updated
+//select list, which is done through the pointer of found in the
+//config of the button (a function returning the select options).
function popUpConfirmWithSelectDialog(target_elem){
var value = $(target_elem).val();
var tab_id = $(target_elem).parents('.tab').attr('id');
@@ -622,8 +646,6 @@ function popUpConfirmWithSelectDialog(target_elem){
$('button#confirm_with_select_proceed').val(value);
$('div#confirm_with_select_dialog').dialog("open");
-
-
}