mirror of https://github.com/apache/cloudstack.git
Merge pull request #1767 from nvazquez/userVmAndTemplatesDetails
CLOUDSTACK-9457: Allow retrieval and modification of VM and template details via API and UIJIRA TICKET: https://issues.apache.org/jira/browse/CLOUDSTACK-9457 ### Goal This PR proposes list/add/update/delete user vm and vm template details via API and UI. ### VM UI Screenshots Setting tab is added on Instances page. Actions allowed are: Add/Edit/Remove  Settings tab is only shown if instance is Stopped:   ### Templates UI Screenshots Setting tab is added on Templates page. Actions allowed are: Add/Edit/Remove:  * pr/1767: CLOUDSTACK-9457: Allow retrieval and modification of VM and template details via API and UI Signed-off-by: Rajani Karuturi <rajani.karuturi@accelerite.com>
This commit is contained in:
commit
202b92f243
|
|
@ -649,6 +649,7 @@ public class ApiConstants {
|
|||
public static final String OVM3_POOL = "ovm3pool";
|
||||
public static final String OVM3_CLUSTER = "ovm3cluster";
|
||||
public static final String OVM3_VIP = "ovm3vip";
|
||||
public static final String CLEAN_UP_DETAILS = "cleanupdetails";
|
||||
|
||||
public static final String ADMIN = "admin";
|
||||
|
||||
|
|
|
|||
|
|
@ -17,7 +17,6 @@
|
|||
package org.apache.cloudstack.api;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import org.apache.cloudstack.api.command.user.iso.UpdateIsoCmd;
|
||||
import org.apache.cloudstack.api.response.GuestOSResponse;
|
||||
import org.apache.cloudstack.api.response.TemplateResponse;
|
||||
|
|
@ -73,6 +72,11 @@ public abstract class BaseUpdateTemplateOrIsoCmd extends BaseCmd {
|
|||
@Parameter(name = ApiConstants.DETAILS, type = CommandType.MAP, description = "Details in key/value pairs using format details[i].keyname=keyvalue. Example: details[0].hypervisortoolsversion=xenserver61")
|
||||
protected Map details;
|
||||
|
||||
@Parameter(name = ApiConstants.CLEAN_UP_DETAILS,
|
||||
type = CommandType.BOOLEAN,
|
||||
description = "optional boolean field, which indicates if details should be cleaned up or not (if set to true, details removed for this resource, details field ignored; if false or not set, no action)")
|
||||
private Boolean cleanupDetails;
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
/////////////////// Accessors ///////////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
|
@ -129,4 +133,8 @@ public abstract class BaseUpdateTemplateOrIsoCmd extends BaseCmd {
|
|||
Collection paramsCollection = this.details.values();
|
||||
return (Map) (paramsCollection.toArray())[0];
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isCleanupDetails(){
|
||||
return cleanupDetails == null ? false : cleanupDetails.booleanValue();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -116,6 +116,11 @@ public class UpdateVMCmd extends BaseCustomIdCmd implements SecurityGroupAction
|
|||
)
|
||||
private List<String> securityGroupNameList;
|
||||
|
||||
@Parameter(name = ApiConstants.CLEAN_UP_DETAILS,
|
||||
type = CommandType.BOOLEAN,
|
||||
description = "optional boolean field, which indicates if details should be cleaned up or not (if set to true, details removed for this resource, details field ignored; if false or not set, no action)")
|
||||
private Boolean cleanupDetails;
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
/////////////////// Accessors ///////////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
|
@ -173,6 +178,10 @@ public class UpdateVMCmd extends BaseCustomIdCmd implements SecurityGroupAction
|
|||
return securityGroupNameList;
|
||||
}
|
||||
|
||||
public boolean isCleanupDetails(){
|
||||
return cleanupDetails == null ? false : cleanupDetails.booleanValue();
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
/////////////// API Implementation///////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -79,4 +79,20 @@ public class VMTemplateDetailVO implements ResourceDetail {
|
|||
public boolean isDisplay() {
|
||||
return display;
|
||||
}
|
||||
|
||||
public void setId(long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public void setResourceId(long resourceId) {
|
||||
this.resourceId = resourceId;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public void setValue(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -80,4 +80,11 @@ public class UserVmDetailVO implements ResourceDetail {
|
|||
return display;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public void setValue(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,7 +51,6 @@ import com.cloud.utils.db.SearchBuilder;
|
|||
import com.cloud.utils.db.SearchCriteria;
|
||||
import com.cloud.vm.UserVmDetailVO;
|
||||
import com.cloud.vm.VirtualMachine.State;
|
||||
import com.cloud.vm.VmDetailConstants;
|
||||
import com.cloud.vm.VmStats;
|
||||
import com.cloud.vm.dao.NicSecondaryIpVO;
|
||||
import com.cloud.vm.dao.UserVmDetailsDao;
|
||||
|
|
@ -292,11 +291,13 @@ public class UserVmJoinDaoImpl extends GenericDaoBaseWithTagInformation<UserVmJo
|
|||
}
|
||||
|
||||
// set resource details map
|
||||
// only hypervisortoolsversion can be returned to the end user
|
||||
UserVmDetailVO hypervisorToolsVersion = _userVmDetailsDao.findDetail(userVm.getId(), VmDetailConstants.HYPERVISOR_TOOLS_VERSION);
|
||||
if (hypervisorToolsVersion != null) {
|
||||
// Allow passing details to end user
|
||||
List<UserVmDetailVO> vmDetails = _userVmDetailsDao.listDetails(userVm.getId());
|
||||
if (vmDetails != null) {
|
||||
Map<String, String> resourceDetails = new HashMap<String, String>();
|
||||
resourceDetails.put(hypervisorToolsVersion.getName(), hypervisorToolsVersion.getValue());
|
||||
for (UserVmDetailVO userVmDetailVO : vmDetails) {
|
||||
resourceDetails.put(userVmDetailVO.getName(), userVmDetailVO.getValue());
|
||||
}
|
||||
userVmResponse.setDetails(resourceDetails);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -161,6 +161,7 @@ import com.cloud.storage.dao.LaunchPermissionDao;
|
|||
import com.cloud.storage.dao.SnapshotDao;
|
||||
import com.cloud.storage.dao.StoragePoolHostDao;
|
||||
import com.cloud.storage.dao.VMTemplateDao;
|
||||
import com.cloud.storage.dao.VMTemplateDetailsDao;
|
||||
import com.cloud.storage.dao.VMTemplatePoolDao;
|
||||
import com.cloud.storage.dao.VMTemplateZoneDao;
|
||||
import com.cloud.storage.dao.VolumeDao;
|
||||
|
|
@ -269,6 +270,8 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
|
|||
private ImageStoreDao _imgStoreDao;
|
||||
@Inject
|
||||
MessageBus _messageBus;
|
||||
@Inject
|
||||
private VMTemplateDetailsDao _tmpltDetailsDao;
|
||||
|
||||
private boolean _disableExtraction = false;
|
||||
private List<TemplateAdapter> _adapters;
|
||||
|
|
@ -1880,6 +1883,7 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
|
|||
Integer sortKey = cmd.getSortKey();
|
||||
Map details = cmd.getDetails();
|
||||
Account account = CallContext.current().getCallingAccount();
|
||||
boolean cleanupDetails = cmd.isCleanupDetails();
|
||||
|
||||
// verify that template exists
|
||||
VMTemplateVO template = _tmpltDao.findById(id);
|
||||
|
|
@ -1911,7 +1915,8 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
|
|||
sortKey == null &&
|
||||
isDynamicallyScalable == null &&
|
||||
isRoutingTemplate == null &&
|
||||
details == null);
|
||||
(! cleanupDetails && details == null) //update details in every case except this one
|
||||
);
|
||||
if (!updateNeeded) {
|
||||
return template;
|
||||
}
|
||||
|
|
@ -1989,7 +1994,11 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
|
|||
}
|
||||
}
|
||||
|
||||
if (details != null && !details.isEmpty()) {
|
||||
if (cleanupDetails) {
|
||||
template.setDetails(null);
|
||||
_tmpltDetailsDao.removeDetails(id);
|
||||
}
|
||||
else if (details != null && !details.isEmpty()) {
|
||||
template.setDetails(details);
|
||||
_tmpltDao.saveDetails(template);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2309,6 +2309,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
Map<String,String> details = cmd.getDetails();
|
||||
Account caller = CallContext.current().getCallingAccount();
|
||||
List<Long> securityGroupIdList = getSecurityGroupIdList(cmd);
|
||||
boolean cleanupDetails = cmd.isCleanupDetails();
|
||||
|
||||
// Input validation and permission checks
|
||||
UserVmVO vmInstance = _vmDao.findById(id);
|
||||
|
|
@ -2347,14 +2348,11 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
|
||||
}
|
||||
|
||||
if (details != null && !details.isEmpty()) {
|
||||
_vmDao.loadDetails(vmInstance);
|
||||
|
||||
for(Map.Entry<String,String> entry : details.entrySet()) {
|
||||
if(entry instanceof Map.Entry) {
|
||||
vmInstance.setDetail(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
if (cleanupDetails){
|
||||
_vmDetailsDao.removeDetails(id);
|
||||
}
|
||||
else if (details != null && !details.isEmpty()) {
|
||||
vmInstance.setDetails(details);
|
||||
_vmDao.saveDetails(vmInstance);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ import com.cloud.storage.dao.LaunchPermissionDao;
|
|||
import com.cloud.storage.dao.SnapshotDao;
|
||||
import com.cloud.storage.dao.StoragePoolHostDao;
|
||||
import com.cloud.storage.dao.VMTemplateDao;
|
||||
import com.cloud.storage.dao.VMTemplateDetailsDao;
|
||||
import com.cloud.storage.dao.VMTemplatePoolDao;
|
||||
import com.cloud.storage.dao.VMTemplateZoneDao;
|
||||
import com.cloud.storage.dao.VolumeDao;
|
||||
|
|
@ -161,6 +162,9 @@ public class TemplateManagerImplTest {
|
|||
@Inject
|
||||
SnapshotDao snapshotDao;
|
||||
|
||||
@Inject
|
||||
VMTemplateDetailsDao tmpltDetailsDao;
|
||||
|
||||
public class CustomThreadPoolExecutor extends ThreadPoolExecutor {
|
||||
AtomicInteger ai = new AtomicInteger(0);
|
||||
public CustomThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit,
|
||||
|
|
@ -623,6 +627,11 @@ public class TemplateManagerImplTest {
|
|||
return Mockito.mock(TemplateAdapter.class);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public VMTemplateDetailsDao vmTemplateDetailsDao() {
|
||||
return Mockito.mock(VMTemplateDetailsDao.class);
|
||||
}
|
||||
|
||||
public static class Library implements TypeFilter {
|
||||
@Override
|
||||
public boolean match(MetadataReader mdr, MetadataReaderFactory arg1) throws IOException {
|
||||
|
|
|
|||
|
|
@ -498,6 +498,10 @@
|
|||
if (includingSecurityGroupService == false) {
|
||||
hiddenTabs.push("securityGroups");
|
||||
}
|
||||
|
||||
if (args.context.instances[0].state == 'Running') {
|
||||
hiddenTabs.push("settings");
|
||||
}
|
||||
|
||||
return hiddenTabs;
|
||||
},
|
||||
|
|
@ -2680,11 +2684,172 @@
|
|||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Settings tab
|
||||
*/
|
||||
settings: {
|
||||
title: 'label.settings',
|
||||
custom: cloudStack.uiCustom.granularDetails({
|
||||
dataProvider: function(args) {
|
||||
$.ajax({
|
||||
url: createURL('listVirtualMachines&id=' + args.context.instances[0].id),
|
||||
success: function(json) {
|
||||
var details = json.listvirtualmachinesresponse.virtualmachine[0].details;
|
||||
args.response.success({
|
||||
data: parseDetails(details)
|
||||
});
|
||||
},
|
||||
|
||||
error: function(json) {
|
||||
args.response.error(parseXMLHttpResponse(json));
|
||||
}
|
||||
});
|
||||
|
||||
},
|
||||
actions: {
|
||||
edit: function(args) {
|
||||
var data = {
|
||||
name: args.data.jsonObj.name,
|
||||
value: args.data.value
|
||||
};
|
||||
var existingDetails;
|
||||
$.ajax({
|
||||
url: createURL('listVirtualMachines&id=' + args.context.instances[0].id),
|
||||
async:false,
|
||||
success: function(json) {
|
||||
var details = json.listvirtualmachinesresponse.virtualmachine[0].details;
|
||||
console.log(details);
|
||||
existingDetails = details;
|
||||
},
|
||||
|
||||
error: function(json) {
|
||||
args.response.error(parseXMLHttpResponse(json));
|
||||
}
|
||||
});
|
||||
console.log(existingDetails);
|
||||
var newDetails = '';
|
||||
for (d in existingDetails) {
|
||||
if (d != data.name) {
|
||||
newDetails += 'details[0].' + d + '=' + existingDetails[d] + '&';
|
||||
}
|
||||
}
|
||||
newDetails += 'details[0].' + data.name + '=' + data.value;
|
||||
|
||||
$.ajax({
|
||||
url: createURL('updateVirtualMachine&id=' + args.context.instances[0].id + '&' + newDetails),
|
||||
async:false,
|
||||
success: function(json) {
|
||||
var items = json.updatevirtualmachineresponse.virtualmachine.details;
|
||||
args.response.success({
|
||||
data: parseDetails(items)
|
||||
});
|
||||
},
|
||||
|
||||
error: function(json) {
|
||||
args.response.error(parseXMLHttpResponse(json));
|
||||
}
|
||||
});
|
||||
},
|
||||
remove: function(args) {
|
||||
var existingDetails;
|
||||
$.ajax({
|
||||
url: createURL('listVirtualMachines&id=' + args.context.instances[0].id),
|
||||
async:false,
|
||||
success: function(json) {
|
||||
var details = json.listvirtualmachinesresponse.virtualmachine[0].details;
|
||||
existingDetails = details;
|
||||
},
|
||||
|
||||
error: function(json) {
|
||||
args.response.error(parseXMLHttpResponse(json));
|
||||
}
|
||||
});
|
||||
|
||||
var detailToDelete = args.data.jsonObj.name;
|
||||
var newDetails = ''
|
||||
for (detail in existingDetails) {
|
||||
if (detail != detailToDelete) {
|
||||
newDetails += 'details[0].' + detail + '=' + existingDetails[detail] + '&';
|
||||
}
|
||||
}
|
||||
if (newDetails != '') {
|
||||
newDetails = newDetails.substring(0, newDetails.length - 1);
|
||||
}
|
||||
else {
|
||||
newDetails += 'cleanupdetails=true'
|
||||
}
|
||||
$.ajax({
|
||||
url: createURL('updateVirtualMachine&id=' + args.context.instances[0].id + '&' + newDetails),
|
||||
async:false,
|
||||
success: function(json) {
|
||||
var items = json.updatevirtualmachineresponse.virtualmachine.details;
|
||||
args.response.success({
|
||||
data: parseDetails(items)
|
||||
});
|
||||
},
|
||||
error: function(json) {
|
||||
args.response.error(parseXMLHttpResponse(json));
|
||||
}
|
||||
});
|
||||
},
|
||||
add: function(args) {
|
||||
var name = args.data.name;
|
||||
var value = args.data.value;
|
||||
|
||||
var details;
|
||||
$.ajax({
|
||||
url: createURL('listVirtualMachines&id=' + args.context.instances[0].id),
|
||||
async:false,
|
||||
success: function(json) {
|
||||
var dets = json.listvirtualmachinesresponse.virtualmachine[0].details;
|
||||
details = dets;
|
||||
},
|
||||
|
||||
error: function(json) {
|
||||
args.response.error(parseXMLHttpResponse(json));
|
||||
}
|
||||
});
|
||||
|
||||
var detailsFormat = '';
|
||||
for (key in details) {
|
||||
detailsFormat += "details[0]." + key + "=" + details[key] + "&";
|
||||
}
|
||||
// Add new detail to the existing ones
|
||||
detailsFormat += "details[0]." + name + "=" + value;
|
||||
$.ajax({
|
||||
url: createURL('updateVirtualMachine&id=' + args.context.instances[0].id + "&" + detailsFormat),
|
||||
async: false,
|
||||
success: function(json) {
|
||||
var items = json.updatevirtualmachineresponse.virtualmachine.details;
|
||||
args.response.success({
|
||||
data: parseDetails(items)
|
||||
});
|
||||
},
|
||||
error: function(json) {
|
||||
args.response.error(parseXMLHttpResponse(json));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var parseDetails = function(details) {
|
||||
var listDetails = [];
|
||||
for (detail in details){
|
||||
var det = {};
|
||||
det["name"] = detail;
|
||||
det["value"] = details[detail];
|
||||
listDetails.push(det);
|
||||
}
|
||||
return listDetails;
|
||||
}
|
||||
|
||||
var vmActionfilter = cloudStack.actionFilter.vmActionFilter = function(args) {
|
||||
var jsonObj = args.context.item;
|
||||
|
|
|
|||
|
|
@ -1780,8 +1780,125 @@
|
|||
}
|
||||
}}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Settings tab
|
||||
*/
|
||||
settings: {
|
||||
title: 'label.settings',
|
||||
custom: cloudStack.uiCustom.granularDetails({
|
||||
dataProvider: function(args) {
|
||||
$.ajax({
|
||||
url: createURL('listTemplates'),
|
||||
data: {
|
||||
templatefilter: "self",
|
||||
id: args.context.templates[0].id
|
||||
},
|
||||
success: function(json) {
|
||||
var details = json.listtemplatesresponse.template[0].details;
|
||||
var listDetails = [];
|
||||
for (detail in details){
|
||||
var det = {};
|
||||
det["name"] = detail;
|
||||
det["value"] = details[detail];
|
||||
listDetails.push(det);
|
||||
}
|
||||
args.response.success({
|
||||
data: listDetails
|
||||
});
|
||||
},
|
||||
|
||||
error: function(json) {
|
||||
args.response.error(parseXMLHttpResponse(json));
|
||||
}
|
||||
});
|
||||
|
||||
},
|
||||
actions: {
|
||||
edit: function(args) {
|
||||
var data = {
|
||||
name: args.data.jsonObj.name,
|
||||
value: args.data.value
|
||||
};
|
||||
var existingDetails = args.context.templates[0].details;
|
||||
var newDetails = '';
|
||||
for (d in existingDetails) {
|
||||
if (d != data.name) {
|
||||
newDetails += 'details[0].' + d + '=' + existingDetails[d] + '&';
|
||||
}
|
||||
}
|
||||
newDetails += 'details[0].' + data.name + '=' + data.value;
|
||||
|
||||
$.ajax({
|
||||
url: createURL('updateTemplate&id=' + args.context.templates[0].id + '&' + newDetails),
|
||||
success: function(json) {
|
||||
var template = json.updatetemplateresponse.template;
|
||||
args.context.templates[0].details = template.details;
|
||||
args.response.success({
|
||||
data: template.details
|
||||
});
|
||||
},
|
||||
|
||||
error: function(json) {
|
||||
args.response.error(parseXMLHttpResponse(json));
|
||||
}
|
||||
});
|
||||
},
|
||||
remove: function(args) {
|
||||
var existingDetails = args.context.templates[0].details;
|
||||
var detailToDelete = args.data.jsonObj.name;
|
||||
var newDetails = ''
|
||||
for (detail in existingDetails) {
|
||||
if (detail != detailToDelete) {
|
||||
newDetails += 'details[0].' + detail + '=' + existingDetails[detail] + '&';
|
||||
}
|
||||
}
|
||||
if (newDetails != '') {
|
||||
newDetails = newDetails.substring(0, newDetails.length - 1);
|
||||
}
|
||||
else {
|
||||
newDetails += 'cleanupdetails=true';
|
||||
}
|
||||
$.ajax({
|
||||
url: createURL('updateTemplate&id=' + args.context.templates[0].id + '&' + newDetails),
|
||||
success: function(json) {
|
||||
var template = json.updatetemplateresponse.template;
|
||||
args.context.templates[0].details = template.details;
|
||||
args.response.success({
|
||||
data: template.details
|
||||
});
|
||||
},
|
||||
error: function(json) {
|
||||
args.response.error(parseXMLHttpResponse(json));
|
||||
}
|
||||
});
|
||||
},
|
||||
add: function(args) {
|
||||
var name = args.data.name;
|
||||
var value = args.data.value;
|
||||
var details = args.context.templates[0].details;
|
||||
var detailsFormat = '';
|
||||
for (key in details) {
|
||||
detailsFormat += "details[0]." + key + "=" + details[key] + "&";
|
||||
}
|
||||
// Add new detail to the existing ones
|
||||
detailsFormat += "details[0]." + name + "=" + value;
|
||||
$.ajax({
|
||||
url: createURL('updateTemplate&id=' + args.context.templates[0].id + "&" + detailsFormat),
|
||||
async: false,
|
||||
success: function(json) {
|
||||
var template = json.updatetemplateresponse.template;
|
||||
args.context.templates[0].details = template.details;
|
||||
args.response.success({
|
||||
data: template.details
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -54,4 +54,88 @@
|
|||
return $listView;
|
||||
}
|
||||
};
|
||||
}(jQuery, cloudStack));
|
||||
cloudStack.uiCustom.granularDetails = function(args) {
|
||||
var dataProvider = args.dataProvider;
|
||||
var actions = args.actions;
|
||||
|
||||
return function(args) {
|
||||
var context = args.context;
|
||||
|
||||
var listView = {
|
||||
id: 'details',
|
||||
fields: {
|
||||
name: {
|
||||
label: 'label.name'
|
||||
},
|
||||
value: {
|
||||
label: 'label.value',
|
||||
editable: true
|
||||
}
|
||||
},
|
||||
actions: {
|
||||
edit: {
|
||||
label: 'label.change.value',
|
||||
action: actions.edit
|
||||
},
|
||||
remove: {
|
||||
label: 'Remove Setting',
|
||||
messages: {
|
||||
confirm: function(args) {
|
||||
return 'Delete Setting';
|
||||
},
|
||||
notification: function(args) {
|
||||
return 'Setting deleted';
|
||||
}
|
||||
},
|
||||
action: actions.remove,
|
||||
notification: {
|
||||
poll: function(args) {
|
||||
args.complete();
|
||||
}
|
||||
}
|
||||
},
|
||||
add : {
|
||||
label: 'Add Setting',
|
||||
messages: {
|
||||
confirm: function(args) {
|
||||
return 'Add Setting';
|
||||
},
|
||||
notification: function(args) {
|
||||
return 'Setting added';
|
||||
}
|
||||
},
|
||||
preFilter: function(args) {
|
||||
return true;
|
||||
},
|
||||
createForm: {
|
||||
title: 'Add New Setting',
|
||||
fields: {
|
||||
name: {
|
||||
label: 'label.name',
|
||||
validation: {
|
||||
required: true
|
||||
}
|
||||
},
|
||||
value: {
|
||||
label: 'label.value',
|
||||
validation: {
|
||||
required: true
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
action: actions.add
|
||||
}
|
||||
},
|
||||
dataProvider: dataProvider
|
||||
};
|
||||
|
||||
var $listView = $('<div>').listView({
|
||||
context: context,
|
||||
listView: listView
|
||||
});
|
||||
|
||||
return $listView;
|
||||
}
|
||||
};
|
||||
}(jQuery, cloudStack));
|
||||
Loading…
Reference in New Issue