Merge remote-tracking branch 'origin/4.15'

Signed-off-by: Rohit Yadav <rohit.yadav@shapeblue.com>
This commit is contained in:
Rohit Yadav 2021-03-29 16:34:22 +05:30
commit c1a02e1697
115 changed files with 399 additions and 120 deletions

View File

@ -42,6 +42,4 @@ public interface ApiServerService {
public String handleRequest(Map<String, Object[]> params, String responseType, StringBuilder auditTrailSb) throws ServerApiException; public String handleRequest(Map<String, Object[]> params, String responseType, StringBuilder auditTrailSb) throws ServerApiException;
public Class<?> getCmdClass(String cmdName); public Class<?> getCmdClass(String cmdName);
public boolean isValidApiName(String apiName);
} }

View File

@ -94,9 +94,6 @@ public class ImportRoleCmd extends RoleCmd {
if (Strings.isNullOrEmpty(rule)) { if (Strings.isNullOrEmpty(rule)) {
throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Empty rule provided in rules param"); throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Empty rule provided in rules param");
} }
if (!rule.contains("*") && !_apiServer.isValidApiName(rule)) {
throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Invalid api name: " + rule + " provided in rules param");
}
ruleDetails.put(ApiConstants.RULE, new Rule(rule)); ruleDetails.put(ApiConstants.RULE, new Rule(rule));
String permission = detail.get(ApiConstants.PERMISSION); String permission = detail.get(ApiConstants.PERMISSION);

View File

@ -173,6 +173,7 @@ public class PrimaryDataStoreHelper {
public DataStore attachZone(DataStore store) { public DataStore attachZone(DataStore store) {
StoragePoolVO pool = this.dataStoreDao.findById(store.getId()); StoragePoolVO pool = this.dataStoreDao.findById(store.getId());
storageMgr.createCapacityEntry(pool.getId());
pool.setScope(ScopeType.ZONE); pool.setScope(ScopeType.ZONE);
pool.setStatus(StoragePoolStatus.Up); pool.setStatus(StoragePoolStatus.Up);
this.dataStoreDao.update(pool.getId(), pool); this.dataStoreDao.update(pool.getId(), pool);
@ -181,6 +182,7 @@ public class PrimaryDataStoreHelper {
public DataStore attachZone(DataStore store, HypervisorType hypervisor) { public DataStore attachZone(DataStore store, HypervisorType hypervisor) {
StoragePoolVO pool = this.dataStoreDao.findById(store.getId()); StoragePoolVO pool = this.dataStoreDao.findById(store.getId());
storageMgr.createCapacityEntry(pool.getId());
pool.setScope(ScopeType.ZONE); pool.setScope(ScopeType.ZONE);
pool.setHypervisor(hypervisor); pool.setHypervisor(hypervisor);
pool.setStatus(StoragePoolStatus.Up); pool.setStatus(StoragePoolStatus.Up);

View File

@ -2072,7 +2072,13 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
// Setup ROOT/DATA disk devices // Setup ROOT/DATA disk devices
// //
for (DiskTO vol : sortedDisks) { for (DiskTO vol : sortedDisks) {
if (vol.getType() == Volume.Type.ISO || deployAsIs && vol.getType() == Volume.Type.ROOT) { if (vol.getType() == Volume.Type.ISO) {
continue;
}
if (deployAsIs && vol.getType() == Volume.Type.ROOT) {
rootDiskTO = vol;
resizeRootDiskOnVMStart(vmMo, rootDiskTO, hyperHost, context);
continue; continue;
} }

View File

@ -31,6 +31,7 @@ import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.BaseCmd; import org.apache.cloudstack.api.BaseCmd;
import org.apache.cloudstack.api.command.user.firewall.CreateFirewallRuleCmd; import org.apache.cloudstack.api.command.user.firewall.CreateFirewallRuleCmd;
import org.apache.cloudstack.api.command.user.vm.StartVMCmd; import org.apache.cloudstack.api.command.user.vm.StartVMCmd;
import org.apache.cloudstack.api.command.user.volume.ResizeVolumeCmd;
import org.apache.commons.codec.binary.Base64; import org.apache.commons.codec.binary.Base64;
import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.CollectionUtils;
import org.apache.log4j.Level; import org.apache.log4j.Level;
@ -70,6 +71,10 @@ import com.cloud.network.rules.RulesService;
import com.cloud.network.rules.dao.PortForwardingRulesDao; import com.cloud.network.rules.dao.PortForwardingRulesDao;
import com.cloud.offering.ServiceOffering; import com.cloud.offering.ServiceOffering;
import com.cloud.resource.ResourceManager; import com.cloud.resource.ResourceManager;
import com.cloud.storage.Volume;
import com.cloud.storage.VolumeApiService;
import com.cloud.storage.VolumeVO;
import com.cloud.storage.dao.VolumeDao;
import com.cloud.user.Account; import com.cloud.user.Account;
import com.cloud.user.SSHKeyPairVO; import com.cloud.user.SSHKeyPairVO;
import com.cloud.uservm.UserVm; import com.cloud.uservm.UserVm;
@ -118,6 +123,10 @@ public class KubernetesClusterResourceModifierActionWorker extends KubernetesClu
protected VMInstanceDao vmInstanceDao; protected VMInstanceDao vmInstanceDao;
@Inject @Inject
protected UserVmManager userVmManager; protected UserVmManager userVmManager;
@Inject
protected VolumeApiService volumeService;
@Inject
protected VolumeDao volumeDao;
protected String kubernetesClusterNodeNamePrefix; protected String kubernetesClusterNodeNamePrefix;
@ -268,6 +277,29 @@ public class KubernetesClusterResourceModifierActionWorker extends KubernetesClu
return plan(kubernetesCluster.getTotalNodeCount(), zone, offering); return plan(kubernetesCluster.getTotalNodeCount(), zone, offering);
} }
protected void resizeNodeVolume(final UserVm vm) throws ManagementServerException {
try {
if (vm.getHypervisorType() == Hypervisor.HypervisorType.VMware && templateDao.findById(vm.getTemplateId()).isDeployAsIs()) {
List<VolumeVO> vmVols = volumeDao.findByInstance(vm.getId());
for (VolumeVO volumeVO : vmVols) {
if (volumeVO.getVolumeType() == Volume.Type.ROOT) {
ResizeVolumeCmd resizeVolumeCmd = new ResizeVolumeCmd();
resizeVolumeCmd = ComponentContext.inject(resizeVolumeCmd);
Field f = resizeVolumeCmd.getClass().getDeclaredField("size");
Field f1 = resizeVolumeCmd.getClass().getDeclaredField("id");
f.setAccessible(true);
f1.setAccessible(true);
f1.set(resizeVolumeCmd, volumeVO.getId());
f.set(resizeVolumeCmd, kubernetesCluster.getNodeRootDiskSize());
volumeService.resizeVolume(resizeVolumeCmd);
}
}
}
} catch (IllegalAccessException | NoSuchFieldException e) {
throw new ManagementServerException(String.format("Failed to resize volume of VM in the Kubernetes cluster : %s", kubernetesCluster.getName()), e);
}
}
protected void startKubernetesVM(final UserVm vm) throws ManagementServerException { protected void startKubernetesVM(final UserVm vm) throws ManagementServerException {
try { try {
StartVMCmd startVm = new StartVMCmd(); StartVMCmd startVm = new StartVMCmd();
@ -275,6 +307,7 @@ public class KubernetesClusterResourceModifierActionWorker extends KubernetesClu
Field f = startVm.getClass().getDeclaredField("id"); Field f = startVm.getClass().getDeclaredField("id");
f.setAccessible(true); f.setAccessible(true);
f.set(startVm, vm.getId()); f.set(startVm, vm.getId());
resizeNodeVolume(vm);
userVmService.startVirtualMachine(startVm); userVmService.startVirtualMachine(startVm);
if (LOGGER.isInfoEnabled()) { if (LOGGER.isInfoEnabled()) {
LOGGER.info(String.format("Started VM : %s in the Kubernetes cluster : %s", vm.getDisplayName(), kubernetesCluster.getName())); LOGGER.info(String.format("Started VM : %s in the Kubernetes cluster : %s", vm.getDisplayName(), kubernetesCluster.getName()));
@ -296,6 +329,7 @@ public class KubernetesClusterResourceModifierActionWorker extends KubernetesClu
for (int i = offset + 1; i <= nodeCount; i++) { for (int i = offset + 1; i <= nodeCount; i++) {
UserVm vm = createKubernetesNode(publicIpAddress, i); UserVm vm = createKubernetesNode(publicIpAddress, i);
addKubernetesClusterVm(kubernetesCluster.getId(), vm.getId()); addKubernetesClusterVm(kubernetesCluster.getId(), vm.getId());
resizeNodeVolume(vm);
startKubernetesVM(vm); startKubernetesVM(vm);
vm = userVmDao.findById(vm.getId()); vm = userVmDao.findById(vm.getId());
if (vm == null) { if (vm == null) {

View File

@ -277,6 +277,7 @@ public class KubernetesClusterStartWorker extends KubernetesClusterResourceModif
UserVm k8sMasterVM = null; UserVm k8sMasterVM = null;
k8sMasterVM = createKubernetesMaster(network, publicIpAddress); k8sMasterVM = createKubernetesMaster(network, publicIpAddress);
addKubernetesClusterVm(kubernetesCluster.getId(), k8sMasterVM.getId()); addKubernetesClusterVm(kubernetesCluster.getId(), k8sMasterVM.getId());
resizeNodeVolume(k8sMasterVM);
startKubernetesVM(k8sMasterVM); startKubernetesVM(k8sMasterVM);
k8sMasterVM = userVmDao.findById(k8sMasterVM.getId()); k8sMasterVM = userVmDao.findById(k8sMasterVM.getId());
if (k8sMasterVM == null) { if (k8sMasterVM == null) {
@ -296,6 +297,7 @@ public class KubernetesClusterStartWorker extends KubernetesClusterResourceModif
UserVm vm = null; UserVm vm = null;
vm = createKubernetesAdditionalMaster(publicIpAddress, i); vm = createKubernetesAdditionalMaster(publicIpAddress, i);
addKubernetesClusterVm(kubernetesCluster.getId(), vm.getId()); addKubernetesClusterVm(kubernetesCluster.getId(), vm.getId());
resizeNodeVolume(vm);
startKubernetesVM(vm); startKubernetesVM(vm);
vm = userVmDao.findById(vm.getId()); vm = userVmDao.findById(vm.getId());
if (vm == null) { if (vm == null) {

View File

@ -1208,17 +1208,6 @@ public class ApiServer extends ManagerBase implements HttpRequestHandler, ApiSer
} }
} }
@Override
public boolean isValidApiName(String apiName) {
if (apiName == null || apiName.isEmpty())
return false;
if (!s_apiNameCmdClassMap.containsKey(apiName))
return false;
return true;
}
// FIXME: rather than isError, we might was to pass in the status code to give more flexibility // FIXME: rather than isError, we might was to pass in the status code to give more flexibility
private void writeResponse(final HttpResponse resp, final String responseText, final int statusCode, final String responseType, final String reasonPhrase) { private void writeResponse(final HttpResponse resp, final String responseText, final int statusCode, final String responseType, final String reasonPhrase) {
try { try {

View File

@ -962,8 +962,15 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
} }
// if we are to use the existing disk offering // if we are to use the existing disk offering
ImageFormat format = null;
if (newDiskOffering == null) { if (newDiskOffering == null) {
if (volume.getVolumeType().equals(Volume.Type.ROOT) && diskOffering.getDiskSize() > 0) { Long templateId = volume.getTemplateId();
if (templateId != null) {
VMTemplateVO template = _templateDao.findById(templateId);
format = template.getFormat();
}
if (volume.getVolumeType().equals(Volume.Type.ROOT) && diskOffering.getDiskSize() > 0 && format != null && format != ImageFormat.ISO) {
throw new InvalidParameterValueException( throw new InvalidParameterValueException(
"Failed to resize Root volume. The service offering of this Volume has been configured with a root disk size; " "Failed to resize Root volume. The service offering of this Volume has been configured with a root disk size; "
+ "on such case a Root Volume can only be resized when changing to another Service Offering with a Root disk size. " + "on such case a Root Volume can only be resized when changing to another Service Offering with a Root disk size. "

View File

@ -145,6 +145,8 @@ import com.cloud.agent.api.to.deployasis.OVFPropertyTO;
import com.cloud.agent.manager.Commands; import com.cloud.agent.manager.Commands;
import com.cloud.alert.AlertManager; import com.cloud.alert.AlertManager;
import com.cloud.api.ApiDBUtils; import com.cloud.api.ApiDBUtils;
import com.cloud.api.query.dao.ServiceOfferingJoinDao;
import com.cloud.api.query.vo.ServiceOfferingJoinVO;
import com.cloud.capacity.Capacity; import com.cloud.capacity.Capacity;
import com.cloud.capacity.CapacityManager; import com.cloud.capacity.CapacityManager;
import com.cloud.configuration.Config; import com.cloud.configuration.Config;
@ -512,7 +514,9 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
@Inject @Inject
private UserVmDeployAsIsDetailsDao userVmDeployAsIsDetailsDao; private UserVmDeployAsIsDetailsDao userVmDeployAsIsDetailsDao;
@Inject @Inject
private StorageManager _storageManager; private StorageManager storageManager;
@Inject
private ServiceOfferingJoinDao serviceOfferingJoinDao;
private ScheduledExecutorService _executor = null; private ScheduledExecutorService _executor = null;
private ScheduledExecutorService _vmIpFetchExecutor = null; private ScheduledExecutorService _vmIpFetchExecutor = null;
@ -2051,7 +2055,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
if (poolType == StoragePoolType.PowerFlex) { if (poolType == StoragePoolType.PowerFlex) {
// Get volume stats from the pool directly instead of sending cmd to host // Get volume stats from the pool directly instead of sending cmd to host
// Added support for ScaleIO/PowerFlex pool only // Added support for ScaleIO/PowerFlex pool only
answer = _storageManager.getVolumeStats(storagePool, cmd); answer = storageManager.getVolumeStats(storagePool, cmd);
} else { } else {
if (timeout > 0) { if (timeout > 0) {
cmd.setWait(timeout/1000); cmd.setWait(timeout/1000);
@ -5313,10 +5317,22 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
throw new InvalidParameterValueException("Unable to use template " + templateId); throw new InvalidParameterValueException("Unable to use template " + templateId);
} }
ServiceOfferingJoinVO svcOffering = serviceOfferingJoinDao.findById(serviceOfferingId);
if (template.isDeployAsIs()) {
if (svcOffering != null && svcOffering.getRootDiskSize() != null && svcOffering.getRootDiskSize() > 0) {
throw new InvalidParameterValueException("Failed to deploy Virtual Machine as a service offering with root disk size specified cannot be used with a deploy as-is template");
}
if (cmd.getDetails().get("rootdisksize") != null) {
throw new InvalidParameterValueException("Overriding root disk size isn't supported for VMs deployed from defploy as-is templates");
}
// Bootmode and boottype are not supported on VMWare dpeloy-as-is templates (since 4.15) // Bootmode and boottype are not supported on VMWare dpeloy-as-is templates (since 4.15)
if (template.isDeployAsIs() && (cmd.getBootMode() != null || cmd.getBootType() != null)) { if ((cmd.getBootMode() != null || cmd.getBootType() != null)) {
throw new InvalidParameterValueException("Boot type and boot mode are not supported on VMware, as we honour what is defined in the template."); throw new InvalidParameterValueException("Boot type and boot mode are not supported on VMware, as we honour what is defined in the template.");
} }
}
Long diskOfferingId = cmd.getDiskOfferingId(); Long diskOfferingId = cmd.getDiskOfferingId();
DiskOffering diskOffering = null; DiskOffering diskOffering = null;
@ -6349,7 +6365,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
HypervisorType hypervisorType = _volsDao.getHypervisorType(volume.getId()); HypervisorType hypervisorType = _volsDao.getHypervisorType(volume.getId());
if (hypervisorType.equals(HypervisorType.VMware)) { if (hypervisorType.equals(HypervisorType.VMware)) {
try { try {
boolean isStoragePoolStoragepolicyComplaince = _storageManager.isStoragePoolComplaintWithStoragePolicy(Arrays.asList(volume), pool); boolean isStoragePoolStoragepolicyComplaince = storageManager.isStoragePoolComplaintWithStoragePolicy(Arrays.asList(volume), pool);
if (!isStoragePoolStoragepolicyComplaince) { if (!isStoragePoolStoragepolicyComplaince) {
throw new CloudRuntimeException(String.format("Storage pool %s is not storage policy compliance with the volume %s", pool.getUuid(), volume.getUuid())); throw new CloudRuntimeException(String.format("Storage pool %s is not storage policy compliance with the volume %s", pool.getUuid(), volume.getUuid()));
} }

View File

@ -2692,6 +2692,7 @@
"message.delete.vpn.customer.gateway": "Please confirm that you want to delete this VPN Customer Gateway", "message.delete.vpn.customer.gateway": "Please confirm that you want to delete this VPN Customer Gateway",
"message.delete.vpn.gateway": "Please confirm that you want to delete this VPN Gateway", "message.delete.vpn.gateway": "Please confirm that you want to delete this VPN Gateway",
"message.deleting.vm": "Deleting VM", "message.deleting.vm": "Deleting VM",
"message.deployasis": "Selected template is Deploy As-Is i.e., the VM is deployed by importing an OVA with vApps directly into vCenter. Root disk(s) resize is allowed only on stopped VMs for such templates.",
"message.desc.add.new.lb.sticky.rule": "Add new LB sticky rule", "message.desc.add.new.lb.sticky.rule": "Add new LB sticky rule",
"message.desc.advanced.zone": "For more sophisticated network topologies. This network model provides the most flexibility in defining guest networks and providing custom network offerings such as firewall, VPN, or load balancer support.", "message.desc.advanced.zone": "For more sophisticated network topologies. This network model provides the most flexibility in defining guest networks and providing custom network offerings such as firewall, VPN, or load balancer support.",
"message.desc.basic.zone": "Provide a single network where each VM instance is assigned an IP directly from the network. Guest isolation can be provided through layer-3 means such as security groups (IP address source filtering).", "message.desc.basic.zone": "Provide a single network where each VM instance is assigned an IP directly from the network. Guest isolation can be provided through layer-3 means such as security groups (IP address source filtering).",

View File

@ -22,7 +22,8 @@
style="width: 25vw;float: right;margin-bottom: 10px; z-index: 8" style="width: 25vw;float: right;margin-bottom: 10px; z-index: 8"
:placeholder="$t('label.search')" :placeholder="$t('label.search')"
v-model="filter" v-model="filter"
@search="handleSearch" /> @search="handleSearch"
autoFocus />
<a-table <a-table
size="small" size="small"

View File

@ -34,6 +34,7 @@
v-decorator="[item.resourcetype, { v-decorator="[item.resourcetype, {
initialValue: item.max initialValue: item.max
}]" }]"
:autoFocus="index === 0"
/> />
</a-form-item> </a-form-item>
<div class="card-footer"> <div class="card-footer">

View File

@ -240,3 +240,9 @@ a {
color: @primary-color; color: @primary-color;
} }
} }
@media only screen and (max-width: 576px) {
.ant-pagination-options {
display: inline-block;
}
}

View File

@ -173,7 +173,7 @@
}]" }]"
v-model="formModel[field.name]" v-model="formModel[field.name]"
:placeholder="field.description" :placeholder="field.description"
:autoFocus="fieldIndex === 0" :autoFocus="fieldIndex === firstIndex"
/> />
</span> </span>
<span v-else-if="currentAction.mapping && field.name in currentAction.mapping && currentAction.mapping[field.name].options"> <span v-else-if="currentAction.mapping && field.name in currentAction.mapping && currentAction.mapping[field.name].options">
@ -183,6 +183,7 @@
rules: [{ required: field.required, message: `${$t('message.error.select')}` }] rules: [{ required: field.required, message: `${$t('message.error.select')}` }]
}]" }]"
:placeholder="field.description" :placeholder="field.description"
:autoFocus="fieldIndex === firstIndex"
> >
<a-select-option key="" >{{ }}</a-select-option> <a-select-option key="" >{{ }}</a-select-option>
<a-select-option v-for="(opt, optIndex) in currentAction.mapping[field.name].options" :key="optIndex"> <a-select-option v-for="(opt, optIndex) in currentAction.mapping[field.name].options" :key="optIndex">
@ -204,6 +205,7 @@
:filterOption="(input, option) => { :filterOption="(input, option) => {
return option.componentOptions.children[0].text.toLowerCase().indexOf(input.toLowerCase()) >= 0 return option.componentOptions.children[0].text.toLowerCase().indexOf(input.toLowerCase()) >= 0
}" }"
:autoFocus="fieldIndex === firstIndex"
> >
<a-select-option key="">{{ }}</a-select-option> <a-select-option key="">{{ }}</a-select-option>
<a-select-option v-for="(opt, optIndex) in field.opts" :key="optIndex"> <a-select-option v-for="(opt, optIndex) in field.opts" :key="optIndex">
@ -224,6 +226,7 @@
:filterOption="(input, option) => { :filterOption="(input, option) => {
return option.componentOptions.children[0].text.toLowerCase().indexOf(input.toLowerCase()) >= 0 return option.componentOptions.children[0].text.toLowerCase().indexOf(input.toLowerCase()) >= 0
}" }"
:autoFocus="fieldIndex === firstIndex"
> >
<a-select-option key="">{{ }}</a-select-option> <a-select-option key="">{{ }}</a-select-option>
<a-select-option v-for="opt in field.opts" :key="opt.id"> <a-select-option v-for="opt in field.opts" :key="opt.id">
@ -239,6 +242,7 @@
rules: [{ required: field.required, message: `${$t('message.error.select')}` }] rules: [{ required: field.required, message: `${$t('message.error.select')}` }]
}]" }]"
:placeholder="field.description" :placeholder="field.description"
:autoFocus="fieldIndex === firstIndex"
> >
<a-select-option v-for="(opt, optIndex) in field.opts" :key="optIndex"> <a-select-option v-for="(opt, optIndex) in field.opts" :key="optIndex">
{{ opt.name && opt.type ? opt.name + ' (' + opt.type + ')' : opt.name || opt.description }} {{ opt.name && opt.type ? opt.name + ' (' + opt.type + ')' : opt.name || opt.description }}
@ -247,7 +251,7 @@
</span> </span>
<span v-else-if="field.type==='long'"> <span v-else-if="field.type==='long'">
<a-input-number <a-input-number
:autoFocus="fieldIndex === 0" :autoFocus="fieldIndex === firstIndex"
style="width: 100%;" style="width: 100%;"
v-decorator="[field.name, { v-decorator="[field.name, {
rules: [{ required: field.required, message: `${$t('message.validate.number')}` }] rules: [{ required: field.required, message: `${$t('message.validate.number')}` }]
@ -270,6 +274,7 @@
}]" }]"
:placeholder="field.description" :placeholder="field.description"
@blur="($event) => handleConfirmBlur($event, field.name)" @blur="($event) => handleConfirmBlur($event, field.name)"
:autoFocus="fieldIndex === firstIndex"
/> />
</span> </span>
<span v-else-if="field.name==='certificate' || field.name==='privatekey' || field.name==='certchain'"> <span v-else-if="field.name==='certificate' || field.name==='privatekey' || field.name==='certchain'">
@ -279,11 +284,12 @@
rules: [{ required: field.required, message: `${$t('message.error.required.input')}` }] rules: [{ required: field.required, message: `${$t('message.error.required.input')}` }]
}]" }]"
:placeholder="field.description" :placeholder="field.description"
:autoFocus="fieldIndex === firstIndex"
/> />
</span> </span>
<span v-else> <span v-else>
<a-input <a-input
:autoFocus="fieldIndex === 0" :autoFocus="fieldIndex === firstIndex"
v-decorator="[field.name, { v-decorator="[field.name, {
rules: [{ required: field.required, message: `${$t('message.error.required.input')}` }] rules: [{ required: field.required, message: `${$t('message.error.required.input')}` }]
}]" }]"
@ -394,7 +400,8 @@ export default {
searchParams: {}, searchParams: {},
actions: [], actions: [],
formModel: {}, formModel: {},
confirmDirty: false confirmDirty: false,
firstIndex: 0
} }
}, },
beforeCreate () { beforeCreate () {
@ -756,6 +763,7 @@ export default {
}) })
} }
} }
this.getFirstIndexFocus()
this.showAction = true this.showAction = true
for (const param of this.currentAction.paramFields) { for (const param of this.currentAction.paramFields) {
@ -771,6 +779,16 @@ export default {
this.fillEditFormFieldValues() this.fillEditFormFieldValues()
} }
}, },
getFirstIndexFocus () {
this.firstIndex = 0
for (let fieldIndex = 0; fieldIndex < this.currentAction.paramFields.length; fieldIndex++) {
const field = this.currentAction.paramFields[fieldIndex]
if (!(this.currentAction.mapping && field.name in this.currentAction.mapping && this.currentAction.mapping[field.name].value)) {
this.firstIndex = fieldIndex
break
}
}
},
listUuidOpts (param) { listUuidOpts (param) {
if (this.currentAction.mapping && param.name in this.currentAction.mapping && !this.currentAction.mapping[param.name].api) { if (this.currentAction.mapping && param.name in this.currentAction.mapping && !this.currentAction.mapping[param.name].api) {
return return

View File

@ -29,7 +29,7 @@
<div class="form__item"> <div class="form__item">
<p class="form__label">{{ $t('label.accounttype') }}</p> <p class="form__label">{{ $t('label.accounttype') }}</p>
<a-select v-model="selectedAccountType" defaultValue="account"> <a-select v-model="selectedAccountType" defaultValue="account" autoFocus>
<a-select-option :value="$t('label.account')">{{ $t('label.account') }}</a-select-option> <a-select-option :value="$t('label.account')">{{ $t('label.account') }}</a-select-option>
<a-select-option :value="$t('label.project')">{{ $t('label.project') }}</a-select-option> <a-select-option :value="$t('label.project')">{{ $t('label.project') }}</a-select-option>
</a-select> </a-select>
@ -77,9 +77,14 @@
</a-select> </a-select>
</div> </div>
<a-button type="primary" class="submit-btn" @click="submitData"> <div class="submit-btn">
<a-button @click="closeAction">
{{ $t('label.cancel') }}
</a-button>
<a-button type="primary" @click="submitData">
{{ $t('label.submit') }} {{ $t('label.submit') }}
</a-button> </a-button>
</div>
</div> </div>
@ -183,6 +188,9 @@ export default {
this.selectedAccount = null this.selectedAccount = null
this.fetchNetworks() this.fetchNetworks()
}, },
closeAction () {
this.$emit('close-action')
},
submitData () { submitData () {
let variableKey = '' let variableKey = ''
let variableValue = '' let variableValue = ''
@ -255,6 +263,10 @@ export default {
.submit-btn { .submit-btn {
margin-top: 10px; margin-top: 10px;
align-self: flex-end; align-self: flex-end;
button {
margin-left: 10px;
}
} }
.required { .required {

View File

@ -26,7 +26,8 @@
v-decorator="['id', { v-decorator="['id', {
initialValue: this.selectedIso, initialValue: this.selectedIso,
rules: [{ required: true, message: `${this.$t('label.required')}`}] rules: [{ required: true, message: `${this.$t('label.required')}`}]
}]" > }]"
autoFocus>
<a-select-option v-for="iso in isos" :key="iso.id"> <a-select-option v-for="iso in isos" :key="iso.id">
{{ iso.displaytext || iso.name }} {{ iso.displaytext || iso.name }}
</a-select-option> </a-select-option>

View File

@ -29,7 +29,8 @@
style="margin-bottom: 10px;" style="margin-bottom: 10px;"
:placeholder="$t('label.search')" :placeholder="$t('label.search')"
v-model="filter" v-model="filter"
@search="handleSearch" /> @search="handleSearch"
autoFocus />
</div> </div>
<div class="form__item"> <div class="form__item">

View File

@ -33,7 +33,8 @@
v-decorator="['name', { v-decorator="['name', {
rules: [{ required: true, message: $t('message.error.kubecluster.name') }] rules: [{ required: true, message: $t('message.error.kubecluster.name') }]
}]" }]"
:placeholder="apiParams.name.description"/> :placeholder="apiParams.name.description"
autoFocus />
</a-form-item> </a-form-item>
<a-form-item> <a-form-item>
<span slot="label"> <span slot="label">

View File

@ -28,7 +28,8 @@
v-decorator="['name', { v-decorator="['name', {
rules: [{ required: true, message: $t('message.error.name') }] rules: [{ required: true, message: $t('message.error.name') }]
}]" }]"
:placeholder="apiParams.name.description"/> :placeholder="apiParams.name.description"
autoFocus />
</a-form-item> </a-form-item>
<a-form-item :label="$t('label.publickey')"> <a-form-item :label="$t('label.publickey')">
<a-input <a-input

View File

@ -36,7 +36,8 @@
rules: [{ required: true, message: $t('message.error.select') }] rules: [{ required: true, message: $t('message.error.select') }]
}]" }]"
@change="onChangeVolume" @change="onChangeVolume"
:placeholder="apiParams.volumeid.description"> :placeholder="apiParams.volumeid.description"
autoFocus>
<a-select-option <a-select-option
v-for="volume in listVolumes" v-for="volume in listVolumes"
:key="volume.id"> :key="volume.id">

View File

@ -41,6 +41,7 @@
:options="zoneSelectOptions" :options="zoneSelectOptions"
@change="onSelectZoneId" @change="onSelectZoneId"
:loading="loading.zones" :loading="loading.zones"
autoFocus
></a-select> ></a-select>
</a-form-item> </a-form-item>
<a-form-item <a-form-item
@ -105,7 +106,8 @@
@update-template-iso="updateFieldValue" /> @update-template-iso="updateFieldValue" />
<span> <span>
{{ $t('label.override.rootdisk.size') }} {{ $t('label.override.rootdisk.size') }}
<a-switch @change="val => { this.showRootDiskSizeChanger = val }" style="margin-left: 10px;"/> <a-switch :disabled="template.deployasis" @change="val => { this.showRootDiskSizeChanger = val }" style="margin-left: 10px;"/>
<div v-if="template.deployasis"> {{ this.$t('message.deployasis') }} </div>
</span> </span>
<disk-size-selection <disk-size-selection
v-show="showRootDiskSizeChanger" v-show="showRootDiskSizeChanger"
@ -183,6 +185,7 @@
</a-form-item> </a-form-item>
<compute-offering-selection <compute-offering-selection
:compute-items="options.serviceOfferings" :compute-items="options.serviceOfferings"
:selected-template="template"
:row-count="rowCount.serviceOfferings" :row-count="rowCount.serviceOfferings"
:zoneId="zoneId" :zoneId="zoneId"
:value="serviceOffering ? serviceOffering.id : ''" :value="serviceOffering ? serviceOffering.id : ''"
@ -477,6 +480,7 @@
v-if="vm.templateid && ['KVM', 'VMware'].includes(hypervisor) && !template.deployasis"> v-if="vm.templateid && ['KVM', 'VMware'].includes(hypervisor) && !template.deployasis">
<a-form-item :label="$t('label.boottype')"> <a-form-item :label="$t('label.boottype')">
<a-select <a-select
:autoFocus="vm.templateid && ['KVM', 'VMware'].includes(hypervisor) && !template.deployasis"
v-decorator="['boottype']" v-decorator="['boottype']"
@change="fetchBootModes" @change="fetchBootModes"
> >
@ -543,6 +547,9 @@
:options="keyboardSelectOptions" :options="keyboardSelectOptions"
></a-select> ></a-select>
</a-form-item> </a-form-item>
<a-form-item :label="$t('label.action.start.instance')">
<a-switch v-decorator="['startvm', { initialValue: true }]" :checked="this.startvm" @change="checked => { this.startvm = checked }" />
</a-form-item>
</div> </div>
</template> </template>
</a-step> </a-step>
@ -663,6 +670,7 @@ export default {
podId: null, podId: null,
clusterId: null, clusterId: null,
zoneSelected: false, zoneSelected: false,
startvm: true,
vm: { vm: {
name: null, name: null,
zoneid: null, zoneid: null,
@ -1419,6 +1427,9 @@ export default {
if (values.hypervisor && values.hypervisor.length > 0) { if (values.hypervisor && values.hypervisor.length > 0) {
deployVmData.hypervisor = values.hypervisor deployVmData.hypervisor = values.hypervisor
} }
deployVmData.startvm = values.startvm
// step 3: select service offering // step 3: select service offering
deployVmData.serviceofferingid = values.computeofferingid deployVmData.serviceofferingid = values.computeofferingid
if (this.serviceOffering && this.serviceOffering.iscustomized) { if (this.serviceOffering && this.serviceOffering.iscustomized) {

View File

@ -44,7 +44,8 @@
v-decorator="['volumeids']" v-decorator="['volumeids']"
:placeholder="$t('label.delete.volumes')" :placeholder="$t('label.delete.volumes')"
mode="multiple" mode="multiple"
:loading="loading"> :loading="loading"
:autoFocus="$store.getters.userInfo.roletype !== 'Admin' && !$store.getters.features.allowuserexpungerecovervm">
<a-select-option v-for="volume in volumes" :key="volume.id"> <a-select-option v-for="volume in volumes" :key="volume.id">
{{ volume.name }} {{ volume.name }}
</a-select-option> </a-select-option>

View File

@ -30,7 +30,8 @@
</a-tooltip> </a-tooltip>
</span> </span>
<a-input <a-input
v-decorator="['name', { initialValue: resource.name || '' }]" /> v-decorator="['name', { initialValue: resource.name || '' }]"
autoFocus />
</a-form-item> </a-form-item>
<a-form-item> <a-form-item>
<span slot="label"> <span slot="label">

View File

@ -165,7 +165,7 @@
{{ $t('message.network.addvm.desc') }} {{ $t('message.network.addvm.desc') }}
<div class="modal-form"> <div class="modal-form">
<p class="modal-form__label">{{ $t('label.network') }}:</p> <p class="modal-form__label">{{ $t('label.network') }}:</p>
<a-select :defaultValue="addNetworkData.network" @change="e => addNetworkData.network = e"> <a-select :defaultValue="addNetworkData.network" @change="e => addNetworkData.network = e" autoFocus>
<a-select-option <a-select-option
v-for="network in addNetworkData.allNetworks" v-for="network in addNetworkData.allNetworks"
:key="network.id" :key="network.id"
@ -195,14 +195,16 @@
showSearch showSearch
v-if="editNicResource.type==='Shared'" v-if="editNicResource.type==='Shared'"
v-model="editIpAddressValue" v-model="editIpAddressValue"
:loading="listIps.loading"> :loading="listIps.loading"
:autoFocus="editNicResource.type==='Shared'">
<a-select-option v-for="ip in listIps.opts" :key="ip.ipaddress"> <a-select-option v-for="ip in listIps.opts" :key="ip.ipaddress">
{{ ip.ipaddress }} {{ ip.ipaddress }}
</a-select-option> </a-select-option>
</a-select> </a-select>
<a-input <a-input
v-else v-else
v-model="editIpAddressValue"></a-input> v-model="editIpAddressValue"
:autoFocus="editNicResource.type!=='Shared'"></a-input>
</div> </div>
</a-modal> </a-modal>
@ -218,7 +220,7 @@
{{ $t('message.network.secondaryip') }} {{ $t('message.network.secondaryip') }}
</p> </p>
<a-divider /> <a-divider />
<a-input :placeholder="$t('label.new.secondaryip.description')" v-model="newSecondaryIp"></a-input> <a-input :placeholder="$t('label.new.secondaryip.description')" v-model="newSecondaryIp" autoFocus></a-input>
<div style="margin-top: 10px; display: flex; justify-content:flex-end;"> <div style="margin-top: 10px; display: flex; justify-content:flex-end;">
<a-button @click="submitSecondaryIP" type="primary" style="margin-right: 10px;">{{ $t('label.add.secondary.ip') }}</a-button> <a-button @click="submitSecondaryIP" type="primary" style="margin-right: 10px;">{{ $t('label.add.secondary.ip') }}</a-button>
<a-button @click="closeModals">{{ $t('label.close') }}</a-button> <a-button @click="closeModals">{{ $t('label.close') }}</a-button>

View File

@ -21,7 +21,8 @@
:placeholder="$t('label.search')" :placeholder="$t('label.search')"
v-model="searchQuery" v-model="searchQuery"
style="margin-bottom: 10px;" style="margin-bottom: 10px;"
@search="fetchData" /> @search="fetchData"
autoFocus />
<a-table <a-table
size="small" size="small"
style="overflow-y: auto" style="overflow-y: auto"

View File

@ -45,7 +45,8 @@
} }
}] }]
}]" }]"
:placeholder="apiParams.size.description"/> :placeholder="apiParams.size.description"
autoFocus />
</a-form-item> </a-form-item>
<a-form-item> <a-form-item>
<span slot="label"> <span slot="label">

View File

@ -43,7 +43,8 @@
}" }"
:loading="podsLoading" :loading="podsLoading"
:placeholder="apiParams.podid.description" :placeholder="apiParams.podid.description"
@change="handlePodChange"> @change="handlePodChange"
:autoFocus="this.$store.getters.userInfo.roletype === 'Admin'">
<a-select-option v-for="pod in this.pods" :key="pod.id"> <a-select-option v-for="pod in this.pods" :key="pod.id">
{{ pod.name }} {{ pod.name }}
</a-select-option> </a-select-option>

View File

@ -44,7 +44,8 @@
return option.componentOptions.children[0].text.toLowerCase().indexOf(input.toLowerCase()) >= 0 return option.componentOptions.children[0].text.toLowerCase().indexOf(input.toLowerCase()) >= 0
}" }"
:loading="kubernetesVersionLoading" :loading="kubernetesVersionLoading"
:placeholder="apiParams.kubernetesversionid.description"> :placeholder="apiParams.kubernetesversionid.description"
autoFocus >
<a-select-option v-for="(opt, optIndex) in this.kubernetesVersions" :key="optIndex"> <a-select-option v-for="(opt, optIndex) in this.kubernetesVersions" :key="optIndex">
{{ opt.name || opt.description }} {{ opt.name || opt.description }}
</a-select-option> </a-select-option>

View File

@ -61,7 +61,8 @@
rules: [{required: true, message: $t('message.error.required.input')}] rules: [{required: true, message: $t('message.error.required.input')}]
}]" }]"
:min="1" :min="1"
:max="59"/> :max="59"
autoFocus />
</a-tooltip> </a-tooltip>
</a-form-item> </a-form-item>
</a-col> </a-col>

View File

@ -21,7 +21,8 @@
style="width: 25vw;float: right;margin-bottom: 10px; z-index: 8" style="width: 25vw;float: right;margin-bottom: 10px; z-index: 8"
:placeholder="$t('label.search')" :placeholder="$t('label.search')"
v-model="filter" v-model="filter"
@search="handleSearch" /> @search="handleSearch"
autoFocus />
<a-table <a-table
:columns="columns" :columns="columns"
:dataSource="tableSource" :dataSource="tableSource"
@ -63,6 +64,10 @@ export default {
type: Array, type: Array,
default: () => [] default: () => []
}, },
selectedTemplate: {
type: Object,
default: () => {}
},
rowCount: { rowCount: {
type: Number, type: Number,
default: () => 0 default: () => 0
@ -161,6 +166,9 @@ export default {
(item.iscustomized === true && maxMemory < this.minimumMemory))) { (item.iscustomized === true && maxMemory < this.minimumMemory))) {
disabled = true disabled = true
} }
if (this.selectedTemplate && this.selectedTemplate.hypervisor === 'VMware' && this.selectedTemplate.deployasis && item.rootdisksize) {
disabled = true
}
return { return {
key: item.id, key: item.id,
name: item.name, name: item.name,
@ -238,6 +246,9 @@ export default {
return { return {
on: { on: {
click: () => { click: () => {
if (record.disabled) {
return
}
this.selectedRowKeys = [record.key] this.selectedRowKeys = [record.key]
this.$emit('select-compute-item', record.key) this.$emit('select-compute-item', record.key)
} }

View File

@ -35,6 +35,7 @@
</a-col> </a-col>
<a-col :md="4" :lg="4"> <a-col :md="4" :lg="4">
<a-input-number <a-input-number
:autoFocus="isConstrained"
v-model="cpuNumberInputValue" v-model="cpuNumberInputValue"
@change="($event) => updateComputeCpuNumber($event)" @change="($event) => updateComputeCpuNumber($event)"
/> />
@ -48,6 +49,7 @@
:validate-status="errors.cpuspeed.status" :validate-status="errors.cpuspeed.status"
:help="errors.cpuspeed.message"> :help="errors.cpuspeed.message">
<a-input-number <a-input-number
:autoFocus="!isConstrained"
v-model="cpuSpeedInputValue" v-model="cpuSpeedInputValue"
@change="($event) => updateComputeCpuSpeed($event)" @change="($event) => updateComputeCpuSpeed($event)"
/> />

View File

@ -23,6 +23,7 @@
<a-col :md="4" :lg="4"> <a-col :md="4" :lg="4">
<span style="display: inline-flex"> <span style="display: inline-flex">
<a-input-number <a-input-number
autoFocus
v-model="inputValue" v-model="inputValue"
@change="($event) => updateDiskSize($event)" @change="($event) => updateDiskSize($event)"
/> />

View File

@ -28,6 +28,7 @@
<span slot="offering" slot-scope="text, record"> <span slot="offering" slot-scope="text, record">
<a-select <a-select
autoFocus
v-if="validOfferings[record.id] && validOfferings[record.id].length > 0" v-if="validOfferings[record.id] && validOfferings[record.id].length > 0"
@change="updateOffering($event, record.id)" @change="updateOffering($event, record.id)"
:defaultValue="validOfferings[record.id][0].id"> :defaultValue="validOfferings[record.id][0].id">

View File

@ -30,9 +30,10 @@
<div>{{ text }}</div> <div>{{ text }}</div>
<small v-if="record.type!=='L2'">{{ $t('label.cidr') + ': ' + record.cidr }}</small> <small v-if="record.type!=='L2'">{{ $t('label.cidr') + ': ' + record.cidr }}</small>
</template> </template>
<template slot="ipAddress" slot-scope="text, record"> <template slot="ipAddress" slot-scope="text, record, index">
<a-form-item v-if="record.type!=='L2'"> <a-form-item v-if="record.type!=='L2' && index === 0">
<a-input <a-input
:autoFocus="record.type!=='L2'"
style="width: 150px;" style="width: 150px;"
v-decorator="['ipAddress' + record.id, { v-decorator="['ipAddress' + record.id, {
rules: [{ rules: [{
@ -49,9 +50,10 @@
</a-input> </a-input>
</a-form-item> </a-form-item>
</template> </template>
<template slot="macAddress" slot-scope="text, record"> <template slot="macAddress" slot-scope="text, record, index">
<a-form-item> <a-form-item>
<a-input <a-input
:autoFocus="record.type==='L2' && index === 0"
style="width: 150px;" style="width: 150px;"
:placeholder="$t('label.macaddress')" :placeholder="$t('label.macaddress')"
v-decorator="[`macAddress` + record.id, { v-decorator="[`macAddress` + record.id, {

View File

@ -31,7 +31,8 @@
initialValue: selectedRole, initialValue: selectedRole,
rules: [{ required: true, message: $t('message.error.select') }] }]" rules: [{ required: true, message: $t('message.error.select') }] }]"
:loading="roleLoading" :loading="roleLoading"
:placeholder="apiParams.roleid.description"> :placeholder="apiParams.roleid.description"
autoFocus>
<a-select-option v-for="role in roles" :key="role.id"> <a-select-option v-for="role in roles" :key="role.id">
{{ role.name + ' (' + role.type + ')' }} {{ role.name + ' (' + role.type + ')' }}
</a-select-option> </a-select-option>

View File

@ -50,7 +50,7 @@
@submit="handleSubmit" @submit="handleSubmit"
layout="vertical" > layout="vertical" >
<a-form-item :label="$t('label.filterby')"> <a-form-item :label="$t('label.filterby')">
<a-select @change="fetchListLdapUsers" v-model="selectedFilter" > <a-select @change="fetchListLdapUsers" v-model="selectedFilter" autoFocus >
<a-select-option v-for="opt in filters" :key="opt.id" > <a-select-option v-for="opt in filters" :key="opt.id" >
{{ opt.name }} {{ opt.name }}
</a-select-option> </a-select-option>

View File

@ -30,7 +30,8 @@
v-decorator="['username', { v-decorator="['username', {
rules: [{ required: true, message: $t('message.error.required.input') }] rules: [{ required: true, message: $t('message.error.required.input') }]
}]" }]"
:placeholder="apiParams.username.description" /> :placeholder="apiParams.username.description"
autoFocus/>
</a-form-item> </a-form-item>
<a-row :gutter="12"> <a-row :gutter="12">
<a-col :md="24" :lg="12"> <a-col :md="24" :lg="12">

View File

@ -33,7 +33,8 @@
v-decorator="['currentpassword', { v-decorator="['currentpassword', {
rules: [{ required: true, message: $t('message.error.current.password') }] rules: [{ required: true, message: $t('message.error.current.password') }]
}]" }]"
:placeholder="$t('message.error.current.password')"/> :placeholder="$t('message.error.current.password')"
autoFocus />
</a-form-item> </a-form-item>
<a-form-item> <a-form-item>
<span slot="label"> <span slot="label">

View File

@ -25,6 +25,7 @@
}]" }]"
:checked="isSamlEnabled" :checked="isSamlEnabled"
@change="val => { isSamlEnabled = val }" @change="val => { isSamlEnabled = val }"
autoFocus
/> />
</a-form-item> </a-form-item>
<a-form-item :label="$t('label.samlentity')"> <a-form-item :label="$t('label.samlentity')">

View File

@ -33,7 +33,8 @@
v-decorator="['name', { v-decorator="['name', {
rules: [{ required: true, message: $t('message.error.required.input') }] rules: [{ required: true, message: $t('message.error.required.input') }]
}]" }]"
:placeholder="createRoleApiParams.name.description" /> :placeholder="createRoleApiParams.name.description"
autoFocus />
</a-form-item> </a-form-item>
<a-form-item> <a-form-item>

View File

@ -68,6 +68,7 @@
rules: [{ required: field.required, message: $t('message.error.select') }] rules: [{ required: field.required, message: $t('message.error.select') }]
}]" }]"
:placeholder="field.description" :placeholder="field.description"
:autoFocus="fieldIndex === firstIndex"
> >
<a-select-option v-for="(opt, optIndex) in action.mapping[field.name].options" :key="optIndex"> <a-select-option v-for="(opt, optIndex) in action.mapping[field.name].options" :key="optIndex">
{{ opt }} {{ opt }}
@ -87,6 +88,7 @@
:filterOption="(input, option) => { :filterOption="(input, option) => {
return option.componentOptions.children[0].text.toLowerCase().indexOf(input.toLowerCase()) >= 0 return option.componentOptions.children[0].text.toLowerCase().indexOf(input.toLowerCase()) >= 0
}" }"
:autoFocus="fieldIndex === firstIndex"
> >
<a-select-option v-for="(opt, optIndex) in field.opts" :key="optIndex"> <a-select-option v-for="(opt, optIndex) in field.opts" :key="optIndex">
{{ opt.name || opt.description || opt.traffictype || opt.publicip }} {{ opt.name || opt.description || opt.traffictype || opt.publicip }}
@ -101,6 +103,7 @@
rules: [{ required: field.required, message: $t('message.error.select') }] rules: [{ required: field.required, message: $t('message.error.select') }]
}]" }]"
:placeholder="field.description" :placeholder="field.description"
:autoFocus="fieldIndex === firstIndex"
> >
<a-select-option v-for="(opt, optIndex) in field.opts" :key="optIndex"> <a-select-option v-for="(opt, optIndex) in field.opts" :key="optIndex">
{{ opt.name && opt.type ? opt.name + ' (' + opt.type + ')' : opt.name || opt.description }} {{ opt.name && opt.type ? opt.name + ' (' + opt.type + ')' : opt.name || opt.description }}
@ -113,6 +116,7 @@
rules: [{ required: field.required, message: `${$t('message.validate.number')}` }] rules: [{ required: field.required, message: `${$t('message.validate.number')}` }]
}]" }]"
:placeholder="field.description" :placeholder="field.description"
:autoFocus="fieldIndex === firstIndex"
/> />
</span> </span>
<span v-else> <span v-else>
@ -120,7 +124,8 @@
v-decorator="[field.name, { v-decorator="[field.name, {
rules: [{ required: field.required, message: $t('message.error.required.input') }] rules: [{ required: field.required, message: $t('message.error.required.input') }]
}]" }]"
:placeholder="field.description" /> :placeholder="field.description"
:autoFocus="fieldIndex === firstIndex" />
</span> </span>
</a-form-item> </a-form-item>
</a-form> </a-form>
@ -151,6 +156,16 @@ export default {
beforeCreate () { beforeCreate () {
this.form = this.$form.createForm(this) this.form = this.$form.createForm(this)
}, },
created () {
this.firstIndex = 0
for (let fieldIndex = 0; fieldIndex < this.action.paramFields.length; fieldIndex++) {
const field = this.action.paramFields[fieldIndex]
if (!(this.action.mapping && field.name in this.action.mapping && this.action.mapping[field.name].value)) {
this.firstIndex = fieldIndex
break
}
}
},
mounted () { mounted () {
if (this.action.dataView && this.action.icon === 'edit') { if (this.action.dataView && this.action.icon === 'edit') {
this.fillEditFormFieldValues() this.fillEditFormFieldValues()

View File

@ -30,7 +30,8 @@
v-decorator="['username', { v-decorator="['username', {
rules: [{ required: true, message: $t('message.error.required.input') }] rules: [{ required: true, message: $t('message.error.required.input') }]
}]" }]"
:placeholder="apiParams.username.description" /> :placeholder="apiParams.username.description"
autoFocus />
</a-form-item> </a-form-item>
<a-form-item> <a-form-item>
<span slot="label"> <span slot="label">

View File

@ -62,7 +62,8 @@
v-decorator="['name', { v-decorator="['name', {
rules: [{ required: true, message: $t('message.error.required.input') }] rules: [{ required: true, message: $t('message.error.required.input') }]
}]" }]"
:placeholder="importRoleApiParams.name.description" /> :placeholder="importRoleApiParams.name.description"
autoFocus />
</a-form-item> </a-form-item>
<a-form-item> <a-form-item>

View File

@ -18,7 +18,8 @@
<template> <template>
<a-select <a-select
:value="defaultValue" :value="defaultValue"
@change="handleChange"> @change="handleChange"
autoFocus>
<a-select-option value="allow">{{ $t('label.allow') }}</a-select-option> <a-select-option value="allow">{{ $t('label.allow') }}</a-select-option>
<a-select-option value="deny">{{ $t('label.deny') }}</a-select-option> <a-select-option value="deny">{{ $t('label.deny') }}</a-select-option>
</a-select> </a-select>

View File

@ -33,7 +33,8 @@
v-decorator="['semanticversion', { v-decorator="['semanticversion', {
rules: [{ required: true, message: $t('message.error.kuberversion') }] rules: [{ required: true, message: $t('message.error.kuberversion') }]
}]" }]"
:placeholder="apiParams.semanticversion.description"/> :placeholder="apiParams.semanticversion.description"
autoFocus />
</a-form-item> </a-form-item>
<a-form-item> <a-form-item>
<span slot="label"> <span slot="label">

View File

@ -108,7 +108,8 @@
:filterOption="(input, option) => { :filterOption="(input, option) => {
return option.componentOptions.children[0].text.toLowerCase().indexOf(input.toLowerCase()) >= 0 return option.componentOptions.children[0].text.toLowerCase().indexOf(input.toLowerCase()) >= 0
}" }"
:loading="zoneLoading"> :loading="zoneLoading"
autoFocus>
<a-select-option v-for="zone in zones" :key="zone.id"> <a-select-option v-for="zone in zones" :key="zone.id">
{{ zone.name }} {{ zone.name }}
</a-select-option> </a-select-option>

View File

@ -29,7 +29,7 @@
layout="vertical"> layout="vertical">
<a-form-item v-if="currentForm === 'Create'" :label="$t('label.url')"> <a-form-item v-if="currentForm === 'Create'" :label="$t('label.url')">
<a-input <a-input
autoFocus :autoFocus="currentForm === 'Create'"
v-decorator="['url', { v-decorator="['url', {
rules: [{ required: true, message: `${this.$t('label.upload.iso.from.local')}` }] rules: [{ required: true, message: `${this.$t('label.upload.iso.from.local')}` }]
}]" }]"
@ -57,7 +57,8 @@
v-decorator="['name', { v-decorator="['name', {
rules: [{ required: true, message: `${this.$t('message.error.required.input')}` }] rules: [{ required: true, message: `${this.$t('message.error.required.input')}` }]
}]" }]"
:placeholder="apiParams.name.description" /> :placeholder="apiParams.name.description"
:autoFocus="currentForm !== 'Create'" />
</a-form-item> </a-form-item>
<a-form-item :label="$t('label.displaytext')"> <a-form-item :label="$t('label.displaytext')">

View File

@ -31,7 +31,7 @@
<a-row :gutter="12"> <a-row :gutter="12">
<a-form-item :label="$t('label.url')"> <a-form-item :label="$t('label.url')">
<a-input <a-input
autoFocus :autoFocus="currentForm === 'Create'"
v-decorator="['url', { v-decorator="['url', {
rules: [{ required: true, message: `${this.$t('message.error.required.input')}` }] rules: [{ required: true, message: `${this.$t('message.error.required.input')}` }]
}]" }]"
@ -64,7 +64,8 @@
v-decorator="['name', { v-decorator="['name', {
rules: [{ required: true, message: `${this.$t('message.error.required.input')}` }] rules: [{ required: true, message: `${this.$t('message.error.required.input')}` }]
}]" }]"
:placeholder="apiParams.name.description" /> :placeholder="apiParams.name.description"
:autoFocus="currentForm !== 'Create'"/>
</a-form-item> </a-form-item>
</a-row> </a-row>
<a-row :gutter="12"> <a-row :gutter="12">

View File

@ -100,7 +100,8 @@
:filterOption="(input, option) => { :filterOption="(input, option) => {
return option.componentOptions.children[0].text.toLowerCase().indexOf(input.toLowerCase()) >= 0 return option.componentOptions.children[0].text.toLowerCase().indexOf(input.toLowerCase()) >= 0
}" }"
:loading="zoneLoading"> :loading="zoneLoading"
autoFocus>
<a-select-option v-for="zone in zones" :key="zone.id"> <a-select-option v-for="zone in zones" :key="zone.id">
{{ zone.name }} {{ zone.name }}
</a-select-option> </a-select-option>

View File

@ -34,7 +34,8 @@
return option.componentOptions.children[0].text.toLowerCase().indexOf(input.toLowerCase()) >= 0 return option.componentOptions.children[0].text.toLowerCase().indexOf(input.toLowerCase()) >= 0
}" }"
:loading="stateLoading" :loading="stateLoading"
:placeholder="apiParams.state.description"> :placeholder="apiParams.state.description"
autoFocus >
<a-select-option v-for="(opt, optIndex) in this.states" :key="optIndex"> <a-select-option v-for="(opt, optIndex) in this.states" :key="optIndex">
{{ opt.name || opt.description }} {{ opt.name || opt.description }}
</a-select-option> </a-select-option>

View File

@ -23,7 +23,11 @@
<div class="form__item"> <div class="form__item">
<p class="form__label">{{ $t('label.operation') }}</p> <p class="form__label">{{ $t('label.operation') }}</p>
<a-select v-model="selectedOperation" :defaultValue="$t('label.add')" @change="fetchData"> <a-select
v-model="selectedOperation"
:defaultValue="$t('label.add')"
@change="fetchData"
autoFocus>
<a-select-option :value="$t('label.add')">{{ $t('label.add') }}</a-select-option> <a-select-option :value="$t('label.add')">{{ $t('label.add') }}</a-select-option>
<a-select-option :value="$t('label.remove')">{{ $t('label.remove') }}</a-select-option> <a-select-option :value="$t('label.remove')">{{ $t('label.remove') }}</a-select-option>
<a-select-option :value="$t('label.reset')">{{ $t('label.reset') }}</a-select-option> <a-select-option :value="$t('label.reset')">{{ $t('label.reset') }}</a-select-option>

View File

@ -26,7 +26,10 @@
<a-icon type="info-circle" style="color: rgba(0,0,0,.45)" /> <a-icon type="info-circle" style="color: rgba(0,0,0,.45)" />
</a-tooltip> </a-tooltip>
</span> </span>
<a-select v-decorator="['scope', { initialValue: 'cluster' }]" @change="val => { this.scope = val }"> <a-select
v-decorator="['scope', { initialValue: 'cluster' }]"
@change="val => { this.scope = val }"
autoFocus>
<a-select-option :value="'cluster'"> {{ $t('label.clusterid') }} </a-select-option> <a-select-option :value="'cluster'"> {{ $t('label.clusterid') }} </a-select-option>
<a-select-option :value="'zone'"> {{ $t('label.zoneid') }} </a-select-option> <a-select-option :value="'zone'"> {{ $t('label.zoneid') }} </a-select-option>
</a-select> </a-select>

View File

@ -20,7 +20,7 @@
<a-spin :spinning="loading"> <a-spin :spinning="loading">
<a-form :form="form" layout="vertical"> <a-form :form="form" layout="vertical">
<a-form-item :label="$t('label.name')"> <a-form-item :label="$t('label.name')">
<a-input v-decorator="['name']" /> <a-input v-decorator="['name']" autoFocus />
</a-form-item> </a-form-item>
<a-form-item :label="$t('label.providername')"> <a-form-item :label="$t('label.providername')">
<a-select <a-select

View File

@ -20,7 +20,7 @@
<div class="form"> <div class="form">
<div class="form__item"> <div class="form__item">
<div class="form__label"><span class="required">* </span>{{ $t('label.zonenamelabel') }}</div> <div class="form__label"><span class="required">* </span>{{ $t('label.zonenamelabel') }}</div>
<a-select v-model="zoneId" @change="fetchPods"> <a-select v-model="zoneId" @change="fetchPods" autoFocus>
<a-select-option <a-select-option
v-for="zone in zonesList" v-for="zone in zonesList"
:value="zone.id" :value="zone.id"

View File

@ -21,7 +21,7 @@
<div class="form__item"> <div class="form__item">
<div class="form__label"><span class="required">* </span>{{ $t('label.zonenamelabel') }}</div> <div class="form__label"><span class="required">* </span>{{ $t('label.zonenamelabel') }}</div>
<a-select v-model="zoneId" @change="fetchPods"> <a-select v-model="zoneId" @change="fetchPods" autoFocus>
<a-select-option <a-select-option
v-for="zone in zonesList" v-for="zone in zonesList"
:value="zone.id" :value="zone.id"

View File

@ -32,6 +32,7 @@
}]" }]"
:loading="loading" :loading="loading"
@change="val => { selectedStore = val }" @change="val => { selectedStore = val }"
autoFocus
> >
<a-select-option <a-select-option
v-for="store in imageStores" v-for="store in imageStores"

View File

@ -24,7 +24,8 @@
v-decorator="['zoneid', { v-decorator="['zoneid', {
initialValue: this.zoneId, initialValue: this.zoneId,
rules: [{ required: true, message: `${$t('label.required')}` }] } rules: [{ required: true, message: `${$t('label.required')}` }] }
]"> ]"
autoFocus>
<a-select-option <a-select-option
v-for="zone in zonesList" v-for="zone in zonesList"
:value="zone.id" :value="zone.id"

View File

@ -74,6 +74,7 @@
v-decorator="['range', { v-decorator="['range', {
rules: [{ required: true, message: `${$t('label.required')}` }] rules: [{ required: true, message: `${$t('label.required')}` }]
}]" }]"
autoFocus
></a-input> ></a-input>
</a-form-item> </a-form-item>

View File

@ -27,6 +27,7 @@
</a-tooltip> </a-tooltip>
</span> </span>
<a-select <a-select
autoFocus
v-decorator="['id', { v-decorator="['id', {
initialValue: selectedType, initialValue: selectedType,
rules: [{ required: true, message: $t('message.error.select') }] }]" rules: [{ required: true, message: $t('message.error.select') }] }]"

View File

@ -81,6 +81,7 @@
> >
<a-form-item :label="$t('label.podid')" class="form__item"> <a-form-item :label="$t('label.podid')" class="form__item">
<a-select <a-select
autoFocus
v-decorator="['pod', { v-decorator="['pod', {
rules: [{ required: true, message: `${$t('label.required')}` }] rules: [{ required: true, message: `${$t('label.required')}` }]
}]" }]"

View File

@ -117,7 +117,7 @@
<a-spin :spinning="domainsLoading"> <a-spin :spinning="domainsLoading">
<div style="margin-bottom: 10px;"> <div style="margin-bottom: 10px;">
<div class="list__label">{{ $t('label.account') }}:</div> <div class="list__label">{{ $t('label.account') }}:</div>
<a-input v-model="addAccount.account"></a-input> <a-input v-model="addAccount.account" autoFocus></a-input>
</div> </div>
<div> <div>
<div class="list__label">{{ $t('label.domain') }}:</div> <div class="list__label">{{ $t('label.domain') }}:</div>
@ -145,6 +145,7 @@
> >
<a-form-item :label="$t('label.gateway')" class="form__item"> <a-form-item :label="$t('label.gateway')" class="form__item">
<a-input <a-input
autoFocus
v-decorator="['gateway', { rules: [{ required: true, message: `${$t('label.required')}` }] }]"> v-decorator="['gateway', { rules: [{ required: true, message: `${$t('label.required')}` }] }]">
</a-input> </a-input>
</a-form-item> </a-form-item>

View File

@ -79,6 +79,7 @@
> >
<a-form-item :label="$t('label.podid')" class="form__item"> <a-form-item :label="$t('label.podid')" class="form__item">
<a-select <a-select
autoFocus
v-decorator="['pod', { v-decorator="['pod', {
rules: [{ required: true, message: `${$t('label.required')}` }] rules: [{ required: true, message: `${$t('label.required')}` }]
}]" }]"

View File

@ -80,6 +80,7 @@
:label="$t('label.' + field.name)"> :label="$t('label.' + field.name)">
<span v-if="field.name==='password'"> <span v-if="field.name==='password'">
<a-input-password <a-input-password
:autoFocus="index===0"
v-decorator="[field.name, { v-decorator="[field.name, {
rules: [ rules: [
{ {
@ -92,6 +93,7 @@
</span> </span>
<span v-else-if="field.type==='boolean'"> <span v-else-if="field.type==='boolean'">
<a-switch <a-switch
:autoFocus="index===0"
v-decorator="[field.name, { v-decorator="[field.name, {
rules: [{ rules: [{
required: field.required, required: field.required,
@ -103,6 +105,7 @@
</span> </span>
<span v-else-if="field.type==='uuid'"> <span v-else-if="field.type==='uuid'">
<a-select <a-select
:autoFocus="index===0"
v-decorator="[field.name, { v-decorator="[field.name, {
rules: [{ rules: [{
required: field.required, required: field.required,
@ -118,6 +121,7 @@
</span> </span>
<span v-else> <span v-else>
<a-input <a-input
:autoFocus="index===0"
v-decorator="[field.name, { v-decorator="[field.name, {
rules: [ rules: [
{ {

View File

@ -25,6 +25,7 @@
<a-col :md="24" :lg="24"> <a-col :md="24" :lg="24">
<a-form-item :label="$t('label.ip')"> <a-form-item :label="$t('label.ip')">
<a-input <a-input
autoFocus
v-decorator="['ip', { v-decorator="['ip', {
rules: [{ required: true, message: $t('message.error.required.input') }] rules: [{ required: true, message: $t('message.error.required.input') }]
}]" /> }]" />

View File

@ -25,6 +25,7 @@
<a-col :md="24" :lg="24"> <a-col :md="24" :lg="24">
<a-form-item :label="$t('label.ip')"> <a-form-item :label="$t('label.ip')">
<a-input <a-input
autoFocus
v-decorator="['ip', { v-decorator="['ip', {
rules: [{ required: true, message: $t('message.error.required.input') }] rules: [{ required: true, message: $t('message.error.required.input') }]
}]" /> }]" />

View File

@ -25,6 +25,7 @@
<a-col :md="24" :lg="24"> <a-col :md="24" :lg="24">
<a-form-item :label="$t('label.ip')"> <a-form-item :label="$t('label.ip')">
<a-input <a-input
autoFocus
v-decorator="['ip', { v-decorator="['ip', {
rules: [{ required: true, message: $t('message.error.required.input') }] rules: [{ required: true, message: $t('message.error.required.input') }]
}]" /> }]" />

View File

@ -25,6 +25,7 @@
<a-col :md="24" :lg="24"> <a-col :md="24" :lg="24">
<a-form-item :label="$t('label.ip')"> <a-form-item :label="$t('label.ip')">
<a-input <a-input
autoFocus
v-decorator="['ip', { v-decorator="['ip', {
rules: [{ required: true, message: $t('message.error.required.input') }] rules: [{ required: true, message: $t('message.error.required.input') }]
}]" /> }]" />

View File

@ -25,6 +25,7 @@
<a-col :md="24" :lg="24"> <a-col :md="24" :lg="24">
<a-form-item :label="$t('label.ip')"> <a-form-item :label="$t('label.ip')">
<a-input <a-input
autoFocus
v-decorator="['ip', { v-decorator="['ip', {
rules: [{ required: true, message: $t('message.error.required.input') }] rules: [{ required: true, message: $t('message.error.required.input') }]
}]" /> }]" />

View File

@ -63,7 +63,8 @@
</span> </span>
<a-switch <a-switch
v-decorator="[$t('performfreshchecks')]" v-decorator="[$t('performfreshchecks')]"
:placeholder="apiParams.performfreshchecks.description" /> :placeholder="apiParams.performfreshchecks.description"
autoFocus/>
</a-form-item> </a-form-item>
</a-form> </a-form>
</a-spin> </a-spin>

View File

@ -46,6 +46,7 @@
}] }]
}]" }]"
style="width: 100%;" style="width: 100%;"
autoFocus
/> />
</a-form-item> </a-form-item>
<span :style="{ display: 'inline-block', width: '24px', textAlign: 'center' }"> <span :style="{ display: 'inline-block', width: '24px', textAlign: 'center' }">

View File

@ -42,6 +42,7 @@
rules: [{ required: true, message: $t('message.error.gateway') }] rules: [{ required: true, message: $t('message.error.gateway') }]
}]" }]"
:placeholder="$t('label.gateway')" :placeholder="$t('label.gateway')"
autoFocus
/> />
</a-form-item> </a-form-item>
<a-form-item :style="{ display: 'inline-block', width: '14%' }"> <a-form-item :style="{ display: 'inline-block', width: '14%' }">

View File

@ -45,6 +45,7 @@
] ]
}]" }]"
:allowClear="true" :allowClear="true"
:autoFocus="index === 0"
> >
<a-select-option <a-select-option
v-for="option in field.options" v-for="option in field.options"
@ -58,6 +59,7 @@
v-else-if="field.switch" v-else-if="field.switch"
v-decorator="[field.key]" v-decorator="[field.key]"
:default-checked="isChecked(field)" :default-checked="isChecked(field)"
:autoFocus="index === 0"
/> />
<a-input <a-input
v-else-if="field.password" v-else-if="field.password"
@ -71,6 +73,7 @@
} }
] ]
}]" }]"
:autoFocus="index === 0"
/> />
<a-input <a-input
v-else v-else
@ -89,6 +92,7 @@
} }
] ]
}]" }]"
:autoFocus="index === 0"
/> />
</a-form-item> </a-form-item>
</a-form> </a-form>

View File

@ -29,7 +29,7 @@
:pagination="false" :pagination="false"
style="margin-bottom: 24px;"> style="margin-bottom: 24px;">
<template slot="name" slot-scope="text, record"> <template slot="name" slot-scope="text, record">
<a-input :value="text" @change="e => onCellChange(record.key, 'name', e.target.value)" /> <a-input :value="text" @change="e => onCellChange(record.key, 'name', e.target.value)" autoFocus />
</template> </template>
<template slot="isolationMethod" slot-scope="text, record"> <template slot="isolationMethod" slot-scope="text, record">
<a-select <a-select

View File

@ -35,6 +35,7 @@
initialValue: name initialValue: name
}] }]
}]" }]"
autoFocus
/> />
</a-form-item> </a-form-item>
<a-form-item <a-form-item

View File

@ -50,6 +50,7 @@
v-decorator="['securityGroupsEnabled', { valuePropName: 'checked' }]" v-decorator="['securityGroupsEnabled', { valuePropName: 'checked' }]"
:value="securityGroupsEnabled" :value="securityGroupsEnabled"
:disabled="!isAdvancedZone" :disabled="!isAdvancedZone"
autoFocus
/> />
</a-form-item> </a-form-item>
<span>{{ $t('label.menu.security.groups') }}</span> <span>{{ $t('label.menu.security.groups') }}</span>

View File

@ -104,7 +104,9 @@
<div class="add-tags__input"> <div class="add-tags__input">
<p class="add-tags__label">{{ $t('label.key') }}</p> <p class="add-tags__label">{{ $t('label.key') }}</p>
<a-form-item> <a-form-item>
<a-input v-decorator="['key', { rules: [{ required: true, message: $t('message.specifiy.tag.key')}] }]" /> <a-input
autoFocus
v-decorator="['key', { rules: [{ required: true, message: $t('message.specifiy.tag.key')}] }]" />
</a-form-item> </a-form-item>
</div> </div>
<div class="add-tags__input"> <div class="add-tags__input">
@ -133,7 +135,7 @@
<a-modal :title="ruleModalTitle" :maskClosable="false" v-model="ruleModalVisible" @ok="handleRuleModalForm"> <a-modal :title="ruleModalTitle" :maskClosable="false" v-model="ruleModalVisible" @ok="handleRuleModalForm">
<a-form :form="ruleForm" @submit="handleRuleModalForm"> <a-form :form="ruleForm" @submit="handleRuleModalForm">
<a-form-item :label="$t('label.number')"> <a-form-item :label="$t('label.number')">
<a-input-number style="width: 100%" v-decorator="['number']" /> <a-input-number autoFocus style="width: 100%" v-decorator="['number']" />
</a-form-item> </a-form-item>
<a-form-item :label="$t('label.cidrlist')"> <a-form-item :label="$t('label.cidrlist')">
<a-input v-decorator="['cidrlist']" /> <a-input v-decorator="['cidrlist']" />

View File

@ -34,7 +34,8 @@
v-decorator="['name', { v-decorator="['name', {
rules: [{ required: true, message: $t('message.error.name') }] rules: [{ required: true, message: $t('message.error.name') }]
}]" }]"
:placeholder="this.$t('label.name')"/> :placeholder="this.$t('label.name')"
autoFocus/>
</a-form-item> </a-form-item>
<a-form-item> <a-form-item>
<span slot="label"> <span slot="label">

View File

@ -34,7 +34,8 @@
v-decorator="['name', { v-decorator="['name', {
rules: [{ required: true, message: $t('message.error.name') }] rules: [{ required: true, message: $t('message.error.name') }]
}]" }]"
:placeholder="this.$t('label.name')"/> :placeholder="this.$t('label.name')"
autoFocus/>
</a-form-item> </a-form-item>
<a-form-item> <a-form-item>
<span slot="label"> <span slot="label">

View File

@ -34,7 +34,8 @@
v-decorator="['name', { v-decorator="['name', {
rules: [{ required: true, message: $t('message.error.name') }] rules: [{ required: true, message: $t('message.error.name') }]
}]" }]"
:placeholder="this.$t('label.name')"/> :placeholder="this.$t('label.name')"
autoFocus />
</a-form-item> </a-form-item>
<a-form-item> <a-form-item>
<span slot="label"> <span slot="label">

View File

@ -31,6 +31,7 @@
</a-tooltip> </a-tooltip>
</span> </span>
<a-input <a-input
autoFocus
v-decorator="['gateway', { v-decorator="['gateway', {
rules: [{ required: true, message: $t('message.error.gateway') }] rules: [{ required: true, message: $t('message.error.gateway') }]
}]" }]"

View File

@ -31,7 +31,8 @@
v-decorator="['name', { v-decorator="['name', {
rules: [{ required: true, message: $t('message.error.required.input') }] rules: [{ required: true, message: $t('message.error.required.input') }]
}]" }]"
:placeholder="apiParams.name.description"/> :placeholder="apiParams.name.description"
autoFocus/>
</a-form-item> </a-form-item>
<a-form-item> <a-form-item>
<span slot="label"> <span slot="label">

View File

@ -31,7 +31,8 @@
rules: [{ required: true, message: `${$t('label.required')}` }], rules: [{ required: true, message: `${$t('label.required')}` }],
} }
]" ]"
:placeholder="$t('label.vpncustomergatewayname')" /> :placeholder="$t('label.vpncustomergatewayname')"
autoFocus />
</a-form-item> </a-form-item>
<a-form-item> <a-form-item>
<span slot="label"> <span slot="label">

View File

@ -21,7 +21,7 @@
<div class="form"> <div class="form">
<div class="form__item"> <div class="form__item">
<div class="form__label">{{ $t('label.sourcecidr') }}</div> <div class="form__label">{{ $t('label.sourcecidr') }}</div>
<a-input v-model="newRule.cidrlist"></a-input> <a-input v-model="newRule.cidrlist" autoFocus></a-input>
</div> </div>
<div class="form__item"> <div class="form__item">
<div class="form__label">{{ $t('label.destcidr') }}</div> <div class="form__label">{{ $t('label.destcidr') }}</div>

View File

@ -19,7 +19,11 @@
<div class="list" :loading="loading"> <div class="list" :loading="loading">
<div class="list__header"> <div class="list__header">
<div class="list__header__col" v-if="tiersSelect"> <div class="list__header__col" v-if="tiersSelect">
<a-select @change="handleTierSelect" v-model="vpcTiers" :placeholder="$t('label.select.tier')"> <a-select
autoFocus
@change="handleTierSelect"
v-model="vpcTiers"
:placeholder="$t('label.select.tier')">
<a-select-option v-for="network in networksList" :key="network.id" :value="network.id"> <a-select-option v-for="network in networksList" :key="network.id" :value="network.id">
{{ network.name }} {{ network.name }}
</a-select-option> </a-select-option>

View File

@ -21,7 +21,7 @@
<div class="form"> <div class="form">
<div class="form__item"> <div class="form__item">
<div class="form__label">{{ $t('label.sourcecidr') }}</div> <div class="form__label">{{ $t('label.sourcecidr') }}</div>
<a-input v-model="newRule.cidrlist"></a-input> <a-input autoFocus v-model="newRule.cidrlist"></a-input>
</div> </div>
<div class="form__item"> <div class="form__item">
<div class="form__label">{{ $t('label.protocol') }}</div> <div class="form__label">{{ $t('label.protocol') }}</div>
@ -110,7 +110,7 @@
<div class="add-tags"> <div class="add-tags">
<div class="add-tags__input"> <div class="add-tags__input">
<p class="add-tags__label">{{ $t('label.key') }}</p> <p class="add-tags__label">{{ $t('label.key') }}</p>
<a-input v-model="newTag.key"></a-input> <a-input autoFocus v-model="newTag.key"></a-input>
</div> </div>
<div class="add-tags__input"> <div class="add-tags__input">
<p class="add-tags__label">{{ $t('label.value') }}</p> <p class="add-tags__label">{{ $t('label.value') }}</p>

View File

@ -30,7 +30,11 @@
<div class="form"> <div class="form">
<div class="form__item"> <div class="form__item">
<div class="form__label">{{ $t('label.protocol') }}</div> <div class="form__label">{{ $t('label.protocol') }}</div>
<a-select v-model="newRule.protocol" style="width: 100%;" @change="resetRulePorts"> <a-select
autoFocus
v-model="newRule.protocol"
style="width: 100%;"
@change="resetRulePorts">
<a-select-option value="tcp">{{ $t('label.tcp') | capitalise }}</a-select-option> <a-select-option value="tcp">{{ $t('label.tcp') | capitalise }}</a-select-option>
<a-select-option value="udp">{{ $t('label.udp') | capitalise }}</a-select-option> <a-select-option value="udp">{{ $t('label.udp') | capitalise }}</a-select-option>
<a-select-option value="icmp">{{ $t('label.icmp') | capitalise }}</a-select-option> <a-select-option value="icmp">{{ $t('label.icmp') | capitalise }}</a-select-option>
@ -127,7 +131,9 @@
<div class="add-tags__input"> <div class="add-tags__input">
<p class="add-tags__label">{{ $t('label.key') }}</p> <p class="add-tags__label">{{ $t('label.key') }}</p>
<a-form-item> <a-form-item>
<a-input v-decorator="['key', { rules: [{ required: true, message: this.$t('message.specifiy.tag.key')}] }]" /> <a-input
autoFocus
v-decorator="['key', { rules: [{ required: true, message: this.$t('message.specifiy.tag.key')}] }]" />
</a-form-item> </a-form-item>
</div> </div>
<div class="add-tags__input"> <div class="add-tags__input">

View File

@ -37,6 +37,7 @@
</span> </span>
<a-icon v-if="addVmModalNicLoading" type="loading"></a-icon> <a-icon v-if="addVmModalNicLoading" type="loading"></a-icon>
<a-select <a-select
:autoFocus="!addVmModalNicLoading && iLb.virtualmachineid[index] === vm.id && index === 0"
v-else-if="!addVmModalNicLoading && iLb.virtualmachineid[index] === vm.id" v-else-if="!addVmModalNicLoading && iLb.virtualmachineid[index] === vm.id"
mode="multiple" mode="multiple"
v-model="iLb.vmguestip[index]" v-model="iLb.vmguestip[index]"
@ -52,7 +53,10 @@
<span></span> <span></span>
<span>{{ vm.account }}</span> <span>{{ vm.account }}</span>
<span>{{ vm.zonename }}</span> <span>{{ vm.zonename }}</span>
<a-checkbox :value="vm.id" @change="e => fetchNics(e, index)" /> <a-checkbox
:autoFocus="!(!addVmModalNicLoading && iLb.virtualmachineid[index] === vm.id) && index === 0"
:value="vm.id"
@change="e => fetchNics(e, index)" />
</div> </div>
<a-divider/> <a-divider/>
<a-pagination <a-pagination

View File

@ -29,6 +29,7 @@
<div v-if="$route.path.startsWith('/vpc')"> <div v-if="$route.path.startsWith('/vpc')">
Select Tier: Select Tier:
<a-select <a-select
autoFocus
style="width: 40%; margin-left: 15px;margin-bottom: 15px" style="width: 40%; margin-left: 15px;margin-bottom: 15px"
:loading="fetchLoading" :loading="fetchLoading"
defaultActiveFirstOption defaultActiveFirstOption
@ -110,6 +111,7 @@
<a-alert :message="$t('message.action.acquire.ip')" type="warning" /> <a-alert :message="$t('message.action.acquire.ip')" type="warning" />
<a-form-item :label="$t('label.ipaddress')"> <a-form-item :label="$t('label.ipaddress')">
<a-select <a-select
autoFocus
style="width: 100%;" style="width: 100%;"
showSearch showSearch
v-model="acquireIp"> v-model="acquireIp">

View File

@ -21,7 +21,7 @@
<div class="form"> <div class="form">
<div class="form__item" ref="newRuleName"> <div class="form__item" ref="newRuleName">
<div class="form__label"><span class="form__required">*</span>{{ $t('label.name') }}</div> <div class="form__label"><span class="form__required">*</span>{{ $t('label.name') }}</div>
<a-input v-model="newRule.name"></a-input> <a-input autoFocus v-model="newRule.name"></a-input>
<span class="error-text">{{ $t('label.required') }}</span> <span class="error-text">{{ $t('label.required') }}</span>
</div> </div>
<div class="form__item" ref="newRulePublicPort"> <div class="form__item" ref="newRulePublicPort">
@ -154,7 +154,9 @@
<div class="add-tags__input"> <div class="add-tags__input">
<p class="add-tags__label">{{ $t('label.key') }}</p> <p class="add-tags__label">{{ $t('label.key') }}</p>
<a-form-item> <a-form-item>
<a-input v-decorator="['key', { rules: [{ required: true, message: this.$t('message.specifiy.tag.key')}] }]" /> <a-input
autoFocus
v-decorator="['key', { rules: [{ required: true, message: this.$t('message.specifiy.tag.key')}] }]" />
</a-form-item> </a-form-item>
</div> </div>
<div class="add-tags__input"> <div class="add-tags__input">
@ -193,7 +195,7 @@
<a-form :form="stickinessPolicyForm" @submit="handleSubmitStickinessForm" class="custom-ant-form"> <a-form :form="stickinessPolicyForm" @submit="handleSubmitStickinessForm" class="custom-ant-form">
<a-form-item :label="$t('label.stickiness.method')"> <a-form-item :label="$t('label.stickiness.method')">
<a-select v-decorator="['methodname']" @change="handleStickinessMethodSelectChange"> <a-select autoFocus v-decorator="['methodname']" @change="handleStickinessMethodSelectChange">
<a-select-option value="LbCookie">{{ $t('label.lb.cookie') }}</a-select-option> <a-select-option value="LbCookie">{{ $t('label.lb.cookie') }}</a-select-option>
<a-select-option value="AppCookie">{{ $t('label.app.cookie') }}</a-select-option> <a-select-option value="AppCookie">{{ $t('label.app.cookie') }}</a-select-option>
<a-select-option value="SourceBased">{{ $t('label.source.based') }}</a-select-option> <a-select-option value="SourceBased">{{ $t('label.source.based') }}</a-select-option>
@ -265,7 +267,7 @@
<div class="edit-rule" v-if="selectedRule"> <div class="edit-rule" v-if="selectedRule">
<div class="edit-rule__item"> <div class="edit-rule__item">
<p class="edit-rule__label">{{ $t('label.name') }}</p> <p class="edit-rule__label">{{ $t('label.name') }}</p>
<a-input v-model="editRuleDetails.name" /> <a-input autoFocus v-model="editRuleDetails.name" />
</div> </div>
<div class="edit-rule__item"> <div class="edit-rule__item">
<p class="edit-rule__label">{{ $t('label.algorithm') }}</p> <p class="edit-rule__label">{{ $t('label.algorithm') }}</p>
@ -304,6 +306,7 @@
v-if="'vpcid' in resource && !('associatednetworkid' in resource)"> v-if="'vpcid' in resource && !('associatednetworkid' in resource)">
<strong>{{ $t('label.select.tier') }} </strong> <strong>{{ $t('label.select.tier') }} </strong>
<a-select <a-select
:autoFocus="'vpcid' in resource && !('associatednetworkid' in resource)"
v-model="selectedTier" v-model="selectedTier"
@change="fetchVirtualMachines()" @change="fetchVirtualMachines()"
:placeholder="$t('label.select.tier')" > :placeholder="$t('label.select.tier')" >
@ -316,6 +319,7 @@
</a-select> </a-select>
</span> </span>
<a-input-search <a-input-search
:autoFocus="!('vpcid' in resource && !('associatednetworkid' in resource))"
class="input-search" class="input-search"
:placeholder="$t('label.search')" :placeholder="$t('label.search')"
v-model="searchQuery" v-model="searchQuery"

View File

@ -23,6 +23,7 @@
<div class="form__label">{{ $t('label.privateport') }}</div> <div class="form__label">{{ $t('label.privateport') }}</div>
<a-input-group class="form__item__input-container" compact> <a-input-group class="form__item__input-container" compact>
<a-input <a-input
autoFocus
v-model="newRule.privateport" v-model="newRule.privateport"
:placeholder="$t('label.start')" :placeholder="$t('label.start')"
style="border-right: 0; width: 60px; margin-right: 0;"></a-input> style="border-right: 0; width: 60px; margin-right: 0;"></a-input>
@ -136,7 +137,7 @@
<div class="add-tags"> <div class="add-tags">
<div class="add-tags__input"> <div class="add-tags__input">
<p class="add-tags__label">{{ $t('label.key') }}</p> <p class="add-tags__label">{{ $t('label.key') }}</p>
<a-input v-model="newTag.key"></a-input> <a-input autoFocus v-model="newTag.key"></a-input>
</div> </div>
<div class="add-tags__input"> <div class="add-tags__input">
<p class="add-tags__label">{{ $t('label.value') }}</p> <p class="add-tags__label">{{ $t('label.value') }}</p>
@ -176,6 +177,7 @@
v-if="'vpcid' in resource && !('associatednetworkid' in resource)"> v-if="'vpcid' in resource && !('associatednetworkid' in resource)">
<strong>{{ $t('label.select.tier') }} </strong> <strong>{{ $t('label.select.tier') }} </strong>
<a-select <a-select
:autoFocu="'vpcid' in resource && !('associatednetworkid' in resource)"
v-model="selectedTier" v-model="selectedTier"
@change="fetchVirtualMachines()" @change="fetchVirtualMachines()"
:placeholder="$t('label.select.tier')" > :placeholder="$t('label.select.tier')" >
@ -188,6 +190,7 @@
</a-select> </a-select>
</span> </span>
<a-input-search <a-input-search
:autoFocu="!('vpcid' in resource && !('associatednetworkid' in resource))"
class="input-search" class="input-search"
:placeholder="$t('label.search')" :placeholder="$t('label.search')"
v-model="searchQuery" v-model="searchQuery"

View File

@ -18,7 +18,7 @@
<template> <template>
<a-spin :spinning="componentLoading"> <a-spin :spinning="componentLoading">
<div class="new-route"> <div class="new-route">
<a-input v-model="newRoute" icon="plus" :placeholder="$t('label.cidr.destination.network')"></a-input> <a-input v-model="newRoute" icon="plus" :placeholder="$t('label.cidr.destination.network')" autoFocus></a-input>
<a-button type="primary" :disabled="!('createStaticRoute' in $store.getters.apis)" @click="handleAdd">{{ $t('label.add.route') }}</a-button> <a-button type="primary" :disabled="!('createStaticRoute' in $store.getters.apis)" @click="handleAdd">{{ $t('label.add.route') }}</a-button>
</div> </div>
@ -43,7 +43,9 @@
<div class="add-tags__input"> <div class="add-tags__input">
<p class="add-tags__label">{{ $t('label.key') }}</p> <p class="add-tags__label">{{ $t('label.key') }}</p>
<a-form-item> <a-form-item>
<a-input v-decorator="['key', { rules: [{ required: true, message: this.$t('message.specifiy.tag.key')}] }]" /> <a-input
autoFocus
v-decorator="['key', { rules: [{ required: true, message: this.$t('message.specifiy.tag.key')}] }]" />
</a-form-item> </a-form-item>
</div> </div>
<div class="add-tags__input"> <div class="add-tags__input">

View File

@ -76,7 +76,9 @@
@ok="handleNetworkAclFormSubmit"> @ok="handleNetworkAclFormSubmit">
<a-form @submit.prevent="handleNetworkAclFormSubmit" :form="networkAclForm"> <a-form @submit.prevent="handleNetworkAclFormSubmit" :form="networkAclForm">
<a-form-item :label="$t('label.add.list.name')"> <a-form-item :label="$t('label.add.list.name')">
<a-input v-decorator="['name', {rules: [{ required: true, message: `${$t('label.required')}` }]}]"></a-input> <a-input
v-decorator="['name', {rules: [{ required: true, message: `${$t('label.required')}` }]}]"
autoFocus></a-input>
</a-form-item> </a-form-item>
<a-form-item :label="$t('label.description')"> <a-form-item :label="$t('label.description')">
<a-input v-decorator="['description', {rules: [{ required: true, message: `${$t('label.required')}` }]}]"></a-input> <a-input v-decorator="['description', {rules: [{ required: true, message: `${$t('label.required')}` }]}]"></a-input>
@ -131,7 +133,7 @@
<p>{{ $t('message.add.new.gateway.to.vpc') }}</p> <p>{{ $t('message.add.new.gateway.to.vpc') }}</p>
<a-form @submit.prevent="handleGatewayFormSubmit" :form="gatewayForm"> <a-form @submit.prevent="handleGatewayFormSubmit" :form="gatewayForm">
<a-form-item :label="$t('label.physicalnetworkid')"> <a-form-item :label="$t('label.physicalnetworkid')">
<a-select v-decorator="['physicalnetwork']"> <a-select v-decorator="['physicalnetwork']" autoFocus>
<a-select-option v-for="item in physicalnetworks" :key="item.id" :value="item.id"> <a-select-option v-for="item in physicalnetworks" :key="item.id" :value="item.id">
{{ item.name }} {{ item.name }}
</a-select-option> </a-select-option>
@ -255,7 +257,7 @@
<a-spin :spinning="modals.vpnConnectionLoading"> <a-spin :spinning="modals.vpnConnectionLoading">
<a-form @submit.prevent="handleVpnConnectionFormSubmit" :form="vpnConnectionForm"> <a-form @submit.prevent="handleVpnConnectionFormSubmit" :form="vpnConnectionForm">
<a-form-item :label="$t('label.vpncustomergatewayid')"> <a-form-item :label="$t('label.vpncustomergatewayid')">
<a-select v-decorator="['vpncustomergateway']"> <a-select v-decorator="['vpncustomergateway']" autoFocus>
<a-select-option v-for="item in vpncustomergateways" :key="item.id" :value="item.id"> <a-select-option v-for="item in vpncustomergateways" :key="item.id" :value="item.id">
{{ item.name }} {{ item.name }}
</a-select-option> </a-select-option>

View File

@ -164,7 +164,8 @@
<a-form-item :label="$t('label.name')"> <a-form-item :label="$t('label.name')">
<a-input <a-input
:placeholder="$t('label.unique.name.tier')" :placeholder="$t('label.unique.name.tier')"
v-decorator="['name',{rules: [{ required: true, message: `${$t('label.required')}` }]}]"></a-input> v-decorator="['name',{rules: [{ required: true, message: `${$t('label.required')}` }]}]"
autoFocus></a-input>
</a-form-item> </a-form-item>
<a-form-item :label="$t('label.networkofferingid')"> <a-form-item :label="$t('label.networkofferingid')">
<a-select <a-select
@ -208,6 +209,7 @@
<a-form @submit.prevent="handleAddInternalLBSubmit" :form="form"> <a-form @submit.prevent="handleAddInternalLBSubmit" :form="form">
<a-form-item :label="$t('label.name')"> <a-form-item :label="$t('label.name')">
<a-input <a-input
autoFocus
:placeholder="$t('label.internallb.name.description')" :placeholder="$t('label.internallb.name.description')"
v-decorator="['name', { rules: [{ required: true, message: $t('message.error.internallb.name')}] }]"/> v-decorator="['name', { rules: [{ required: true, message: $t('message.error.internallb.name')}] }]"/>
</a-form-item> </a-form-item>

View File

@ -30,6 +30,7 @@
</a-tooltip> </a-tooltip>
</span> </span>
<a-input <a-input
autoFocus
v-decorator="['name', { v-decorator="['name', {
rules: [{ required: true, message: $t('message.error.required.input') }] rules: [{ required: true, message: $t('message.error.required.input') }]
}]" }]"

View File

@ -30,6 +30,7 @@
</a-tooltip> </a-tooltip>
</span> </span>
<a-input <a-input
autoFocus
v-decorator="['name', { v-decorator="['name', {
rules: [{ required: true, message: $t('message.error.required.input') }] rules: [{ required: true, message: $t('message.error.required.input') }]
}]" }]"

View File

@ -30,6 +30,7 @@
</a-tooltip> </a-tooltip>
</span> </span>
<a-input <a-input
autoFocus
v-decorator="['name', { v-decorator="['name', {
rules: [{ required: true, message: $t('message.error.name') }] rules: [{ required: true, message: $t('message.error.name') }]
}]" }]"

View File

@ -30,6 +30,7 @@
</a-tooltip> </a-tooltip>
</span> </span>
<a-input <a-input
autoFocus
v-decorator="['name', { v-decorator="['name', {
rules: [{ required: true, message: $t('message.error.name') }] rules: [{ required: true, message: $t('message.error.name') }]
}]" }]"

View File

@ -29,6 +29,7 @@
</a-tooltip> </a-tooltip>
</span> </span>
<a-input <a-input
autoFocus
v-decorator="['name', { v-decorator="['name', {
rules: [{ required: true, message: $t('message.error.required.input') }] rules: [{ required: true, message: $t('message.error.required.input') }]
}]"/> }]"/>

View File

@ -29,6 +29,7 @@
<a-form-item :label="$t('label.domainid')" v-if="!this.offeringIsPublic"> <a-form-item :label="$t('label.domainid')" v-if="!this.offeringIsPublic">
<a-select <a-select
:autoFocus="!this.offeringIsPublic"
mode="multiple" mode="multiple"
v-decorator="['domainid', { v-decorator="['domainid', {
rules: [ rules: [
@ -54,6 +55,7 @@
<a-form-item :label="$t('label.zoneid')"> <a-form-item :label="$t('label.zoneid')">
<a-select <a-select
:autoFocus="this.offeringIsPublic"
id="zone-selection" id="zone-selection"
mode="multiple" mode="multiple"
v-decorator="['zoneid', { v-decorator="['zoneid', {

View File

@ -36,6 +36,7 @@
@submit="submitTariff"> @submit="submitTariff">
<a-form-item :label="$t('label.quota.value')"> <a-form-item :label="$t('label.quota.value')">
<a-input <a-input
autoFocus
v-decorator="['value', { v-decorator="['value', {
rules: [{ rules: [{
required: true, required: true,

Some files were not shown because too many files have changed in this diff Show More