Format JS

This commit is contained in:
Ian Duffy 2013-07-18 15:39:28 +01:00 committed by Sebastien Goasguen
parent dfa612d1fe
commit ad69bc8da3
62 changed files with 64071 additions and 59088 deletions

File diff suppressed because it is too large Load Diff

View File

@ -15,169 +15,193 @@
// specific language governing permissions and limitations // specific language governing permissions and limitations
// under the License. // under the License.
(function(cloudStack) { (function(cloudStack) {
cloudStack.sections.affinityGroups = { cloudStack.sections.affinityGroups = {
title: 'label.affinity.groups', title: 'label.affinity.groups',
listView: { listView: {
id: 'affinityGroups', id: 'affinityGroups',
fields: {
name: { label: 'label.name' },
type: { label: 'label.type' }
},
dataProvider: function(args) {
var data = {};
if (args.context != null) {
if ("instances" in args.context) {
$.extend(data, {
virtualmachineid: args.context.instances[0].id
});
}
}
$.ajax({
url: createURL('listAffinityGroups'),
data: data,
success: function(json) {
var items = json.listaffinitygroupsresponse.affinitygroup;
args.response.success({data: items});
}
});
},
actions: {
add: {
label: 'label.add.affinity.group',
messages: {
notification: function(args) {
return 'label.add.affinity.group';
}
},
createForm: {
title: 'label.add.affinity.group',
fields: { fields: {
name: { name: {
label: 'label.name', label: 'label.name'
validation: { required: true } },
}, type: {
description: { label: 'label.type'
label: 'label.description'
},
type: {
label: 'label.type',
select: function(args) {
$.ajax({
url: createURL('listAffinityGroupTypes'),
success: function(json) {
var types = [];
var items = json.listaffinitygrouptypesresponse.affinityGroupType;
if(items != null) {
for(var i = 0; i < items.length; i++) {
types.push({id: items[i].type, description: items[i].type});
}
}
args.response.success({data: types})
}
});
} }
}
}
},
action: function(args) {
var data = {
name: args.data.name,
type: args.data.type
};
if(args.data.description != null && args.data.description.length > 0)
$.extend(data, {description: args.data.description});
$.ajax({
url: createURL('createAffinityGroup'),
data: data,
success: function(json) {
var jid = json.createaffinitygroupresponse.jobid;
args.response.success(
{_custom:
{jobId: jid,
getUpdatedItem: function(json) {
return json.queryasyncjobresultresponse.jobresult.affinitygroup;
}
}
}
);
}
});
},
notification: {
poll: pollAsyncJobResult
}
}
},
detailView: {
actions: {
remove: {
label: 'label.delete.affinity.group',
messages: {
confirm: function(args) {
return 'message.delete.affinity.group';
},
notification: function(args) {
return 'label.delete.affinity.group';
}
}, },
action: function(args) {
$.ajax({
url: createURL('deleteAffinityGroup'),
data: {
id: args.context.affinityGroups[0].id
},
success: function(json) {
var jid = json.deleteaffinitygroupresponse.jobid;
args.response.success({
_custom:{
jobId: jid
}
});
}
});
},
notification: {
poll: pollAsyncJobResult
}
}
},
viewAll: { path: 'instances', label: 'label.instances' },
tabs: {
details: {
title: 'label.details',
fields: [
{
name: { label: 'label.name' }
},
{
description: { label: 'label.description' },
type: { label: 'label.type' },
id: { label: 'label.id' }
}
],
dataProvider: function(args) { dataProvider: function(args) {
$.ajax({ var data = {};
url: createURL('listAffinityGroups'), if (args.context != null) {
data: { if ("instances" in args.context) {
id: args.context.affinityGroups[0].id $.extend(data, {
}, virtualmachineid: args.context.instances[0].id
success: function(json) { });
var item = json.listaffinitygroupsresponse.affinitygroup[0]; }
args.response.success({data: item}); }
} $.ajax({
}); url: createURL('listAffinityGroups'),
data: data,
success: function(json) {
var items = json.listaffinitygroupsresponse.affinitygroup;
args.response.success({
data: items
});
}
});
},
actions: {
add: {
label: 'label.add.affinity.group',
messages: {
notification: function(args) {
return 'label.add.affinity.group';
}
},
createForm: {
title: 'label.add.affinity.group',
fields: {
name: {
label: 'label.name',
validation: {
required: true
}
},
description: {
label: 'label.description'
},
type: {
label: 'label.type',
select: function(args) {
$.ajax({
url: createURL('listAffinityGroupTypes'),
success: function(json) {
var types = [];
var items = json.listaffinitygrouptypesresponse.affinityGroupType;
if (items != null) {
for (var i = 0; i < items.length; i++) {
types.push({
id: items[i].type,
description: items[i].type
});
}
}
args.response.success({
data: types
})
}
});
}
}
}
},
action: function(args) {
var data = {
name: args.data.name,
type: args.data.type
};
if (args.data.description != null && args.data.description.length > 0)
$.extend(data, {
description: args.data.description
});
$.ajax({
url: createURL('createAffinityGroup'),
data: data,
success: function(json) {
var jid = json.createaffinitygroupresponse.jobid;
args.response.success({
_custom: {
jobId: jid,
getUpdatedItem: function(json) {
return json.queryasyncjobresultresponse.jobresult.affinitygroup;
}
}
});
}
});
},
notification: {
poll: pollAsyncJobResult
}
}
},
detailView: {
actions: {
remove: {
label: 'label.delete.affinity.group',
messages: {
confirm: function(args) {
return 'message.delete.affinity.group';
},
notification: function(args) {
return 'label.delete.affinity.group';
}
},
action: function(args) {
$.ajax({
url: createURL('deleteAffinityGroup'),
data: {
id: args.context.affinityGroups[0].id
},
success: function(json) {
var jid = json.deleteaffinitygroupresponse.jobid;
args.response.success({
_custom: {
jobId: jid
}
});
}
});
},
notification: {
poll: pollAsyncJobResult
}
}
},
viewAll: {
path: 'instances',
label: 'label.instances'
},
tabs: {
details: {
title: 'label.details',
fields: [{
name: {
label: 'label.name'
}
}, {
description: {
label: 'label.description'
},
type: {
label: 'label.type'
},
id: {
label: 'label.id'
}
}],
dataProvider: function(args) {
$.ajax({
url: createURL('listAffinityGroups'),
data: {
id: args.context.affinityGroups[0].id
},
success: function(json) {
var item = json.listaffinitygroupsresponse.affinitygroup[0];
args.response.success({
data: item
});
}
});
}
}
}
} }
}
} }
} };
}
};
})(cloudStack); })(cloudStack);

File diff suppressed because it is too large Load Diff

View File

@ -14,7 +14,13 @@
// KIND, either express or implied. See the License for the // KIND, either express or implied. See the License for the
// specific language governing permissions and limitations // specific language governing permissions and limitations
// under the License. // under the License.
$.urlParam = function(name){ var results = new RegExp('[\\?&]' + name + '=([^&#]*)').exec(window.location.href); if (!results) { return 0; } return results[1] || 0;} $.urlParam = function(name) {
var results = new RegExp('[\\?&]' + name + '=([^&#]*)').exec(window.location.href);
if (!results) {
return 0;
}
return results[1] || 0;
}
/* /*
This file is meant to help with implementing single signon integration. If you are using the This file is meant to help with implementing single signon integration. If you are using the
@ -26,12 +32,13 @@ This callback function is called when either the session has timed out for the u
the session ID has been changed (i.e. another user logging into the UI via a different tab), the session ID has been changed (i.e. another user logging into the UI via a different tab),
or it's the first time the user has come to this page. or it's the first time the user has come to this page.
*/ */
function onLogoutCallback() { function onLogoutCallback() {
g_loginResponse = null; //clear single signon variable g_loginResponse g_loginResponse = null; //clear single signon variable g_loginResponse
return true; // return true means the login page will show return true; // return true means the login page will show
/* /*
window.location.replace("http://www.google.com"); //redirect to a different location window.location.replace("http://www.google.com"); //redirect to a different location
return false; //return false means it will stay in the location window.location.replace() sets it to (i.e. "http://www.google.com") return false; //return false means it will stay in the location window.location.replace() sets it to (i.e. "http://www.google.com")
*/ */
@ -50,29 +57,27 @@ Below is a sample login attempt
*/ */
var clientApiUrl = "/client/api"; var clientApiUrl = "/client/api";
var clientConsoleUrl = "/client/console"; var clientConsoleUrl = "/client/console";
$(document).ready(function() { $(document).ready(function() {
var url = $.urlParam("loginUrl"); var url = $.urlParam("loginUrl");
if (url != undefined && url != null && url.length > 0) { if (url != undefined && url != null && url.length > 0) {
url = unescape(clientApiUrl+"?"+url); url = unescape(clientApiUrl + "?" + url);
$.ajax({ $.ajax({
url: url, url: url,
dataType: "json", dataType: "json",
async: false, async: false,
success: function(json) { success: function(json) {
g_loginResponse = json.loginresponse; g_loginResponse = json.loginresponse;
}, },
error: function() { error: function() {
onLogoutCallback(); onLogoutCallback();
// This means the login failed. You should redirect to your login page. // This means the login failed. You should redirect to your login page.
}, },
beforeSend: function(XMLHttpRequest) { beforeSend: function(XMLHttpRequest) {
return true; return true;
} }
}); });
} }
}); });

View File

@ -15,480 +15,518 @@
// specific language governing permissions and limitations // specific language governing permissions and limitations
// under the License. // under the License.
(function(cloudStack, $) { (function(cloudStack, $) {
$.extend(cloudStack, { $.extend(cloudStack, {
home: 'dashboard', home: 'dashboard',
sectionPreFilter: function(args) { sectionPreFilter: function(args) {
var sections = []; var sections = [];
if(isAdmin()) { if (isAdmin()) {
sections = ["dashboard", "instances", "storage", "network", "templates", "accounts", "domains", "events", "system", "global-settings", "configuration", "projects", "regions", "affinityGroups"]; sections = ["dashboard", "instances", "storage", "network", "templates", "accounts", "domains", "events", "system", "global-settings", "configuration", "projects", "regions", "affinityGroups"];
} } else if (isDomainAdmin()) {
else if(isDomainAdmin()) { sections = ["dashboard", "instances", "storage", "network", "templates", "accounts", "domains", "events", "projects", "regions", "affinityGroups"];
sections = ["dashboard", "instances", "storage", "network", "templates", "accounts", "domains", "events", "projects", "regions", "affinityGroups"]; } else if (g_userProjectsEnabled) {
} sections = ["dashboard", "instances", "storage", "network", "templates", "accounts", "events", "projects", "regions", "affinityGroups"];
else if (g_userProjectsEnabled) { } else { //normal user
sections = ["dashboard", "instances", "storage", "network", "templates", "accounts", "events", "projects", "regions", "affinityGroups"]; sections = ["dashboard", "instances", "storage", "network", "templates", "accounts", "events", "regions", "affinityGroups"];
}
else { //normal user
sections = ["dashboard", "instances", "storage", "network", "templates", "accounts", "events", "regions", "affinityGroups"];
}
if (cloudStack.plugins.length) {
sections.push('plugins');
}
return sections;
},
sections: {
/**
* Dashboard
*/
dashboard: {},
instances: {},
affinityGroups: {},
storage: {},
network: {},
templates: {},
events: {},
projects: {},
accounts: {},
domains: {}, //domain-admin and root-admin only
regions: {}, //root-admin only
system: {}, //root-admin only
'global-settings': {}, //root-admin only
configuration: {}, //root-admin only
plugins: {}
}
});
$(window).bind('cloudStack.pluginReady', function() {
// Get language
g_lang = $.cookie('lang') ? $.cookie('lang') : 'en';
/**
* Generic error handling
*/
$.ajaxSetup({
url: clientApiUrl,
async: true,
dataType: 'json',
cache: false,
error: function(data) {
var clickAction = false;
if (isValidJsonString(data.responseText)) {
var json = JSON.parse(data.responseText);
if (json != null) {
var property;
for(property in json) {}
var errorObj = json[property];
if(errorObj.errorcode == 401 && errorObj.errortext == "unable to verify user credentials and/or request signature") {
clickAction = function() {
$('#user-options a').eq(0).trigger('click');
};
} }
}
if (cloudStack.plugins.length) {
sections.push('plugins');
}
return sections;
},
sections: {
/**
* Dashboard
*/
dashboard: {},
instances: {},
affinityGroups: {},
storage: {},
network: {},
templates: {},
events: {},
projects: {},
accounts: {},
domains: {}, //domain-admin and root-admin only
regions: {}, //root-admin only
system: {}, //root-admin only
'global-settings': {}, //root-admin only
configuration: {}, //root-admin only
plugins: {}
} }
cloudStack.dialog.notice({ message: parseXMLHttpResponse(data), clickAction: clickAction });
},
beforeSend: function(XMLHttpRequest) {
if (g_mySession == $.cookie("JSESSIONID")) {
return true;
}
else {
var clickAction = function() {
$('#user-options a').eq(0).trigger('click');
};
cloudStack.dialog.notice({ message: _l('label.session.expired'), clickAction: clickAction });
return false;
}
}
}); });
var $container = $('#cloudStack3-container'); $(window).bind('cloudStack.pluginReady', function() {
// Get language
g_lang = $.cookie('lang') ? $.cookie('lang') : 'en';
var loginArgs = { /**
$container: $container, * Generic error handling
*/
// Use this for checking the session, to bypass login screen $.ajaxSetup({
bypassLoginCheck: function(args) { //determine to show or bypass login screen url: clientApiUrl,
if (g_loginResponse == null) { //show login screen async: true,
/* dataType: 'json',
cache: false,
error: function(data) {
var clickAction = false;
if (isValidJsonString(data.responseText)) {
var json = JSON.parse(data.responseText);
if (json != null) {
var property;
for (property in json) {}
var errorObj = json[property];
if (errorObj.errorcode == 401 && errorObj.errortext == "unable to verify user credentials and/or request signature") {
clickAction = function() {
$('#user-options a').eq(0).trigger('click');
};
}
}
}
cloudStack.dialog.notice({
message: parseXMLHttpResponse(data),
clickAction: clickAction
});
},
beforeSend: function(XMLHttpRequest) {
if (g_mySession == $.cookie("JSESSIONID")) {
return true;
} else {
var clickAction = function() {
$('#user-options a').eq(0).trigger('click');
};
cloudStack.dialog.notice({
message: _l('label.session.expired'),
clickAction: clickAction
});
return false;
}
}
});
var $container = $('#cloudStack3-container');
var loginArgs = {
$container: $container,
// Use this for checking the session, to bypass login screen
bypassLoginCheck: function(args) { //determine to show or bypass login screen
if (g_loginResponse == null) { //show login screen
/*
but if this is a 2nd browser window (of the same domain), login screen still won't show because $.cookie('sessionKey') is valid for 2nd browser window (of the same domain) as well. but if this is a 2nd browser window (of the same domain), login screen still won't show because $.cookie('sessionKey') is valid for 2nd browser window (of the same domain) as well.
i.e. calling listCapabilities API with g_sessionKey from $.cookie('sessionKey') will succeed, i.e. calling listCapabilities API with g_sessionKey from $.cookie('sessionKey') will succeed,
then userValid will be set to true, then an user object (instead of "false") will be returned, then login screen will be bypassed. then userValid will be set to true, then an user object (instead of "false") will be returned, then login screen will be bypassed.
*/ */
g_mySession = $.cookie('JSESSIONID'); g_mySession = $.cookie('JSESSIONID');
g_sessionKey = $.cookie('sessionKey'); g_sessionKey = $.cookie('sessionKey');
g_role = $.cookie('role'); g_role = $.cookie('role');
g_username = $.cookie('username'); g_username = $.cookie('username');
g_userid = $.cookie('userid'); g_userid = $.cookie('userid');
g_account = $.cookie('account'); g_account = $.cookie('account');
g_domainid = $.cookie('domainid'); g_domainid = $.cookie('domainid');
g_userfullname = $.cookie('userfullname'); g_userfullname = $.cookie('userfullname');
g_timezone = $.cookie('timezone'); g_timezone = $.cookie('timezone');
if($.cookie('timezoneoffset') != null) if ($.cookie('timezoneoffset') != null)
g_timezoneoffset = isNaN($.cookie('timezoneoffset'))? null: parseFloat($.cookie('timezoneoffset')); g_timezoneoffset = isNaN($.cookie('timezoneoffset')) ? null : parseFloat($.cookie('timezoneoffset'));
else else
g_timezoneoffset = null; g_timezoneoffset = null;
} } else { //single-sign-on (bypass login screen)
else { //single-sign-on (bypass login screen) g_mySession = $.cookie('JSESSIONID');
g_mySession = $.cookie('JSESSIONID'); g_sessionKey = encodeURIComponent(g_loginResponse.sessionkey);
g_sessionKey = encodeURIComponent(g_loginResponse.sessionkey); g_role = g_loginResponse.type;
g_role = g_loginResponse.type; g_username = g_loginResponse.username;
g_username = g_loginResponse.username; g_userid = g_loginResponse.userid;
g_userid = g_loginResponse.userid; g_account = g_loginResponse.account;
g_account = g_loginResponse.account; g_domainid = g_loginResponse.domainid;
g_domainid = g_loginResponse.domainid; g_userfullname = g_loginResponse.firstname + ' ' + g_loginResponse.lastname;
g_userfullname = g_loginResponse.firstname + ' ' + g_loginResponse.lastname; g_timezone = g_loginResponse.timezone;
g_timezone = g_loginResponse.timezone; if (g_loginResponse.timezoneoffset != null)
if(g_loginResponse.timezoneoffset != null) g_timezoneoffset = isNaN(g_loginResponse.timezoneoffset) ? null : parseFloat(g_loginResponse.timezoneoffset);
g_timezoneoffset = isNaN(g_loginResponse.timezoneoffset)? null: parseFloat(g_loginResponse.timezoneoffset); else
else g_timezoneoffset = null;
g_timezoneoffset = null;
}
var userValid = false;
$.ajax({
url: createURL("listCapabilities"),
dataType: "json",
async: false,
success: function(json) {
g_capabilities = json.listcapabilitiesresponse.capability;
$.cookie('capabilities', g_capabilities, { expires: 1});
g_supportELB = json.listcapabilitiesresponse.capability.supportELB.toString(); //convert boolean to string if it's boolean
$.cookie('supportELB', g_supportELB, { expires: 1});
if (json.listcapabilitiesresponse.capability.userpublictemplateenabled != null) {
g_userPublicTemplateEnabled = json.listcapabilitiesresponse.capability.userpublictemplateenabled.toString(); //convert boolean to string if it's boolean
$.cookie('userpublictemplateenabled', g_userPublicTemplateEnabled, { expires: 1});
}
g_userProjectsEnabled = json.listcapabilitiesresponse.capability.allowusercreateprojects;
$.cookie('userProjectsEnabled', g_userProjectsEnabled, { expires: 1 });
g_cloudstackversion = json.listcapabilitiesresponse.capability.cloudstackversion;
if(json.listcapabilitiesresponse.capability.apilimitinterval != null && json.listcapabilitiesresponse.capability.apilimitmax != null) {
var intervalLimit = ((json.listcapabilitiesresponse.capability.apilimitinterval * 1000) / json.listcapabilitiesresponse.capability.apilimitmax ) * 3; //multiply 3 to be on safe side
//intervalLimit = 9999; //this line is for testing only, comment it before check in
if(intervalLimit > g_queryAsyncJobResultInterval)
g_queryAsyncJobResultInterval = intervalLimit;
}
userValid = true;
},
error: function(xmlHTTP) { //override default error handling, do nothing instead of showing error "unable to verify user credentials" on login screen
},
beforeSend : function(XMLHttpResponse) {
return true;
}
});
if (userValid && isAdmin()) {
$.ajax({
url: createURL("listImageStores"),
data: {
provider: 'Swift'
},
async: false,
success: function(json) {
var items = json.listimagestoreresponse.imagestore;
if(items != null && items.length > 0)
havingSwift = true;
}
});
if (havingSwift == false) {
$.ajax({
url: createURL("listImageStores"),
data: {
provider: 'S3'
},
async: false,
success: function(json) {
var items = json.listimagestoreresponse.imagestore;
if (items != null && items.length > 0) {
havingS3 = true;
}
}
});
}
} else {
havingSwift = false;
havingS3 = false;
}
return userValid ? {
user: {
userid: g_userid,
username: g_username,
account: g_account,
name: g_userfullname,
role: g_role,
domainid: g_domainid
}
} : false;
return testAddUser;
},
// Actual login process, via form
loginAction: function(args) {
var array1 = [];
array1.push("&username=" + encodeURIComponent(args.data.username));
var password;
if (md5HashedLogin)
password = $.md5(args.data.password);
else
password = todb(args.data.password);
array1.push("&password=" + password);
var domain;
if(args.data.domain != null && args.data.domain.length > 0) {
if (args.data.domain.charAt(0) != "/")
domain = "/" + args.data.domain;
else
domain = args.data.domain;
array1.push("&domain=" + encodeURIComponent(domain));
}
else {
array1.push("&domain=" + encodeURIComponent("/"));
}
var loginCmdText = array1.join("");
$.ajax({
type: "POST",
data: "command=login" + loginCmdText + "&response=json",
dataType: "json",
async: false,
success: function(json) {
var loginresponse = json.loginresponse;
g_mySession = $.cookie('JSESSIONID');
g_sessionKey = encodeURIComponent(loginresponse.sessionkey);
g_role = loginresponse.type;
g_username = loginresponse.username;
g_userid = loginresponse.userid;
g_account = loginresponse.account;
g_domainid = loginresponse.domainid;
g_timezone = loginresponse.timezone;
g_timezoneoffset = loginresponse.timezoneoffset;
g_userfullname = loginresponse.firstname + ' ' + loginresponse.lastname;
$.cookie('sessionKey', g_sessionKey, { expires: 1});
$.cookie('username', g_username, { expires: 1});
$.cookie('account', g_account, { expires: 1});
$.cookie('domainid', g_domainid, { expires: 1});
$.cookie('role', g_role, { expires: 1});
$.cookie('timezoneoffset', g_timezoneoffset, { expires: 1});
$.cookie('timezone', g_timezone, { expires: 1});
$.cookie('userfullname', g_userfullname, { expires: 1 });
$.cookie('userid', g_userid, { expires: 1 });
$.ajax({
url: createURL("listCapabilities"),
dataType: "json",
async: false,
success: function(json) {
g_capabilities = json.listcapabilitiesresponse.capability;
$.cookie('capabilities', g_capabilities, { expires: 1});
g_supportELB = json.listcapabilitiesresponse.capability.supportELB.toString(); //convert boolean to string if it's boolean
$.cookie('supportELB', g_supportELB, { expires: 1});
if (json.listcapabilitiesresponse.capability.userpublictemplateenabled != null) {
g_userPublicTemplateEnabled = json.listcapabilitiesresponse.capability.userpublictemplateenabled.toString(); //convert boolean to string if it's boolean
$.cookie('userpublictemplateenabled', g_userPublicTemplateEnabled, { expires: 1});
} }
g_userProjectsEnabled = json.listcapabilitiesresponse.capability.allowusercreateprojects; var userValid = false;
$.cookie('userProjectsEnabled', g_userProjectsEnabled, { expires: 1 });
g_cloudstackversion = json.listcapabilitiesresponse.capability.cloudstackversion;
if(json.listcapabilitiesresponse.capability.apilimitinterval != null && json.listcapabilitiesresponse.capability.apilimitmax != null) {
var intervalLimit = ((json.listcapabilitiesresponse.capability.apilimitinterval * 1000) / json.listcapabilitiesresponse.capability.apilimitmax ) * 3; //multiply 3 to be on safe side
//intervalLimit = 8888; //this line is for testing only, comment it before check in
if(intervalLimit > g_queryAsyncJobResultInterval)
g_queryAsyncJobResultInterval = intervalLimit;
}
args.response.success({
data: {
user: $.extend(true, {}, loginresponse, {
name: loginresponse.firstname + ' ' + loginresponse.lastname,
role: loginresponse.type == 1 ? 'admin' : 'user',
type: loginresponse.type
})
}
});
},
error: function(xmlHTTP) {
args.response.error();
}
});
if (isAdmin()) {
$.ajax({
url: createURL("listImageStores"),
data:{
provider: 'Swift'
},
async: false,
success: function(json) {
var items = json.listimagestoreresponse.imagestore;
if(items != null && items.length > 0)
havingSwift = true;
}
});
if (havingSwift = false) {
$.ajax({ $.ajax({
url: createURL("listImageStores"), url: createURL("listCapabilities"),
data: { dataType: "json",
provider: 'S3' async: false,
}, success: function(json) {
async: false, g_capabilities = json.listcapabilitiesresponse.capability;
success: function(json) { $.cookie('capabilities', g_capabilities, {
var items = json.listimagestoreresponse.imagestore; expires: 1
if (items != null && items.length > 0) { });
havingS3 = true;
g_supportELB = json.listcapabilitiesresponse.capability.supportELB.toString(); //convert boolean to string if it's boolean
$.cookie('supportELB', g_supportELB, {
expires: 1
});
if (json.listcapabilitiesresponse.capability.userpublictemplateenabled != null) {
g_userPublicTemplateEnabled = json.listcapabilitiesresponse.capability.userpublictemplateenabled.toString(); //convert boolean to string if it's boolean
$.cookie('userpublictemplateenabled', g_userPublicTemplateEnabled, {
expires: 1
});
}
g_userProjectsEnabled = json.listcapabilitiesresponse.capability.allowusercreateprojects;
$.cookie('userProjectsEnabled', g_userProjectsEnabled, {
expires: 1
});
g_cloudstackversion = json.listcapabilitiesresponse.capability.cloudstackversion;
if (json.listcapabilitiesresponse.capability.apilimitinterval != null && json.listcapabilitiesresponse.capability.apilimitmax != null) {
var intervalLimit = ((json.listcapabilitiesresponse.capability.apilimitinterval * 1000) / json.listcapabilitiesresponse.capability.apilimitmax) * 3; //multiply 3 to be on safe side
//intervalLimit = 9999; //this line is for testing only, comment it before check in
if (intervalLimit > g_queryAsyncJobResultInterval)
g_queryAsyncJobResultInterval = intervalLimit;
}
userValid = true;
},
error: function(xmlHTTP) { //override default error handling, do nothing instead of showing error "unable to verify user credentials" on login screen
},
beforeSend: function(XMLHttpResponse) {
return true;
} }
}
}); });
}
} else {
havingSwift = false;
havingS3 = false;
}
// Get project configuration if (userValid && isAdmin()) {
// TEMPORARY -- replace w/ output of capability response, etc., once implemented $.ajax({
window.g_projectsInviteRequired = false; url: createURL("listImageStores"),
}, data: {
error: function(XMLHttpRequest) { provider: 'Swift'
var errorMsg = parseXMLHttpResponse(XMLHttpRequest); },
if(errorMsg.length == 0 && XMLHttpRequest.status == 0) async: false,
errorMsg = dictionary['error.unable.to.reach.management.server']; success: function(json) {
else var items = json.listimagestoreresponse.imagestore;
errorMsg = _l('error.invalid.username.password'); //override error message if (items != null && items.length > 0)
args.response.error(errorMsg); havingSwift = true;
}, }
beforeSend : function(XMLHttpResponse) { });
return true; if (havingSwift == false) {
} $.ajax({
}); url: createURL("listImageStores"),
}, data: {
provider: 'S3'
logoutAction: function(args) { },
$.ajax({ async: false,
url: createURL('logout'), success: function(json) {
async: false, var items = json.listimagestoreresponse.imagestore;
success: function() { if (items != null && items.length > 0) {
g_mySession = null; havingS3 = true;
g_sessionKey = null; }
g_username = null; }
g_account = null; });
g_domainid = null;
g_timezoneoffset = null;
g_timezone = null;
g_supportELB = null;
g_loginCmdText = null;
$.cookie('JSESSIONID', null);
$.cookie('sessionKey', null);
$.cookie('username', null);
$.cookie('account', null);
$.cookie('domainid', null);
$.cookie('role', null);
$.cookie('networktype', null);
$.cookie('timezoneoffset', null);
$.cookie('timezone', null);
$.cookie('supportELB', null);
if(onLogoutCallback()) { //onLogoutCallback() will set g_loginResponse(single-sign-on variable) to null, then bypassLoginCheck() will show login screen.
document.location.reload(); //when onLogoutCallback() returns true, reload the current document.
}
},
error: function() {
if(onLogoutCallback()) { //onLogoutCallback() will set g_loginResponse(single-sign-on variable) to null, then bypassLoginCheck() will show login screen.
document.location.reload(); //when onLogoutCallback() returns true, reload the current document.
}
},
beforeSend : function(XMLHttpResponse) {
return true;
}
});
},
// Show cloudStack main UI widget
complete: function(args) {
var context = {
users: [args.user]
};
var cloudStackArgs = $.extend(cloudStack, {
context: context
});
// Check to invoke install wizard
cloudStack.installWizard.check({
context: context,
response: {
success: function(args) {
if (args.doInstall && isAdmin()) {
var initInstallWizard = function() {
cloudStack.uiCustom.installWizard({
$container: $container,
context: context,
complete: function() {
// Show cloudStack main UI
$container.cloudStack($.extend(cloudStackArgs, { hasLogo: false }));
} }
}); } else {
havingSwift = false;
havingS3 = false;
}
return userValid ? {
user: {
userid: g_userid,
username: g_username,
account: g_account,
name: g_userfullname,
role: g_role,
domainid: g_domainid
}
} : false;
return testAddUser;
},
// Actual login process, via form
loginAction: function(args) {
var array1 = [];
array1.push("&username=" + encodeURIComponent(args.data.username));
var password;
if (md5HashedLogin)
password = $.md5(args.data.password);
else
password = todb(args.data.password);
array1.push("&password=" + password);
var domain;
if (args.data.domain != null && args.data.domain.length > 0) {
if (args.data.domain.charAt(0) != "/")
domain = "/" + args.data.domain;
else
domain = args.data.domain;
array1.push("&domain=" + encodeURIComponent(domain));
} else {
array1.push("&domain=" + encodeURIComponent("/"));
}
var loginCmdText = array1.join("");
$.ajax({
type: "POST",
data: "command=login" + loginCmdText + "&response=json",
dataType: "json",
async: false,
success: function(json) {
var loginresponse = json.loginresponse;
g_mySession = $.cookie('JSESSIONID');
g_sessionKey = encodeURIComponent(loginresponse.sessionkey);
g_role = loginresponse.type;
g_username = loginresponse.username;
g_userid = loginresponse.userid;
g_account = loginresponse.account;
g_domainid = loginresponse.domainid;
g_timezone = loginresponse.timezone;
g_timezoneoffset = loginresponse.timezoneoffset;
g_userfullname = loginresponse.firstname + ' ' + loginresponse.lastname;
$.cookie('sessionKey', g_sessionKey, {
expires: 1
});
$.cookie('username', g_username, {
expires: 1
});
$.cookie('account', g_account, {
expires: 1
});
$.cookie('domainid', g_domainid, {
expires: 1
});
$.cookie('role', g_role, {
expires: 1
});
$.cookie('timezoneoffset', g_timezoneoffset, {
expires: 1
});
$.cookie('timezone', g_timezone, {
expires: 1
});
$.cookie('userfullname', g_userfullname, {
expires: 1
});
$.cookie('userid', g_userid, {
expires: 1
});
$.ajax({
url: createURL("listCapabilities"),
dataType: "json",
async: false,
success: function(json) {
g_capabilities = json.listcapabilitiesresponse.capability;
$.cookie('capabilities', g_capabilities, {
expires: 1
});
g_supportELB = json.listcapabilitiesresponse.capability.supportELB.toString(); //convert boolean to string if it's boolean
$.cookie('supportELB', g_supportELB, {
expires: 1
});
if (json.listcapabilitiesresponse.capability.userpublictemplateenabled != null) {
g_userPublicTemplateEnabled = json.listcapabilitiesresponse.capability.userpublictemplateenabled.toString(); //convert boolean to string if it's boolean
$.cookie('userpublictemplateenabled', g_userPublicTemplateEnabled, {
expires: 1
});
}
g_userProjectsEnabled = json.listcapabilitiesresponse.capability.allowusercreateprojects;
$.cookie('userProjectsEnabled', g_userProjectsEnabled, {
expires: 1
});
g_cloudstackversion = json.listcapabilitiesresponse.capability.cloudstackversion;
if (json.listcapabilitiesresponse.capability.apilimitinterval != null && json.listcapabilitiesresponse.capability.apilimitmax != null) {
var intervalLimit = ((json.listcapabilitiesresponse.capability.apilimitinterval * 1000) / json.listcapabilitiesresponse.capability.apilimitmax) * 3; //multiply 3 to be on safe side
//intervalLimit = 8888; //this line is for testing only, comment it before check in
if (intervalLimit > g_queryAsyncJobResultInterval)
g_queryAsyncJobResultInterval = intervalLimit;
}
args.response.success({
data: {
user: $.extend(true, {}, loginresponse, {
name: loginresponse.firstname + ' ' + loginresponse.lastname,
role: loginresponse.type == 1 ? 'admin' : 'user',
type: loginresponse.type
})
}
});
},
error: function(xmlHTTP) {
args.response.error();
}
});
if (isAdmin()) {
$.ajax({
url: createURL("listImageStores"),
data: {
provider: 'Swift'
},
async: false,
success: function(json) {
var items = json.listimagestoreresponse.imagestore;
if (items != null && items.length > 0)
havingSwift = true;
}
});
if (havingSwift = false) {
$.ajax({
url: createURL("listImageStores"),
data: {
provider: 'S3'
},
async: false,
success: function(json) {
var items = json.listimagestoreresponse.imagestore;
if (items != null && items.length > 0) {
havingS3 = true;
}
}
});
}
} else {
havingSwift = false;
havingS3 = false;
}
// Get project configuration
// TEMPORARY -- replace w/ output of capability response, etc., once implemented
window.g_projectsInviteRequired = false;
},
error: function(XMLHttpRequest) {
var errorMsg = parseXMLHttpResponse(XMLHttpRequest);
if (errorMsg.length == 0 && XMLHttpRequest.status == 0)
errorMsg = dictionary['error.unable.to.reach.management.server'];
else
errorMsg = _l('error.invalid.username.password'); //override error message
args.response.error(errorMsg);
},
beforeSend: function(XMLHttpResponse) {
return true;
}
});
},
logoutAction: function(args) {
$.ajax({
url: createURL('logout'),
async: false,
success: function() {
g_mySession = null;
g_sessionKey = null;
g_username = null;
g_account = null;
g_domainid = null;
g_timezoneoffset = null;
g_timezone = null;
g_supportELB = null;
g_loginCmdText = null;
$.cookie('JSESSIONID', null);
$.cookie('sessionKey', null);
$.cookie('username', null);
$.cookie('account', null);
$.cookie('domainid', null);
$.cookie('role', null);
$.cookie('networktype', null);
$.cookie('timezoneoffset', null);
$.cookie('timezone', null);
$.cookie('supportELB', null);
if (onLogoutCallback()) { //onLogoutCallback() will set g_loginResponse(single-sign-on variable) to null, then bypassLoginCheck() will show login screen.
document.location.reload(); //when onLogoutCallback() returns true, reload the current document.
}
},
error: function() {
if (onLogoutCallback()) { //onLogoutCallback() will set g_loginResponse(single-sign-on variable) to null, then bypassLoginCheck() will show login screen.
document.location.reload(); //when onLogoutCallback() returns true, reload the current document.
}
},
beforeSend: function(XMLHttpResponse) {
return true;
}
});
},
// Show cloudStack main UI widget
complete: function(args) {
var context = {
users: [args.user]
}; };
var cloudStackArgs = $.extend(cloudStack, {
context: context
});
initInstallWizard(); // Check to invoke install wizard
} else { cloudStack.installWizard.check({
// Show cloudStack main UI context: context,
$container.cloudStack($.extend(cloudStackArgs, { hasLogo: false })); response: {
} success: function(args) {
if (args.doInstall && isAdmin()) {
var initInstallWizard = function() {
cloudStack.uiCustom.installWizard({
$container: $container,
context: context,
complete: function() {
// Show cloudStack main UI
$container.cloudStack($.extend(cloudStackArgs, {
hasLogo: false
}));
}
});
};
initInstallWizard();
} else {
// Show cloudStack main UI
$container.cloudStack($.extend(cloudStackArgs, {
hasLogo: false
}));
}
}
}
});
// Logout action
$('#user-options a').live('click', function() {
loginArgs.logoutAction({
context: cloudStack.context
});
});
window._reloadUI = function() {
$('#container').html('');
$('#container').cloudStack(window.cloudStack);
};
} }
}
});
// Logout action
$('#user-options a').live('click', function() {
loginArgs.logoutAction({
context: cloudStack.context
});
});
window._reloadUI = function() {
$('#container').html('');
$('#container').cloudStack(window.cloudStack);
}; };
}
};
if ($.urlParam('loginUrl') != 0) { if ($.urlParam('loginUrl') != 0) {
// SSO // SSO
loginArgs.hideLoginScreen = true; loginArgs.hideLoginScreen = true;
} }
cloudStack.uiCustom.login(loginArgs); cloudStack.uiCustom.login(loginArgs);
// Localization // Localization
if (!$.isFunction(cloudStack.localizationFn)) { // i.e., localize is overridden by a plugin/module if (!$.isFunction(cloudStack.localizationFn)) { // i.e., localize is overridden by a plugin/module
cloudStack.localizationFn = function(str) { cloudStack.localizationFn = function(str) {
return dictionary[str]; return dictionary[str];
}; };
} }
document.title = _l('label.app.name'); document.title = _l('label.app.name');
}); });
})(cloudStack, jQuery); })(cloudStack, jQuery);

File diff suppressed because it is too large Load Diff

View File

@ -15,249 +15,245 @@
// specific language governing permissions and limitations // specific language governing permissions and limitations
// under the License. // under the License.
(function($, cloudStack) { (function($, cloudStack) {
// Admin dashboard
cloudStack.sections.dashboard = {
title: 'label.menu.dashboard',
show: cloudStack.uiCustom.dashboard,
adminCheck: function(args) {
return isAdmin() ? true : false;
},
// User dashboard
user: {
dataProvider: function(args) {
var dataFns = {
instances: function(data) {
$.ajax({
url: createURL('listVirtualMachines'),
data: {
listAll: true
},
success: function(json) {
var instances = json.listvirtualmachinesresponse.virtualmachine ?
json.listvirtualmachinesresponse.virtualmachine : [];
dataFns.account($.extend(data, {
runningInstances: $.grep(instances, function(instance) {
return instance.state == 'Running';
}).length,
stoppedInstances: $.grep(instances, function(instance) {
return instance.state == 'Stopped';
}).length,
totalInstances: instances.length
}));
}
});
},
account: function(data) {
var user = cloudStack.context.users[0];
dataFns.events($.extend(data, {
accountID: user.userid,
accountName: user.account,
userName: user.username,
accountType: user.role,
accountDomainID: user.domainid
}));
},
events: function(data) {
$.ajax({
url: createURL('listEvents'),
data: {
listAll: true,
page: 1,
pageSize: 4
},
success: function(json) {
dataFns.ipAddresses($.extend(data, {
events: json.listeventsresponse.event ?
json.listeventsresponse.event : []
}));
}
});
},
ipAddresses: function(data) {
$.ajax({
url: createURL('listNetworks'),
data: {
listAll: true,
type: 'isolated',
supportedServices: 'SourceNat'
},
success: function(json) {
var netTotal = json.listnetworksresponse.count ?
json.listnetworksresponse.count : 0;
$.ajax({
url: createURL('listPublicIpAddresses'),
success: function(json) {
var ipTotal = json.listpublicipaddressesresponse.count ?
json.listpublicipaddressesresponse.count : 0;
complete($.extend(data, {
netTotal: netTotal,
ipTotal: ipTotal
}));
}
});
}
});
}
};
var complete = function(data) {
args.response.success({
data: data
});
};
dataFns.instances({});
}
},
// Admin dashboard // Admin dashboard
admin: { cloudStack.sections.dashboard = {
zoneDetailView: { title: 'label.menu.dashboard',
tabs: { show: cloudStack.uiCustom.dashboard,
resources: {
title: 'label.resources', adminCheck: function(args) {
custom: cloudStack.uiCustom.systemChart('resources') return isAdmin() ? true : false;
} },
// User dashboard
user: {
dataProvider: function(args) {
var dataFns = {
instances: function(data) {
$.ajax({
url: createURL('listVirtualMachines'),
data: {
listAll: true
},
success: function(json) {
var instances = json.listvirtualmachinesresponse.virtualmachine ?
json.listvirtualmachinesresponse.virtualmachine : [];
dataFns.account($.extend(data, {
runningInstances: $.grep(instances, function(instance) {
return instance.state == 'Running';
}).length,
stoppedInstances: $.grep(instances, function(instance) {
return instance.state == 'Stopped';
}).length,
totalInstances: instances.length
}));
}
});
},
account: function(data) {
var user = cloudStack.context.users[0];
dataFns.events($.extend(data, {
accountID: user.userid,
accountName: user.account,
userName: user.username,
accountType: user.role,
accountDomainID: user.domainid
}));
},
events: function(data) {
$.ajax({
url: createURL('listEvents'),
data: {
listAll: true,
page: 1,
pageSize: 4
},
success: function(json) {
dataFns.ipAddresses($.extend(data, {
events: json.listeventsresponse.event ? json.listeventsresponse.event : []
}));
}
});
},
ipAddresses: function(data) {
$.ajax({
url: createURL('listNetworks'),
data: {
listAll: true,
type: 'isolated',
supportedServices: 'SourceNat'
},
success: function(json) {
var netTotal = json.listnetworksresponse.count ?
json.listnetworksresponse.count : 0;
$.ajax({
url: createURL('listPublicIpAddresses'),
success: function(json) {
var ipTotal = json.listpublicipaddressesresponse.count ?
json.listpublicipaddressesresponse.count : 0;
complete($.extend(data, {
netTotal: netTotal,
ipTotal: ipTotal
}));
}
});
}
});
}
};
var complete = function(data) {
args.response.success({
data: data
});
};
dataFns.instances({});
}
},
// Admin dashboard
admin: {
zoneDetailView: {
tabs: {
resources: {
title: 'label.resources',
custom: cloudStack.uiCustom.systemChart('resources')
}
}
},
dataProvider: function(args) {
var dataFns = {
zones: function(data) {
$.ajax({
url: createURL('listZones'),
success: function(json) {
dataFns.capacity({
zones: json.listzonesresponse.zone
});
}
});
},
capacity: function(data) {
var latestData = null;
if (window.fetchLatestflag == 1) {
latestData = {
fetchLatest: true
}
} else {
latestData = {
fetchLatest: false
}
}
window.fetchLatestflag = 0;
dataFns.alerts(data);
},
alerts: function(data) {
$.ajax({
url: createURL('listAlerts'),
data: {
page: 1,
pageSize: 4
},
success: function(json) {
var alerts = json.listalertsresponse.alert ?
json.listalertsresponse.alert : [];
dataFns.hostAlerts($.extend(data, {
alerts: $.map(alerts, function(alert) {
return {
name: cloudStack.converters.toAlertType(alert.type),
description: alert.description,
sent: cloudStack.converters.toLocalDate(alert.sent)
};
})
}));
}
});
},
hostAlerts: function(data) {
$.ajax({
url: createURL('listHosts'),
data: {
state: 'Alert',
page: 1,
pageSize: 4
},
success: function(json) {
var hosts = json.listhostsresponse.host ?
json.listhostsresponse.host : [];
dataFns.zoneCapacity($.extend(data, {
hostAlerts: $.map(hosts, function(host) {
return {
name: host.name,
description: 'message.alert.state.detected'
};
})
}));
}
});
},
zoneCapacity: function(data) {
$.ajax({
url: createURL('listCapacity'),
data: {
fetchLatest: false,
sortBy: 'usage',
page: 0,
pagesize: 8
},
success: function(json) {
var capacities = json.listcapacityresponse.capacity ?
json.listcapacityresponse.capacity : [];
complete($.extend(data, {
zoneCapacities: $.map(capacities, function(capacity) {
if (capacity.podname) {
capacity.zonename = capacity.zonename.concat(', ' + _l('label.pod') + ': ' + capacity.podname);
}
if (capacity.clustername) {
capacity.zonename = capacity.zonename.concat(', ' + _l('label.cluster') + ': ' + capacity.clustername);
}
capacity.zonename.replace('Zone:', _l('label.zone') + ':');
return {
zoneID: capacity.zoneid, // Temporary fix for dashboard
zoneName: capacity.zonename,
type: cloudStack.converters.toCapacityCountType(capacity.type),
percent: parseInt(capacity.percentused),
used: cloudStack.converters.convertByType(capacity.type, capacity.capacityused),
total: cloudStack.converters.convertByType(capacity.type, capacity.capacitytotal)
};
})
}));
}
});
}
};
var complete = function(data) {
args.response.success({
data: data
});
};
dataFns.zones({});
}
} }
}, };
dataProvider: function(args) {
var dataFns = {
zones: function(data) {
$.ajax({
url: createURL('listZones'),
success: function(json) {
dataFns.capacity({
zones: json.listzonesresponse.zone
});
}
});
},
capacity: function(data) {
var latestData =null;
if(window.fetchLatestflag == 1)
{
latestData = {
fetchLatest:true
}
}
else
{
latestData = {
fetchLatest:false
}
}
window.fetchLatestflag = 0;
dataFns.alerts(data);
},
alerts: function(data) {
$.ajax({
url: createURL('listAlerts'),
data: {
page: 1,
pageSize: 4
},
success: function(json) {
var alerts = json.listalertsresponse.alert ?
json.listalertsresponse.alert : [];
dataFns.hostAlerts($.extend(data, {
alerts: $.map(alerts, function(alert) {
return {
name: cloudStack.converters.toAlertType(alert.type),
description: alert.description,
sent: cloudStack.converters.toLocalDate(alert.sent)
};
})
}));
}
});
},
hostAlerts: function(data) {
$.ajax({
url: createURL('listHosts'),
data: {
state: 'Alert',
page: 1,
pageSize: 4
},
success: function(json) {
var hosts = json.listhostsresponse.host ?
json.listhostsresponse.host : [];
dataFns.zoneCapacity($.extend(data, {
hostAlerts: $.map(hosts, function(host) {
return {
name: host.name,
description: 'message.alert.state.detected'
};
})
}));
}
});
},
zoneCapacity: function(data) {
$.ajax({
url: createURL('listCapacity'),
data: {
fetchLatest: false,
sortBy: 'usage',
page: 0,
pagesize: 8
},
success: function(json) {
var capacities = json.listcapacityresponse.capacity ?
json.listcapacityresponse.capacity : [];
complete($.extend(data, {
zoneCapacities: $.map(capacities, function(capacity) {
if (capacity.podname) {
capacity.zonename = capacity.zonename.concat(', ' + _l('label.pod') + ': ' + capacity.podname);
}
if (capacity.clustername) {
capacity.zonename = capacity.zonename.concat(', ' + _l('label.cluster') + ': ' + capacity.clustername);
}
capacity.zonename.replace('Zone:', _l('label.zone') + ':');
return {
zoneID: capacity.zoneid, // Temporary fix for dashboard
zoneName: capacity.zonename,
type: cloudStack.converters.toCapacityCountType(capacity.type),
percent: parseInt(capacity.percentused),
used: cloudStack.converters.convertByType(capacity.type, capacity.capacityused),
total: cloudStack.converters.convertByType(capacity.type, capacity.capacitytotal)
};
})
}));
}
});
}
};
var complete = function(data) {
args.response.success({
data: data
});
};
dataFns.zones({});
}
}
};
})(jQuery, cloudStack); })(jQuery, cloudStack);

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -16,341 +16,428 @@
// under the License. // under the License.
(function(cloudStack) { (function(cloudStack) {
cloudStack.sections['global-settings'] = { cloudStack.sections['global-settings'] = {
title: 'label.menu.global.settings',
id: 'global-settings',
sectionSelect: {
label: 'label.select-view'
},
sections: {
globalSettings: {
type: 'select',
title: 'label.menu.global.settings', title: 'label.menu.global.settings',
listView: { id: 'global-settings',
label: 'label.menu.global.settings', sectionSelect: {
actions: { label: 'label.select-view'
edit: { },
label: 'label.change.value', sections: {
action: function(args) { globalSettings: {
var data = { type: 'select',
name: args.data.jsonObj.name, title: 'label.menu.global.settings',
value: args.data.value listView: {
}; label: 'label.menu.global.settings',
$.ajax({ actions: {
url: createURL('updateConfiguration'), edit: {
data: data, label: 'label.change.value',
success: function(json) { action: function(args) {
var item = json.updateconfigurationresponse.configuration; var data = {
if(item.category == "Usage") name: args.data.jsonObj.name,
cloudStack.dialog.notice({ message: _l('message.restart.mgmt.usage.server') }); value: args.data.value
else };
cloudStack.dialog.notice({ message: _l('message.restart.mgmt.server') }); $.ajax({
args.response.success({data: item}); url: createURL('updateConfiguration'),
}, data: data,
error: function(json) { success: function(json) {
args.response.error(parseXMLHttpResponse(json)); var item = json.updateconfigurationresponse.configuration;
} if (item.category == "Usage")
}); cloudStack.dialog.notice({
} message: _l('message.restart.mgmt.usage.server')
} });
}, else
fields: { cloudStack.dialog.notice({
name: { label: 'label.name', id: true }, message: _l('message.restart.mgmt.server')
description: { label: 'label.description' }, });
value: { label: 'label.value', editable: true, truncate: true } args.response.success({
}, data: item
dataProvider: function(args) { });
var data = { },
page: args.page, error: function(json) {
pagesize: pageSize args.response.error(parseXMLHttpResponse(json));
}; }
});
}
}
},
fields: {
name: {
label: 'label.name',
id: true
},
description: {
label: 'label.description'
},
value: {
label: 'label.value',
editable: true,
truncate: true
}
},
dataProvider: function(args) {
var data = {
page: args.page,
pagesize: pageSize
};
if (args.filterBy.search.value) { if (args.filterBy.search.value) {
data.name = args.filterBy.search.value; data.name = args.filterBy.search.value;
} }
$.ajax({
url: createURL('listConfigurations'),
data: data,
dataType: "json",
async: true,
success: function(json) {
var items = json.listconfigurationsresponse.configuration;
args.response.success({ data: items });
}
});
}
}
},
ldapConfiguration:{
type:'select',
title:'LDAP Configuration',
listView:{
id:'ldap',
label:'LDAP Configuration',
fields:{
hostname: {label: 'Hostname'},
queryfilter: {label: 'Query Filter'},
searchbase: {label: 'Search Base'},
port: {label: 'LDAP Port'},
ssl: {
label: 'SSL'
}
},
dataProvider:function(args){
var data = {};
listViewDataProvider(args, data);
$.ajax({
url: createURL('ldapConfig&listall=true'), //Need a list LDAP configuration API call which needs to be implemented
data: data,
success: function(json) {
var items = json.ldapconfigresponse.ldapconfig;
args.response.success({data:items});
},
error: function(data) {
args.response.error(parseXMLHttpResponse(data));
}
});
},
detailView: {
name: 'label.details',
actions: {
// Remove LDAP
remove: {
label: 'Remove LDAP',
messages: {
notification: function(args) {
return 'LDAP Configuration Deleted';
},
confirm: function() {
return 'Are you sure you want to delete the LDAP configuration?';
}
},
action: function(args) {
$.ajax({
url:createURL("ldapRemove"),
success:function(json){
args.response.success();
}
});
$(window).trigger('cloudStack.fullRefresh');
$.ajax({
url: createURL('listConfigurations'),
data: data,
dataType: "json",
async: true,
success: function(json) {
var items = json.listconfigurationsresponse.configuration;
args.response.success({
data: items
});
}
});
}
} }
} },
},
tabs:{ ldapConfiguration: {
type: 'select',
details: { title: 'LDAP Configuration',
title: 'LDAP Configuration Details', listView: {
fields: [ id: 'ldap',
{ label: 'LDAP Configuration',
hostname: { label: 'Hostname' }, fields: {
description: { label: 'label.description' }, hostname: {
ssl : { label: 'SSL'} label: 'Hostname'
} },
], queryfilter: {
dataProvider: function(args) { label: 'Query Filter'
$.ajax({ },
url: createURL("ldapConfig&listAll=true" ), searchbase: {
dataType: "json", label: 'Search Base'
async: true, },
success: function(json) { port: {
var item = json.ldapconfigresponse.ldapconfig; label: 'LDAP Port'
args.response.success({data: item}); },
} ssl: {
}); label: 'SSL'
}
}
}
},
actions: {
add:{
label: 'Configure LDAP',
messages: {
confirm: function(args) {
return 'Do you really want to configure LDAP ? ';
},
notification: function(args) {
return 'LDAP configured';
}
},
createForm: {
title: 'Configure LDAP',
fields:{
name:{label: 'Bind DN' , validation: {required:true} },
password: {label: 'Bind Password', validation: {required: true },isPassword:true },
hostname: {label:'Hostname' , validation:{required:true}},
queryfilter: {label:'Query Filter' , validation: {required:true} , docID:'helpLdapQueryFilter'},
searchbase: {label:'SearchBase',validation:{required:true}},
ssl: {
label:'SSL' ,
isBoolean:true,
isChecked:false
},
port: { label: 'Port' , defaultValue: '389' },
truststore:{ label:'Trust Store' , isHidden:true , dependsOn:'ssl',validation:{required:true} },
truststorepassword:{ label:'Trust Store Password' ,isHidden:true , dependsOn:'ssl', validation:{required:true}}
}
},
action:function(args) {
var array = [];
array.push("&binddn=" + todb(args.data.name));
array.push("&bindpass=" + todb(args.data.password));
array.push("&hostname=" + todb(args.data.hostname));
array.push("&searchbase=" +todb(args.data.searchbase));
array.push("&queryfilter=" +todb(args.data.queryfilter));
array.push("&port=" +todb(args.data.port));
if(args.$form.find('.form-item[rel=ssl]').find('input[type=checkbox]').is(':Checked')== true) {
array.push("&ssl=true");
if(args.data.truststore != "")
array.push("&truststore=" +todb(args.data.truststore));
if(args.data.truststorepassword !="")
array.push("&truststorepass=" +todb(args.data.truststorepassword));
} }
else
array.push("&ssl=false");
$.ajax({
url: createURL("ldapConfig" + array.join("")),
dataType: "json",
async: true,
success: function(json) {
var items = json.ldapconfigresponse.ldapconfig;
args.response.success({
data: items
});
},
error:function(json){
args.response.error(parseXMLHttpResponse(json));
}
});
}
}
}
}
},
hypervisorCapabilities: {
type: 'select',
title: 'label.hypervisor.capabilities',
listView: {
id: 'hypervisorCapabilities',
label: 'label.hypervisor.capabilities',
fields: {
hypervisor: { label: 'label.hypervisor' },
hypervisorversion: { label: 'label.hypervisor.version' },
maxguestslimit: { label: 'label.max.guest.limit' }
},
dataProvider: function(args) {
var data = {};
listViewDataProvider(args, data);
$.ajax({
url: createURL('listHypervisorCapabilities'),
data: data,
success: function(json) {
var items = json.listhypervisorcapabilitiesresponse.hypervisorCapabilities;
args.response.success({data:items});
},
error: function(data) {
args.response.error(parseXMLHttpResponse(data));
}
});
},
detailView: {
name: 'label.details',
actions: {
edit: {
label: 'label.edit',
action: function(args) {
var data = {
id: args.context.hypervisorCapabilities[0].id,
maxguestslimit: args.data.maxguestslimit
};
$.ajax({
url: createURL('updateHypervisorCapabilities'),
data: data,
success: function(json) {
var item = json.updatehypervisorcapabilitiesresponse['null'];
args.response.success({data: item});
}, },
error: function(data) { dataProvider: function(args) {
args.response.error(parseXMLHttpResponse(data)); var data = {};
} listViewDataProvider(args, data);
}); $.ajax({
} url: createURL('ldapConfig&listall=true'), //Need a list LDAP configuration API call which needs to be implemented
} data: data,
}, success: function(json) {
var items = json.ldapconfigresponse.ldapconfig;
args.response.success({
data: items
});
},
error: function(data) {
args.response.error(parseXMLHttpResponse(data));
}
});
},
detailView: {
name: 'label.details',
actions: {
// Remove LDAP
remove: {
label: 'Remove LDAP',
messages: {
notification: function(args) {
return 'LDAP Configuration Deleted';
},
confirm: function() {
return 'Are you sure you want to delete the LDAP configuration?';
}
},
action: function(args) {
$.ajax({
url: createURL("ldapRemove"),
success: function(json) {
args.response.success();
}
});
$(window).trigger('cloudStack.fullRefresh');
}
}
},
tabs: {
details: {
title: 'LDAP Configuration Details',
fields: [{
hostname: {
label: 'Hostname'
},
description: {
label: 'label.description'
},
ssl: {
label: 'SSL'
}
}],
dataProvider: function(args) {
$.ajax({
url: createURL("ldapConfig&listAll=true"),
dataType: "json",
async: true,
success: function(json) {
var item = json.ldapconfigresponse.ldapconfig;
args.response.success({
data: item
});
}
});
}
}
}
},
actions: {
add: {
label: 'Configure LDAP',
messages: {
confirm: function(args) {
return 'Do you really want to configure LDAP ? ';
},
notification: function(args) {
return 'LDAP configured';
}
},
createForm: {
title: 'Configure LDAP',
fields: {
name: {
label: 'Bind DN',
validation: {
required: true
}
},
password: {
label: 'Bind Password',
validation: {
required: true
},
isPassword: true
},
hostname: {
label: 'Hostname',
validation: {
required: true
}
},
queryfilter: {
label: 'Query Filter',
validation: {
required: true
},
docID: 'helpLdapQueryFilter'
},
searchbase: {
label: 'SearchBase',
validation: {
required: true
}
},
ssl: {
label: 'SSL',
isBoolean: true,
isChecked: false
},
port: {
label: 'Port',
defaultValue: '389'
},
truststore: {
label: 'Trust Store',
isHidden: true,
dependsOn: 'ssl',
validation: {
required: true
}
},
truststorepassword: {
label: 'Trust Store Password',
isHidden: true,
dependsOn: 'ssl',
validation: {
required: true
}
}
}
},
action: function(args) {
var array = [];
array.push("&binddn=" + todb(args.data.name));
array.push("&bindpass=" + todb(args.data.password));
array.push("&hostname=" + todb(args.data.hostname));
array.push("&searchbase=" + todb(args.data.searchbase));
array.push("&queryfilter=" + todb(args.data.queryfilter));
array.push("&port=" + todb(args.data.port));
if (args.$form.find('.form-item[rel=ssl]').find('input[type=checkbox]').is(':Checked') == true) {
array.push("&ssl=true");
if (args.data.truststore != "")
array.push("&truststore=" + todb(args.data.truststore));
if (args.data.truststorepassword != "")
array.push("&truststorepass=" + todb(args.data.truststorepassword));
} else
array.push("&ssl=false");
$.ajax({
url: createURL("ldapConfig" + array.join("")),
dataType: "json",
async: true,
success: function(json) {
var items = json.ldapconfigresponse.ldapconfig;
args.response.success({
data: items
});
},
error: function(json) {
args.response.error(parseXMLHttpResponse(json));
}
});
}
}
tabs: {
details: {
title: 'label.details',
fields: [
{
id: { label: 'label.id' },
hypervisor: { label: 'label.hypervisor' },
hypervisorversion: { label: 'label.hypervisor.version' },
maxguestslimit: {
label: 'label.max.guest.limit',
isEditable: true
} }
}
],
dataProvider: function(args) {
args.response.success( }
{
data:args.context.hypervisorCapabilities[0]
}
); },
hypervisorCapabilities: {
type: 'select',
title: 'label.hypervisor.capabilities',
listView: {
id: 'hypervisorCapabilities',
label: 'label.hypervisor.capabilities',
fields: {
hypervisor: {
label: 'label.hypervisor'
},
hypervisorversion: {
label: 'label.hypervisor.version'
},
maxguestslimit: {
label: 'label.max.guest.limit'
}
},
dataProvider: function(args) {
var data = {};
listViewDataProvider(args, data);
$.ajax({
url: createURL('listHypervisorCapabilities'),
data: data,
success: function(json) {
var items = json.listhypervisorcapabilitiesresponse.hypervisorCapabilities;
args.response.success({
data: items
});
},
error: function(data) {
args.response.error(parseXMLHttpResponse(data));
}
});
},
detailView: {
name: 'label.details',
actions: {
edit: {
label: 'label.edit',
action: function(args) {
var data = {
id: args.context.hypervisorCapabilities[0].id,
maxguestslimit: args.data.maxguestslimit
};
$.ajax({
url: createURL('updateHypervisorCapabilities'),
data: data,
success: function(json) {
var item = json.updatehypervisorcapabilitiesresponse['null'];
args.response.success({
data: item
});
},
error: function(data) {
args.response.error(parseXMLHttpResponse(data));
}
});
}
}
},
tabs: {
details: {
title: 'label.details',
fields: [{
id: {
label: 'label.id'
},
hypervisor: {
label: 'label.hypervisor'
},
hypervisorversion: {
label: 'label.hypervisor.version'
},
maxguestslimit: {
label: 'label.max.guest.limit',
isEditable: true
}
}],
dataProvider: function(args) {
args.response.success({
data: args.context.hypervisorCapabilities[0]
});
}
}
}
}
} }
}
} }
}
} }
} };
}
};
})(cloudStack); })(cloudStack);

View File

@ -15,342 +15,344 @@
// specific language governing permissions and limitations // specific language governing permissions and limitations
// under the License. // under the License.
(function($, cloudStack) { (function($, cloudStack) {
cloudStack.installWizard = { cloudStack.installWizard = {
// Check if install wizard should be invoked // Check if install wizard should be invoked
check: function(args) { check: function(args) {
$.ajax({ $.ajax({
url: createURL('listZones'), url: createURL('listZones'),
dataType: 'json', dataType: 'json',
async: true, async: true,
success: function(data) { success: function(data) {
args.response.success({ args.response.success({
doInstall: !data.listzonesresponse.zone doInstall: !data.listzonesresponse.zone
});
}
});
},
changeUser: function(args) {
$.ajax({
url: createURL('updateUser'),
data: {
id: cloudStack.context.users[0].userid,
password: md5Hashed ? $.md5(args.data.password) : todb(args.data.password)
},
dataType: 'json',
async: true,
success: function(data) {
args.response.success({
data: { newUser: data.updateuserresponse.user }
});
}
});
},
// Copy text
copy: {
// Tooltips
'tooltip.addZone.name': function(args) {
args.response.success({
text: 'message.installWizard.tooltip.addZone.name'
});
},
'tooltip.addZone.ip4dns1': function(args) {
args.response.success({
text: 'message.installWizard.tooltip.addZone.dns1'
});
},
'tooltip.addZone.ip4dns2': function(args) {
args.response.success({
text: 'message.installWizard.tooltip.addZone.dns2'
});
},
'tooltip.addZone.internaldns1': function(args) {
args.response.success({
text: 'message.installWizard.tooltip.addZone.internaldns1'
});
},
'tooltip.addZone.internaldns2': function(args) {
args.response.success({
text: 'message.installWizard.tooltip.addZone.internaldns2'
});
},
'tooltip.configureGuestTraffic.name': function(args) {
args.response.success({
text: 'message.installWizard.tooltip.configureGuestTraffic.name'
});
},
'tooltip.configureGuestTraffic.description': function(args) {
args.response.success({
text: 'message.installWizard.tooltip.configureGuestTraffic.description'
});
},
'tooltip.configureGuestTraffic.guestGateway': function(args) {
args.response.success({
text: 'message.installWizard.tooltip.configureGuestTraffic.guestGateway'
});
},
'tooltip.configureGuestTraffic.guestNetmask': function(args) {
args.response.success({
text: 'message.installWizard.tooltip.configureGuestTraffic.guestNetmask'
});
},
'tooltip.configureGuestTraffic.guestStartIp': function(args) {
args.response.success({
text: 'message.installWizard.tooltip.configureGuestTraffic.guestStartIp'
});
},
'tooltip.configureGuestTraffic.guestEndIp': function(args) {
args.response.success({
text: 'message.installWizard.tooltip.configureGuestTraffic.guestEndIp'
});
},
'tooltip.addPod.name': function(args) {
args.response.success({
text: 'message.installWizard.tooltip.addPod.name'
});
},
'tooltip.addPod.reservedSystemGateway': function(args) {
args.response.success({
text: 'message.installWizard.tooltip.addPod.reservedSystemGateway'
});
},
'tooltip.addPod.reservedSystemNetmask': function(args) {
args.response.success({
text: 'message.installWizard.tooltip.addPod.reservedSystemNetmask'
});
},
'tooltip.addPod.reservedSystemStartIp': function(args) {
args.response.success({
text: 'message.installWizard.tooltip.addPod.reservedSystemStartIp'
});
},
'tooltip.addPod.reservedSystemEndIp': function(args) {
args.response.success({
text: 'message.installWizard.tooltip.addPod.reservedSystemEndIp'
});
},
'tooltip.addCluster.name': function(args) {
args.response.success({
text: 'message.installWizard.tooltip.addCluster.name'
});
},
'tooltip.addHost.hostname': function(args) {
args.response.success({
text: 'message.installWizard.tooltip.addHost.hostname'
});
},
'tooltip.addHost.username': function(args) {
args.response.success({
text: 'message.installWizard.tooltip.addHost.username'
});
},
'tooltip.addHost.password': function(args) {
args.response.success({
text: 'message.installWizard.tooltip.addHost.password'
});
},
'tooltip.addPrimaryStorage.name': function(args) {
args.response.success({
text: 'message.installWizard.tooltip.addPrimaryStorage.name'
});
},
'tooltip.addPrimaryStorage.server': function(args) {
args.response.success({
text: 'message.installWizard.tooltip.addPrimaryStorage.server'
});
},
'tooltip.addPrimaryStorage.path': function(args) {
args.response.success({
text: 'message.installWizard.tooltip.addPrimaryStorage.path'
});
},
'tooltip.addSecondaryStorage.nfsServer': function(args) {
args.response.success({
text: 'message.installWizard.tooltip.addSecondaryStorage.nfsServer'
});
},
'tooltip.addSecondaryStorage.path': function(args) {
args.response.success({
text: 'message.installWizard.tooltip.addSecondaryStorage.path'
});
},
// Intro text
whatIsCloudStack: function(args) {
args.response.success({
text: 'message.installWizard.copy.whatIsCloudStack'
});
},
whatIsAZone: function(args) {
args.response.success({
text: 'message.installWizard.copy.whatIsAZone'
});
},
whatIsAPod: function(args) {
args.response.success({
text: 'message.installWizard.copy.whatIsAPod'
});
},
whatIsACluster: function(args) {
args.response.success({
text: 'message.installWizard.copy.whatIsACluster'
});
},
whatIsAHost: function(args) {
args.response.success({
text: 'message.installWizard.copy.whatIsAHost'
});
},
whatIsPrimaryStorage: function(args) {
args.response.success({
text: 'message.installWizard.copy.whatIsPrimaryStorage'
});
},
whatIsSecondaryStorage: function(args) {
args.response.success({
text: 'message.installWizard.copy.whatIsSecondaryStorage'
});
}
},
action: function(args) {
var success = args.response.success;
var message = args.response.message;
// Get default network offering
var selectedNetworkOffering;
$.ajax({
url: createURL("listNetworkOfferings&state=Enabled&guestiptype=Shared"),
dataType: "json",
async: false,
success: function(json) {
selectedNetworkOffering = $.grep(
json.listnetworkofferingsresponse.networkoffering,
function(networkOffering) {
var services = $.map(networkOffering.service, function(service) {
return service.name;
});
//pick the network offering including SecurityGroup, but excluding Lb and StaticNat. (bug 13665)
return (($.inArray('SecurityGroup', services) != -1) && ($.inArray('Lb', services) == -1) && ($.inArray('StaticNat', services) == -1)) ;
}
)[0];
}
});
cloudStack.zoneWizard.action($.extend(true, {}, args, {
// Plug in hard-coded values specific to quick install
data: {
zone: {
networkType: 'Basic',
networkOfferingId: selectedNetworkOffering.id
},
pluginFrom: {
name: 'installWizard',
selectedNetworkOffering: selectedNetworkOffering,
selectedNetworkOfferingHavingSG: true
}
},
response: {
success: function(args) {
var enableZone = function() {
message('Enabling zone...');
cloudStack.zoneWizard.enableZoneAction({
data: args.data,
formData: args.data,
launchData: args.data,
response: {
success: function(args) {
pollSystemVMs();
}
}
});
};
var pollSystemVMs = function() {
// Poll System VMs, then enable zone
message('Creating system VMs (this may take a while)');
var poll = setInterval(function() {
$.ajax({
url: createURL('listSystemVms'),
success: function(data) {
var systemVMs = data.listsystemvmsresponse.systemvm;
if (systemVMs && systemVMs.length > 1) {
if (systemVMs.length == $.grep(systemVMs, function(vm) {
return vm.state == 'Running';
}).length) {
clearInterval(poll);
message('System VMs ready.');
setTimeout(pollBuiltinTemplates, 500);
}
}
}
});
}, 5000);
};
// Wait for builtin template to be present -- otherwise VMs cannot launch
var pollBuiltinTemplates = function() {
message('Waiting for builtin templates to load...');
var poll = setInterval(function() {
$.ajax({
url: createURL('listTemplates'),
data: {
templatefilter: 'all'
},
success: function(data) {
var templates = data.listtemplatesresponse.template ?
data.listtemplatesresponse.template : [];
var builtinTemplates = $.grep(templates, function(template) {
return template.templatetype == 'BUILTIN';
}); });
}
});
},
if (builtinTemplates.length) { changeUser: function(args) {
clearInterval(poll); $.ajax({
message('Your CloudStack is ready!'); url: createURL('updateUser'),
setTimeout(success, 1000); data: {
} id: cloudStack.context.users[0].userid,
} password: md5Hashed ? $.md5(args.data.password) : todb(args.data.password)
},
dataType: 'json',
async: true,
success: function(data) {
args.response.success({
data: {
newUser: data.updateuserresponse.user
}
});
}
});
},
// Copy text
copy: {
// Tooltips
'tooltip.addZone.name': function(args) {
args.response.success({
text: 'message.installWizard.tooltip.addZone.name'
}); });
}, 5000); },
};
enableZone(); 'tooltip.addZone.ip4dns1': function(args) {
} args.response.success({
text: 'message.installWizard.tooltip.addZone.dns1'
});
},
'tooltip.addZone.ip4dns2': function(args) {
args.response.success({
text: 'message.installWizard.tooltip.addZone.dns2'
});
},
'tooltip.addZone.internaldns1': function(args) {
args.response.success({
text: 'message.installWizard.tooltip.addZone.internaldns1'
});
},
'tooltip.addZone.internaldns2': function(args) {
args.response.success({
text: 'message.installWizard.tooltip.addZone.internaldns2'
});
},
'tooltip.configureGuestTraffic.name': function(args) {
args.response.success({
text: 'message.installWizard.tooltip.configureGuestTraffic.name'
});
},
'tooltip.configureGuestTraffic.description': function(args) {
args.response.success({
text: 'message.installWizard.tooltip.configureGuestTraffic.description'
});
},
'tooltip.configureGuestTraffic.guestGateway': function(args) {
args.response.success({
text: 'message.installWizard.tooltip.configureGuestTraffic.guestGateway'
});
},
'tooltip.configureGuestTraffic.guestNetmask': function(args) {
args.response.success({
text: 'message.installWizard.tooltip.configureGuestTraffic.guestNetmask'
});
},
'tooltip.configureGuestTraffic.guestStartIp': function(args) {
args.response.success({
text: 'message.installWizard.tooltip.configureGuestTraffic.guestStartIp'
});
},
'tooltip.configureGuestTraffic.guestEndIp': function(args) {
args.response.success({
text: 'message.installWizard.tooltip.configureGuestTraffic.guestEndIp'
});
},
'tooltip.addPod.name': function(args) {
args.response.success({
text: 'message.installWizard.tooltip.addPod.name'
});
},
'tooltip.addPod.reservedSystemGateway': function(args) {
args.response.success({
text: 'message.installWizard.tooltip.addPod.reservedSystemGateway'
});
},
'tooltip.addPod.reservedSystemNetmask': function(args) {
args.response.success({
text: 'message.installWizard.tooltip.addPod.reservedSystemNetmask'
});
},
'tooltip.addPod.reservedSystemStartIp': function(args) {
args.response.success({
text: 'message.installWizard.tooltip.addPod.reservedSystemStartIp'
});
},
'tooltip.addPod.reservedSystemEndIp': function(args) {
args.response.success({
text: 'message.installWizard.tooltip.addPod.reservedSystemEndIp'
});
},
'tooltip.addCluster.name': function(args) {
args.response.success({
text: 'message.installWizard.tooltip.addCluster.name'
});
},
'tooltip.addHost.hostname': function(args) {
args.response.success({
text: 'message.installWizard.tooltip.addHost.hostname'
});
},
'tooltip.addHost.username': function(args) {
args.response.success({
text: 'message.installWizard.tooltip.addHost.username'
});
},
'tooltip.addHost.password': function(args) {
args.response.success({
text: 'message.installWizard.tooltip.addHost.password'
});
},
'tooltip.addPrimaryStorage.name': function(args) {
args.response.success({
text: 'message.installWizard.tooltip.addPrimaryStorage.name'
});
},
'tooltip.addPrimaryStorage.server': function(args) {
args.response.success({
text: 'message.installWizard.tooltip.addPrimaryStorage.server'
});
},
'tooltip.addPrimaryStorage.path': function(args) {
args.response.success({
text: 'message.installWizard.tooltip.addPrimaryStorage.path'
});
},
'tooltip.addSecondaryStorage.nfsServer': function(args) {
args.response.success({
text: 'message.installWizard.tooltip.addSecondaryStorage.nfsServer'
});
},
'tooltip.addSecondaryStorage.path': function(args) {
args.response.success({
text: 'message.installWizard.tooltip.addSecondaryStorage.path'
});
},
// Intro text
whatIsCloudStack: function(args) {
args.response.success({
text: 'message.installWizard.copy.whatIsCloudStack'
});
},
whatIsAZone: function(args) {
args.response.success({
text: 'message.installWizard.copy.whatIsAZone'
});
},
whatIsAPod: function(args) {
args.response.success({
text: 'message.installWizard.copy.whatIsAPod'
});
},
whatIsACluster: function(args) {
args.response.success({
text: 'message.installWizard.copy.whatIsACluster'
});
},
whatIsAHost: function(args) {
args.response.success({
text: 'message.installWizard.copy.whatIsAHost'
});
},
whatIsPrimaryStorage: function(args) {
args.response.success({
text: 'message.installWizard.copy.whatIsPrimaryStorage'
});
},
whatIsSecondaryStorage: function(args) {
args.response.success({
text: 'message.installWizard.copy.whatIsSecondaryStorage'
});
}
},
action: function(args) {
var success = args.response.success;
var message = args.response.message;
// Get default network offering
var selectedNetworkOffering;
$.ajax({
url: createURL("listNetworkOfferings&state=Enabled&guestiptype=Shared"),
dataType: "json",
async: false,
success: function(json) {
selectedNetworkOffering = $.grep(
json.listnetworkofferingsresponse.networkoffering,
function(networkOffering) {
var services = $.map(networkOffering.service, function(service) {
return service.name;
});
//pick the network offering including SecurityGroup, but excluding Lb and StaticNat. (bug 13665)
return (($.inArray('SecurityGroup', services) != -1) && ($.inArray('Lb', services) == -1) && ($.inArray('StaticNat', services) == -1));
}
)[0];
}
});
cloudStack.zoneWizard.action($.extend(true, {}, args, {
// Plug in hard-coded values specific to quick install
data: {
zone: {
networkType: 'Basic',
networkOfferingId: selectedNetworkOffering.id
},
pluginFrom: {
name: 'installWizard',
selectedNetworkOffering: selectedNetworkOffering,
selectedNetworkOfferingHavingSG: true
}
},
response: {
success: function(args) {
var enableZone = function() {
message('Enabling zone...');
cloudStack.zoneWizard.enableZoneAction({
data: args.data,
formData: args.data,
launchData: args.data,
response: {
success: function(args) {
pollSystemVMs();
}
}
});
};
var pollSystemVMs = function() {
// Poll System VMs, then enable zone
message('Creating system VMs (this may take a while)');
var poll = setInterval(function() {
$.ajax({
url: createURL('listSystemVms'),
success: function(data) {
var systemVMs = data.listsystemvmsresponse.systemvm;
if (systemVMs && systemVMs.length > 1) {
if (systemVMs.length == $.grep(systemVMs, function(vm) {
return vm.state == 'Running';
}).length) {
clearInterval(poll);
message('System VMs ready.');
setTimeout(pollBuiltinTemplates, 500);
}
}
}
});
}, 5000);
};
// Wait for builtin template to be present -- otherwise VMs cannot launch
var pollBuiltinTemplates = function() {
message('Waiting for builtin templates to load...');
var poll = setInterval(function() {
$.ajax({
url: createURL('listTemplates'),
data: {
templatefilter: 'all'
},
success: function(data) {
var templates = data.listtemplatesresponse.template ?
data.listtemplatesresponse.template : [];
var builtinTemplates = $.grep(templates, function(template) {
return template.templatetype == 'BUILTIN';
});
if (builtinTemplates.length) {
clearInterval(poll);
message('Your CloudStack is ready!');
setTimeout(success, 1000);
}
}
});
}, 5000);
};
enableZone();
}
}
}));
} }
})); };
}
};
}(jQuery, cloudStack)); }(jQuery, cloudStack));

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -16,292 +16,304 @@
// under the License. // under the License.
(function($, cloudStack) { (function($, cloudStack) {
cloudStack.lbStickyPolicy = { cloudStack.lbStickyPolicy = {
dialog: function(args) { dialog: function(args) {
return function(args) { return function(args) {
var success = args.response.success; var success = args.response.success;
var context = args.context; var context = args.context;
var network; var network;
if('vpc' in args.context) { //from VPC section if ('vpc' in args.context) { //from VPC section
var data = { var data = {
listAll: true, listAll: true,
supportedservices: 'Lb' supportedservices: 'Lb'
}; };
if(args.context.ipAddresses[0].associatednetworkid == null) { if (args.context.ipAddresses[0].associatednetworkid == null) {
$.extend(data, { $.extend(data, {
vpcid: args.context.vpc[0].id vpcid: args.context.vpc[0].id
}); });
} } else {
else { $.extend(data, {
$.extend(data, { id: args.context.ipAddresses[0].associatednetworkid
id: args.context.ipAddresses[0].associatednetworkid });
}); }
}
$.ajax({ $.ajax({
url: createURL("listNetworks"), //check whether the VPC has a network including Lb service url: createURL("listNetworks"), //check whether the VPC has a network including Lb service
data: data, data: data,
async: false, async: false,
success: function(json) { success: function(json) {
var items = json.listnetworksresponse.network; var items = json.listnetworksresponse.network;
if(items != null && items.length > 0) { if (items != null && items.length > 0) {
network = items[0]; network = items[0];
} }
} }
}); });
} } else { //from Guest Network section
else { //from Guest Network section network = args.context.networks[0];
network = args.context.networks[0]; }
}
var $item = args.$item; var $item = args.$item;
var lbService = $.grep(network.service, function(service) { var lbService = $.grep(network.service, function(service) {
return service.name == 'Lb'; return service.name == 'Lb';
})[0];
var stickinessCapabilities = JSON.parse($.grep(
lbService.capability,
function(capability) {
return capability.name == 'SupportedStickinessMethods';
}
)[0].value);
var baseFields = {
stickyName: { label: 'Sticky Name', validation: { required: true } }
};
$.map(
$.map(
stickinessCapabilities,
function(c) { return c.paramlist; }
),
function(p) {
baseFields[p.paramname] = {
label: _l('label.sticky.' + p.paramname),
isHidden: true,
isBoolean: p.isflag,
validation: { required: p.required }
};
}
);
var conditionalFields = {
methodname: {
label: 'Stickiness method',
select: function(args) {
var $select = args.$select;
var $form = $select.closest('form');
var stickyOptions = [];
stickinessCapabilities.push({ methodname: 'None', paramlist: [] });
$(stickinessCapabilities).each(function() {
var stickyCapability = this;
stickyOptions.push({
id: stickyCapability.methodname,
description: stickyCapability.methodname
});
});
stickyOptions = stickyOptions.sort(function() {
return this.id != 'None';
});
args.response.success({
data: stickyOptions
}, 500);
$select.change(function() {
var value = $select.val();
var showFields = [];
var targetMethod = $.grep(stickinessCapabilities, function(stickyCapability) {
return stickyCapability.methodname == value;
})[0]; })[0];
var visibleParams = $.map(targetMethod.paramlist, function(param) {
return param.paramname;
});
$select.closest('.form-item').siblings('.form-item').each(function() { var stickinessCapabilities = JSON.parse($.grep(
var $field = $(this); lbService.capability,
var id = $field.attr('rel'); function(capability) {
return capability.name == 'SupportedStickinessMethods';
}
)[0].value);
if ($.inArray(id, visibleParams) > -1) { var baseFields = {
$field.css('display', 'inline-block'); stickyName: {
$field.attr('sticky-method', value); label: 'Sticky Name',
} else { validation: {
$field.hide(); required: true
$field.attr('sticky-method', null); }
} }
}); };
// Name always is required $.map(
if ($select.val() != 'None') { $.map(
$select.closest('.form-item').siblings('.form-item[rel=stickyName]') stickinessCapabilities,
.css('display', 'inline-block'); function(c) {
return c.paramlist;
}
),
function(p) {
baseFields[p.paramname] = {
label: _l('label.sticky.' + p.paramname),
isHidden: true,
isBoolean: p.isflag,
validation: {
required: p.required
}
};
}
);
var conditionalFields = {
methodname: {
label: 'Stickiness method',
select: function(args) {
var $select = args.$select;
var $form = $select.closest('form');
var stickyOptions = [];
stickinessCapabilities.push({
methodname: 'None',
paramlist: []
});
$(stickinessCapabilities).each(function() {
var stickyCapability = this;
stickyOptions.push({
id: stickyCapability.methodname,
description: stickyCapability.methodname
});
});
stickyOptions = stickyOptions.sort(function() {
return this.id != 'None';
});
args.response.success({
data: stickyOptions
}, 500);
$select.change(function() {
var value = $select.val();
var showFields = [];
var targetMethod = $.grep(stickinessCapabilities, function(stickyCapability) {
return stickyCapability.methodname == value;
})[0];
var visibleParams = $.map(targetMethod.paramlist, function(param) {
return param.paramname;
});
$select.closest('.form-item').siblings('.form-item').each(function() {
var $field = $(this);
var id = $field.attr('rel');
if ($.inArray(id, visibleParams) > -1) {
$field.css('display', 'inline-block');
$field.attr('sticky-method', value);
} else {
$field.hide();
$field.attr('sticky-method', null);
}
});
// Name always is required
if ($select.val() != 'None') {
$select.closest('.form-item').siblings('.form-item[rel=stickyName]')
.css('display', 'inline-block');
}
$select.closest(':ui-dialog').dialog('option', 'position', 'center');
});
}
}
};
var fields = $.extend(conditionalFields, baseFields);
if (args.data) {
var populatedFields = $.map(fields, function(field, id) {
return id;
});
$(populatedFields).each(function() {
var id = this;
var field = fields[id];
var dataItem = args.data[id];
if (field.isBoolean) {
field.isChecked = dataItem ? true : false;
} else {
field.defaultValue = dataItem;
}
});
} }
$select.closest(':ui-dialog').dialog('option', 'position', 'center'); cloudStack.dialog.createForm({
}); form: {
} title: 'Configure Sticky Policy',
} desc: 'Please complete the following fields',
}; fields: fields
},
after: function(args) {
// Remove fields not applicable to sticky method
args.$form.find('.form-item:hidden').remove();
var fields = $.extend(conditionalFields, baseFields); var data = cloudStack.serializeForm(args.$form);
if (args.data) { /* $item indicates that this is an existing sticky rule;
var populatedFields = $.map(fields, function(field, id) {
return id;
});
$(populatedFields).each(function() {
var id = this;
var field = fields[id];
var dataItem = args.data[id];
if (field.isBoolean) {
field.isChecked = dataItem ? true : false;
} else {
field.defaultValue = dataItem;
}
});
}
cloudStack.dialog.createForm({
form: {
title: 'Configure Sticky Policy',
desc: 'Please complete the following fields',
fields: fields
},
after: function(args) {
// Remove fields not applicable to sticky method
args.$form.find('.form-item:hidden').remove();
var data = cloudStack.serializeForm(args.$form);
/* $item indicates that this is an existing sticky rule;
re-create sticky rule with new parameters */ re-create sticky rule with new parameters */
if ($item) { if ($item) {
var $loading = $('<div>').addClass('loading-overlay'); var $loading = $('<div>').addClass('loading-overlay');
$loading.prependTo($item); $loading.prependTo($item);
cloudStack.lbStickyPolicy.actions.recreate( cloudStack.lbStickyPolicy.actions.recreate(
$item.data('multi-custom-data').id, $item.data('multi-custom-data').id,
$item.data('multi-custom-data').lbRuleID, $item.data('multi-custom-data').lbRuleID,
data, data,
function() { // Complete function() { // Complete
$(window).trigger('cloudStack.fullRefresh'); $(window).trigger('cloudStack.fullRefresh');
}, },
function(error) { // Error function(error) { // Error
$(window).trigger('cloudStack.fullRefresh'); $(window).trigger('cloudStack.fullRefresh');
}
);
} else {
success({
data: data
});
}
}
});
};
},
actions: {
add: function(lbRuleID, data, complete, error) {
var stickyURLData = '';
var stickyParams = $.map(data, function(value, key) {
return key;
});
var notParams = ['methodname', 'stickyName'];
var index = 0;
$(stickyParams).each(function() {
var param = '&param[' + index + ']';
var name = this.toString();
var value = data[name];
if (!value || $.inArray(name, notParams) > -1) return true;
if (value == 'on') value = true;
stickyURLData += param + '.name=' + name + param + '.value=' + value;
index++;
return true;
});
$.ajax({
url: createURL('createLBStickinessPolicy' + stickyURLData),
data: {
lbruleid: lbRuleID,
name: data.stickyName,
methodname: data.methodname
},
success: function(json) {
cloudStack.ui.notifications.add({
desc: 'Add new LB sticky rule',
section: 'Network',
poll: pollAsyncJobResult,
_custom: {
jobId: json.createLBStickinessPolicy.jobid
}
},
complete, {},
error, {}
);
},
error: function(json) {
complete();
cloudStack.dialog.notice({
message: parseXMLHttpResponse(json)
});
}
});
},
'delete': function(stickyRuleID, complete, error) {
$.ajax({
url: createURL('deleteLBStickinessPolicy'),
data: {
id: stickyRuleID
},
success: function(json) {
cloudStack.ui.notifications.add({
desc: 'Remove previous LB sticky rule',
section: 'Network',
poll: pollAsyncJobResult,
_custom: {
jobId: json.deleteLBstickinessrruleresponse.jobid
}
},
complete, {},
error, {}
);
},
error: function(json) {
complete();
cloudStack.dialog.notice({
message: parseXMLHttpResponse(json)
});
}
});
},
recreate: function(stickyRuleID, lbRuleID, data, complete, error) {
var addStickyPolicy = function() {
cloudStack.lbStickyPolicy.actions.add(
lbRuleID,
data,
complete,
error
);
};
// Delete existing rule
if (data.methodname !== 'None') {
addStickyPolicy();
} else {
cloudStack.lbStickyPolicy.actions['delete'](stickyRuleID, complete, error);
} }
);
} else {
success({
data: data
});
} }
}
});
};
},
actions: {
add: function(lbRuleID, data, complete, error) {
var stickyURLData = '';
var stickyParams = $.map(data, function(value, key) {
return key;
});
var notParams = ['methodname', 'stickyName'];
var index = 0;
$(stickyParams).each(function() {
var param = '&param[' + index + ']';
var name = this.toString();
var value = data[name];
if (!value || $.inArray(name, notParams) > -1) return true;
if (value == 'on') value = true;
stickyURLData += param + '.name=' + name + param + '.value=' + value;
index++;
return true;
});
$.ajax({
url: createURL('createLBStickinessPolicy' + stickyURLData),
data: {
lbruleid: lbRuleID,
name: data.stickyName,
methodname: data.methodname
},
success: function(json) {
cloudStack.ui.notifications.add(
{
desc: 'Add new LB sticky rule',
section: 'Network',
poll: pollAsyncJobResult,
_custom: {
jobId: json.createLBStickinessPolicy.jobid
}
},
complete, {},
error, {}
);
},
error: function(json) {
complete();
cloudStack.dialog.notice({ message: parseXMLHttpResponse(json) });
}
});
},
'delete': function(stickyRuleID, complete, error) {
$.ajax({
url: createURL('deleteLBStickinessPolicy'),
data: {
id: stickyRuleID
},
success: function(json) {
cloudStack.ui.notifications.add(
{
desc: 'Remove previous LB sticky rule',
section: 'Network',
poll: pollAsyncJobResult,
_custom: {
jobId: json.deleteLBstickinessrruleresponse.jobid
}
},
complete, {},
error, {}
);
},
error: function(json) {
complete();
cloudStack.dialog.notice({ message: parseXMLHttpResponse(json) });
}
});
},
recreate: function(stickyRuleID, lbRuleID, data, complete, error) {
var addStickyPolicy = function() {
cloudStack.lbStickyPolicy.actions.add(
lbRuleID,
data,
complete,
error
);
};
// Delete existing rule
if (data.methodname !== 'None') {
addStickyPolicy();
} else {
cloudStack.lbStickyPolicy.actions['delete'](stickyRuleID, complete, error);
} }
} };
}
};
}(jQuery, cloudStack)); }(jQuery, cloudStack));

File diff suppressed because it is too large Load Diff

View File

@ -15,100 +15,100 @@
// specific language governing permissions and limitations // specific language governing permissions and limitations
// under the License. // under the License.
(function($, cloudStack, require) { (function($, cloudStack, require) {
if (!cloudStack.pluginAPI) { if (!cloudStack.pluginAPI) {
cloudStack.pluginAPI = {}; cloudStack.pluginAPI = {};
}
var loadCSS = function(path) {
if (document.createStyleSheet) {
// IE-compatible CSS loading
document.createStyleSheet(path);
} else {
var $link = $('<link>');
$link.attr({
rel: 'stylesheet',
type: 'text/css',
href: path
});
$('html head').append($link);
} }
};
$.extend(cloudStack.pluginAPI, { var loadCSS = function(path) {
ui: { if (document.createStyleSheet) {
pollAsyncJob: pollAsyncJobResult, // IE-compatible CSS loading
apiCall: function(command, args) { document.createStyleSheet(path);
$.ajax({ } else {
url: createURL(command), var $link = $('<link>');
data: args.data,
success: args.success,
error: function(json) {
args.error(parseXMLHttpResponse(json));
}
});
},
addSection: function(section) {
cloudStack.sections[section.id] = $.extend(section, {
customIcon: 'plugins/' + section.id + '/icon.png'
});
},
extend: function(obj) {
$.extend(true, cloudStack, obj);
}
}
});
cloudStack.sections.plugins = { $link.attr({
title: 'label.plugins', rel: 'stylesheet',
show: cloudStack.uiCustom.pluginListing type: 'text/css',
}; href: path
});
var loadedPlugins = 0; $('html head').append($link);
var pluginTotal = cloudStack.plugins.length + cloudStack.modules.length; }
};
// Load $.extend(cloudStack.pluginAPI, {
$(['modules', 'plugins']).each(function() { ui: {
var type = this; pollAsyncJob: pollAsyncJobResult,
var paths = $(cloudStack[type]).map(function(index, id) { apiCall: function(command, args) {
return type + '/' + id + '/' + id; $.ajax({
}).toArray(); url: createURL(command),
data: args.data,
success: args.success,
error: function(json) {
args.error(parseXMLHttpResponse(json));
}
});
},
addSection: function(section) {
cloudStack.sections[section.id] = $.extend(section, {
customIcon: 'plugins/' + section.id + '/icon.png'
});
},
extend: function(obj) {
$.extend(true, cloudStack, obj);
}
}
});
// Load modules cloudStack.sections.plugins = {
require( title: 'label.plugins',
paths, show: cloudStack.uiCustom.pluginListing
function() { };
$(cloudStack[type]).map(function(index, id) {
var basePath = type + '/' + id + '/';
var css = basePath + id + '.css';
var configJS = type == 'plugins' ? basePath + 'config' : null;
if (configJS) { var loadedPlugins = 0;
// Load config metadata var pluginTotal = cloudStack.plugins.length + cloudStack.modules.length;
require([configJS]);
}
// Execute module // Load
cloudStack[type][id]( $(['modules', 'plugins']).each(function() {
$.extend(true, {}, cloudStack.pluginAPI, { var type = this;
pluginAPI: { var paths = $(cloudStack[type]).map(function(index, id) {
extend: function(api) { return type + '/' + id + '/' + id;
cloudStack.pluginAPI[id] = api; }).toArray();
}
}
})
);
loadedPlugins = loadedPlugins + 1; // Load modules
require(
paths,
function() {
$(cloudStack[type]).map(function(index, id) {
var basePath = type + '/' + id + '/';
var css = basePath + id + '.css';
var configJS = type == 'plugins' ? basePath + 'config' : null;
if (loadedPlugins === pluginTotal) { if (configJS) {
$(window).trigger('cloudStack.pluginReady'); // Load config metadata
} require([configJS]);
}
loadCSS(css); // Execute module
}); cloudStack[type][id](
} $.extend(true, {}, cloudStack.pluginAPI, {
); pluginAPI: {
}); extend: function(api) {
cloudStack.pluginAPI[id] = api;
}
}
})
);
loadedPlugins = loadedPlugins + 1;
if (loadedPlugins === pluginTotal) {
$(window).trigger('cloudStack.pluginReady');
}
loadCSS(css);
});
}
);
});
}(jQuery, cloudStack, require)); }(jQuery, cloudStack, require));

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -15,159 +15,160 @@
// specific language governing permissions and limitations // specific language governing permissions and limitations
// under the License. // under the License.
(function(cloudStack, $) { (function(cloudStack, $) {
cloudStack.uiCustom.affinity = function(args) { cloudStack.uiCustom.affinity = function(args) {
var listView = args.listView; var listView = args.listView;
var action = args.action; var action = args.action;
var tierSelect = args.tierSelect; var tierSelect = args.tierSelect;
return function(args) { return function(args) {
var context = args.context; var context = args.context;
var $instanceRow = args.$instanceRow; var $instanceRow = args.$instanceRow;
var vmList = function(args) { var vmList = function(args) {
// Create a listing of instances, based on limited information // Create a listing of instances, based on limited information
// from main instances list view // from main instances list view
var $listView; var $listView;
var instances = $.extend(true, {}, args.listView, { var instances = $.extend(true, {}, args.listView, {
context: context, context: context,
uiCustom: true uiCustom: true
});
instances.listView.actions = {
select: {
label: _l('label.select.instance'),
type: 'checkbox',
action: {
uiCustom: function(args) {
var $item = args.$item;
var $input = $item.find('td.actions input:visible');
if ($input.attr('type') == 'checkbox') {
if ($input.is(':checked'))
$item.addClass('multi-edit-selected');
else
$item.removeClass('multi-edit-selected');
} else {
$item.siblings().removeClass('multi-edit-selected');
$item.addClass('multi-edit-selected');
}
}
}
}
};
$listView = $('<div>').listView(instances);
// Change action label
$listView.find('th.actions').html(_l('label.select'));
return $listView;
};
var $dataList = vmList({
listView: listView
}).dialog({
dialogClass: 'multi-edit-add-list panel',
width: 825,
title: _l('label.affinity.groups'),
buttons: [
{
text: _l('label.apply'),
'class': 'ok',
click: function() {
if ($dataList.find('.tier-select select').val() == -1) {
cloudStack.dialog.notice({ message: ('Please select a tier')});
return false;
}
var complete = args.complete;
var start = args.start;
start();
$dataList.fadeOut(function() {
action({
tierID: $dataList.find('.tier-select select').val(),
_subselect: $dataList.find('tr.multi-edit-selected .subselect select').val(),
context: $.extend(true, {}, context, {
affinityGroups: $dataList.find('tbody tr').map(function(index, elem) {
var itemData = $(elem).data('json-obj');
itemData._isSelected = false;
if ($(elem).hasClass('multi-edit-selected')) {
itemData._isSelected = true;
}
return itemData;
})
}),
response: {
success: function(args) {
complete({
_custom: args._custom,
$item: $instanceRow
});
},
error: function(args) {
cloudStack.dialog.notice({ message: args });
}
}
}); });
$dataList.remove();
});
$('div.overlay').fadeOut(function() { instances.listView.actions = {
$('div.overlay').remove(); select: {
$(':ui-dialog').dialog('destroy'); label: _l('label.select.instance'),
}); type: 'checkbox',
action: {
uiCustom: function(args) {
var $item = args.$item;
var $input = $item.find('td.actions input:visible');
if ($input.attr('type') == 'checkbox') {
if ($input.is(':checked'))
$item.addClass('multi-edit-selected');
else
$item.removeClass('multi-edit-selected');
} else {
$item.siblings().removeClass('multi-edit-selected');
$item.addClass('multi-edit-selected');
}
}
}
}
};
$listView = $('<div>').listView(instances);
// Change action label
$listView.find('th.actions').html(_l('label.select'));
return $listView;
};
var $dataList = vmList({
listView: listView
}).dialog({
dialogClass: 'multi-edit-add-list panel',
width: 825,
title: _l('label.affinity.groups'),
buttons: [{
text: _l('label.apply'),
'class': 'ok',
click: function() {
if ($dataList.find('.tier-select select').val() == -1) {
cloudStack.dialog.notice({
message: ('Please select a tier')
});
return false;
}
var complete = args.complete;
var start = args.start;
start();
$dataList.fadeOut(function() {
action({
tierID: $dataList.find('.tier-select select').val(),
_subselect: $dataList.find('tr.multi-edit-selected .subselect select').val(),
context: $.extend(true, {}, context, {
affinityGroups: $dataList.find('tbody tr').map(function(index, elem) {
var itemData = $(elem).data('json-obj');
itemData._isSelected = false;
if ($(elem).hasClass('multi-edit-selected')) {
itemData._isSelected = true;
}
return itemData;
})
}),
response: {
success: function(args) {
complete({
_custom: args._custom,
$item: $instanceRow
});
},
error: function(args) {
cloudStack.dialog.notice({
message: args
});
}
}
});
$dataList.remove();
});
$('div.overlay').fadeOut(function() {
$('div.overlay').remove();
$(':ui-dialog').dialog('destroy');
});
}
}, {
text: _l('label.cancel'),
'class': 'cancel',
click: function() {
$dataList.fadeOut(function() {
$dataList.remove();
});
$('div.overlay').fadeOut(function() {
$('div.overlay').remove();
$(':ui-dialog').dialog('destroy');
});
}
}]
}).parent('.ui-dialog').overlay();
// Add tier select dialog
if (tierSelect) {
var $toolbar = $dataList.find('.toolbar');
var $tierSelect = $('<div>').addClass('filters tier-select').prependTo($toolbar);
var $tierSelectLabel = $('<label>').html('Select tier').appendTo($tierSelect);
var $tierSelectInput = $('<select>').appendTo($tierSelect);
// Get tier data
tierSelect({
context: context,
$tierSelect: $tierSelect,
response: {
success: function(args) {
var data = args.data;
$(data).map(function(index, item) {
var $option = $('<option>');
$option.attr('value', item.id);
$option.html(item.description);
$option.appendTo($tierSelectInput);
});
},
error: function(message) {
cloudStack.dialog.notice({
message: message ? message : 'Could not retrieve VPC tiers'
});
}
}
});
} }
}, };
{
text: _l('label.cancel'),
'class': 'cancel',
click: function() {
$dataList.fadeOut(function() {
$dataList.remove();
});
$('div.overlay').fadeOut(function() {
$('div.overlay').remove();
$(':ui-dialog').dialog('destroy');
});
}
}
]
}).parent('.ui-dialog').overlay();
// Add tier select dialog
if (tierSelect) {
var $toolbar = $dataList.find('.toolbar');
var $tierSelect = $('<div>').addClass('filters tier-select').prependTo($toolbar);
var $tierSelectLabel = $('<label>').html('Select tier').appendTo($tierSelect);
var $tierSelectInput = $('<select>').appendTo($tierSelect);
// Get tier data
tierSelect({
context: context,
$tierSelect: $tierSelect,
response: {
success: function(args) {
var data = args.data;
$(data).map(function(index, item) {
var $option = $('<option>');
$option.attr('value', item.id);
$option.html(item.description);
$option.appendTo($tierSelectInput);
});
},
error: function(message) {
cloudStack.dialog.notice({
message: message ? message : 'Could not retrieve VPC tiers'
});
}
}
});
}
}; };
};
}(cloudStack, jQuery)); }(cloudStack, jQuery));

View File

@ -16,386 +16,403 @@
// under the License. // under the License.
(function($, cloudStack) { (function($, cloudStack) {
cloudStack.uiCustom.autoscaler = function(args) { cloudStack.uiCustom.autoscaler = function(args) {
// Place outer args here as local variables // Place outer args here as local variables
// i.e, -- var dataProvider = args.dataProvider // i.e, -- var dataProvider = args.dataProvider
var forms = $.extend(true, {}, args.forms); var forms = $.extend(true, {}, args.forms);
var topfields = forms.topFields; var topfields = forms.topFields;
var bottomfields = forms.bottomFields; var bottomfields = forms.bottomFields;
var scaleuppolicy = forms.scaleUpPolicy; var scaleuppolicy = forms.scaleUpPolicy;
var scaledownpolicy = forms.scaleDownPolicy; var scaledownpolicy = forms.scaleDownPolicy;
var dataProvider = cloudStack.autoscaler.dataProvider; var dataProvider = cloudStack.autoscaler.dataProvider;
var actions = cloudStack.autoscaler.autoscaleActions; var actions = cloudStack.autoscaler.autoscaleActions;
var actionFilter = cloudStack.autoscaler.actionFilter; var actionFilter = cloudStack.autoscaler.actionFilter;
return function(args) { return function(args) {
var context = args.data ? var context = args.data ?
$.extend(true, {}, args.context, { $.extend(true, {}, args.context, {
lbRules: [args.data] lbRules: [args.data]
}) : args.context; }) : args.context;
var formData = args.formData; var formData = args.formData;
var $autoscalerDialog = $('<div>').addClass('autoscaler'); var $autoscalerDialog = $('<div>').addClass('autoscaler');
var $topFields = $('<div>').addClass('field-group top-fields'); var $topFields = $('<div>').addClass('field-group top-fields');
var $bottomFields = $('<div>').addClass('field-group bottom-fields'); var $bottomFields = $('<div>').addClass('field-group bottom-fields');
var $scaleUpPolicy = $('<div>').addClass('scale-up-policy'); var $scaleUpPolicy = $('<div>').addClass('scale-up-policy');
var $slideScaleUp = $('<div></div>').addClass('expand'); var $slideScaleUp = $('<div></div>').addClass('expand');
var $hideScaleUp = $('<div></div>').addClass('hide'); var $hideScaleUp = $('<div></div>').addClass('hide');
var $scaleUpLabel= $('<div>Show</div>').addClass('slide-label'); var $scaleUpLabel = $('<div>Show</div>').addClass('slide-label');
var $scaleUpHideLabel=$('<div>Hide</div>').addClass('slide-label'); var $scaleUpHideLabel = $('<div>Hide</div>').addClass('slide-label');
var $scaleDownHideLabel=$('<div>Hide</div>').addClass('slide-label'); var $scaleDownHideLabel = $('<div>Hide</div>').addClass('slide-label');
var $scaleDownLabel=$('<div>Show</div>').addClass('slide-label'); var $scaleDownLabel = $('<div>Show</div>').addClass('slide-label');
var $slideScaleDown = $('<div></div>').addClass('expand'); var $slideScaleDown = $('<div></div>').addClass('expand');
var $hideScaleDown = $('<div></div>').addClass('hide'); var $hideScaleDown = $('<div></div>').addClass('hide');
var $scaleUpDivider = $('<hr></hr>').addClass('policy-divider'); var $scaleUpDivider = $('<hr></hr>').addClass('policy-divider');
var $scaleDownDivider = $('<hr></hr>').addClass('policy-divider'); var $scaleDownDivider = $('<hr></hr>').addClass('policy-divider');
var $bottomFieldDivider = $('<hr></hr>').addClass('policy-divider'); var $bottomFieldDivider = $('<hr></hr>').addClass('policy-divider');
var $scaleDownPolicy = $('<div>').addClass('scale-down-policy'); var $scaleDownPolicy = $('<div>').addClass('scale-down-policy');
var $scaleUpPolicyTitle = $('<div>').addClass('scale-up-policy-title') var $scaleUpPolicyTitle = $('<div>').addClass('scale-up-policy-title')
.html("Scale Up Policy"); .html("Scale Up Policy");
var $scaleDownPolicyTitle = $('<div>').addClass('scale-down-policy-title') var $scaleDownPolicyTitle = $('<div>').addClass('scale-down-policy-title')
.html("Scale Down Policy"); .html("Scale Down Policy");
var topFieldForm, $topFieldForm, var topFieldForm, $topFieldForm,
bottomFieldForm, $bottomFieldForm, bottomFieldForm, $bottomFieldForm,
scaleUpPolicyTitleForm, $scaleUpPolicyTitleForm, scaleUpPolicyTitleForm, $scaleUpPolicyTitleForm,
scaleDownPolicyTitleForm, $scaleDownPolicyTitleForm, scaleDownPolicyTitleForm, $scaleDownPolicyTitleForm,
scaleUpPolicyForm, scaleDownPolicyForm; scaleUpPolicyForm, scaleDownPolicyForm;
var renderActions = function(args) { var renderActions = function(args) {
var targetActionFilter = args.actionFilter ? args.actionFilter : actionFilter; var targetActionFilter = args.actionFilter ? args.actionFilter : actionFilter;
var data = args.data; var data = args.data;
var context = args.context; var context = args.context;
var $actions = $('<div>').addClass('detail-group'); var $actions = $('<div>').addClass('detail-group');
var $actionsTable = $('<table>').append('<tr>'); var $actionsTable = $('<table>').append('<tr>');
var $detailActions = $('<td>').addClass('detail-actions'); var $detailActions = $('<td>').addClass('detail-actions');
var $buttons = $('<div>').addClass('buttons'); var $buttons = $('<div>').addClass('buttons');
var visibleActions = targetActionFilter ? var visibleActions = targetActionFilter ?
targetActionFilter({ targetActionFilter({
context: $.extend(true, {}, context, { context: $.extend(true, {}, context, {
originalAutoscaleData: data ? [data] : null originalAutoscaleData: data ? [data] : null
}) })
}) : }) :
$.map(actions, function(value, key) { return key; }); $.map(actions, function(value, key) {
return key;
$detailActions.append($buttons);
$actionsTable.find('tr').append($detailActions);
$actions.append($actionsTable);
$(visibleActions).map(function(index, actionID) {
var action = actions[actionID];
var label = _l(action.label);
var $action = $('<div>').addClass('action').addClass(actionID);
var $icon = $('<a>')
.attr({ href: '#', title: label })
.append($('<span>').addClass('icon'));
if (visibleActions.length == 1) $action.addClass('single');
else if (!index) $action.addClass('first');
else if (index == visibleActions.length - 1) $action.addClass('last');
// Perform action event
$action.click(function() {
var $loading = $('<div>').addClass('loading-overlay').appendTo($autoscalerDialog);
var success = function(args) {
$loading.remove();
cloudStack.dialog.notice({
message: _l('label.task.completed') + ': ' + label
});
// Reload actions
if(data != null) { //data is originalAutoscaleData in \ui\scripts\autoscaler.js
data['afterActionIsComplete'] = args.data;
}
var $newActions = renderActions({
data: data ? $.extend(data, args.data) : args.data,
actionFilter: args.actionFilter,
context: context
});
$actions.after($newActions);
$actions.remove();
};
var error = function(message) {
$loading.remove();
cloudStack.dialog.notice({ message: message });
};
action.action({
context: {
originalAutoscaleData: args.data
},
response: {
success: function(args) {
var notification = $.extend(args.notification, {
_custom: args._custom,
desc: label
});
cloudStack.ui.notifications.add(
notification,
success, {},
error, {}
);
},
error: error
}
});
});
$action.append($icon);
$action.appendTo($buttons);
});
if (!visibleActions || !visibleActions.length) $actions.hide();
return $actions;
};
var renderDialogContent = function(args) {
var data = args.data ? args.data : {};
// Setup default values, in case where existing data is present
var setDefaultFields = function(fieldID, field) {
var fieldData = data[fieldID];
if (fieldData && !field.isBoolean) {
field.defaultValue = fieldData;
} else {
field.isChecked = fieldData;
}
};
$.each(topfields, setDefaultFields);
$.each(bottomfields, setDefaultFields);
$.extend(context, {
originalAutoscaleData: args.data
});
// Create and append top fields
// -- uses create form to generate fields
topFieldForm = cloudStack.dialog.createForm({
context: context,
noDialog: true, // Don't render a dialog, just return $formContainer
form: {
title: '',
fields: topfields
}
});
$topFieldForm = topFieldForm.$formContainer;
$topFieldForm.appendTo($topFields);
scaleUpPolicyTitleForm = cloudStack.dialog.createForm({
context: context,
noDialog: true,
form: {
title: '',
fields: {
scaleUpDuration: { label: 'Duration(in sec)', validation: { required: true } }
}
}
});
$scaleUpPolicyTitleForm = scaleUpPolicyTitleForm.$formContainer;
$scaleUpPolicyTitleForm.appendTo($scaleUpPolicyTitle);
scaleDownPolicyTitleForm = cloudStack.dialog.createForm({
context: context,
noDialog: true,
form: {
title: '',
fields: {
scaleDownDuration: { label: 'Duration(in sec)', validation: { required: true } }
}
}
});
$scaleDownPolicyTitleForm = scaleDownPolicyTitleForm.$formContainer;
$scaleDownPolicyTitleForm.appendTo($scaleDownPolicyTitle);
// Make multi-edits
//
// Scale up policy
if (data.scaleUpPolicy && $.isArray(data.scaleUpPolicy.conditions)) {
$autoscalerDialog.data('autoscaler-scale-up-data',
data.scaleUpPolicy.conditions);
}
if (data.scaleUpPolicy && data.scaleUpPolicy.duration) {
$scaleUpPolicyTitleForm.find('input[name=scaleUpDuration]').val(
data.scaleUpPolicy.duration
);
}
scaleuppolicy.context = context;
scaleUpPolicyForm = $scaleUpPolicy.multiEdit(scaleuppolicy);
// Scale down policy
if (data.scaleDownPolicy && $.isArray(data.scaleDownPolicy.conditions)) {
$autoscalerDialog.data('autoscaler-scale-down-data',
data.scaleDownPolicy.conditions);
}
if (data.scaleDownPolicy && data.scaleDownPolicy.duration) {
$scaleDownPolicyTitleForm.find('input[name=scaleDownDuration]').val(
data.scaleDownPolicy.duration
);
}
scaledownpolicy.context = context;
scaleDownPolicyForm = $scaleDownPolicy.multiEdit(scaledownpolicy);
// Create and append bottom fields
bottomFieldForm = cloudStack.dialog.createForm({
context: context,
noDialog: true, // Don't render a dialog, just return $formContainer
form: {
title: '',
fields: bottomfields
}
});
$bottomFieldForm = bottomFieldForm.$formContainer;
$bottomFieldForm.appendTo($bottomFields);
// Append main div elements
$autoscalerDialog.append(
$topFields,
$scaleUpPolicyTitle,
$scaleUpPolicy,
$scaleDownPolicyTitle,
$scaleDownPolicy,
$bottomFields
);
// Render dialog
//$autoscalerDialog.find('.form-item[rel=templateNames] label').hide();
/* Duration Fields*/
//$('div.ui-dialog div.autoscaler').find('div.scale-up-policy-title').append("<br></br>").append($inputLabel = $('<label>').html('Duration').attr({left:'200'})).append($('<input>').attr({ name: 'username' }));
//$('div.ui-dialog div.autoscaler').find('div.scale-down-policy-title').append("<br></br>").append($inputLabel = $('<label>').html('Duration').attr({left:'200'})).append($('<input>').attr({ name: 'username' }));
/*Dividers*/
$autoscalerDialog.find('div.scale-up-policy-title').prepend($scaleUpDivider);
$autoscalerDialog.find('div.scale-down-policy-title').prepend($scaleDownDivider);
$autoscalerDialog.find('div.field-group.bottom-fields').prepend($bottomFieldDivider);
/* Hide effects for multi-edit table*/
$autoscalerDialog.find('div.scale-up-policy').prepend($hideScaleUp);
$autoscalerDialog.find('div.scale-down-policy ').prepend($hideScaleDown);
$autoscalerDialog.find('div.scale-up-policy').prepend($scaleUpHideLabel);
$autoscalerDialog.find('div.scale-down-policy').prepend($scaleDownHideLabel);
/*Toggling the labels and data-item table - SCALE UP POLICY*/
$autoscalerDialog.find('div.scale-up-policy div.hide').click(function() {
$autoscalerDialog.find('div.scale-up-policy div.multi-edit div.data-item').slideToggle();
$scaleUpLabel = $autoscalerDialog.find('div.scale-up-policy div.slide-label').replaceWith($scaleUpLabel);
});
/*Toggling the images */
$('div.ui-dialog div.autoscaler div.scale-up-policy div.hide').click(function() {
$(this).toggleClass('expand hide');
});
$('div.ui-dialog div.autoscaler div.scale-down-policy div.hide').click(function() {
$(this).toggleClass('expand hide');
});
/*Toggling the labels and data-item table - SCALE DOWN POLICY*/
$('div.ui-dialog div.autoscaler div.scale-down-policy div.hide').click(function() {
$('div.ui-dialog div.autoscaler div.scale-down-policy div.multi-edit div.data div.data-item').slideToggle();
$scaleDownLabel = $('div.ui-dialog div.autoscaler div.scale-down-policy div.slide-label').replaceWith($scaleDownLabel);
});
$('div.ui-dialog div.autoscaler div.scale-down-policy div.multi-edit div.data div.expand').click(function() { $('div.ui-dialog div.autoscaler div.scale-down-policy div.multi-edit div.data div.data-item').slideToggle(); });
$autoscalerDialog.dialog('option', 'position', 'center');
$autoscalerDialog.dialog('option', 'height', 'auto');
// Setup actions
renderActions(args).prependTo($autoscalerDialog);
};
var $loading = $('<div>').addClass('loading-overlay').appendTo($autoscalerDialog);
$autoscalerDialog.dialog({
title: 'AutoScale Configuration Wizard',
width: 825,
height: 600,
draggable: true,
closeonEscape: false,
overflow:'auto',
open:function() {
$("button").each(function(){
$(this).attr("style", "left: 600px; position: relative; margin-right: 5px; ");
});
},
buttons: [
{
text: _l('label.cancel'),
'class': 'cancel',
click: function() {
$autoscalerDialog.dialog('destroy');
$('.overlay').remove();
}
},
{
text: _l('Apply'),
'class': 'ok',
click: function() {
var data = cloudStack.serializeForm($('.ui-dialog .autoscaler form'));
// Pass VPC data
if (formData.tier) {
data.tier = formData.tier;
}
$loading.appendTo($autoscalerDialog);
cloudStack.autoscaler.actions.apply({
formData: formData,
context: context,
data: data,
response: {
success: function() {
$loading.remove();
$autoscalerDialog.dialog('destroy');
$autoscalerDialog.closest(':ui-dialog').remove();
$('.overlay').remove();
cloudStack.dialog.notice({
message: 'Autoscale configured successfully.'
}); });
},
error: function(message) { $detailActions.append($buttons);
cloudStack.dialog.notice({ message: message }); $actionsTable.find('tr').append($detailActions);
$loading.remove(); $actions.append($actionsTable);
}
$(visibleActions).map(function(index, actionID) {
var action = actions[actionID];
var label = _l(action.label);
var $action = $('<div>').addClass('action').addClass(actionID);
var $icon = $('<a>')
.attr({
href: '#',
title: label
})
.append($('<span>').addClass('icon'));
if (visibleActions.length == 1) $action.addClass('single');
else if (!index) $action.addClass('first');
else if (index == visibleActions.length - 1) $action.addClass('last');
// Perform action event
$action.click(function() {
var $loading = $('<div>').addClass('loading-overlay').appendTo($autoscalerDialog);
var success = function(args) {
$loading.remove();
cloudStack.dialog.notice({
message: _l('label.task.completed') + ': ' + label
});
// Reload actions
if (data != null) { //data is originalAutoscaleData in \ui\scripts\autoscaler.js
data['afterActionIsComplete'] = args.data;
}
var $newActions = renderActions({
data: data ? $.extend(data, args.data) : args.data,
actionFilter: args.actionFilter,
context: context
});
$actions.after($newActions);
$actions.remove();
};
var error = function(message) {
$loading.remove();
cloudStack.dialog.notice({
message: message
});
};
action.action({
context: {
originalAutoscaleData: args.data
},
response: {
success: function(args) {
var notification = $.extend(args.notification, {
_custom: args._custom,
desc: label
});
cloudStack.ui.notifications.add(
notification,
success, {},
error, {}
);
},
error: error
}
});
});
$action.append($icon);
$action.appendTo($buttons);
});
if (!visibleActions || !visibleActions.length) $actions.hide();
return $actions;
};
var renderDialogContent = function(args) {
var data = args.data ? args.data : {};
// Setup default values, in case where existing data is present
var setDefaultFields = function(fieldID, field) {
var fieldData = data[fieldID];
if (fieldData && !field.isBoolean) {
field.defaultValue = fieldData;
} else {
field.isChecked = fieldData;
}
};
$.each(topfields, setDefaultFields);
$.each(bottomfields, setDefaultFields);
$.extend(context, {
originalAutoscaleData: args.data
});
// Create and append top fields
// -- uses create form to generate fields
topFieldForm = cloudStack.dialog.createForm({
context: context,
noDialog: true, // Don't render a dialog, just return $formContainer
form: {
title: '',
fields: topfields
}
});
$topFieldForm = topFieldForm.$formContainer;
$topFieldForm.appendTo($topFields);
scaleUpPolicyTitleForm = cloudStack.dialog.createForm({
context: context,
noDialog: true,
form: {
title: '',
fields: {
scaleUpDuration: {
label: 'Duration(in sec)',
validation: {
required: true
}
}
}
}
});
$scaleUpPolicyTitleForm = scaleUpPolicyTitleForm.$formContainer;
$scaleUpPolicyTitleForm.appendTo($scaleUpPolicyTitle);
scaleDownPolicyTitleForm = cloudStack.dialog.createForm({
context: context,
noDialog: true,
form: {
title: '',
fields: {
scaleDownDuration: {
label: 'Duration(in sec)',
validation: {
required: true
}
}
}
}
});
$scaleDownPolicyTitleForm = scaleDownPolicyTitleForm.$formContainer;
$scaleDownPolicyTitleForm.appendTo($scaleDownPolicyTitle);
// Make multi-edits
//
// Scale up policy
if (data.scaleUpPolicy && $.isArray(data.scaleUpPolicy.conditions)) {
$autoscalerDialog.data('autoscaler-scale-up-data',
data.scaleUpPolicy.conditions);
} }
});
}
}
]
}).closest('.ui-dialog').overlay();
dataProvider({ if (data.scaleUpPolicy && data.scaleUpPolicy.duration) {
context: context, $scaleUpPolicyTitleForm.find('input[name=scaleUpDuration]').val(
response: { data.scaleUpPolicy.duration
success: function(args) { );
$loading.remove(); }
renderDialogContent(args);
if (args.data == null) { //from a new LB rule scaleuppolicy.context = context;
$autoscalerDialog.find('select[name=serviceOfferingId]').removeAttr('disabled'); scaleUpPolicyForm = $scaleUpPolicy.multiEdit(scaleuppolicy);
$autoscalerDialog.find('select[name=securityGroups]').removeAttr('disabled');
$autoscalerDialog.find('select[name=diskOfferingId]').removeAttr('disabled');
}
else { //from an existing LB rule
$autoscalerDialog.find('select[name=serviceOfferingId]').attr('disabled', true);
$autoscalerDialog.find('select[name=securityGroups]').attr('disabled', true);
$autoscalerDialog.find('select[name=diskOfferingId]').attr('disabled', true);
if(args.data.isAdvanced != null) { // Scale down policy
$autoscalerDialog.find('input[type=checkbox]').trigger('click'); if (data.scaleDownPolicy && $.isArray(data.scaleDownPolicy.conditions)) {
$autoscalerDialog.find('input[type=checkbox]').attr('checked', 'checked'); $autoscalerDialog.data('autoscaler-scale-down-data',
} data.scaleDownPolicy.conditions);
} }
}
} if (data.scaleDownPolicy && data.scaleDownPolicy.duration) {
}); $scaleDownPolicyTitleForm.find('input[name=scaleDownDuration]').val(
data.scaleDownPolicy.duration
);
}
scaledownpolicy.context = context;
scaleDownPolicyForm = $scaleDownPolicy.multiEdit(scaledownpolicy);
// Create and append bottom fields
bottomFieldForm = cloudStack.dialog.createForm({
context: context,
noDialog: true, // Don't render a dialog, just return $formContainer
form: {
title: '',
fields: bottomfields
}
});
$bottomFieldForm = bottomFieldForm.$formContainer;
$bottomFieldForm.appendTo($bottomFields);
// Append main div elements
$autoscalerDialog.append(
$topFields,
$scaleUpPolicyTitle,
$scaleUpPolicy,
$scaleDownPolicyTitle,
$scaleDownPolicy,
$bottomFields
);
// Render dialog
//$autoscalerDialog.find('.form-item[rel=templateNames] label').hide();
/* Duration Fields*/
//$('div.ui-dialog div.autoscaler').find('div.scale-up-policy-title').append("<br></br>").append($inputLabel = $('<label>').html('Duration').attr({left:'200'})).append($('<input>').attr({ name: 'username' }));
//$('div.ui-dialog div.autoscaler').find('div.scale-down-policy-title').append("<br></br>").append($inputLabel = $('<label>').html('Duration').attr({left:'200'})).append($('<input>').attr({ name: 'username' }));
/*Dividers*/
$autoscalerDialog.find('div.scale-up-policy-title').prepend($scaleUpDivider);
$autoscalerDialog.find('div.scale-down-policy-title').prepend($scaleDownDivider);
$autoscalerDialog.find('div.field-group.bottom-fields').prepend($bottomFieldDivider);
/* Hide effects for multi-edit table*/
$autoscalerDialog.find('div.scale-up-policy').prepend($hideScaleUp);
$autoscalerDialog.find('div.scale-down-policy ').prepend($hideScaleDown);
$autoscalerDialog.find('div.scale-up-policy').prepend($scaleUpHideLabel);
$autoscalerDialog.find('div.scale-down-policy').prepend($scaleDownHideLabel);
/*Toggling the labels and data-item table - SCALE UP POLICY*/
$autoscalerDialog.find('div.scale-up-policy div.hide').click(function() {
$autoscalerDialog.find('div.scale-up-policy div.multi-edit div.data-item').slideToggle();
$scaleUpLabel = $autoscalerDialog.find('div.scale-up-policy div.slide-label').replaceWith($scaleUpLabel);
});
/*Toggling the images */
$('div.ui-dialog div.autoscaler div.scale-up-policy div.hide').click(function() {
$(this).toggleClass('expand hide');
});
$('div.ui-dialog div.autoscaler div.scale-down-policy div.hide').click(function() {
$(this).toggleClass('expand hide');
});
/*Toggling the labels and data-item table - SCALE DOWN POLICY*/
$('div.ui-dialog div.autoscaler div.scale-down-policy div.hide').click(function() {
$('div.ui-dialog div.autoscaler div.scale-down-policy div.multi-edit div.data div.data-item').slideToggle();
$scaleDownLabel = $('div.ui-dialog div.autoscaler div.scale-down-policy div.slide-label').replaceWith($scaleDownLabel);
});
$('div.ui-dialog div.autoscaler div.scale-down-policy div.multi-edit div.data div.expand').click(function() {
$('div.ui-dialog div.autoscaler div.scale-down-policy div.multi-edit div.data div.data-item').slideToggle();
});
$autoscalerDialog.dialog('option', 'position', 'center');
$autoscalerDialog.dialog('option', 'height', 'auto');
// Setup actions
renderActions(args).prependTo($autoscalerDialog);
};
var $loading = $('<div>').addClass('loading-overlay').appendTo($autoscalerDialog);
$autoscalerDialog.dialog({
title: 'AutoScale Configuration Wizard',
width: 825,
height: 600,
draggable: true,
closeonEscape: false,
overflow: 'auto',
open: function() {
$("button").each(function() {
$(this).attr("style", "left: 600px; position: relative; margin-right: 5px; ");
});
},
buttons: [{
text: _l('label.cancel'),
'class': 'cancel',
click: function() {
$autoscalerDialog.dialog('destroy');
$('.overlay').remove();
}
}, {
text: _l('Apply'),
'class': 'ok',
click: function() {
var data = cloudStack.serializeForm($('.ui-dialog .autoscaler form'));
// Pass VPC data
if (formData.tier) {
data.tier = formData.tier;
}
$loading.appendTo($autoscalerDialog);
cloudStack.autoscaler.actions.apply({
formData: formData,
context: context,
data: data,
response: {
success: function() {
$loading.remove();
$autoscalerDialog.dialog('destroy');
$autoscalerDialog.closest(':ui-dialog').remove();
$('.overlay').remove();
cloudStack.dialog.notice({
message: 'Autoscale configured successfully.'
});
},
error: function(message) {
cloudStack.dialog.notice({
message: message
});
$loading.remove();
}
}
});
}
}]
}).closest('.ui-dialog').overlay();
dataProvider({
context: context,
response: {
success: function(args) {
$loading.remove();
renderDialogContent(args);
if (args.data == null) { //from a new LB rule
$autoscalerDialog.find('select[name=serviceOfferingId]').removeAttr('disabled');
$autoscalerDialog.find('select[name=securityGroups]').removeAttr('disabled');
$autoscalerDialog.find('select[name=diskOfferingId]').removeAttr('disabled');
} else { //from an existing LB rule
$autoscalerDialog.find('select[name=serviceOfferingId]').attr('disabled', true);
$autoscalerDialog.find('select[name=securityGroups]').attr('disabled', true);
$autoscalerDialog.find('select[name=diskOfferingId]').attr('disabled', true);
if (args.data.isAdvanced != null) {
$autoscalerDialog.find('input[type=checkbox]').trigger('click');
$autoscalerDialog.find('input[type=checkbox]').attr('checked', 'checked');
}
}
}
}
});
};
}; };
};
}(jQuery, cloudStack)); }(jQuery, cloudStack));

View File

@ -15,178 +15,191 @@
// specific language governing permissions and limitations // specific language governing permissions and limitations
// under the License. // under the License.
(function($, cloudStack) { (function($, cloudStack) {
cloudStack.uiCustom.dashboard = function() { cloudStack.uiCustom.dashboard = function() {
/** /**
* Retrieve chart data * Retrieve chart data
*/ */
var getData = function() { var getData = function() {
// Populate data // Populate data
$dashboard.find('[data-item]').hide(); $dashboard.find('[data-item]').hide();
cloudStack.sections.dashboard[dashboardType].dataProvider({ cloudStack.sections.dashboard[dashboardType].dataProvider({
response: { response: {
success: function(args) { success: function(args) {
var $browser = $dashboard.closest('#browser .container'); var $browser = $dashboard.closest('#browser .container');
var data = args.data; var data = args.data;
// Iterate over data; populate corresponding DOM elements // Iterate over data; populate corresponding DOM elements
$.each(data, function(key, value) { $.each(data, function(key, value) {
var $elem = $dashboard.find('[data-item=' + key + ']'); var $elem = $dashboard.find('[data-item=' + key + ']');
// This assumes an array of data // This assumes an array of data
if ($elem.is('ul')) { if ($elem.is('ul')) {
$elem.show(); $elem.show();
var $liTmpl = $elem.find('li').remove(); var $liTmpl = $elem.find('li').remove();
$(value).each(function() { $(value).each(function() {
var item = this; var item = this;
var $li = $liTmpl.clone().appendTo($elem).hide(); var $li = $liTmpl.clone().appendTo($elem).hide();
if ($li.is('.zone-stats li')) { if ($li.is('.zone-stats li')) {
$li.click(function() { $li.click(function() {
$browser.cloudBrowser('addPanel', { $browser.cloudBrowser('addPanel', {
title: _l('label.zone.details'), title: _l('label.zone.details'),
parent: $dashboard.closest('.panel'), parent: $dashboard.closest('.panel'),
maximizeIfSelected: true, maximizeIfSelected: true,
complete: function($newPanel) { complete: function($newPanel) {
$newPanel.detailView($.extend(true, {}, $newPanel.detailView($.extend(true, {},
cloudStack.sections.dashboard.admin.zoneDetailView, cloudStack.sections.dashboard.admin.zoneDetailView, {
{ $browser: $browser,
$browser: $browser, context: $.extend(true, {}, cloudStack.context, {
context: $.extend(true, {}, cloudStack.context, { physicalResources: [{
physicalResources: [{ id: item.zoneID }] id: item.zoneID
}) }]
})
} }
)); ));
} }
}); });
}); });
} }
$.each(item, function(arrayKey, arrayValue) { $.each(item, function(arrayKey, arrayValue) {
if (!arrayValue) arrayValue = ''; if (!arrayValue) arrayValue = '';
var $arrayElem = $li.find('[data-list-item=' + arrayKey + ']'); var $arrayElem = $li.find('[data-list-item=' + arrayKey + ']');
$arrayElem.each(function() { $arrayElem.each(function() {
var $arrayElem = $(this); var $arrayElem = $(this);
if ($arrayElem.hasClass('pie-chart')) { if ($arrayElem.hasClass('pie-chart')) {
// Generate pie chart // Generate pie chart
// -- values above 80 have a red color // -- values above 80 have a red color
setTimeout(function() { setTimeout(function() {
pieChart($arrayElem, [ pieChart($arrayElem, [{
{ data: [[1, 100 - arrayValue]], color: '#54697e' }, data: [
{ data: [[1, arrayValue]], color: arrayValue < 80 ? 'orange' : 'red' } [1, 100 - arrayValue]
]); ],
color: '#54697e'
}, {
data: [
[1, arrayValue]
],
color: arrayValue < 80 ? 'orange' : 'red'
}]);
});
} else {
if ($li.attr('concat-value')) {
var val = $(_l(arrayValue).toString().split(', ')).map(function() {
var val = _s(this.toString());
var concatValue = parseInt($li.attr('concat-value'));
return val.length >= concatValue ?
val.substring(0, concatValue).concat('...') : val;
}).toArray().join('<br />');
$arrayElem.html(val);
} else {
$arrayElem.html(_s(_l(arrayValue)));
}
$arrayElem.attr('title', _l(arrayValue).toString().replace('<br/>', ', '));
}
});
});
$li.attr({
title: _s(_l(item.description))
});
$li.fadeIn();
});
} else {
$elem.each(function() {
var $item = $(this);
if ($item.hasClass('chart-line')) {
$item.show().animate({
width: value + '%'
});
} else {
$item.hide().html(_s(value)).fadeIn();
}
});
}
}); });
} else { }
if ($li.attr('concat-value')) { }
var val = $(_l(arrayValue).toString().split(', ')).map(function() { });
var val = _s(this.toString()); };
var concatValue = parseInt($li.attr('concat-value'));
return val.length >= concatValue ? /**
val.substring(0, concatValue).concat('...') : val; * Render circular pie chart, without labels
}).toArray().join('<br />'); */
var pieChart = function($container, data) {
$arrayElem.html(val); $container.css({
} else { width: 70,
$arrayElem.html(_s(_l(arrayValue))); height: 66
});
$.plot($container, data, {
width: 100,
height: 100,
series: {
pie: {
innerRadius: 0.7,
show: true,
label: {
show: false
} }
}
$arrayElem.attr('title', _l(arrayValue).toString().replace('<br/>', ', ')); },
} legend: {
}); show: false
}); }
$li.attr({ title: _s(_l(item.description)) });
$li.fadeIn();
});
} else {
$elem.each(function() {
var $item = $(this);
if ($item.hasClass('chart-line')) {
$item.show().animate({ width: value + '%' });
} else {
$item.hide().html(_s(value)).fadeIn();
}
});
}
}); });
} };
}
});
};
/** // Determine if user or admin dashboard should be shown
* Render circular pie chart, without labels var dashboardType = cloudStack.sections.dashboard.adminCheck({
*/ context: cloudStack.context
var pieChart = function($container, data) { }) ? 'admin' : 'user';
$container.css({ width: 70, height: 66 });
$.plot($container, data, {
width: 100,
height: 100,
series: {
pie: {
innerRadius: 0.7,
show: true,
label: {
show: false
}
}
},
legend: {
show: false
}
});
};
// Determine if user or admin dashboard should be shown // Get dashboard layout
var dashboardType = cloudStack.sections.dashboard.adminCheck({ var $dashboard = $('#template').find('div.dashboard.' + dashboardType).clone();
context: cloudStack.context
}) ? 'admin' : 'user';
// Get dashboard layout // Update text
var $dashboard = $('#template').find('div.dashboard.' + dashboardType).clone(); $dashboard.find('.button.view-all').html(_l('label.view.all'));
$dashboard.find('.dashboard-container.sub.alerts.first .top .title span').html(_l('label.general.alerts'));
$dashboard.find('.dashboard-container.sub.alerts.last .top .title span').html(_l('label.host.alerts'));
$dashboard.find('.dashboard-container.head .top .title span').html(_l('label.system.capacity'));
// Update text // View all action
$dashboard.find('.button.view-all').html(_l('label.view.all')); $dashboard.find('.view-all').click(function() {
$dashboard.find('.dashboard-container.sub.alerts.first .top .title span').html(_l('label.general.alerts')); var $browser = $('#browser .container');
$dashboard.find('.dashboard-container.sub.alerts.last .top .title span').html(_l('label.host.alerts'));
$dashboard.find('.dashboard-container.head .top .title span').html(_l('label.system.capacity'));
// View all action if ($(this).hasClass('network')) $('#navigation li.network').click();
$dashboard.find('.view-all').click(function() { else {
var $browser = $('#browser .container'); $browser.cloudBrowser('addPanel', {
title: $dashboard.hasClass('admin') ? 'Alerts' : 'Events',
if ($(this).hasClass('network')) $('#navigation li.network').click(); maximizeIfSelected: true,
else { complete: function($newPanel) {
$browser.cloudBrowser('addPanel', { $newPanel.listView({
title: $dashboard.hasClass('admin') ? 'Alerts' : 'Events', $browser: $browser,
maximizeIfSelected: true, context: cloudStack.context,
complete: function($newPanel) { listView: $dashboard.hasClass('admin') ? cloudStack.sections.events.sections.alerts.listView : cloudStack.sections.events.sections.events.listView // Users cannot see events
$newPanel.listView({ });
$browser: $browser, }
context: cloudStack.context, });
listView: $dashboard.hasClass('admin') ? };
cloudStack.sections.events.sections.alerts.listView :
cloudStack.sections.events.sections.events.listView // Users cannot see events
});
}
}); });
};
});
//Fetch Latest action //Fetch Latest action
$dashboard.find('.fetch-latest').click(function() { $dashboard.find('.fetch-latest').click(function() {
window.fetchLatestflag = 1; window.fetchLatestflag = 1;
var $browser = $('#browser .container'); var $browser = $('#browser .container');
if ($(this).hasClass('fetch-latest')) $('#navigation li.dashboard').click(); if ($(this).hasClass('fetch-latest')) $('#navigation li.dashboard').click();
}); });
getData(); getData();
return $dashboard; return $dashboard;
}; };
}(jQuery, cloudStack)); }(jQuery, cloudStack));

View File

@ -15,157 +15,160 @@
// specific language governing permissions and limitations // specific language governing permissions and limitations
// under the License. // under the License.
(function(cloudStack, $) { (function(cloudStack, $) {
cloudStack.uiCustom.enableStaticNAT = function(args) { cloudStack.uiCustom.enableStaticNAT = function(args) {
var listView = args.listView; var listView = args.listView;
var action = args.action; var action = args.action;
var tierSelect = args.tierSelect; var tierSelect = args.tierSelect;
return function(args) { return function(args) {
var context = args.context; var context = args.context;
var $instanceRow = args.$instanceRow; var $instanceRow = args.$instanceRow;
var vmList = function(args) { var vmList = function(args) {
// Create a listing of instances, based on limited information // Create a listing of instances, based on limited information
// from main instances list view // from main instances list view
var $listView; var $listView;
var instances = $.extend(true, {}, args.listView, { var instances = $.extend(true, {}, args.listView, {
context: context, context: context,
uiCustom: true uiCustom: true
});
instances.listView.actions = {
select: {
label: _l('label.select.instance'),
type: 'radio',
action: {
uiCustom: function(args) {
var $item = args.$item;
var $input = $item.find('td.actions input:visible');
if ($input.attr('type') == 'checkbox') {
if ($input.is(':checked'))
$item.addClass('multi-edit-selected');
else
$item.removeClass('multi-edit-selected');
} else {
$item.siblings().removeClass('multi-edit-selected');
$item.addClass('multi-edit-selected');
}
}
}
}
};
$listView = $('<div>').listView(instances);
// Change action label
$listView.find('th.actions').html(_l('label.select'));
return $listView;
};
var $dataList = vmList({
listView: listView
}).dialog({
dialogClass: 'multi-edit-add-list panel',
width: 825,
title: _l('label.select.vm.for.static.nat'),
buttons: [
{
text: _l('label.apply'),
'class': 'ok',
click: function() {
if ($dataList.find('.tier-select select').val() == -1) {
cloudStack.dialog.notice({ message: ('Please select a tier')});
return false;
}
if (!$dataList.find(
'input[type=radio]:checked, input[type=checkbox]:checked'
).size()) {
cloudStack.dialog.notice({ message: _l('message.select.instance')});
return false;
}
var complete = args.complete;
var start = args.start;
start();
$dataList.fadeOut(function() {
action({
tierID: $dataList.find('.tier-select select').val(),
_subselect: $dataList.find('tr.multi-edit-selected .subselect select').val(),
context: $.extend(true, {}, context, {
instances: [
$dataList.find('tr.multi-edit-selected').data('json-obj')
]
}),
response: {
success: function(args) {
complete({
$item: $instanceRow
});
},
error: function(args) {
cloudStack.dialog.notice({ message: args });
}
}
}); });
$dataList.remove();
});
$('div.overlay').fadeOut(function() { instances.listView.actions = {
$('div.overlay').remove(); select: {
}); label: _l('label.select.instance'),
type: 'radio',
action: {
uiCustom: function(args) {
var $item = args.$item;
var $input = $item.find('td.actions input:visible');
if ($input.attr('type') == 'checkbox') {
if ($input.is(':checked'))
$item.addClass('multi-edit-selected');
else
$item.removeClass('multi-edit-selected');
} else {
$item.siblings().removeClass('multi-edit-selected');
$item.addClass('multi-edit-selected');
}
}
}
}
};
$listView = $('<div>').listView(instances);
// Change action label
$listView.find('th.actions').html(_l('label.select'));
return $listView;
};
var $dataList = vmList({
listView: listView
}).dialog({
dialogClass: 'multi-edit-add-list panel',
width: 825,
title: _l('label.select.vm.for.static.nat'),
buttons: [{
text: _l('label.apply'),
'class': 'ok',
click: function() {
if ($dataList.find('.tier-select select').val() == -1) {
cloudStack.dialog.notice({
message: ('Please select a tier')
});
return false;
}
if (!$dataList.find(
'input[type=radio]:checked, input[type=checkbox]:checked'
).size()) {
cloudStack.dialog.notice({
message: _l('message.select.instance')
});
return false;
}
var complete = args.complete;
var start = args.start;
start();
$dataList.fadeOut(function() {
action({
tierID: $dataList.find('.tier-select select').val(),
_subselect: $dataList.find('tr.multi-edit-selected .subselect select').val(),
context: $.extend(true, {}, context, {
instances: [
$dataList.find('tr.multi-edit-selected').data('json-obj')
]
}),
response: {
success: function(args) {
complete({
$item: $instanceRow
});
},
error: function(args) {
cloudStack.dialog.notice({
message: args
});
}
}
});
$dataList.remove();
});
$('div.overlay').fadeOut(function() {
$('div.overlay').remove();
});
}
}, {
text: _l('label.cancel'),
'class': 'cancel',
click: function() {
$dataList.fadeOut(function() {
$dataList.remove();
});
$('div.overlay').fadeOut(function() {
$('div.overlay').remove();
});
}
}]
}).parent('.ui-dialog').overlay();
// Add tier select dialog
if (tierSelect) {
var $toolbar = $dataList.find('.toolbar');
var $tierSelect = $('<div>').addClass('filters tier-select').prependTo($toolbar);
var $tierSelectLabel = $('<label>').html('Select tier').appendTo($tierSelect);
var $tierSelectInput = $('<select>').appendTo($tierSelect);
// Get tier data
tierSelect({
context: context,
$tierSelect: $tierSelect,
response: {
success: function(args) {
var data = args.data;
$(data).map(function(index, item) {
var $option = $('<option>');
$option.attr('value', item.id);
$option.html(item.description);
$option.appendTo($tierSelectInput);
});
},
error: function(message) {
cloudStack.dialog.notice({
message: message ? message : 'Could not retrieve VPC tiers'
});
}
}
});
} }
}, };
{
text: _l('label.cancel'),
'class': 'cancel',
click: function() {
$dataList.fadeOut(function() {
$dataList.remove();
});
$('div.overlay').fadeOut(function() {
$('div.overlay').remove();
});
}
}
]
}).parent('.ui-dialog').overlay();
// Add tier select dialog
if (tierSelect) {
var $toolbar = $dataList.find('.toolbar');
var $tierSelect = $('<div>').addClass('filters tier-select').prependTo($toolbar);
var $tierSelectLabel = $('<label>').html('Select tier').appendTo($tierSelect);
var $tierSelectInput = $('<select>').appendTo($tierSelect);
// Get tier data
tierSelect({
context: context,
$tierSelect: $tierSelect,
response: {
success: function(args) {
var data = args.data;
$(data).map(function(index, item) {
var $option = $('<option>');
$option.attr('value', item.id);
$option.html(item.description);
$option.appendTo($tierSelectInput);
});
},
error: function(message) {
cloudStack.dialog.notice({
message: message ? message : 'Could not retrieve VPC tiers'
});
}
}
});
}
}; };
};
}(cloudStack, jQuery)); }(cloudStack, jQuery));

View File

@ -16,31 +16,39 @@
// under the License. // under the License.
(function($, cloudStack) { (function($, cloudStack) {
cloudStack.uiCustom.granularSettings = function(args) { cloudStack.uiCustom.granularSettings = function(args) {
var dataProvider = args.dataProvider; var dataProvider = args.dataProvider;
var actions = args.actions; var actions = args.actions;
return function(args) { return function(args) {
var context = args.context; var context = args.context;
var listView = { var listView = {
id: 'settings', id: 'settings',
fields: { fields: {
name: { label: 'label.name' }, name: {
value: { label: 'label.value', editable: true } label: 'label.name'
}, },
actions: { value: {
edit: { label: 'label.value',
label: 'label.change.value', editable: true
action: actions.edit }
} },
}, actions: {
dataProvider: dataProvider edit: {
}; label: 'label.change.value',
action: actions.edit
}
},
dataProvider: dataProvider
};
var $listView = $('<div>').listView({ context: context, listView: listView }); var $listView = $('<div>').listView({
context: context,
listView: listView
});
return $listView; return $listView;
} }
}; };
}(jQuery, cloudStack)); }(jQuery, cloudStack));

View File

@ -17,334 +17,367 @@
(function($, cloudStack) { (function($, cloudStack) {
cloudStack.uiCustom.healthCheck = function(args) { cloudStack.uiCustom.healthCheck = function(args) {
// Place outer args here as local variables // Place outer args here as local variables
// i.e, -- var dataProvider = args.dataProvider // i.e, -- var dataProvider = args.dataProvider
return function(args){ return function(args) {
if(args.context.multiRules == undefined) { //LB rule is not created yet if (args.context.multiRules == undefined) { //LB rule is not created yet
cloudStack.dialog.notice({ message: _l('Health Check can only be configured on a created LB rule') }); cloudStack.dialog.notice({
return; message: _l('Health Check can only be configured on a created LB rule')
} });
return;
}
var formData = args.formData; var formData = args.formData;
var forms = $.extend(true, {}, args.forms); var forms = $.extend(true, {}, args.forms);
var topFieldForm, bottomFieldForm , $topFieldForm , $bottomFieldForm; var topFieldForm, bottomFieldForm, $topFieldForm, $bottomFieldForm;
var topfields = forms.topFields; var topfields = forms.topFields;
var $healthCheckDesc = $('<div>Your load balancer will automatically perform health checks on your cloudstack instances and only route traffic to instances that pass the health check </div>').addClass('health-check-description'); var $healthCheckDesc = $('<div>Your load balancer will automatically perform health checks on your cloudstack instances and only route traffic to instances that pass the health check </div>').addClass('health-check-description');
var $healthCheckConfigTitle = $('<div><br><br>Configuration Options :</div>').addClass('health-check-config-title'); var $healthCheckConfigTitle = $('<div><br><br>Configuration Options :</div>').addClass('health-check-config-title');
var $healthCheckAdvancedTitle = $('<div><br><br> Advanced Options : </div>').addClass('health-check-advanced-title'); var $healthCheckAdvancedTitle = $('<div><br><br> Advanced Options : </div>').addClass('health-check-advanced-title');
var $healthCheckDialog = $('<div>').addClass('health-check'); var $healthCheckDialog = $('<div>').addClass('health-check');
$healthCheckDialog.append($healthCheckDesc); $healthCheckDialog.append($healthCheckDesc);
$healthCheckDialog.append($healthCheckConfigTitle); $healthCheckDialog.append($healthCheckConfigTitle);
var $loadingOnDialog = $('<div>').addClass('loading-overlay'); var $loadingOnDialog = $('<div>').addClass('loading-overlay');
var policyObj = null; var policyObj = null;
var pingpath1 = '/'; var pingpath1 = '/';
var responsetimeout1 = '2'; var responsetimeout1 = '2';
var healthinterval1 = '5'; var healthinterval1 = '5';
var healthythreshold1 = '2'; var healthythreshold1 = '2';
var unhealthythreshold1 = '1'; var unhealthythreshold1 = '1';
$.ajax({ $.ajax({
url: createURL('listLBHealthCheckPolicies'), url: createURL('listLBHealthCheckPolicies'),
data: { data: {
lbruleid: args.context.multiRules[0].id lbruleid: args.context.multiRules[0].id
}, },
async: false, async: false,
success: function(json) { success: function(json) {
if(json.listlbhealthcheckpoliciesresponse.healthcheckpolicies[0].healthcheckpolicy[0] != undefined) { if (json.listlbhealthcheckpoliciesresponse.healthcheckpolicies[0].healthcheckpolicy[0] != undefined) {
policyObj = json.listlbhealthcheckpoliciesresponse.healthcheckpolicies[0].healthcheckpolicy[0]; policyObj = json.listlbhealthcheckpoliciesresponse.healthcheckpolicies[0].healthcheckpolicy[0];
pingpath1 = policyObj.pingpath; //API bug: API doesn't return it pingpath1 = policyObj.pingpath; //API bug: API doesn't return it
responsetimeout1 = policyObj.responsetime; responsetimeout1 = policyObj.responsetime;
healthinterval1 = policyObj.healthcheckinterval; healthinterval1 = policyObj.healthcheckinterval;
healthythreshold1 = policyObj.healthcheckthresshold; healthythreshold1 = policyObj.healthcheckthresshold;
unhealthythreshold1 = policyObj.unhealthcheckthresshold; unhealthythreshold1 = policyObj.unhealthcheckthresshold;
} }
} }
}); });
topFieldForm = cloudStack.dialog.createForm({ topFieldForm = cloudStack.dialog.createForm({
context: args.context, context: args.context,
noDialog: true, // Don't render a dialog, just return $formContainer noDialog: true, // Don't render a dialog, just return $formContainer
form: { form: {
title: '', title: '',
fields:{ fields: {
pingpath: {label: 'Ping Path', validation: {required: false}, defaultValue: pingpath1} pingpath: {
} label: 'Ping Path',
} validation: {
}); required: false
},
defaultValue: pingpath1
}
}
}
});
$topFieldForm = topFieldForm.$formContainer; $topFieldForm = topFieldForm.$formContainer;
$topFieldForm.appendTo($healthCheckDialog); $topFieldForm.appendTo($healthCheckDialog);
$healthCheckDialog.append($healthCheckAdvancedTitle); $healthCheckDialog.append($healthCheckAdvancedTitle);
bottomFieldForm = cloudStack.dialog.createForm({
context: args.context,
noDialog: true,
form: {
title: '',
fields: {
responsetimeout: {
label: 'Response Timeout (in sec)',
validation: {
required: false
},
defaultValue: responsetimeout1
},
healthinterval: {
label: 'Health Check Interval (in sec)',
validation: {
required: false
},
defaultValue: healthinterval1
},
healthythreshold: {
label: 'Healthy Threshold',
validation: {
required: false
},
defaultValue: healthythreshold1
},
unhealthythreshold: {
label: 'Unhealthy Threshold',
validation: {
required: false
},
defaultValue: unhealthythreshold1
}
}
}
});
$bottomFieldForm = bottomFieldForm.$formContainer;
$bottomFieldForm.appendTo($healthCheckDialog);
var buttons = [{
text: _l('label.cancel'),
'class': 'cancel',
click: function() {
$healthCheckDialog.dialog('destroy');
$('.overlay').remove();
}
}];
if (policyObj == null) { //policy is not created yet
buttons.push({
text: _l('Create'),
'class': 'ok',
click: function() {
$loadingOnDialog.appendTo($healthCheckDialog);
var formData = cloudStack.serializeForm($healthCheckDialog.find('form'));
var data = {
lbruleid: args.context.multiRules[0].id,
pingpath: formData.pingpath,
responsetimeout: formData.responsetimeout,
intervaltime: formData.healthinterval,
healthythreshold: formData.healthythreshold,
unhealthythreshold: formData.unhealthythreshold
};
$.ajax({
url: createURL('createLBHealthCheckPolicy'),
data: data,
success: function(json) {
var jobId = json.createlbhealthcheckpolicyresponse.jobid;
var createLBHealthCheckPolicyIntervalId = setInterval(function() {
$.ajax({
url: createURL('queryAsyncJobResult'),
data: {
jobid: jobId
},
success: function(json) {
var result = json.queryasyncjobresultresponse;
if (result.jobstatus == 0) {
return; //Job has not completed
} else {
clearInterval(createLBHealthCheckPolicyIntervalId);
if (result.jobstatus == 1) {
cloudStack.dialog.notice({
message: _l('Health Check Policy has been created')
});
$loadingOnDialog.remove();
$healthCheckDialog.dialog('destroy');
$('.overlay').remove();
} else if (result.jobstatus == 2) {
cloudStack.dialog.notice({
message: _s(result.jobresult.errortext)
});
$loadingOnDialog.remove();
$healthCheckDialog.dialog('destroy');
$('.overlay').remove();
}
}
}
});
}, g_queryAsyncJobResultInterval);
},
error: function(json) {
cloudStack.dialog.notice({
message: _s(json.responseText)
}); //Error message in the API needs to be improved
$healthCheckDialog.dialog('close');
$('.overlay').remove();
}
});
}
});
} else { //policy exists already
buttons.push(
//Update Button (begin) - call delete API first, then create API
{
text: _l('Update'),
'class': 'ok',
click: function() {
$loadingOnDialog.appendTo($healthCheckDialog);
$.ajax({
url: createURL('deleteLBHealthCheckPolicy'),
data: {
id: policyObj.id
},
success: function(json) {
var jobId = json.deletelbhealthcheckpolicyresponse.jobid;
var deleteLBHealthCheckPolicyIntervalId = setInterval(function() {
$.ajax({
url: createURL('queryAsyncJobResult'),
data: {
jobid: jobId
},
success: function(json) {
var result = json.queryasyncjobresultresponse;
if (result.jobstatus == 0) {
return; //Job has not completed
} else {
clearInterval(deleteLBHealthCheckPolicyIntervalId);
if (result.jobstatus == 1) {
var formData = cloudStack.serializeForm($healthCheckDialog.find('form'));
var data = {
lbruleid: args.context.multiRules[0].id,
pingpath: formData.pingpath,
responsetimeout: formData.responsetimeout,
intervaltime: formData.healthinterval,
healthythreshold: formData.healthythreshold,
unhealthythreshold: formData.unhealthythreshold
};
$.ajax({
url: createURL('createLBHealthCheckPolicy'),
data: data,
success: function(json) {
var jobId = json.createlbhealthcheckpolicyresponse.jobid;
var createLBHealthCheckPolicyIntervalId = setInterval(function() {
$.ajax({
url: createURL('queryAsyncJobResult'),
data: {
jobid: jobId
},
success: function(json) {
var result = json.queryasyncjobresultresponse;
if (result.jobstatus == 0) {
return; //Job has not completed
} else {
clearInterval(createLBHealthCheckPolicyIntervalId);
if (result.jobstatus == 1) {
cloudStack.dialog.notice({
message: _l('Health Check Policy has been updated')
});
$loadingOnDialog.remove();
$healthCheckDialog.dialog('destroy');
$('.overlay').remove();
} else if (result.jobstatus == 2) {
cloudStack.dialog.notice({
message: _s(result.jobresult.errortext)
});
$loadingOnDialog.remove();
$healthCheckDialog.dialog('destroy');
$('.overlay').remove();
}
}
}
});
}, g_queryAsyncJobResultInterval);
}
});
} else if (result.jobstatus == 2) {
cloudStack.dialog.notice({
message: _s(result.jobresult.errortext)
});
$loadingOnDialog.remove();
$healthCheckDialog.dialog('destroy');
$('.overlay').remove();
}
}
}
});
}, g_queryAsyncJobResultInterval);
}
});
}
}
//Update Button (end)
,
//Delete Button (begin) - call delete API
{
text: _l('Delete'),
'class': 'delete',
click: function() {
$loadingOnDialog.appendTo($healthCheckDialog);
$.ajax({
url: createURL('deleteLBHealthCheckPolicy'),
data: {
id: policyObj.id
},
success: function(json) {
var jobId = json.deletelbhealthcheckpolicyresponse.jobid;
var deleteLBHealthCheckPolicyIntervalId = setInterval(function() {
$.ajax({
url: createURL('queryAsyncJobResult'),
data: {
jobid: jobId
},
success: function(json) {
var result = json.queryasyncjobresultresponse;
if (result.jobstatus == 0) {
return; //Job has not completed
} else {
clearInterval(deleteLBHealthCheckPolicyIntervalId);
if (result.jobstatus == 1) {
cloudStack.dialog.notice({
message: _l('Health Check Policy has been deleted')
});
$loadingOnDialog.remove();
$healthCheckDialog.dialog('destroy');
$('.overlay').remove();
} else if (result.jobstatus == 2) {
cloudStack.dialog.notice({
message: _s(result.jobresult.errortext)
});
$loadingOnDialog.remove();
$healthCheckDialog.dialog('destroy');
$('.overlay').remove();
}
}
}
});
}, g_queryAsyncJobResultInterval);
}
});
}
}
//Delete Button (end)
);
}
$healthCheckDialog.dialog({
title: 'Health Check Wizard',
width: 600,
height: 600,
draggable: true,
closeonEscape: false,
overflow: 'auto',
open: function() {
$("button").each(function() {
$(this).attr("style", "left: 400px; position: relative; margin-right: 5px; ");
});
$('.ui-dialog .delete').css('left', '140px');
},
buttons: buttons
}).closest('.ui-dialog').overlay();
bottomFieldForm = cloudStack.dialog.createForm ({
context:args.context,
noDialog:true,
form:{
title:'',
fields:{
responsetimeout: {label: 'Response Timeout (in sec)' , validation:{required:false}, defaultValue: responsetimeout1},
healthinterval: {label: 'Health Check Interval (in sec)', validation:{required:false}, defaultValue: healthinterval1},
healthythreshold: {label: 'Healthy Threshold', validation: {required:false}, defaultValue: healthythreshold1},
unhealthythreshold: {label: 'Unhealthy Threshold' , validation: { required:false}, defaultValue: unhealthythreshold1}
}
} }
});
$bottomFieldForm = bottomFieldForm.$formContainer;
$bottomFieldForm.appendTo($healthCheckDialog);
var buttons = [
{
text: _l('label.cancel'),
'class': 'cancel',
click: function() {
$healthCheckDialog.dialog('destroy');
$('.overlay').remove();
}
}
];
if(policyObj == null) { //policy is not created yet
buttons.push(
{
text: _l('Create'),
'class': 'ok',
click: function() {
$loadingOnDialog.appendTo($healthCheckDialog);
var formData = cloudStack.serializeForm($healthCheckDialog.find('form'));
var data = {
lbruleid: args.context.multiRules[0].id,
pingpath: formData.pingpath,
responsetimeout: formData.responsetimeout,
intervaltime: formData.healthinterval,
healthythreshold: formData.healthythreshold,
unhealthythreshold: formData.unhealthythreshold
};
$.ajax({
url: createURL('createLBHealthCheckPolicy'),
data: data,
success: function(json) {
var jobId = json.createlbhealthcheckpolicyresponse.jobid;
var createLBHealthCheckPolicyIntervalId = setInterval(function(){
$.ajax({
url: createURL('queryAsyncJobResult'),
data: {
jobid: jobId
},
success: function(json) {
var result = json.queryasyncjobresultresponse;
if (result.jobstatus == 0) {
return; //Job has not completed
}
else {
clearInterval(createLBHealthCheckPolicyIntervalId);
if (result.jobstatus == 1) {
cloudStack.dialog.notice({ message: _l('Health Check Policy has been created') });
$loadingOnDialog.remove();
$healthCheckDialog.dialog('destroy');
$('.overlay').remove();
}
else if (result.jobstatus == 2) {
cloudStack.dialog.notice({ message: _s(result.jobresult.errortext) });
$loadingOnDialog.remove();
$healthCheckDialog.dialog('destroy');
$('.overlay').remove();
}
}
}
});
}, g_queryAsyncJobResultInterval);
},
error:function(json){
cloudStack.dialog.notice({message: _s(json.responseText)}); //Error message in the API needs to be improved
$healthCheckDialog.dialog('close');
$('.overlay').remove();
}
});
}
}
);
}
else { //policy exists already
buttons.push(
//Update Button (begin) - call delete API first, then create API
{
text: _l('Update'),
'class': 'ok',
click: function() {
$loadingOnDialog.appendTo($healthCheckDialog);
$.ajax({
url: createURL('deleteLBHealthCheckPolicy'),
data: {
id : policyObj.id
},
success: function(json) {
var jobId = json.deletelbhealthcheckpolicyresponse.jobid;
var deleteLBHealthCheckPolicyIntervalId = setInterval(function(){
$.ajax({
url: createURL('queryAsyncJobResult'),
data: {
jobid: jobId
},
success: function(json) {
var result = json.queryasyncjobresultresponse;
if (result.jobstatus == 0) {
return; //Job has not completed
}
else {
clearInterval(deleteLBHealthCheckPolicyIntervalId);
if (result.jobstatus == 1) {
var formData = cloudStack.serializeForm($healthCheckDialog.find('form'));
var data = {
lbruleid: args.context.multiRules[0].id,
pingpath: formData.pingpath,
responsetimeout: formData.responsetimeout,
intervaltime: formData.healthinterval,
healthythreshold: formData.healthythreshold,
unhealthythreshold: formData.unhealthythreshold
};
$.ajax({
url: createURL('createLBHealthCheckPolicy'),
data: data,
success: function(json) {
var jobId = json.createlbhealthcheckpolicyresponse.jobid;
var createLBHealthCheckPolicyIntervalId = setInterval(function(){
$.ajax({
url: createURL('queryAsyncJobResult'),
data: {
jobid: jobId
},
success: function(json) {
var result = json.queryasyncjobresultresponse;
if (result.jobstatus == 0) {
return; //Job has not completed
}
else {
clearInterval(createLBHealthCheckPolicyIntervalId);
if (result.jobstatus == 1) {
cloudStack.dialog.notice({ message: _l('Health Check Policy has been updated') });
$loadingOnDialog.remove();
$healthCheckDialog.dialog('destroy');
$('.overlay').remove();
}
else if (result.jobstatus == 2) {
cloudStack.dialog.notice({ message: _s(result.jobresult.errortext) });
$loadingOnDialog.remove();
$healthCheckDialog.dialog('destroy');
$('.overlay').remove();
}
}
}
});
}, g_queryAsyncJobResultInterval);
}
});
}
else if (result.jobstatus == 2) {
cloudStack.dialog.notice({ message: _s(result.jobresult.errortext) });
$loadingOnDialog.remove();
$healthCheckDialog.dialog('destroy');
$('.overlay').remove();
}
}
}
});
}, g_queryAsyncJobResultInterval);
}
});
}
}
//Update Button (end)
,
//Delete Button (begin) - call delete API
{
text: _l('Delete'),
'class': 'delete',
click: function() {
$loadingOnDialog.appendTo($healthCheckDialog);
$.ajax({
url: createURL('deleteLBHealthCheckPolicy'),
data: {
id : policyObj.id
},
success: function(json) {
var jobId = json.deletelbhealthcheckpolicyresponse.jobid;
var deleteLBHealthCheckPolicyIntervalId = setInterval(function(){
$.ajax({
url: createURL('queryAsyncJobResult'),
data: {
jobid: jobId
},
success: function(json) {
var result = json.queryasyncjobresultresponse;
if (result.jobstatus == 0) {
return; //Job has not completed
}
else {
clearInterval(deleteLBHealthCheckPolicyIntervalId);
if (result.jobstatus == 1) {
cloudStack.dialog.notice({ message: _l('Health Check Policy has been deleted') });
$loadingOnDialog.remove();
$healthCheckDialog.dialog('destroy');
$('.overlay').remove();
}
else if (result.jobstatus == 2) {
cloudStack.dialog.notice({ message: _s(result.jobresult.errortext) });
$loadingOnDialog.remove();
$healthCheckDialog.dialog('destroy');
$('.overlay').remove();
}
}
}
});
}, g_queryAsyncJobResultInterval);
}
});
}
}
//Delete Button (end)
);
}
$healthCheckDialog.dialog({
title: 'Health Check Wizard',
width: 600,
height: 600,
draggable: true,
closeonEscape: false,
overflow:'auto',
open:function() {
$("button").each(function(){
$(this).attr("style", "left: 400px; position: relative; margin-right: 5px; ");
});
$('.ui-dialog .delete').css('left','140px');
},
buttons: buttons
}).closest('.ui-dialog').overlay();
} }
} }(jQuery, cloudStack));
}(jQuery, cloudStack));

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -15,152 +15,149 @@
// specific language governing permissions and limitations // specific language governing permissions and limitations
// under the License. // under the License.
(function($, cloudStack) { (function($, cloudStack) {
cloudStack.ipRules = function(args) { cloudStack.ipRules = function(args) {
return function(detailArgs) { return function(detailArgs) {
var context = detailArgs.context; var context = detailArgs.context;
var portMultiEdit = function(args) { var portMultiEdit = function(args) {
return $('<div>').multiEdit(args); return $('<div>').multiEdit(args);
}; };
var makeMultiEditPanel = function($item) { var makeMultiEditPanel = function($item) {
if ($item.closest('li').hasClass('disabled')) if ($item.closest('li').hasClass('disabled'))
return false; return false;
var targetId = $item.attr('net-target'); var targetId = $item.attr('net-target');
var targetName = $item.parent().find('.name').find('span').html(); var targetName = $item.parent().find('.name').find('span').html();
var target = args[targetId]; var target = args[targetId];
var $browser = $item.closest('.detail-view').data('view-args').$browser; var $browser = $item.closest('.detail-view').data('view-args').$browser;
$browser.cloudBrowser('addPanel', {
title: targetName,
maximizeIfSelected: true,
complete: function($newPanel) {
$newPanel.detailView({
$browser: $browser,
name: targetId,
context: context,
tabs: {
network: {
title: targetName,
custom: function(args) {
return portMultiEdit($.extend(target, {
context: context
}));
}
}
}
});
}
});
return true;
};
var staticNATChart = function(args, includingFirewall) {
var $chart = $('#template').find('.network-chart.static-nat').clone();
var $vmName = $chart.find('li.static-nat-enabled .vmname');
var $browser = $('#browser .container');
var vmDataProvider = args.vmDataProvider;
var vmDetails = args.vmDetails;
args.staticNATDataProvider({
context: context,
response: {
success: function(args) {
var vmID = args.data.virtualmachineid;
var vmIP = args.data.vmipaddress;
var vmName = args.data.virtualmachinename;
$vmName.append(
$('<span>').html('VM: ' + _s(vmName)),
$('<span>').html('<br/>VM IP: ' + vmIP)
);
$vmName.click(function() {
$browser.cloudBrowser('addPanel', { $browser.cloudBrowser('addPanel', {
title: _l('label.static.nat.vm.details'), title: targetName,
complete: function($newPanel) { maximizeIfSelected: true,
vmDataProvider({ complete: function($newPanel) {
context: context, $newPanel.detailView({
response: {
success: function(args) {
var instance = args.data;
var detailViewArgs = $.extend(true, {}, vmDetails, {
$browser: $browser, $browser: $browser,
context: $.extend(true, {}, context, { name: targetId,
instances: [instance] context: context,
}), tabs: {
jsonObj: instance, network: {
id: instance.id title: targetName,
}); custom: function(args) {
return portMultiEdit($.extend(target, {
// No actions available context: context
detailViewArgs.actions = {}; }));
}
$newPanel.detailView(detailViewArgs); }
} }
} });
}); }
}
}); });
});
}
}
});
if(includingFirewall == true) { return true;
$chart.find('li.firewall .view-details').click(function() { };
//makeMultiEditPanel($(this), { title: _l('label.nat.port.range')});
makeMultiEditPanel($(this));
});
}
else {
$chart.find('li.firewall').hide();
}
return $chart; var staticNATChart = function(args, includingFirewall) {
}; var $chart = $('#template').find('.network-chart.static-nat').clone();
var $vmName = $chart.find('li.static-nat-enabled .vmname');
var $browser = $('#browser .container');
var vmDataProvider = args.vmDataProvider;
var vmDetails = args.vmDetails;
var netChart = function(args) { args.staticNATDataProvider({
context: context,
response: {
success: function(args) {
var vmID = args.data.virtualmachineid;
var vmIP = args.data.vmipaddress;
var vmName = args.data.virtualmachinename;
var $chart = $('#template').find('.network-chart.normal').clone(); $vmName.append(
var preFilter = args.preFilter ? args.preFilter({ $('<span>').html('VM: ' + _s(vmName)),
items: ['firewall', 'portForwarding', 'loadBalancing'], $('<span>').html('<br/>VM IP: ' + vmIP)
context: context );
}) : [];
// 1. choose between staticNAT chart and non-staticNAT chart 2. filter disabled tabs $vmName.click(function() {
if (preFilter.length) { $browser.cloudBrowser('addPanel', {
if($.inArray('nonStaticNATChart', preFilter) != -1) { //choose static NAT chart title: _l('label.static.nat.vm.details'),
if($.inArray('firewall', preFilter) == -1) { complete: function($newPanel) {
return staticNATChart(args, true); //static NAT including Firewall vmDataProvider({
} context: context,
else { response: {
return staticNATChart(args, false); //static NAT excluding Firewall success: function(args) {
} var instance = args.data;
} var detailViewArgs = $.extend(true, {}, vmDetails, {
else { //choose non-static NAT chart $browser: $browser,
$(preFilter).each(function() { context: $.extend(true, {}, context, {
var id = this; instances: [instance]
}),
jsonObj: instance,
id: instance.id
});
var $li = $chart.find('li').filter(function() { // No actions available
return $(this).hasClass(id); detailViewArgs.actions = {};
}).addClass('disabled');
});
}
}
$chart.find('.view-details').click(function() { $newPanel.detailView(detailViewArgs);
makeMultiEditPanel($(this)); }
return false; }
}); });
}
});
});
}
}
});
return $chart; if (includingFirewall == true) {
}; $chart.find('li.firewall .view-details').click(function() {
//makeMultiEditPanel($(this), { title: _l('label.nat.port.range')});
makeMultiEditPanel($(this));
});
} else {
$chart.find('li.firewall').hide();
}
return netChart(args); return $chart;
};
var netChart = function(args) {
var $chart = $('#template').find('.network-chart.normal').clone();
var preFilter = args.preFilter ? args.preFilter({
items: ['firewall', 'portForwarding', 'loadBalancing'],
context: context
}) : [];
// 1. choose between staticNAT chart and non-staticNAT chart 2. filter disabled tabs
if (preFilter.length) {
if ($.inArray('nonStaticNATChart', preFilter) != -1) { //choose static NAT chart
if ($.inArray('firewall', preFilter) == -1) {
return staticNATChart(args, true); //static NAT including Firewall
} else {
return staticNATChart(args, false); //static NAT excluding Firewall
}
} else { //choose non-static NAT chart
$(preFilter).each(function() {
var id = this;
var $li = $chart.find('li').filter(function() {
return $(this).hasClass(id);
}).addClass('disabled');
});
}
}
$chart.find('.view-details').click(function() {
makeMultiEditPanel($(this));
return false;
});
return $chart;
};
return netChart(args);
};
}; };
};
})(jQuery, cloudStack); })(jQuery, cloudStack);

View File

@ -15,133 +15,135 @@
// specific language governing permissions and limitations // specific language governing permissions and limitations
// under the License. // under the License.
(function($, cloudStack) { (function($, cloudStack) {
/** /**
* Login process * Login process
*/ */
cloudStack.uiCustom.login = function(args) { cloudStack.uiCustom.login = function(args) {
var $container = args.$container; var $container = args.$container;
var $login = $('#template').find('.login').clone(); var $login = $('#template').find('.login').clone();
var $form = $login.find('form'); var $form = $login.find('form');
var $inputs = $form.find('input[type=text], input[type=password]'); var $inputs = $form.find('input[type=text], input[type=password]');
var complete = args.complete; var complete = args.complete;
var bypass = args.bypassLoginCheck && args.bypassLoginCheck(); var bypass = args.bypassLoginCheck && args.bypassLoginCheck();
// Check to see if we can bypass login screen // Check to see if we can bypass login screen
if (bypass) { if (bypass) {
complete({
user: bypass.user
});
$(window).trigger('cloudStack.init');
return;
}
$login.appendTo('html body');
$('html body').addClass('login');
// Remove label if field was auto filled
$.each($form.find('label'), function() {
var $label = $(this);
var $input = $form.find('input').filter(function() {
return $(this).attr('name') == $label.attr('for');
});
if ($input.val()) {
$label.hide();
}
});
// Form validation
$form.validate();
// Form label behavior
$inputs.bind('keydown focus click blur', function(event) {
var $target = $(event.target);
var $label = $form.find('label').filter(function() {
return $(this).attr('for') == $target.attr('name');
});
if (event.type == 'keydown') {
$label.hide();
return true;
} else if (event.type == 'blur') {
if ($target.hasClass('first-input')) {
$target.removeClass('first-input');
}
if (!$(this).val()) {
$label.show();
}
} else {
if (!$target.hasClass('first-input')) {
$label.hide();
}
}
return true;
});
if (!args.hasLogo) $login.addClass('nologo');
// Labels cause related input to be focused
$login.find('label').click(function() {
var $input = $inputs.filter('[name=' + $(this).attr('for') + ']');
var $label = $(this);
$input.focus();
$label.hide();
});
$inputs.filter(':first').addClass('first-input').focus();
// Login action
$login.find('input[type=submit]').click(function() {
if (!$form.valid()) return false;
var data = cloudStack.serializeForm($form);
args.loginAction({
data: data,
response: {
success: function(args) {
$login.remove();
$('html body').removeClass('login');
complete({ complete({
user: args.data.user user: bypass.user
}); });
}, $(window).trigger('cloudStack.init');
error: function(args) {
cloudStack.dialog.notice({ message: args }); return;
}
} }
});
return false; $login.appendTo('html body');
}); $('html body').addClass('login');
// Select language // Remove label if field was auto filled
var $languageSelect = $login.find('select[name=language]'); $.each($form.find('label'), function() {
$languageSelect.change(function() { var $label = $(this);
if($(this).val() != '') //language dropdown is not blank var $input = $form.find('input').filter(function() {
$.cookie('lang', $(this).val()); //the selected option in language dropdown will be used (instead of browser's default language) return $(this).attr('name') == $label.attr('for');
else //language dropdown is blank });
$.cookie('lang', null); //null $.cookie('lang'), so browser's default language will be used. if ($input.val()) {
document.location.reload(); $label.hide();
}); }
});
$languageSelect.val($.cookie('lang')); // Form validation
$form.validate();
// Hide login screen, mainly for SSO // Form label behavior
if (args.hideLoginScreen) { $inputs.bind('keydown focus click blur', function(event) {
$login.children().hide(); var $target = $(event.target);
$login.append($('<div>').addClass('loading-overlay').append( var $label = $form.find('label').filter(function() {
$('<span>').html( return $(this).attr('for') == $target.attr('name');
// _l is not set yet, so localize directly to dictionary });
// [should fix in future]
dictionary['label.loading'] + '...'
)
));
}
$(window).trigger('cloudStack.init'); if (event.type == 'keydown') {
}; $label.hide();
return true;
} else if (event.type == 'blur') {
if ($target.hasClass('first-input')) {
$target.removeClass('first-input');
}
if (!$(this).val()) {
$label.show();
}
} else {
if (!$target.hasClass('first-input')) {
$label.hide();
}
}
return true;
});
if (!args.hasLogo) $login.addClass('nologo');
// Labels cause related input to be focused
$login.find('label').click(function() {
var $input = $inputs.filter('[name=' + $(this).attr('for') + ']');
var $label = $(this);
$input.focus();
$label.hide();
});
$inputs.filter(':first').addClass('first-input').focus();
// Login action
$login.find('input[type=submit]').click(function() {
if (!$form.valid()) return false;
var data = cloudStack.serializeForm($form);
args.loginAction({
data: data,
response: {
success: function(args) {
$login.remove();
$('html body').removeClass('login');
complete({
user: args.data.user
});
},
error: function(args) {
cloudStack.dialog.notice({
message: args
});
}
}
});
return false;
});
// Select language
var $languageSelect = $login.find('select[name=language]');
$languageSelect.change(function() {
if ($(this).val() != '') //language dropdown is not blank
$.cookie('lang', $(this).val()); //the selected option in language dropdown will be used (instead of browser's default language)
else //language dropdown is blank
$.cookie('lang', null); //null $.cookie('lang'), so browser's default language will be used.
document.location.reload();
});
$languageSelect.val($.cookie('lang'));
// Hide login screen, mainly for SSO
if (args.hideLoginScreen) {
$login.children().hide();
$login.append($('<div>').addClass('loading-overlay').append(
$('<span>').html(
// _l is not set yet, so localize directly to dictionary
// [should fix in future]
dictionary['label.loading'] + '...'
)
));
}
$(window).trigger('cloudStack.init');
};
})(jQuery, cloudStack); })(jQuery, cloudStack);

View File

@ -15,123 +15,139 @@
// specific language governing permissions and limitations // specific language governing permissions and limitations
// under the License. // under the License.
(function(cloudStack, $) { (function(cloudStack, $) {
cloudStack.uiCustom.physicalResources = function(args) { cloudStack.uiCustom.physicalResources = function(args) {
var listView = function(targetID) { var listView = function(targetID) {
var target = args.sections.physicalResources.listView[targetID]; var target = args.sections.physicalResources.listView[targetID];
var listViewArgs = $.isFunction(target) ? target() : target; var listViewArgs = $.isFunction(target) ? target() : target;
return $('<div>').listView( return $('<div>').listView(
(listViewArgs.listView || listViewArgs.sections) ? listViewArgs : { listView: listViewArgs } (listViewArgs.listView || listViewArgs.sections) ? listViewArgs : {
); listView: listViewArgs
}; }
var $dashboard = $('#template').find('.system-dashboard-view').clone(); );
var getData = function() { };
// Populate data var $dashboard = $('#template').find('.system-dashboard-view').clone();
$dashboard.find('[data-item]').hide(); var getData = function() {
cloudStack.sections.system.dashboard.dataProvider({ // Populate data
response: { $dashboard.find('[data-item]').hide();
success: function(args) { cloudStack.sections.system.dashboard.dataProvider({
var data = args.data; response: {
$.each(data, function(key, value) { success: function(args) {
var $elem = $dashboard.find('[data-item=' + key + ']'); var data = args.data;
$elem.hide().html(value).fadeIn(); $.each(data, function(key, value) {
}); var $elem = $dashboard.find('[data-item=' + key + ']');
} $elem.hide().html(value).fadeIn();
} });
});
};
var resourceChart = function(args) {
getData();
return $dashboard
.click(function(event) {
var $target = $(event.target);
if ($target.closest('[view-all-target]').size()) {
var targetID = $target.closest('[view-all-target]').attr('view-all-target');
args.$browser.cloudBrowser('addPanel', {
title: $target.closest('[view-all-title]').attr('view-all-title'),
data: '',
noSelectPanel: true,
maximizeIfSelected: true,
complete: function($newPanel) {
listView(targetID).appendTo($newPanel);
}
});
}
});
};
$(window).bind('cloudStack.fullRefresh cloudStack.updateResources', function() {
if ($dashboard.is(':visible')) {
getData();
}
});
return function(args) {
$dashboard.find('#update_ssl_button').click(function() {
cloudStack.dialog.createForm({
form: {
title: 'label.update.ssl',
desc: 'message.update.ssl',
fields: {
certificate: { label: 'label.certificate', isTextarea: true },
privatekey: { label: 'label.privatekey', isTextarea: true },
domainsuffix: { label: 'label.domain.suffix' }
}
},
after: function(args) {
var $loading = $('<div>').addClass('loading-overlay');
$('.system-dashboard-view:visible').prepend($loading);
$.ajax({
type: "POST",
url: createURL('uploadCustomCertificate'),
data: {
certificate: encodeURIComponent(args.data.certificate),
privatekey: encodeURIComponent(args.data.privatekey),
domainsuffix: args.data.domainsuffix
},
dataType: 'json',
success: function(json) {
var jid = json.uploadcustomcertificateresponse.jobid;
var uploadCustomCertificateIntervalID = setInterval(function() {
$.ajax({
url: createURL("queryAsyncJobResult&jobId=" + jid),
dataType: "json",
success: function(json) {
var result = json.queryasyncjobresultresponse;
if (result.jobstatus == 0) {
return; //Job has not completed
}
else {
clearInterval(uploadCustomCertificateIntervalID);
if (result.jobstatus == 1) {
cloudStack.dialog.notice({ message: 'Update SSL Certiciate succeeded' });
}
else if (result.jobstatus == 2) {
cloudStack.dialog.notice({ message: 'Failed to update SSL Certificate. ' + _s(result.jobresult.errortext) });
}
$loading.remove();
}
},
error: function(XMLHttpResponse) {
cloudStack.dialog.notice({ message: 'Failed to update SSL Certificate. ' + parseXMLHttpResponse(XMLHttpResponse) });
$loading.remove();
} }
}); }
}, g_queryAsyncJobResultInterval);
},
error: function(XMLHttpResponse) {
cloudStack.dialog.notice({ message: 'Failed to update SSL Certificate. ' + parseXMLHttpResponse(XMLHttpResponse) });
$loading.remove();
}
}); });
}, };
context: {} var resourceChart = function(args) {
getData();
return $dashboard
.click(function(event) {
var $target = $(event.target);
if ($target.closest('[view-all-target]').size()) {
var targetID = $target.closest('[view-all-target]').attr('view-all-target');
args.$browser.cloudBrowser('addPanel', {
title: $target.closest('[view-all-title]').attr('view-all-title'),
data: '',
noSelectPanel: true,
maximizeIfSelected: true,
complete: function($newPanel) {
listView(targetID).appendTo($newPanel);
}
});
}
});
};
$(window).bind('cloudStack.fullRefresh cloudStack.updateResources', function() {
if ($dashboard.is(':visible')) {
getData();
}
}); });
return false; return function(args) {
}); $dashboard.find('#update_ssl_button').click(function() {
$dashboard.find('#refresh_button').click(function() { cloudStack.dialog.createForm({
getData(); form: {
return false; title: 'label.update.ssl',
}); desc: 'message.update.ssl',
return resourceChart(args); fields: {
certificate: {
label: 'label.certificate',
isTextarea: true
},
privatekey: {
label: 'label.privatekey',
isTextarea: true
},
domainsuffix: {
label: 'label.domain.suffix'
}
}
},
after: function(args) {
var $loading = $('<div>').addClass('loading-overlay');
$('.system-dashboard-view:visible').prepend($loading);
$.ajax({
type: "POST",
url: createURL('uploadCustomCertificate'),
data: {
certificate: encodeURIComponent(args.data.certificate),
privatekey: encodeURIComponent(args.data.privatekey),
domainsuffix: args.data.domainsuffix
},
dataType: 'json',
success: function(json) {
var jid = json.uploadcustomcertificateresponse.jobid;
var uploadCustomCertificateIntervalID = setInterval(function() {
$.ajax({
url: createURL("queryAsyncJobResult&jobId=" + jid),
dataType: "json",
success: function(json) {
var result = json.queryasyncjobresultresponse;
if (result.jobstatus == 0) {
return; //Job has not completed
} else {
clearInterval(uploadCustomCertificateIntervalID);
if (result.jobstatus == 1) {
cloudStack.dialog.notice({
message: 'Update SSL Certiciate succeeded'
});
} else if (result.jobstatus == 2) {
cloudStack.dialog.notice({
message: 'Failed to update SSL Certificate. ' + _s(result.jobresult.errortext)
});
}
$loading.remove();
}
},
error: function(XMLHttpResponse) {
cloudStack.dialog.notice({
message: 'Failed to update SSL Certificate. ' + parseXMLHttpResponse(XMLHttpResponse)
});
$loading.remove();
}
});
}, g_queryAsyncJobResultInterval);
},
error: function(XMLHttpResponse) {
cloudStack.dialog.notice({
message: 'Failed to update SSL Certificate. ' + parseXMLHttpResponse(XMLHttpResponse)
});
$loading.remove();
}
});
},
context: {}
});
return false;
});
$dashboard.find('#refresh_button').click(function() {
getData();
return false;
});
return resourceChart(args);
};
}; };
};
}(cloudStack, jQuery)); }(cloudStack, jQuery));

View File

@ -15,95 +15,107 @@
// specific language governing permissions and limitations // specific language governing permissions and limitations
// under the License. // under the License.
(function($, cloudStack) { (function($, cloudStack) {
var elems = { var elems = {
pluginItem: function(args) { pluginItem: function(args) {
var id = args.id; var id = args.id;
var title = args.title; var title = args.title;
var desc = args.desc; var desc = args.desc;
var iconURL = args.iconURL; var iconURL = args.iconURL;
var $pluginItem = $('<li>').addClass('plugin-item').addClass(id); var $pluginItem = $('<li>').addClass('plugin-item').addClass(id);
var $title = $('<span>').addClass('title').html(title); var $title = $('<span>').addClass('title').html(title);
var $desc = $('<span>').addClass('desc').html(desc); var $desc = $('<span>').addClass('desc').html(desc);
var $icon = $('<span>').addClass('icon').append( var $icon = $('<span>').addClass('icon').append(
$('<img>').attr({ src: iconURL }) $('<img>').attr({
); src: iconURL
})
);
$pluginItem.append( $pluginItem.append(
$icon, $title, $desc $icon, $title, $desc
); );
return $pluginItem; return $pluginItem;
}, },
pluginListing: function(args) { pluginListing: function(args) {
var plugins = args.plugins; var plugins = args.plugins;
var $plugins = $('<ul>'); var $plugins = $('<ul>');
var $pluginsListing = $('<div>').addClass('plugins-listing'); var $pluginsListing = $('<div>').addClass('plugins-listing');
$(plugins).each(function() { $(plugins).each(function() {
var plugin = this; var plugin = this;
var $plugin = elems.pluginItem({ var $plugin = elems.pluginItem({
id: plugin.id, id: plugin.id,
title: plugin.title, title: plugin.title,
desc: plugin.desc, desc: plugin.desc,
iconURL: 'plugins/' + plugin.id + '/icon.png' iconURL: 'plugins/' + plugin.id + '/icon.png'
}); });
var $browser = $('#browser .container'); var $browser = $('#browser .container');
$plugin.click(function() { $plugin.click(function() {
$browser.cloudBrowser('addPanel', { $browser.cloudBrowser('addPanel', {
title: plugin.title, title: plugin.title,
$parent: $('.panel:first'), $parent: $('.panel:first'),
complete: function($panel) { complete: function($panel) {
$panel.detailView({ $panel.detailView({
name: 'Plugin details', name: 'Plugin details',
tabs: { tabs: {
details: { details: {
title: 'label.plugin.details', title: 'label.plugin.details',
fields: [ fields: [{
{ name: {
name: { label: 'label.name' } label: 'label.name'
}, }
{ }, {
desc: { label: 'label.description' }, desc: {
externalLink: { label: 'label.description'
isExternalLink: true, },
label: 'label.external.link' externalLink: {
isExternalLink: true,
label: 'label.external.link'
}
}, {
authorName: {
label: 'label.author.name'
},
authorEmail: {
label: 'label.author.email'
},
id: {
label: 'label.id'
}
}],
dataProvider: function(args) {
args.response.success({
data: plugin
});
}
}
}
});
} }
}, });
{ });
authorName: { label: 'label.author.name' },
authorEmail: { label: 'label.author.email' }, $plugin.appendTo($plugins);
id: { label: 'label.id' } });
}
], $pluginsListing.append($plugins);
dataProvider: function(args) {
args.response.success({ data: plugin }); return $pluginsListing;
} }
} };
}
}); cloudStack.uiCustom.pluginListing = function() {
} var plugins = cloudStack.plugins;
});
return elems.pluginListing({
plugins: $(plugins).map(function(index, pluginID) {
var plugin = cloudStack.plugins[pluginID].config;
return $.extend(plugin, {
id: pluginID
});
})
}); });
};
$plugin.appendTo($plugins);
});
$pluginsListing.append($plugins);
return $pluginsListing;
}
};
cloudStack.uiCustom.pluginListing = function() {
var plugins = cloudStack.plugins;
return elems.pluginListing({
plugins: $(plugins).map(function(index, pluginID) {
var plugin = cloudStack.plugins[pluginID].config;
return $.extend(plugin, { id: pluginID });
})
});
};
}(jQuery, cloudStack)); }(jQuery, cloudStack));

View File

@ -16,51 +16,52 @@
// under the License. // under the License.
(function($, cloudStack) { (function($, cloudStack) {
$(window).bind('cloudStack.ready', function() { $(window).bind('cloudStack.ready', function() {
var $header = $('#header .controls'); var $header = $('#header .controls');
var $projectSwitcher = $('<div>').addClass('project-switcher'); var $projectSwitcher = $('<div>').addClass('project-switcher');
var $projectSelect = $('<select>').append( var $projectSelect = $('<select>').append(
$('<option>').attr('value', '-1').html(_l('Default view')) $('<option>').attr('value', '-1').html(_l('Default view'))
); );
var $label = $('<label>').html('Project:'); var $label = $('<label>').html('Project:');
// Get project list // Get project list
cloudStack.projects.dataProvider({ cloudStack.projects.dataProvider({
context: cloudStack.context, context: cloudStack.context,
response: { response: {
success: function(args) { success: function(args) {
var projects = args.data; var projects = args.data;
$(projects).map(function(index, project) { $(projects).map(function(index, project) {
var $option = $('<option>').val(_s(project.id)); var $option = $('<option>').val(_s(project.id));
$option.html(_s(project.displaytext ? project.displaytext : project.name)); $option.html(_s(project.displaytext ? project.displaytext : project.name));
$option.appendTo($projectSelect); $option.appendTo($projectSelect);
}); });
}, },
error: function() {} error: function() {}
} }
});
$projectSwitcher.append($label, $projectSelect);
$projectSwitcher.insertBefore($header.find('.region-switcher'));
// Change project event
$projectSelect.change(function() {
var projectID = $projectSelect.val();
if (projectID != -1) {
cloudStack.context.projects = [{
id: projectID
}];
cloudStack.uiCustom.projects({
alreadySelected: true
});
} else {
cloudStack.context.projects = null;
$('#cloudStack3-container').removeClass('project-view');
$('#navigation li.dashboard').click();
}
});
}); });
$projectSwitcher.append($label, $projectSelect);
$projectSwitcher.insertBefore($header.find('.region-switcher'));
// Change project event
$projectSelect.change(function() {
var projectID = $projectSelect.val();
if (projectID != -1) {
cloudStack.context.projects = [{
id: projectID
}];
cloudStack.uiCustom.projects({ alreadySelected: true });
} else {
cloudStack.context.projects = null;
$('#cloudStack3-container').removeClass('project-view');
$('#navigation li.dashboard').click();
}
});
});
}(jQuery, cloudStack)); }(jQuery, cloudStack));

File diff suppressed because it is too large Load Diff

View File

@ -15,200 +15,201 @@
// specific language governing permissions and limitations // specific language governing permissions and limitations
// under the License. // under the License.
(function(cloudStack, $) { (function(cloudStack, $) {
cloudStack.uiCustom.recurringSnapshots = function(args) { cloudStack.uiCustom.recurringSnapshots = function(args) {
var desc = args.desc; var desc = args.desc;
var selects = args.selects; var selects = args.selects;
var actions = args.actions; var actions = args.actions;
var dataProvider = args.dataProvider; var dataProvider = args.dataProvider;
return function(args) { return function(args) {
var $snapshots = $('#template').find('.recurring-snapshots').clone(); var $snapshots = $('#template').find('.recurring-snapshots').clone();
var context = args.context; var context = args.context;
// Update labels // Update labels
$snapshots.find('.forms ul li.hourly a').html(_l('label.hourly')); $snapshots.find('.forms ul li.hourly a').html(_l('label.hourly'));
$snapshots.find('.forms ul li.daily a').html(_l('label.daily')); $snapshots.find('.forms ul li.daily a').html(_l('label.daily'));
$snapshots.find('.forms ul li.weekly a').html(_l('label.weekly')); $snapshots.find('.forms ul li.weekly a').html(_l('label.weekly'));
$snapshots.find('.forms ul li.monthly a').html(_l('label.monthly')); $snapshots.find('.forms ul li.monthly a').html(_l('label.monthly'));
$snapshots.find('.field.timezone .name').html(_l('label.timezone')); $snapshots.find('.field.timezone .name').html(_l('label.timezone'));
$snapshots.find('.field.time .name').html(_l('label.time')); $snapshots.find('.field.time .name').html(_l('label.time'));
$snapshots.find('.field.time .value label').html(_l('label.minute.past.hour')); $snapshots.find('.field.time .value label').html(_l('label.minute.past.hour'));
$snapshots.find('.add-snapshot-action.add').html(_l('label.add')); $snapshots.find('.add-snapshot-action.add').html(_l('label.add'));
// Get description // Get description
$snapshots.find('.desc').html(_l(desc)); $snapshots.find('.desc').html(_l(desc));
// Snapshot type tabs // Snapshot type tabs
$snapshots.find('.forms').tabs(); $snapshots.find('.forms').tabs();
// Populate selects // Populate selects
$snapshots.find('form select').each(function() { $snapshots.find('form select').each(function() {
var $select = $(this); var $select = $(this);
var selectData = selects[$select.attr('name')]; var selectData = selects[$select.attr('name')];
if (selectData) { if (selectData) {
selectData({ selectData({
response: { response: {
success: function(args) { success: function(args) {
$(args.data).each(function() { $(args.data).each(function() {
var $option = $('<option>').appendTo($select); var $option = $('<option>').appendTo($select);
$option.val(this.id).html(_l(this.name)); $option.val(this.id).html(_l(this.name));
}); });
} }
} }
}); });
} }
});
// Form validation
$snapshots.find('form').validate();
// Add snapshot
$snapshots.find('.add-snapshot-action.add').click(function() {
var $form = $snapshots.find('form:visible');
if (!$form.valid()) return false;
var formData = cloudStack.serializeForm($form);
actions.add({
context: context,
snapshot: formData,
response: {
success: function(args) {
var $snapshotRow = $snapshots.find('.scheduled-snapshots tr').filter(function() {
return $(this).index() == args.data.type;
}).addClass('active').show();
$snapshotRow.data('json-obj', args.data);
// Update fields
$snapshotRow.find('td.time span').html(args.data.time);
$snapshotRow.find('td.day-of-week span').html(_l(
args.data['day-of-week'] ?
$snapshots.find('select[name=day-of-week] option').filter(function() {
return $(this).val() == args.data['day-of-week'];
}).html() :
args.data['day-of-month']
));
$snapshotRow.find('td.timezone span').html(
$snapshots.find('select[name=timezone] option').filter(function() {
return $(this).val() == args.data['timezone'];
}).html()
);
$snapshotRow.find('td.keep span').html(args.data.keep);
$(':ui-dialog').dialog('option', 'position', 'center');
refreshSnapshotTabs();
}
}
});
return true;
});
// Enable/disable snapshot tabs based on table contents;
var refreshSnapshotTabs = function() {
$snapshots.find('li').each(function() {
var index = $(this).index();
var $tr = $snapshots.find('tr').filter(function() {
return $(this).index() == index;
});
if ($tr.size() && $tr.hasClass('active')) { $(this).addClass('disabled ui-state-disabled'); }
else { $(this).removeClass('disabled ui-state-disabled'); }
if ($(this).is('.ui-tabs-selected.ui-state-disabled')) {
$snapshots.find('form').show();
if ($snapshots.find('li.ui-state-disabled').size() == $snapshots.find('li').size()) {
$snapshots.find('form').hide();
} else {
$snapshots.find('li:not(.ui-state-disabled):first a').click();
}
}
});
};
// Remove snapshot
$snapshots.find('.action.destroy').click(function() {
var $tr = $(this).closest('tr');
actions.remove({
context: context,
snapshot: $tr.data('json-obj'),
response: {
success: function(args) {
$tr.hide().removeClass('active');
$(':ui-dialog').dialog('option', 'position', 'center');
refreshSnapshotTabs();
}
}
});
});
// Get existing data
dataProvider({
context: context,
response: {
success: function(args) {
$(args.data).each(function() {
var snapshot = this;
// Get matching table row
var $tr = $snapshots.find('tr').filter(function() {
return $(this).index() == snapshot.type;
}).addClass('active').show();
$tr.data('json-obj', snapshot);
$tr.find('td.time span').html(snapshot.time);
$tr.find('td.timezone span').html(
$snapshots.find('select[name=timezone] option').filter(function() {
return $(this).val() == snapshot['timezone'];
}).html()
);
$tr.find('td.keep span').html(snapshot.keep);
$tr.find('td.day-of-week span').html(
snapshot['day-of-week'] ?
$snapshots.find('select[name=day-of-week] option').filter(function() {
return $(this).val() == snapshot['day-of-week'];
}).html() :
snapshot['day-of-month']
);
}); });
refreshSnapshotTabs(); // Form validation
} $snapshots.find('form').validate();
}
});
// Create dialog // Add snapshot
var $dialog = $snapshots.dialog({ $snapshots.find('.add-snapshot-action.add').click(function() {
title: _l('label.action.recurring.snapshot'), var $form = $snapshots.find('form:visible');
dialogClass: 'recurring-snapshots',
closeOnEscape:false,
width: 600,
buttons: [
{
text: _l('label.done'),
'class': 'ok',
click: function() {
$dialog.fadeOut(function() {
$dialog.remove();
});
$('div.overlay').fadeOut(function() { if (!$form.valid()) return false;
$('div.overlay').remove();
});
}
}
]
}).closest('.ui-dialog').overlay();
return $dialog; var formData = cloudStack.serializeForm($form);
actions.add({
context: context,
snapshot: formData,
response: {
success: function(args) {
var $snapshotRow = $snapshots.find('.scheduled-snapshots tr').filter(function() {
return $(this).index() == args.data.type;
}).addClass('active').show();
$snapshotRow.data('json-obj', args.data);
// Update fields
$snapshotRow.find('td.time span').html(args.data.time);
$snapshotRow.find('td.day-of-week span').html(_l(
args.data['day-of-week'] ?
$snapshots.find('select[name=day-of-week] option').filter(function() {
return $(this).val() == args.data['day-of-week'];
}).html() :
args.data['day-of-month']
));
$snapshotRow.find('td.timezone span').html(
$snapshots.find('select[name=timezone] option').filter(function() {
return $(this).val() == args.data['timezone'];
}).html()
);
$snapshotRow.find('td.keep span').html(args.data.keep);
$(':ui-dialog').dialog('option', 'position', 'center');
refreshSnapshotTabs();
}
}
});
return true;
});
// Enable/disable snapshot tabs based on table contents;
var refreshSnapshotTabs = function() {
$snapshots.find('li').each(function() {
var index = $(this).index();
var $tr = $snapshots.find('tr').filter(function() {
return $(this).index() == index;
});
if ($tr.size() && $tr.hasClass('active')) {
$(this).addClass('disabled ui-state-disabled');
} else {
$(this).removeClass('disabled ui-state-disabled');
}
if ($(this).is('.ui-tabs-selected.ui-state-disabled')) {
$snapshots.find('form').show();
if ($snapshots.find('li.ui-state-disabled').size() == $snapshots.find('li').size()) {
$snapshots.find('form').hide();
} else {
$snapshots.find('li:not(.ui-state-disabled):first a').click();
}
}
});
};
// Remove snapshot
$snapshots.find('.action.destroy').click(function() {
var $tr = $(this).closest('tr');
actions.remove({
context: context,
snapshot: $tr.data('json-obj'),
response: {
success: function(args) {
$tr.hide().removeClass('active');
$(':ui-dialog').dialog('option', 'position', 'center');
refreshSnapshotTabs();
}
}
});
});
// Get existing data
dataProvider({
context: context,
response: {
success: function(args) {
$(args.data).each(function() {
var snapshot = this;
// Get matching table row
var $tr = $snapshots.find('tr').filter(function() {
return $(this).index() == snapshot.type;
}).addClass('active').show();
$tr.data('json-obj', snapshot);
$tr.find('td.time span').html(snapshot.time);
$tr.find('td.timezone span').html(
$snapshots.find('select[name=timezone] option').filter(function() {
return $(this).val() == snapshot['timezone'];
}).html()
);
$tr.find('td.keep span').html(snapshot.keep);
$tr.find('td.day-of-week span').html(
snapshot['day-of-week'] ?
$snapshots.find('select[name=day-of-week] option').filter(function() {
return $(this).val() == snapshot['day-of-week'];
}).html() :
snapshot['day-of-month']
);
});
refreshSnapshotTabs();
}
}
});
// Create dialog
var $dialog = $snapshots.dialog({
title: _l('label.action.recurring.snapshot'),
dialogClass: 'recurring-snapshots',
closeOnEscape: false,
width: 600,
buttons: [{
text: _l('label.done'),
'class': 'ok',
click: function() {
$dialog.fadeOut(function() {
$dialog.remove();
});
$('div.overlay').fadeOut(function() {
$('div.overlay').remove();
});
}
}]
}).closest('.ui-dialog').overlay();
return $dialog;
};
}; };
};
}(cloudStack, jQuery)); }(cloudStack, jQuery));

View File

@ -16,115 +16,117 @@
// under the License. // under the License.
(function($, cloudStack) { (function($, cloudStack) {
$(window).bind('cloudStack.ready', function() { $(window).bind('cloudStack.ready', function() {
// Region switcher // Region switcher
var $regionList = $('<ul>'); var $regionList = $('<ul>');
// Get region listing // Get region listing
var refreshRegions = function() { var refreshRegions = function() {
$regionList.find('li').remove(); $regionList.find('li').remove();
cloudStack.sections.regions.regionSelector.dataProvider({ cloudStack.sections.regions.regionSelector.dataProvider({
response: { response: {
success: function(args) { success: function(args) {
var data = args.data; var data = args.data;
var currentRegion = null; var currentRegion = null;
$(data).each(function() { $(data).each(function() {
var region = this; var region = this;
var regionName = region.name; var regionName = region.name;
var $li = $('<li>').append($('<span>').html(_s(region.name))); var $li = $('<li>').append($('<span>').html(_s(region.name)));
$li.data('region-data', region); $li.data('region-data', region);
/* e.g. /* e.g.
region.endpoint == "http://localhost:8080/client/" region.endpoint == "http://localhost:8080/client/"
document.location.href == "http://localhost:8080/client/#" document.location.href == "http://localhost:8080/client/#"
*/ */
if(document.location.href.indexOf(region.endpoint) != -1) { if (document.location.href.indexOf(region.endpoint) != -1) {
currentRegion = region; currentRegion = region;
$li.addClass('active'); $li.addClass('active');
} }
$regionList.append($li); $regionList.append($li);
});
if (currentRegion != null) {
$regionSwitcherButton.find('.title').html(_s(currentRegion.name)).attr('title', _s(currentRegion.name));
} else {
$regionSwitcherButton.find('.title').html('').attr('title', '');
}
}
}
}); });
};
if(currentRegion != null) { $(window).bind('cloudStack.refreshRegions', refreshRegions);
$regionSwitcherButton.find('.title').html(_s(currentRegion.name)).attr('title', _s(currentRegion.name));
var $regionSelector = $('<div>').addClass('region-selector')
.append($('<div>').addClass('top-arrow'))
.append($('<h2>').html(_l('label.menu.regions')))
.append($regionList)
.append(
$('<div>').addClass('buttons')
.append(
$('<div>').addClass('button close').append($('<span>').html(_l('label.close')))
)
)
.hide();
var $regionSwitcherButton = $('<div>').addClass('region-switcher')
.attr('title', 'Select region')
.append(
$('<span>').addClass('icon').html('&nbsp;'),
$('<span>').addClass('title').html('')
);
var closeRegionSelector = function(args) {
$regionSwitcherButton.removeClass('active');
$regionSelector.fadeOut(args ? args.complete : null);
$('body > .overlay').fadeOut(function() {
$('body > .overlay').remove()
});
};
var switchRegion = function(url) {
closeRegionSelector({
complete: function() {
$('#container').prepend($('<div>').addClass('loading-overlay'));
document.location.href = url;
}
});
};
$regionList.click(function(event) {
var $target = $(event.target);
var $li = $target.closest('li');
var region, url;
if ($li.size() && !$li.hasClass('active')) {
region = $li.data('region-data');
url = region.endpoint;
id = region.id;
if (id != '-1') {
switchRegion(url);
}
} }
else { });
$regionSwitcherButton.find('.title').html('').attr('title', '');
$regionSwitcherButton.click(function() {
if ($regionSwitcherButton.hasClass('active')) {
closeRegionSelector();
} else {
$regionSwitcherButton.addClass('active');
$regionSelector.fadeIn('fast').overlay({
closeAction: closeRegionSelector
});
} }
} });
}
});
};
$(window).bind('cloudStack.refreshRegions', refreshRegions); $regionSelector.find('.button.close').click(function() {
closeRegionSelector();
});
var $regionSelector = $('<div>').addClass('region-selector') $('#header .controls .view-switcher.button:last').after($regionSwitcherButton, $regionSelector);
.append($('<div>').addClass('top-arrow')) refreshRegions();
.append($('<h2>').html(_l('label.menu.regions')))
.append($regionList)
.append(
$('<div>').addClass('buttons')
.append(
$('<div>').addClass('button close').append($('<span>').html(_l('label.close')))
)
)
.hide();
var $regionSwitcherButton = $('<div>').addClass('region-switcher')
.attr('title', 'Select region')
.append(
$('<span>').addClass('icon').html('&nbsp;'),
$('<span>').addClass('title').html('')
);
var closeRegionSelector = function(args) {
$regionSwitcherButton.removeClass('active');
$regionSelector.fadeOut(args ? args.complete : null);
$('body > .overlay').fadeOut(function() { $('body > .overlay').remove() });
};
var switchRegion = function(url) {
closeRegionSelector({
complete: function() {
$('#container').prepend($('<div>').addClass('loading-overlay'));
document.location.href = url;
}
});
};
$regionList.click(function(event) {
var $target = $(event.target);
var $li = $target.closest('li');
var region, url;
if ($li.size() && !$li.hasClass('active')) {
region = $li.data('region-data');
url = region.endpoint;
id = region.id;
if (id != '-1') {
switchRegion(url);
}
}
}); });
$regionSwitcherButton.click(function() {
if ($regionSwitcherButton.hasClass('active')) {
closeRegionSelector();
} else {
$regionSwitcherButton.addClass('active');
$regionSelector.fadeIn('fast').overlay({ closeAction: closeRegionSelector });
}
});
$regionSelector.find('.button.close').click(function() {
closeRegionSelector();
});
$('#header .controls .view-switcher.button:last').after($regionSwitcherButton, $regionSelector);
refreshRegions();
});
}(jQuery, cloudStack)); }(jQuery, cloudStack));

View File

@ -15,59 +15,59 @@
// specific language governing permissions and limitations // specific language governing permissions and limitations
// under the License. // under the License.
(function($, cloudStack) { (function($, cloudStack) {
cloudStack.uiCustom.securityRules = function(args) { cloudStack.uiCustom.securityRules = function(args) {
var multiEdit = args; var multiEdit = args;
return function(args) { return function(args) {
var context = args.context; var context = args.context;
var $multi = $('<div>').addClass('security-rules').multiEdit( var $multi = $('<div>').addClass('security-rules').multiEdit(
$.extend(true, {}, multiEdit, { $.extend(true, {}, multiEdit, {
context: context context: context
})
);
var $fields = $multi.find('form table').find('th, td');
var $accountFields = $fields.filter(function() {
return $(this).hasClass('accountname') ||
$(this).hasClass('securitygroupname');
});
var $cidrFields = $fields.filter(function() {
return $(this).hasClass('cidr');
});
$multi.prepend(
$('<div>').addClass('add-by')
.append($('<span>').html('Add by:'))
.append(
$('<div>').addClass('selection')
.append(
$('<input>').attr({
type: 'radio',
name: 'add-by',
checked: 'checked'
}).click(function() {
$accountFields.hide();
$cidrFields.show();
return true;
}).click()
)
.append($('<label>').html('CIDR'))
.append(
$('<input>').attr({
type: 'radio',
name: 'add-by'
}).click(function() {
$accountFields.show();
$cidrFields.hide();
return true;
}) })
) );
.append($('<label>').html('Account')) var $fields = $multi.find('form table').find('th, td');
) var $accountFields = $fields.filter(function() {
); return $(this).hasClass('accountname') ||
$(this).hasClass('securitygroupname');
});
var $cidrFields = $fields.filter(function() {
return $(this).hasClass('cidr');
});
return $multi; $multi.prepend(
$('<div>').addClass('add-by')
.append($('<span>').html('Add by:'))
.append(
$('<div>').addClass('selection')
.append(
$('<input>').attr({
type: 'radio',
name: 'add-by',
checked: 'checked'
}).click(function() {
$accountFields.hide();
$cidrFields.show();
return true;
}).click()
)
.append($('<label>').html('CIDR'))
.append(
$('<input>').attr({
type: 'radio',
name: 'add-by'
}).click(function() {
$accountFields.show();
$cidrFields.hide();
return true;
})
)
.append($('<label>').html('Account'))
)
);
return $multi;
};
}; };
};
})(jQuery, cloudStack); })(jQuery, cloudStack);

View File

@ -15,157 +15,162 @@
// specific language governing permissions and limitations // specific language governing permissions and limitations
// under the License. // under the License.
(function(cloudStack, $) { (function(cloudStack, $) {
cloudStack.uiCustom.uploadVolume = function(args) { cloudStack.uiCustom.uploadVolume = function(args) {
var listView = args.listView; var listView = args.listView;
var action = args.action; var action = args.action;
var validate = function($uploadVolume) { var validate = function($uploadVolume) {
if (!$uploadVolume.find('input[type=text]').val()) { if (!$uploadVolume.find('input[type=text]').val()) {
cloudStack.dialog.notice({ message: _l('message.specify.url')}); cloudStack.dialog.notice({
message: _l('message.specify.url')
});
return false; return false;
}
if (!$uploadVolume.find(
'input[type=radio]:checked, input[type=checkbox]:checked'
).size()) {
cloudStack.dialog.notice({ message: _l('message.select.instance')});
return false;
}
return true;
};
return function(args) {
var $uploadVolume = $('<div>').addClass('upload-volume');
var context = args.context;
var topFields = function() {
var $form = $('<form>').addClass('top-fields');
var $urlLabel = $('<label>').html(_l('label.url') + ':');
var $urlField = $('<div>').addClass('field url');
var $nameLabel = $('<label>').html(_l('label.name') + ':');
var $nameField = $('<div>').addClass('field name');
var $urlInput = $('<input>').attr({
type: 'text',
name: 'url'
}).addClass('required');
var $nameInput = $('<input>').attr({
type: 'text',
name: 'name'
}).addClass('required');
$urlField.append($urlLabel, $urlInput);
$nameField.append($nameLabel, $nameInput);
$form.append($nameField, $urlField);
return $form;
};
var vmList = function(args) {
// Create a listing of instances, based on limited information
// from main instances list view
var $listView;
var instances = $.extend(true, {}, args.listView, {
context: context,
uiCustom: true
});
instances.listView.actions = {
select: {
label: _l('label.select.instance'),
type: 'radio',
action: {
uiCustom: function(args) {
var $item = args.$item;
var $input = $item.find('td.actions input:visible');
if ($input.attr('type') == 'checkbox') {
if ($input.is(':checked'))
$item.addClass('multi-edit-selected');
else
$item.removeClass('multi-edit-selected');
} else {
$item.siblings().removeClass('multi-edit-selected');
$item.addClass('multi-edit-selected');
}
}
} }
}
if (!$uploadVolume.find(
'input[type=radio]:checked, input[type=checkbox]:checked'
).size()) {
cloudStack.dialog.notice({
message: _l('message.select.instance')
});
return false;
}
return true;
}; };
$listView = $('<div>').listView(instances); return function(args) {
var $uploadVolume = $('<div>').addClass('upload-volume');
var context = args.context;
var topFields = function() {
var $form = $('<form>').addClass('top-fields');
var $urlLabel = $('<label>').html(_l('label.url') + ':');
var $urlField = $('<div>').addClass('field url');
var $nameLabel = $('<label>').html(_l('label.name') + ':');
var $nameField = $('<div>').addClass('field name');
var $urlInput = $('<input>').attr({
type: 'text',
name: 'url'
}).addClass('required');
var $nameInput = $('<input>').attr({
type: 'text',
name: 'name'
}).addClass('required');
// Change action label $urlField.append($urlLabel, $urlInput);
$listView.find('th.actions').html(_l('label.select')); $nameField.append($nameLabel, $nameInput);
$form.append($nameField, $urlField);
return $listView; return $form;
}; };
var vmList = function(args) {
// Create a listing of instances, based on limited information
// from main instances list view
var $listView;
var instances = $.extend(true, {}, args.listView, {
context: context,
uiCustom: true
});
$uploadVolume.append( instances.listView.actions = {
topFields, select: {
$('<div>').addClass('desc').html(_l('label.select.instance.to.attach.volume.to') + ':'), label: _l('label.select.instance'),
$('<div>').addClass('listView-container').append( type: 'radio',
vmList({ listView: listView }) action: {
) uiCustom: function(args) {
); var $item = args.$item;
$uploadVolume.dialog({ var $input = $item.find('td.actions input:visible');
dialogClass: 'multi-edit-add-list panel',
width: 900,
title: _l('label.upload.volume'),
buttons: [
{
text: _l('label.upload'),
'class': 'ok',
click: function() {
if (!validate($uploadVolume)) return false;
var complete = args.complete; if ($input.attr('type') == 'checkbox') {
var $loading = $('<div>').addClass('loading-overlay'); if ($input.is(':checked'))
$item.addClass('multi-edit-selected');
else
$item.removeClass('multi-edit-selected');
} else {
$item.siblings().removeClass('multi-edit-selected');
$item.addClass('multi-edit-selected');
}
}
}
}
};
$loading.appendTo($uploadVolume); $listView = $('<div>').listView(instances);
action({
data: cloudStack.serializeForm($uploadVolume.find('form')), // Change action label
context: $.extend(true, {}, context, { $listView.find('th.actions').html(_l('label.select'));
instances: [
$uploadVolume.find('tr.multi-edit-selected').data('json-obj') return $listView;
] };
}),
response: { $uploadVolume.append(
success: function(args) { topFields,
$('.ui-dialog').fadeOut(function() { $('<div>').addClass('desc').html(_l('label.select.instance.to.attach.volume.to') + ':'),
$('.ui-dialog').remove(); $('<div>').addClass('listView-container').append(
$(window).trigger('cloudStack.fullRefresh'); vmList({
}); listView: listView
$('div.overlay').fadeOut(function() { })
$('div.overlay').remove(); )
}); );
complete({ $uploadVolume.dialog({
$item: $('<div>'), dialogClass: 'multi-edit-add-list panel',
_custom: args._custom width: 900,
}); title: _l('label.upload.volume'),
}, buttons: [{
error: function(args) { text: _l('label.upload'),
$loading.remove(); 'class': 'ok',
cloudStack.dialog.notice({ message: args }); click: function() {
} if (!validate($uploadVolume)) return false;
}
}); var complete = args.complete;
} var $loading = $('<div>').addClass('loading-overlay');
},
{ $loading.appendTo($uploadVolume);
text: _l('label.cancel'), action({
'class': 'cancel', data: cloudStack.serializeForm($uploadVolume.find('form')),
click: function() { context: $.extend(true, {}, context, {
$('.ui-dialog').fadeOut(function() { instances: [
$('.ui-dialog').remove(); $uploadVolume.find('tr.multi-edit-selected').data('json-obj')
}); ]
$('div.overlay').fadeOut(function() { }),
$('div.overlay').remove(); response: {
}); success: function(args) {
} $('.ui-dialog').fadeOut(function() {
} $('.ui-dialog').remove();
] $(window).trigger('cloudStack.fullRefresh');
}).closest('.ui-dialog').overlay(); });
$('div.overlay').fadeOut(function() {
$('div.overlay').remove();
});
complete({
$item: $('<div>'),
_custom: args._custom
});
},
error: function(args) {
$loading.remove();
cloudStack.dialog.notice({
message: args
});
}
}
});
}
}, {
text: _l('label.cancel'),
'class': 'cancel',
click: function() {
$('.ui-dialog').fadeOut(function() {
$('.ui-dialog').remove();
});
$('div.overlay').fadeOut(function() {
$('div.overlay').remove();
});
}
}]
}).closest('.ui-dialog').overlay();
};
}; };
};
}(cloudStack, jQuery)); }(cloudStack, jQuery));

File diff suppressed because it is too large Load Diff

View File

@ -15,412 +15,440 @@
// specific language governing permissions and limitations // specific language governing permissions and limitations
// under the License. // under the License.
(function($, cloudStack) { (function($, cloudStack) {
/**
* Zone details chart
*/
cloudStack.uiCustom.systemChart = function(chartID) {
/** /**
* Make view all button * Zone details chart
*/ */
var viewAllButton = function(args) { cloudStack.uiCustom.systemChart = function(chartID) {
var $viewAll = $('<div>').addClass('button view-all'); /**
var $label = $('<span>').addClass('view-all-label').html(args.label ? args.label : 'View all'); * Make view all button
var $browser = args.$browser; */
var action = args.action; var viewAllButton = function(args) {
// Launch a list view var $viewAll = $('<div>').addClass('button view-all');
//var $multiple-click=$viewAll.data('multiple-click',false); var $label = $('<span>').addClass('view-all-label').html(args.label ? args.label : 'View all');
$viewAll.click(function() { var $browser = args.$browser;
if ($viewAll.data('multiple-click')) return false; var action = args.action;
//@pranav-handling the multiple clicks by using a flag variable // Launch a list view
$viewAll.data('multiple-click', true); //var $multiple-click=$viewAll.data('multiple-click',false);
$browser.cloudBrowser('addPanel', { $viewAll.click(function() {
title: args.title, if ($viewAll.data('multiple-click')) return false;
maximizeIfSelected: true, //@pranav-handling the multiple clicks by using a flag variable
complete: function($newPanel) { $viewAll.data('multiple-click', true);
$viewAll.data('multiple-click', false); $browser.cloudBrowser('addPanel', {
action({ $panel: $newPanel }); title: args.title,
} maximizeIfSelected: true,
}); complete: function($newPanel) {
}); $viewAll.data('multiple-click', false);
action({
$panel: $newPanel
});
}
});
});
$viewAll.append($label); $viewAll.append($label);
return $viewAll; return $viewAll;
};
/**
* Chart button action generators
*/
var actions = {
/**
* Makes a list view from given zone sub-section
*/
listView: function(targetID, context) {
return function(args) {
var $elem = args.$panel;
var listView = cloudStack.sections.system.subsections[targetID];
$elem.listView($.extend(true, {}, listView, {
context: context
}));
};
},
providerListView: function(context) {
return function(args) {
var $elem = args.$panel;
var listViewArgs = cloudStack.sections.system.naas.providerListView;
$elem.listView({
context: context,
listView: listViewArgs
});
};
},
/**
* Makes details for a given traffic type
*/
trafficTypeDetails: function(targetID, context) {
return function(args) {
var $elem = args.$panel;
var detailViewArgs = cloudStack.sections.system.naas.mainNetworks[targetID].detailView;
$elem.detailView($.extend(true, {}, detailViewArgs, {
$browser: $('#browser .container'),
context: context
}));
};
}
};
/**
* Chart generators
*/
var charts = {
/**
* Compute tab
*/
compute: function(args) {
var $chart = $('<div>');
var $browser = $('#browser .container');
var context = args.context;
// Resource items
var computeResources = {
zone: {
label: 'Zone'
},
pods: {
label: 'Pods',
viewAll: {
action: actions.listView('pods', context)
}
},
clusters: {
label: 'Clusters',
viewAll: {
action: actions.listView('clusters', context)
}
},
hosts: {
label: 'Hosts',
viewAll: {
action: actions.listView('hosts', context)
}
},
primaryStorage: {
label: 'Primary Storage',
viewAll: {
action: actions.listView('primary-storage', context)
}
},
ucs: {
label: 'UCS',
viewAll: {
action: actions.listView('ucs', context)
}
},
secondaryStorage: {
label: 'Secondary Storage',
viewAll: {
action: actions.listView('secondary-storage', context)
}
}
}; };
/**
* Chart button action generators
*/
var actions = {
/**
* Makes a list view from given zone sub-section
*/
listView: function(targetID, context) {
return function(args) {
var $elem = args.$panel;
var listView = cloudStack.sections.system.subsections[targetID];
var $computeResources = $('<ul>').addClass('resources'); $elem.listView($.extend(true, {}, listView, {
context: context
// Make resource items }));
$.each(computeResources, function(id, resource) {
var $li = $('<li>');
var $label = $('<span>').addClass('label');
$li.addClass(id);
$label.html(resource.label);
$label.appendTo($li);
// View all
if (resource.viewAll) {
viewAllButton($.extend(resource.viewAll, {
title: resource.label,
$browser: $browser,
context: context
})).appendTo($li);
}
$li.appendTo($computeResources);
});
$chart.append($computeResources);
return $chart;
},
network: function(args) {
var $chart = $('<div>');
var $browser = $('#browser .container');
var $loading = $('<div>').addClass('loading-overlay');
var context = args.context;
var networkDataProvider = cloudStack.sections.system.naas.networks.dataProvider;
var trafficTypeDataProvider = cloudStack.sections.system.naas.trafficTypes.dataProvider;
$loading.appendTo($chart);
var renderChart = function(args) {
var $targetChart = args.$chart ? args.$chart : $chart;
var targetContext = $.extend(true, {}, context, {
physicalNetworks: [args.data]
});
// Get traffic type data
trafficTypeDataProvider({
context: targetContext,
response: {
success: function(args) {
var $networkChart = $('<div>').addClass('system-network-chart');
var $trafficTypes = $('<ul>').addClass('resources traffic-types');
$loading.remove();
var trafficTypes = {
'public': {
label: _l('label.public'),
configure: {
action: actions.trafficTypeDetails('public', targetContext)
}
},
'guest': {
label: _l('label.guest'),
configure: {
action: actions.trafficTypeDetails('guest', targetContext)
}
},
'management': {
label: _l('label.management'),
configure: {
action: actions.trafficTypeDetails('management', targetContext)
}
},
'storage': {
label: _l('label.storage'),
configure: {
action: actions.trafficTypeDetails('storage', targetContext)
}
},
'providers': {
label: _l('label.network.service.providers'),
ignoreChart: true,
dependsOn: 'guest',
configure: {
action: actions.providerListView(targetContext)
}
}
}; };
},
var validTrafficTypes = $.map(args.data, function(trafficType) { providerListView: function(context) {
return trafficType.name.toLowerCase(); return function(args) {
}); var $elem = args.$panel;
var listViewArgs = cloudStack.sections.system.naas.providerListView;
// Make traffic type elems $elem.listView({
$.each(trafficTypes, function(id, trafficType) { context: context,
if ($.inArray(id, validTrafficTypes) == -1) { //if it is not a valid traffic type listView: listViewArgs
if(trafficType.dependsOn != null && trafficType.dependsOn.length > 0) { //if it has dependsOn });
if($.inArray(trafficType.dependsOn, validTrafficTypes) == -1) { //if its dependsOn is not a valid traffic type, either };
return true; //skip this item },
}
//else, if its dependsOn is a valid traffic type, continue to Make list item (e.g. providers.dependsOn is 'guest')
}
else {
return true; //if it doesn't have dependsOn, skip this item
}
}
// Make list item /**
var $li = $('<li>').addClass(id); * Makes details for a given traffic type
var $label = $('<span>').addClass('label').html(trafficType.label); */
var $configureButton = viewAllButton($.extend(trafficType.configure, { trafficTypeDetails: function(targetID, context) {
label: _l('label.configure'), return function(args) {
title: trafficType.label, var $elem = args.$panel;
$browser: $browser, var detailViewArgs = cloudStack.sections.system.naas.mainNetworks[targetID].detailView;
targetContext: targetContext
}));
$li.append($label, $configureButton); $elem.detailView($.extend(true, {}, detailViewArgs, {
$li.appendTo($trafficTypes); $browser: $('#browser .container'),
context: context
// Make chart }));
if (trafficType.ignoreChart) };
return true;
var $targetChartItem = $('<div>').addClass('network-chart-item').addClass(id);
$targetChartItem.appendTo($networkChart);
});
var $switchIcon = $('<div>').addClass('network-switch-icon').append(
$('<span>').html('L2/L3 switch')
);
var $circleIcon = $('<div>').addClass('base-circle-icon');
$targetChart.append($trafficTypes, $switchIcon, $networkChart, $circleIcon);
}
} }
});
}; };
// Get network data /**
networkDataProvider({ * Chart generators
context: context, */
response: { var charts = {
success: function(args) { /**
var data = args.data; * Compute tab
var actionFilter = args.actionFilter; */
compute: function(args) {
var $chart = $('<div>');
var $browser = $('#browser .container');
var context = args.context;
$chart.listView({ // Resource items
listView: $.extend(true, {}, cloudStack.sections.system.naas.networks.listView, { var computeResources = {
dataProvider: function(args) { zone: {
args.response.success({ actionFilter: actionFilter, data: data }); label: 'Zone'
}, },
detailView: {
noCompact: true,
tabs: {
network: {
title: 'Network',
custom: function(args) {
var $chart = $('<div>').addClass('system-chart network');
renderChart({ pods: {
$chart: $chart, label: 'Pods',
data: args.context.physicalNetworks[0] viewAll: {
}); action: actions.listView('pods', context)
}
return $chart; },
clusters: {
label: 'Clusters',
viewAll: {
action: actions.listView('clusters', context)
}
},
hosts: {
label: 'Hosts',
viewAll: {
action: actions.listView('hosts', context)
}
},
primaryStorage: {
label: 'Primary Storage',
viewAll: {
action: actions.listView('primary-storage', context)
}
},
ucs: {
label: 'UCS',
viewAll: {
action: actions.listView('ucs', context)
}
},
secondaryStorage: {
label: 'Secondary Storage',
viewAll: {
action: actions.listView('secondary-storage', context)
} }
}
} }
} };
})
});
$loading.remove(); var $computeResources = $('<ul>').addClass('resources');
// Make resource items
$.each(computeResources, function(id, resource) {
var $li = $('<li>');
var $label = $('<span>').addClass('label');
$li.addClass(id);
$label.html(resource.label);
$label.appendTo($li);
// View all
if (resource.viewAll) {
viewAllButton($.extend(resource.viewAll, {
title: resource.label,
$browser: $browser,
context: context
})).appendTo($li);
}
$li.appendTo($computeResources);
});
$chart.append($computeResources);
return $chart;
},
network: function(args) {
var $chart = $('<div>');
var $browser = $('#browser .container');
var $loading = $('<div>').addClass('loading-overlay');
var context = args.context;
var networkDataProvider = cloudStack.sections.system.naas.networks.dataProvider;
var trafficTypeDataProvider = cloudStack.sections.system.naas.trafficTypes.dataProvider;
$loading.appendTo($chart);
var renderChart = function(args) {
var $targetChart = args.$chart ? args.$chart : $chart;
var targetContext = $.extend(true, {}, context, {
physicalNetworks: [args.data]
});
// Get traffic type data
trafficTypeDataProvider({
context: targetContext,
response: {
success: function(args) {
var $networkChart = $('<div>').addClass('system-network-chart');
var $trafficTypes = $('<ul>').addClass('resources traffic-types');
$loading.remove();
var trafficTypes = {
'public': {
label: _l('label.public'),
configure: {
action: actions.trafficTypeDetails('public', targetContext)
}
},
'guest': {
label: _l('label.guest'),
configure: {
action: actions.trafficTypeDetails('guest', targetContext)
}
},
'management': {
label: _l('label.management'),
configure: {
action: actions.trafficTypeDetails('management', targetContext)
}
},
'storage': {
label: _l('label.storage'),
configure: {
action: actions.trafficTypeDetails('storage', targetContext)
}
},
'providers': {
label: _l('label.network.service.providers'),
ignoreChart: true,
dependsOn: 'guest',
configure: {
action: actions.providerListView(targetContext)
}
}
};
var validTrafficTypes = $.map(args.data, function(trafficType) {
return trafficType.name.toLowerCase();
});
// Make traffic type elems
$.each(trafficTypes, function(id, trafficType) {
if ($.inArray(id, validTrafficTypes) == -1) { //if it is not a valid traffic type
if (trafficType.dependsOn != null && trafficType.dependsOn.length > 0) { //if it has dependsOn
if ($.inArray(trafficType.dependsOn, validTrafficTypes) == -1) { //if its dependsOn is not a valid traffic type, either
return true; //skip this item
}
//else, if its dependsOn is a valid traffic type, continue to Make list item (e.g. providers.dependsOn is 'guest')
} else {
return true; //if it doesn't have dependsOn, skip this item
}
}
// Make list item
var $li = $('<li>').addClass(id);
var $label = $('<span>').addClass('label').html(trafficType.label);
var $configureButton = viewAllButton($.extend(trafficType.configure, {
label: _l('label.configure'),
title: trafficType.label,
$browser: $browser,
targetContext: targetContext
}));
$li.append($label, $configureButton);
$li.appendTo($trafficTypes);
// Make chart
if (trafficType.ignoreChart)
return true;
var $targetChartItem = $('<div>').addClass('network-chart-item').addClass(id);
$targetChartItem.appendTo($networkChart);
});
var $switchIcon = $('<div>').addClass('network-switch-icon').append(
$('<span>').html('L2/L3 switch')
);
var $circleIcon = $('<div>').addClass('base-circle-icon');
$targetChart.append($trafficTypes, $switchIcon, $networkChart, $circleIcon);
}
}
});
};
// Get network data
networkDataProvider({
context: context,
response: {
success: function(args) {
var data = args.data;
var actionFilter = args.actionFilter;
$chart.listView({
listView: $.extend(true, {}, cloudStack.sections.system.naas.networks.listView, {
dataProvider: function(args) {
args.response.success({
actionFilter: actionFilter,
data: data
});
},
detailView: {
noCompact: true,
tabs: {
network: {
title: 'Network',
custom: function(args) {
var $chart = $('<div>').addClass('system-chart network');
renderChart({
$chart: $chart,
data: args.context.physicalNetworks[0]
});
return $chart;
}
}
}
}
})
});
$loading.remove();
}
}
});
return $chart;
},
resources: function(args) {
var $chart = $('<div>').addClass('dashboard admin');
var $chartItems = $('<ul>');
var $stats = $('<div>').addClass('stats');
var $container = $('<div>').addClass('dashboard-container head');
var $top = $('<div>').addClass('top');
var $title = $('<div>').addClass('title').append($('<span>').html(_l('label.system.wide.capacity')));
var chartItems = {
// The keys are based on the internal type ID associated with each capacity
0: {
name: _l('label.memory')
},
1: {
name: _l('label.cpu')
},
2: {
name: _l('label.storage')
},
3: {
name: _l('label.primary.allocated')
},
6: {
name: _l('label.secondary.storage')
},
9: {
name: _l('label.local.storage')
},
4: {
name: _l('label.public.ips')
},
5: {
name: _l('label.management.ips')
},
8: {
name: _l('label.direct.ips')
},
7: {
name: _l('label.vlan')
}
};
$top.append($title);
$container.append($top, $stats.append($chartItems));
$chart.append($container);
var $loading = $('<div>').addClass('loading-overlay').prependTo($chart);
cloudStack.sections.system.zoneDashboard({
context: args.context,
response: {
success: function(args) {
$loading.remove();
$.each(chartItems, function(id, chartItem) {
var data = args.data[id] ? args.data[id] : {
used: 0,
total: 0,
percent: 0
};
var $item = $('<li>');
var $name = $('<div>').addClass('name').html(chartItem.name);
var $value = $('<div>').addClass('value');
var $content = $('<div>').addClass('content').html('Allocated: ');
var $allocatedValue = $('<span>').addClass('allocated').html(data.used);
var $totalValue = $('<span>').addClass('total').html(data.total);
var $chart = $('<div>').addClass('chart');
var $chartLine = $('<div>').addClass('chart-line')
.css({
width: '0%'
})
.animate({
width: data.percent + '%'
});
var $percent = $('<div>').addClass('percentage');
var $percentValue = $('<soan>').addClass('value').html(data.percent);
$chartItems.append(
$item.append(
$name,
$value.append(
$content.append(
$allocatedValue,
' / ',
$totalValue
)
),
$chart.append($chartLine),
$percent.append($percentValue, '%')
)
);
});
}
}
});
return $chart;
} }
}
});
return $chart;
},
resources: function(args) {
var $chart = $('<div>').addClass('dashboard admin');
var $chartItems = $('<ul>');
var $stats = $('<div>').addClass('stats');
var $container = $('<div>').addClass('dashboard-container head');
var $top = $('<div>').addClass('top');
var $title = $('<div>').addClass('title').append($('<span>').html(_l('label.system.wide.capacity')));
var chartItems = {
// The keys are based on the internal type ID associated with each capacity
0: { name: _l('label.memory') },
1: { name: _l('label.cpu') },
2: { name: _l('label.storage') },
3: { name: _l('label.primary.allocated') },
6: { name: _l('label.secondary.storage') },
9: { name: _l('label.local.storage') },
4: { name: _l('label.public.ips') },
5: { name: _l('label.management.ips') },
8: { name: _l('label.direct.ips') },
7: { name: _l('label.vlan') }
}; };
$top.append($title); return function(args) {
$container.append($top, $stats.append($chartItems)); // Fix zone context naming
$chart.append($container); args.context.zones = args.context.physicalResources;
var $loading = $('<div>').addClass('loading-overlay').prependTo($chart);
cloudStack.sections.system.zoneDashboard({ var $chart = charts[chartID](args).addClass('system-chart').addClass(chartID);
context: args.context,
response: {
success: function(args) {
$loading.remove();
$.each(chartItems, function(id, chartItem) {
var data = args.data[id] ? args.data[id] : {
used: 0,
total: 0,
percent: 0
};
var $item = $('<li>');
var $name = $('<div>').addClass('name').html(chartItem.name);
var $value = $('<div>').addClass('value');
var $content = $('<div>').addClass('content').html('Allocated: ');
var $allocatedValue = $('<span>').addClass('allocated').html(data.used);
var $totalValue = $('<span>').addClass('total').html(data.total);
var $chart = $('<div>').addClass('chart');
var $chartLine = $('<div>').addClass('chart-line')
.css({ width: '0%' })
.animate({ width: data.percent + '%' });
var $percent = $('<div>').addClass('percentage');
var $percentValue = $('<soan>').addClass('value').html(data.percent);
$chartItems.append( return $chart;
$item.append( };
$name,
$value.append(
$content.append(
$allocatedValue,
' / ',
$totalValue
)
),
$chart.append($chartLine),
$percent.append($percentValue, '%')
)
);
});
}
}
});
return $chart;
}
}; };
return function(args) {
// Fix zone context naming
args.context.zones = args.context.physicalResources;
var $chart = charts[chartID](args).addClass('system-chart').addClass(chartID);
return $chart;
};
};
})(jQuery, cloudStack); })(jQuery, cloudStack);

View File

@ -16,24 +16,23 @@
// under the License. // under the License.
(function($, cloudStack) { (function($, cloudStack) {
$(window).bind('cloudStack.ready', function() { $(window).bind('cloudStack.ready', function() {
var $header = $('#header .controls'); var $header = $('#header .controls');
var $zoneFilter = $('<div>').addClass('zone-filter'); var $zoneFilter = $('<div>').addClass('zone-filter');
var $zoneTypeSelect = $('<select>').append( var $zoneTypeSelect = $('<select>').append(
$('<option>').attr('value', '').html(_l('All zones')), $('<option>').attr('value', '').html(_l('All zones')),
$('<option>').attr('value', 'Basic').html(_l('Basic')), $('<option>').attr('value', 'Basic').html(_l('Basic')),
$('<option>').attr('value', 'Advanced').html(_l('Advanced')) $('<option>').attr('value', 'Advanced').html(_l('Advanced'))
); );
var $label = $('<label>').html('Zone type:'); var $label = $('<label>').html('Zone type:');
$zoneFilter.append($label, $zoneTypeSelect); $zoneFilter.append($label, $zoneTypeSelect);
$zoneFilter.insertAfter($header.find('.project-switcher')); $zoneFilter.insertAfter($header.find('.project-switcher'));
$zoneTypeSelect.change(function() { $zoneTypeSelect.change(function() {
cloudStack.context.zoneType = $zoneTypeSelect.val(); cloudStack.context.zoneType = $zoneTypeSelect.val();
// Go to default/start page (dashboard) // Go to default/start page (dashboard)
$('#breadcrumbs .home').click(); $('#breadcrumbs .home').click();
});
}); });
});
}(jQuery, cloudStack)); }(jQuery, cloudStack));

File diff suppressed because it is too large Load Diff

View File

@ -15,443 +15,462 @@
// specific language governing permissions and limitations // specific language governing permissions and limitations
// under the License. // under the License.
(function($, cloudStack) { (function($, cloudStack) {
$.extend(cloudStack, { $.extend(cloudStack, {
ui: { ui: {
widgets: {} // Defines API methods for UI widgets widgets: {} // Defines API methods for UI widgets
}, },
uiCustom: {} uiCustom: {}
});
/**
* Generate navigation <li>s
*
* @param args cloudStack data args
*/
var makeNavigation = function(args) {
var $navList = $('<ul>');
var preFilter = cloudStack.sectionPreFilter ?
cloudStack.sectionPreFilter({
context: $.extend(true, {}, args.context, {
sections: $.map(cloudStack.sections, function(value, key) {
return key;
})
})
}) : null;
$.each(args.sections, function(sectionID, args) {
if (preFilter && $.inArray(sectionID, preFilter) == -1) {
if (!(args.preFilter && args.preFilter())) {
return true;
}
}
var $li = $('<li>')
.addClass('navigation-item')
.addClass(sectionID)
.append($('<span>').addClass('icon').html('&nbsp;'))
.append($('<span>').html(_l(args.title)))
.data('cloudStack-section-id', sectionID);
if (args.customIcon) {
$li.addClass('custom-icon').find('span.icon').html('').append(
$('<img>').attr({ src: args.customIcon })
);
}
$li.appendTo($navList);
return true;
}); });
// Special classes for first and last items /**
$navList.find('li:first').addClass('first'); * Generate navigation <li>s
$navList.find('li:last').addClass('last'); *
* @param args cloudStack data args
*/
var makeNavigation = function(args) {
var $navList = $('<ul>');
var preFilter = cloudStack.sectionPreFilter ?
cloudStack.sectionPreFilter({
context: $.extend(true, {}, args.context, {
sections: $.map(cloudStack.sections, function(value, key) {
return key;
})
})
}) : null;
return $navList; $.each(args.sections, function(sectionID, args) {
}; if (preFilter && $.inArray(sectionID, preFilter) == -1) {
if (!(args.preFilter && args.preFilter())) {
/** return true;
* Create section contents }
*
* @param sectionID Section's ID to show
* @param args CloudStack3 configuration
*/
var showSection = function(sectionID, args, $browser) {
var $navItem = $('#navigation').find('li').filter(function() {
return $(this).hasClass(sectionID);
});
var data = args.sections[sectionID];
data.$browser = $browser;
$navItem.siblings().removeClass('active');
$navItem.addClass('active');
// Reset browser panels
$browser.cloudBrowser('removeAllPanels');
$browser.cloudBrowser('addPanel', {
title: '<span class="section">' + _l(data.title) + '</span>' + '<span class="subsection"></span>',
data: '',
complete: function($panel, $breadcrumb) {
$breadcrumb.attr('title', _l(data.title));
data.$breadcrumb = $breadcrumb;
// Hide breadcrumb if this is the home section
if (args.home === sectionID) {
$('#breadcrumbs').find('li:first, div.end:last').hide();
}
// Append specified widget to view
if (data.show)
$panel.append(data.show(data));
else if (data.treeView)
$panel.treeView(data, { context: args.context });
else
$panel.listView(data, { context: args.context });
}
});
return $navItem;
};
// Define page element generation fns
var pageElems = {
header: function(args) {
// Make notification area
var $notificationArea = $('<div>').addClass('button notifications')
.append(
$('<div>').addClass('total')
// Total notifications
.append($('<span>').html(0))
)
.append($('<span>').html(_l('label.notifications')))
.notifications();
// Project switcher
var $viewSwitcher = $('<div>').addClass('button view-switcher')
.append(
// Default View
$('<div>').addClass('select default-view active')
.html(_l('label.default.view'))
.prepend(
$('<span>').addClass('icon').html('&nbsp;')
)
)
.append(
// Project View
$('<div>').addClass('select project-view')
.html(_l('label.project.view'))
.prepend(
$('<span>').addClass('icon').html('&nbsp;')
)
)
.click(function(event) {
var $target = $(event.target);
var $projectSwitcher = $(this);
var $container = $('html body');
var $navDisabled = $(
$.map([
'projects',
'accounts',
'domains',
'system',
'global-settings',
'configuration'
], function(id) {
return '#navigation li.' + id;
}).join(',')
);
if ($target.closest('.select.project-view').size()) {
$('#cloudStack3-container').addClass('project-view');
$projectSwitcher.addClass('alt');
$projectSwitcher.find('.select.project-view').addClass('active')
.siblings().removeClass('active');
// Activate project view
$navDisabled.hide();
cloudStack.uiCustom.projects({
$projectSelect: $projectSelect.hide().find('select')
});
} else {
$navDisabled.show();
$('#cloudStack3-container').removeClass('project-view');
$projectSwitcher.removeClass('alt');
$projectSelect.hide();
$projectSwitcher.find('.select.default-view').addClass('active')
.siblings().removeClass('active');
// Put project name in header
$('.select.project-view').html(
'<span class="icon">&nbsp;</span>' + _l('label.project.view')
).attr('title', '');
// Clear out project
cloudStack.context.projects = null;
}
$('#navigation li.dashboard').click();
return false;
});
var $projectSelect = $('<div>').addClass('view-switcher').hide()
.append($('<select>'));
// User status area
var userLabel = args.context.users[0].name ?
args.context.users[0].name : args.context.users[0].login;
var $userInfo = $('<div>').attr({ id: 'user' }).addClass('button')
.append(
$('<div>').addClass('name').html(
args.context && args.context.users ?
cloudStack.concat(userLabel, 14) : 'Invalid User'
)
)
.append(
$('<div>').addClass('icon options')
.append(
$('<div>').addClass('icon arrow')
)
);
$userInfo.attr('title', userLabel);
return [
$('<div>').addClass('logo'),
$('<div>').addClass('controls')
.append($notificationArea)
.append($viewSwitcher)
.append($projectSelect)
.append($userInfo)
];
},
'main-area': function(args) {
var $navigation = $('<div>').attr({ id: 'navigation' });
var $browser = $('<div>').attr({ id: 'browser' })
.append(
// Home breadcrumb
$('<div>').attr({ id: 'breadcrumbs' })
.append($('<div>').addClass('home'))
.append($('<div>').addClass('end'))
)
.append(
// Panel container
$('<div>').addClass('container')
);
makeNavigation(args).appendTo($navigation);
return [
$navigation, $browser
];
}
};
$.fn.cloudStack = function(args) {
var $container = $('<div>')
.attr({
id: 'container',
'cloudStack-container': true
})
.data('cloudStack-args', args)
.appendTo(this);
var context = args.context;
// Create pageElems
$.each(pageElems, function(id, fn) {
var $elem = $('<div>').attr({ id: id });
$(fn(args)).each(function() {
$elem.append($(this));
});
$elem.appendTo($container);
});
// User options
var $options = $('<div>').attr({ id: 'user-options' })
.appendTo($('#header'));
$(['label.logout', 'label.help', 'label.about']).each(function() {
var $link = $('<a>')
.attr({ href: '#' })
.html(_l(this.toString()))
.appendTo($options);
if (this == 'label.help') {
$link.click(function() {
var helpURL = 'http://docs.cloud.com/CloudStack_Documentation';
window.open(helpURL, '_blank');
return false;
});
}
if (this == 'label.about') {
$link.click(function() {
var $logo = $('<div>').addClass('logo').html(_l('label.app.name')),
$version = $('<div>').addClass('version').html(g_cloudstackversion),
$about = $('<div>').addClass('about').append($logo).append($version);
$about.dialog({
modal: true,
width: 300,
title: _l('label.about.app'),
closeOnEscape: false,
dialogClass: 'dialog-about',
buttons: {
'Close': function() {
$( this ).dialog( "close" );
$(':ui-dialog, .overlay').remove();
}
} }
}).closest('.ui-dialog').overlay();
return false;
var $li = $('<li>')
.addClass('navigation-item')
.addClass(sectionID)
.append($('<span>').addClass('icon').html('&nbsp;'))
.append($('<span>').html(_l(args.title)))
.data('cloudStack-section-id', sectionID);
if (args.customIcon) {
$li.addClass('custom-icon').find('span.icon').html('').append(
$('<img>').attr({
src: args.customIcon
})
);
}
$li.appendTo($navList);
return true;
}); });
}
});
// Initialize browser // Special classes for first and last items
$container.find('#browser div.container').cloudBrowser(); $navList.find('li:first').addClass('first');
$container.find('#navigation li') $navList.find('li:last').addClass('last');
.filter(function() {
return $(this).hasClass(args.home);
})
.click();
// Validation return $navList;
$.extend($.validator.messages, { required: _l('label.required') }); };
$.validator.addMethod( /**
"disallowSpecialCharacters", * Create section contents
function(value, element) { *
return (value.indexOf("<") == -1 && value.indexOf(">") == -1); * @param sectionID Section's ID to show
}, * @param args CloudStack3 configuration
jQuery.format("Disallowed characters: <, >") */
); var showSection = function(sectionID, args, $browser) {
var $navItem = $('#navigation').find('li').filter(function() {
return $(this).hasClass(sectionID);
});
var data = args.sections[sectionID];
// Check for pending project invitations data.$browser = $browser;
if (args.projects) { $navItem.siblings().removeClass('active');
args.projects.invitationCheck({ $navItem.addClass('active');
context: cloudStack.context,
response: {
success: function(args) {
if (!args.data.length) return;
var projectList = $.map(args.data, function(invitation) { // Reset browser panels
return '<li>' + invitation.project + '</li>'; $browser.cloudBrowser('removeAllPanels');
}).join(''); $browser.cloudBrowser('addPanel', {
title: '<span class="section">' + _l(data.title) + '</span>' + '<span class="subsection"></span>',
data: '',
complete: function($panel, $breadcrumb) {
$breadcrumb.attr('title', _l(data.title));
data.$breadcrumb = $breadcrumb;
cloudStack.dialog.notice({ // Hide breadcrumb if this is the home section
message: _l('message.pending.projects.1') + if (args.home === sectionID) {
'<ul>' + projectList + '</ul>' + $('#breadcrumbs').find('li:first, div.end:last').hide();
'<p>' + _l('message.pending.projects.2') + '</p>' }
// Append specified widget to view
if (data.show)
$panel.append(data.show(data));
else if (data.treeView)
$panel.treeView(data, {
context: args.context
});
else
$panel.listView(data, {
context: args.context
});
}
});
return $navItem;
};
// Define page element generation fns
var pageElems = {
header: function(args) {
// Make notification area
var $notificationArea = $('<div>').addClass('button notifications')
.append(
$('<div>').addClass('total')
// Total notifications
.append($('<span>').html(0))
)
.append($('<span>').html(_l('label.notifications')))
.notifications();
// Project switcher
var $viewSwitcher = $('<div>').addClass('button view-switcher')
.append(
// Default View
$('<div>').addClass('select default-view active')
.html(_l('label.default.view'))
.prepend(
$('<span>').addClass('icon').html('&nbsp;')
)
)
.append(
// Project View
$('<div>').addClass('select project-view')
.html(_l('label.project.view'))
.prepend(
$('<span>').addClass('icon').html('&nbsp;')
)
)
.click(function(event) {
var $target = $(event.target);
var $projectSwitcher = $(this);
var $container = $('html body');
var $navDisabled = $(
$.map([
'projects',
'accounts',
'domains',
'system',
'global-settings',
'configuration'
], function(id) {
return '#navigation li.' + id;
}).join(',')
);
if ($target.closest('.select.project-view').size()) {
$('#cloudStack3-container').addClass('project-view');
$projectSwitcher.addClass('alt');
$projectSwitcher.find('.select.project-view').addClass('active')
.siblings().removeClass('active');
// Activate project view
$navDisabled.hide();
cloudStack.uiCustom.projects({
$projectSelect: $projectSelect.hide().find('select')
});
} else {
$navDisabled.show();
$('#cloudStack3-container').removeClass('project-view');
$projectSwitcher.removeClass('alt');
$projectSelect.hide();
$projectSwitcher.find('.select.default-view').addClass('active')
.siblings().removeClass('active');
// Put project name in header
$('.select.project-view').html(
'<span class="icon">&nbsp;</span>' + _l('label.project.view')
).attr('title', '');
// Clear out project
cloudStack.context.projects = null;
}
$('#navigation li.dashboard').click();
return false;
});
var $projectSelect = $('<div>').addClass('view-switcher').hide()
.append($('<select>'));
// User status area
var userLabel = args.context.users[0].name ?
args.context.users[0].name : args.context.users[0].login;
var $userInfo = $('<div>').attr({
id: 'user'
}).addClass('button')
.append(
$('<div>').addClass('name').html(
args.context && args.context.users ?
cloudStack.concat(userLabel, 14) : 'Invalid User'
)
)
.append(
$('<div>').addClass('icon options')
.append(
$('<div>').addClass('icon arrow')
)
);
$userInfo.attr('title', userLabel);
return [
$('<div>').addClass('logo'),
$('<div>').addClass('controls')
.append($notificationArea)
.append($viewSwitcher)
.append($projectSelect)
.append($userInfo)
];
},
'main-area': function(args) {
var $navigation = $('<div>').attr({
id: 'navigation'
}); });
} var $browser = $('<div>').attr({
id: 'browser'
})
.append(
// Home breadcrumb
$('<div>').attr({
id: 'breadcrumbs'
})
.append($('<div>').addClass('home'))
.append($('<div>').addClass('end'))
)
.append(
// Panel container
$('<div>').addClass('container')
);
makeNavigation(args).appendTo($navigation);
return [
$navigation, $browser
];
} }
}); };
}
// Hide logo conditionally $.fn.cloudStack = function(args) {
if (!args.hasLogo) $('#header, #header .controls').addClass('nologo'); var $container = $('<div>')
.attr({
id: 'container',
'cloudStack-container': true
})
.data('cloudStack-args', args)
.appendTo(this);
var context = args.context;
$(window).trigger('cloudStack.ready'); // Create pageElems
$.each(pageElems, function(id, fn) {
var $elem = $('<div>').attr({
id: id
});
return this; $(fn(args)).each(function() {
}; $elem.append($(this));
});
// Events $elem.appendTo($container);
$(function() {
// Check if target should be hovered
function checkHoveredLabel($target) {
var $multiWizard = $('div.ui-dialog div.multi-wizard');
if (($target.is('label[for]') && !$target.parents('body.login')) ||
($multiWizard.size() &&
($target.is('.multi-wizard label') && $target.prev('input[type="radio"],input[type="checkbox"]').size()) ||
($target.is('.multi-wizard .select-desc div.name') && $target.parent('div.select-desc').prev('input[type="radio"],input[type="checkbox"]').size())
))
return true;
return false;
}
// Rollover behavior for user options
$(document).bind('mouseover', function(event) {
var $target = $(event.target);
if (checkHoveredLabel($target)) {
$target.addClass('label-hovered');
}
if ($target.closest('#user, #user-options').size()) {
return false;
}
else $('#user-options').hide();
return false;
});
$(document).bind('mouseout', function(event) {
var $target = $(event.target);
if (checkHoveredLabel($target)) {
$target.removeClass('label-hovered');
}
});
$(document).bind('click', function(event) {
var $target = $(event.target);
var $container = $target.closest('[cloudStack-container]');
var args = $container.data('cloudStack-args');
var $browser = $container.find('#browser .container');
var $multiWizard = $('div.ui-dialog div.multi-wizard');
// Wizard: trigger click event for input when click it label
if ($multiWizard.size()) {
if ($target.is('.multi-wizard label') && $target.prev('input[type="radio"],input[type="checkbox"]').size()) {
$target.prev('input').trigger('click');
}
if ($target.is('.multi-wizard .select-desc div.name') && $target.parent('div.select-desc').prev('input[type="radio"],input[type="checkbox"]').size()) {
$target.parent('div.select-desc').prev('input').trigger('click');
}
}
if (!$container.size()) return true;
// Navigation items
if ($target.closest('li.navigation-item').size() && $target.closest('#navigation').size()) {
var $navItem = $target.closest('li.navigation-item');
if ($navItem.is('.disabled')) return false;
showSection($navItem.data('cloudStack-section-id'), args, $browser);
return false;
}
// Browser expand
if ($target.hasClass('control expand') && $target.closest('div.panel div.toolbar').size()) {
$browser.cloudBrowser('toggleMaximizePanel', {
panel: $target.closest('div.panel')
}); });
return false; // User options
} var $options = $('<div>').attr({
id: 'user-options'
})
.appendTo($('#header'));
// Home breadcrumb $(['label.logout', 'label.help', 'label.about']).each(function() {
if ($target.is('#breadcrumbs div.home')) { var $link = $('<a>')
showSection(args.home, args, $browser); .attr({
return false; href: '#'
} })
.html(_l(this.toString()))
.appendTo($options);
// User options if (this == 'label.help') {
if ($target.closest('#user div.icon.options').size()) { $link.click(function() {
$('#user-options').toggle(); var helpURL = 'http://docs.cloud.com/CloudStack_Documentation';
return false; window.open(helpURL, '_blank');
}
return true; return false;
});
}
if (this == 'label.about') {
$link.click(function() {
var $logo = $('<div>').addClass('logo').html(_l('label.app.name')),
$version = $('<div>').addClass('version').html(g_cloudstackversion),
$about = $('<div>').addClass('about').append($logo).append($version);
$about.dialog({
modal: true,
width: 300,
title: _l('label.about.app'),
closeOnEscape: false,
dialogClass: 'dialog-about',
buttons: {
'Close': function() {
$(this).dialog("close");
$(':ui-dialog, .overlay').remove();
}
}
}).closest('.ui-dialog').overlay();
return false;
});
}
});
// Initialize browser
$container.find('#browser div.container').cloudBrowser();
$container.find('#navigation li')
.filter(function() {
return $(this).hasClass(args.home);
})
.click();
// Validation
$.extend($.validator.messages, {
required: _l('label.required')
});
$.validator.addMethod(
"disallowSpecialCharacters",
function(value, element) {
return (value.indexOf("<") == -1 && value.indexOf(">") == -1);
},
jQuery.format("Disallowed characters: <, >")
);
// Check for pending project invitations
if (args.projects) {
args.projects.invitationCheck({
context: cloudStack.context,
response: {
success: function(args) {
if (!args.data.length) return;
var projectList = $.map(args.data, function(invitation) {
return '<li>' + invitation.project + '</li>';
}).join('');
cloudStack.dialog.notice({
message: _l('message.pending.projects.1') + '<ul>' + projectList + '</ul>' + '<p>' + _l('message.pending.projects.2') + '</p>'
});
}
}
});
}
// Hide logo conditionally
if (!args.hasLogo) $('#header, #header .controls').addClass('nologo');
$(window).trigger('cloudStack.ready');
return this;
};
// Events
$(function() {
// Check if target should be hovered
function checkHoveredLabel($target) {
var $multiWizard = $('div.ui-dialog div.multi-wizard');
if (($target.is('label[for]') && !$target.parents('body.login')) ||
($multiWizard.size() &&
($target.is('.multi-wizard label') && $target.prev('input[type="radio"],input[type="checkbox"]').size()) ||
($target.is('.multi-wizard .select-desc div.name') && $target.parent('div.select-desc').prev('input[type="radio"],input[type="checkbox"]').size())
))
return true;
return false;
}
// Rollover behavior for user options
$(document).bind('mouseover', function(event) {
var $target = $(event.target);
if (checkHoveredLabel($target)) {
$target.addClass('label-hovered');
}
if ($target.closest('#user, #user-options').size()) {
return false;
} else $('#user-options').hide();
return false;
});
$(document).bind('mouseout', function(event) {
var $target = $(event.target);
if (checkHoveredLabel($target)) {
$target.removeClass('label-hovered');
}
});
$(document).bind('click', function(event) {
var $target = $(event.target);
var $container = $target.closest('[cloudStack-container]');
var args = $container.data('cloudStack-args');
var $browser = $container.find('#browser .container');
var $multiWizard = $('div.ui-dialog div.multi-wizard');
// Wizard: trigger click event for input when click it label
if ($multiWizard.size()) {
if ($target.is('.multi-wizard label') && $target.prev('input[type="radio"],input[type="checkbox"]').size()) {
$target.prev('input').trigger('click');
}
if ($target.is('.multi-wizard .select-desc div.name') && $target.parent('div.select-desc').prev('input[type="radio"],input[type="checkbox"]').size()) {
$target.parent('div.select-desc').prev('input').trigger('click');
}
}
if (!$container.size()) return true;
// Navigation items
if ($target.closest('li.navigation-item').size() && $target.closest('#navigation').size()) {
var $navItem = $target.closest('li.navigation-item');
if ($navItem.is('.disabled')) return false;
showSection($navItem.data('cloudStack-section-id'), args, $browser);
return false;
}
// Browser expand
if ($target.hasClass('control expand') && $target.closest('div.panel div.toolbar').size()) {
$browser.cloudBrowser('toggleMaximizePanel', {
panel: $target.closest('div.panel')
});
return false;
}
// Home breadcrumb
if ($target.is('#breadcrumbs div.home')) {
showSection(args.home, args, $browser);
return false;
}
// User options
if ($target.closest('#user div.icon.options').size()) {
$('#user-options').toggle();
return false;
}
return true;
});
}); });
});
})(window.jQuery, })(window.jQuery,
window.cloudStack ? window.cloudStack : window.cloudStack = {}); window.cloudStack ? window.cloudStack : window.cloudStack = {});

File diff suppressed because it is too large Load Diff

View File

@ -15,46 +15,48 @@
// specific language governing permissions and limitations // specific language governing permissions and limitations
// under the License. // under the License.
(function($, cloudStack) { (function($, cloudStack) {
cloudStack.ui.event = { cloudStack.ui.event = {
// Attach element to specific event type // Attach element to specific event type
elem: function(widget, elem, $elem, extraData) { elem: function(widget, elem, $elem, extraData) {
// Setup DOM metadata // Setup DOM metadata
var data = { cloudStack: {} }; var data = {
data.cloudStack[widget] = { cloudStack: {}
elem: elem };
}; data.cloudStack[widget] = {
if (extraData) $.extend(data.cloudStack[widget], extraData); elem: elem
};
if (extraData) $.extend(data.cloudStack[widget], extraData);
return $elem return $elem
.addClass('cloudStack-elem') .addClass('cloudStack-elem')
.addClass(widget) .addClass(widget)
.data(data); .data(data);
}, },
// Create widget-based event // Create widget-based event
bind: function(widget, events) { bind: function(widget, events) {
return function(event) { return function(event) {
var $target = $(event.target); var $target = $(event.target);
var $widget, $elem; var $widget, $elem;
var data, elem; var data, elem;
$elem = $target.closest('.cloudStack-elem.' + widget); $elem = $target.closest('.cloudStack-elem.' + widget);
if (!$elem.size()) if (!$elem.size())
return true; return true;
$widget = $('.cloudStack-widget.' + widget); $widget = $('.cloudStack-widget.' + widget);
data = $elem.data('cloudStack')[widget]; data = $elem.data('cloudStack')[widget];
elem = data.elem; elem = data.elem;
events[elem]($elem, $widget, data); events[elem]($elem, $widget, data);
return false; return false;
}; };
}, },
// Trigger CloudStack UI event (cloudStack.*) // Trigger CloudStack UI event (cloudStack.*)
call: function(eventName, data) { call: function(eventName, data) {
$(window).trigger('cloudStack.' + eventName, data); $(window).trigger('cloudStack.' + eventName, data);
} }
}; };
})(jQuery, cloudStack); })(jQuery, cloudStack);

View File

@ -15,113 +15,110 @@
// specific language governing permissions and limitations // specific language governing permissions and limitations
// under the License. // under the License.
(function($, cloudStack) { (function($, cloudStack) {
// General utils // General utils
cloudStack.serializeForm = function($form, options) { cloudStack.serializeForm = function($form, options) {
if (!options) options = {}; if (!options) options = {};
var data = {}; var data = {};
$($form.serializeArray()).each(function() { $($form.serializeArray()).each(function() {
var dataItem = data[this.name]; var dataItem = data[this.name];
var value = _s(this.value.toString()); var value = _s(this.value.toString());
if (options.escapeSlashes) { if (options.escapeSlashes) {
value = value.replace(/\//g, '__forwardSlash__'); value = value.replace(/\//g, '__forwardSlash__');
} }
if (!dataItem) { if (!dataItem) {
data[this.name] = value; data[this.name] = value;
} else if (dataItem && !$.isArray(dataItem)) { } else if (dataItem && !$.isArray(dataItem)) {
data[this.name] = [dataItem, value]; data[this.name] = [dataItem, value];
} else if($.isArray(dataItem)){ } else if ($.isArray(dataItem)) {
dataItem.push(value); dataItem.push(value);
} }
}); });
return data; return data;
}; };
// Even/odd row handling // Even/odd row handling
cloudStack.evenOdd = function($container, itemSelector, args) { cloudStack.evenOdd = function($container, itemSelector, args) {
var even = false; var even = false;
$container.find(itemSelector).each(function() { $container.find(itemSelector).each(function() {
var $elem = $(this); var $elem = $(this);
if (even) { if (even) {
even = false; even = false;
args.odd($elem); args.odd($elem);
} else { } else {
even = true; even = true;
args.even($elem); args.even($elem);
} }
}); });
}; };
/** /**
* Localization -- shortcut _l * Localization -- shortcut _l
* *
* Takes string and runs through localization function -- if no code * Takes string and runs through localization function -- if no code
* exists or function isn't present, return string as-is * exists or function isn't present, return string as-is
*/ */
cloudStack.localize = window._l = function(str) { cloudStack.localize = window._l = function(str) {
var localized = cloudStack.localizationFn ? var localized = cloudStack.localizationFn ?
cloudStack.localizationFn(str) : null; cloudStack.localizationFn(str) : null;
return localized ? localized : str; return localized ? localized : str;
}; };
/** /**
* Sanitize user input (HTML Encoding) -- shortcut _s * Sanitize user input (HTML Encoding) -- shortcut _s
* *
* Strip unwanted characters from user-based input * Strip unwanted characters from user-based input
*/ */
cloudStack.sanitize = window._s = function(value) { cloudStack.sanitize = window._s = function(value) {
if(typeof(value) == "number") { if (typeof(value) == "number") {
//alert("number does not need to be sanitized. Only string needs to be sanitized."); //alert("number does not need to be sanitized. Only string needs to be sanitized.");
return value; return value;
} } else if (typeof(value) == "boolean") {
else if(typeof(value) == "boolean") { //alert("boolean does not need to be sanitized. Only string needs to be sanitized.");
//alert("boolean does not need to be sanitized. Only string needs to be sanitized."); return value;
return value; } else if (typeof(value) == "object") {
} //alert("object cant not be sanitized. Only string can be sanitized.");
else if(typeof(value) == "object") { return value;
//alert("object cant not be sanitized. Only string can be sanitized."); } else if (typeof(value) == null || typeof(value) == "undefined") {
return value; return '';
} }
else if(typeof(value) == null || typeof(value) == "undefined") {
return '';
}
var sanitized = value var sanitized = value
.replace(/&/g, "&amp;") .replace(/&/g, "&amp;")
.replace(/</g, "&lt;") .replace(/</g, "&lt;")
.replace(/>/g, "&gt;"); .replace(/>/g, "&gt;");
return sanitized; return sanitized;
}; };
/** /**
* Reverse sanitization (HTML Decoding) * Reverse sanitization (HTML Decoding)
*/ */
cloudStack.sanitizeReverse = function(value) { cloudStack.sanitizeReverse = function(value) {
var reversedValue = value var reversedValue = value
.replace(/&amp;/g, "&") .replace(/&amp;/g, "&")
.replace(/&lt;/g, "<") .replace(/&lt;/g, "<")
.replace(/&gt;/g, ">"); .replace(/&gt;/g, ">");
return reversedValue; return reversedValue;
}; };
/** /**
* If the str.length is > maxLen, * If the str.length is > maxLen,
* then concatenate and add '...' to the end of the string * then concatenate and add '...' to the end of the string
*/ */
cloudStack.concat = function(str, maxLen) { cloudStack.concat = function(str, maxLen) {
if (str.length > maxLen) { if (str.length > maxLen) {
return str.substr(0, maxLen) + '...'; return str.substr(0, maxLen) + '...';
} else { } else {
return str; return str;
} }
}; };
})(jQuery, cloudStack); })(jQuery, cloudStack);

View File

@ -15,418 +15,427 @@
// specific language governing permissions and limitations // specific language governing permissions and limitations
// under the License. // under the License.
(function($, cloudStack) { (function($, cloudStack) {
cloudStack.ui.widgets.browser = {}; cloudStack.ui.widgets.browser = {};
/**
* Breadcrumb-related functions
*/
var _breadcrumb = cloudStack.ui.widgets.browser.breadcrumb = {
/**
* Generate new breadcrumb
*/
create: function($panel, title) {
// Attach panel as ref for breadcrumb
return cloudStack.ui.event.elem(
'cloudBrowser', 'breadcrumb',
$('<div>')
.append(
$('<li>')
.attr({
title: title
})
.append(
$('<span>').html(title)
)
)
.append($('<div>').addClass('end'))
.children(),
{
panel: $panel
}
);
},
/** /**
* Get breadcrumbs matching specified panels * Breadcrumb-related functions
*/ */
filter: function($panels) { var _breadcrumb = cloudStack.ui.widgets.browser.breadcrumb = {
var $breadcrumbs = $('#breadcrumbs ul li'); /**
var $result = $([]); * Generate new breadcrumb
*/
create: function($panel, title) {
// Attach panel as ref for breadcrumb
return cloudStack.ui.event.elem(
'cloudBrowser', 'breadcrumb',
$('<div>')
.append(
$('<li>')
.attr({
title: title
})
.append(
$('<span>').html(title)
)
)
.append($('<div>').addClass('end'))
.children(), {
panel: $panel
}
);
},
$panels.each(function() { /**
var $panel = $(this); * Get breadcrumbs matching specified panels
*/
filter: function($panels) {
var $breadcrumbs = $('#breadcrumbs ul li');
var $result = $([]);
$.merge( $panels.each(function() {
$result, var $panel = $(this);
$.merge(
$breadcrumbs.filter(function() {
return $(this).index('#breadcrumbs ul li') == $panel.index();
}),
// Also include ends $.merge(
$breadcrumbs.siblings('div.end').filter(function() { $result,
return $(this).index('div.end') == $panel.index() + 1; $.merge(
}) $breadcrumbs.filter(function() {
) return $(this).index('#breadcrumbs ul li') == $panel.index();
); }),
});
return $result; // Also include ends
} $breadcrumbs.siblings('div.end').filter(function() {
}; return $(this).index('div.end') == $panel.index() + 1;
})
/** )
* Container-related functions );
*/
var _container = cloudStack.ui.widgets.browser.container = {
/**
* Get all panels from container
*/
panels: function($container) {
return $container.find('div.panel');
}
};
/**
* Panel-related functions
*/
var _panel = cloudStack.ui.widgets.browser.panel = {
/**
* Compute width of panel, relative to container
*/
width: function($container, options) {
options = options ? options : {};
var width = $container.find('div.panel').size() < 1 || options.maximized == true ?
$container.width() : $container.width() - $container.width() / 4;
return width;
},
/**
* Get left position
*/
position: function($container, options) {
return $container.find('div.panel').size() <= 1 || options.maximized == true ?
0 : _panel.width($container, options) - _panel.width($container, options) / 1.5;
},
/**
* Get the top panel z-index, for proper stacking
*/
topIndex: function($container) {
var base = 50; // Minimum z-index
return Math.max.apply(
null,
$.map(
$container.find('div.panel'),
function(elem) {
return parseInt($(elem).css('z-index')) || base;
}
)
) + 1;
},
/**
* State when panel is outside container
*/
initialState: function($container) {
return {
left: $container.width()
};
},
/**
* Get panel and breadcrumb behind specific panel
*/
lower: function($container, $panel) {
return _container.panels($container).filter(function() {
return $(this).index() < $panel.index();
});
},
/**
* Get panel and breadcrumb stacked above specific panel
*/
higher: function($container, $panel) {
return _container.panels($container).filter(function() {
return $(this).index() > $panel.index();
});
},
/**
* Generate new panel
*/
create: function($container, options) {
var $panel = $('<div>').addClass('panel').css(
{
position: 'absolute',
width: _panel.width($container, { maximized: options.maximized }),
zIndex: _panel.topIndex($container)
}
).append(
// Shadow
$('<div>').addClass('shadow')
).append(options.data);
if (options.maximized) $panel.addClass('always-maximized');
return $panel;
}
};
/**
* Browser -- jQuery widget
*/
$.widget('cloudStack.cloudBrowser', {
_init: function() {
this.element.addClass('cloudStack-widget cloudBrowser');
$('#breadcrumbs').append(
$('<ul>')
);
},
/**
* Make target panel the top-most
*/
selectPanel: function(args) {
var $panel = args.panel;
var $container = this.element;
var $toShow = _panel.lower($container, $panel);
var $toRemove = _panel.higher($container, $panel);
var complete = args.complete;
if ($panel.hasClass('maximized')) return false;
_breadcrumb.filter($toRemove).remove();
_breadcrumb.filter($panel.siblings()).removeClass('active');
_breadcrumb.filter($panel).addClass('active');
_breadcrumb.filter($('div.panel')).find('span').animate({
opacity: 1
});
_breadcrumb.filter(
$('div.panel.maximized')
.removeClass('maximized')
.addClass('reduced')
).removeClass('active maximized');
$toRemove.animate(
_panel.initialState($container),
{
duration: 500,
complete: function() {
$(this).remove();
if (complete) complete($toShow);
}
}
);
$toShow.show();
$panel.animate({
left: _panel.position($container, { maximized: $panel.hasClass('always-maximized') })
});
$panel.show().removeClass('reduced');
},
/**
* Toggle selected panel as fully expanded, hiding/showing other panels
*/
toggleMaximizePanel: function(args) {
var $panel = args.panel;
var $container = this.element;
var $toHide = $panel.siblings(':not(.always-maximized)');
var $shadow = $toHide.find('div.shadow');
if (args.panel.hasClass('maximized')) {
_breadcrumb.filter($panel).removeClass('maximized');
$panel.removeClass('maximized');
$panel.addClass('reduced');
_breadcrumb.filter($panel.siblings()).find('span').animate({ opacity: 1 });
$toHide.animate({ left: _panel.position($container, {}) },
{ duration: 500 });
$shadow.show();
} else {
_breadcrumb.filter($panel).addClass('maximized');
$panel.removeClass('reduced');
$panel.addClass('maximized');
_breadcrumb.filter($panel.siblings()).find('span').animate({ opacity: 0.5 });
$toHide.animate(_panel.initialState($container),
{ duration: 500 });
$shadow.hide();
}
},
/**
* Append new panel to end of container
*/
addPanel: function(args) {
var duration = args.duration ? args.duration : 500;
var $container = this.element;
var $parent = args.parent;
var $panel, $reduced, targetPosition;
// Create panel
$panel = _panel.create(this.element, {
maximized: args.maximizeIfSelected,
data: args.data
});
// Remove existing panels from parent
if ($parent) {
// Cleanup transitioning panels -- prevent old complete actions from running
$parent.siblings().stop();
_breadcrumb.filter(
$('div.panel.maximized')
.removeClass('maximized')
.addClass('reduced')
).removeClass('active maximized');
$parent.removeClass('maximized');
_breadcrumb.filter($parent.next()).remove();
$container.find($parent.next()).remove();
}
// Append panel
$panel.appendTo($container);
_breadcrumb.filter($panel.siblings()).removeClass('active');
_breadcrumb.create($panel, args.title)
.addClass('active')
.appendTo('#breadcrumbs ul');
// Reduced appearance for previous panels
$panel.siblings().filter(function() {
return $(this).index() < $panel.index();
}).addClass('reduced');
// Panel initial state
if ($panel.index() == 0) $panel.addClass('always-maximized');
$panel.css(
_panel.initialState($container, $panel)
);
// Panel slide-in
targetPosition = _panel.position($container, {
maximized: args.maximizeIfSelected
});
if (!$panel.index()) {
// Just show immediately if this is the first panel
$panel.css(
{ left: targetPosition }
);
if (args.complete) args.complete($panel, _breadcrumb.filter($panel));
} else {
// Animate slide-in
$panel.animate({ left: targetPosition }, {
duration: duration,
easing: 'easeOutCirc',
complete: function() {
// Hide panels
$panel.siblings().filter(function() {
return $(this).width() == $panel.width();
}); });
if ($panel.is(':visible') && args.complete) args.complete($panel); return $result;
} }
}); };
};
return $panel;
},
/** /**
* Clear all panels * Container-related functions
*/ */
removeAllPanels: function(args) { var _container = cloudStack.ui.widgets.browser.container = {
$('div.panel').stop(); // Prevent destroyed panels from animating /**
this.element.find('div.panel').remove(); * Get all panels from container
$('#breadcrumbs').find('ul li').remove(); */
$('#breadcrumbs').find('ul div.end').remove(); panels: function($container) {
} return $container.find('div.panel');
}); }
};
$('#breadcrumbs li').live('click', cloudStack.ui.event.bind( /**
'cloudBrowser', * Panel-related functions
{ */
'breadcrumb': function($target, $browser, data) { var _panel = cloudStack.ui.widgets.browser.panel = {
/**
* Compute width of panel, relative to container
*/
width: function($container, options) {
options = options ? options : {};
var width = $container.find('div.panel').size() < 1 || options.maximized == true ?
$container.width() : $container.width() - $container.width() / 4;
if ($ ('#browser').hasClass('panel-highlight')) { return width;
return false; },
}
$browser.cloudBrowser('selectPanel', { panel: data.panel }); /**
} * Get left position
} */
)); position: function($container, options) {
return $container.find('div.panel').size() <= 1 || options.maximized == true ?
0 : _panel.width($container, options) - _panel.width($container, options) / 1.5;
},
// Breadcrumb hovering /**
$('#breadcrumbs li').live('mouseover', cloudStack.ui.event.bind( * Get the top panel z-index, for proper stacking
'cloudBrowser', */
{ topIndex: function($container) {
'breadcrumb': function($target, $browser, data) { var base = 50; // Minimum z-index
var $hiddenPanels = data.panel.siblings().filter(function(){
return $(this).index() > data.panel.index();
});
var $targetPanel = data.panel.filter(':first');
var $targetBreadcrumb = _breadcrumb.filter($targetPanel);
var $panelWrapper = $('<div>').addClass('panel panel-highlight-wrapper');
$hiddenPanels.addClass('mouseover-hidden'); return Math.max.apply(
null,
$.map(
$container.find('div.panel'),
function(elem) {
return parseInt($(elem).css('z-index')) || base;
}
)
) + 1;
},
$browser.data('browser-panel-highlight-timer', setTimeout(function() { /**
$('#browser').addClass('panel-highlight'); * State when panel is outside container
$('.overlay').remove(); */
initialState: function($container) {
return {
left: $container.width()
};
},
// Setup panel and wrapper positioning /**
$panelWrapper * Get panel and breadcrumb behind specific panel
.css({ */
left: $targetPanel.position().left lower: function($container, $panel) {
}) return _container.panels($container).filter(function() {
.width($targetPanel.width()); return $(this).index() < $panel.index();
$targetPanel });
.wrap($panelWrapper); },
$panelWrapper
.zIndex(10000)
.overlay();
$targetPanel.filter(':last').addClass('highlighted');
// Setup breadcrumbs /**
$targetBreadcrumb.each(function() { * Get panel and breadcrumb stacked above specific panel
$(this).data('breadcrumb-original-zindex', $(this).zIndex()); */
}); higher: function($container, $panel) {
$targetBreadcrumb.zIndex(10001); return _container.panels($container).filter(function() {
return $(this).index() > $panel.index();
});
},
$hiddenPanels.hide(); /**
}, 1000)); * Generate new panel
} */
} create: function($container, options) {
)); var $panel = $('<div>').addClass('panel').css({
position: 'absolute',
width: _panel.width($container, {
maximized: options.maximized
}),
zIndex: _panel.topIndex($container)
}).append(
// Shadow
$('<div>').addClass('shadow')
).append(options.data);
$('#breadcrumbs li').live('mouseout',cloudStack.ui.event.bind( if (options.maximized) $panel.addClass('always-maximized');
'cloudBrowser',
{
'breadcrumb': function($target, $browser, data) {
var $getHiddenPanels = $browser.find('.panel.mouseover-hidden');
var $visiblePanels = $getHiddenPanels.siblings();
var $visibleBreadcrumbs = _breadcrumb.filter($visiblePanels);
clearTimeout($browser.data('browser-panel-highlight-timer')); return $panel;
$('#browser').removeClass('panel-highlight'); }
$('#browser .panel').removeClass('highlighted'); };
$('#browser .panel.panel-highlight-wrapper').each(function() {
var $wrapper = $(this);
var $panel = $wrapper.find('.panel');
$wrapper.after($panel); /**
$wrapper.remove(); * Browser -- jQuery widget
}); */
$getHiddenPanels.removeClass('mouseover-hidden').show(); $.widget('cloudStack.cloudBrowser', {
$visibleBreadcrumbs.each(function() { _init: function() {
$(this).zIndex($(this).data('breadcrumb-original-zindex')); this.element.addClass('cloudStack-widget cloudBrowser');
}); $('#breadcrumbs').append(
$('.overlay').remove(); $('<ul>')
$('#browser .panel > .highlight-arrow').remove(); );
} },
}
)); /**
* Make target panel the top-most
*/
selectPanel: function(args) {
var $panel = args.panel;
var $container = this.element;
var $toShow = _panel.lower($container, $panel);
var $toRemove = _panel.higher($container, $panel);
var complete = args.complete;
if ($panel.hasClass('maximized')) return false;
_breadcrumb.filter($toRemove).remove();
_breadcrumb.filter($panel.siblings()).removeClass('active');
_breadcrumb.filter($panel).addClass('active');
_breadcrumb.filter($('div.panel')).find('span').animate({
opacity: 1
});
_breadcrumb.filter(
$('div.panel.maximized')
.removeClass('maximized')
.addClass('reduced')
).removeClass('active maximized');
$toRemove.animate(
_panel.initialState($container), {
duration: 500,
complete: function() {
$(this).remove();
if (complete) complete($toShow);
}
}
);
$toShow.show();
$panel.animate({
left: _panel.position($container, {
maximized: $panel.hasClass('always-maximized')
})
});
$panel.show().removeClass('reduced');
},
/**
* Toggle selected panel as fully expanded, hiding/showing other panels
*/
toggleMaximizePanel: function(args) {
var $panel = args.panel;
var $container = this.element;
var $toHide = $panel.siblings(':not(.always-maximized)');
var $shadow = $toHide.find('div.shadow');
if (args.panel.hasClass('maximized')) {
_breadcrumb.filter($panel).removeClass('maximized');
$panel.removeClass('maximized');
$panel.addClass('reduced');
_breadcrumb.filter($panel.siblings()).find('span').animate({
opacity: 1
});
$toHide.animate({
left: _panel.position($container, {})
}, {
duration: 500
});
$shadow.show();
} else {
_breadcrumb.filter($panel).addClass('maximized');
$panel.removeClass('reduced');
$panel.addClass('maximized');
_breadcrumb.filter($panel.siblings()).find('span').animate({
opacity: 0.5
});
$toHide.animate(_panel.initialState($container), {
duration: 500
});
$shadow.hide();
}
},
/**
* Append new panel to end of container
*/
addPanel: function(args) {
var duration = args.duration ? args.duration : 500;
var $container = this.element;
var $parent = args.parent;
var $panel, $reduced, targetPosition;
// Create panel
$panel = _panel.create(this.element, {
maximized: args.maximizeIfSelected,
data: args.data
});
// Remove existing panels from parent
if ($parent) {
// Cleanup transitioning panels -- prevent old complete actions from running
$parent.siblings().stop();
_breadcrumb.filter(
$('div.panel.maximized')
.removeClass('maximized')
.addClass('reduced')
).removeClass('active maximized');
$parent.removeClass('maximized');
_breadcrumb.filter($parent.next()).remove();
$container.find($parent.next()).remove();
}
// Append panel
$panel.appendTo($container);
_breadcrumb.filter($panel.siblings()).removeClass('active');
_breadcrumb.create($panel, args.title)
.addClass('active')
.appendTo('#breadcrumbs ul');
// Reduced appearance for previous panels
$panel.siblings().filter(function() {
return $(this).index() < $panel.index();
}).addClass('reduced');
// Panel initial state
if ($panel.index() == 0) $panel.addClass('always-maximized');
$panel.css(
_panel.initialState($container, $panel)
);
// Panel slide-in
targetPosition = _panel.position($container, {
maximized: args.maximizeIfSelected
});
if (!$panel.index()) {
// Just show immediately if this is the first panel
$panel.css({
left: targetPosition
});
if (args.complete) args.complete($panel, _breadcrumb.filter($panel));
} else {
// Animate slide-in
$panel.animate({
left: targetPosition
}, {
duration: duration,
easing: 'easeOutCirc',
complete: function() {
// Hide panels
$panel.siblings().filter(function() {
return $(this).width() == $panel.width();
});
if ($panel.is(':visible') && args.complete) args.complete($panel);
}
});
};
return $panel;
},
/**
* Clear all panels
*/
removeAllPanels: function(args) {
$('div.panel').stop(); // Prevent destroyed panels from animating
this.element.find('div.panel').remove();
$('#breadcrumbs').find('ul li').remove();
$('#breadcrumbs').find('ul div.end').remove();
}
});
$('#breadcrumbs li').live('click', cloudStack.ui.event.bind(
'cloudBrowser', {
'breadcrumb': function($target, $browser, data) {
if ($('#browser').hasClass('panel-highlight')) {
return false;
}
$browser.cloudBrowser('selectPanel', {
panel: data.panel
});
}
}
));
// Breadcrumb hovering
$('#breadcrumbs li').live('mouseover', cloudStack.ui.event.bind(
'cloudBrowser', {
'breadcrumb': function($target, $browser, data) {
var $hiddenPanels = data.panel.siblings().filter(function() {
return $(this).index() > data.panel.index();
});
var $targetPanel = data.panel.filter(':first');
var $targetBreadcrumb = _breadcrumb.filter($targetPanel);
var $panelWrapper = $('<div>').addClass('panel panel-highlight-wrapper');
$hiddenPanels.addClass('mouseover-hidden');
$browser.data('browser-panel-highlight-timer', setTimeout(function() {
$('#browser').addClass('panel-highlight');
$('.overlay').remove();
// Setup panel and wrapper positioning
$panelWrapper
.css({
left: $targetPanel.position().left
})
.width($targetPanel.width());
$targetPanel
.wrap($panelWrapper);
$panelWrapper
.zIndex(10000)
.overlay();
$targetPanel.filter(':last').addClass('highlighted');
// Setup breadcrumbs
$targetBreadcrumb.each(function() {
$(this).data('breadcrumb-original-zindex', $(this).zIndex());
});
$targetBreadcrumb.zIndex(10001);
$hiddenPanels.hide();
}, 1000));
}
}
));
$('#breadcrumbs li').live('mouseout', cloudStack.ui.event.bind(
'cloudBrowser', {
'breadcrumb': function($target, $browser, data) {
var $getHiddenPanels = $browser.find('.panel.mouseover-hidden');
var $visiblePanels = $getHiddenPanels.siblings();
var $visibleBreadcrumbs = _breadcrumb.filter($visiblePanels);
clearTimeout($browser.data('browser-panel-highlight-timer'));
$('#browser').removeClass('panel-highlight');
$('#browser .panel').removeClass('highlighted');
$('#browser .panel.panel-highlight-wrapper').each(function() {
var $wrapper = $(this);
var $panel = $wrapper.find('.panel');
$wrapper.after($panel);
$wrapper.remove();
});
$getHiddenPanels.removeClass('mouseover-hidden').show();
$visibleBreadcrumbs.each(function() {
$(this).zIndex($(this).data('breadcrumb-original-zindex'));
});
$('.overlay').remove();
$('#browser .panel > .highlight-arrow').remove();
}
}
));
})(jQuery, cloudStack); })(jQuery, cloudStack);

View File

@ -15,264 +15,264 @@
// specific language governing permissions and limitations // specific language governing permissions and limitations
// under the License. // under the License.
(function($) { (function($) {
/**
* Convert table to be resizable and sortable
*
*/
$.fn.dataTable = function(method, options) {
var $table = this;
/** /**
* Check if position is in 'resize zone' * Convert table to be resizable and sortable
* *
* @return boolean, true if position is within bounds
*/ */
var withinResizeBounds = function($elem, posX) { $.fn.dataTable = function(method, options) {
var leftBound = $elem.offset().left + $elem.width() / 1.2; var $table = this;
return posX > leftBound; /**
}; * Check if position is in 'resize zone'
*
* @return boolean, true if position is within bounds
*/
var withinResizeBounds = function($elem, posX) {
var leftBound = $elem.offset().left + $elem.width() / 1.2;
/** return posX > leftBound;
* Handles actual resizing of table headers };
*/
var resizeDragEvent = function(event) {
var $elem = $(this);
if (event.type == 'mousedown') { /**
$elem.addClass('dragging'); * Handles actual resizing of table headers
*/
var resizeDragEvent = function(event) {
var $elem = $(this);
return false; if (event.type == 'mousedown') {
} else if (event.type == 'mouseup') { $elem.addClass('dragging');
$table.find('th').removeClass('dragging');
return false; return false;
} } else if (event.type == 'mouseup') {
$table.find('th').removeClass('dragging');
var isDraggable = $elem.hasClass('dragging'); return false;
}
if (!isDraggable) { var isDraggable = $elem.hasClass('dragging');
return false;
}
var columnIndex = $elem.index(); if (!isDraggable) {
return false;
}
// Get all TDs from column var columnIndex = $elem.index();
var columnCells = [];
$table.find('tbody tr:first').each(function() {
var targetCell = $($(this).find('td')[columnIndex]);
columnCells.push(targetCell); // Get all TDs from column
}); var columnCells = [];
$table.find('tbody tr:first').each(function() {
var targetCell = $($(this).find('td')[columnIndex]);
var tolerance = 25; columnCells.push(targetCell);
var targetWidth = event.pageX - $elem.offset().left + tolerance; });
$(columnCells).each(function() {
$(this).css({
width: targetWidth
});
});
resizeHeaders(); var tolerance = 25;
var targetWidth = event.pageX - $elem.offset().left + tolerance;
$(columnCells).each(function() {
$(this).css({
width: targetWidth
});
});
return true; resizeHeaders();
};
var splitTable = function() { return true;
var $mainContainer = $('<div>') };
.addClass('data-table')
.appendTo($table.parent()) var splitTable = function() {
.append( var $mainContainer = $('<div>')
$table.remove() .addClass('data-table')
.appendTo($table.parent())
.append(
$table.remove()
); );
$table = $mainContainer; $table = $mainContainer;
var $theadContainer = $('<div>').addClass('fixed-header').prependTo($table); var $theadContainer = $('<div>').addClass('fixed-header').prependTo($table);
var $theadTable = $('<table>').appendTo($theadContainer).attr('nowrap', 'nowrap'); var $theadTable = $('<table>').appendTo($theadContainer).attr('nowrap', 'nowrap');
var $thead = $table.find('thead').remove().appendTo($theadTable); var $thead = $table.find('thead').remove().appendTo($theadTable);
return $thead; return $thead;
}; };
/** /**
* Event to set resizable appearance on hover * Event to set resizable appearance on hover
*/ */
var hoverResizableEvent = function(event) { var hoverResizableEvent = function(event) {
var $elem = $(this); var $elem = $(this);
var posX = event.pageX; var posX = event.pageX;
if (event.type != 'mouseout' && withinResizeBounds($elem, posX)) { if (event.type != 'mouseout' && withinResizeBounds($elem, posX)) {
$elem.addClass('resizable'); $elem.addClass('resizable');
} else { } else {
$elem.removeClass('resizable'); $elem.removeClass('resizable');
} }
return true; return true;
}; };
/** /**
* Make row at specified index selected or unselected * Make row at specified index selected or unselected
* *
* @param rowIndex Row's index, starting at 1 * @param rowIndex Row's index, starting at 1
*/ */
var toggleSelectRow = function(rowIndex) { var toggleSelectRow = function(rowIndex) {
var $rows = $table.find('tbody tr'); var $rows = $table.find('tbody tr');
var $row = $($rows[rowIndex]); var $row = $($rows[rowIndex]);
$row.siblings().removeClass('selected'); $row.siblings().removeClass('selected');
return $row.addClass('selected'); return $row.addClass('selected');
}; };
var computeEvenOddRows = function() { var computeEvenOddRows = function() {
var currentRowType = 'even'; var currentRowType = 'even';
$table.find('tbody tr').each(function() { $table.find('tbody tr').each(function() {
var $row = $(this); var $row = $(this);
$row.removeClass('even').removeClass('odd'); $row.removeClass('even').removeClass('odd');
$row.addClass(currentRowType); $row.addClass(currentRowType);
if (currentRowType == 'even') currentRowType = 'odd'; if (currentRowType == 'even') currentRowType = 'odd';
else currentRowType = 'even'; else currentRowType = 'even';
}); });
}; };
/** /**
* Sort table by column * Sort table by column
* *
* @param columnIndex Index of column (starting at 0) to sort by * @param columnIndex Index of column (starting at 0) to sort by
*/ */
var sortTable = function(columnIndex) { var sortTable = function(columnIndex) {
return false; return false;
var direction = 'asc'; var direction = 'asc';
if ($table.find('thead th').hasClass('sorted ' + direction)) { if ($table.find('thead th').hasClass('sorted ' + direction)) {
direction = 'desc'; direction = 'desc';
} }
$table.find('thead th').removeClass('sorted desc asc'); $table.find('thead th').removeClass('sorted desc asc');
$($table.find('thead th')[columnIndex]).addClass('sorted').addClass(direction); $($table.find('thead th')[columnIndex]).addClass('sorted').addClass(direction);
var $elems = $table.find('tbody td').filter(function() { var $elems = $table.find('tbody td').filter(function() {
return $(this).index() == columnIndex; return $(this).index() == columnIndex;
}); });
var sortData = []; var sortData = [];
$elems.each(function() { $elems.each(function() {
sortData.push($(this).html()); sortData.push($(this).html());
sortData.sort(); sortData.sort();
if (direction == 'asc') { if (direction == 'asc') {
sortData.reverse(); sortData.reverse();
} }
}); });
$(sortData).each(function() { $(sortData).each(function() {
var sortKey = this; var sortKey = this;
var $targetCell = $elems.filter(function() { var $targetCell = $elems.filter(function() {
return $(this).html() == sortKey; return $(this).html() == sortKey;
}); });
var $targetContainer = $targetCell.parent(); var $targetContainer = $targetCell.parent();
$targetContainer.remove().appendTo($table.find('tbody')); $targetContainer.remove().appendTo($table.find('tbody'));
}); });
computeEvenOddRows(); computeEvenOddRows();
}; };
var resizeHeaders = function() { var resizeHeaders = function() {
var $thead = $table.closest('div.data-table').find('thead'); var $thead = $table.closest('div.data-table').find('thead');
var $tbody = $table.find('tbody'); var $tbody = $table.find('tbody');
var $ths = $thead.find('th'); var $ths = $thead.find('th');
var $tds = $tbody.find('tr:first td'); var $tds = $tbody.find('tr:first td');
if ($ths.size() > $tds.size()) { if ($ths.size() > $tds.size()) {
$ths.width( $ths.width(
$table.width() / $ths.size() $table.width() / $ths.size()
); );
return false; return false;
} }
$ths.each(function() { $ths.each(function() {
var $th = $(this); var $th = $(this);
var $td = $tds.filter(function() { var $td = $tds.filter(function() {
return $(this).index() == $th.index(); return $(this).index() == $th.index();
}); });
$th.width($td.width()); $th.width($td.width());
return true; return true;
}); });
return $ths; return $ths;
}; };
var methods = { var methods = {
removeRow: function(rowIndex) { removeRow: function(rowIndex) {
var $row = $($table.find('tbody tr')[rowIndex]); var $row = $($table.find('tbody tr')[rowIndex]);
$row.fadeOut(function() { $row.fadeOut(function() {
$row.remove(); $row.remove();
computeEvenOddRows(); computeEvenOddRows();
}); });
return $row; return $row;
}, },
refresh: function() { refresh: function() {
resizeHeaders(); resizeHeaders();
computeEvenOddRows(); computeEvenOddRows();
}, },
selectRow: function(rowIndex) { selectRow: function(rowIndex) {
var $row = $($table.find('tbody tr')[rowIndex]); var $row = $($table.find('tbody tr')[rowIndex]);
$row.siblings().removeClass('selected'); $row.siblings().removeClass('selected');
$row.addClass('selected'); $row.addClass('selected');
} }
}; };
var init = function() { var init = function() {
var noSelect = options && options.noSelect == true ? true : false; var noSelect = options && options.noSelect == true ? true : false;
if (!$table.closest('div.data-table').size() && !$table.hasClass('no-split')) { if (!$table.closest('div.data-table').size() && !$table.hasClass('no-split')) {
splitTable(); splitTable();
$table.find('tbody').closest('table').addClass('body'); $table.find('tbody').closest('table').addClass('body');
} }
$table.find('th').bind('mousemove mouseout', hoverResizableEvent); $table.find('th').bind('mousemove mouseout', hoverResizableEvent);
$table.find('th').bind('mousedown mousemove mouseup mouseout', resizeDragEvent); $table.find('th').bind('mousedown mousemove mouseup mouseout', resizeDragEvent);
$table.find('th').bind('click', function(event) { $table.find('th').bind('click', function(event) {
if ($(this).hasClass('resizable')) { if ($(this).hasClass('resizable')) {
return false; return false;
}
sortTable($(event.target).index());
return false;
});
$table.bind('click', function(event) {
var $tr = $(event.target).closest('tr');
if (!$tr.size() || noSelect) return true;
var rowIndex = $tr.index();
toggleSelectRow(rowIndex);
return true;
});
computeEvenOddRows();
resizeHeaders();
};
if (methods[method]) {
return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
} else if (!method) {
init();
} else {
$.error('Method ' + method + ' does not exist on jQuery.dataTable');
} }
sortTable($(event.target).index()); return $table;
return false;
});
$table.bind('click', function(event) {
var $tr = $(event.target).closest('tr');
if (!$tr.size() || noSelect) return true;
var rowIndex = $tr.index();
toggleSelectRow(rowIndex);
return true;
});
computeEvenOddRows();
resizeHeaders();
}; };
if (methods[method]) {
return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
} else if (!method) {
init();
} else {
$.error('Method ' + method + ' does not exist on jQuery.dataTable');
}
return $table;
};
}(jQuery)); }(jQuery));

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -15,356 +15,367 @@
// specific language governing permissions and limitations // specific language governing permissions and limitations
// under the License. // under the License.
(function($, cloudStack, _l) { (function($, cloudStack, _l) {
/** /**
* Notification handling * Notification handling
*/ */
var notifications = { var notifications = {
activeTasks: [], activeTasks: [],
cornerAlert: function(args, options) { cornerAlert: function(args, options) {
if (!options) options = {}; if (!options) options = {};
var $container = $('#container'); // Put in main container box var $container = $('#container'); // Put in main container box
var $cornerAlert = $('<div>').addClass('notification corner-alert') var $cornerAlert = $('<div>').addClass('notification corner-alert')
.hide() .hide()
.appendTo($container) .appendTo($container)
.append(
$('<div>').addClass('title').append(
$('<span>').html(
options.error ? options.error : _l('label.task.completed')
)
)
)
.append(
$('<div>').addClass('message')
.append( .append(
$('<span>').html(_l(args.message)) $('<div>').addClass('title').append(
) $('<span>').html(
); options.error ? options.error : _l('label.task.completed')
)
if (options.error) { )
$cornerAlert.addClass('error');
}
return $cornerAlert
.css({
opacity: 0,
position: 'absolute',
top: $($container).height(),
left: $($container).width() - $cornerAlert.width()
})
.animate({
opacity: 1,
top: $container.height() - $cornerAlert.height()
}, {
complete: function() {
setTimeout(function() {
$cornerAlert.fadeOut('fast', function() {
$cornerAlert.remove();
});
}, 5000);
}
})
.show();
},
add: function(args, $popup, $total) {
var currentTotal = parseInt($total.html());
var newTotal = currentTotal + 1;
var desc = args.desc;
var section = $('html body')
.find('[cloudStack-container]')
.data('cloudStack-args')
.sections[args.section];
var _custom = args._custom;
var $item = $('<li>')
.append(
$('<span>').html(_l(args.desc))
) )
.append( .append(
$('<div>').addClass('remove') $('<div>').addClass('message')
.append(
$('<span>').html(_l(args.message))
)
); );
var additionalComplete = args.complete;
// Get information for specified section path if (options.error) {
$item.data('notification-section', args.section); $cornerAlert.addClass('error');
$item.data('notification-custom', _custom);
$popup.find('ul').append($item);
$total.html(newTotal);
$total.parent().addClass('pending');
$item.addClass('pending');
// Setup timer
var pollTimer = setInterval(function() {
args.poll({
_custom: _custom,
pollTimer: pollTimer,
complete: function(args) {
clearInterval(pollTimer);
notifications.cornerAlert({ message: $item.html() });
notifications.activeTasks.pop(pollTimer);
$item.removeClass('pending');
if (additionalComplete) additionalComplete();
},
incomplete: function(args) {},
error: function(args) {
if (args.message) {
cloudStack.dialog.notice({ message: _s(args.message) });
} }
clearInterval(pollTimer); return $cornerAlert
notifications.activeTasks.pop(pollTimer); .css({
notifications.cornerAlert({ message: $item.html() }, { opacity: 0,
error: _l('label.error') position: 'absolute',
top: $($container).height(),
left: $($container).width() - $cornerAlert.width()
})
.animate({
opacity: 1,
top: $container.height() - $cornerAlert.height()
}, {
complete: function() {
setTimeout(function() {
$cornerAlert.fadeOut('fast', function() {
$cornerAlert.remove();
});
}, 5000);
}
})
.show();
},
add: function(args, $popup, $total) {
var currentTotal = parseInt($total.html());
var newTotal = currentTotal + 1;
var desc = args.desc;
var section = $('html body')
.find('[cloudStack-container]')
.data('cloudStack-args')
.sections[args.section];
var _custom = args._custom;
var $item = $('<li>')
.append(
$('<span>').html(_l(args.desc))
)
.append(
$('<div>').addClass('remove')
);
var additionalComplete = args.complete;
// Get information for specified section path
$item.data('notification-section', args.section);
$item.data('notification-custom', _custom);
$popup.find('ul').append($item);
$total.html(newTotal);
$total.parent().addClass('pending');
$item.addClass('pending');
// Setup timer
var pollTimer = setInterval(function() {
args.poll({
_custom: _custom,
pollTimer: pollTimer,
complete: function(args) {
clearInterval(pollTimer);
notifications.cornerAlert({
message: $item.html()
});
notifications.activeTasks.pop(pollTimer);
$item.removeClass('pending');
if (additionalComplete) additionalComplete();
},
incomplete: function(args) {},
error: function(args) {
if (args.message) {
cloudStack.dialog.notice({
message: _s(args.message)
});
}
clearInterval(pollTimer);
notifications.activeTasks.pop(pollTimer);
notifications.cornerAlert({
message: $item.html()
}, {
error: _l('label.error')
});
$item.removeClass('pending').addClass('error');
if (additionalComplete) additionalComplete();
}
});
}, args.interval);
notifications.activeTasks.push(pollTimer);
return $total;
},
/**
* Set total to 0
*/
resetTotal: function($popup) {
var $total = $popup.data('notifications-attach-to').find('div.total span');
var $items = $popup.find('ul li');
var total = $items.size();
var completed = $items.filter(':not(.pending)').size();
var newTotal = total - completed;
if (newTotal < 0) newTotal = completed;
$total.html(newTotal);
if (!newTotal)
$total.parent().removeClass('pending');
},
/**
* Remove item from notification list
*/
removeItem: function($popup, $item) {
if ($item.closest('li').hasClass('pending')) return false;
$item.remove();
return true;
},
/**
* Remove all completed notifications
*/
clear: function($popup) {
$popup.find('ul li').each(function() {
var $item = $(this);
if (!$item.hasClass('pending')) {
notifications.removeItem($popup, $item);
}
}); });
$item.removeClass('pending').addClass('error'); },
popup: {
create: function($attachTo) {
var $popup = $('<div>')
.addClass('notification-box')
.append(
// Header
$('<h3>').html(_l('label.notifications'))
)
.append(
// Container
$('<div>').addClass('container')
.append(
// Notification list
$('<ul>')
)
)
.append(
// Buttons
$('<div>').addClass('buttons')
.append(
// Clear list
$('<div>').addClass('button clear-list')
.append(
$('<span>').html(_l('label.clear.list'))
)
)
.append(
$('<div>').addClass('button close')
.append(
$('<span>').html(_l('label.close'))
)
)
)
.css({
position: 'absolute'
})
.data('notifications-attach-to', $attachTo)
.hide();
if (additionalComplete) additionalComplete(); if (!$attachTo.hasClass('notifications')) $attachTo.addClass('notifications');
} $attachTo.data('notifications-popup', $popup);
});
}, args.interval);
notifications.activeTasks.push(pollTimer);
return $total; return $popup;
}, },
show: function($popup, $attachTo) {
/** notifications.resetTotal($popup);
* Set total to 0 return notifications.popup.reposition($popup, $attachTo)
*/ .overlay({
resetTotal: function($popup) { closeAction: function() {
var $total = $popup.data('notifications-attach-to').find('div.total span'); notifications.popup.hide($popup);
var $items = $popup.find('ul li'); }
var total = $items.size(); })
var completed = $items.filter(':not(.pending)').size(); .fadeIn();
var newTotal = total - completed; },
hide: function($popup) {
if (newTotal < 0) newTotal = completed; $popup.fadeOut();
},
$total.html(newTotal); reposition: function($popup, $attachTo) {
return $popup
if (!newTotal) .css({
$total.parent().removeClass('pending'); zIndex: 10000,
}, top: $attachTo.offset().top + $attachTo.height() + 10,
left: $attachTo.offset().left - $attachTo.width()
/** });
* Remove item from notification list
*/
removeItem: function($popup, $item) {
if ($item.closest('li').hasClass('pending')) return false;
$item.remove();
return true;
},
/**
* Remove all completed notifications
*/
clear: function($popup) {
$popup.find('ul li').each(function() {
var $item = $(this);
if (!$item.hasClass('pending')) {
notifications.removeItem($popup, $item);
}
});
},
popup: {
create: function($attachTo) {
var $popup = $('<div>')
.addClass('notification-box')
.append(
// Header
$('<h3>').html(_l('label.notifications'))
)
.append(
// Container
$('<div>').addClass('container')
.append(
// Notification list
$('<ul>')
)
)
.append(
// Buttons
$('<div>').addClass('buttons')
.append(
// Clear list
$('<div>').addClass('button clear-list')
.append(
$('<span>').html(_l('label.clear.list'))
)
)
.append(
$('<div>').addClass('button close')
.append(
$('<span>').html(_l('label.close'))
)
)
)
.css({ position: 'absolute' })
.data('notifications-attach-to', $attachTo)
.hide();
if (!$attachTo.hasClass('notifications')) $attachTo.addClass('notifications');
$attachTo.data('notifications-popup', $popup);
return $popup;
},
show: function($popup, $attachTo) {
notifications.resetTotal($popup);
return notifications.popup.reposition($popup, $attachTo)
.overlay({
closeAction: function() {
notifications.popup.hide($popup);
} }
}) }
.fadeIn();
},
hide: function($popup) {
$popup.fadeOut();
},
reposition: function($popup, $attachTo) {
return $popup
.css({
zIndex: 10000,
top: $attachTo.offset().top + $attachTo.height() + 10,
left: $attachTo.offset().left - $attachTo.width()
});
}
}
};
/**
* Define notification widget -- this is basically represented in a
* notifications icon, that contains a pop-up list of notifications
*/
$.fn.notifications = function(method, args) {
var $attachTo = this;
var $total = $attachTo.find('div.total span');
var $popup;
var init = function() {
$popup = notifications.popup.create($attachTo).appendTo('html body');
}; };
if (method == 'add') /**
notifications.add(args, $attachTo.data('notifications-popup'), $total); * Define notification widget -- this is basically represented in a
else * notifications icon, that contains a pop-up list of notifications
init(); */
$.fn.notifications = function(method, args) {
var $attachTo = this;
var $total = $attachTo.find('div.total span');
var $popup;
return this; var init = function() {
}; $popup = notifications.popup.create($attachTo).appendTo('html body');
};
/** if (method == 'add')
* Notifications UI helpers notifications.add(args, $attachTo.data('notifications-popup'), $total);
*/ else
cloudStack.ui.notifications = { init();
add: function(notification, success, successArgs, error, errorArgs) {
if (!notification) {
success(successArgs);
return false; return this;
}; };
var $notifications = $('div.notifications'); /**
* Notifications UI helpers
*/
cloudStack.ui.notifications = {
add: function(notification, success, successArgs, error, errorArgs) {
if (!notification) {
success(successArgs);
if (!notification.poll) { return false;
cloudStack.ui.event.call('addNotification', { };
section: notification.section,
desc: notification.desc,
interval: 0,
poll: function(args) { success(successArgs); args.complete(); }
});
} else {
cloudStack.ui.event.call('addNotification', {
section: notification.section,
desc: notification.desc,
interval: notification.interval ? notification.interval : g_queryAsyncJobResultInterval,
_custom: notification._custom,
poll: function(args) {
var complete = args.complete;
var notificationError = args.error;
notification.poll({ var $notifications = $('div.notifications');
_custom: args._custom,
complete: function(args) {
success($.extend(successArgs, args));
complete(args);
},
error: function(args) {
error($.extend(errorArgs, args));
notificationError(args);
}
});
}
});
}
return true; if (!notification.poll) {
} cloudStack.ui.event.call('addNotification', {
}; section: notification.section,
desc: notification.desc,
interval: 0,
poll: function(args) {
success(successArgs);
args.complete();
}
});
} else {
cloudStack.ui.event.call('addNotification', {
section: notification.section,
desc: notification.desc,
interval: notification.interval ? notification.interval : g_queryAsyncJobResultInterval,
_custom: notification._custom,
poll: function(args) {
var complete = args.complete;
var notificationError = args.error;
// Setup notification listener -- accepts same args as notification.poll({
$(window).bind('cloudStack.addNotification', function(event, data) { _custom: args._custom,
$('.notifications').notifications('add', data); complete: function(args) {
}); success($.extend(successArgs, args));
complete(args);
},
error: function(args) {
error($.extend(errorArgs, args));
notificationError(args);
}
});
}
});
}
$(document).click(function(event) { return true;
var $target = $(event.target); }
var $attachTo, $popup; };
// Notifications header area // Setup notification listener -- accepts same args as
if ($target.closest('.notifications').size()) { $(window).bind('cloudStack.addNotification', function(event, data) {
$attachTo = $target.closest('.notifications'); $('.notifications').notifications('add', data);
$popup = $attachTo.data('notifications-popup'); });
notifications.popup.show($popup, $attachTo);
return false; $(document).click(function(event) {
} var $target = $(event.target);
var $attachTo, $popup;
// Notification item // Notifications header area
if ($target.is('.notification-box li span')) { if ($target.closest('.notifications').size()) {
var $li = $target.closest('.notification-box li'); $attachTo = $target.closest('.notifications');
$popup = $attachTo.data('notifications-popup');
notifications.popup.show($popup, $attachTo);
$('#navigation ul li').filter(function() { return false;
return $(this).hasClass($li.data('notification-section')); }
}).click();
$('div.overlay').click();
return false; // Notification item
} if ($target.is('.notification-box li span')) {
var $li = $target.closest('.notification-box li');
// Popup $('#navigation ul li').filter(function() {
if ($target.closest('div.notification-box').size()) { return $(this).hasClass($li.data('notification-section'));
$popup = $target.closest('div.notification-box'); }).click();
$('div.overlay').click();
// Clear list return false;
if ($target.closest('.button.clear-list').size()) { }
notifications.clear($popup);
}
// Remove instance item // Popup
else if ($target.hasClass('remove')) { if ($target.closest('div.notification-box').size()) {
notifications.removeItem($popup, $target.closest('li')); $popup = $target.closest('div.notification-box');
}
// Close button // Clear list
else if ($target.closest('.button.close')) { if ($target.closest('.button.clear-list').size()) {
$('div.overlay').click(); notifications.clear($popup);
} }
return false; // Remove instance item
} else if ($target.hasClass('remove')) {
notifications.removeItem($popup, $target.closest('li'));
}
return true; // Close button
}); else if ($target.closest('.button.close')) {
$('div.overlay').click();
}
$(window).resize(function(event) { return false;
var $popup = $('div.notification-box:visible'); }
if ($popup.size()) return true;
notifications.popup.reposition($popup, $popup.data('notifications-attach-to')); });
});
$(window).resize(function(event) {
var $popup = $('div.notification-box:visible');
if ($popup.size())
notifications.popup.reposition($popup, $popup.data('notifications-attach-to'));
});
})(window.jQuery, window.cloudStack, window._l); })(window.jQuery, window.cloudStack, window._l);

View File

@ -15,36 +15,36 @@
// specific language governing permissions and limitations // specific language governing permissions and limitations
// under the License. // under the License.
(function($) { (function($) {
/** /**
* Create a dark overlay, for modal dialogs, etc. * Create a dark overlay, for modal dialogs, etc.
*/ */
$.fn.overlay = function(args) { $.fn.overlay = function(args) {
var $topElem = this; var $topElem = this;
var $overlay = $('<div class="overlay">').hide().appendTo('html body').css({ var $overlay = $('<div class="overlay">').hide().appendTo('html body').css({
position: 'absolute', position: 'absolute',
background: 'black', background: 'black',
opacity: 0.5, opacity: 0.5,
width: '100%', width: '100%',
height: '100%', height: '100%',
top: $(window).scrollTop(), top: $(window).scrollTop(),
left: 0, left: 0,
zIndex: $topElem.css('z-index') - 1 zIndex: $topElem.css('z-index') - 1
}).show(); }).show();
// Events // Events
$overlay.click(function(event) { $overlay.click(function(event) {
if (!args || !args.closeAction) return false; if (!args || !args.closeAction) return false;
args.closeAction(); args.closeAction();
$overlay.fadeOut(function() { $overlay.fadeOut(function() {
$overlay.remove(); $overlay.remove();
}); });
});
return this;
};
$(window).bind('resize scroll', function() {
$('.overlay').css('top', $(window).scrollTop());
}); });
return this;
};
$(window).bind('resize scroll', function() {
$('.overlay').css( 'top', $(window).scrollTop());
});
})(window.jQuery); })(window.jQuery);

View File

@ -16,220 +16,236 @@
// under the License. // under the License.
(function($, cloudStack) { (function($, cloudStack) {
var isFormValid = function($form) { var isFormValid = function($form) {
var key = $form.find('input[name=key]').val(); var key = $form.find('input[name=key]').val();
var value = $form.find('input[name=value]').val(); var value = $form.find('input[name=value]').val();
if (!key || !value) { if (!key || !value) {
cloudStack.dialog.notice({ message: 'Please specify a tag key and value' }); cloudStack.dialog.notice({
return false; message: 'Please specify a tag key and value'
}
if($form.find('div.field.key').find('label.error').css('display') == 'block' || $form.find('div.field.value').find('label.error').css('display') == 'block')
return false;
return true;
};
var elems = {
inputArea: function(args) {
var $form = $('<form>').addClass('tag-input');
var $keyField = $('<div>').addClass('field key');
var $keyLabel = $('<label>').attr('for', 'key').html(_l('label.key') + ':');
var $key = $('<input>').addClass('key disallowSpecialCharacters').attr('name', 'key');
var $valueField = $('<div>').addClass('field value');
var $valueLabel = $('<label>').attr('for', 'value').html(_l('label.value') + ':');
var $value = $('<input>').addClass('value disallowSpecialCharacters').attr('name', 'value');
var $submit = $('<input>').attr('type', 'submit').val('Add');
$keyField.append($keyLabel, $key);
$valueField.append($valueLabel, $value);
$form.append(
$keyField, $valueField,
$submit
);
$form.validate();
$form.submit(
args.onSubmit ?
function() {
if (!isFormValid($form)) return false;
args.onSubmit({
data: cloudStack.serializeForm($form),
response: {
success: function() {
// Restore editing of input
$key.attr('disabled', false);
$value.attr('disabled', false);
// Clear out old data
$key.val(''); $value.val('');
$key.focus();
},
error: function() {
// Restore editing of input
$key.attr('disabled', false);
$value.attr('disabled', false);
$key.focus();
}
}
}); });
// Prevent input during submission
$key.attr('disabled', 'disabled');
$value.attr('disabled', 'disabled');
return false; return false;
} :
function() { return false; }
);
return $form;
},
tagItem: function(title, onRemove, data) {
var $li = $('<li>');
var $label = $('<span>').addClass('label').html(_s(title));
var $remove = $('<span>').addClass('remove').html('X');
$remove.click(function() {
if (onRemove) onRemove($li, data);
});
$li.append($remove, $label);
return $li;
},
info: function(text) {
var $info = $('<div>').addClass('tag-info');
var $text = $('<span>').html(text);
$text.appendTo($info);
return $info;
}
};
$.widget('cloudStack.tagger', {
_init: function(args) {
var context = this.options.context;
var jsonObj = this.options.jsonObj;
var dataProvider = this.options.dataProvider;
var actions = this.options.actions;
var $container = this.element.addClass('tagger');
var $tagArea = $('<ul>').addClass('tags');
var $title = elems.info(_l('label.tags')).addClass('title');
var $loading = $('<div>').addClass('loading-overlay');
var onRemoveItem = function($item, data) {
$loading.appendTo($container);
actions.remove({
context: $.extend(true, {}, context, {
tagItems: [data]
}),
response: {
success: function(args) {
var notification = $.extend(true, {} , args.notification, {
interval: 500,
_custom: args._custom
});
cloudStack.ui.notifications.add(
notification,
// Success
function() {
$loading.remove();
$item.remove();
}, {},
// Error
function() {
$loading.remove();
}, {}
);
},
error: function(message) {
$loading.remove();
cloudStack.dialog.notice({ message: message });
}
}
});
};
var $inputArea = elems.inputArea({
onSubmit: function(args) {
var data = args.data;
var success = args.response.success;
var error = args.response.error;
var title = data.key + ' = ' + data.value;
$loading.appendTo($container);
actions.add({
data: data,
context: context,
response: {
success: function(args) {
var notification = $.extend(true, {} , args.notification, {
interval: 500,
_custom: args._custom
});
cloudStack.ui.notifications.add(
notification,
// Success
function() {
$loading.remove();
elems.tagItem(title, onRemoveItem, data).appendTo($tagArea);
success();
}, {},
// Error
function() {
$loading.remove();
error();
}, {}
);
},
error: function(message) {
$loading.remove();
error();
cloudStack.dialog.notice({ message: message });
}
}
});
} }
});
$container.append($title, $inputArea, $tagArea); if ($form.find('div.field.key').find('label.error').css('display') == 'block' || $form.find('div.field.value').find('label.error').css('display') == 'block')
return false;
// Get data return true;
$loading.appendTo($container); };
dataProvider({
context: context,
jsonObj: jsonObj,
response: {
success: function(args) {
var data = args.data;
$loading.remove(); var elems = {
$(data).map(function(index, item) { inputArea: function(args) {
var key = item.key; var $form = $('<form>').addClass('tag-input');
var value = item.value; var $keyField = $('<div>').addClass('field key');
var data = { key: key, value: value }; var $keyLabel = $('<label>').attr('for', 'key').html(_l('label.key') + ':');
var $key = $('<input>').addClass('key disallowSpecialCharacters').attr('name', 'key');
var $valueField = $('<div>').addClass('field value');
var $valueLabel = $('<label>').attr('for', 'value').html(_l('label.value') + ':');
var $value = $('<input>').addClass('value disallowSpecialCharacters').attr('name', 'value');
var $submit = $('<input>').attr('type', 'submit').val('Add');
elems.tagItem(key + ' = ' + value, onRemoveItem, data).appendTo($tagArea); $keyField.append($keyLabel, $key);
$valueField.append($valueLabel, $value);
$form.append(
$keyField, $valueField,
$submit
);
$form.validate();
$form.submit(
args.onSubmit ?
function() {
if (!isFormValid($form)) return false;
args.onSubmit({
data: cloudStack.serializeForm($form),
response: {
success: function() {
// Restore editing of input
$key.attr('disabled', false);
$value.attr('disabled', false);
// Clear out old data
$key.val('');
$value.val('');
$key.focus();
},
error: function() {
// Restore editing of input
$key.attr('disabled', false);
$value.attr('disabled', false);
$key.focus();
}
}
});
// Prevent input during submission
$key.attr('disabled', 'disabled');
$value.attr('disabled', 'disabled');
return false;
} :
function() {
return false;
}
);
return $form;
},
tagItem: function(title, onRemove, data) {
var $li = $('<li>');
var $label = $('<span>').addClass('label').html(_s(title));
var $remove = $('<span>').addClass('remove').html('X');
$remove.click(function() {
if (onRemove) onRemove($li, data);
}); });
},
error: function(message) { $li.append($remove, $label);
$loading.remove();
$container.find('ul').html(message); return $li;
} },
info: function(text) {
var $info = $('<div>').addClass('tag-info');
var $text = $('<span>').html(text);
$text.appendTo($info);
return $info;
} }
}); };
}
}); $.widget('cloudStack.tagger', {
_init: function(args) {
var context = this.options.context;
var jsonObj = this.options.jsonObj;
var dataProvider = this.options.dataProvider;
var actions = this.options.actions;
var $container = this.element.addClass('tagger');
var $tagArea = $('<ul>').addClass('tags');
var $title = elems.info(_l('label.tags')).addClass('title');
var $loading = $('<div>').addClass('loading-overlay');
var onRemoveItem = function($item, data) {
$loading.appendTo($container);
actions.remove({
context: $.extend(true, {}, context, {
tagItems: [data]
}),
response: {
success: function(args) {
var notification = $.extend(true, {}, args.notification, {
interval: 500,
_custom: args._custom
});
cloudStack.ui.notifications.add(
notification,
// Success
function() {
$loading.remove();
$item.remove();
}, {},
// Error
function() {
$loading.remove();
}, {}
);
},
error: function(message) {
$loading.remove();
cloudStack.dialog.notice({
message: message
});
}
}
});
};
var $inputArea = elems.inputArea({
onSubmit: function(args) {
var data = args.data;
var success = args.response.success;
var error = args.response.error;
var title = data.key + ' = ' + data.value;
$loading.appendTo($container);
actions.add({
data: data,
context: context,
response: {
success: function(args) {
var notification = $.extend(true, {}, args.notification, {
interval: 500,
_custom: args._custom
});
cloudStack.ui.notifications.add(
notification,
// Success
function() {
$loading.remove();
elems.tagItem(title, onRemoveItem, data).appendTo($tagArea);
success();
}, {},
// Error
function() {
$loading.remove();
error();
}, {}
);
},
error: function(message) {
$loading.remove();
error();
cloudStack.dialog.notice({
message: message
});
}
}
});
}
});
$container.append($title, $inputArea, $tagArea);
// Get data
$loading.appendTo($container);
dataProvider({
context: context,
jsonObj: jsonObj,
response: {
success: function(args) {
var data = args.data;
$loading.remove();
$(data).map(function(index, item) {
var key = item.key;
var value = item.value;
var data = {
key: key,
value: value
};
elems.tagItem(key + ' = ' + value, onRemoveItem, data).appendTo($tagArea);
});
},
error: function(message) {
$loading.remove();
$container.find('ul').html(message);
}
}
});
}
});
}(jQuery, cloudStack)); }(jQuery, cloudStack));

View File

@ -14,151 +14,157 @@
// KIND, either express or implied. See the License for the // KIND, either express or implied. See the License for the
// specific language governing permissions and limitations // specific language governing permissions and limitations
// under the License. // under the License.
(function($,cloudStack) { (function($, cloudStack) {
$.widget("cloudStack.toolTip", { $.widget("cloudStack.toolTip", {
_init: function(args) { _init: function(args) {
var context = this.options.context; var context = this.options.context;
var dataProvider = this.options.dataProvider; var dataProvider = this.options.dataProvider;
var actions = this.options.actions; var actions = this.options.actions;
var docID = this.options.docID; var docID = this.options.docID;
var text = cloudStack.docs[docID].desc; var text = cloudStack.docs[docID].desc;
var $tooltip = $('<div>').addClass('tooltip-box'); var $tooltip = $('<div>').addClass('tooltip-box');
var $text = $('<p>').html(text).appendTo($tooltip); var $text = $('<p>').html(text).appendTo($tooltip);
var $container = $('#cloudStack3-container'); var $container = $('#cloudStack3-container');
$tooltip.appendTo($container); $tooltip.appendTo($container);
if (this.options.mode == 'hover'){ if (this.options.mode == 'hover') {
$(this.element).hover(hoverHandler,outHandler); $(this.element).hover(hoverHandler, outHandler);
} else if (this.options.mode == 'focus'){ } else if (this.options.mode == 'focus') {
$(this.element).focus(hoverHandler); $(this.element).focus(hoverHandler);
$(this.element).blur(outHandler); $(this.element).blur(outHandler);
} else if (this.options.mode == 'manual'){} } else if (this.options.mode == 'manual') {}
$(this.element).data('$tooltip', $tooltip); $(this.element).data('$tooltip', $tooltip);
// Add arrow // Add arrow
$tooltip.append($('<div></div>').addClass('arrow')); $tooltip.append($('<div></div>').addClass('arrow'));
$tooltip.hide(); $tooltip.hide();
}, },
show: function(){ show: function() {
var o = this.options; var o = this.options;
if(o.mode=='manual'){ if (o.mode == 'manual') {
prepare(this.element,o); prepare(this.element, o);
} }
$(o.toolTip).show(); $(o.toolTip).show();
}, },
hide: function(){
var o = this.options;
$(o.toolTip).hide();
}
});
$.extend($.cloudStack.toolTip, {
defaults: {
toolTip: '',
onShow: function(sender){
//Flipping arrow and text
var $tooltip = $('.tooltip-box');
//Switch styles based on how close to viewport border
if($(window).width()-sender.target.offset().left <= $tooltip.width()) {
$('.tooltiptextleft',$tooltip).removeClass('tooltiptextleft').addClass('tooltiptextright');
$('.tooltiparrowleft',$tooltip).removeClass('tooltiparrowleft').addClass('tooltiparrowright');
hide: function() {
var o = this.options;
$(o.toolTip).hide();
} }
else{ });
$('.tooltiptextright',$tooltip).removeClass('tooltiptextright').addClass('tooltiptextleft');
$('.tooltiparrowright',$tooltip).removeClass('tooltiparrowright').addClass('tooltiparrowleft'); $.extend($.cloudStack.toolTip, {
defaults: {
toolTip: '',
onShow: function(sender) {
//Flipping arrow and text
var $tooltip = $('.tooltip-box');
//Switch styles based on how close to viewport border
if ($(window).width() - sender.target.offset().left <= $tooltip.width()) {
$('.tooltiptextleft', $tooltip).removeClass('tooltiptextleft').addClass('tooltiptextright');
$('.tooltiparrowleft', $tooltip).removeClass('tooltiparrowleft').addClass('tooltiparrowright');
} else {
$('.tooltiptextright', $tooltip).removeClass('tooltiptextright').addClass('tooltiptextleft');
$('.tooltiparrowright', $tooltip).removeClass('tooltiparrowright').addClass('tooltiparrowleft');
}
},
onHide: undefined,
mode: 'hover',
// provide a speed for the animation
speed: 1000,
// provide a period for the popup to keep showing
period: 2000,
// default the animation algorithm to the basic slide
animation: 'slide'
},
animations: {
slide: function(e, options) {
},
fade: function(e, options) {
}
}
});
function hoverHandler(event) {
//Fetch Options
var o = $.data(this, 'toolTip').options;
//Element who raised the event
var $this = $(this);
//Helper functon for Positioning and Calling Callback function
prepare($this, o);
//Call Show method of the tooltip Widget,
//Show method should play on any required animations
$.data(this, '$tooltip').show();
};
function outHandler(event) {
//Fetch Options
var o = $.data(this, 'toolTip').options;
//Get tooptip Element
var $tooltip = $(o.toolTip);
//If call back method defined, initiate the call
if ($.data(this, 'toolTip').options.onHide) {
$.data(this, 'toolTip').options.onHide.call(this, {
target: $(this)
});
} }
}, //Call Hide method of the tooltip Widget,
onHide: undefined, //Hide method should play on any required animations
mode: 'hover', $.data(this, '$tooltip').hide();
// provide a speed for the animation };
speed: 1000,
// provide a period for the popup to keep showing
period: 2000,
// default the animation algorithm to the basic slide
animation:'slide'
},
animations: {
slide: function(e, options) {
}, function prepare(jObj, options) {
fade: function(e, options) { var $tooltip = $(options.tooltip);
var element = options.attachTo ?
jObj.closest(options.attachTo) : jObj;
var offset = element.offset();
} var left = offset.left + element.width();
} var top = offset.top - 5;
});
function hoverHandler(event) if (options.onShow) {
{ options.onShow.call(this, {
//Fetch Options target: jObj
var o = $.data(this,'toolTip').options; });
}
//Element who raised the event if ($(window).width() - offset.left <= $tooltip.width()) {
var $this = $(this); left = offset.left - $tooltip.width();
} else {
left += 35;
}
$tooltip.css({
position: 'absolute',
top: top + 'px',
left: left + 'px'
});
//Helper functon for Positioning and Calling Callback function // Fix overlay
prepare($this,o); setTimeout(function() {
$('.tooltip-box').zIndex($(':ui-dialog').zIndex() + 10);
});
//Call Show method of the tooltip Widget, };
//Show method should play on any required animations
$.data(this,'$tooltip').show();
};
function outHandler(event)
{
//Fetch Options
var o = $.data(this,'toolTip').options;
//Get tooptip Element
var $tooltip = $(o.toolTip);
//If call back method defined, initiate the call
if($.data(this,'toolTip').options.onHide){
$.data(this,'toolTip').options.onHide.call(this, {target:$(this)});
}
//Call Hide method of the tooltip Widget,
//Hide method should play on any required animations
$.data(this,'$tooltip').hide();
};
function prepare(jObj, options)
{
var $tooltip = $(options.tooltip);
var element = options.attachTo ?
jObj.closest(options.attachTo) : jObj;
var offset = element.offset();
var left = offset.left + element.width();
var top = offset.top-5;
if(options.onShow){
options.onShow.call(this, {target:jObj});
}
if($(window).width()-offset.left <= $tooltip.width()) {
left = offset.left - $tooltip.width();
}
else{
left += 35;
}
$tooltip.css({position:'absolute', top:top+'px', left:left+'px'});
// Fix overlay
setTimeout(function() {
$('.tooltip-box').zIndex($(':ui-dialog').zIndex() + 10); });
};
})(jQuery,cloudStack); })(jQuery, cloudStack);

View File

@ -15,130 +15,136 @@
// specific language governing permissions and limitations // specific language governing permissions and limitations
// under the License. // under the License.
(function($, cloudStack, _s) { (function($, cloudStack, _s) {
/** /**
* Make <ul> of tree items * Make <ul> of tree items
*/ */
var makeTreeList = function(args) { var makeTreeList = function(args) {
var $treeList = $('<ul>'); var $treeList = $('<ul>');
args.dataProvider({ args.dataProvider({
context: $.extend(args.context, { context: $.extend(args.context, {
parentDomain: args.parent parentDomain: args.parent
}), }),
response: { response: {
success: function(successArgs) { success: function(successArgs) {
$(successArgs.data).each(function() { $(successArgs.data).each(function() {
$('<li>') $('<li>')
.data('tree-view-item-id', this.id) .data('tree-view-item-id', this.id)
.data('tree-view-item-obj', this) .data('tree-view-item-obj', this)
.append( .append(
$('<div>')
.addClass('expand')
)
.append(
$('<div>').addClass('name')
.html(_s(this.name))
)
.appendTo($treeList);
});
}
}
});
return $treeList;
};
/**
* Define an infinite 'tree' list
*/
$.fn.treeView = function(args) {
var $treeView = $('<div>')
.appendTo(this)
.addClass('view tree-view');
var $toolbar = $('<div>')
.addClass('toolbar')
.append(
$('<div>') $('<div>')
.addClass('expand') .addClass('text-search')
) .append(
.append( $('<div>')
$('<div>').addClass('name') .addClass('search-bar').attr('style', 'display:none') //no place to show search result in a tree, so hide it for now
.html(_s(this.name)) .append(
) $('<input>').attr('type', 'text')
.appendTo($treeList); )
}); )
} .append(
} $('<div>').addClass('button search').attr('style', 'display:none') //no place to show search result in a tree, so hide it for now
}); )
)
return $treeList; .prependTo($treeView);
}; var treeViewArgs = args.treeView;
var $browser = args.$browser;
/**
* Define an infinite 'tree' list
*/
$.fn.treeView = function(args) {
var $treeView = $('<div>')
.appendTo(this)
.addClass('view tree-view');
var $toolbar = $('<div>')
.addClass('toolbar')
.append(
$('<div>')
.addClass('text-search')
.append(
$('<div>')
.addClass('search-bar').attr('style', 'display:none') //no place to show search result in a tree, so hide it for now
.append(
$('<input>').attr('type', 'text')
)
)
.append(
$('<div>').addClass('button search').attr('style', 'display:none') //no place to show search result in a tree, so hide it for now
)
)
.prependTo($treeView);
var treeViewArgs = args.treeView;
var $browser = args.$browser;
makeTreeList({
parent: null,
dataProvider: treeViewArgs.dataProvider,
context: args.context
}).appendTo($treeView);
setTimeout(function() {
$treeView.find('li:first div.name').click();
}, 100);
this.click(function(event) {
var $target = $(event.target);
var $li = $target.closest('li');
if ($target.is('li div.expand') && $li.data('tree-view-item-obj')) {
if ($li.find('ul').size()) {
$li.find('ul').remove();
$li.removeClass('expanded');
return false;
}
makeTreeList({ makeTreeList({
parent: $li.data('tree-view-item-obj'), parent: null,
dataProvider: treeViewArgs.dataProvider dataProvider: treeViewArgs.dataProvider,
}).appendTo($li); context: args.context
$li.addClass('expanded'); }).appendTo($treeView);
return false; setTimeout(function() {
} $treeView.find('li:first div.name').click();
}, 100);
if ($target.is('li .name')) { this.click(function(event) {
$treeView.find('li .name').removeClass('selected'); var $target = $(event.target);
$target.addClass('selected'); var $li = $target.closest('li');
$browser.cloudBrowser('addPanel', {
title: $target.html(), if ($target.is('li div.expand') && $li.data('tree-view-item-obj')) {
data: '', if ($li.find('ul').size()) {
parent: $treeView.closest('div.panel'), $li.find('ul').remove();
complete: function($panel) { $li.removeClass('expanded');
$panel.detailView($.extend(treeViewArgs.detailView, {
id: $li.data('tree-view-item-id'), return false;
$browser: $browser, }
context: { domains: [ $li.data('tree-view-item-obj') ] }
})); makeTreeList({
} parent: $li.data('tree-view-item-obj'),
dataProvider: treeViewArgs.dataProvider
}).appendTo($li);
$li.addClass('expanded');
return false;
}
if ($target.is('li .name')) {
$treeView.find('li .name').removeClass('selected');
$target.addClass('selected');
$browser.cloudBrowser('addPanel', {
title: $target.html(),
data: '',
parent: $treeView.closest('div.panel'),
complete: function($panel) {
$panel.detailView($.extend(treeViewArgs.detailView, {
id: $li.data('tree-view-item-id'),
$browser: $browser,
context: {
domains: [$li.data('tree-view-item-obj')]
}
}));
}
});
}
return true;
}); });
}
return true; // Action events
}); $(window).bind('cloudstack.view-item-action', function(event, data) {
var actionName = data.actionName;
var $li = $treeView.find('li').filter(function() {
return $(this).data('tree-view-item-id') == data.id;
});
// Action events if (actionName == 'destroy') {
$(window).bind('cloudstack.view-item-action', function(event, data) { $li.animate({
var actionName = data.actionName; opacity: 0.5
var $li = $treeView.find('li').filter(function() { });
return $(this).data('tree-view-item-id') == data.id; $li.bind('click', function() {
}); return false;
});
}
});
if (actionName == 'destroy') { return this;
$li.animate({ opacity: 0.5 }); };
$li.bind('click', function() { return false; });
}
});
return this;
};
})(jQuery, cloudStack, cloudStack.sanitize); })(jQuery, cloudStack, cloudStack.sanitize);

View File

@ -15,182 +15,185 @@
// specific language governing permissions and limitations // specific language governing permissions and limitations
// under the License. // under the License.
(function($, cloudStack) { (function($, cloudStack) {
cloudStack.sections.vmsnapshots = { cloudStack.sections.vmsnapshots = {
title: 'label.vmsnapshot', title: 'label.vmsnapshot',
id: 'vmsnapshots', id: 'vmsnapshots',
listView: { listView: {
id: 'vmsnapshots', id: 'vmsnapshots',
isMaximized: true, isMaximized: true,
fields: {
displayname: {
label: 'label.name'
},
state: {
label: 'label.state',
indicator: {
'Ready': 'on',
'Error': 'off'
}
},
type:{
label: 'label.vmsnapshot.type'
},
current:{
label: 'label.vmsnapshot.current',
converter: cloudStack.converters.toBooleanText
},
parentName:{
label: 'label.vmsnapshot.parentname'
},
created: {
label: 'label.date',
converter: cloudStack.converters.toLocalDate
}
},
dataProvider: function(args) {
var apiCmd = "listVMSnapshot&listAll=true";
if (args.context != null) {
if ("instances" in args.context) {
apiCmd += "&virtualmachineid=" + args.context.instances[0].id;
}
}
$.ajax({
url: createURL(apiCmd),
dataType: "json",
async: true,
success: function(json) {
var jsonObj;
jsonObj = json.listvmsnapshotresponse.vmSnapshot;
args.response.success({
data: jsonObj
});
}
});
},
//dataProvider end
detailView: {
tabs: {
details: {
title: 'label.details',
fields: { fields: {
id: { displayname: {
label: 'label.id' label: 'label.name'
}, },
name: { state: {
label: 'label.name' label: 'label.state',
}, indicator: {
displayname: { 'Ready': 'on',
label: 'label.display.name', 'Error': 'off'
}, }
type: { },
label: 'label.vmsnapshot.type', type: {
}, label: 'label.vmsnapshot.type'
description: { },
label: 'label.description', current: {
}, label: 'label.vmsnapshot.current',
state: { converter: cloudStack.converters.toBooleanText
label: 'label.state', },
indicator: { parentName: {
'Ready': 'on', label: 'label.vmsnapshot.parentname'
'Error': 'off' },
created: {
label: 'label.date',
converter: cloudStack.converters.toLocalDate
} }
},
current: {
label: 'label.vmsnapshot.current',
converter: cloudStack.converters.toBooleanText
},
parentName: {
label: 'label.vmsnapshot.parentname'
},
created: {
label: 'label.date',
converter: cloudStack.converters.toLocalDate
},
}, },
dataProvider: function(args) { dataProvider: function(args) {
$.ajax({ var apiCmd = "listVMSnapshot&listAll=true";
url: createURL("listVMSnapshot&listAll=true&id=" + args.context.vmsnapshots[0].id), if (args.context != null) {
dataType: "json", if ("instances" in args.context) {
async: true, apiCmd += "&virtualmachineid=" + args.context.instances[0].id;
success: function(json) {
var jsonObj;
jsonObj = json.listvmsnapshotresponse.vmSnapshot[0];
args.response.success({
//actionFilter: vmActionfilter,
data: jsonObj
});
}
});
},
tags: cloudStack.api.tags({ resourceType: 'VMSnapshot', contextId: 'vmsnapshots' })
}
},
actions: {
//delete a snapshot
remove: {
label: 'label.action.vmsnapshot.delete',
messages: {
confirm: function(args) {
return 'message.action.vmsnapshot.delete';
},
notification: function(args) {
return 'label.action.vmsnapshot.delete';
}
},
action: function(args) {
$.ajax({
url: createURL("deleteVMSnapshot&vmsnapshotid=" + args.context.vmsnapshots[0].id),
dataType: "json",
async: true,
success: function(json) {
var jid = json.deletevmsnapshotresponse.jobid;
args.response.success(
{_custom:
{jobId: jid}
} }
);
} }
}); $.ajax({
}, url: createURL(apiCmd),
notification: { dataType: "json",
poll: pollAsyncJobResult async: true,
} success: function(json) {
}, var jsonObj;
restart: { jsonObj = json.listvmsnapshotresponse.vmSnapshot;
label: 'label.action.vmsnapshot.revert', args.response.success({
messages: { data: jsonObj
confirm: function(args) { });
return 'label.action.vmsnapshot.revert';
},
notification: function(args) {
return 'message.action.vmsnapshot.revert';
}
},
action: function(args) {
$.ajax({
url: createURL("revertToVMSnapshot&vmsnapshotid=" + args.context.vmsnapshots[0].id),
dataType: "json",
async: true,
success: function(json) {
var jid = json.reverttovmsnapshotresponse.jobid;
args.response.success({
_custom: {
jobId: jid
} }
}); });
} },
}); //dataProvider end
detailView: {
tabs: {
details: {
title: 'label.details',
fields: {
id: {
label: 'label.id'
},
name: {
label: 'label.name'
},
displayname: {
label: 'label.display.name',
},
type: {
label: 'label.vmsnapshot.type',
},
description: {
label: 'label.description',
},
state: {
label: 'label.state',
indicator: {
'Ready': 'on',
'Error': 'off'
}
},
current: {
label: 'label.vmsnapshot.current',
converter: cloudStack.converters.toBooleanText
},
parentName: {
label: 'label.vmsnapshot.parentname'
},
created: {
label: 'label.date',
converter: cloudStack.converters.toLocalDate
},
}, },
notification: { dataProvider: function(args) {
poll: pollAsyncJobResult $.ajax({
url: createURL("listVMSnapshot&listAll=true&id=" + args.context.vmsnapshots[0].id),
dataType: "json",
async: true,
success: function(json) {
var jsonObj;
jsonObj = json.listvmsnapshotresponse.vmSnapshot[0];
args.response.success({
//actionFilter: vmActionfilter,
data: jsonObj
});
}
});
},
tags: cloudStack.api.tags({
resourceType: 'VMSnapshot',
contextId: 'vmsnapshots'
})
}
},
actions: {
//delete a snapshot
remove: {
label: 'label.action.vmsnapshot.delete',
messages: {
confirm: function(args) {
return 'message.action.vmsnapshot.delete';
},
notification: function(args) {
return 'label.action.vmsnapshot.delete';
}
},
action: function(args) {
$.ajax({
url: createURL("deleteVMSnapshot&vmsnapshotid=" + args.context.vmsnapshots[0].id),
dataType: "json",
async: true,
success: function(json) {
var jid = json.deletevmsnapshotresponse.jobid;
args.response.success({
_custom: {
jobId: jid
}
});
}
});
},
notification: {
poll: pollAsyncJobResult
}
},
restart: {
label: 'label.action.vmsnapshot.revert',
messages: {
confirm: function(args) {
return 'label.action.vmsnapshot.revert';
},
notification: function(args) {
return 'message.action.vmsnapshot.revert';
}
},
action: function(args) {
$.ajax({
url: createURL("revertToVMSnapshot&vmsnapshotid=" + args.context.vmsnapshots[0].id),
dataType: "json",
async: true,
success: function(json) {
var jid = json.reverttovmsnapshotresponse.jobid;
args.response.success({
_custom: {
jobId: jid
}
});
}
});
},
notification: {
poll: pollAsyncJobResult
}
}
}
} }
} //detailview end
} }
}
//detailview end
} }
}
})(jQuery, cloudStack); })(jQuery, cloudStack);

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff