diff --git a/client/WEB-INF/classes/resources/messages.properties b/client/WEB-INF/classes/resources/messages.properties index e700d5d1902..c78df29cf31 100644 --- a/client/WEB-INF/classes/resources/messages.properties +++ b/client/WEB-INF/classes/resources/messages.properties @@ -1271,6 +1271,7 @@ label.zone.type=Zone Type label.zone.wide=Zone-Wide label.zone=Zone label.zones=Zones +label.multiplezones=Multiple Zones label.zoneWizard.trafficType.guest=Guest\: Traffic between end-user virtual machines label.zoneWizard.trafficType.management=Management\: Traffic between CloudStack\\\\'s internal resources, including any components that communicate with the Management Server, such as hosts and CloudStack system VMs label.zoneWizard.trafficType.public=Public\: Traffic between the internet and virtual machines in the cloud. diff --git a/ui/css/cloudstack3.css b/ui/css/cloudstack3.css old mode 100644 new mode 100755 index cb9fa3521f2..d7ed1afb098 --- a/ui/css/cloudstack3.css +++ b/ui/css/cloudstack3.css @@ -1298,6 +1298,11 @@ div.panel div.list-view div.data-table table { border-left: 1px solid #CACACA; } +.detail-view div#details-tab-zones div.list-view div.data-table table td div.disabled { + display: none; +} + + div.panel div.list-view div.fixed-header { position: absolute; top: 29px; @@ -1313,7 +1318,7 @@ div.panel div.list-view div.fixed-header { .detail-view div.list-view div.fixed-header { width: 703px !important; top: 49px !important; - left: 32px !important; + left: 25px !important; background: #FFFFFF; } diff --git a/ui/dictionary.jsp b/ui/dictionary.jsp index 2172d19f603..b5fda4097bf 100644 --- a/ui/dictionary.jsp +++ b/ui/dictionary.jsp @@ -1237,6 +1237,8 @@ dictionary = { 'label.yes': '', 'label.zone.details': '', 'label.zone': '', +'label.zones': '', +'label.multiplezones': '', 'label.zone.id': '', 'label.zone.name': '', 'label.zone.step.1.title': '', diff --git a/ui/scripts/templates.js b/ui/scripts/templates.js index 67cc2fb99e7..814e76baed2 100644 --- a/ui/scripts/templates.js +++ b/ui/scripts/templates.js @@ -53,7 +53,7 @@ name: { label: 'label.name' }, - zonename: { + zones: { label: 'label.zone' }, hypervisor: { @@ -601,9 +601,31 @@ data: data, success: function(json) { var items = json.listtemplatesresponse.template; + var itemsView = []; + + $(items).each(function(index, item) { + var existing = $.grep(itemsView, function(it){ + return it != null && it.id !=null && it.id == item.id; + }); + + if (existing.length == 0) { + itemsView.push({ + id: item.id, + name: item.name, + description: item.description, + zones: item.zonename, + zoneids: [item.zoneid] + }); + } + else { + existing[0].zones = 'label.multiplezones'; + existing[0].zoneids.push(item.zoneid); + } + }); + args.response.success({ actionFilter: templateActionfilter, - data: items + data: itemsView }); } }); @@ -749,91 +771,6 @@ } }, - copyTemplate: { - label: 'label.action.copy.template', - messages: { - confirm: function(args) { - return 'message.copy.template.confirm'; - }, - success: function(args) { - return 'message.template.copying'; - }, - notification: function(args) { - return 'label.action.copy.template'; - } - }, - createForm: { - title: 'label.action.copy.template', - desc: '', - fields: { - destinationZoneId: { - label: 'label.destination.zone', - docID: 'helpCopyTemplateDestination', - validation: { - required: true - }, - select: function(args) { - $.ajax({ - url: createURL("listZones&available=true"), - dataType: "json", - async: true, - success: function(json) { - var zoneObjs = []; - var items = json.listzonesresponse.zone; - if (items != null) { - for (var i = 0; i < items.length; i++) { - if (items[i].id != args.context.templates[0].zoneid) { //destination zone must be different from source zone - zoneObjs.push({ - id: items[i].id, - description: items[i].name - }); - } - } - } - args.response.success({ - data: zoneObjs - }); - } - }); - } - } - } - }, - action: function(args) { - var data = { - id: args.context.templates[0].id, - destzoneid: args.data.destinationZoneId - }; - if (args.context.templates[0].zoneid != undefined) { - $.extend(data, { - sourcezoneid: args.context.templates[0].zoneid - }); - } - - $.ajax({ - url: createURL('copyTemplate'), - data: data, - success: function(json) { - var jid = json.copytemplateresponse.jobid; - args.response.success({ - _custom: { - jobId: jid, - getUpdatedItem: function(json) { - return {}; //nothing in this template needs to be updated - }, - getActionFilter: function() { - return templateActionfilter; - } - } - }); - } - }); - }, - notification: { - poll: pollAsyncJobResult - } - }, - downloadTemplate: { label: 'label.action.download.template', messages: { @@ -880,40 +817,6 @@ } }, - remove: { - label: 'label.action.delete.template', - messages: { - confirm: function(args) { - return 'message.action.delete.template'; - }, - notification: function(args) { - return 'label.action.delete.template'; - } - }, - action: function(args) { - var array1 = []; - if (args.context.templates[0].zoneid != null) - array1.push("&zoneid=" + args.context.templates[0].zoneid); - - $.ajax({ - url: createURL("deleteTemplate&id=" + args.context.templates[0].id + array1.join("")), - dataType: "json", - async: true, - success: function(json) { - var jid = json.deletetemplateresponse.jobid; - args.response.success({ - _custom: { - jobId: jid - } - }); - } - }); - }, - notification: { - poll: pollAsyncJobResult - } - } - }, tabs: { details: { @@ -943,14 +846,6 @@ } } }, { - isready: { - label: 'state.ready', - converter: cloudStack.converters.toBooleanText - }, - status: { - label: 'label.status' - }, - hypervisor: { label: 'label.hypervisor' }, @@ -1050,9 +945,6 @@ } }, - zonename: { - label: 'label.zone.name' - }, crossZones: { label: 'label.cross.zones', converter: cloudStack.converters.toBooleanText @@ -1082,9 +974,6 @@ id: { label: 'label.id' - }, - zoneid: { - label: 'label.zone.id' } }], @@ -1120,6 +1009,160 @@ } }); } + }, + + zones: { + title: 'label.zones', + listView: { + id: 'zones', + fields: { + zonename: { + label: 'label.name' + }, + status: { + label: 'label.status' + }, + isready: { + label: 'state.ready', + converter: cloudStack.converters.toBooleanText + } + }, + hideSearchBar: true, + actions: { + remove: { + label: 'label.action.delete.template', + messages: { + confirm: function(args) { + return 'message.action.delete.template'; + }, + notification: function(args) { + return 'label.action.delete.template'; + } + }, + action: function(args) { + $.ajax({ + url: createURL("deleteTemplate&id=" + args.context.templates[0].id + "&zoneid=" + args.context.zones[0].zoneid), + dataType: "json", + async: true, + success: function(json) { + var jid = json.deletetemplateresponse.jobid; + args.response.success({ + _custom: { + jobId: jid + } + }); + } + }); + }, + notification: { + poll: pollAsyncJobResult + } + }, + copyTemplate: { + label: 'label.action.copy.template', + messages: { + confirm: function(args) { + return 'message.copy.template.confirm'; + }, + success: function(args) { + return 'message.template.copying'; + }, + notification: function(args) { + return 'label.action.copy.template'; + } + }, + createForm: { + title: 'label.action.copy.template', + desc: '', + fields: { + destinationZoneId: { + label: 'label.destination.zone', + docID: 'helpCopyTemplateDestination', + validation: { + required: true + }, + select: function(args) { + $.ajax({ + url: createURL("listZones&available=true"), + dataType: "json", + async: true, + success: function(json) { + var zoneObjs = []; + var items = json.listzonesresponse.zone; + if (items != null) { + for (var i = 0; i < items.length; i++) { + if ($.inArray(items[i].id, args.context.templates[0].zoneids) == -1) { //destination zones should not contain zones where the template is already available + zoneObjs.push({ + id: items[i].id, + description: items[i].name + }); + } + } + } + args.response.success({ + data: zoneObjs + }); + } + }); + } + } + } + }, + action: function(args) { + var data = { + id: args.context.templates[0].id, + destzoneid: args.data.destinationZoneId + }; + $.extend(data, { + sourcezoneid: args.context.templates[0].zoneid + }); + + $.ajax({ + url: createURL('copyTemplate'), + data: data, + success: function(json) { + var jid = json.copytemplateresponse.jobid; + args.response.success({ + _custom: { + jobId: jid, + getUpdatedItem: function(json) { + return {}; //nothing in this template needs to be updated + }, + getActionFilter: function() { + return templateActionfilter; + } + } + }); + } + }); + }, + notification: { + poll: pollAsyncJobResult + } + } + }, + + dataProvider: function(args) { + var jsonObj = args.context.templates[0]; + var apiCmd = "listTemplates&templatefilter=self&id=" + jsonObj.id; + + $.ajax({ + url: createURL(apiCmd), + dataType: "json", + success: function(json) { + var templates = json.listtemplatesresponse.template; + var zones = []; + zones = templates; + + args.response.success({ + actionFilter: templateActionfilter, + data: zones + }); + } + }); + } + + } } } } @@ -1154,7 +1197,7 @@ name: { label: 'label.name' }, - zonename: { + zones: { label: 'label.zone' } }, @@ -1434,9 +1477,30 @@ data: data, success: function(json) { var items = json.listisosresponse.iso; + + var itemsView = []; + $(items).each(function(index, item) { + var existing = $.grep(itemsView, function(it){ + return it != null && it.id !=null && it.id == item.id; + }); + if (existing.length == 0) { + itemsView.push({ + id: item.id, + name: item.name, + description: item.description, + zones: item.zonename, + zoneids: [item.zoneid] + }); + } + else { + existing[0].zones = 'Multiple Zones'; + existing[0].zoneids.push(item.zoneid); + } + } +); args.response.success({ actionFilter: isoActionfilter, - data: items + data: itemsView }); } }); @@ -1531,85 +1595,6 @@ }); } }, - - copyISO: { - label: 'label.action.copy.ISO', - messages: { - notification: function(args) { - return 'Copying ISO'; - } - }, - createForm: { - title: 'label.action.copy.ISO', - desc: 'label.action.copy.ISO', - fields: { - destinationZoneId: { - label: 'label.destination.zone', - validation: { - required: true - }, - select: function(args) { - $.ajax({ - url: createURL("listZones&available=true"), - dataType: "json", - async: true, - success: function(json) { - var zoneObjs = []; - var items = json.listzonesresponse.zone; - if (items != null) { - for (var i = 0; i < items.length; i++) { - if (items[i].id != args.context.isos[0].zoneid) { //destination zone must be different from source zone - zoneObjs.push({ - id: items[i].id, - description: items[i].name - }); - } - } - } - args.response.success({ - data: zoneObjs - }); - } - }); - } - } - } - }, - action: function(args) { - var data = { - id: args.context.isos[0].id, - destzoneid: args.data.destinationZoneId - }; - if (args.context.isos[0].zoneid != undefined) { - $.extend(data, { - sourcezoneid: args.context.isos[0].zoneid - }); - } - - $.ajax({ - url: createURL('copyIso'), - data: data, - success: function(json) { - var jid = json.copytemplateresponse.jobid; - args.response.success({ - _custom: { - jobId: jid, - getUpdatedItem: function(json) { - return {}; //nothing in this ISO needs to be updated - }, - getActionFilter: function() { - return isoActionfilter; - } - } - }); - } - }); - }, - notification: { - poll: pollAsyncJobResult - } - }, - downloadISO: { label: 'label.action.download.ISO', messages: { @@ -1654,42 +1639,7 @@ notification: { poll: pollAsyncJobResult } - }, - - remove: { - label: 'label.action.delete.ISO', - messages: { - confirm: function(args) { - return 'message.action.delete.ISO'; - }, - notification: function(args) { - return 'label.action.delete.ISO'; - } - }, - action: function(args) { - var array1 = []; - if (args.context.isos[0].zoneid != null) - array1.push("&zoneid=" + args.context.isos[0].zoneid); - - $.ajax({ - url: createURL("deleteIso&id=" + args.context.isos[0].id + array1.join("")), - dataType: "json", - async: true, - success: function(json) { - var jid = json.deleteisosresponse.jobid; - args.response.success({ - _custom: { - jobId: jid - } - }); - } - }); - }, - notification: { - poll: pollAsyncJobResult - } } - }, tabs: { @@ -1708,12 +1658,6 @@ id: { label: 'ID' }, - zonename: { - label: 'label.zone.name' - }, - zoneid: { - label: 'label.zone.id' - }, displaytext: { label: 'label.description', isEditable: true, @@ -1721,13 +1665,6 @@ required: true } }, - isready: { - label: 'state.Ready', - converter: cloudStack.converters.toBooleanText - }, - status: { - label: 'label.status' - }, size: { label: 'label.size', converter: function(args) { @@ -1834,6 +1771,158 @@ }); } + }, + zones: { + title: 'label.zones', + listView: { + id: 'zones', + fields: { + zonename: { + label: 'label.name' + }, + status: { + label: 'label.status' + }, + isready: { + label: 'state.ready', + converter: cloudStack.converters.toBooleanText + } + }, + hideSearchBar: true, + actions: { + copyISO: { + label: 'label.action.copy.ISO', + messages: { + notification: function(args) { + return 'Copying ISO'; + } + }, + createForm: { + title: 'label.action.copy.ISO', + desc: 'label.action.copy.ISO', + fields: { + destinationZoneId: { + label: 'label.destination.zone', + validation: { + required: true + }, + select: function(args) { + $.ajax({ + url: createURL("listZones&available=true"), + dataType: "json", + async: true, + success: function(json) { + var zoneObjs = []; + var items = json.listzonesresponse.zone; + if (items != null) { + for (var i = 0; i < items.length; i++) { + if ($.inArray(items[i].id, args.context.isos[0].zoneids) == -1) { //destination zones should not contain zones where the ISO is already available + zoneObjs.push({ + id: items[i].id, + description: items[i].name + }); + } + } + } + args.response.success({ + data: zoneObjs + }); + } + }); + } + } + } + }, + action: function(args) { + var data = { + id: args.context.isos[0].id, + destzoneid: args.data.destinationZoneId + }; + if (args.context.isos[0].zoneid != undefined) { + $.extend(data, { + sourcezoneid: args.context.isos[0].zoneid + }); + } + + $.ajax({ + url: createURL('copyIso'), + data: data, + success: function(json) { + var jid = json.copytemplateresponse.jobid; + args.response.success({ + _custom: { + jobId: jid, + getUpdatedItem: function(json) { + return {}; //nothing in this ISO needs to be updated + }, + getActionFilter: function() { + return isoActionfilter; + } + } + }); + } + }); + }, + notification: { + poll: pollAsyncJobResult + } + }, + + remove: { + label: 'label.action.delete.ISO', + messages: { + confirm: function(args) { + return 'message.action.delete.ISO'; + }, + notification: function(args) { + return 'label.action.delete.ISO'; + } + }, + action: function(args) { + var array1 = []; + if (args.context.isos[0].zoneid != null) + array1.push("&zoneid=" + args.context.isos[0].zoneid); + + $.ajax({ + url: createURL("deleteIso&id=" + args.context.isos[0].id + "&zoneid=" + args.context.zones[0].zoneid), + dataType: "json", + async: true, + success: function(json) { + var jid = json.deleteisosresponse.jobid; + args.response.success({ + _custom: { + jobId: jid + } + }); + } + }); + }, + notification: { + poll: pollAsyncJobResult + } + } + }, + + dataProvider: function(args) { + var jsonObj = args.context.isos[0]; + var apiCmd = "listIsos&isofilter=self&id=" + jsonObj.id; + + $.ajax({ + url: createURL(apiCmd), + dataType: "json", + success: function(json) { + var isos = json.listisosresponse.iso; + var zones = []; + zones = isos; + + args.response.success({ + actionFilter: isoActionfilter, + data: zones + }); + } + }); + } + } } } }